Skip to main content

steel_core/behavior/blocks/vegetation/
eyeblossom_block.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::vanilla_block_tags::BlockTag;
5use steel_utils::{BlockPos, BlockStateId};
6
7use crate::behavior::block::BlockBehavior;
8use crate::behavior::context::BlockPlaceContext;
9use crate::world::{LevelReader, World};
10
11use super::{BlockRef, default_surviving_state, survives_on_tag};
12
13#[derive(Clone, Copy)]
14/// Vanilla open/closed eyeblossom type from `classes.json`.
15pub enum EyeblossomType {
16    /// Emits open-eyeblossom effects and transforms closed at daytime.
17    Open,
18    /// Emits closed-eyeblossom effects and transforms open at nighttime.
19    Closed,
20}
21
22/// Vanilla `EyeblossomBlock` survival and ticking shape.
23// TODO: Implement eyeblossom day/night transforms, sounds, particles, and bee effects
24// once Steel has environment attributes and particle dispatch.
25#[block_behavior]
26pub struct EyeblossomBlock {
27    block: BlockRef,
28    #[json_arg(r#enum = "EyeblossomType", json = "type")]
29    eyeblossom_type: EyeblossomType,
30}
31
32impl EyeblossomBlock {
33    /// Creates a new eyeblossom behavior.
34    #[must_use]
35    pub const fn new(block: BlockRef, eyeblossom_type: EyeblossomType) -> Self {
36        Self {
37            block,
38            eyeblossom_type,
39        }
40    }
41}
42
43impl BlockBehavior for EyeblossomBlock {
44    fn can_survive(&self, _state: BlockStateId, world: &dyn LevelReader, pos: BlockPos) -> bool {
45        survives_on_tag(world, pos, &BlockTag::SUPPORTS_VEGETATION)
46    }
47
48    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
49        default_surviving_state(self.block, self, context)
50    }
51
52    fn random_tick(&self, _state: BlockStateId, _world: &Arc<World>, _pos: BlockPos) {
53        let _ = self.eyeblossom_type;
54    }
55
56    fn tick(&self, _state: BlockStateId, _world: &Arc<World>, _pos: BlockPos) {
57        let _ = self.eyeblossom_type;
58    }
59}
60
61#[cfg(test)]
62mod tests {
63    use steel_registry::{init_vanilla_registry, vanilla_blocks};
64    use steel_utils::BlockPos;
65
66    use crate::test_support::TestLevel;
67
68    use super::*;
69
70    fn level_with_support(support: BlockRef) -> TestLevel {
71        TestLevel::default().with_block(BlockPos::new(0, 63, 0), support.default_state())
72    }
73
74    #[test]
75    fn eyeblossom_requires_vegetation_support() {
76        init_vanilla_registry();
77        let behavior =
78            EyeblossomBlock::new(&vanilla_blocks::CLOSED_EYEBLOSSOM, EyeblossomType::Closed);
79        let pos = BlockPos::new(0, 64, 0);
80        let state = vanilla_blocks::CLOSED_EYEBLOSSOM.default_state();
81
82        assert!(behavior.can_survive(state, &level_with_support(&vanilla_blocks::DIRT), pos));
83        assert!(!behavior.can_survive(state, &level_with_support(&vanilla_blocks::AIR), pos));
84    }
85}