valence_entity/
lib.rs

1#![doc = include_str!("../README.md")]
2#![allow(clippy::unseparated_literal_suffix, clippy::manual_string_new)]
3
4pub mod active_status_effects;
5pub mod attributes;
6mod flags;
7pub mod hitbox;
8pub mod manager;
9pub mod query;
10pub mod tracked_data;
11
12use bevy_app::prelude::*;
13use bevy_ecs::prelude::*;
14use derive_more::{Deref, DerefMut};
15pub use manager::EntityManager;
16use paste::paste;
17use tracing::warn;
18use tracked_data::TrackedData;
19use valence_math::{DVec3, Vec3};
20use valence_protocol::{Decode, Encode, VarInt};
21use valence_server_common::{Despawned, UniqueId};
22
23use crate::attributes::TrackedEntityAttributes;
24
25include!(concat!(env!("OUT_DIR"), "/entity.rs"));
26
27pub struct EntityPlugin;
28
29/// When new Minecraft entities are initialized and added to
30/// [`EntityManager`].
31///
32/// Systems that need Minecraft entities to be in a valid state should run
33/// _after_ this set.
34///
35/// This set lives in [`PostUpdate`].
36#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
37pub struct InitEntitiesSet;
38
39/// When tracked data is written to the entity's [`TrackedData`] component.
40/// Systems that modify tracked data should run _before_ this.
41///
42/// This set lives in [`PostUpdate`].
43#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
44pub struct UpdateTrackedDataSet;
45
46/// When entities are updated and changes from the current tick are cleared.
47/// Systems that need to observe changes to entities (Such as the difference
48/// between [`Position`] and [`OldPosition`]) should run _before_ this set (and
49/// probably after [`InitEntitiesSet`]).
50///
51/// This set lives in [`PostUpdate`].
52#[derive(SystemSet, Copy, Clone, PartialEq, Eq, Hash, Debug)]
53pub struct ClearEntityChangesSet;
54
55impl Plugin for EntityPlugin {
56    fn build(&self, app: &mut App) {
57        app.insert_resource(EntityManager::new())
58            .configure_sets(
59                PostUpdate,
60                (
61                    InitEntitiesSet,
62                    UpdateTrackedDataSet,
63                    ClearEntityChangesSet
64                        .after(InitEntitiesSet)
65                        .after(UpdateTrackedDataSet),
66                ),
67            )
68            .add_systems(
69                PostUpdate,
70                (remove_despawned_from_manager, init_entities)
71                    .chain()
72                    .in_set(InitEntitiesSet),
73            )
74            .add_systems(
75                PostUpdate,
76                (
77                    clear_status_changes,
78                    clear_animation_changes,
79                    clear_tracked_data_changes,
80                    clear_tracked_attributes_changes,
81                    update_old_position,
82                    update_old_layer_id,
83                )
84                    .in_set(ClearEntityChangesSet),
85            );
86
87        add_tracked_data_systems(app);
88    }
89}
90
91fn update_old_position(mut query: Query<(&Position, &mut OldPosition)>) {
92    for (pos, mut old_pos) in &mut query {
93        old_pos.0 = pos.0;
94    }
95}
96
97fn update_old_layer_id(mut query: Query<(&EntityLayerId, &mut OldEntityLayerId)>) {
98    for (loc, mut old_loc) in &mut query {
99        old_loc.0 = loc.0;
100    }
101}
102
103fn remove_despawned_from_manager(
104    entities: Query<&EntityId, (With<EntityKind>, With<Despawned>)>,
105    mut manager: ResMut<EntityManager>,
106) {
107    for id in &entities {
108        manager.id_to_entity.remove(&id.0);
109    }
110}
111
112fn init_entities(
113    mut entities: Query<
114        (Entity, &mut EntityId, &Position, &mut OldPosition),
115        (Added<EntityKind>, Without<Despawned>),
116    >,
117    mut manager: ResMut<EntityManager>,
118) {
119    for (entity, mut id, pos, mut old_pos) in &mut entities {
120        *old_pos = OldPosition::new(pos.0);
121
122        if *id == EntityId::default() {
123            *id = manager.next_id();
124        }
125
126        if let Some(conflict) = manager.id_to_entity.insert(id.0, entity) {
127            warn!(
128                "entity {entity:?} has conflicting entity ID of {} with entity {conflict:?}",
129                id.0
130            );
131        }
132    }
133}
134
135fn clear_status_changes(mut statuses: Query<&mut EntityStatuses, Changed<EntityStatuses>>) {
136    for mut statuses in &mut statuses {
137        statuses.0 = 0;
138    }
139}
140
141fn clear_animation_changes(
142    mut animations: Query<&mut EntityAnimations, Changed<EntityAnimations>>,
143) {
144    for mut animations in &mut animations {
145        animations.0 = 0;
146    }
147}
148
149fn clear_tracked_data_changes(mut tracked_data: Query<&mut TrackedData, Changed<TrackedData>>) {
150    for mut tracked_data in &mut tracked_data {
151        tracked_data.clear_update_values();
152    }
153}
154
155fn clear_tracked_attributes_changes(
156    mut attributes: Query<&mut TrackedEntityAttributes, Changed<TrackedEntityAttributes>>,
157) {
158    for mut attributes in &mut attributes {
159        attributes.clear();
160    }
161}
162
163/// Contains the entity layer an entity is on.
164#[derive(Component, Copy, Clone, PartialEq, Eq, Debug, Deref)]
165pub struct EntityLayerId(pub Entity);
166
167impl Default for EntityLayerId {
168    fn default() -> Self {
169        Self(Entity::PLACEHOLDER)
170    }
171}
172
173impl PartialEq<OldEntityLayerId> for EntityLayerId {
174    fn eq(&self, other: &OldEntityLayerId) -> bool {
175        self.0 == other.0
176    }
177}
178
179/// The value of [`EntityLayerId`] from the end of the previous tick.
180#[derive(Component, Copy, Clone, PartialEq, Eq, Debug, Deref)]
181pub struct OldEntityLayerId(Entity);
182
183impl OldEntityLayerId {
184    pub fn get(&self) -> Entity {
185        self.0
186    }
187}
188
189impl Default for OldEntityLayerId {
190    fn default() -> Self {
191        Self(Entity::PLACEHOLDER)
192    }
193}
194
195impl PartialEq<EntityLayerId> for OldEntityLayerId {
196    fn eq(&self, other: &EntityLayerId) -> bool {
197        self.0 == other.0
198    }
199}
200
201#[derive(Component, Copy, Clone, PartialEq, Default, Debug, Deref, DerefMut)]
202pub struct Position(pub DVec3);
203
204impl Position {
205    pub fn new<P: Into<DVec3>>(pos: P) -> Self {
206        Self(pos.into())
207    }
208
209    pub fn get(self) -> DVec3 {
210        self.0
211    }
212
213    pub fn set<P: Into<DVec3>>(&mut self, pos: P) {
214        self.0 = pos.into();
215    }
216}
217
218impl PartialEq<OldPosition> for Position {
219    fn eq(&self, other: &OldPosition) -> bool {
220        self.0 == other.0
221    }
222}
223
224/// The value of [`Position`] from the end of the previous tick.
225///
226/// **NOTE**: You should not modify this component after the entity is spawned.
227#[derive(Component, Clone, PartialEq, Default, Debug, Deref)]
228pub struct OldPosition(DVec3);
229
230impl OldPosition {
231    pub fn new<P: Into<DVec3>>(pos: P) -> Self {
232        Self(pos.into())
233    }
234
235    pub fn get(&self) -> DVec3 {
236        self.0
237    }
238}
239
240impl PartialEq<Position> for OldPosition {
241    fn eq(&self, other: &Position) -> bool {
242        self.0 == other.0
243    }
244}
245
246/// Describes the direction an entity is looking using pitch and yaw angles.
247#[derive(Component, Copy, Clone, PartialEq, Default, Debug)]
248pub struct Look {
249    /// The yaw angle in degrees, where:
250    /// - `-90` is looking east (towards positive x).
251    /// - `0` is looking south (towards positive z).
252    /// - `90` is looking west (towards negative x).
253    /// - `180` is looking north (towards negative z).
254    ///
255    /// Values -180 to 180 are also valid.
256    pub yaw: f32,
257    /// The pitch angle in degrees, where:
258    /// - `-90` is looking straight up.
259    /// - `0` is looking straight ahead.
260    /// - `90` is looking straight down.
261    pub pitch: f32,
262}
263
264impl Look {
265    pub const fn new(yaw: f32, pitch: f32) -> Self {
266        Self { yaw, pitch }
267    }
268
269    /// Gets a normalized direction vector from the yaw and pitch.
270    pub fn vec(self) -> Vec3 {
271        let (yaw_sin, yaw_cos) = (self.yaw + 90.0).to_radians().sin_cos();
272        let (pitch_sin, pitch_cos) = (-self.pitch).to_radians().sin_cos();
273
274        Vec3::new(yaw_cos * pitch_cos, pitch_sin, yaw_sin * pitch_cos)
275    }
276
277    /// Sets the yaw and pitch using a normalized direction vector.
278    pub fn set_vec(&mut self, dir: Vec3) {
279        debug_assert!(
280            dir.is_normalized(),
281            "the direction vector should be normalized"
282        );
283
284        // Preserve the current yaw if we're looking straight up or down.
285        if dir.x != 0.0 || dir.z != 0.0 {
286            self.yaw = f32::atan2(dir.z, dir.x).to_degrees() - 90.0;
287        }
288
289        self.pitch = -(dir.y).asin().to_degrees();
290    }
291}
292
293#[derive(Component, Copy, Clone, PartialEq, Eq, Default, Debug, Deref, DerefMut)]
294pub struct OnGround(pub bool);
295
296/// A Minecraft entity's ID according to the protocol.
297///
298/// IDs should be _unique_ for the duration of the server and  _constant_ for
299/// the lifetime of the entity. IDs of -1 (the default) will be assigned to
300/// something else on the tick the entity is added. If you need to know the ID
301/// ahead of time, set this component to the value returned by
302/// [`EntityManager::next_id`] before spawning.
303#[derive(Component, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Debug, Deref)]
304pub struct EntityId(i32);
305
306impl EntityId {
307    /// Returns the underlying entity ID as an integer.
308    pub fn get(self) -> i32 {
309        self.0
310    }
311}
312
313/// Returns an entity ID of -1.
314impl Default for EntityId {
315    fn default() -> Self {
316        Self(-1)
317    }
318}
319
320#[derive(Component, Copy, Clone, PartialEq, Default, Debug, Deref, DerefMut)]
321pub struct HeadYaw(pub f32);
322
323/// Entity velocity in m/s.
324#[derive(Component, Copy, Clone, Default, Debug, Deref, DerefMut)]
325pub struct Velocity(pub Vec3);
326
327impl Velocity {
328    pub fn to_packet_units(self) -> valence_protocol::Velocity {
329        valence_protocol::Velocity::from_ms_f32(self.0.into())
330    }
331}
332
333// TODO: don't make statuses and animations components.
334
335#[derive(Component, Copy, Clone, Default, Debug, Deref, DerefMut)]
336pub struct EntityStatuses(pub u64);
337
338impl EntityStatuses {
339    pub fn trigger(&mut self, status: EntityStatus) {
340        self.set(status, true);
341    }
342
343    pub fn set(&mut self, status: EntityStatus, triggered: bool) {
344        self.0 |= u64::from(triggered) << status as u64;
345    }
346
347    pub fn get(&self, status: EntityStatus) -> bool {
348        (self.0 >> status as u64) & 1 == 1
349    }
350}
351
352#[derive(Component, Default, Debug, Copy, Clone, Deref, DerefMut)]
353pub struct EntityAnimations(pub u8);
354
355impl EntityAnimations {
356    pub fn trigger(&mut self, anim: EntityAnimation) {
357        self.set(anim, true);
358    }
359
360    pub fn set(&mut self, anim: EntityAnimation, triggered: bool) {
361        self.0 |= u8::from(triggered) << anim as u8;
362    }
363
364    pub fn get(&self, anim: EntityAnimation) -> bool {
365        (self.0 >> anim as u8) & 1 == 1
366    }
367}
368
369/// Extra integer data passed to the entity spawn packet. The meaning depends on
370/// the type of entity being spawned.
371///
372/// Some examples:
373/// - **Experience Orb**: Experience count
374/// - **(Glowing) Item Frame**: Rotation
375/// - **Painting**: Rotation
376/// - **Falling Block**: Block state
377/// - **Fishing Bobber**: Hook entity ID
378/// - **Warden**: Initial pose
379#[derive(Component, Default, Debug, Deref, DerefMut)]
380pub struct ObjectData(pub i32);
381
382#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Debug)]
383pub struct VillagerData {
384    pub kind: VillagerKind,
385    pub profession: VillagerProfession,
386    pub level: i32,
387}
388
389impl VillagerData {
390    pub const fn new(kind: VillagerKind, profession: VillagerProfession, level: i32) -> Self {
391        Self {
392            kind,
393            profession,
394            level,
395        }
396    }
397}
398
399impl Default for VillagerData {
400    fn default() -> Self {
401        Self {
402            kind: Default::default(),
403            profession: Default::default(),
404            level: 1,
405        }
406    }
407}
408
409impl Encode for VillagerData {
410    fn encode(&self, mut w: impl std::io::Write) -> anyhow::Result<()> {
411        self.kind.encode(&mut w)?;
412        self.profession.encode(&mut w)?;
413        VarInt(self.level).encode(w)
414    }
415}
416
417impl Decode<'_> for VillagerData {
418    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
419        Ok(Self {
420            kind: VillagerKind::decode(r)?,
421            profession: VillagerProfession::decode(r)?,
422            level: VarInt::decode(r)?.0,
423        })
424    }
425}
426
427#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
428pub enum VillagerKind {
429    Desert,
430    Jungle,
431    #[default]
432    Plains,
433    Savanna,
434    Snow,
435    Swamp,
436    Taiga,
437}
438
439#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
440pub enum VillagerProfession {
441    #[default]
442    None,
443    Armorer,
444    Butcher,
445    Cartographer,
446    Cleric,
447    Farmer,
448    Fisherman,
449    Fletcher,
450    Leatherworker,
451    Librarian,
452    Mason,
453    Nitwit,
454    Shepherd,
455    Toolsmith,
456    Weaponsmith,
457}
458
459#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
460pub enum Pose {
461    #[default]
462    Standing,
463    FallFlying,
464    Sleeping,
465    Swimming,
466    SpinAttack,
467    Sneaking,
468    LongJumping,
469    Dying,
470    Croaking,
471    UsingTongue,
472    Roaring,
473    Sniffing,
474    Emerging,
475    Digging,
476}
477
478#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
479pub enum BoatKind {
480    #[default]
481    Oak,
482    Spruce,
483    Birch,
484    Jungle,
485    Acacia,
486    DarkOak,
487}
488
489#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
490pub enum CatKind {
491    Tabby,
492    #[default]
493    Black,
494    Red,
495    Siamese,
496    BritishShorthair,
497    Calico,
498    Persian,
499    Ragdoll,
500    White,
501    Jellie,
502    AllBlack,
503}
504
505#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
506pub enum FrogKind {
507    #[default]
508    Temperate,
509    Warm,
510    Cold,
511}
512
513#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
514pub enum PaintingKind {
515    #[default]
516    Kebab,
517    Aztec,
518    Alban,
519    Aztec2,
520    Bomb,
521    Plant,
522    Wasteland,
523    Pool,
524    Courbet,
525    Sea,
526    Sunset,
527    Creebet,
528    Wanderer,
529    Graham,
530    Match,
531    Bust,
532    Stage,
533    Void,
534    SkullAndRoses,
535    Wither,
536    Fighters,
537    Pointer,
538    Pigscene,
539    BurningSkull,
540    Skeleton,
541    Earth,
542    Wind,
543    Water,
544    Fire,
545    DonkeyKong,
546}
547
548#[derive(Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash, Default, Debug, Encode, Decode)]
549pub enum SnifferState {
550    #[default]
551    Idling,
552    FeelingHappy,
553    Scenting,
554    Sniffing,
555    Searching,
556    Digging,
557    Rising,
558}
559
560#[derive(Clone, Copy, PartialEq, PartialOrd, Debug, Encode, Decode)]
561pub struct EulerAngle {
562    pub pitch: f32,
563    pub yaw: f32,
564    pub roll: f32,
565}
566
567#[derive(Copy, Clone)]
568struct OptionalInt(Option<i32>);
569
570impl Encode for OptionalInt {
571    fn encode(&self, w: impl std::io::Write) -> anyhow::Result<()> {
572        if let Some(n) = self.0 {
573            VarInt(n.wrapping_add(1))
574        } else {
575            VarInt(0)
576        }
577        .encode(w)
578    }
579}
580
581impl Decode<'_> for OptionalInt {
582    fn decode(r: &mut &[u8]) -> anyhow::Result<Self> {
583        let n = VarInt::decode(r)?.0;
584
585        Ok(Self(if n == 0 {
586            None
587        } else {
588            Some(n.wrapping_sub(1))
589        }))
590    }
591}