azalea/client_impl/
entity_query.rs

1use std::{any, sync::Arc};
2
3use azalea_core::position::Vec3;
4use azalea_entity::Position;
5use azalea_world::WorldName;
6use bevy_ecs::{
7    component::Component,
8    entity::Entity,
9    query::{QueryData, QueryEntityError, QueryFilter, QueryItem, ROQueryItem},
10    world::World,
11};
12use parking_lot::{MappedRwLockReadGuard, RwLock, RwLockReadGuard};
13
14use crate::{Client, entity_ref::EntityRef};
15
16impl Client {
17    /// Get a component from the client.
18    ///
19    /// This allows you to access certain data stored about the client entity
20    /// that isn't accessible in a simpler way.
21    ///
22    /// This returns a reference to the component wrapped by a read guard. This
23    /// makes the component cheap to access, but means that the ECS cannot be
24    /// mutated while it's in scope (it will cause a deadlock). In some cases,
25    /// it may be simpler for you to immediately clone the component after
26    /// accessing it.
27    ///
28    /// If the component isn't guaranteed to be present, consider using
29    /// [`Self::get_component`] instead.
30    ///
31    /// To do more complex queries or to mutate data, see [`Self::query_self`].
32    ///
33    /// To access data about other entities, you can use
34    /// [`Self::entity_component`] (and its other related functions).
35    ///
36    /// You may also use [`Self::ecs`] directly if you need more control over
37    /// when the ECS is locked.
38    ///
39    /// # Panics
40    ///
41    /// This will panic if the component doesn't exist on the client. Use
42    /// [`Self::get_component`] to avoid this.
43    ///
44    /// # Examples
45    ///
46    /// ```
47    /// # use azalea_world::WorldName;
48    /// # fn example(client: &azalea::Client) {
49    /// let world_name = client.component::<WorldName>();
50    /// # }
51    pub fn component<T: Component>(&self) -> MappedRwLockReadGuard<'_, T> {
52        self.get_component::<T>().unwrap_or_else(|| {
53            panic!(
54                "Our client is missing a required component: {:?}",
55                any::type_name::<&T>()
56            )
57        })
58    }
59
60    /// Get a component on this client, or `None` if it doesn't exist.
61    ///
62    /// If the component is guaranteed to be present, consider using
63    /// [`Self::component`]. Also see that function for more details.
64    pub fn get_component<T: Component>(&self) -> Option<MappedRwLockReadGuard<'_, T>> {
65        self.get_entity_component::<T>(self.entity)
66    }
67
68    /// Query the ECS for data from our client entity.
69    ///
70    /// To query another entity, you can use [`Self::query_entity`].
71    ///
72    /// You can use this to mutate data on the client.
73    ///
74    /// # Examples
75    ///
76    /// ```
77    /// # use azalea_entity::Position;
78    /// # fn example(mut client: azalea::Client) {
79    /// // teleport one block up
80    /// client.query_self::<&mut Position, _>(|mut pos| pos.y += 1.0);
81    /// # }
82    /// ```
83    ///
84    /// # Panics
85    ///
86    /// This will panic if the client is missing a component required by the
87    /// query. Consider using [`Self::try_query_self`] to avoid this.
88    pub fn query_self<D: QueryData, R>(&self, f: impl FnOnce(QueryItem<D>) -> R) -> R {
89        self.try_query_self::<D, R>(f).unwrap_or_else(|_| {
90            panic!(
91                "`Client::query_self` failed when querying for {:?}",
92                any::type_name::<D>()
93            )
94        })
95    }
96
97    /// Query the ECS for data from our client entity, or return `None` if the
98    /// query failed.
99    ///
100    /// Also see [`Self::query_self`].
101    pub fn try_query_self<D: QueryData, R>(
102        &self,
103        f: impl FnOnce(QueryItem<D>) -> R,
104    ) -> Result<R, QueryEntityError> {
105        let mut ecs = self.ecs.write();
106        let mut qs = ecs.query::<D>();
107        qs.get_mut(&mut ecs, self.entity).map(f)
108    }
109
110    /// Query the ECS for data from an entity.
111    ///
112    /// Note that it is often simpler to use [`Self::entity_component`].
113    ///
114    /// To query the client, you should use [`Self::query_self`].
115    ///
116    /// You can also use this to mutate data on an entity.
117    ///
118    /// # Panics
119    ///
120    /// This will panic if the entity doesn't exist or if the query isn't valid
121    /// for the entity. For a non-panicking version, you may use
122    /// [`Self::try_query_entity`].
123    pub fn query_entity<D: QueryData, R>(
124        &self,
125        entity: Entity,
126        f: impl FnOnce(QueryItem<D>) -> R,
127    ) -> R {
128        self.try_query_entity(entity, f).unwrap_or_else(|_| {
129            panic!(
130                "Querying entity {entity} failed when getting {:?}",
131                any::type_name::<D>()
132            )
133        })
134    }
135
136    /// A convenience function for getting components from any entity, or None
137    /// if the query fails.
138    ///
139    /// If you're sure that the entity exists and that the query will succeed,
140    /// you can use [`Self::query_entity`].
141    pub fn try_query_entity<D: QueryData, R>(
142        &self,
143        entity: Entity,
144        f: impl FnOnce(QueryItem<D>) -> R,
145    ) -> Result<R, QueryEntityError> {
146        let mut ecs = self.ecs.write();
147        let mut qs = ecs.query::<D>();
148        qs.get_mut(&mut ecs, entity).map(f)
149    }
150
151    /// Quickly returns an [`EntityRef`] for an arbitrary entity that
152    /// matches the given predicate function that is in the same
153    /// [`World`] as the client.
154    ///
155    /// [`World`]: azalea_world::World
156    pub fn any_entity_by<Q: QueryData, F: QueryFilter>(
157        &self,
158        predicate: impl EntityPredicate<Q, F>,
159    ) -> Option<EntityRef> {
160        self.any_entity_id_by(predicate)
161            .map(|e| self.entity_ref_for(e))
162    }
163    /// Quickly returns a lightweight [`Entity`] for an arbitrary entity that
164    /// matches the given predicate function that is in the same
165    /// [`World`] as the client.
166    ///
167    /// To get an [`EntityRef`], consider using [`Self::any_entity_by`]
168    /// instead.
169    ///
170    /// If you want to find the nearest entity, consider using
171    /// [`Self::nearest_entity_id_by`] instead. If you want to find all entities
172    /// that match the predicate, use [`Self::nearest_entity_ids_by`].
173    ///
174    /// # Example
175    ///
176    /// ```
177    /// use azalea::{entity::metadata::Player, player::GameProfileComponent};
178    /// use bevy_ecs::query::With;
179    ///
180    /// # fn example(mut bot: azalea::Client, sender_name: String) {
181    /// let entity = bot.any_entity_id_by::<&GameProfileComponent, With<Player>>(
182    ///     |profile: &GameProfileComponent| profile.name == sender_name,
183    /// );
184    /// # }
185    /// ```
186    ///
187    /// [`World`]: azalea_world::World
188    pub fn any_entity_id_by<Q: QueryData, F: QueryFilter>(
189        &self,
190        predicate: impl EntityPredicate<Q, F>,
191    ) -> Option<Entity> {
192        let world_name = self.get_component::<WorldName>()?.clone();
193        predicate.find_any(self.ecs.clone(), &world_name)
194    }
195
196    /// Return an [`EntityRef`] for the nearest entity that matches the
197    /// given predicate function.
198    ///
199    /// If you don't need the entity to be the nearest one, it may be more
200    /// efficient to use [`Self::any_entity_by`] instead. You can also use
201    /// [`Self::nearest_entities_by`] to get all nearby entities.
202    ///
203    /// Also see [`Self::nearest_entity_id_by`] if you only need the lightweight
204    /// [`Entity`] identifier.
205    pub fn nearest_entity_by<Q: QueryData, F: QueryFilter>(
206        &self,
207        predicate: impl EntityPredicate<Q, F>,
208    ) -> Option<EntityRef> {
209        self.nearest_entity_id_by(predicate)
210            .map(|e| self.entity_ref_for(e))
211    }
212    /// Return a lightweight [`Entity`] for the nearest entity that matches the
213    /// given predicate function.
214    ///
215    /// To get an [`EntityRef`], consider using [`Self::nearest_entity_by`]
216    /// instead.
217    ///
218    /// If you don't need the entity to be the nearest one, it may be more
219    /// efficient to use [`Self::any_entity_id_by`] instead. You can also use
220    /// [`Self::nearest_entity_ids_by`] to get all nearby entities.
221    pub fn nearest_entity_id_by<Q: QueryData, F: QueryFilter>(
222        &self,
223        predicate: impl EntityPredicate<Q, F>,
224    ) -> Option<Entity> {
225        self.nearest_entity_ids_by(predicate).first().copied()
226    }
227
228    /// Returns an array of all [`EntityRef`]s in the world that match the
229    /// predicate, sorted by nearest first.
230    ///
231    /// To only get the nearest entity, consider using
232    /// [`Self::nearest_entity_by`]. If you only need the [`Entity`]
233    /// identifiers, you can use [`Self::nearest_entity_ids_by`] instead.
234    pub fn nearest_entities_by<Q: QueryData, F: QueryFilter>(
235        &self,
236        predicate: impl EntityPredicate<Q, F>,
237    ) -> Box<[EntityRef]> {
238        self.nearest_entity_ids_by(predicate)
239            .into_iter()
240            .map(|e| self.entity_ref_for(e))
241            .collect()
242    }
243    /// Returns an array of all [`Entity`]s in the world that match the
244    /// predicate, sorted by nearest first.
245    ///
246    /// To only get the nearest entity, consider using
247    /// [`Self::nearest_entity_id_by`]. To get the [`EntityRef`]s instead, you
248    /// can use [`Self::nearest_entities_by`].
249    ///
250    /// ```
251    /// # use azalea_entity::{LocalEntity, Position, metadata::Player};
252    /// # use bevy_ecs::query::{With, Without};
253    /// # fn example(mut bot: azalea::Client, sender_name: String) {
254    /// let nearby_players =
255    ///     bot.nearest_entities_by::<(), (With<Player>, Without<LocalEntity>)>(|_: ()| true);
256    /// # }
257    /// ```
258    pub fn nearest_entity_ids_by<Q: QueryData, F: QueryFilter>(
259        &self,
260        predicate: impl EntityPredicate<Q, F>,
261    ) -> Box<[Entity]> {
262        let (world_name, position) = {
263            let Some(world_name) = self.get_component::<WorldName>() else {
264                return Box::new([]);
265            };
266            let Some(position) = self.get_component::<Position>() else {
267                return Box::new([]);
268            };
269
270            (world_name.clone(), **position)
271        };
272
273        predicate.find_all_sorted(self.ecs.clone(), &world_name, position)
274    }
275
276    /// Get a component from an entity.
277    ///
278    /// This allows you to access data stored about entities that isn't
279    /// accessible in a simpler way.
280    ///
281    /// This returns a reference to the component wrapped by a read guard. This
282    /// makes the component cheap to access, but means that the ECS cannot be
283    /// mutated while it's in scope. In some cases, it may be simpler for you to
284    /// immediately clone the component after accessing it.
285    ///
286    /// If you're trying to get a component for this client, you should use
287    /// [`Self::component`] instead.
288    ///
289    /// To do more complex queries or to mutate data, see
290    /// [`Self::query_entity`].
291    ///
292    /// # Panics
293    ///
294    /// This will panic if the component doesn't exist on the entity. Use
295    /// [`Self::get_entity_component`] to avoid this.
296    pub fn entity_component<T: Component>(&self, entity: Entity) -> MappedRwLockReadGuard<'_, T> {
297        self.get_entity_component::<T>(entity).unwrap_or_else(|| {
298            panic!(
299                "Entity {entity} is missing a required component: {:?}",
300                any::type_name::<&T>()
301            )
302        })
303    }
304
305    /// Get a component from an entity, if it exists.
306    ///
307    /// This is similar to [`Self::entity_component`] but returns an `Option`
308    /// instead of panicking if the component isn't present.
309    pub fn get_entity_component<T: Component>(
310        &self,
311        entity: Entity,
312    ) -> Option<MappedRwLockReadGuard<'_, T>> {
313        let ecs = self.ecs.read();
314        RwLockReadGuard::try_map(ecs, |ecs: &World| ecs.get(entity)).ok()
315    }
316}
317
318pub trait EntityPredicate<Q: QueryData, Filter: QueryFilter> {
319    fn find_any(&self, ecs_lock: Arc<RwLock<World>>, world_name: &WorldName) -> Option<Entity>;
320    fn find_all_sorted(
321        &self,
322        ecs_lock: Arc<RwLock<World>>,
323        world_name: &WorldName,
324        nearest_to: Vec3,
325    ) -> Box<[Entity]>;
326}
327impl<F, Q: QueryData, Filter: QueryFilter> EntityPredicate<Q, Filter> for F
328where
329    F: Fn(ROQueryItem<Q>) -> bool,
330    for<'w, 's> <<Q as QueryData>::ReadOnly as QueryData>::Item<'w, 's>: Copy,
331{
332    fn find_any(&self, ecs_lock: Arc<RwLock<World>>, world_name: &WorldName) -> Option<Entity> {
333        let mut ecs = ecs_lock.write();
334        let mut query = ecs.query_filtered::<(Entity, &WorldName, Q), Filter>();
335        query
336            .iter(&ecs)
337            .find(|(_, e_world_name, q)| *e_world_name == world_name && (self)(*q))
338            .map(|(e, _, _)| e)
339    }
340
341    fn find_all_sorted(
342        &self,
343        ecs_lock: Arc<RwLock<World>>,
344        world_name: &WorldName,
345        nearest_to: Vec3,
346    ) -> Box<[Entity]> {
347        let mut ecs = ecs_lock.write();
348        let mut query = ecs.query_filtered::<(Entity, &WorldName, &Position, Q), Filter>();
349        let mut entities = query
350            .iter(&ecs)
351            .filter(|(_, e_world_name, _, q)| *e_world_name == world_name && (self)(*q))
352            .map(|(e, _, position, _)| (e, Vec3::from(position)))
353            .collect::<Vec<(Entity, Vec3)>>();
354
355        entities.sort_by_cached_key(|(_, position)| {
356            // to_bits is fine here as long as the number is positive
357            position.distance_squared_to(nearest_to).to_bits()
358        });
359
360        entities
361            .into_iter()
362            .map(|(e, _)| e)
363            .collect::<Box<[Entity]>>()
364    }
365}