steel_core/worldgen/feature/features/
block_column.rs1use super::super::prelude::*;
2use super::super::runner::FeatureDecorationRunner;
3
4impl FeatureDecorationRunner {
5 pub(in crate::worldgen::feature) fn place_block_column_feature(
6 region: &mut WorldGenRegion<'_>,
7 registry: &Registry,
8 random: &mut WorldgenRandom,
9 config: &BlockColumnConfiguration,
10 origin: BlockPos,
11 ) -> bool {
12 let mut layer_heights = config
13 .layers
14 .iter()
15 .map(|layer| layer.height.sample(random))
16 .collect::<Vec<_>>();
17 let total_height = layer_heights.iter().sum::<i32>();
18 if total_height == 0 {
19 return false;
20 }
21
22 let mut next_pos = origin.relative(config.direction);
23 for height in 0..total_height {
24 if !Self::test_block_predicate(region, registry, &config.allowed_placement, next_pos) {
25 Self::truncate_block_column_layers(
26 &mut layer_heights,
27 total_height,
28 height,
29 config.prioritize_tip,
30 );
31 break;
32 }
33 next_pos = next_pos.relative(config.direction);
34 }
35
36 let mut place_pos = origin;
37 for (layer_index, layer) in config.layers.iter().enumerate() {
38 for _ in 0..layer_heights[layer_index] {
39 let state = Self::sample_block_state_provider(
40 region,
41 registry,
42 random,
43 &layer.provider,
44 place_pos,
45 );
46 let _ = region.set_block_state(place_pos, state, UpdateFlags::UPDATE_CLIENTS);
47 place_pos = place_pos.relative(config.direction);
48 }
49 }
50
51 true
52 }
53
54 pub(in crate::worldgen::feature) fn truncate_block_column_layers(
55 layer_heights: &mut [i32],
56 total_height: i32,
57 new_height: i32,
58 prioritize_tip: bool,
59 ) {
60 let mut amount_to_remove = total_height - new_height;
61 if prioritize_tip {
62 for height in layer_heights {
63 if amount_to_remove == 0 {
64 return;
65 }
66 let removed = (*height).min(amount_to_remove);
67 amount_to_remove -= removed;
68 *height -= removed;
69 }
70 } else {
71 for height in layer_heights.iter_mut().rev() {
72 if amount_to_remove == 0 {
73 return;
74 }
75 let removed = (*height).min(amount_to_remove);
76 amount_to_remove -= removed;
77 *height -= removed;
78 }
79 }
80 }
81}