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