steel_core/worldgen/feature/features/
bamboo.rs1use steel_registry::vanilla_block_tags::BlockTag;
2
3use super::super::prelude::*;
4use super::super::runner::FeatureDecorationRunner;
5
6impl FeatureDecorationRunner {
7 pub(in crate::worldgen::feature) fn place_bamboo_feature(
8 region: &mut WorldGenRegion<'_>,
9 random: &mut WorldgenRandom,
10 config: &BambooConfiguration,
11 origin: BlockPos,
12 ) -> bool {
13 let mut placed = 0;
14 let mut bamboo_pos = origin;
15
16 if region.block_state(bamboo_pos).is_air() {
17 let bamboo = vanilla_blocks::BAMBOO.default_state();
18 let behavior = BLOCK_BEHAVIORS.get_behavior(&vanilla_blocks::BAMBOO);
19 if behavior.can_survive(bamboo, region, bamboo_pos) {
20 let height = random.next_i32_bounded(12) + 5;
21 if random.next_f32() < config.probability {
22 Self::place_bamboo_podzol_disc(region, random, origin);
23 }
24
25 let trunk = Self::bamboo_trunk_state();
26 for _ in 0..height {
27 if !region.block_state(bamboo_pos).is_air() {
28 break;
29 }
30 let _ = region.set_block_state(bamboo_pos, trunk, UpdateFlags::UPDATE_CLIENTS);
31 bamboo_pos = bamboo_pos.above();
32 }
33
34 if bamboo_pos.y() - origin.y() >= 3 {
35 let _ = region.set_block_state(
36 bamboo_pos,
37 Self::bamboo_final_large_state(),
38 UpdateFlags::UPDATE_CLIENTS,
39 );
40 bamboo_pos = bamboo_pos.below();
41 let _ = region.set_block_state(
42 bamboo_pos,
43 Self::bamboo_top_large_state(),
44 UpdateFlags::UPDATE_CLIENTS,
45 );
46 bamboo_pos = bamboo_pos.below();
47 let _ = region.set_block_state(
48 bamboo_pos,
49 Self::bamboo_top_small_state(),
50 UpdateFlags::UPDATE_CLIENTS,
51 );
52 }
53 }
54
55 placed += 1;
56 }
57
58 placed > 0
59 }
60
61 fn place_bamboo_podzol_disc(
62 region: &mut WorldGenRegion<'_>,
63 random: &mut WorldgenRandom,
64 origin: BlockPos,
65 ) {
66 let radius = random.next_i32_bounded(4) + 1;
67 for x in origin.x() - radius..=origin.x() + radius {
68 for z in origin.z() - radius..=origin.z() + radius {
69 let dx = x - origin.x();
70 let dz = z - origin.z();
71 if dx * dx + dz * dz > radius * radius {
72 continue;
73 }
74
75 let y = region.height_at(HeightmapType::WorldSurface, x, z) - 1;
76 let pos = BlockPos::new(x, y, z);
77 let state = region.block_state(pos);
78 if state
79 .get_block()
80 .has_tag(&BlockTag::BENEATH_BAMBOO_PODZOL_REPLACEABLE)
81 {
82 let _ = region.set_block_state(
83 pos,
84 vanilla_blocks::PODZOL.default_state(),
85 UpdateFlags::UPDATE_CLIENTS,
86 );
87 }
88 }
89 }
90 }
91
92 fn bamboo_trunk_state() -> BlockStateId {
93 vanilla_blocks::BAMBOO
94 .default_state()
95 .set_value(&BlockStateProperties::AGE_1, 1)
96 .set_value(&BlockStateProperties::BAMBOO_LEAVES, BambooLeaves::None)
97 .set_value(&BlockStateProperties::STAGE, 0)
98 }
99
100 fn bamboo_final_large_state() -> BlockStateId {
101 Self::bamboo_trunk_state()
102 .set_value(&BlockStateProperties::BAMBOO_LEAVES, BambooLeaves::Large)
103 .set_value(&BlockStateProperties::STAGE, 1)
104 }
105
106 fn bamboo_top_large_state() -> BlockStateId {
107 Self::bamboo_trunk_state()
108 .set_value(&BlockStateProperties::BAMBOO_LEAVES, BambooLeaves::Large)
109 }
110
111 fn bamboo_top_small_state() -> BlockStateId {
112 Self::bamboo_trunk_state()
113 .set_value(&BlockStateProperties::BAMBOO_LEAVES, BambooLeaves::Small)
114 }
115}