Skip to main content

steel_core/behavior/blocks/building/
waterlogged_transparent_block.rs

1use std::sync::Arc;
2
3use steel_macros::block_behavior;
4use steel_registry::blocks::properties::{BoolProperty, Direction};
5use steel_registry::blocks::{
6    BlockRef, block_state_ext::BlockStateExt as _, properties::BlockStateProperties,
7};
8use steel_utils::{BlockPos, BlockStateId};
9
10use super::weathering_block::{WeatherState, WeatheringCopper};
11use crate::behavior::block::schedule_water_tick_if_waterlogged;
12use crate::behavior::{BlockBehavior, BlockPlaceContext};
13use crate::world::{ScheduledTickAccess, World};
14
15/// Vanilla `WaterloggedTransparentBlock` behavior.
16#[block_behavior]
17pub struct WaterloggedTransparentBlock {
18    block: BlockRef,
19}
20
21const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
22
23impl WaterloggedTransparentBlock {
24    /// Creates a new waterlogged transparent block behavior.
25    #[must_use]
26    pub const fn new(block: BlockRef) -> Self {
27        Self { block }
28    }
29}
30
31impl BlockBehavior for WaterloggedTransparentBlock {
32    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
33        Some(
34            self.block
35                .default_state()
36                .set_value(WATERLOGGED, context.is_water_source()),
37        )
38    }
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        schedule_water_tick_if_waterlogged(state, world, pos);
50
51        state
52    }
53}
54
55/// Vanilla `WeatheringCopperGrateBlock` behavior.
56#[block_behavior]
57pub struct WeatheringCopperGrateBlock {
58    transparent: WaterloggedTransparentBlock,
59    #[json_arg(r#enum = "WeatherState", json = "weather_state")]
60    weathering: WeatheringCopper,
61}
62
63impl WeatheringCopperGrateBlock {
64    /// Creates a new weathering copper grate behavior.
65    #[must_use]
66    pub const fn new(block: BlockRef, weather_state: WeatherState) -> Self {
67        Self {
68            transparent: WaterloggedTransparentBlock::new(block),
69            weathering: WeatheringCopper::new(weather_state),
70        }
71    }
72}
73
74impl BlockBehavior for WeatheringCopperGrateBlock {
75    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
76        self.transparent.get_state_for_placement(context)
77    }
78
79    fn update_shape(
80        &self,
81        state: BlockStateId,
82        world: &dyn ScheduledTickAccess,
83        pos: BlockPos,
84        direction: Direction,
85        neighbor_pos: BlockPos,
86        neighbor_state: BlockStateId,
87    ) -> BlockStateId {
88        self.transparent
89            .update_shape(state, world, pos, direction, neighbor_pos, neighbor_state)
90    }
91
92    fn random_tick(&self, state: BlockStateId, world: &Arc<World>, pos: BlockPos) {
93        self.weathering.change_over_time(state, world, pos);
94    }
95}
96
97#[cfg(test)]
98mod tests {
99    use super::*;
100    use steel_registry::init_vanilla_registry;
101    use steel_registry::vanilla_blocks;
102    use steel_registry::vanilla_fluids;
103
104    #[test]
105    fn waterlogged_transparent_block_returns_falling_source_water() {
106        init_vanilla_registry();
107        let state = vanilla_blocks::WAXED_COPPER_GRATE
108            .default_state()
109            .set_value(WATERLOGGED, true);
110
111        let fluid = state.get_fluid_state();
112
113        assert_eq!(fluid.fluid_id, &vanilla_fluids::WATER);
114        assert!(fluid.is_source());
115        assert!(fluid.falling);
116    }
117}