steel_core/behavior/blocks/vegetation/
huge_mushroom_block.rs1use steel_macros::block_behavior;
2use steel_registry::blocks::block_state_ext::BlockStateExt;
3use steel_registry::blocks::properties::Direction;
4use steel_utils::{BlockPos, BlockStateId};
5
6use crate::behavior::block::BlockBehavior;
7use crate::behavior::blocks::utils::multiface_face_property;
8use crate::behavior::context::BlockPlaceContext;
9use crate::world::{LevelReader, ScheduledTickAccess};
10
11use super::BlockRef;
12
13#[block_behavior]
15pub struct HugeMushroomBlock {
16 block: BlockRef,
17}
18
19impl HugeMushroomBlock {
20 #[must_use]
22 pub const fn new(block: BlockRef) -> Self {
23 Self { block }
24 }
25
26 fn placement_state(&self, world: &dyn LevelReader, pos: BlockPos) -> BlockStateId {
27 let mut state = self.block.default_state();
28 for direction in Direction::ALL {
29 let exposed = world.get_block_state(pos.relative(direction)).get_block() != self.block;
30 state = state.set_value(multiface_face_property(direction), exposed);
31 }
32 state
33 }
34}
35
36impl BlockBehavior for HugeMushroomBlock {
37 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
38 Some(self.placement_state(context.world, context.place_pos()))
39 }
40
41 fn update_shape(
42 &self,
43 state: BlockStateId,
44 _world: &dyn ScheduledTickAccess,
45 _pos: BlockPos,
46 direction: Direction,
47 _neighbor_pos: BlockPos,
48 neighbor_state: BlockStateId,
49 ) -> BlockStateId {
50 if neighbor_state.get_block() == self.block {
51 state.set_value(multiface_face_property(direction), false)
52 } else {
53 state
54 }
55 }
56}
57
58#[cfg(test)]
59mod tests {
60 use crate::test_support::TestLevel;
61 use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
62 use steel_registry::{init_vanilla_registry, vanilla_blocks};
63
64 use super::*;
65
66 const DOWN: &BoolProperty = &BlockStateProperties::DOWN;
67 const EAST: &BoolProperty = &BlockStateProperties::EAST;
68 const NORTH: &BoolProperty = &BlockStateProperties::NORTH;
69 const SOUTH: &BoolProperty = &BlockStateProperties::SOUTH;
70 const UP: &BoolProperty = &BlockStateProperties::UP;
71 const WEST: &BoolProperty = &BlockStateProperties::WEST;
72
73 #[test]
74 fn placement_hides_only_faces_joined_to_the_same_mushroom_block() {
75 init_vanilla_registry();
76 let pos = BlockPos::new(0, 64, 0);
77 let level = TestLevel::default()
78 .with_block(
79 pos.below(),
80 vanilla_blocks::BROWN_MUSHROOM_BLOCK.default_state(),
81 )
82 .with_block(
83 pos.above(),
84 vanilla_blocks::BROWN_MUSHROOM_BLOCK.default_state(),
85 )
86 .with_block(
87 pos.north(),
88 vanilla_blocks::BROWN_MUSHROOM_BLOCK.default_state(),
89 )
90 .with_block(
91 pos.south(),
92 vanilla_blocks::RED_MUSHROOM_BLOCK.default_state(),
93 );
94 let behavior = HugeMushroomBlock::new(&vanilla_blocks::BROWN_MUSHROOM_BLOCK);
95
96 let state = behavior.placement_state(&level, pos);
97
98 assert!(!state.get_value(DOWN));
99 assert!(!state.get_value(UP));
100 assert!(!state.get_value(NORTH));
101 assert!(state.get_value(SOUTH));
102 assert!(state.get_value(WEST));
103 assert!(state.get_value(EAST));
104 }
105
106 #[test]
107 fn matching_neighbor_hides_the_joined_face() {
108 init_vanilla_registry();
109 let behavior = HugeMushroomBlock::new(&vanilla_blocks::MUSHROOM_STEM);
110 let state = vanilla_blocks::MUSHROOM_STEM.default_state();
111 let level = TestLevel::default();
112
113 let updated = behavior.update_shape(
114 state,
115 &level,
116 BlockPos::ZERO,
117 Direction::East,
118 BlockPos::ZERO.east(),
119 vanilla_blocks::MUSHROOM_STEM.default_state(),
120 );
121
122 assert!(!updated.get_value(EAST));
123 }
124
125 #[test]
126 fn removing_a_neighbor_does_not_restore_a_hidden_face() {
127 init_vanilla_registry();
128 let behavior = HugeMushroomBlock::new(&vanilla_blocks::RED_MUSHROOM_BLOCK);
129 let state = vanilla_blocks::RED_MUSHROOM_BLOCK
130 .default_state()
131 .set_value(WEST, false);
132 let level = TestLevel::default();
133
134 let updated = behavior.update_shape(
135 state,
136 &level,
137 BlockPos::ZERO,
138 Direction::West,
139 BlockPos::ZERO.west(),
140 vanilla_blocks::AIR.default_state(),
141 );
142
143 assert!(!updated.get_value(WEST));
144 }
145}