@@ -518,6 +518,14 @@ impl Client {
518518 /// Get a component from this client. This will clone the component and
519519 /// return it.
520520 ///
521+ ///
522+ /// If the component can't be cloned, try [`Self::map_component`] instead.
523+ /// If it isn't guaranteed to be present, use [`Self::get_component`] or
524+ /// [`Self::map_get_component`].
525+ ///
526+ /// You may also use [`Self::ecs`] and [`Self::query`] directly if you need
527+ /// more control over when the ECS is locked.
528+ ///
521529 /// # Panics
522530 ///
523531 /// This will panic if the component doesn't exist on the client.
@@ -534,10 +542,56 @@ impl Client {
534542 }
535543
536544 /// Get a component from this client, or `None` if it doesn't exist.
545+ ///
546+ /// If the component can't be cloned, try [`Self::map_component`] instead.
547+ /// You may also have to use [`Self::ecs`] and [`Self::query`] directly.
537548 pub fn get_component < T : Component + Clone > ( & self ) -> Option < T > {
538549 self . query :: < Option < & T > > ( & mut self . ecs . lock ( ) ) . cloned ( )
539550 }
540551
552+ /// Get a required component for this client and call the given function.
553+ ///
554+ /// Similar to [`Self::component`], but doesn't clone the component since
555+ /// it's passed as a reference. [`Self::ecs`] will remain locked while the
556+ /// callback is being run.
557+ ///
558+ /// If the component is not guaranteed to be present, use
559+ /// [`Self::get_component`] instead.
560+ ///
561+ /// # Panics
562+ ///
563+ /// This will panic if the component doesn't exist on the client.
564+ ///
565+ /// ```
566+ /// # use azalea_client::{Client, Hunger};
567+ /// # fn example(bot: &Client) {
568+ /// let hunger = bot.map_component::<Hunger, _>(|h| h.food);
569+ /// # }
570+ /// ```
571+ pub fn map_component < T : Component , R > ( & self , f : impl FnOnce ( & T ) -> R ) -> R {
572+ let mut ecs = self . ecs . lock ( ) ;
573+ let value = self . query :: < & T > ( & mut ecs) ;
574+ f ( value)
575+ }
576+
577+ /// Optionally get a component for this client and call the given function.
578+ ///
579+ /// Similar to [`Self::get_component`], but doesn't clone the component
580+ /// since it's passed as a reference. [`Self::ecs`] will remain locked
581+ /// while the callback is being run.
582+ ///
583+ /// ```
584+ /// # use azalea_client::{Client, mining::Mining};
585+ /// # fn example(bot: &Client) {
586+ /// let is_mining = bot.map_get_component::<Mining, _>(|m| m.is_some());
587+ /// # }
588+ /// ```
589+ pub fn map_get_component < T : Component , R > ( & self , f : impl FnOnce ( Option < & T > ) -> R ) -> R {
590+ let mut ecs = self . ecs . lock ( ) ;
591+ let value = self . query :: < Option < & T > > ( & mut ecs) ;
592+ f ( value)
593+ }
594+
541595 /// Get an `RwLock` with a reference to our (potentially shared) world.
542596 ///
543597 /// This gets the [`Instance`] from the client's [`InstanceHolder`]
0 commit comments