steel_core/behavior/blocks/vegetation/
spreading_grass_block.rs1use super::snowy_block::is_snowy_setting;
2use crate::behavior::BlockRef;
3use crate::chunk::light::{MAX_LIGHT_LEVEL, get_light_block_into};
4use crate::world::{LevelReader, World};
5use std::sync::Arc;
6use steel_registry::blocks::properties::BlockStateProperties;
7use steel_registry::entity_data::Direction;
8use steel_registry::vanilla_blocks;
9use steel_registry::{blocks::block_state_ext::BlockStateExt, vanilla_fluid_tags::FluidTag};
10use steel_utils::types::UpdateFlags;
11use steel_utils::{BlockPos, BlockStateId};
12
13pub struct SpreadingGrassBlock {}
15
16impl SpreadingGrassBlock {
17 fn can_stay_alive(state: BlockStateId, level: &Arc<World>, pos: BlockPos) -> bool {
18 let above = pos.above();
19 let above_state: BlockStateId = level.get_block_state(above);
20 if above_state.get_block() == &vanilla_blocks::SNOW
21 && above_state.get_value(&BlockStateProperties::LAYERS) == 1
22 {
23 return true;
24 }
25 if above_state.get_fluid_state().is_full() {
26 return false;
27 }
28
29 let light_dampening_top_face = get_light_block_into(
30 state,
31 above_state,
32 Direction::Up,
33 above_state.get_light_dampening(),
34 );
35 light_dampening_top_face < MAX_LIGHT_LEVEL
36 }
37 fn can_propagate(state: BlockStateId, level: &Arc<World>, pos: BlockPos) -> bool {
38 Self::can_stay_alive(state, level, pos)
39 && !level
40 .get_block_state(pos.above())
41 .get_fluid_state()
42 .fluid_id
43 .has_tag(&FluidTag::WATER)
44 }
45
46 pub fn random_tick(
49 own: BlockRef,
50 base: BlockRef,
51 state: BlockStateId,
52 world: &Arc<World>,
53 pos: BlockPos,
54 ) {
55 if !Self::can_stay_alive(state, world, pos) {
56 world.set_block(pos, base.default_state(), UpdateFlags::UPDATE_ALL);
57 } else if world.max_local_raw_brightness(pos.above(), world.sky_darkening()) >= 9 {
58 let default_block_state = own.default_state();
59
60 for _ in 0..4 {
61 let test_pos = pos.offset(
62 rand::random_range(-1..2),
63 rand::random_range(-3..2),
64 rand::random_range(-1..2),
65 );
66 if world.get_block_state(test_pos).get_block() == base
67 && Self::can_propagate(default_block_state, world, test_pos)
68 {
69 world.set_block(
70 test_pos,
71 default_block_state.set_value(
72 &BlockStateProperties::SNOWY,
73 is_snowy_setting(world.get_block_state(test_pos.above())),
74 ),
75 UpdateFlags::UPDATE_ALL,
76 );
77 }
78 }
79 }
80 }
81}