Skip to main content

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}