azalea_entity/plugin/
components.rs

1use azalea_block::fluid_state::FluidKind;
2use azalea_core::position::{BlockPos, ChunkPos, Vec3};
3use azalea_registry::builtin::EntityKind;
4use azalea_world::WorldName;
5use bevy_ecs::{bundle::Bundle, component::Component};
6use derive_more::{Deref, DerefMut};
7use uuid::Uuid;
8
9use crate::{
10    ActiveEffects, Attributes, EntityUuid, FluidOnEyes, LookDirection, Physics, Position,
11    dimensions::EntityDimensions, indexing::EntityChunkPos,
12};
13
14/// A bundle of components that every entity has.
15///
16/// This doesn't contain metadata; that has to be added separately.
17#[derive(Bundle)]
18pub struct EntityBundle {
19    pub kind: EntityKindComponent,
20    pub uuid: EntityUuid,
21    pub world_name: WorldName,
22    pub position: Position,
23    pub last_sent_position: LastSentPosition,
24
25    pub chunk_pos: EntityChunkPos,
26
27    pub physics: Physics,
28    pub direction: LookDirection,
29    pub dimensions: EntityDimensions,
30    pub attributes: Attributes,
31    pub jumping: Jumping,
32    pub crouching: Crouching,
33    pub fluid_on_eyes: FluidOnEyes,
34    pub on_climbable: OnClimbable,
35    pub active_effects: ActiveEffects,
36}
37
38impl EntityBundle {
39    pub fn new(uuid: Uuid, pos: Vec3, kind: EntityKind, world_name: WorldName) -> Self {
40        let dimensions = EntityDimensions::from(kind);
41
42        Self {
43            kind: EntityKindComponent(kind),
44            uuid: EntityUuid(uuid),
45            world_name,
46            position: Position(pos),
47            chunk_pos: EntityChunkPos(ChunkPos::from(&pos)),
48            last_sent_position: LastSentPosition(pos),
49            physics: Physics::new(&dimensions, pos),
50            dimensions,
51            direction: LookDirection::default(),
52
53            attributes: Attributes::new(EntityKind::Player),
54
55            jumping: Jumping(false),
56            crouching: Crouching(false),
57            fluid_on_eyes: FluidOnEyes(FluidKind::Empty),
58            on_climbable: OnClimbable(false),
59            active_effects: ActiveEffects::default(),
60        }
61    }
62}
63
64/// Marker component for entities that are dead.
65///
66/// "Dead" means that the entity has 0 health.
67#[derive(Clone, Component, Copy, Default)]
68pub struct Dead;
69
70/// A component NewType for [`EntityKind`].
71///
72/// Most of the time, you should be using `azalea_registry::EntityKind`
73/// directly instead.
74#[derive(Clone, Component, Copy, Debug, Deref, PartialEq)]
75pub struct EntityKindComponent(pub EntityKind);
76
77/// A marker component that signifies that this entity is "local" and shouldn't
78/// be updated by other clients.
79///
80/// If this is for a client then all of our clients will have this.
81///
82/// This component is not removed from clients when they disconnect.
83#[derive(Clone, Component, Copy, Debug, Default)]
84pub struct LocalEntity;
85
86impl FluidOnEyes {
87    pub fn new(fluid: FluidKind) -> Self {
88        Self(fluid)
89    }
90}
91
92#[derive(Clone, Component, Copy, Debug, Deref, DerefMut, PartialEq)]
93pub struct OnClimbable(bool);
94
95/// A component that indicates whether the player is currently sneaking.
96///
97/// If the entity isn't a local player, then this is just a shortcut for
98/// checking if the [`Pose`] is `Crouching`.
99///
100/// If you need to modify this value, use
101/// `azalea_client::PhysicsState::trying_to_crouch` or `Client::set_crouching`
102/// instead.
103///
104/// [`Pose`]: crate::data::Pose
105#[derive(Clone, Component, Copy, Default, Deref, DerefMut)]
106pub struct Crouching(bool);
107
108/// A component that indicates whether the client has loaded.
109///
110/// This is updated by a system in `azalea-client`.
111#[derive(Component)]
112pub struct HasClientLoaded;
113
114/// The second most recent position of the entity that was sent over the
115/// network.
116///
117/// This is currently only updated for our own local player entities.
118#[derive(Clone, Copy, Component, Debug, Default, Deref, DerefMut, PartialEq)]
119pub struct LastSentPosition(Vec3);
120impl From<&LastSentPosition> for Vec3 {
121    fn from(value: &LastSentPosition) -> Self {
122        value.0
123    }
124}
125impl From<LastSentPosition> for ChunkPos {
126    fn from(value: LastSentPosition) -> Self {
127        ChunkPos::from(&value.0)
128    }
129}
130impl From<LastSentPosition> for BlockPos {
131    fn from(value: LastSentPosition) -> Self {
132        BlockPos::from(&value.0)
133    }
134}
135impl From<&LastSentPosition> for ChunkPos {
136    fn from(value: &LastSentPosition) -> Self {
137        ChunkPos::from(value.0)
138    }
139}
140impl From<&LastSentPosition> for BlockPos {
141    fn from(value: &LastSentPosition) -> Self {
142        BlockPos::from(value.0)
143    }
144}
145
146/// A component for entities that can jump.
147///
148/// If this is true, the entity will try to jump every tick. It's equivalent to
149/// the space key being held in vanilla.
150#[derive(Clone, Copy, Component, Debug, Default, Deref, DerefMut, Eq, PartialEq)]
151pub struct Jumping(pub bool);