steel_core/entity/entities/
raw.rs1use std::sync::Weak;
4
5use glam::DVec3;
6use simdnbt::borrow::NbtCompound as BorrowedNbtCompoundView;
7use simdnbt::owned::NbtCompound;
8use steel_registry::entity_type::EntityTypeRef;
9use steel_utils::{DowncastType, DowncastTypeKey, UuidExt, locks::SyncMutex};
10use uuid::Uuid;
11
12use crate::entity::{Entity, EntityBase, EntityBaseLoad};
13use crate::world::World;
14
15pub struct RawEntity {
20 base: EntityBase,
21 entity_type: EntityTypeRef,
22 data: SyncMutex<NbtCompound>,
23}
24
25unsafe impl DowncastType for RawEntity {
28 const TYPE_KEY: DowncastTypeKey = DowncastTypeKey::new("steel:entity/raw");
29}
30
31impl RawEntity {
32 #[must_use]
34 pub fn new(id: i32, position: DVec3, world: Weak<World>, entity_type: EntityTypeRef) -> Self {
35 Self {
36 base: EntityBase::new(id, position, entity_type.dimensions, world),
37 entity_type,
38 data: SyncMutex::new(NbtCompound::new()),
39 }
40 }
41
42 #[must_use]
44 pub fn from_saved(load: EntityBaseLoad, entity_type: EntityTypeRef) -> Self {
45 Self {
46 base: EntityBase::from_load(load, entity_type.dimensions),
47 entity_type,
48 data: SyncMutex::new(NbtCompound::new()),
49 }
50 }
51
52 pub fn snap_to(&self, position: DVec3, yaw: f32, pitch: f32) {
59 if let Err(error) = self.base.try_set_position(position) {
60 panic!(
61 "failed to commit raw entity {} snap position: {error}",
62 self.base.id()
63 );
64 }
65 self.base.set_rotation((yaw, pitch));
66 self.set_old_position_to_current();
67 }
68
69 pub fn set_persistence_required(&self) {
71 self.data.lock().insert("PersistenceRequired", 1_i8);
72 }
73}
74
75impl Entity for RawEntity {
76 fn base(&self) -> &EntityBase {
77 &self.base
78 }
79
80 fn entity_type(&self) -> EntityTypeRef {
81 self.entity_type
82 }
83
84 fn tick(&self) {
85 }
87
88 fn attackable(&self) -> bool {
89 false
90 }
91
92 fn projectile_owner_uuid(&self) -> Option<Uuid> {
93 if !self.entity_type.is_projectile {
94 return None;
95 }
96
97 self.projectile_owner_uuid_from_nbt()
98 }
99
100 fn load_additional(&self, nbt: BorrowedNbtCompoundView<'_, '_>) {
101 *self.data.lock() = nbt.to_owned();
102 }
103
104 fn save_additional(&self, nbt: &mut NbtCompound) {
105 *nbt = self.data.lock().clone();
106 }
107}
108
109impl RawEntity {
110 fn projectile_owner_uuid_from_nbt(&self) -> Option<Uuid> {
111 let data = self.data.lock();
112 let owner = data.int_array("Owner")?;
113 Uuid::from_int_array(owner)
114 }
115}
116
117#[cfg(test)]
118mod tests {
119 use std::sync::Weak;
120
121 use glam::DVec3;
122 use simdnbt::owned::NbtTag;
123 use steel_registry::vanilla_entities;
124 use steel_utils::UuidExt;
125 use uuid::Uuid;
126
127 use crate::entity::Entity;
128
129 use super::RawEntity;
130
131 #[test]
132 fn raw_projectile_reads_vanilla_owner_uuid() {
133 let owner = Uuid::from_u128(42);
134 let entity = RawEntity::new(1, DVec3::ZERO, Weak::new(), &vanilla_entities::ENDER_PEARL);
135 entity
136 .data
137 .lock()
138 .insert("Owner", NbtTag::IntArray(owner.to_int_array().to_vec()));
139
140 assert_eq!(entity.projectile_owner_uuid(), Some(owner));
141 }
142}