Skip to main content

steel_core/worldgen/feature/features/
weeping_vines.rs

1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5    pub(in crate::worldgen::feature) fn place_weeping_vines_feature(
6        region: &mut WorldGenRegion<'_>,
7        random: &mut WorldgenRandom,
8        origin: BlockPos,
9    ) -> bool {
10        if !region.block_state(origin).is_air() {
11            return false;
12        }
13
14        let above_block = region.block_state(origin.above()).get_block();
15        if above_block != &vanilla_blocks::NETHERRACK
16            && above_block != &vanilla_blocks::NETHER_WART_BLOCK
17        {
18            return false;
19        }
20
21        Self::place_roof_nether_wart(region, random, origin);
22        Self::place_roof_weeping_vines(region, random, origin);
23        true
24    }
25
26    fn place_roof_nether_wart(
27        region: &mut WorldGenRegion<'_>,
28        random: &mut WorldgenRandom,
29        origin: BlockPos,
30    ) {
31        let wart = vanilla_blocks::NETHER_WART_BLOCK.default_state();
32        let _ = region.set_block_state(origin, wart, UpdateFlags::UPDATE_CLIENTS);
33
34        for _ in 0..200 {
35            let place_pos = origin.offset(
36                random.next_i32_bounded(6) - random.next_i32_bounded(6),
37                random.next_i32_bounded(2) - random.next_i32_bounded(5),
38                random.next_i32_bounded(6) - random.next_i32_bounded(6),
39            );
40            if !region.block_state(place_pos).is_air() {
41                continue;
42            }
43
44            let mut neighbors = 0;
45            for direction in Self::VANILLA_DIRECTION_VALUES {
46                let neighbor_block = region
47                    .block_state(place_pos.relative(direction))
48                    .get_block();
49                if neighbor_block == &vanilla_blocks::NETHERRACK
50                    || neighbor_block == &vanilla_blocks::NETHER_WART_BLOCK
51                {
52                    neighbors += 1;
53                }
54
55                if neighbors > 1 {
56                    break;
57                }
58            }
59
60            if neighbors == 1 {
61                let _ = region.set_block_state(place_pos, wart, UpdateFlags::UPDATE_CLIENTS);
62            }
63        }
64    }
65
66    fn place_roof_weeping_vines(
67        region: &mut WorldGenRegion<'_>,
68        random: &mut WorldgenRandom,
69        origin: BlockPos,
70    ) {
71        for _ in 0..100 {
72            let place_pos = origin.offset(
73                random.next_i32_bounded(8) - random.next_i32_bounded(8),
74                random.next_i32_bounded(2) - random.next_i32_bounded(7),
75                random.next_i32_bounded(8) - random.next_i32_bounded(8),
76            );
77            if !region.block_state(place_pos).is_air() {
78                continue;
79            }
80
81            let above_block = region.block_state(place_pos.above()).get_block();
82            if above_block == &vanilla_blocks::NETHERRACK
83                || above_block == &vanilla_blocks::NETHER_WART_BLOCK
84            {
85                let mut vine_height = random.next_i32_between(1, 8);
86                if random.next_i32_bounded(6) == 0 {
87                    vine_height *= 2;
88                }
89
90                if random.next_i32_bounded(5) == 0 {
91                    vine_height = 1;
92                }
93
94                Self::place_weeping_vines_column(region, random, place_pos, vine_height, 17, 25);
95            }
96        }
97    }
98
99    pub(in crate::worldgen::feature) fn place_weeping_vines_column(
100        region: &mut WorldGenRegion<'_>,
101        random: &mut WorldgenRandom,
102        mut place_pos: BlockPos,
103        total_height: i32,
104        min_age: u8,
105        max_age: u8,
106    ) {
107        for height in 0..=total_height {
108            if region.block_state(place_pos).is_air() {
109                if height == total_height || !region.block_state(place_pos.below()).is_air() {
110                    let state = vanilla_blocks::WEEPING_VINES.default_state().set_value(
111                        &BlockStateProperties::AGE_25,
112                        random.next_i32_between(i32::from(min_age), i32::from(max_age)) as u8,
113                    );
114                    let _ = region.set_block_state(place_pos, state, UpdateFlags::UPDATE_CLIENTS);
115                    break;
116                }
117
118                let _ = region.set_block_state(
119                    place_pos,
120                    vanilla_blocks::WEEPING_VINES_PLANT.default_state(),
121                    UpdateFlags::UPDATE_CLIENTS,
122                );
123            }
124
125            place_pos = place_pos.below();
126        }
127    }
128}