Skip to main content

steel_core/behavior/blocks/building/
composter_block.rs

1//! Comparator-visible composter state.
2//!
3//! Composting interactions and hopper automation are independent mechanics;
4//! comparators read the block-state fill level directly in vanilla.
5
6use steel_macros::block_behavior;
7use steel_registry::blocks::{
8    BlockRef,
9    block_state_ext::BlockStateExt as _,
10    properties::{BlockStateProperties, Direction, IntProperty},
11};
12use steel_utils::{BlockPos, BlockStateId};
13
14use crate::{
15    behavior::{BlockBehavior, BlockPlaceContext},
16    entity::ai::path::PathComputationType,
17    world::LevelReader,
18};
19
20/// Vanilla composter behavior required by analog signal readers.
21#[block_behavior]
22pub struct ComposterBlock {
23    block: BlockRef,
24}
25
26const LEVEL_COMPOSTER: &IntProperty = &BlockStateProperties::LEVEL_COMPOSTER;
27
28impl ComposterBlock {
29    /// Creates composter behavior.
30    #[must_use]
31    pub const fn new(block: BlockRef) -> Self {
32        Self { block }
33    }
34}
35
36impl BlockBehavior for ComposterBlock {
37    fn get_state_for_placement(&self, _context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
38        Some(self.block.default_state())
39    }
40
41    fn has_analog_output_signal(&self, _state: BlockStateId) -> bool {
42        true
43    }
44
45    fn get_analog_output_signal(
46        &self,
47        state: BlockStateId,
48        _world: &dyn LevelReader,
49        _pos: BlockPos,
50        _direction: Direction,
51    ) -> i32 {
52        i32::from(state.get_value(LEVEL_COMPOSTER))
53    }
54
55    fn is_pathfindable(
56        &self,
57        _state: BlockStateId,
58        _computation_type: PathComputationType,
59    ) -> bool {
60        false
61    }
62}
63
64#[cfg(test)]
65mod tests {
66    use steel_registry::{init_vanilla_registry, vanilla_blocks};
67
68    use super::*;
69    use crate::{
70        behavior::{BLOCK_BEHAVIORS, init_behaviors},
71        test_support::TestLevel,
72    };
73
74    #[test]
75    fn registered_composter_outputs_its_full_state_level() {
76        init_vanilla_registry();
77        init_behaviors();
78        let state = vanilla_blocks::COMPOSTER
79            .default_state()
80            .set_value(LEVEL_COMPOSTER, LEVEL_COMPOSTER.max);
81        let behavior = BLOCK_BEHAVIORS.get_behavior(state.get_block());
82
83        assert!(behavior.has_analog_output_signal(state));
84        assert_eq!(
85            behavior.get_analog_output_signal(
86                state,
87                &TestLevel::default(),
88                BlockPos::ZERO,
89                Direction::North,
90            ),
91            i32::from(LEVEL_COMPOSTER.max),
92        );
93    }
94}