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 !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}