steel_core/behavior/blocks/vegetation/
mod.rs1use std::sync::Arc;
4
5mod attached_stem_block;
6mod azalea_block;
7mod bamboo;
8mod bamboo_sapling;
9mod base_coral_fan_block;
10mod base_coral_plant_block;
11mod base_coral_wall_fan_block;
12mod beetroots;
13mod big_dripleaf_block;
14mod big_dripleaf_stem_block;
15pub mod bonemealable;
16mod bush_block;
17mod cactus_block;
18mod cactus_flower_block;
19mod carpet_block;
20mod carrot;
21mod carved_pumpkin_block;
22mod cave_vines_block;
23mod cave_vines_plant_block;
24mod chorus_flower_block;
25mod chorus_plant_block;
26mod cocoa_block;
27mod coral_block;
28mod coral_fan_block;
29mod coral_plant_block;
30mod coral_wall_fan_block;
31mod crop_block;
32mod dirt_path_block;
33mod double_plant_block;
34mod dry_vegetation_block;
35mod eyeblossom_block;
36mod farmland_block;
37mod firefly_bush_block;
38mod flower_bed_block;
39mod flower_block;
40mod glow_lichen_block;
41mod grass_block;
42mod growing_plant_block;
43mod growing_plant_body_block;
44mod growing_plant_head_block;
45mod hanging_moss_block;
46mod hanging_roots_block;
47mod huge_mushroom_block;
48mod kelp_block;
49mod kelp_plant_block;
50mod leaf_litter_block;
51mod leaves_block;
52mod lily_pad_block;
53mod mangrove_propagule_block;
54mod mangrove_roots_block;
55mod mossy_carpet_block;
56pub(crate) mod multiface_block;
57mod mushroom_block;
58mod mycelium_block;
59mod nether_fungus_block;
60mod nether_roots_block;
61mod nether_sprouts;
62mod nether_vines;
63mod nether_wart;
64mod pitcher_crop;
65mod pointed_dripstone_block;
66mod potato;
67mod pumpkin_block;
68mod rooted_dirt_block;
69mod sapling_block;
70mod sculk_vein_block;
71mod sea_pickle_block;
72mod seagrass_block;
73mod segmentable_block;
74mod shelf_mushroom_block;
75mod short_dry_grass_block;
76mod small_dripleaf_block;
77mod snowy_block;
78mod spore_blossom_block;
79mod spreading_grass_block;
80mod stem_block;
81mod sugar_cane;
82mod sweet_berry_bush;
83mod tall_dry_grass_block;
84mod tall_flower_block;
85mod tall_grass_block;
86mod tall_seagrass_block;
87mod torchflower;
88mod turtle_egg_block;
89mod twisting_vines_block;
90mod twisting_vines_plant_block;
91mod vegetation_block;
92mod vine_block;
93mod weeping_vines_block;
94mod weeping_vines_plant_block;
95mod wither_rose_block;
96
97pub use attached_stem_block::*;
98pub use azalea_block::*;
99pub use bamboo::*;
100pub use bamboo_sapling::*;
101pub use base_coral_fan_block::*;
102pub use base_coral_plant_block::*;
103pub use base_coral_wall_fan_block::*;
104pub use beetroots::*;
105pub use big_dripleaf_block::*;
106pub use big_dripleaf_stem_block::*;
107pub use bush_block::*;
108pub use cactus_block::*;
109pub use cactus_flower_block::*;
110pub use carpet_block::*;
111pub use carrot::*;
112pub use carved_pumpkin_block::*;
113pub use cave_vines_block::*;
114pub use cave_vines_plant_block::*;
115pub use chorus_flower_block::*;
116pub use chorus_plant_block::*;
117pub use cocoa_block::*;
118pub use coral_block::*;
119pub use coral_fan_block::*;
120pub use coral_plant_block::*;
121pub use coral_wall_fan_block::*;
122pub use crop_block::*;
123pub use dirt_path_block::*;
124pub use double_plant_block::*;
125pub use dry_vegetation_block::*;
126pub use eyeblossom_block::*;
127pub use farmland_block::*;
128pub use firefly_bush_block::*;
129pub use flower_bed_block::*;
130pub use flower_block::*;
131pub use glow_lichen_block::*;
132pub use grass_block::*;
133pub use growing_plant_head_block::*;
134pub use hanging_moss_block::*;
135pub use hanging_roots_block::*;
136pub use huge_mushroom_block::*;
137pub use kelp_block::*;
138pub use kelp_plant_block::*;
139pub use leaf_litter_block::*;
140pub use leaves_block::*;
141pub use lily_pad_block::*;
142pub use mangrove_propagule_block::*;
143pub use mangrove_roots_block::*;
144pub use mossy_carpet_block::*;
145pub use multiface_block::*;
146pub use mushroom_block::*;
147pub use mycelium_block::*;
148pub use nether_fungus_block::*;
149pub use nether_roots_block::*;
150pub use nether_sprouts::*;
151pub use nether_wart::*;
152pub use pitcher_crop::*;
153pub use pointed_dripstone_block::*;
154pub use potato::*;
155pub use pumpkin_block::*;
156pub use rooted_dirt_block::*;
157pub use sapling_block::*;
158pub use sculk_vein_block::*;
159pub use sea_pickle_block::*;
160pub use seagrass_block::*;
161pub use shelf_mushroom_block::*;
162pub use short_dry_grass_block::*;
163pub use small_dripleaf_block::*;
164pub use snowy_block::*;
165pub use spore_blossom_block::*;
166pub use spreading_grass_block::*;
167pub use stem_block::*;
168pub use sugar_cane::*;
169pub use sweet_berry_bush::*;
170pub use tall_dry_grass_block::*;
171pub use tall_flower_block::*;
172pub use tall_grass_block::*;
173pub use tall_seagrass_block::*;
174pub use torchflower::*;
175pub use turtle_egg_block::*;
176pub use twisting_vines_block::*;
177pub use twisting_vines_plant_block::*;
178pub use vegetation_block::*;
179pub use vine_block::*;
180pub use weeping_vines_block::*;
181pub use weeping_vines_plant_block::*;
182pub use wither_rose_block::*;
183
184use steel_registry::blocks::properties::Direction;
185use steel_registry::blocks::{BlockRef, block_state_ext::BlockStateExt};
186use steel_registry::fluid::FluidState;
187use steel_registry::vanilla_fluids;
188use steel_registry::{vanilla_blocks, vanilla_game_events};
189use steel_utils::{BlockPos, BlockStateId, types::UpdateFlags};
190
191use crate::behavior::block::BlockBehavior;
192use crate::behavior::block::push_entities_up;
193use crate::behavior::context::BlockPlaceContext;
194use crate::entity::Entity;
195use crate::world::game_event::GameEventContext;
196use crate::world::{LevelReader, World};
197
198pub(super) type BlockTagRef<'a> = &'a steel_utils::Identifier;
199
200pub(crate) fn turn_to_dirt(
202 state: BlockStateId,
203 world: &Arc<World>,
204 pos: BlockPos,
205 source_entity: Option<&dyn Entity>,
206) {
207 let dirt_state = push_entities_up(state, vanilla_blocks::DIRT.default_state(), world, pos);
208 if world.set_block(pos, dirt_state, UpdateFlags::UPDATE_ALL) {
209 world.game_event(
210 &vanilla_game_events::BLOCK_CHANGE,
211 pos,
212 &GameEventContext::new(source_entity, Some(dirt_state)),
213 );
214 }
215}
216
217pub(super) fn survives_on_tag(
218 world: &dyn LevelReader,
219 pos: BlockPos,
220 tag: BlockTagRef<'_>,
221) -> bool {
222 let below = world.get_block_state(pos.below());
223 below.get_block().has_tag(tag)
224}
225
226pub(super) fn default_surviving_state(
227 block: BlockRef,
228 behavior: &dyn BlockBehavior,
229 context: &BlockPlaceContext<'_>,
230) -> Option<BlockStateId> {
231 let state = block.default_state();
232 behavior
233 .can_survive(state, context.world, context.place_pos())
234 .then_some(state)
235}
236
237pub(super) fn water_source_fluid_state() -> FluidState {
238 FluidState::source(&vanilla_fluids::WATER)
239}
240
241pub fn get_top_connected_block(
243 world: &dyn LevelReader,
244 pos: BlockPos,
245 body_block: BlockRef,
246 growth_direction: Direction,
247 head_block: BlockRef,
248) -> Option<BlockPos> {
249 let mut forward_pos = pos;
250 let mut forward_state;
251
252 loop {
253 forward_pos = forward_pos.relative(growth_direction);
254 forward_state = world.get_block_state(forward_pos);
255
256 if forward_state.get_block() != body_block {
257 break;
258 }
259 }
260
261 if forward_state.get_block() == head_block {
262 Some(forward_pos)
263 } else {
264 None
265 }
266}
267
268#[cfg(test)]
269mod tests {
270 use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
271 use steel_registry::init_vanilla_registry;
272
273 use super::*;
274 use crate::behavior::init_behaviors;
275 use crate::test_support::TestLevel;
276
277 const NORTH: &BoolProperty = &BlockStateProperties::NORTH;
278 const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
279
280 #[test]
281 fn multiface_update_uses_supplied_neighbor_state_and_schedules_water_first() {
282 init_vanilla_registry();
283 init_behaviors();
284 let pos = BlockPos::new(0, 64, 0);
285 let state = vanilla_blocks::GLOW_LICHEN
286 .default_state()
287 .set_value(NORTH, true)
288 .set_value(WATERLOGGED, true);
289 let level =
290 TestLevel::default().with_block(pos.north(), vanilla_blocks::STONE.default_state());
291
292 let updated = MultifaceBlock::update_shape(
293 &MultifaceBlock::new(&vanilla_blocks::GLOW_LICHEN),
294 state,
295 &level,
296 pos,
297 Direction::North,
298 pos.north(),
299 vanilla_blocks::AIR.default_state(),
300 );
301
302 assert!(updated.is_air());
303 assert!(level.scheduled_water_tick());
304 }
305}