steel_core/behavior/
mod.rs1mod block;
28pub mod blocks;
29mod context;
30pub mod fluid;
31mod item;
32pub(crate) mod item_utils;
33pub mod items;
34
35#[expect(warnings)]
36#[rustfmt::skip]
37#[path = "generated/blocks.rs"]
38pub mod block_behaviors;
39
40#[expect(warnings)]
41#[rustfmt::skip]
42#[path = "generated/candle_cakes.rs"]
43pub mod candle_cakes;
44
45#[allow(warnings)]
46#[rustfmt::skip]
47#[path = "generated/items.rs"]
48pub mod item_behaviors;
49
50#[expect(warnings)]
51#[rustfmt::skip]
52#[path = "generated/strippables.rs"]
53pub mod strippables;
54
55#[expect(warnings)]
56#[rustfmt::skip]
57#[path = "generated/waxables.rs"]
58pub mod waxables;
59
60#[expect(warnings)]
61#[rustfmt::skip]
62#[path = "generated/weathering.rs"]
63pub mod weathering;
64
65pub(crate) use block::pickup_waterlogged_block;
66pub use block::{
67 BlockBehavior, BlockBehaviorRegistry, BlockCollisionBoxes, BlockCollisionContext,
68 BlockEntityCreation, BlockLootContext, DefaultBlockBehavior, EntityFallDamage,
69 EntityFallOnContext, EntityFallOnFacts, EntityLandingContext, RailBehavior,
70};
71use block_behaviors::register_block_behaviors;
72pub use context::{
73 BlockHitResult, BlockPlaceContext, InteractionResult, InventoryAccess, PlacementOrientation,
74 PlacementSource, UseItemContext, UseOnContext,
75};
76pub use fluid::{FLUID_BEHAVIORS, FluidBehaviorRegistry};
77pub use item::{ItemBehavior, ItemBehaviorRegistry};
78use item_behaviors::register_item_behaviors;
79pub use items::{
80 BlockItem, BucketItem, DefaultItemBehavior, DoubleHighBlockItem, EnderEyeItem, HangingSignItem,
81 ShovelItem, SignItem, StandingAndWallBlockItem,
82};
83use std::ops::Deref;
84use std::sync::OnceLock;
85use steel_registry::blocks::BlockRef;
86use steel_registry::blocks::block_state_ext::BlockStateExt;
87use steel_registry::vanilla_fluids;
88use steel_utils::BlockStateId;
89
90use crate::entity::ai::path::PathComputationType;
91use crate::fluid::{FluidBehavior, LavaFluid, WaterFluid};
92
93pub struct BlockBehaviorLock(OnceLock<BlockBehaviorRegistry>);
95
96impl Deref for BlockBehaviorLock {
97 type Target = BlockBehaviorRegistry;
98
99 fn deref(&self) -> &Self::Target {
100 self.0.get().expect("Block behaviors not initialized")
101 }
102}
103
104pub struct ItemBehaviorLock(OnceLock<ItemBehaviorRegistry>);
106
107impl Deref for ItemBehaviorLock {
108 type Target = ItemBehaviorRegistry;
109
110 fn deref(&self) -> &Self::Target {
111 self.0.get().expect("Item behaviors not initialized")
112 }
113}
114
115pub trait BlockStateBehaviorExt {
120 fn is_liquid_container(&self) -> bool;
122
123 fn can_be_replaced_by_fluid(&self, fluid_block: BlockRef) -> bool;
125
126 fn can_be_replaced(&self, context: &BlockPlaceContext<'_>) -> bool;
128
129 fn is_pathfindable(&self, computation_type: PathComputationType) -> bool;
131}
132
133impl BlockStateBehaviorExt for BlockStateId {
134 fn is_liquid_container(&self) -> bool {
135 let block = self.get_block();
136 let behavior = BLOCK_BEHAVIORS.get_behavior(block);
137 behavior.is_liquid_container(*self)
138 }
139
140 fn can_be_replaced_by_fluid(&self, fluid_block: BlockRef) -> bool {
141 let block = self.get_block();
142 let behavior = BLOCK_BEHAVIORS.get_behavior(block);
143 behavior.can_be_replaced_by_fluid(*self, fluid_block)
144 }
145
146 fn can_be_replaced(&self, context: &BlockPlaceContext<'_>) -> bool {
147 let block = self.get_block();
148 let behavior = BLOCK_BEHAVIORS.get_behavior(block);
149 behavior.can_be_replaced(*self, context)
150 }
151
152 fn is_pathfindable(&self, computation_type: PathComputationType) -> bool {
153 let block = self.get_block();
154 let behavior = BLOCK_BEHAVIORS.get_behavior(block);
155 behavior.is_pathfindable(*self, computation_type)
156 }
157}
158
159pub static BLOCK_BEHAVIORS: BlockBehaviorLock = BlockBehaviorLock(OnceLock::new());
163
164pub static ITEM_BEHAVIORS: ItemBehaviorLock = ItemBehaviorLock(OnceLock::new());
168
169pub fn init_behaviors() {
173 BLOCK_BEHAVIORS.0.get_or_init(|| {
174 let mut block_behaviors = BlockBehaviorRegistry::new();
175 register_block_behaviors(&mut block_behaviors);
176 block_behaviors
177 });
178
179 FLUID_BEHAVIORS.0.get_or_init(|| {
180 let mut fluid_behaviors = FluidBehaviorRegistry::new();
181
182 let water_behavior: Box<dyn FluidBehavior> = Box::new(WaterFluid);
184 fluid_behaviors.set_behavior(&vanilla_fluids::WATER, water_behavior);
186 fluid_behaviors.set_behavior(&vanilla_fluids::FLOWING_WATER, Box::new(WaterFluid));
187
188 let lava_behavior: Box<dyn FluidBehavior> = Box::new(LavaFluid);
190 fluid_behaviors.set_behavior(&vanilla_fluids::LAVA, lava_behavior);
191 fluid_behaviors.set_behavior(&vanilla_fluids::FLOWING_LAVA, Box::new(LavaFluid));
192
193 fluid_behaviors
194 });
195
196 ITEM_BEHAVIORS.0.get_or_init(|| {
197 let mut item_behaviors = ItemBehaviorRegistry::new();
198 register_item_behaviors(&mut item_behaviors);
199 item_behaviors
200 });
201}