steel_core/behavior/blocks/building/
spawner_block.rs1use std::sync::{Arc, Weak};
4
5use steel_macros::block_behavior;
6use steel_registry::block_entity_type::BlockEntityTypeRef;
7use steel_registry::blocks::BlockRef;
8use steel_registry::item_stack::ItemStack;
9use steel_registry::vanilla_block_entity_types;
10use steel_utils::{BlockPos, BlockStateId};
11
12use crate::behavior::{BlockBehavior, BlockEntityCreation, BlockPlaceContext};
13use crate::block_entity::{BLOCK_ENTITIES, BlockEntityTicker};
14use crate::world::World;
15
16#[block_behavior]
18pub struct SpawnerBlock {
19 block: BlockRef,
20}
21
22impl SpawnerBlock {
23 const BASE_BREAK_EXPERIENCE: i32 = 15;
25 const BONUS_BREAK_EXPERIENCE_BOUND: i32 = 15;
27
28 #[must_use]
30 pub const fn new(block: BlockRef) -> Self {
31 Self { block }
32 }
33}
34
35impl BlockBehavior for SpawnerBlock {
36 fn get_state_for_placement(&self, _context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
37 Some(self.block.default_state())
38 }
39
40 fn new_block_entity(
41 &self,
42 level: Weak<World>,
43 pos: BlockPos,
44 state: BlockStateId,
45 ) -> BlockEntityCreation {
46 BlockEntityCreation::from_registered_factory(BLOCK_ENTITIES.create(
47 &vanilla_block_entity_types::MOB_SPAWNER,
48 level,
49 pos,
50 state,
51 ))
52 }
53
54 fn get_block_entity_ticker(
55 &self,
56 _world: &Arc<World>,
57 _state: BlockStateId,
58 block_entity_type: BlockEntityTypeRef,
59 ) -> Option<BlockEntityTicker> {
60 BlockEntityTicker::for_matching_entity_tick(
61 block_entity_type,
62 &vanilla_block_entity_types::MOB_SPAWNER,
63 )
64 }
65
66 fn trigger_event(
67 &self,
68 _state: BlockStateId,
69 world: &Arc<World>,
70 pos: BlockPos,
71 event: i32,
72 data: i32,
73 ) -> bool {
74 world
75 .get_block_entity(pos)
76 .is_some_and(|block_entity| block_entity.trigger_event(event, data))
77 }
78
79 fn spawn_after_break(
80 &self,
81 _state: BlockStateId,
82 world: &Arc<World>,
83 pos: BlockPos,
84 _tool: &ItemStack,
85 drop_experience: bool,
86 ) {
87 if drop_experience {
88 let experience = Self::BASE_BREAK_EXPERIENCE
89 + rand::random_range(0..Self::BONUS_BREAK_EXPERIENCE_BOUND)
90 + rand::random_range(0..Self::BONUS_BREAK_EXPERIENCE_BOUND);
91 world.pop_experience(pos, experience);
92 }
93 }
94}