Skip to main content

steel_core/worldgen/feature/features/
basalt_pillar.rs

1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5    pub(in crate::worldgen::feature) fn place_basalt_pillar_feature(
6        region: &mut WorldGenRegion<'_>,
7        random: &mut WorldgenRandom,
8        origin: BlockPos,
9    ) -> bool {
10        if !region.block_state(origin).is_air() || region.block_state(origin.above()).is_air() {
11            return false;
12        }
13
14        let basalt = vanilla_blocks::BASALT.default_state();
15        let mut pos = origin;
16        let mut place_north_hangoff = true;
17        let mut place_south_hangoff = true;
18        let mut place_west_hangoff = true;
19        let mut place_east_hangoff = true;
20
21        while region.block_state(pos).is_air() {
22            if region.is_outside_build_height(pos.y()) {
23                return true;
24            }
25
26            let _ = region.set_block_state(pos, basalt, UpdateFlags::UPDATE_CLIENTS);
27            if place_north_hangoff {
28                place_north_hangoff =
29                    Self::place_basalt_pillar_hangoff(region, random, basalt, pos.north());
30            }
31            if place_south_hangoff {
32                place_south_hangoff =
33                    Self::place_basalt_pillar_hangoff(region, random, basalt, pos.south());
34            }
35            if place_west_hangoff {
36                place_west_hangoff =
37                    Self::place_basalt_pillar_hangoff(region, random, basalt, pos.west());
38            }
39            if place_east_hangoff {
40                place_east_hangoff =
41                    Self::place_basalt_pillar_hangoff(region, random, basalt, pos.east());
42            }
43
44            pos = pos.below();
45        }
46
47        pos = pos.above();
48        Self::place_basalt_pillar_base_hangoff(region, random, basalt, pos.north());
49        Self::place_basalt_pillar_base_hangoff(region, random, basalt, pos.south());
50        Self::place_basalt_pillar_base_hangoff(region, random, basalt, pos.west());
51        Self::place_basalt_pillar_base_hangoff(region, random, basalt, pos.east());
52        pos = pos.below();
53
54        for dx in -3i32..4 {
55            for dz in -3i32..4 {
56                let probability = dx.abs() * dz.abs();
57                if random.next_i32_bounded(10) < 10 - probability {
58                    let mut base_pos = pos.offset(dx, 0, dz);
59                    let mut max_drop = 3;
60
61                    while region.block_state(base_pos.below()).is_air() {
62                        base_pos = base_pos.below();
63                        max_drop -= 1;
64                        if max_drop <= 0 {
65                            break;
66                        }
67                    }
68
69                    if !region.block_state(base_pos.below()).is_air() {
70                        let _ =
71                            region.set_block_state(base_pos, basalt, UpdateFlags::UPDATE_CLIENTS);
72                    }
73                }
74            }
75        }
76
77        true
78    }
79
80    pub(in crate::worldgen::feature) fn place_basalt_pillar_base_hangoff(
81        region: &mut WorldGenRegion<'_>,
82        random: &mut WorldgenRandom,
83        basalt: BlockStateId,
84        pos: BlockPos,
85    ) {
86        if random.next_bool() {
87            let _ = region.set_block_state(pos, basalt, UpdateFlags::UPDATE_CLIENTS);
88        }
89    }
90
91    pub(in crate::worldgen::feature) fn place_basalt_pillar_hangoff(
92        region: &mut WorldGenRegion<'_>,
93        random: &mut WorldgenRandom,
94        basalt: BlockStateId,
95        pos: BlockPos,
96    ) -> bool {
97        if random.next_i32_bounded(10) == 0 {
98            return false;
99        }
100
101        let _ = region.set_block_state(pos, basalt, UpdateFlags::UPDATE_CLIENTS);
102        true
103    }
104}