Skip to main content

steel_core/behavior/blocks/vegetation/
vegetation_block.rs

1use steel_registry::{
2    blocks::block_state_ext::BlockStateExt, vanilla_block_tags::BlockTag, vanilla_blocks,
3};
4use steel_utils::{BlockPos, BlockStateId};
5
6use crate::{
7    behavior::BlockBehavior,
8    world::{LevelReader, ScheduledTickAccess},
9};
10
11/// Common behavior for vegetation blocks
12pub trait Vegetation {
13    /// Checks if the vegetation block can be placed on the given block state below on the given position below.
14    fn may_place_on(&self, state: BlockStateId, _world: &dyn LevelReader, _pos: BlockPos) -> bool {
15        state.get_block().has_tag(&BlockTag::SUPPORTS_VEGETATION)
16    }
17}
18
19/// Shared survival logic for basic vegetation.
20pub fn vegetation_can_survive<H: Vegetation>(
21    hooks: &H,
22    _state: BlockStateId,
23    world: &dyn LevelReader,
24    pos: BlockPos,
25) -> bool {
26    let state_below = world.get_block_state(pos.below());
27    hooks.may_place_on(state_below, world, pos.below())
28}
29
30/// Shared update-shape logic for blocks that break when they can no longer survive.
31///
32/// Important: this calls the final `BlockBehavior::can_survive`,
33/// not `vegetation_can_survive`, so leaf blocks can override survival.
34pub fn survival_update_shape<B: BlockBehavior>(
35    block: &B,
36    state: BlockStateId,
37    world: &dyn ScheduledTickAccess,
38    pos: BlockPos,
39) -> BlockStateId {
40    if block.can_survive(state, world, pos) {
41        state
42    } else {
43        vanilla_blocks::AIR.default_state()
44    }
45}