steel_core/worldgen/feature/features/
twisting_vines.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_twisting_vines_feature(
6 region: &mut WorldGenRegion<'_>,
7 random: &mut WorldgenRandom,
8 config: &TwistingVinesConfiguration,
9 origin: BlockPos,
10 ) -> bool {
11 if Self::twisting_vines_invalid_placement_location(region, origin) {
12 return false;
13 }
14
15 for _ in 0..config.spread_width * config.spread_width {
16 let mut place_pos = origin.offset(
17 random.next_i32_between(-config.spread_width, config.spread_width),
18 random.next_i32_between(-config.spread_height, config.spread_height),
19 random.next_i32_between(-config.spread_width, config.spread_width),
20 );
21
22 if Self::find_first_air_block_above_ground(region, &mut place_pos)
23 && !Self::twisting_vines_invalid_placement_location(region, place_pos)
24 {
25 let mut vine_height = random.next_i32_between(1, config.max_height);
26 if random.next_i32_bounded(6) == 0 {
27 vine_height *= 2;
28 }
29
30 if random.next_i32_bounded(5) == 0 {
31 vine_height = 1;
32 }
33
34 Self::place_twisting_vines_column(region, random, place_pos, vine_height, 17, 25);
35 }
36 }
37
38 true
39 }
40
41 fn find_first_air_block_above_ground(
42 region: &WorldGenRegion<'_>,
43 place_pos: &mut BlockPos,
44 ) -> bool {
45 loop {
46 *place_pos = place_pos.below();
47 if region.is_outside_build_height(place_pos.y()) {
48 return false;
49 }
50
51 if !region.block_state(*place_pos).is_air() {
52 *place_pos = place_pos.above();
53 return true;
54 }
55 }
56 }
57
58 fn place_twisting_vines_column(
59 region: &mut WorldGenRegion<'_>,
60 random: &mut WorldgenRandom,
61 mut place_pos: BlockPos,
62 total_height: i32,
63 min_age: u8,
64 max_age: u8,
65 ) {
66 for height in 1..=total_height {
67 if region.block_state(place_pos).is_air() {
68 if height == total_height || !region.block_state(place_pos.above()).is_air() {
69 let state = vanilla_blocks::TWISTING_VINES.default_state().set_value(
70 &BlockStateProperties::AGE_25,
71 random.next_i32_between(i32::from(min_age), i32::from(max_age)) as u8,
72 );
73 let _ = region.set_block_state(place_pos, state, UpdateFlags::UPDATE_CLIENTS);
74 break;
75 }
76
77 let _ = region.set_block_state(
78 place_pos,
79 vanilla_blocks::TWISTING_VINES_PLANT.default_state(),
80 UpdateFlags::UPDATE_CLIENTS,
81 );
82 }
83
84 place_pos = place_pos.above();
85 }
86 }
87
88 fn twisting_vines_invalid_placement_location(
89 region: &WorldGenRegion<'_>,
90 pos: BlockPos,
91 ) -> bool {
92 if !region.block_state(pos).is_air() {
93 return true;
94 }
95
96 let below_block = region.block_state(pos.below()).get_block();
97 below_block != &vanilla_blocks::NETHERRACK
98 && below_block != &vanilla_blocks::WARPED_NYLIUM
99 && below_block != &vanilla_blocks::WARPED_WART_BLOCK
100 }
101}