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}