steel_worldgen/density/mod.rs
1//! Density function types and transpiler for world generation.
2//!
3//! Density functions form a tree structure parsed from JSON at build time.
4//! The transpiler compiles these trees into native Rust code — runtime evaluation
5//! is done by the transpiled output, not by interpreting this tree.
6//!
7//! # Key Types
8//!
9//! - [`DensityFunction`] - The density function enum with all operation types
10//! - [`NoiseRouter`] - Collection of all density functions for world generation
11//! - [`CubicSpline`] - Cubic spline interpolation for smooth terrain transitions
12//! - [`RarityValueMapper`] - Used at runtime by transpiled cave generation code
13//! - [`DimensionNoises`] - Trait for dimension-specific noise generators
14//! - [`NoiseSettings`] - Trait for dimension-specific settings from datapack
15
16use crate::noise::NormalNoise;
17use crate::random::RandomSplitter;
18
19pub mod spline_eval;
20pub mod traits;
21
22pub use traits::{ColumnCache, DimensionNoises, NoiseSettings};
23
24/// Parameters for creating a noise generator.
25///
26/// Mirrors vanilla's `NormalNoise.Parameters` codec, used directly by datapack
27/// `worldgen/noise/*.json` entries.
28#[derive(Debug, Clone)]
29pub struct NoiseParameters {
30 /// Amplitude at the base octave, before persistence falloff.
31 pub base_amplitude: f64,
32 /// The first (lowest-frequency) octave level.
33 pub base_octave: i32,
34 /// Number of octaves.
35 pub octave_count: i32,
36 /// Whether to apply persistence normalization (`Normalization.ENABLED`).
37 pub normalize: bool,
38 /// Per-octave amplitude multipliers. Empty means "all `1.0`".
39 pub amplitude_modifiers: Vec<f64>,
40}
41
42impl NoiseParameters {
43 /// Create new noise parameters.
44 #[must_use]
45 pub const fn new(
46 base_amplitude: f64,
47 base_octave: i32,
48 octave_count: i32,
49 normalize: bool,
50 amplitude_modifiers: Vec<f64>,
51 ) -> Self {
52 Self {
53 base_amplitude,
54 base_octave,
55 octave_count,
56 normalize,
57 amplitude_modifiers,
58 }
59 }
60
61 /// Create a [`NormalNoise`] generator from these parameters, seeded from `splitter`
62 /// under the given noise `id`.
63 #[must_use]
64 pub fn create(&self, splitter: &RandomSplitter, id: &str) -> NormalNoise {
65 NormalNoise::create_with_params(
66 splitter,
67 id,
68 self.base_octave,
69 self.base_amplitude,
70 self.octave_count,
71 self.normalize,
72 &self.amplitude_modifiers,
73 )
74 }
75}
76
77/// Rarity value mapper for cave generation.
78///
79/// Used at runtime by transpiled `WeirdScaledSampler` code.
80#[derive(Debug, Clone, Copy, PartialEq, Eq)]
81pub enum RarityValueMapper {
82 /// Mapper type `"type_1"` for tunnels.
83 Tunnels,
84 /// Mapper type `"type_2"` for caves.
85 Caves,
86}
87
88impl RarityValueMapper {
89 /// Get the scaling factor for this mapper based on rarity value.
90 ///
91 /// From vanilla `NoiseRouterData.QuantizedSpaghettiRarity`.
92 #[must_use]
93 pub fn get_values(self, rarity: f32) -> f32 {
94 match self {
95 Self::Tunnels => {
96 if rarity < -0.5 {
97 0.75
98 } else if rarity < 0.0 {
99 1.0
100 } else if rarity < 0.5 {
101 1.5
102 } else {
103 2.0
104 }
105 }
106 Self::Caves => {
107 if rarity < -0.75 {
108 0.5
109 } else if rarity < -0.5 {
110 0.75
111 } else if rarity < 0.5 {
112 1.0
113 } else if rarity < 0.75 {
114 2.0
115 } else {
116 3.0
117 }
118 }
119 }
120 }
121}