steel_core/behavior/blocks/vegetation/
hanging_roots_block.rs1use 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#[block_behavior]
15pub struct HangingRootsBlock {
16 block: BlockRef,
17}
18
19const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
20
21impl HangingRootsBlock {
22 #[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 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}