steel_core/behavior/blocks/vegetation/
tall_dry_grass_block.rs1use std::sync::Arc;
2
3use rand::Rng;
4use steel_macros::block_behavior;
5use steel_registry::{vanilla_block_tags::BlockTag, vanilla_blocks};
6use steel_utils::{BlockPos, BlockStateId, Direction, types::UpdateFlags};
7
8use crate::behavior::{
9 block::BlockBehavior,
10 blocks::vegetation::bonemealable::{
11 BonemealAction, Bonemealable, find_spreadable_neighbor_pos, has_spreadable_neighbor_pos,
12 },
13 context::BlockPlaceContext,
14};
15use crate::world::{LevelReader, ScheduledTickAccess, World};
16
17use super::{
18 BlockRef, default_surviving_state, survives_on_tag, vegetation_block::survival_update_shape,
19};
20
21#[block_behavior]
23pub struct TallDryGrassBlock {
24 block: BlockRef,
25}
26
27impl TallDryGrassBlock {
28 #[must_use]
30 pub const fn new(block: BlockRef) -> Self {
31 Self { block }
32 }
33}
34
35impl BlockBehavior for TallDryGrassBlock {
36 fn update_shape(
37 &self,
38 state: BlockStateId,
39 world: &dyn ScheduledTickAccess,
40 pos: BlockPos,
41 _direction: Direction,
42 _neighbor_pos: BlockPos,
43 _neighbor_state: BlockStateId,
44 ) -> BlockStateId {
45 survival_update_shape(self, state, world, pos)
46 }
47
48 fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
49 survives_on_tag(world, pos, &BlockTag::SUPPORTS_DRY_VEGETATION)
50 }
51
52 fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
53 default_surviving_state(self.block, self, context)
54 }
55
56 fn as_bonemealable(&self) -> Option<&dyn Bonemealable> {
57 Some(self)
58 }
59}
60
61impl Bonemealable for TallDryGrassBlock {
62 fn is_valid_bonemeal_target(
63 &self,
64 _state: BlockStateId,
65 world: &dyn LevelReader,
66 pos: BlockPos,
67 ) -> bool {
68 has_spreadable_neighbor_pos(world, pos, vanilla_blocks::SHORT_DRY_GRASS.default_state())
69 }
70
71 fn perform_bonemeal(
72 &self,
73 _state: BlockStateId,
74 world: &Arc<World>,
75 _rng: &mut dyn Rng,
76 pos: BlockPos,
77 ) {
78 if let Some(spread_pos) = find_spreadable_neighbor_pos(
79 world,
80 pos,
81 vanilla_blocks::SHORT_DRY_GRASS.default_state(),
82 ) {
83 world.set_block(
84 spread_pos,
85 vanilla_blocks::SHORT_DRY_GRASS.default_state(),
86 UpdateFlags::UPDATE_ALL,
87 );
88 }
89 }
90
91 fn bonemeal_action_type(&self) -> BonemealAction {
92 BonemealAction::NeighborSpreader
93 }
94}