Skip to main content

azalea/client_impl/
entity_query.rs

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