steel_core/behavior/blocks/vegetation/
chorus_plant_block.rs1use steel_macros::block_behavior;
2use steel_registry::blocks::block_state_ext::BlockStateExt;
3use steel_registry::blocks::properties::BlockStateProperties;
4use steel_registry::vanilla_block_tags::BlockTag;
5use steel_registry::vanilla_blocks;
6use steel_utils::{BlockPos, BlockStateId, Direction};
7
8use crate::behavior::block::BlockBehavior;
9use crate::behavior::context::BlockPlaceContext;
10use crate::world::LevelReader;
11
12use super::BlockRef;
13
14const HORIZONTAL_DIRECTIONS: [Direction; 4] = [
15 Direction::North,
16 Direction::East,
17 Direction::South,
18 Direction::West,
19];
20
21#[block_behavior]
24pub struct ChorusPlantBlock {
25 block: BlockRef,
26}
27
28impl ChorusPlantBlock {
29 #[must_use]
31 pub const fn new(block: BlockRef) -> Self {
32 Self { block }
33 }
34
35 #[must_use]
36 pub(crate) fn state_with_connections(
37 world: &dyn LevelReader,
38 pos: BlockPos,
39 mut state: BlockStateId,
40 ) -> BlockStateId {
41 let down = world.get_block_state(pos.below());
42 let up = world.get_block_state(pos.above());
43 let north = world.get_block_state(pos.north());
44 let east = world.get_block_state(pos.east());
45 let south = world.get_block_state(pos.south());
46 let west = world.get_block_state(pos.west());
47 let block = state.get_block();
48
49 state = state.set_value(
50 &BlockStateProperties::DOWN,
51 down.get_block() == block
52 || down.get_block() == &vanilla_blocks::CHORUS_FLOWER
53 || down.get_block().has_tag(&BlockTag::SUPPORTS_CHORUS_PLANT),
54 );
55 state = state.set_value(
56 &BlockStateProperties::UP,
57 up.get_block() == block || up.get_block() == &vanilla_blocks::CHORUS_FLOWER,
58 );
59 state = state.set_value(
60 &BlockStateProperties::NORTH,
61 north.get_block() == block || north.get_block() == &vanilla_blocks::CHORUS_FLOWER,
62 );
63 state = state.set_value(
64 &BlockStateProperties::EAST,
65 east.get_block() == block || east.get_block() == &vanilla_blocks::CHORUS_FLOWER,
66 );
67 state = state.set_value(
68 &BlockStateProperties::SOUTH,
69 south.get_block() == block || south.get_block() == &vanilla_blocks::CHORUS_FLOWER,
70 );
71 state.set_value(
72 &BlockStateProperties::WEST,
73 west.get_block() == block || west.get_block() == &vanilla_blocks::CHORUS_FLOWER,
74 )
75 }
76}
77
78impl BlockBehavior for ChorusPlantBlock {
79 fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
80 let below_state = world.get_block_state(pos.below());
81 let block_above_or_below =
82 !world.get_block_state(pos.above()).is_air() && !below_state.is_air();
83
84 for direction in HORIZONTAL_DIRECTIONS {
85 let neighbor_pos = pos.relative(direction);
86 let neighbor_state = world.get_block_state(neighbor_pos);
87 if neighbor_state.get_block() == self.block {
88 if block_above_or_below {
89 return false;
90 }
91
92 let below = world.get_block_state(neighbor_pos.below());
93 if below.get_block() == self.block
94 || below.get_block().has_tag(&BlockTag::SUPPORTS_CHORUS_PLANT)
95 {
96 return true;
97 }
98 }
99 }
100
101 below_state.get_block() == self.block
102 || below_state
103 .get_block()
104 .has_tag(&BlockTag::SUPPORTS_CHORUS_PLANT)
105 }
106
107 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
108 Some(Self::state_with_connections(
109 context.world.as_ref(),
110 context.place_pos(),
111 self.block.default_state(),
112 ))
113 }
114}