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_utils::{BlockPos, BlockStateId};
12
13pub trait FluidBehavior: Send + Sync {
16 fn fluid_type(&self) -> FluidRef;
18
19 fn is_same(&self, other: FluidRef) -> bool {
25 self.fluid_type() == other
26 }
27
28 fn tick_delay(&self, world: &Arc<World>) -> i32;
30 fn drop_off(&self, world: &Arc<World>) -> u8;
33 fn slope_find_distance(&self, world: &Arc<World>) -> u8;
36
37 fn tick(
42 &self,
43 world: &Arc<World>,
44 pos: BlockPos,
45 block_state: BlockStateId,
46 fluid_state: FluidState,
47 );
48 fn spread(
50 &self,
51 world: &Arc<World>,
52 pos: BlockPos,
53 block_state: BlockStateId,
54 fluid_state: FluidState,
55 );
56
57 fn can_be_replaced_with(
60 &self,
61 fluid_state: FluidState,
62 world: &Arc<World>,
63 pos: BlockPos,
64 other_fluid: FluidRef,
65 direction: Direction,
66 ) -> bool;
67
68 fn before_destroying_block(
70 &self,
71 _world: &Arc<World>,
72 _pos: BlockPos,
73 _replaced: BlockStateId,
74 ) {
75 }
77
78 fn can_convert_to_source(&self, _world: &Arc<World>) -> bool {
80 false
81 }
82
83 #[expect(
85 unused_variables,
86 reason = "default trait implementation ignores all params"
87 )]
88 fn entity_inside(
89 &self,
90 world: &Arc<World>,
91 pos: BlockPos,
92 entity: &dyn Entity,
93 effect_collector: &mut InsideBlockEffectCollector,
94 ) {
95 }
96
97 fn explosion_resistance(&self) -> f32 {
99 0.0
100 }
101
102 #[expect(
105 unused_variables,
106 reason = "default trait implementation ignores all params"
107 )]
108 fn random_tick(&self, world: &Arc<World>, pos: BlockPos) {}
109
110 #[expect(
113 unused_variables,
114 reason = "default implementation only uses world and tick_delay; old/new states are available for overrides"
115 )]
116 fn get_spread_delay(
117 &self,
118 world: &Arc<World>,
119 _pos: BlockPos,
120 old_state: FluidState,
121 new_state: FluidState,
122 ) -> i32 {
123 self.tick_delay(world)
124 }
125
126 #[expect(
128 unused_variables,
129 reason = "default implementation is used by empty/non-flowing fluids"
130 )]
131 fn get_flow(&self, world: &Arc<World>, pos: BlockPos, fluid_state: FluidState) -> DVec3 {
132 DVec3::ZERO
133 }
134}