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;
4use steel_registry::{vanilla_blocks, vanilla_fluids};
5use steel_utils::{BlockPos, BlockStateId, Direction};
6
7use crate::behavior::block::BlockBehavior;
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
19impl HangingRootsBlock {
20 #[must_use]
22 pub const fn new(block: BlockRef) -> Self {
23 Self { block }
24 }
25}
26
27impl BlockBehavior for HangingRootsBlock {
28 fn update_shape(
29 &self,
30 state: BlockStateId,
31 world: &dyn ScheduledTickAccess,
32 pos: BlockPos,
33 direction: Direction,
34 _neighbor_pos: BlockPos,
35 _neighbor_state: BlockStateId,
36 ) -> BlockStateId {
37 if direction == Direction::Up && !self.can_survive(state, world, pos) {
38 return vanilla_blocks::AIR.default_state();
39 }
40
41 if state.get_value(&BlockStateProperties::WATERLOGGED) {
42 let delay = world.fluid_tick_delay(&vanilla_fluids::WATER);
43 let _ = world.schedule_fluid_tick_default(pos, &vanilla_fluids::WATER, delay);
44 }
45
46 state
47 }
48
49 fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
50 let above_pos = pos.above();
52 let above = world.get_block_state(above_pos);
53 world.is_face_sturdy(above, above_pos, Direction::Down)
54 }
55
56 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
57 let state = self.block.default_state();
58 if !self.can_survive(state, context.world, context.place_pos()) {
59 return None;
60 }
61 Some(state.set_value(
62 &BlockStateProperties::WATERLOGGED,
63 context.is_water_source(),
64 ))
65 }
66}