Skip to main content

steel_core/behavior/blocks/vegetation/
torchflower.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::{
5    blocks::{
6        BlockRef,
7        block_state_ext::BlockStateExt,
8        properties::{BlockStateProperties, IntProperty},
9    },
10    item_stack::ItemStack,
11    vanilla_blocks, vanilla_items,
12};
13use steel_utils::BlockStateId;
14
15use crate::{
16    behavior::blocks::vegetation::{
17        bonemealable::{Bonemealable, CropBonemealExt},
18        crop_block::CropLike,
19    },
20    world::{LevelReader, World},
21};
22
23/// Behavior for the Torchflower Block
24#[block_behavior]
25pub struct TorchflowerCropBlock {
26    block: BlockRef,
27}
28
29const AGE: &IntProperty = &BlockStateProperties::AGE_1;
30
31impl TorchflowerCropBlock {
32    /// Creates a new crop block behavior with a custom age property.
33    #[must_use]
34    pub const fn new(block: BlockRef) -> Self {
35        Self { block }
36    }
37}
38
39impl CropLike for TorchflowerCropBlock {
40    fn block(&self) -> BlockRef {
41        self.block
42    }
43
44    fn age_property(&self) -> &IntProperty {
45        AGE
46    }
47
48    fn max_age(&self) -> u8 {
49        2
50    }
51
52    fn get_state_for_age(&self, age: u8) -> BlockStateId {
53        if age == 2 {
54            vanilla_blocks::TORCHFLOWER.default_state()
55        } else {
56            self.block
57                .default_state()
58                .set_value(self.age_property(), age)
59        }
60    }
61
62    fn clone_item_stack(&self) -> ItemStack {
63        ItemStack::new(&vanilla_items::TORCHFLOWER_SEEDS)
64    }
65
66    fn should_random_tick(&self) -> bool {
67        rand::random_range(0..3) != 0
68    }
69}
70
71impl Bonemealable for TorchflowerCropBlock {
72    fn get_bonemeal_age_increase(&self, _world: &Arc<World>, _rng: &mut dyn rand::Rng) -> u8 {
73        1
74    }
75
76    fn is_valid_bonemeal_target(
77        &self,
78        state: BlockStateId,
79        _world: &dyn LevelReader,
80        _pos: steel_utils::BlockPos,
81    ) -> bool {
82        !self.is_max_age(state)
83    }
84
85    fn perform_bonemeal(
86        &self,
87        state: BlockStateId,
88        world: &Arc<World>,
89        rng: &mut dyn rand::Rng,
90        pos: steel_utils::BlockPos,
91    ) {
92        self.default_perform_bonemeal(state, world, rng, pos);
93    }
94}
95
96#[cfg(test)]
97mod tests {
98    use steel_registry::{init_vanilla_registry, vanilla_blocks};
99
100    use super::*;
101
102    #[test]
103    fn torchflower_age_two_becomes_flower_block() {
104        init_vanilla_registry();
105        let behavior = TorchflowerCropBlock::new(&vanilla_blocks::TORCHFLOWER_CROP);
106
107        let age_one = behavior.get_state_for_age(1);
108        assert_eq!(age_one.get_block(), &vanilla_blocks::TORCHFLOWER_CROP);
109        assert_eq!(age_one.get_value(AGE), 1);
110
111        let mature = behavior.get_state_for_age(2);
112        assert_eq!(mature.get_block(), &vanilla_blocks::TORCHFLOWER);
113    }
114}