steel_core/behavior/blocks/vegetation/
mushroom_block.rs1use steel_macros::block_behavior;
2use steel_registry::blocks::block_state_ext::BlockStateExt;
3use steel_registry::blocks::properties::Direction;
4use steel_registry::vanilla_block_tags::BlockTag;
5use steel_registry::vanilla_blocks;
6use steel_utils::{BlockPos, BlockStateId};
7
8use crate::behavior::block::BlockBehavior;
9use crate::behavior::context::BlockPlaceContext;
10use crate::world::{LevelReader, ScheduledTickAccess};
11
12use super::{BlockRef, default_surviving_state};
13
14#[block_behavior]
17pub struct MushroomBlock {
18 block: BlockRef,
19}
20
21impl MushroomBlock {
22 #[must_use]
24 pub const fn new(block: BlockRef) -> Self {
25 Self { block }
26 }
27}
28
29impl BlockBehavior for MushroomBlock {
30 fn update_shape(
31 &self,
32 state: BlockStateId,
33 world: &dyn ScheduledTickAccess,
34 pos: BlockPos,
35 _direction: Direction,
36 _neighbor_pos: BlockPos,
37 _neighbor_state: BlockStateId,
38 ) -> BlockStateId {
39 if self.can_survive(state, world, pos) {
40 state
41 } else {
42 vanilla_blocks::AIR.default_state()
43 }
44 }
45
46 fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
47 let below_pos = pos.below();
48 let below = world.get_block_state(below_pos);
49 if below
50 .get_block()
51 .has_tag(&BlockTag::OVERRIDES_MUSHROOM_LIGHT_REQUIREMENT)
52 {
53 return true;
54 }
55
56 world.raw_brightness(pos, 0) < 13 && below.is_solid_render()
57 }
58
59 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
60 default_surviving_state(self.block, self, context)
61 }
62}
63
64#[cfg(test)]
65mod tests {
66 use steel_registry::{REGISTRY, init_vanilla_registry, vanilla_blocks};
67
68 use crate::test_support::TestLevel;
69
70 use super::*;
71
72 fn single_support_level(support: BlockStateId, raw_brightness: u8) -> TestLevel {
73 TestLevel::default()
74 .with_block(BlockPos::ZERO.below(), support)
75 .with_raw_brightness(raw_brightness)
76 }
77
78 #[test]
79 fn mushroom_survival_uses_solid_render_support() {
80 init_vanilla_registry();
81
82 let mushroom = MushroomBlock::new(&vanilla_blocks::BROWN_MUSHROOM);
83 let state = REGISTRY
84 .blocks
85 .get_default_state_id(&vanilla_blocks::BROWN_MUSHROOM);
86 let pos = BlockPos::new(0, 0, 0);
87
88 let grass_block = REGISTRY
89 .blocks
90 .get_default_state_id(&vanilla_blocks::GRASS_BLOCK);
91 assert!(mushroom.can_survive(state, &single_support_level(grass_block, 12), pos));
92 assert!(!mushroom.can_survive(state, &single_support_level(grass_block, 13), pos));
93
94 let oak_leaves = REGISTRY
95 .blocks
96 .get_default_state_id(&vanilla_blocks::OAK_LEAVES);
97 assert!(!mushroom.can_survive(state, &single_support_level(oak_leaves, 0), pos));
98
99 let podzol = REGISTRY
100 .blocks
101 .get_default_state_id(&vanilla_blocks::PODZOL);
102 assert!(mushroom.can_survive(state, &single_support_level(podzol, 15), pos));
103 }
104}