steel_core/worldgen/feature/features/
delta.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_delta_feature(
6 region: &mut WorldGenRegion<'_>,
7 registry: &Registry,
8 random: &mut WorldgenRandom,
9 config: &DeltaFeatureConfiguration,
10 origin: BlockPos,
11 ) -> bool {
12 let contents =
13 BlockStateProviderEvaluator::block_state_from_data(registry, &config.contents);
14 let rim = BlockStateProviderEvaluator::block_state_from_data(registry, &config.rim);
15 let spawn_rim = random.next_f64() < 0.9;
16 let rim_x = if spawn_rim {
17 config.rim_size.sample(random)
18 } else {
19 0
20 };
21 let rim_z = if spawn_rim {
22 config.rim_size.sample(random)
23 } else {
24 0
25 };
26 let has_rim = spawn_rim && rim_x != 0 && rim_z != 0;
27 let radius_x = config.size.sample(random);
28 let radius_z = config.size.sample(random);
29 let radius_limit = radius_x.max(radius_z);
30 let mut any_placed = false;
31
32 Self::for_each_vanilla_within_manhattan(origin, radius_x, 0, radius_z, |pos| {
33 if Self::manhattan_distance(pos, origin) > radius_limit {
34 return false;
35 }
36
37 if Self::delta_is_clear(region, pos, contents) {
38 if has_rim {
39 let _ = region.set_block_state(pos, rim, UpdateFlags::UPDATE_CLIENTS);
40 any_placed = true;
41 }
42
43 let offset_pos = pos.offset(rim_x, 0, rim_z);
44 if Self::delta_is_clear(region, offset_pos, contents) {
45 let _ =
46 region.set_block_state(offset_pos, contents, UpdateFlags::UPDATE_CLIENTS);
47 any_placed = true;
48 }
49 }
50
51 true
52 });
53
54 any_placed
55 }
56
57 fn delta_is_clear(region: &WorldGenRegion<'_>, pos: BlockPos, contents: BlockStateId) -> bool {
58 let state = region.block_state(pos);
59 if state.get_block() == contents.get_block() {
60 return false;
61 }
62
63 if Self::delta_cannot_replace(state.get_block()) {
64 return false;
65 }
66
67 for direction in Self::VANILLA_DIRECTION_VALUES {
68 let is_air = region.block_state(pos.relative(direction)).is_air();
69 if (is_air && direction != Direction::Up) || (!is_air && direction == Direction::Up) {
70 return false;
71 }
72 }
73
74 true
75 }
76
77 fn delta_cannot_replace(block: BlockRef) -> bool {
78 block == &vanilla_blocks::BEDROCK
79 || block == &vanilla_blocks::NETHER_BRICKS
80 || block == &vanilla_blocks::NETHER_BRICK_FENCE
81 || block == &vanilla_blocks::NETHER_BRICK_STAIRS
82 || block == &vanilla_blocks::NETHER_WART
83 || block == &vanilla_blocks::CHEST
84 || block == &vanilla_blocks::SPAWNER
85 }
86}