steel_core/block_entity/entities/spawner/
mod.rs1mod base_spawner;
4mod spawn_data;
5#[cfg(test)]
6mod tests;
7
8use std::sync::{Arc, Weak};
9
10use simdnbt::borrow::BaseNbtCompound as BorrowedNbtCompound;
11use simdnbt::owned::NbtCompound;
12use steel_registry::data_components::components::EntityData;
13use steel_registry::entity_type::EntityTypeRef;
14use steel_registry::vanilla_block_entity_types;
15use steel_utils::{BlockPos, BlockStateId, DowncastType, DowncastTypeKey};
16
17use crate::block_entity::{BlockEntity, BlockEntityBase};
18use crate::world::World;
19
20pub use base_spawner::{BaseSpawner, BaseSpawnerConfig};
21pub use spawn_data::{CustomSpawnRules, EquipmentTable, LightRange, SpawnData, WeightedSpawnData};
22
23pub trait Spawner {
25 fn set_entity_id(&self, entity_type: EntityTypeRef);
27
28 fn set_entity_data(&self, entity_data: &EntityData);
30
31 fn spawn_delay(&self) -> i32;
33
34 fn set_spawn_delay(&self, delay: i32);
36
37 fn config(&self) -> BaseSpawnerConfig;
39
40 fn set_config(&self, config: BaseSpawnerConfig);
42
43 fn spawn_potentials(&self) -> Vec<WeightedSpawnData>;
45
46 fn set_spawn_potentials(&self, potentials: Vec<WeightedSpawnData>);
48
49 fn next_spawn_data(&self) -> Option<SpawnData>;
51
52 fn set_next_spawn_data(&self, data: SpawnData);
54}
55
56pub struct SpawnerBlockEntity {
58 base: BlockEntityBase,
59 spawner: BaseSpawner,
60}
61
62unsafe impl DowncastType for SpawnerBlockEntity {
64 const TYPE_KEY: DowncastTypeKey = DowncastTypeKey::new("steel:block_entity/spawner");
65}
66
67impl SpawnerBlockEntity {
68 #[must_use]
70 pub fn new(level: Weak<World>, pos: BlockPos, state: BlockStateId) -> Self {
71 Self {
72 base: BlockEntityBase::new(&vanilla_block_entity_types::MOB_SPAWNER, level, pos, state),
73 spawner: BaseSpawner::new(),
74 }
75 }
76
77 fn save_and_sync(&self) {
78 self.set_changed();
79 if let Some(world) = self.get_level() {
80 world.send_block_updated(self.get_block_pos());
81 }
82 }
83}
84
85impl Spawner for SpawnerBlockEntity {
86 fn set_entity_id(&self, entity_type: EntityTypeRef) {
87 self.spawner.set_entity_id(entity_type);
88 self.save_and_sync();
89 }
90
91 fn set_entity_data(&self, entity_data: &EntityData) {
92 self.spawner.set_entity_data(entity_data);
93 self.save_and_sync();
94 }
95
96 fn spawn_delay(&self) -> i32 {
97 self.spawner.spawn_delay()
98 }
99
100 fn set_spawn_delay(&self, delay: i32) {
101 self.spawner.set_spawn_delay(delay);
102 self.save_and_sync();
103 }
104
105 fn config(&self) -> BaseSpawnerConfig {
106 self.spawner.config()
107 }
108
109 fn set_config(&self, config: BaseSpawnerConfig) {
110 self.spawner.set_config(config);
111 self.save_and_sync();
112 }
113
114 fn spawn_potentials(&self) -> Vec<WeightedSpawnData> {
115 self.spawner.spawn_potentials()
116 }
117
118 fn set_spawn_potentials(&self, potentials: Vec<WeightedSpawnData>) {
119 self.spawner.set_spawn_potentials(potentials);
120 self.save_and_sync();
121 }
122
123 fn next_spawn_data(&self) -> Option<SpawnData> {
124 self.spawner.next_spawn_data()
125 }
126
127 fn set_next_spawn_data(&self, data: SpawnData) {
128 self.spawner.set_next_spawn_data(data);
129 self.save_and_sync();
130 }
131}
132
133impl BlockEntity for SpawnerBlockEntity {
134 fn base(&self) -> &BlockEntityBase {
135 &self.base
136 }
137
138 fn load_additional(&self, nbt: &BorrowedNbtCompound<'_>) {
139 self.spawner.load(nbt);
140 }
141
142 fn save_additional(&self, nbt: &mut NbtCompound) {
143 self.spawner.save(nbt);
144 }
145
146 fn get_update_tag(&self) -> Option<NbtCompound> {
147 let mut nbt = self.save_custom_only();
148 nbt.remove("SpawnPotentials");
149 Some(nbt)
150 }
151
152 fn trigger_event(&self, event: i32, _data: i32) -> bool {
153 self.spawner.on_event_triggered(event)
154 }
155
156 fn as_spawner(&self) -> Option<&dyn Spawner> {
157 Some(self)
158 }
159
160 fn tick(&self, world: &Arc<World>) {
161 let result = self.spawner.server_tick(world, self.get_block_pos());
162 if result.state_changed {
163 self.set_changed();
164 }
165 if result.next_spawn_data_changed {
166 world.send_block_updated(self.get_block_pos());
167 }
168 }
169}