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