Skip to main content

steel_core/behavior/blocks/vegetation/
mangrove_roots_block.rs

1use steel_macros::block_behavior;
2use steel_registry::blocks::properties::Direction;
3use steel_utils::{BlockPos, BlockStateId};
4
5use crate::behavior::block::BlockBehavior;
6use crate::behavior::blocks::WaterloggedTransparentBlock;
7use crate::behavior::context::BlockPlaceContext;
8use crate::world::ScheduledTickAccess;
9
10use super::BlockRef;
11
12/// Vanilla mangrove roots behavior.
13#[block_behavior]
14pub struct MangroveRootsBlock {
15    waterlogged: WaterloggedTransparentBlock,
16}
17
18impl MangroveRootsBlock {
19    /// Creates a new mangrove roots behavior.
20    #[must_use]
21    pub const fn new(block: BlockRef) -> Self {
22        Self {
23            waterlogged: WaterloggedTransparentBlock::new(block),
24        }
25    }
26}
27
28impl BlockBehavior for MangroveRootsBlock {
29    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
30        self.waterlogged.get_state_for_placement(context)
31    }
32
33    fn update_shape(
34        &self,
35        state: BlockStateId,
36        world: &dyn ScheduledTickAccess,
37        pos: BlockPos,
38        direction: Direction,
39        neighbor_pos: BlockPos,
40        neighbor_state: BlockStateId,
41    ) -> BlockStateId {
42        self.waterlogged
43            .update_shape(state, world, pos, direction, neighbor_pos, neighbor_state)
44    }
45}
46
47#[cfg(test)]
48mod tests {
49    use steel_registry::blocks::block_state_ext::BlockStateExt;
50    use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
51    use steel_registry::item_stack::ItemStack;
52    use steel_registry::{init_vanilla_registry, vanilla_blocks, vanilla_fluids, vanilla_items};
53    use steel_utils::{ChunkPos, types::UpdateFlags};
54
55    use super::*;
56    use crate::behavior::init_behaviors;
57    use crate::test_support::{TestLevel, fresh_test_world, insert_ready_full_chunk};
58
59    const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
60
61    #[test]
62    fn placement_preserves_source_water() {
63        init_vanilla_registry();
64        init_behaviors();
65        let world = fresh_test_world("mangrove_roots_placement");
66        let wet_pos = BlockPos::new(8, 64, 8);
67        let dry_pos = wet_pos.east();
68        insert_ready_full_chunk(&world, ChunkPos::from_block_pos(wet_pos));
69        assert!(world.set_block(
70            wet_pos,
71            vanilla_blocks::WATER.default_state(),
72            UpdateFlags::UPDATE_NONE,
73        ));
74        let behavior = MangroveRootsBlock::new(&vanilla_blocks::MANGROVE_ROOTS);
75
76        let wet_state = {
77            let mut stack = ItemStack::new(&vanilla_items::MANGROVE_ROOTS);
78            let context = BlockPlaceContext::directional(
79                &world,
80                wet_pos,
81                Direction::Down,
82                &mut stack,
83                Direction::Up,
84            );
85            behavior
86                .get_state_for_placement(&context)
87                .expect("mangrove roots should have a wet placement state")
88        };
89        let dry_state = {
90            let mut stack = ItemStack::new(&vanilla_items::MANGROVE_ROOTS);
91            let context = BlockPlaceContext::directional(
92                &world,
93                dry_pos,
94                Direction::Down,
95                &mut stack,
96                Direction::Up,
97            );
98            behavior
99                .get_state_for_placement(&context)
100                .expect("mangrove roots should have a dry placement state")
101        };
102
103        assert!(wet_state.get_value(WATERLOGGED));
104        assert!(!dry_state.get_value(WATERLOGGED));
105    }
106
107    #[test]
108    fn waterlogged_neighbor_update_schedules_water_tick() {
109        init_vanilla_registry();
110        let behavior = MangroveRootsBlock::new(&vanilla_blocks::MANGROVE_ROOTS);
111        let wet_state = vanilla_blocks::MANGROVE_ROOTS
112            .default_state()
113            .set_value(WATERLOGGED, true);
114        let dry_state = wet_state.set_value(WATERLOGGED, false);
115        let wet_level = TestLevel::default();
116        let dry_level = TestLevel::default();
117
118        assert_eq!(
119            behavior.update_shape(
120                wet_state,
121                &wet_level,
122                BlockPos::ZERO,
123                Direction::Up,
124                BlockPos::ZERO.above(),
125                vanilla_blocks::AIR.default_state(),
126            ),
127            wet_state
128        );
129        assert_eq!(
130            behavior.update_shape(
131                dry_state,
132                &dry_level,
133                BlockPos::ZERO,
134                Direction::Up,
135                BlockPos::ZERO.above(),
136                vanilla_blocks::AIR.default_state(),
137            ),
138            dry_state
139        );
140        assert!(wet_level.scheduled_water_tick());
141        assert!(!dry_level.scheduled_water_tick());
142    }
143
144    #[test]
145    fn waterlogged_roots_contain_source_water() {
146        init_vanilla_registry();
147        let state = vanilla_blocks::MANGROVE_ROOTS
148            .default_state()
149            .set_value(WATERLOGGED, true);
150
151        let fluid = state.get_fluid_state();
152
153        assert_eq!(fluid.fluid_id, &vanilla_fluids::WATER);
154        assert!(fluid.is_source());
155    }
156}