steel_core/behavior/block/
waterlogging.rs1use super::{
2 Arc, BlockBehavior, BlockPos, BlockStateExt, BlockStateId, BlockStateProperties,
3 ConditionalBlockSetResult, FluidState, GameType, ItemStack, LevelAccessor, PickupResult,
4 Player, ScheduledTickAccess, UpdateFlags, World, sound_events, vanilla_blocks, vanilla_fluids,
5 vanilla_items,
6};
7
8#[must_use]
9pub(crate) fn drained_waterlogged_state(state: BlockStateId) -> Option<BlockStateId> {
10 (state.try_get_value(&BlockStateProperties::WATERLOGGED) == Some(true))
11 .then(|| state.set_value(&BlockStateProperties::WATERLOGGED, false))
12}
13
14pub(crate) fn pickup_waterlogged_block(
15 behavior: &dyn BlockBehavior,
16 world: &Arc<World>,
17 pos: BlockPos,
18 state: BlockStateId,
19 player: Option<&Player>,
20) -> Option<PickupResult> {
21 let new_state = drained_waterlogged_state(state)?;
22 if !can_pick_up_drained_waterlogged_state(state, player) {
23 return None;
24 }
25
26 if world.set_block_if_unchanged(pos, state, new_state, UpdateFlags::UPDATE_ALL)
27 != ConditionalBlockSetResult::Changed
28 {
29 return None;
30 }
31
32 if !behavior.can_survive(new_state, world, pos) {
33 world.destroy_block(pos, true);
34 }
35
36 Some(PickupResult {
37 filled_bucket: ItemStack::new(&vanilla_items::WATER_BUCKET),
38 sound: Some(&sound_events::ITEM_BUCKET_FILL),
39 })
40}
41
42pub(super) fn can_pick_up_drained_waterlogged_state(
43 state: BlockStateId,
44 player: Option<&Player>,
45) -> bool {
46 if state.get_block() != &vanilla_blocks::BARRIER {
49 return true;
50 }
51
52 player.is_some_and(|player| player.game_mode() == GameType::Creative)
53}
54
55pub(crate) fn schedule_placed_liquid_tick(
56 level: &dyn LevelAccessor,
57 pos: BlockPos,
58 fluid_state: FluidState,
59) {
60 let delay = level.fluid_tick_delay(fluid_state.fluid_id);
61 level.schedule_fluid_tick_default(pos, fluid_state.fluid_id, delay);
62}
63
64pub(crate) fn schedule_water_tick_if_waterlogged(
67 state: BlockStateId,
68 level: &dyn ScheduledTickAccess,
69 pos: BlockPos,
70) {
71 if state.try_get_value(&BlockStateProperties::WATERLOGGED) == Some(true) {
72 let delay = level.fluid_tick_delay(&vanilla_fluids::WATER);
73 level.schedule_fluid_tick_default(pos, &vanilla_fluids::WATER, delay);
74 }
75}
76
77pub(crate) fn place_simple_waterlogged_liquid(
78 level: &dyn LevelAccessor,
79 pos: BlockPos,
80 state: BlockStateId,
81 fluid_state: FluidState,
82) -> bool {
83 if state.try_get_value(&BlockStateProperties::WATERLOGGED) != Some(false)
84 || fluid_state.fluid_id != &vanilla_fluids::WATER
85 {
86 return false;
87 }
88
89 let new_state = state.set_value(&BlockStateProperties::WATERLOGGED, true);
90 level.set_block_state(pos, new_state, UpdateFlags::UPDATE_ALL);
91 schedule_placed_liquid_tick(level, pos, fluid_state);
92 true
93}
94
95pub(crate) fn simple_waterlogged_is_liquid_container(state: BlockStateId) -> bool {
96 state
97 .try_get_value(&BlockStateProperties::WATERLOGGED)
98 .is_some()
99}