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}