Skip to main content

steel_core/worldgen/feature/features/
twisting_vines.rs

1use 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}