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