azalea_client/
entity_query.rs1use std::{any, sync::Arc};
2
3use azalea_core::position::Vec3;
4use azalea_entity::Position;
5use azalea_world::InstanceName;
6use bevy_ecs::{
7 component::Component,
8 entity::Entity,
9 query::{QueryData, QueryFilter, ROQueryItem},
10 world::World,
11};
12use parking_lot::Mutex;
13
14use crate::Client;
15
16impl Client {
17 pub fn query<'w, D: QueryData>(&self, ecs: &'w mut World) -> D::Item<'w> {
29 ecs.query::<D>()
30 .get_mut(ecs, self.entity)
31 .unwrap_or_else(|_| {
32 panic!(
33 "Our client is missing a required component {:?}",
34 any::type_name::<D>()
35 )
36 })
37 }
38
39 pub fn entity_by<F: QueryFilter, Q: QueryData>(
69 &self,
70 predicate: impl EntityPredicate<Q, F>,
71 ) -> Option<Entity> {
72 let instance_name = self.get_component::<InstanceName>()?;
73 predicate.find_any(self.ecs.clone(), &instance_name)
74 }
75
76 pub fn entities_by<F: QueryFilter, Q: QueryData>(
82 &self,
83 predicate: impl EntityPredicate<Q, F>,
84 ) -> Vec<Entity> {
85 let Some(instance_name) = self.get_component::<InstanceName>() else {
86 return vec![];
87 };
88 let Some(position) = self.get_component::<Position>() else {
89 return vec![];
90 };
91 predicate.find_all_sorted(self.ecs.clone(), &instance_name, (&position).into())
92 }
93
94 pub fn entity_component<Q: Component + Clone>(&self, entity: Entity) -> Q {
100 let mut ecs = self.ecs.lock();
101 let mut q = ecs.query::<&Q>();
102 let components = q.get(&ecs, entity).unwrap_or_else(|_| {
103 panic!(
104 "Entity is missing a required component {:?}",
105 any::type_name::<Q>()
106 )
107 });
108 components.clone()
109 }
110
111 pub fn get_entity_component<Q: Component + Clone>(&self, entity: Entity) -> Option<Q> {
115 let mut ecs = self.ecs.lock();
116 let mut q = ecs.query::<&Q>();
117 let components = q.get(&ecs, entity).ok();
118 components.cloned()
119 }
120}
121
122pub trait EntityPredicate<Q: QueryData, Filter: QueryFilter> {
123 fn find_any(&self, ecs_lock: Arc<Mutex<World>>, instance_name: &InstanceName)
124 -> Option<Entity>;
125 fn find_all_sorted(
126 &self,
127 ecs_lock: Arc<Mutex<World>>,
128 instance_name: &InstanceName,
129 nearest_to: Vec3,
130 ) -> Vec<Entity>;
131}
132impl<F, Q: QueryData, Filter: QueryFilter> EntityPredicate<Q, Filter> for F
133where
134 F: Fn(&ROQueryItem<Q>) -> bool,
135{
136 fn find_any(
137 &self,
138 ecs_lock: Arc<Mutex<World>>,
139 instance_name: &InstanceName,
140 ) -> Option<Entity> {
141 let mut ecs = ecs_lock.lock();
142 let mut query = ecs.query_filtered::<(Entity, &InstanceName, Q), Filter>();
143 query
144 .iter(&ecs)
145 .find(|(_, e_instance_name, q)| *e_instance_name == instance_name && (self)(q))
146 .map(|(e, _, _)| e)
147 }
148
149 fn find_all_sorted(
150 &self,
151 ecs_lock: Arc<Mutex<World>>,
152 instance_name: &InstanceName,
153 nearest_to: Vec3,
154 ) -> Vec<Entity> {
155 let mut ecs = ecs_lock.lock();
156 let mut query = ecs.query_filtered::<(Entity, &InstanceName, &Position, Q), Filter>();
157 let mut entities = query
158 .iter(&ecs)
159 .filter(|(_, e_instance_name, _, q)| *e_instance_name == instance_name && (self)(q))
160 .map(|(e, _, position, _)| (e, Vec3::from(position)))
161 .collect::<Vec<(Entity, Vec3)>>();
162
163 entities.sort_by_cached_key(|(_, position)| {
164 position.distance_squared_to(nearest_to).to_bits()
166 });
167
168 entities
169 .into_iter()
170 .map(|(e, _)| e)
171 .collect::<Vec<Entity>>()
172 }
173}