steel_core/worldgen/feature/features/
replace_blobs.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_netherrack_replace_blobs_feature(
6 region: &mut WorldGenRegion<'_>,
7 registry: &Registry,
8 random: &mut WorldgenRandom,
9 config: &NetherrackReplaceBlobsConfiguration,
10 origin: BlockPos,
11 ) -> bool {
12 let target = Self::block_state_from_data(registry, &config.target);
13 let replacement = Self::block_state_from_data(registry, &config.state);
14 let clamped_origin = BlockPos::new(
15 origin.x(),
16 origin
17 .y()
18 .clamp(region.min_y() + 1, region.max_y_exclusive() - 1),
19 origin.z(),
20 );
21 let Some(center) = Self::find_replace_blobs_target(region, clamped_origin, target) else {
22 return false;
23 };
24
25 let radius_x = config.radius.sample(random);
26 let radius_y = config.radius.sample(random);
27 let radius_z = config.radius.sample(random);
28 let maximum_radius = radius_x.max(radius_y).max(radius_z);
29 let target_block = target.get_block();
30 let mut replaced_any = false;
31
32 Self::for_each_vanilla_within_manhattan(center, radius_x, radius_y, radius_z, |pos| {
33 if Self::manhattan_distance(pos, center) > maximum_radius {
34 return false;
35 }
36
37 if region.block_state(pos).get_block() == target_block {
38 let _ = region.set_block_state(pos, replacement, UpdateFlags::UPDATE_CLIENTS);
39 replaced_any = true;
40 }
41
42 true
43 });
44
45 replaced_any
46 }
47
48 fn find_replace_blobs_target(
49 region: &WorldGenRegion<'_>,
50 mut cursor: BlockPos,
51 target: BlockStateId,
52 ) -> Option<BlockPos> {
53 let target_block = target.get_block();
54 while cursor.y() > region.min_y() + 1 {
55 if region.block_state(cursor).get_block() == target_block {
56 return Some(cursor);
57 }
58 cursor = cursor.below();
59 }
60
61 None
62 }
63}