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}