Skip to main content

steel_core/worldgen/feature/features/
replace_blobs.rs

1use 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}