Skip to main content

steel_core/behavior/blocks/vegetation/
hanging_roots_block.rs

1use steel_macros::block_behavior;
2use steel_registry::blocks::block_state_ext::BlockStateExt;
3use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
4use steel_registry::vanilla_blocks;
5use steel_utils::{BlockPos, BlockStateId, Direction};
6
7use crate::behavior::block::{BlockBehavior, schedule_water_tick_if_waterlogged};
8use crate::behavior::context::BlockPlaceContext;
9use crate::world::{LevelReader, ScheduledTickAccess};
10
11use super::BlockRef;
12
13/// Vanilla `HangingRootsBlock` survival
14#[block_behavior]
15pub struct HangingRootsBlock {
16    block: BlockRef,
17}
18
19const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
20
21impl HangingRootsBlock {
22    /// Creates a new hanging roots block behavior.
23    #[must_use]
24    pub const fn new(block: BlockRef) -> Self {
25        Self { block }
26    }
27}
28
29impl BlockBehavior for HangingRootsBlock {
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 direction == Direction::Up && !self.can_survive(state, world, pos) {
40            return vanilla_blocks::AIR.default_state();
41        }
42
43        schedule_water_tick_if_waterlogged(state, world, pos);
44
45        state
46    }
47
48    fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
49        // Vanilla: the block above must be face-sturdy on its DOWN face.
50        let above_pos = pos.above();
51        let above = world.get_block_state(above_pos);
52        world.is_face_sturdy(above, above_pos, Direction::Down)
53    }
54
55    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
56        let state = self.block.default_state();
57        if !self.can_survive(state, context.world, context.place_pos()) {
58            return None;
59        }
60        Some(state.set_value(WATERLOGGED, context.is_water_source()))
61    }
62}