steel_core/behavior/blocks/vegetation/
mangrove_propagule_block.rs1use steel_macros::block_behavior;
2use steel_registry::blocks::block_state_ext::BlockStateExt;
3use steel_registry::blocks::properties::{BlockStateProperties, Direction};
4use steel_registry::vanilla_block_tags::BlockTag;
5use steel_registry::vanilla_blocks;
6use steel_utils::{BlockPos, BlockStateId};
7
8use crate::behavior::block::{BlockBehavior, schedule_water_tick_if_waterlogged};
9use crate::behavior::context::BlockPlaceContext;
10use crate::world::{LevelReader, ScheduledTickAccess};
11
12use super::{BlockRef, default_surviving_state};
13
14#[block_behavior]
21pub struct MangrovePropaguleBlock {
22 block: BlockRef,
23}
24
25impl MangrovePropaguleBlock {
26 #[must_use]
28 pub const fn new(block: BlockRef) -> Self {
29 Self { block }
30 }
31
32 pub(crate) fn create_new_hanging_propagule() -> BlockStateId {
34 vanilla_blocks::MANGROVE_PROPAGULE
35 .default_state()
36 .set_value(&BlockStateProperties::HANGING, true)
37 .set_value(&BlockStateProperties::AGE_4, 0)
38 }
39}
40
41impl BlockBehavior for MangrovePropaguleBlock {
42 fn update_shape(
43 &self,
44 state: BlockStateId,
45 world: &dyn ScheduledTickAccess,
46 pos: BlockPos,
47 _direction: Direction,
48 _neighbor_pos: BlockPos,
49 _neighbor_state: BlockStateId,
50 ) -> BlockStateId {
51 schedule_water_tick_if_waterlogged(state, world, pos);
52 if self.can_survive(state, world, pos) {
53 state
54 } else {
55 vanilla_blocks::AIR.default_state()
56 }
57 }
58
59 fn can_survive(&self, state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
60 if state.get_value(&BlockStateProperties::HANGING) {
61 let above = world.get_block_state(pos.above());
62 return above
63 .get_block()
64 .has_tag(&BlockTag::SUPPORTS_HANGING_MANGROVE_PROPAGULE);
65 }
66
67 let below = world.get_block_state(pos.below());
68 below
69 .get_block()
70 .has_tag(&BlockTag::SUPPORTS_MANGROVE_PROPAGULE)
71 }
72
73 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
74 default_surviving_state(self.block, self, context)
75 }
76}
77
78#[cfg(test)]
79mod tests {
80 use steel_registry::init_vanilla_registry;
81
82 use super::*;
83 use crate::test_support::TestLevel;
84
85 #[test]
86 fn new_hanging_propagule_starts_at_age_zero() {
87 init_vanilla_registry();
88
89 let state = MangrovePropaguleBlock::create_new_hanging_propagule();
90
91 assert_eq!(state.get_block(), &vanilla_blocks::MANGROVE_PROPAGULE);
92 assert!(state.get_value(&BlockStateProperties::HANGING));
93 assert_eq!(state.get_value(&BlockStateProperties::AGE_4), 0);
94 }
95
96 #[test]
97 fn unsupported_waterlogged_propagule_schedules_water_before_breaking() {
98 init_vanilla_registry();
99 let behavior = MangrovePropaguleBlock::new(&vanilla_blocks::MANGROVE_PROPAGULE);
100 let state = vanilla_blocks::MANGROVE_PROPAGULE
101 .default_state()
102 .set_value(&BlockStateProperties::WATERLOGGED, true);
103 let level = TestLevel::default();
104
105 assert!(
106 behavior
107 .update_shape(
108 state,
109 &level,
110 BlockPos::ZERO,
111 Direction::Down,
112 BlockPos::ZERO.below(),
113 vanilla_blocks::AIR.default_state(),
114 )
115 .is_air()
116 );
117 assert!(level.scheduled_water_tick());
118 }
119}