steel_core/entity/base/persistence.rs
1use std::{collections::BTreeSet, sync::Weak};
2
3use glam::DVec3;
4use simdnbt::owned::NbtCompound;
5use text_components::TextComponent;
6use uuid::Uuid;
7
8use super::{DEFAULT_MAX_AIR_SUPPLY, EntityFireFreezeState, MAX_ENTITY_TAGS};
9use crate::world::World;
10
11/// Shared vanilla entity save data that is not part of the movement snapshot.
12#[derive(Debug, Clone, PartialEq)]
13pub struct EntityBaseSaveData {
14 /// Synchronized vanilla `Air`/air supply value.
15 pub air_supply: i32,
16 /// Vanilla dimension-change portal cooldown.
17 pub portal_cooldown: i32,
18 /// Shared vanilla `NoGravity` flag.
19 pub no_gravity: bool,
20 /// Shared vanilla `Invulnerable` flag.
21 pub invulnerable: bool,
22 /// Optional synchronized vanilla custom name.
23 pub custom_name: Option<TextComponent>,
24 /// Synchronized vanilla custom-name visibility flag.
25 pub custom_name_visible: bool,
26 /// Synchronized vanilla silent flag.
27 pub silent: bool,
28 /// Server-owned vanilla glowing tag, projected into the shared flags byte.
29 pub glowing: bool,
30 /// Vanilla scoreboard tags.
31 pub tags: BTreeSet<String>,
32 /// Vanilla custom data component payload.
33 pub custom_data: NbtCompound,
34}
35
36impl EntityBaseSaveData {
37 /// Creates default vanilla base save data.
38 #[must_use]
39 pub fn new() -> Self {
40 Self {
41 air_supply: DEFAULT_MAX_AIR_SUPPLY,
42 portal_cooldown: 0,
43 no_gravity: false,
44 invulnerable: false,
45 custom_name: None,
46 custom_name_visible: false,
47 silent: false,
48 glowing: false,
49 tags: BTreeSet::new(),
50 custom_data: NbtCompound::new(),
51 }
52 }
53
54 /// Adds a scoreboard tag, respecting vanilla's per-entity tag limit.
55 pub fn add_tag(&mut self, tag: String) -> bool {
56 if self.tags.len() >= MAX_ENTITY_TAGS && !self.tags.contains(&tag) {
57 return false;
58 }
59 self.tags.insert(tag)
60 }
61}
62
63impl Default for EntityBaseSaveData {
64 fn default() -> Self {
65 Self::new()
66 }
67}
68
69/// Base fields restored from persistent entity data.
70///
71/// Vanilla loads these fields through `Entity.load` before type-specific
72/// entity data. Keeping them bundled makes the load boundary explicit and
73/// prevents constructor signatures from drifting as base state grows.
74#[derive(Debug, Clone)]
75pub struct EntityBaseLoad {
76 /// Fresh runtime ID from `next_entity_id()`.
77 pub id: i32,
78 /// Restored entity position.
79 pub position: DVec3,
80 /// Persisted entity UUID.
81 pub uuid: Uuid,
82 /// Restored velocity.
83 pub velocity: DVec3,
84 /// Restored yaw and pitch.
85 pub rotation: (f32, f32),
86 /// Restored accumulated fall distance.
87 pub fall_distance: f64,
88 /// Restored vanilla fire/freeze state.
89 pub fire_freeze: EntityFireFreezeState,
90 /// Restored ground-contact flag.
91 pub on_ground: bool,
92 /// Restored shared vanilla save data.
93 pub save_data: EntityBaseSaveData,
94 /// World reference for the loaded entity.
95 pub world: Weak<World>,
96}