steel_core/behavior/blocks/building/
waterlogged_transparent_block.rs1use 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#[block_behavior]
17pub struct WaterloggedTransparentBlock {
18 block: BlockRef,
19}
20
21impl WaterloggedTransparentBlock {
22 #[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#[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 #[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}