Skip to main content

steel_core/worldgen/structure/piece_placer/
pool_element.rs

1use steel_registry::structure::LiquidSettingsData;
2use steel_registry::structure_processor::StructureProcessorKind;
3use steel_registry::template_pool::{PoolElement, ProcessorList, Projection};
4use steel_registry::{Registry, RegistryExt};
5use steel_utils::random::worldgen_random::WorldgenRandom;
6use steel_utils::{BlockPos, BoundingBox, Identifier, Rotation};
7
8use crate::worldgen::feature::FeatureDecorationRunner;
9use crate::worldgen::region::WorldGenRegion;
10use crate::worldgen::template::{
11    StructurePlaceSettings, StructureProcessorRandom, StructureTemplate,
12};
13use steel_worldgen::structure::{StructureBlockIgnore, StructureMirror};
14
15use super::StructurePiecePlacer;
16
17impl StructurePiecePlacer {
18    #[expect(
19        clippy::too_many_arguments,
20        reason = "mirrors StructurePoolElement.place inputs"
21    )]
22    pub(super) fn place_pool_element(
23        region: &mut WorldGenRegion<'_>,
24        registry: &Registry,
25        element: &PoolElement,
26        position: BlockPos,
27        reference_pos: BlockPos,
28        rotation: Rotation,
29        clip: BoundingBox,
30        random: &mut WorldgenRandom,
31        liquid_settings: LiquidSettingsData,
32        biome_zoom_seed: i64,
33    ) -> bool {
34        match element {
35            PoolElement::Single {
36                location,
37                processors,
38                projection,
39            } => Self::place_single_pool_element(
40                region,
41                registry,
42                location,
43                processors,
44                *projection,
45                StructureBlockIgnore::StructureBlock,
46                StructureBlockIgnore::None,
47                position,
48                reference_pos,
49                rotation,
50                clip,
51                random,
52                liquid_settings,
53            ),
54            PoolElement::LegacySingle {
55                location,
56                processors,
57                projection,
58            } => Self::place_single_pool_element(
59                region,
60                registry,
61                location,
62                processors,
63                *projection,
64                StructureBlockIgnore::None,
65                StructureBlockIgnore::StructureAndAir,
66                position,
67                reference_pos,
68                rotation,
69                clip,
70                random,
71                liquid_settings,
72            ),
73            PoolElement::Empty => true,
74            PoolElement::Feature { feature, .. } => {
75                FeatureDecorationRunner::place_structure_pool_feature(
76                    region,
77                    registry,
78                    random,
79                    position,
80                    feature,
81                    biome_zoom_seed,
82                )
83            }
84            PoolElement::List { elements, .. } => {
85                for element in elements {
86                    if !Self::place_pool_element(
87                        region,
88                        registry,
89                        element,
90                        position,
91                        reference_pos,
92                        rotation,
93                        clip,
94                        random,
95                        liquid_settings,
96                        biome_zoom_seed,
97                    ) {
98                        return false;
99                    }
100                }
101                true
102            }
103        }
104    }
105
106    #[expect(
107        clippy::too_many_arguments,
108        reason = "mirrors SinglePoolElement.place and StructureTemplate.placeInWorld"
109    )]
110    fn place_single_pool_element(
111        region: &mut WorldGenRegion<'_>,
112        registry: &Registry,
113        location: &Identifier,
114        processors: &ProcessorList,
115        projection: Projection,
116        block_ignore: StructureBlockIgnore,
117        late_block_ignore: StructureBlockIgnore,
118        position: BlockPos,
119        reference_pos: BlockPos,
120        rotation: Rotation,
121        clip: BoundingBox,
122        random: &mut WorldgenRandom,
123        liquid_settings: LiquidSettingsData,
124    ) -> bool {
125        let template = match StructureTemplate::load_vanilla(registry, location) {
126            Ok(template) => template,
127            Err(err) => panic!("{err}"),
128        };
129        let processor_list = Self::pool_processors(registry, processors);
130        let settings = StructurePlaceSettings {
131            mirror: StructureMirror::None,
132            rotation,
133            rotation_pivot: BlockPos::ZERO,
134            bounding_box: clip,
135            processors: processor_list,
136            block_ignore,
137            late_block_ignore,
138            replace_jigsaws: true,
139            projection: Some(projection),
140            processor_random: StructureProcessorRandom::Positional,
141            liquid_settings,
142        };
143
144        template.place_in_world(
145            region,
146            registry,
147            position,
148            reference_pos,
149            &settings,
150            random,
151            Self::JIGSAW_UPDATE_FLAGS,
152        )
153    }
154
155    fn pool_processors<'a>(
156        registry: &'a Registry,
157        processors: &'a ProcessorList,
158    ) -> &'a [StructureProcessorKind] {
159        match processors {
160            ProcessorList::Empty => &[],
161            ProcessorList::Registry(key) => {
162                let Some(processor_list) = registry.structure_processors.by_key(key) else {
163                    panic!("template pool references unknown processor list {key}");
164                };
165                &processor_list.data.processors
166            }
167        }
168    }
169}