Skip to main content

steel_core/worldgen/feature/features/
disk.rs

1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5    pub(in crate::worldgen::feature) fn place_disk_feature(
6        region: &mut WorldGenRegion<'_>,
7        registry: &Registry,
8        random: &mut WorldgenRandom,
9        config: &DiskConfiguration,
10        origin: BlockPos,
11    ) -> bool {
12        let top = origin.y() + config.half_height;
13        let bottom = origin.y() - config.half_height - 1;
14        let radius = config.radius.sample(random);
15        let mut placed_any = false;
16
17        Self::for_each_vanilla_between_closed(
18            origin.offset(-radius, 0, -radius),
19            origin.offset(radius, 0, radius),
20            |column_pos| {
21                let dx = column_pos.x() - origin.x();
22                let dz = column_pos.z() - origin.z();
23                if dx * dx + dz * dz <= radius * radius {
24                    placed_any |= Self::place_disk_column(
25                        region, registry, random, config, top, bottom, column_pos,
26                    );
27                }
28            },
29        );
30
31        placed_any
32    }
33
34    pub(in crate::worldgen::feature) fn place_disk_column(
35        region: &mut WorldGenRegion<'_>,
36        registry: &Registry,
37        random: &mut WorldgenRandom,
38        config: &DiskConfiguration,
39        top: i32,
40        bottom: i32,
41        column_pos: BlockPos,
42    ) -> bool {
43        let mut placed_any = false;
44        let mut placed_above = false;
45
46        for y in (bottom + 1..=top).rev() {
47            let pos = BlockPos::new(column_pos.x(), y, column_pos.z());
48            if Self::test_block_predicate(region, registry, &config.target, pos) {
49                if let Some(state) = Self::sample_block_state_provider_optional(
50                    region,
51                    registry,
52                    random,
53                    &config.state_provider,
54                    pos,
55                ) {
56                    let _ = region.set_block_state(pos, state, UpdateFlags::UPDATE_CLIENTS);
57                    if !placed_above {
58                        Self::mark_above_for_postprocessing(region, pos);
59                    }
60                    placed_any = true;
61                    placed_above = true;
62                }
63            } else {
64                placed_above = false;
65            }
66        }
67
68        placed_any
69    }
70
71    pub(in crate::worldgen::feature) fn mark_above_for_postprocessing(
72        region: &WorldGenRegion<'_>,
73        pos: BlockPos,
74    ) {
75        let mut mark_pos = pos;
76        for _ in 0..2 {
77            mark_pos = mark_pos.above();
78            if region.block_state(mark_pos).is_air() {
79                return;
80            }
81            region.mark_pos_for_postprocessing(mark_pos);
82        }
83    }
84}