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;
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
23impl RedstoneLampBlock {
24 #[must_use]
26 pub const fn new(block: BlockRef) -> Self {
27 Self { block }
28 }
29}
30
31impl BlockBehavior for RedstoneLampBlock {
32 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
33 Some(self.block.default_state().set_value(
34 &BlockStateProperties::LIT,
35 context.world.has_neighbor_signal(context.place_pos()),
36 ))
37 }
38
39 fn handle_neighbor_changed(
40 &self,
41 state: BlockStateId,
42 world: &Arc<World>,
43 pos: BlockPos,
44 _source_block: BlockRef,
45 _moved_by_piston: bool,
46 ) {
47 let lit = state.get_value(&BlockStateProperties::LIT);
48 if lit == world.has_neighbor_signal(pos) {
49 return;
50 }
51 if lit {
52 world.schedule_block_tick_default(pos, self.block, TURN_OFF_DELAY);
53 } else {
54 world.set_block(
55 pos,
56 state.set_value(&BlockStateProperties::LIT, true),
57 UpdateFlags::UPDATE_CLIENTS,
58 );
59 }
60 }
61
62 fn tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
63 if state.get_value(&BlockStateProperties::LIT) && !world.has_neighbor_signal(pos) {
64 world.set_block(
65 pos,
66 state.set_value(&BlockStateProperties::LIT, false),
67 UpdateFlags::UPDATE_CLIENTS,
68 );
69 }
70 }
71}