Skip to main content

steel_core/worldgen/feature/features/
block_column.rs

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