steel_core/worldgen/feature/features/
block_pile.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_block_pile_feature(
6 region: &mut WorldGenRegion<'_>,
7 registry: &Registry,
8 random: &mut WorldgenRandom,
9 config: &BlockPileConfiguration,
10 origin: BlockPos,
11 ) -> bool {
12 if origin.y() < region.min_y() + 5 {
13 return false;
14 }
15
16 let x_radius = 2 + random.next_i32_bounded(2);
17 let z_radius = 2 + random.next_i32_bounded(2);
18
19 Self::for_each_vanilla_between_closed(
20 origin.offset(-x_radius, 0, -z_radius),
21 origin.offset(x_radius, 1, z_radius),
22 |pos| {
23 let dx = origin.x() - pos.x();
24 let dz = origin.z() - pos.z();
25 let distance_squared = (dx * dx + dz * dz) as f32;
26 if distance_squared <= random.next_f32() * 10.0 - random.next_f32() * 6.0
27 || random.next_f32() < 0.031
28 {
29 Self::try_place_block_pile_block(region, registry, random, config, pos);
30 }
31 },
32 );
33
34 true
35 }
36
37 pub(in crate::worldgen::feature) fn try_place_block_pile_block(
38 region: &mut WorldGenRegion<'_>,
39 registry: &Registry,
40 random: &mut WorldgenRandom,
41 config: &BlockPileConfiguration,
42 pos: BlockPos,
43 ) {
44 if !region.block_state(pos).is_air() || !Self::block_pile_may_place_on(region, random, pos)
45 {
46 return;
47 }
48
49 let state = Self::sample_block_state_provider(
50 region,
51 registry,
52 random,
53 &config.state_provider,
54 pos,
55 );
56 let _ = region.set_block_state(pos, state, UpdateFlags::UPDATE_NONE);
57 }
58
59 pub(in crate::worldgen::feature) fn block_pile_may_place_on(
60 region: &WorldGenRegion<'_>,
61 random: &mut WorldgenRandom,
62 pos: BlockPos,
63 ) -> bool {
64 let below_pos = pos.below();
65 let below = region.block_state(below_pos);
66 if below.get_block() == &vanilla_blocks::DIRT_PATH {
67 return random.next_bool();
68 }
69
70 below.is_face_sturdy_at(below_pos, Direction::Up)
71 }
72}