Skip to main content

steel_core/behavior/blocks/vegetation/
mycelium_block.rs

1use steel_macros::block_behavior;
2use steel_registry::blocks::BlockRef;
3use steel_registry::vanilla_blocks;
4use steel_utils::{BlockPos, BlockStateId, Direction};
5
6use super::snowy_block::{snowy_placement_state, update_snowy_shape};
7use super::spreading_grass_block::SpreadingGrassBlock;
8use crate::behavior::block::BlockBehavior;
9use crate::behavior::context::BlockPlaceContext;
10use crate::world::{ScheduledTickAccess, World};
11use std::sync::Arc;
12
13/// Behavior for mycelium blocks.
14#[block_behavior]
15pub struct MyceliumBlock {
16    block: BlockRef,
17}
18
19impl MyceliumBlock {
20    /// Creates a new mycelium block behavior.
21    #[must_use]
22    pub const fn new(block: BlockRef) -> Self {
23        Self { block }
24    }
25}
26
27impl BlockBehavior for MyceliumBlock {
28    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
29        Some(snowy_placement_state(self.block, context))
30    }
31
32    fn update_shape(
33        &self,
34        state: BlockStateId,
35        _world: &dyn ScheduledTickAccess,
36        _pos: BlockPos,
37        direction: Direction,
38        _neighbor_pos: BlockPos,
39        neighbor_state: BlockStateId,
40    ) -> BlockStateId {
41        update_snowy_shape(state, direction, neighbor_state)
42    }
43
44    fn random_tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
45        SpreadingGrassBlock::random_tick(
46            &vanilla_blocks::MYCELIUM,
47            &vanilla_blocks::DIRT,
48            state,
49            world,
50            pos,
51        );
52    }
53}
54
55#[cfg(test)]
56mod tests {
57    use steel_registry::blocks::block_state_ext::BlockStateExt;
58    use steel_registry::blocks::properties::BlockStateProperties;
59    use steel_registry::{init_vanilla_registry, vanilla_blocks};
60    use steel_utils::{BlockPos, Direction};
61
62    use super::*;
63    use crate::behavior::init_behaviors;
64    use crate::test_support::TestLevel;
65
66    #[test]
67    fn mycelium_block_updates_snowy_state() {
68        init_vanilla_registry();
69        init_behaviors();
70
71        let level = TestLevel::default();
72        let pos = BlockPos::new(0, 64, 0);
73        let behavior = MyceliumBlock::new(&vanilla_blocks::MYCELIUM);
74
75        let non_snowy = vanilla_blocks::MYCELIUM.default_state();
76        let snowy = behavior.update_shape(
77            non_snowy,
78            &level,
79            pos,
80            Direction::Up,
81            pos.above(),
82            vanilla_blocks::SNOW.default_state(),
83        );
84        assert!(snowy.get_value(&BlockStateProperties::SNOWY));
85
86        let cleared = behavior.update_shape(
87            snowy,
88            &level,
89            pos,
90            Direction::Up,
91            pos.above(),
92            vanilla_blocks::AIR.default_state(),
93        );
94        assert!(!cleared.get_value(&BlockStateProperties::SNOWY));
95    }
96}