Skip to main content

steel_registry/feature/
data.rs

1//! Typed worldgen feature registry data.
2//!
3//! These types mirror vanilla's configured feature, placed feature, placement
4//! modifier, provider, predicate, and tree-shape data after build-time decoding.
5//! Runtime data stores typed registry refs where the referenced vanilla entry is
6//! known at build time.
7
8use super::{ConfiguredFeatureEntryRef, PlacedFeatureEntryRef};
9use crate::blocks::BlockRef;
10use crate::fluid::FluidRef;
11use glam::IVec3;
12use steel_utils::{
13    Direction, Identifier, Rotation,
14    value_providers::{
15        FloatProvider, HeightProvider, IntProvider, UniformIntProvider, VerticalAnchor,
16    },
17};
18
19/// A configured feature reference, either a registry entry or an inline configured feature.
20#[derive(Debug, Clone)]
21pub enum ConfiguredFeatureRef {
22    /// Registry-backed configured feature.
23    Reference(ConfiguredFeatureEntryRef),
24    /// Inline configured feature.
25    Inline(Box<ConfiguredFeatureKind>),
26}
27
28/// A placed feature reference, either a registry entry or an inline placed feature.
29#[derive(Debug, Clone)]
30pub enum PlacedFeatureRef {
31    /// Registry-backed placed feature.
32    Reference(PlacedFeatureEntryRef),
33    /// Inline placed feature.
34    Inline(Box<PlacedFeatureData>),
35}
36
37/// A placed feature: configured feature plus ordered placement modifiers.
38#[derive(Debug, Clone)]
39pub struct PlacedFeatureData {
40    /// Configured feature reference.
41    pub feature: ConfiguredFeatureRef,
42    /// Ordered placement modifier chain.
43    pub placement: Vec<PlacementModifier>,
44}
45
46/// A configured feature kind with its typed configuration.
47#[derive(Debug, Clone)]
48#[expect(
49    clippy::large_enum_variant,
50    reason = "typed feature configs are registry data moved by reference; boxing individual variants would add noise before placement implementations use them"
51)]
52pub enum ConfiguredFeatureKind {
53    Bamboo(BambooConfiguration),
54    BasaltColumns(BasaltColumnsConfiguration),
55    BasaltPillar,
56    BlockBlob(BlockBlobConfiguration),
57    BlockColumn(BlockColumnConfiguration),
58    BlockPile(BlockPileConfiguration),
59    BlueIce,
60    BonusChest,
61    ChorusPlant,
62    CoralClaw {
63        feature: PlacedFeatureRef,
64    },
65    CoralMushroom,
66    CoralTree {
67        feature: PlacedFeatureRef,
68    },
69    DeltaFeature(DeltaFeatureConfiguration),
70    DesertWell,
71    Disk(DiskConfiguration),
72    DripstoneCluster(DripstoneClusterConfiguration),
73    EndGateway(EndGatewayConfiguration),
74    EndIsland,
75    EndPlatform,
76    EndPodium {
77        active: bool,
78    },
79    EndSpike(EndSpikeConfiguration),
80    FallenTree(FallenTreeConfiguration),
81    Fossil(FossilConfiguration),
82    FreezeTopLayer,
83    Geode(GeodeConfiguration),
84    GlowstoneBlob,
85    HugeBrownMushroom(HugeMushroomConfiguration),
86    HugeFungus(HugeFungusConfiguration),
87    HugeRedMushroom(HugeMushroomConfiguration),
88    Iceberg(BlockStateData),
89    Kelp,
90    Lake(LakeConfiguration),
91    LargeDripstone(LargeDripstoneConfiguration),
92    MonsterRoom,
93    NoOp,
94    MultifaceGrowth(MultifaceGrowthConfiguration),
95    NetherForestVegetation(NetherForestVegetationConfiguration),
96    NetherrackReplaceBlobs(NetherrackReplaceBlobsConfiguration),
97    /// Places every placed feature in the set at the same origin.
98    Overlay {
99        features: Vec<PlacedFeatureRef>,
100    },
101    Ore(OreConfiguration),
102    ProjectedRandomPatchySquare(ProjectedRandomPatchySquareConfiguration),
103    PointedDripstone(PointedDripstoneConfiguration),
104    RandomNeighborSpread(RandomNeighborSpreadConfiguration),
105    RandomBooleanSelector(RandomBooleanSelectorConfiguration),
106    RandomSelector(RandomSelectorConfiguration),
107    RootSystem(RootSystemConfiguration),
108    ScatteredOre(OreConfiguration),
109    SculkPatch(SculkPatchConfiguration),
110    SeaPickle(SeaPickleConfiguration),
111    Seagrass(SeagrassConfiguration),
112    Sequence(CompositeFeatureConfiguration),
113    SimpleBlock(SimpleBlockConfiguration),
114    SingleBlockPillar(SingleBlockPillarConfiguration),
115    SteppedColumnCluster(SteppedColumnClusterConfiguration),
116    SimpleRandomSelector(SimpleRandomSelectorConfiguration),
117    Speleothem(SpeleothemConfiguration),
118    SpeleothemCluster(SpeleothemClusterConfiguration),
119    Spike(SpikeConfiguration),
120    SpringFeature(SpringConfiguration),
121    Template(TemplateFeatureConfiguration),
122    Tree(TreeConfiguration),
123    TwistingVines(TwistingVinesConfiguration),
124    UnderwaterMagma(UnderwaterMagmaConfiguration),
125    VegetationPatch(VegetationPatchConfiguration),
126    Vines,
127    VoidStartPlatform,
128    WaterloggedVegetationPatch(VegetationPatchConfiguration),
129    WeightedRandomSelector(WeightedRandomFeatureConfiguration),
130    WeepingVines,
131}
132
133/// Block refs decoded from vanilla's single-or-list codec shape at build time.
134#[derive(Debug, Clone)]
135pub struct BlockRefList(pub Vec<BlockRef>);
136
137/// Fluid refs decoded from vanilla's single-or-list codec shape at build time.
138#[derive(Debug, Clone)]
139pub struct FluidRefList(pub Vec<FluidRef>);
140
141/// Block holder set decoded from vanilla's holder-set codec shape at build time.
142#[derive(Debug, Clone)]
143pub enum BlockHolderSet {
144    Tag(Identifier),
145    Entries(Vec<BlockRef>),
146}
147
148/// Block state data emitted by the feature generator without baking a state id.
149#[derive(Debug, Clone)]
150pub struct BlockStateData {
151    /// Referenced block entry.
152    pub block: BlockRef,
153    /// Explicit state properties from the extracted feature config.
154    pub properties: &'static [(&'static str, &'static str)],
155}
156
157/// Fluid state data emitted by the feature generator without runtime key lookup.
158#[derive(Debug, Clone)]
159pub struct FluidStateData {
160    /// Referenced fluid entry.
161    pub fluid: FluidRef,
162    /// Explicit state properties from the extracted feature config.
163    pub properties: &'static [(&'static str, &'static str)],
164}
165
166/// Block position offset.
167pub type Offset = IVec3;
168
169/// Block predicates used by placement modifiers and feature configs.
170#[derive(Debug, Clone)]
171pub enum BlockPredicate {
172    True,
173    AllOf {
174        predicates: Vec<BlockPredicate>,
175    },
176    AnyOf {
177        predicates: Vec<BlockPredicate>,
178    },
179    Not {
180        predicate: Box<BlockPredicate>,
181    },
182    MatchingBlockTag {
183        tag: Identifier,
184        offset: Offset,
185    },
186    MatchingBlocks {
187        blocks: BlockRefList,
188        offset: Offset,
189    },
190    MatchingFluids {
191        fluids: FluidRefList,
192        offset: Offset,
193    },
194    Solid {
195        offset: Offset,
196    },
197    WouldSurvive {
198        state: BlockStateData,
199        offset: Offset,
200    },
201    Replaceable {
202        offset: Offset,
203    },
204    HasSturdyFace {
205        direction: Direction,
206        offset: Offset,
207    },
208    InsideWorldBounds {
209        offset: Offset,
210    },
211    HeightRange {
212        min_inclusive: VerticalAnchor,
213        max_inclusive: VerticalAnchor,
214    },
215    VolumeMatch {
216        min: Offset,
217        max: Offset,
218        matches: Box<BlockPredicate>,
219    },
220}
221
222/// A registered `worldgen/block_state_provider` entry.
223#[derive(Debug)]
224pub struct BlockStateProvider {
225    /// Registry key.
226    pub key: Identifier,
227    /// Typed provider data.
228    pub kind: BlockStateProviderKind,
229    /// Build-time-baked `BlockStateProvider.DIRECT_CODEC` encoding, for the registry sync packet.
230    pub nbt: fn() -> simdnbt::owned::NbtCompound,
231    /// Cached registry ID.
232    pub id: std::sync::OnceLock<usize>,
233}
234
235/// Read-only reference to a registered [`BlockStateProvider`].
236pub type BlockStateProviderRef = &'static BlockStateProvider;
237
238/// Block-state provider used by features.
239#[derive(Debug, Clone)]
240pub enum BlockStateProviderKind {
241    /// Registry-backed block-state provider.
242    Reference(BlockStateProviderRef),
243    Simple {
244        state: BlockStateData,
245    },
246    Weighted {
247        entries: Vec<WeightedBlockState>,
248    },
249    RotatedBlock {
250        state: Box<BlockStateProviderKind>,
251        direction: Option<Direction>,
252    },
253    RandomizedInt {
254        property: String,
255        source: Box<BlockStateProviderKind>,
256        values: IntProvider,
257    },
258    RuleBased {
259        fallback: Option<Box<BlockStateProviderKind>>,
260        rules: Vec<RuleBasedStateProviderRule>,
261    },
262    Noise(NoiseProvider),
263    NoiseThreshold(NoiseThresholdProvider),
264    DualNoise(DualNoiseProvider),
265    /// Copies the properties of the block being replaced onto the sourced state.
266    CopyProperties {
267        source: Box<BlockStateProviderKind>,
268    },
269    /// Picks a random block from a holder set (default state, no properties).
270    RandomBlock {
271        blocks: BlockHolderSet,
272    },
273}
274
275/// Weighted block-state provider entry.
276#[derive(Debug, Clone)]
277pub struct WeightedBlockState {
278    pub data: BlockStateData,
279    pub weight: i32,
280}
281
282/// Rule-based provider rule.
283#[derive(Debug, Clone)]
284pub struct RuleBasedStateProviderRule {
285    pub if_true: BlockPredicate,
286    pub then: BlockStateProviderKind,
287}
288
289/// `NormalNoise.Parameters`, embedded in vanilla feature providers.
290///
291/// `normalize` is modeled as a plain bool (`enabled`/`disabled`, matching
292/// vanilla's `Codec.BOOL` branch) — the deprecated `"legacy"` string form
293/// never appears in extracted data.
294#[derive(Debug, Clone)]
295pub struct FeatureNoiseParameters {
296    pub base_amplitude: f64,
297    pub base_octave: i32,
298    pub octave_count: i32,
299    pub normalize: bool,
300    pub amplitude_modifiers: Vec<f64>,
301}
302
303#[derive(Debug, Clone)]
304pub struct NoiseProvider {
305    pub noise: FeatureNoiseParameters,
306    pub scale: f32,
307    pub seed: i64,
308    pub states: Vec<BlockStateData>,
309}
310
311#[derive(Debug, Clone)]
312pub struct NoiseThresholdProvider {
313    pub noise: FeatureNoiseParameters,
314    pub scale: f32,
315    pub seed: i64,
316    pub threshold: f32,
317    pub high_chance: f32,
318    pub default_state: BlockStateData,
319    pub low_states: Vec<BlockStateData>,
320    pub high_states: Vec<BlockStateData>,
321}
322
323#[derive(Debug, Clone)]
324pub struct DualNoiseProvider {
325    pub noise: FeatureNoiseParameters,
326    pub scale: f32,
327    pub seed: i64,
328    pub slow_noise: FeatureNoiseParameters,
329    pub slow_scale: f32,
330    pub states: Vec<BlockStateData>,
331    pub variety: [i32; 2],
332}
333
334/// Feature placement modifiers.
335#[derive(Debug, Clone)]
336pub enum PlacementModifier {
337    Biome,
338    BlockPredicateFilter {
339        predicate: BlockPredicate,
340    },
341    Count {
342        count: IntProvider,
343    },
344    CountOnEveryLayer {
345        count: IntProvider,
346    },
347    EnvironmentScan {
348        direction_of_search: Direction,
349        target_condition: BlockPredicate,
350        allowed_search_condition: Option<BlockPredicate>,
351        max_steps: i32,
352    },
353    FixedPlacement {
354        positions: Vec<Offset>,
355    },
356    HeightRange {
357        height: HeightProvider,
358    },
359    Heightmap {
360        heightmap: FeatureHeightmap,
361    },
362    InSquare,
363    Offset {
364        x: IntProvider,
365        y: IntProvider,
366        z: IntProvider,
367    },
368    RandomlySelected {
369        placements: Vec<PlacementModifier>,
370    },
371    RandomChance {
372        chance: f32,
373    },
374    Cuboid {
375        xz_size: IntProvider,
376        y_size: IntProvider,
377        include_edges: bool,
378        include_interior: bool,
379    },
380    NoiseBasedCount {
381        noise_to_count_ratio: i32,
382        noise_factor: f64,
383        noise_offset: f64,
384    },
385    NoiseThresholdCount {
386        noise_level: f64,
387        below_noise: i32,
388        above_noise: i32,
389    },
390    RandomOffset {
391        xz_spread: IntProvider,
392        y_spread: IntProvider,
393    },
394    RarityFilter {
395        chance: i32,
396    },
397    SurfaceRelativeThresholdFilter {
398        heightmap: FeatureHeightmap,
399        min_inclusive: Option<i32>,
400        max_inclusive: Option<i32>,
401    },
402    SurfaceWaterDepthFilter {
403        max_water_depth: i32,
404    },
405}
406
407/// Heightmap names used by placed feature modifiers.
408#[derive(Debug, Clone, Copy, PartialEq, Eq)]
409pub enum FeatureHeightmap {
410    WorldSurface,
411    MotionBlocking,
412    MotionBlockingNoLeaves,
413    OceanFloor,
414    WorldSurfaceWg,
415    OceanFloorWg,
416}
417
418#[derive(Debug, Clone)]
419pub struct BambooConfiguration {
420    pub probability: f32,
421}
422
423#[derive(Debug, Clone)]
424pub struct BasaltColumnsConfiguration {
425    pub height: IntProvider,
426    pub reach: IntProvider,
427}
428
429#[derive(Debug, Clone)]
430pub struct BlockBlobConfiguration {
431    pub state: BlockStateData,
432    pub can_place_on: BlockPredicate,
433}
434
435#[derive(Debug, Clone)]
436pub struct BlockColumnConfiguration {
437    pub direction: Direction,
438    pub allowed_placement: BlockPredicate,
439    pub layers: Vec<BlockColumnLayer>,
440    pub prioritize_tip: bool,
441}
442
443#[derive(Debug, Clone)]
444pub struct BlockColumnLayer {
445    pub height: IntProvider,
446    pub provider: BlockStateProviderKind,
447}
448
449#[derive(Debug, Clone)]
450pub struct BlockPileConfiguration {
451    pub state_provider: BlockStateProviderKind,
452}
453
454#[derive(Debug, Clone)]
455pub struct DeltaFeatureConfiguration {
456    pub contents: BlockStateData,
457    pub rim: BlockStateData,
458    pub size: IntProvider,
459    pub rim_size: IntProvider,
460}
461
462#[derive(Debug, Clone)]
463pub struct DiskConfiguration {
464    pub state_provider: BlockStateProviderKind,
465    pub target: BlockPredicate,
466    pub radius: IntProvider,
467    pub half_height: i32,
468}
469
470/// `ProjectedRandomPatchySquare` — projects a random square patch of blocks
471/// downward until `project_through` stops matching.
472#[derive(Debug, Clone)]
473pub struct ProjectedRandomPatchySquareConfiguration {
474    pub block: BlockStateProviderKind,
475    pub project_through: BlockPredicate,
476    pub size: IntProvider,
477    pub max_projection_height: i32,
478}
479
480/// `RandomNeighborSpreadFeature` — spreads a block outward from the origin
481/// wherever exactly one accepted-neighbor block is adjacent.
482#[derive(Debug, Clone)]
483pub struct RandomNeighborSpreadConfiguration {
484    pub block: BlockStateProviderKind,
485    pub accepted_neighbors: BlockHolderSet,
486    pub can_replace: BlockPredicate,
487    pub attempts: IntProvider,
488    pub xz_offset: IntProvider,
489    pub y_offset: IntProvider,
490}
491
492/// `SingleBlockPillarFeature` — grows a pillar of one block, optionally
493/// capped with another placed feature.
494#[derive(Debug, Clone)]
495pub struct SingleBlockPillarConfiguration {
496    pub block: BlockStateProviderKind,
497    pub can_replace: BlockPredicate,
498    pub direction: Direction,
499    pub chance_to_continue: f32,
500    pub cap_feature: Option<PlacedFeatureRef>,
501}
502
503/// `SteppedColumnClusterFeature` — places a cluster of block columns of
504/// varying height/reach (basalt pillars, dripstone-adjacent clusters).
505#[derive(Debug, Clone)]
506pub struct SteppedColumnClusterConfiguration {
507    pub block: BlockStateProviderKind,
508    pub continue_through: BlockPredicate,
509    pub can_replace: BlockPredicate,
510    pub cannot_place_on: BlockHolderSet,
511    pub cluster_reach: IntProvider,
512    pub column_count: IntProvider,
513    pub column_reach: IntProvider,
514    pub height: IntProvider,
515}
516
517#[derive(Debug, Clone)]
518pub struct DripstoneClusterConfiguration {
519    pub floor_to_ceiling_search_range: i32,
520    pub height: IntProvider,
521    pub radius: IntProvider,
522    pub max_stalagmite_stalactite_height_diff: i32,
523    pub height_deviation: i32,
524    pub dripstone_block_layer_thickness: IntProvider,
525    pub density: FloatProvider,
526    pub wetness: FloatProvider,
527    pub chance_of_dripstone_column_at_max_distance_from_center: f32,
528    pub max_distance_from_center_affecting_height_bias: i32,
529    pub max_distance_from_edge_affecting_chance_of_dripstone_column: i32,
530}
531
532#[derive(Debug, Clone)]
533pub struct SpeleothemClusterConfiguration {
534    pub base_block: BlockStateData,
535    pub pointed_block: BlockStateData,
536    pub replaceable_blocks: BlockHolderSet,
537    pub floor_to_ceiling_search_range: i32,
538    pub height: IntProvider,
539    pub radius: IntProvider,
540    pub max_stalagmite_stalactite_height_diff: i32,
541    pub height_deviation: i32,
542    pub speleothem_block_layer_thickness: IntProvider,
543    pub density: FloatProvider,
544    pub wetness: FloatProvider,
545    pub chance_of_speleothem_at_max_distance_from_center: f32,
546    pub max_distance_from_edge_affecting_chance_of_speleothem: i32,
547    pub max_distance_from_center_affecting_height_bias: i32,
548}
549
550#[derive(Debug, Clone)]
551pub struct SpeleothemConfiguration {
552    pub base_block: BlockStateData,
553    pub pointed_block: BlockStateData,
554    pub replaceable_blocks: BlockHolderSet,
555    pub chance_of_taller_generation: f32,
556    pub chance_of_directional_spread: f32,
557    pub chance_of_spread_radius2: f32,
558    pub chance_of_spread_radius3: f32,
559}
560
561#[derive(Debug, Clone)]
562pub struct EndGatewayConfiguration {
563    pub exit: Option<Offset>,
564    pub exact: bool,
565}
566
567#[derive(Debug, Clone)]
568pub struct EndSpikeConfiguration {
569    pub spikes: Vec<EndSpike>,
570    pub crystal_invulnerable: bool,
571    pub crystal_beam_target: Option<Offset>,
572}
573
574#[derive(Debug, Clone)]
575pub struct EndSpike {
576    pub center_x: i32,
577    pub center_z: i32,
578    pub radius: i32,
579    pub height: i32,
580    pub guarded: bool,
581}
582
583#[derive(Debug, Clone)]
584pub struct FallenTreeConfiguration {
585    pub trunk_provider: BlockStateProviderKind,
586    pub log_length: IntProvider,
587    pub stump_decorators: Vec<TreeDecorator>,
588    pub log_decorators: Vec<TreeDecorator>,
589}
590
591#[derive(Debug, Clone)]
592pub struct FossilConfiguration {
593    pub fossil_structures: Vec<Identifier>,
594    pub overlay_structures: Vec<Identifier>,
595    pub fossil_processors: Identifier,
596    pub overlay_processors: Identifier,
597    pub max_empty_corners_allowed: i32,
598}
599
600#[derive(Debug, Clone)]
601pub struct GeodeConfiguration {
602    pub blocks: GeodeBlockSettings,
603    pub layers: GeodeLayerSettings,
604    pub crack: GeodeCrackSettings,
605    pub use_potential_placements_chance: f64,
606    pub use_alternate_layer0_chance: f64,
607    pub placements_require_layer0_alternate: bool,
608    pub outer_wall_distance: IntProvider,
609    pub distribution_points: IntProvider,
610    pub point_offset: IntProvider,
611    pub min_gen_offset: i32,
612    pub max_gen_offset: i32,
613    pub invalid_blocks_threshold: i32,
614    pub noise_multiplier: f64,
615}
616
617#[derive(Debug, Clone)]
618pub struct GeodeBlockSettings {
619    pub filling_provider: BlockStateProviderKind,
620    pub inner_layer_provider: BlockStateProviderKind,
621    pub alternate_inner_layer_provider: BlockStateProviderKind,
622    pub middle_layer_provider: BlockStateProviderKind,
623    pub outer_layer_provider: BlockStateProviderKind,
624    pub inner_placements: Vec<BlockStateData>,
625    pub cannot_replace: Identifier,
626    pub invalid_blocks: Identifier,
627}
628
629#[derive(Debug, Clone)]
630pub struct GeodeLayerSettings {
631    pub filling: f64,
632    pub inner_layer: f64,
633    pub middle_layer: f64,
634    pub outer_layer: f64,
635}
636
637#[derive(Debug, Clone)]
638pub struct GeodeCrackSettings {
639    pub generate_crack_chance: f64,
640    pub base_crack_size: f64,
641    pub crack_point_offset: i32,
642}
643
644#[derive(Debug, Clone)]
645pub struct HugeMushroomConfiguration {
646    pub cap_provider: BlockStateProviderKind,
647    pub stem_provider: BlockStateProviderKind,
648    pub foliage_radius: i32,
649    pub can_place_on: BlockPredicate,
650}
651
652#[derive(Debug, Clone)]
653pub struct HugeFungusConfiguration {
654    pub valid_base_block: BlockStateData,
655    pub stem_state: BlockStateData,
656    pub hat_state: BlockStateData,
657    pub decor_state: BlockStateData,
658    pub replaceable_blocks: BlockPredicate,
659    pub planted: bool,
660}
661
662#[derive(Debug, Clone)]
663pub struct LakeConfiguration {
664    pub fluid: BlockStateProviderKind,
665    pub barrier: BlockStateProviderKind,
666    pub can_place_feature: BlockPredicate,
667    pub can_replace_with_air_or_fluid: BlockPredicate,
668    pub can_replace_with_barrier: BlockPredicate,
669}
670
671#[derive(Debug, Clone)]
672pub struct LargeDripstoneConfiguration {
673    pub replaceable_blocks: BlockHolderSet,
674    pub floor_to_ceiling_search_range: i32,
675    pub column_radius: IntProvider,
676    pub height_scale: FloatProvider,
677    pub max_column_radius_to_cave_height_ratio: f32,
678    pub stalactite_bluntness: FloatProvider,
679    pub stalagmite_bluntness: FloatProvider,
680    pub wind_speed: FloatProvider,
681    pub min_radius_for_wind: i32,
682    pub min_bluntness_for_wind: f32,
683}
684
685#[derive(Debug, Clone)]
686pub struct MultifaceGrowthConfiguration {
687    pub block: BlockRef,
688    pub search_range: i32,
689    pub can_place_on_floor: bool,
690    pub can_place_on_ceiling: bool,
691    pub can_place_on_wall: bool,
692    pub chance_of_spreading: f32,
693    pub can_be_placed_on: Vec<BlockRef>,
694}
695
696#[derive(Debug, Clone)]
697pub struct NetherForestVegetationConfiguration {
698    pub state_provider: BlockStateProviderKind,
699    pub spread_width: i32,
700    pub spread_height: i32,
701}
702
703#[derive(Debug, Clone)]
704pub struct NetherrackReplaceBlobsConfiguration {
705    pub target: BlockStateData,
706    pub state: BlockStateData,
707    pub radius: IntProvider,
708}
709
710#[derive(Debug, Clone)]
711pub struct OreConfiguration {
712    pub targets: Vec<OreTarget>,
713    pub size: i32,
714    pub discard_chance_on_air_exposure: f32,
715}
716
717#[derive(Debug, Clone)]
718pub struct OreTarget {
719    /// Vanilla's shared `RuleTest` type (`net.minecraft.world.level.levelgen.structure.templatesystem.RuleTest`)
720    /// — the same predicate tree used by structure processors' `input_predicate`/`location_predicate`.
721    pub target: crate::structure::processor::data::StructureRuleTestData,
722    pub state: BlockStateData,
723}
724
725#[derive(Debug, Clone)]
726pub struct PointedDripstoneConfiguration {
727    pub chance_of_taller_dripstone: f32,
728    pub chance_of_directional_spread: f32,
729    pub chance_of_spread_radius2: f32,
730    pub chance_of_spread_radius3: f32,
731}
732
733#[derive(Debug, Clone)]
734pub struct RandomBooleanSelectorConfiguration {
735    pub feature_true: PlacedFeatureRef,
736    pub feature_false: PlacedFeatureRef,
737}
738
739#[derive(Debug, Clone)]
740pub struct RandomSelectorConfiguration {
741    pub features: Vec<WeightedPlacedFeature>,
742    pub default: PlacedFeatureRef,
743}
744
745#[derive(Debug, Clone)]
746pub struct WeightedPlacedFeature {
747    pub chance: f32,
748    pub feature: PlacedFeatureRef,
749}
750
751#[derive(Debug, Clone)]
752pub struct WeightedRandomFeatureConfiguration {
753    pub features: Vec<WeightedRandomPlacedFeature>,
754}
755
756#[derive(Debug, Clone)]
757pub struct WeightedRandomPlacedFeature {
758    pub data: PlacedFeatureRef,
759    pub weight: u32,
760}
761
762#[derive(Debug, Clone)]
763pub struct SimpleRandomSelectorConfiguration {
764    pub features: Vec<PlacedFeatureRef>,
765}
766
767#[derive(Debug, Clone)]
768pub struct CompositeFeatureConfiguration {
769    pub features: Vec<PlacedFeatureRef>,
770}
771
772#[derive(Debug, Clone)]
773pub struct RootSystemConfiguration {
774    pub feature: PlacedFeatureRef,
775    pub required_vertical_space_for_tree: i32,
776    pub level_test_distance: i32,
777    pub max_level_deviation: i32,
778    pub root_radius: i32,
779    pub root_placement_attempts: i32,
780    pub root_column_max_height: i32,
781    pub hanging_root_radius: i32,
782    pub hanging_roots_vertical_span: i32,
783    pub hanging_root_placement_attempts: i32,
784    pub allowed_vertical_water_for_tree: i32,
785    pub root_state_provider: BlockStateProviderKind,
786    pub hanging_root_state_provider: BlockStateProviderKind,
787    pub root_replaceable: BlockHolderSet,
788    pub allowed_tree_position: BlockPredicate,
789}
790
791#[derive(Debug, Clone)]
792pub struct SculkPatchConfiguration {
793    pub charge_count: i32,
794    pub amount_per_charge: i32,
795    pub spread_attempts: i32,
796    pub growth_rounds: i32,
797    pub spread_rounds: i32,
798}
799
800#[derive(Debug, Clone)]
801pub struct SeaPickleConfiguration {
802    pub count: IntProvider,
803}
804
805#[derive(Debug, Clone)]
806pub struct SeagrassConfiguration {
807    pub probability: f32,
808}
809
810#[derive(Debug, Clone)]
811pub struct SimpleBlockConfiguration {
812    pub to_place: BlockStateProviderKind,
813    pub schedule_tick: bool,
814}
815
816#[derive(Debug, Clone)]
817pub struct SpikeConfiguration {
818    pub state: BlockStateData,
819    pub can_place_on: BlockPredicate,
820    pub can_replace: BlockPredicate,
821}
822
823#[derive(Debug, Clone)]
824pub struct SpringConfiguration {
825    pub state: FluidStateData,
826    pub requires_block_below: bool,
827    pub rock_count: i32,
828    pub hole_count: i32,
829    pub valid_blocks: BlockHolderSet,
830}
831
832#[derive(Debug, Clone)]
833pub struct TemplateFeatureConfiguration {
834    pub templates: Vec<WeightedTemplateEntry>,
835    /// Structure processors applied after placing the template. Only the
836    /// inline (`{"processors": [...]}`) shape appears in extracted data —
837    /// a bare registry-reference string isn't modeled yet.
838    pub processors: Option<crate::structure::processor::data::StructureProcessorListData>,
839}
840
841#[derive(Debug, Clone)]
842pub struct WeightedTemplateEntry {
843    pub data: TemplateEntry,
844    pub weight: u32,
845}
846
847#[derive(Debug, Clone)]
848pub struct TemplateEntry {
849    pub id: Identifier,
850    pub rotations: Vec<Rotation>,
851}
852
853#[derive(Debug, Clone)]
854pub struct TreeConfiguration {
855    pub trunk_provider: BlockStateProviderKind,
856    pub below_trunk_provider: BlockStateProviderKind,
857    pub foliage_provider: BlockStateProviderKind,
858    pub trunk_placer: TrunkPlacer,
859    pub foliage_placer: FoliagePlacer,
860    pub minimum_size: FeatureSize,
861    pub decorators: Vec<TreeDecorator>,
862    pub root_placer: Option<RootPlacer>,
863    pub ignore_vines: bool,
864}
865
866#[derive(Debug, Clone)]
867pub enum TrunkPlacer {
868    Straight(TrunkPlacerBase),
869    Giant(TrunkPlacerBase),
870    Fancy(TrunkPlacerBase),
871    Forking(TrunkPlacerBase),
872    DarkOak(TrunkPlacerBase),
873    MegaJungle(TrunkPlacerBase),
874    Bending(BendingTrunkPlacer),
875    UpwardsBranching(UpwardsBranchingTrunkPlacer),
876    Cherry(CherryTrunkPlacer),
877    Poplar(PoplarTrunkPlacer),
878}
879
880#[derive(Debug, Clone)]
881pub struct PoplarTrunkPlacer {
882    pub base_height: i32,
883    pub height_rand_a: i32,
884    pub height_rand_b: i32,
885    pub trunk_height_above_branches: IntProvider,
886    pub branch_amount: IntProvider,
887}
888
889#[derive(Debug, Clone)]
890pub struct TrunkPlacerBase {
891    pub base_height: i32,
892    pub height_rand_a: i32,
893    pub height_rand_b: i32,
894}
895
896#[derive(Debug, Clone)]
897pub struct BendingTrunkPlacer {
898    pub base_height: i32,
899    pub height_rand_a: i32,
900    pub height_rand_b: i32,
901    pub min_height_for_leaves: i32,
902    pub bend_length: IntProvider,
903}
904
905#[derive(Debug, Clone)]
906pub struct UpwardsBranchingTrunkPlacer {
907    pub base_height: i32,
908    pub height_rand_a: i32,
909    pub height_rand_b: i32,
910    pub extra_branch_steps: IntProvider,
911    pub extra_branch_length: IntProvider,
912    pub place_branch_per_log_probability: f32,
913    pub can_grow_through: Identifier,
914}
915
916#[derive(Debug, Clone)]
917pub struct CherryTrunkPlacer {
918    pub base_height: i32,
919    pub height_rand_a: i32,
920    pub height_rand_b: i32,
921    pub branch_count: IntProvider,
922    pub branch_horizontal_length: IntProvider,
923    pub branch_start_offset_from_top: UniformIntProvider,
924    pub branch_end_offset_from_top: IntProvider,
925}
926
927#[derive(Debug, Clone)]
928pub enum FoliagePlacer {
929    Blob(BlobFoliagePlacer),
930    Spruce(SpruceFoliagePlacer),
931    Pine(PineFoliagePlacer),
932    Acacia(FoliagePlacerBase),
933    Bush(BlobFoliagePlacer),
934    Fancy(BlobFoliagePlacer),
935    Jungle(BlobFoliagePlacer),
936    MegaPine(MegaPineFoliagePlacer),
937    DarkOak(FoliagePlacerBase),
938    RandomSpread(RandomSpreadFoliagePlacer),
939    Cherry(CherryFoliagePlacer),
940    Poplar(PoplarFoliagePlacer),
941}
942
943#[derive(Debug, Clone)]
944pub struct PoplarFoliagePlacer {
945    pub radius: IntProvider,
946    pub offset: IntProvider,
947    pub height: IntProvider,
948    pub side_hole_chance: f32,
949}
950
951#[derive(Debug, Clone)]
952pub struct FoliagePlacerBase {
953    pub radius: IntProvider,
954    pub offset: IntProvider,
955}
956
957#[derive(Debug, Clone)]
958pub struct BlobFoliagePlacer {
959    pub radius: IntProvider,
960    pub offset: IntProvider,
961    pub height: IntProvider,
962}
963
964#[derive(Debug, Clone)]
965pub struct SpruceFoliagePlacer {
966    pub radius: IntProvider,
967    pub offset: IntProvider,
968    pub trunk_height: IntProvider,
969}
970
971#[derive(Debug, Clone)]
972pub struct PineFoliagePlacer {
973    pub radius: IntProvider,
974    pub offset: IntProvider,
975    pub height: IntProvider,
976}
977
978#[derive(Debug, Clone)]
979pub struct MegaPineFoliagePlacer {
980    pub radius: IntProvider,
981    pub offset: IntProvider,
982    pub crown_height: IntProvider,
983}
984
985#[derive(Debug, Clone)]
986pub struct RandomSpreadFoliagePlacer {
987    pub radius: IntProvider,
988    pub offset: IntProvider,
989    pub foliage_height: i32,
990    pub leaf_placement_attempts: i32,
991}
992
993#[derive(Debug, Clone)]
994pub struct CherryFoliagePlacer {
995    pub radius: IntProvider,
996    pub offset: IntProvider,
997    pub height: IntProvider,
998    pub wide_bottom_layer_hole_chance: f32,
999    pub corner_hole_chance: f32,
1000    pub hanging_leaves_chance: f32,
1001    pub hanging_leaves_extension_chance: f32,
1002}
1003
1004#[derive(Debug, Clone)]
1005pub enum FeatureSize {
1006    TwoLayers(TwoLayersFeatureSize),
1007    ThreeLayers(ThreeLayersFeatureSize),
1008}
1009
1010#[derive(Debug, Clone)]
1011pub struct TwoLayersFeatureSize {
1012    pub limit: i32,
1013    pub lower_size: i32,
1014    pub upper_size: i32,
1015    pub min_clipped_height: Option<i32>,
1016}
1017
1018#[derive(Debug, Clone)]
1019pub struct ThreeLayersFeatureSize {
1020    pub limit: i32,
1021    pub lower_size: i32,
1022    pub middle_size: i32,
1023    pub upper_limit: i32,
1024    pub upper_size: i32,
1025    pub min_clipped_height: Option<i32>,
1026}
1027
1028#[derive(Debug, Clone)]
1029pub enum RootPlacer {
1030    Mangrove(MangroveRootPlacer),
1031}
1032
1033#[derive(Debug, Clone)]
1034pub struct MangroveRootPlacer {
1035    pub trunk_offset_y: IntProvider,
1036    pub root_provider: BlockStateProviderKind,
1037    pub above_root_placement: AboveRootPlacement,
1038    pub mangrove_root_placement: MangroveRootPlacement,
1039}
1040
1041#[derive(Debug, Clone)]
1042pub struct AboveRootPlacement {
1043    pub above_root_provider: BlockStateProviderKind,
1044    pub above_root_placement_chance: f32,
1045}
1046
1047#[derive(Debug, Clone)]
1048pub struct MangroveRootPlacement {
1049    pub can_grow_through: Identifier,
1050    pub muddy_roots_in: Vec<Identifier>,
1051    pub muddy_roots_provider: BlockStateProviderKind,
1052    pub max_root_width: i32,
1053    pub max_root_length: i32,
1054    pub random_skew_chance: f32,
1055}
1056
1057#[derive(Debug, Clone)]
1058pub enum TreeDecorator {
1059    AlterGround {
1060        provider: BlockStateProviderKind,
1061    },
1062    Beehive {
1063        probability: f32,
1064    },
1065    Cocoa {
1066        probability: f32,
1067    },
1068    CreakingHeart {
1069        probability: f32,
1070    },
1071    LeaveVine {
1072        probability: f32,
1073    },
1074    TrunkVine,
1075    AttachedToLeaves(AttachedToLeavesDecorator),
1076    AttachedToLogs(AttachedToLogsDecorator),
1077    PlaceOnGround(PlaceOnGroundDecorator),
1078    PaleMoss {
1079        leaves_probability: f32,
1080        trunk_probability: f32,
1081        ground_probability: f32,
1082    },
1083    ShelfMushroom {
1084        probability: f32,
1085    },
1086}
1087
1088#[derive(Debug, Clone)]
1089pub struct AttachedToLeavesDecorator {
1090    pub probability: f32,
1091    pub exclusion_radius_xz: i32,
1092    pub exclusion_radius_y: i32,
1093    pub required_empty_blocks: i32,
1094    pub block_provider: BlockStateProviderKind,
1095    pub directions: Vec<Direction>,
1096}
1097
1098#[derive(Debug, Clone)]
1099pub struct AttachedToLogsDecorator {
1100    pub probability: f32,
1101    pub block_provider: BlockStateProviderKind,
1102    pub directions: Vec<Direction>,
1103}
1104
1105#[derive(Debug, Clone)]
1106pub struct PlaceOnGroundDecorator {
1107    pub block_state_provider: BlockStateProviderKind,
1108    pub tries: i32,
1109    pub radius: i32,
1110    pub height: i32,
1111}
1112
1113#[derive(Debug, Clone)]
1114pub struct TwistingVinesConfiguration {
1115    pub spread_width: i32,
1116    pub spread_height: i32,
1117    pub max_height: i32,
1118}
1119
1120#[derive(Debug, Clone)]
1121pub struct UnderwaterMagmaConfiguration {
1122    pub floor_search_range: i32,
1123    pub placement_radius_around_floor: i32,
1124    pub placement_probability_per_valid_position: f32,
1125}
1126
1127#[derive(Debug, Clone)]
1128pub struct VegetationPatchConfiguration {
1129    pub replaceable: Identifier,
1130    pub ground_state: BlockStateProviderKind,
1131    pub vegetation_feature: PlacedFeatureRef,
1132    pub surface: VerticalSurface,
1133    pub depth: IntProvider,
1134    pub extra_bottom_block_chance: f32,
1135    pub vertical_range: i32,
1136    pub vegetation_chance: f32,
1137    pub xz_radius: IntProvider,
1138    pub extra_edge_column_chance: f32,
1139}
1140
1141/// Vertical surface used by vegetation patches.
1142#[derive(Debug, Clone, Copy, PartialEq, Eq)]
1143pub enum VerticalSurface {
1144    Floor,
1145    Ceiling,
1146}