steel_core/fluid/
fluid_behavior.rs1use std::sync::Arc;
4
5use glam::DVec3;
6
7use crate::entity::{Entity, InsideBlockEffectCollector};
8use crate::world::World;
9use steel_registry::blocks::properties::Direction;
10use steel_registry::fluid::{FluidRef, FluidState};
11use steel_registry::items::ItemRef;
12use steel_registry::sound_event::SoundEventRef;
13use steel_utils::{BlockPos, BlockStateId};
14
15pub trait FluidBehavior: Send + Sync {
18 fn fluid_type(&self) -> FluidRef;
20
21 fn create_legacy_block(&self, fluid_state: FluidState) -> BlockStateId;
23
24 fn bucket(&self) -> ItemRef;
26
27 fn is_same(&self, other: FluidRef) -> bool {
33 self.fluid_type() == other
34 }
35
36 fn tick_delay(&self, world: &Arc<World>) -> i32;
38 fn drop_off(&self, world: &Arc<World>) -> u8;
41 fn slope_find_distance(&self, world: &Arc<World>) -> u8;
44
45 fn tick(
49 &self,
50 world: &Arc<World>,
51 pos: BlockPos,
52 block_state: BlockStateId,
53 fluid_state: FluidState,
54 );
55 fn spread(
57 &self,
58 world: &Arc<World>,
59 pos: BlockPos,
60 block_state: BlockStateId,
61 fluid_state: FluidState,
62 );
63
64 fn can_be_replaced_with(
67 &self,
68 fluid_state: FluidState,
69 world: &Arc<World>,
70 pos: BlockPos,
71 other_fluid: FluidRef,
72 direction: Direction,
73 ) -> bool;
74
75 fn before_destroying_block(
77 &self,
78 _world: &Arc<World>,
79 _pos: BlockPos,
80 _replaced: BlockStateId,
81 ) {
82 }
84
85 fn can_convert_to_source(&self, _world: &Arc<World>) -> bool {
87 false
88 }
89
90 #[expect(
92 unused_variables,
93 reason = "default trait implementation ignores all params"
94 )]
95 fn entity_inside(
96 &self,
97 world: &Arc<World>,
98 pos: BlockPos,
99 entity: &dyn Entity,
100 effect_collector: &mut InsideBlockEffectCollector,
101 ) {
102 }
103
104 fn explosion_resistance(&self) -> f32 {
106 0.0
107 }
108
109 fn pickup_sound(&self) -> Option<SoundEventRef> {
111 None
112 }
113
114 #[expect(
117 unused_variables,
118 reason = "default trait implementation ignores all params"
119 )]
120 fn random_tick(&self, world: &Arc<World>, pos: BlockPos) {}
121
122 #[expect(
125 unused_variables,
126 reason = "default implementation only uses world and tick_delay; old/new states are available for overrides"
127 )]
128 fn get_spread_delay(
129 &self,
130 world: &Arc<World>,
131 _pos: BlockPos,
132 old_state: FluidState,
133 new_state: FluidState,
134 ) -> i32 {
135 self.tick_delay(world)
136 }
137
138 #[expect(
140 unused_variables,
141 reason = "default implementation is used by empty/non-flowing fluids"
142 )]
143 fn get_flow(&self, world: &Arc<World>, pos: BlockPos, fluid_state: FluidState) -> DVec3 {
144 DVec3::ZERO
145 }
146}