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::Direction;
5use steel_registry::blocks::{
6    BlockRef, block_state_ext::BlockStateExt as _, properties::BlockStateProperties,
7};
8use steel_registry::vanilla_fluids;
9use steel_utils::{BlockPos, BlockStateId};
10
11use super::weathering_block::{WeatherState, WeatheringCopper};
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
21impl WaterloggedTransparentBlock {
22    /// Creates a new waterlogged transparent block behavior.
23    #[must_use]
24    pub const fn new(block: BlockRef) -> Self {
25        Self { block }
26    }
27}
28
29impl BlockBehavior for WaterloggedTransparentBlock {
30    fn get_state_for_placement(&self, context: &BlockPlaceContext<'_>) -> Option<BlockStateId> {
31        Some(self.block.default_state().set_value(
32            &BlockStateProperties::WATERLOGGED,
33            context.is_water_source(),
34        ))
35    }
36
37    fn update_shape(
38        &self,
39        state: BlockStateId,
40        world: &dyn ScheduledTickAccess,
41        pos: BlockPos,
42        _direction: Direction,
43        _neighbor_pos: BlockPos,
44        _neighbor_state: BlockStateId,
45    ) -> BlockStateId {
46        if state.get_value(&BlockStateProperties::WATERLOGGED) {
47            let delay = world.fluid_tick_delay(&vanilla_fluids::WATER);
48            let _ = world.schedule_fluid_tick_default(pos, &vanilla_fluids::WATER, delay);
49        }
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
103    #[test]
104    fn waterlogged_transparent_block_returns_falling_source_water() {
105        init_vanilla_registry();
106        let state = vanilla_blocks::WAXED_COPPER_GRATE
107            .default_state()
108            .set_value(&BlockStateProperties::WATERLOGGED, true);
109
110        let fluid = state.get_fluid_state();
111
112        assert_eq!(fluid.fluid_id, &vanilla_fluids::WATER);
113        assert!(fluid.is_source());
114        assert!(fluid.falling);
115    }
116}