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 short_dry_grass_block;
75mod small_dripleaf_block;
76mod snowy_block;
77mod spore_blossom_block;
78mod spreading_grass_block;
79mod stem_block;
80mod sugar_cane;
81mod sweet_berry_bush;
82mod tall_dry_grass_block;
83mod tall_flower_block;
84mod tall_grass_block;
85mod tall_seagrass_block;
86mod torchflower;
87mod turtle_egg_block;
88mod twisting_vines_block;
89mod twisting_vines_plant_block;
90mod vegetation_block;
91mod vine_block;
92mod weeping_vines_block;
93mod weeping_vines_plant_block;
94mod wither_rose_block;
95
96pub use attached_stem_block::AttachedStemBlock;
97pub use azalea_block::AzaleaBlock;
98pub use bamboo::BambooStalkBlock;
99pub use bamboo_sapling::BambooSaplingBlock;
100pub use base_coral_fan_block::BaseCoralFanBlock;
101pub use base_coral_plant_block::BaseCoralPlantBlock;
102pub use base_coral_wall_fan_block::BaseCoralWallFanBlock;
103pub use beetroots::BeetrootBlock;
104pub use big_dripleaf_block::BigDripleafBlock;
105pub use big_dripleaf_stem_block::BigDripleafStemBlock;
106pub use bush_block::BushBlock;
107pub use cactus_block::CactusBlock;
108pub use cactus_flower_block::CactusFlowerBlock;
109pub use carpet_block::{CarpetBlock, WoolCarpetBlock};
110pub use carrot::CarrotBlock;
111pub use carved_pumpkin_block::CarvedPumpkinBlock;
112pub use cave_vines_block::CaveVinesBlock;
113pub use cave_vines_plant_block::CaveVinesPlantBlock;
114pub use chorus_flower_block::ChorusFlowerBlock;
115pub use chorus_plant_block::ChorusPlantBlock;
116pub use cocoa_block::CocoaBlock;
117pub use coral_block::CoralBlock;
118pub use coral_fan_block::CoralFanBlock;
119pub use coral_plant_block::CoralPlantBlock;
120pub use coral_wall_fan_block::CoralWallFanBlock;
121pub use crop_block::CropBlock;
122pub use dirt_path_block::DirtPathBlock;
123pub use double_plant_block::DoublePlantBlock;
124pub use dry_vegetation_block::DryVegetationBlock;
125pub use eyeblossom_block::{EyeblossomBlock, EyeblossomType};
126pub use farmland_block::FarmlandBlock;
127pub use firefly_bush_block::FireflyBushBlock;
128pub use flower_bed_block::FlowerBedBlock;
129pub use flower_block::FlowerBlock;
130pub use glow_lichen_block::GlowLichenBlock;
131pub use grass_block::GrassBlock;
132pub use growing_plant_head_block::{GrowingPlantHeadBehavior, MAX_AGE};
133pub use hanging_moss_block::HangingMossBlock;
134pub use hanging_roots_block::HangingRootsBlock;
135pub use huge_mushroom_block::HugeMushroomBlock;
136pub use kelp_block::KelpBlock;
137pub use kelp_plant_block::KelpPlantBlock;
138pub use leaf_litter_block::LeafLitterBlock;
139pub use leaves_block::{
140 MangroveLeavesBlock, TintedParticleLeavesBlock, UntintedParticleLeavesBlock,
141};
142pub use lily_pad_block::LilyPadBlock;
143pub use mangrove_propagule_block::MangrovePropaguleBlock;
144pub use mangrove_roots_block::MangroveRootsBlock;
145pub use mossy_carpet_block::MossyCarpetBlock;
146pub use multiface_block::MultifaceBlock;
147pub(crate) use multiface_block::{MultifaceSpreadPos, MultifaceSpreadType, multiface_spread_pos};
148pub use mushroom_block::MushroomBlock;
149pub use mycelium_block::MyceliumBlock;
150pub use nether_fungus_block::NetherFungusBlock;
151pub use nether_roots_block::NetherRootsBlock;
152pub use nether_sprouts::NetherSproutsBlock;
153pub use nether_wart::NetherWartBlock;
154pub use pitcher_crop::PitcherCropBlock;
155pub use pointed_dripstone_block::{
156 PointedDripstoneBlock, SulfurSpikeBlock, find_stalactite_tip_above_cauldron,
157 get_cauldron_fill_fluid_type,
158};
159pub use potato::PotatoBlock;
160pub use pumpkin_block::PumpkinBlock;
161pub use rooted_dirt_block::RootedDirtBlock;
162pub use sapling_block::SaplingBlock;
163pub use sculk_vein_block::SculkVeinBlock;
164pub use sea_pickle_block::SeaPickleBlock;
165pub use seagrass_block::SeagrassBlock;
166pub use short_dry_grass_block::ShortDryGrassBlock;
167pub use small_dripleaf_block::SmallDripleafBlock;
168pub use snowy_block::SnowyBlock;
169pub use spore_blossom_block::SporeBlossomBlock;
170pub use spreading_grass_block::SpreadingGrassBlock;
171pub use stem_block::StemBlock;
172pub use sugar_cane::SugarCaneBlock;
173pub use sweet_berry_bush::SweetBerryBushBlock;
174pub use tall_dry_grass_block::TallDryGrassBlock;
175pub use tall_flower_block::TallFlowerBlock;
176pub use tall_grass_block::TallGrassBlock;
177pub use tall_seagrass_block::TallSeagrassBlock;
178pub use torchflower::TorchflowerCropBlock;
179pub use turtle_egg_block::TurtleEggBlock;
180pub use twisting_vines_block::TwistingVinesBlock;
181pub use twisting_vines_plant_block::TwistingVinesPlantBlock;
182pub use vegetation_block::Vegetation;
183pub use vine_block::VineBlock;
184pub use weeping_vines_block::WeepingVinesBlock;
185pub use weeping_vines_plant_block::WeepingVinesPlantBlock;
186pub use wither_rose_block::WitherRoseBlock;
187
188use steel_registry::blocks::properties::Direction;
189use steel_registry::blocks::{BlockRef, block_state_ext::BlockStateExt};
190use steel_registry::fluid::FluidState;
191use steel_registry::vanilla_fluids;
192use steel_registry::{vanilla_blocks, vanilla_game_events};
193use steel_utils::{BlockPos, BlockStateId, types::UpdateFlags};
194
195use crate::behavior::block::BlockBehavior;
196use crate::behavior::block::push_entities_up;
197use crate::behavior::context::BlockPlaceContext;
198use crate::entity::Entity;
199use crate::world::game_event::GameEventContext;
200use crate::world::{LevelReader, World};
201
202pub(super) type BlockTagRef<'a> = &'a steel_utils::Identifier;
203
204pub(crate) fn turn_to_dirt(
206 state: BlockStateId,
207 world: &Arc<World>,
208 pos: BlockPos,
209 source_entity: Option<&dyn Entity>,
210) {
211 let dirt_state = push_entities_up(state, vanilla_blocks::DIRT.default_state(), world, pos);
212 if world.set_block(pos, dirt_state, UpdateFlags::UPDATE_ALL) {
213 world.game_event(
214 &vanilla_game_events::BLOCK_CHANGE,
215 pos,
216 &GameEventContext::new(source_entity, Some(dirt_state)),
217 );
218 }
219}
220
221pub(super) fn survives_on_tag(
222 world: &dyn LevelReader,
223 pos: BlockPos,
224 tag: BlockTagRef<'_>,
225) -> bool {
226 let below = world.get_block_state(pos.below());
227 below.get_block().has_tag(tag)
228}
229
230pub(super) fn default_surviving_state(
231 block: BlockRef,
232 behavior: &dyn BlockBehavior,
233 context: &BlockPlaceContext<'_>,
234) -> Option<BlockStateId> {
235 let state = block.default_state();
236 behavior
237 .can_survive(state, context.world, context.place_pos())
238 .then_some(state)
239}
240
241pub(super) fn water_source_fluid_state() -> FluidState {
242 FluidState::source(&vanilla_fluids::WATER)
243}
244
245pub fn get_top_connected_block(
247 world: &dyn LevelReader,
248 pos: BlockPos,
249 body_block: BlockRef,
250 growth_direction: Direction,
251 head_block: BlockRef,
252) -> Option<BlockPos> {
253 let mut forward_pos = pos;
254 let mut forward_state;
255
256 loop {
257 forward_pos = forward_pos.relative(growth_direction);
258 forward_state = world.get_block_state(forward_pos);
259
260 if forward_state.get_block() != body_block {
261 break;
262 }
263 }
264
265 if forward_state.get_block() == head_block {
266 Some(forward_pos)
267 } else {
268 None
269 }
270}
271
272#[cfg(test)]
273mod tests {
274 use steel_registry::blocks::properties::{BlockStateProperties, BoolProperty};
275 use steel_registry::init_vanilla_registry;
276
277 use super::*;
278 use crate::behavior::init_behaviors;
279 use crate::test_support::TestLevel;
280
281 const NORTH: &BoolProperty = &BlockStateProperties::NORTH;
282 const WATERLOGGED: &BoolProperty = &BlockStateProperties::WATERLOGGED;
283
284 #[test]
285 fn multiface_update_uses_supplied_neighbor_state_and_schedules_water_first() {
286 init_vanilla_registry();
287 init_behaviors();
288 let pos = BlockPos::new(0, 64, 0);
289 let state = vanilla_blocks::GLOW_LICHEN
290 .default_state()
291 .set_value(NORTH, true)
292 .set_value(WATERLOGGED, true);
293 let level =
294 TestLevel::default().with_block(pos.north(), vanilla_blocks::STONE.default_state());
295
296 let updated = MultifaceBlock::update_shape(
297 &MultifaceBlock::new(&vanilla_blocks::GLOW_LICHEN),
298 state,
299 &level,
300 pos,
301 Direction::North,
302 pos.north(),
303 vanilla_blocks::AIR.default_state(),
304 );
305
306 assert!(updated.is_air());
307 assert!(level.scheduled_water_tick());
308 }
309}