steel_core/behavior/blocks/redstone/
redstone_lamp_block.rs1use std::sync::Arc;
4
5use steel_macros::block_behavior;
6use steel_registry::blocks::BlockRef;
7use steel_registry::blocks::block_state_ext::BlockStateExt as _;
8use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
9use steel_utils::types::UpdateFlags;
10use steel_utils::{BlockPos, BlockStateId};
11
12use crate::behavior::{BlockBehavior, BlockPlaceContext};
13use crate::world::{SignalGetter as _, World};
14
15const TURN_OFF_DELAY: i32 = 4;
16
17#[block_behavior]
19pub struct RedstoneLampBlock {
20 block: BlockRef,
21}
22
23const LIT: &BoolProperty = &BlockStateProperties::LIT;
24
25impl RedstoneLampBlock {
26 #[must_use]
28 pub const fn new(block: BlockRef) -> Self {
29 Self { block }
30 }
31}
32
33impl BlockBehavior for RedstoneLampBlock {
34 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
35 Some(
36 self.block
37 .default_state()
38 .set_value(LIT, context.world.has_neighbor_signal(context.place_pos())),
39 )
40 }
41
42 fn handle_neighbor_changed(
43 &self,
44 state: BlockStateId,
45 world: &Arc<World>,
46 pos: BlockPos,
47 _source_block: BlockRef,
48 _moved_by_piston: bool,
49 ) {
50 let lit = state.get_value(LIT);
51 if lit == world.has_neighbor_signal(pos) {
52 return;
53 }
54 if lit {
55 world.schedule_block_tick_default(pos, self.block, TURN_OFF_DELAY);
56 } else {
57 world.set_block(pos, state.set_value(LIT, true), UpdateFlags::UPDATE_CLIENTS);
58 }
59 }
60
61 fn tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
62 if state.get_value(LIT) && !world.has_neighbor_signal(pos) {
63 world.set_block(
64 pos,
65 state.set_value(LIT, false),
66 UpdateFlags::UPDATE_CLIENTS,
67 );
68 }
69 }
70}