azalea/entity_ref/mod.rs
1pub mod shared_impls;
2
3use std::fmt::Debug;
4
5use azalea_entity::EntityKindComponent;
6use azalea_registry::builtin::EntityKind;
7use bevy_ecs::{
8 component::Component,
9 entity::Entity,
10 query::{QueryData, QueryEntityError, QueryItem},
11};
12use parking_lot::MappedRwLockReadGuard;
13
14use crate::Client;
15
16/// A reference to an entity in a world.
17///
18/// This is different from [`Entity`], since you can perform actions with just
19/// an `EntityRef` instead of it only being an identifier.
20///
21/// Most functions on `EntityRef` that return a value will result in a panic if
22/// the client has despawned, so if your code involves waiting, you should check
23/// [`Self::is_alive`] or [`Self::exists`] before calling those functions.
24///
25/// Also, since `EntityRef` stores the [`Client`] alongside the entity, this
26/// means that it supports interactions such as [`Self::attack`].
27///
28/// Not to be confused with Bevy's [`EntityRef`](bevy_ecs::world::EntityRef).
29#[derive(Clone)]
30pub struct EntityRef {
31 client: Client,
32 entity: Entity,
33}
34
35impl EntityRef {
36 pub fn new(client: Client, entity: Entity) -> Self {
37 Self { client, entity }
38 }
39
40 /// Returns the ECS identifier for the entity.
41 pub fn id(&self) -> Entity {
42 self.entity
43 }
44
45 /// Get a component on the entity.
46 ///
47 /// This allows you to access certain data stored about the entity that
48 /// isn't accessible in a simpler way.
49 ///
50 /// See [`Client::component`] for more details.
51 ///
52 /// # Panics
53 ///
54 /// This will panic if the component doesn't exist on the client. Use
55 /// [`Self::get_component`] to avoid this.
56 ///
57 /// # Examples
58 ///
59 /// ```
60 /// # use azalea_world::InstanceName;
61 /// # fn example(client: &azalea::Client) {
62 /// let world_name = client.component::<InstanceName>();
63 /// # }
64 pub fn component<T: Component>(&self) -> MappedRwLockReadGuard<'_, T> {
65 self.client.entity_component(self.entity)
66 }
67
68 /// Get a component on this client, or `None` if it doesn't exist.
69 ///
70 /// If the component is guaranteed to be present, consider using
71 /// [`Self::component`].
72 ///
73 /// See [`Client::component`] for more details.
74 pub fn get_component<T: Component>(&self) -> Option<MappedRwLockReadGuard<'_, T>> {
75 self.client.get_entity_component(self.entity)
76 }
77
78 /// Query the ECS for data from the entity.
79 ///
80 /// You can use this to mutate data on the entity.
81 ///
82 /// Also see [`Client::query_self`] and [`Client::query_entity`].
83 ///
84 /// # Panics
85 ///
86 /// This will panic if the entity doesn't exist or is missing a component
87 /// required by the query. Consider using [`Self::try_query_self`] to
88 /// avoid this.
89 pub fn query_self<D: QueryData, R>(&self, f: impl FnOnce(QueryItem<D>) -> R) -> R {
90 self.client.query_entity(self.entity, f)
91 }
92
93 /// Query the ECS for data from the entity, or return an error if the query
94 /// fails.
95 ///
96 /// Also see [`Self::query_self`].
97 pub fn try_query_self<D: QueryData, R>(
98 &self,
99 f: impl FnOnce(QueryItem<D>) -> R,
100 ) -> Result<R, QueryEntityError> {
101 self.client.try_query_entity(self.entity, f)
102 }
103}
104
105impl Debug for EntityRef {
106 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
107 f.debug_struct("EntityRef")
108 .field("client", &self.client.entity)
109 .field("entity", &self.entity)
110 .finish()
111 }
112}
113
114impl EntityRef {
115 /// Returns the type of entity that this is.
116 pub fn kind(&self) -> EntityKind {
117 **self.component::<EntityKindComponent>()
118 }
119}
120
121impl EntityRef {
122 /// Attack this entity from the client that created this `EntityRef`.
123 ///
124 /// Also see [`Client::attack`].
125 pub fn attack(&self) {
126 self.client.attack(self.entity);
127 }
128
129 /// Right-click this entity from the client that created this `EntityRef`.
130 ///
131 /// See [`Client::entity_interact`] for more information.
132 pub fn interact(&self) {
133 self.client.entity_interact(self.entity);
134 }
135
136 /// Look at this entity from the client that created the `EntityRef`.
137 pub fn look_at(&self) {
138 self.client.look_at(self.eye_position());
139 }
140
141 /// Returns the distance between the client's feet position and this
142 /// entity's feet position.
143 pub fn distance_to_client(&self) -> f64 {
144 self.position().distance_to(self.client.position())
145 }
146}