Skip to main content

azalea/entity_ref/
mod.rs

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