steel_core/worldgen/feature/features/
disk.rs1use 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 BlockStateProviderEvaluator::test_block_predicate(
49 region,
50 registry,
51 &config.target,
52 pos,
53 ) {
54 if let Some(state) =
55 BlockStateProviderEvaluator::sample_block_state_provider_optional(
56 region,
57 registry,
58 random,
59 &config.state_provider,
60 pos,
61 )
62 {
63 let _ = region.set_block_state(pos, state, UpdateFlags::UPDATE_CLIENTS);
64 if !placed_above {
65 Self::mark_above_for_postprocessing(region, pos);
66 }
67 placed_any = true;
68 placed_above = true;
69 }
70 } else {
71 placed_above = false;
72 }
73 }
74
75 placed_any
76 }
77
78 pub(in crate::worldgen::feature) fn mark_above_for_postprocessing(
79 region: &WorldGenRegion<'_>,
80 pos: BlockPos,
81 ) {
82 let mut mark_pos = pos;
83 for _ in 0..2 {
84 mark_pos = mark_pos.above();
85 if region.block_state(mark_pos).is_air() {
86 return;
87 }
88 region.mark_pos_for_postprocessing(mark_pos);
89 }
90 }
91}