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