Skip to main content

steel_core/behavior/blocks/vegetation/
firefly_bush_block.rs

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