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 !BlockStateProviderEvaluator::test_block_predicate(
25 region,
26 registry,
27 &config.allowed_placement,
28 next_pos,
29 ) {
30 Self::truncate_block_column_layers(
31 &mut layer_heights,
32 total_height,
33 height,
34 config.prioritize_tip,
35 );
36 break;
37 }
38 next_pos = next_pos.relative(config.direction);
39 }
40
41 let mut place_pos = origin;
42 for (layer_index, layer) in config.layers.iter().enumerate() {
43 for _ in 0..layer_heights[layer_index] {
44 let state = BlockStateProviderEvaluator::sample_block_state_provider(
45 region,
46 registry,
47 random,
48 &layer.provider,
49 place_pos,
50 );
51 let _ = region.set_block_state(place_pos, state, UpdateFlags::UPDATE_CLIENTS);
52 place_pos = place_pos.relative(config.direction);
53 }
54 }
55
56 true
57 }
58
59 pub(in crate::worldgen::feature) fn truncate_block_column_layers(
60 layer_heights: &mut [i32],
61 total_height: i32,
62 new_height: i32,
63 prioritize_tip: bool,
64 ) {
65 let mut amount_to_remove = total_height - new_height;
66 if prioritize_tip {
67 for height in layer_heights {
68 if amount_to_remove == 0 {
69 return;
70 }
71 let removed = (*height).min(amount_to_remove);
72 amount_to_remove -= removed;
73 *height -= removed;
74 }
75 } else {
76 for height in layer_heights.iter_mut().rev() {
77 if amount_to_remove == 0 {
78 return;
79 }
80 let removed = (*height).min(amount_to_remove);
81 amount_to_remove -= removed;
82 *height -= removed;
83 }
84 }
85 }
86}