Skip to main content

steel_core/behavior/blocks/vegetation/
tall_dry_grass_block.rs

1use 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/// Vanilla `TallDryGrassBlock` survival
22#[block_behavior]
23pub struct TallDryGrassBlock {
24    block: BlockRef,
25}
26
27impl TallDryGrassBlock {
28    /// Creates a new tall dry grass block behavior.
29    #[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}