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 = BlockStateProviderEvaluator::block_state_from_data(registry, &config.target);
13 let replacement =
14 BlockStateProviderEvaluator::block_state_from_data(registry, &config.state);
15 let clamped_origin = BlockPos::new(
16 origin.x(),
17 origin
18 .y()
19 .clamp(region.min_y() + 1, region.max_y_exclusive() - 1),
20 origin.z(),
21 );
22 let Some(center) = Self::find_replace_blobs_target(region, clamped_origin, target) else {
23 return false;
24 };
25
26 let radius_x = config.radius.sample(random);
27 let radius_y = config.radius.sample(random);
28 let radius_z = config.radius.sample(random);
29 let maximum_radius = radius_x.max(radius_y).max(radius_z);
30 let target_block = target.get_block();
31 let mut replaced_any = false;
32
33 Self::for_each_vanilla_within_manhattan(center, radius_x, radius_y, radius_z, |pos| {
34 if Self::manhattan_distance(pos, center) > maximum_radius {
35 return false;
36 }
37
38 if region.block_state(pos).get_block() == target_block {
39 let _ = region.set_block_state(pos, replacement, UpdateFlags::UPDATE_CLIENTS);
40 replaced_any = true;
41 }
42
43 true
44 });
45
46 replaced_any
47 }
48
49 fn find_replace_blobs_target(
50 region: &WorldGenRegion<'_>,
51 mut cursor: BlockPos,
52 target: BlockStateId,
53 ) -> Option<BlockPos> {
54 let target_block = target.get_block();
55 while cursor.y() > region.min_y() + 1 {
56 if region.block_state(cursor).get_block() == target_block {
57 return Some(cursor);
58 }
59 cursor = cursor.below();
60 }
61
62 None
63 }
64}