use std::sync::LazyLock; use serde::Deserialize; use crate::{noise::simplex::OctaveSimplexNoiseSampler, random::legacy_rand::LegacyRand}; pub static TEMPERATURE_NOISE: LazyLock = LazyLock::new(|| { let mut rand = LegacyRand::from_seed(1234); OctaveSimplexNoiseSampler::new(&mut rand, &[0]) }); pub static FROZEN_OCEAN_NOISE: LazyLock = LazyLock::new(|| { let mut rand = LegacyRand::from_seed(3456); OctaveSimplexNoiseSampler::new(&mut rand, &[-2, -1, 0]) }); pub static FOLIAGE_NOISE: LazyLock = LazyLock::new(|| { let mut rand = LegacyRand::from_seed(2345); OctaveSimplexNoiseSampler::new(&mut rand, &[0]) }); #[derive(Clone, Deserialize, Copy, Hash, PartialEq, Eq, Debug)] #[serde(rename_all = "UPPERCASE")] pub enum TemperatureModifier { None, Frozen, } impl TemperatureModifier { pub fn convert_temperature(&self, x: f64, z: f64, temperature: f32) -> f32 { match self { Self::None => temperature, Self::Frozen => { let frozen_ocean_sample = FROZEN_OCEAN_NOISE.sample(x * 0.05, z * 0.05, false) * 7.0; let foliage_sample = FOLIAGE_NOISE.sample(x * 0.2, z * 0.2, false); let threshold = frozen_ocean_sample + foliage_sample; if threshold < 0.3 { let foliage_sample = FOLIAGE_NOISE.sample(x * 0.09, z * 0.09, false); if foliage_sample < 0.8 { return 0.2f32; } } temperature } } } } #[derive(Clone, Debug)] pub struct Weather { #[expect(dead_code)] has_precipitation: bool, temperature: f32, temperature_modifier: TemperatureModifier, #[expect(dead_code)] downfall: f32, } impl Weather { #[must_use] pub const fn new( has_precipitation: bool, temperature: f32, temperature_modifier: TemperatureModifier, downfall: f32, ) -> Self { Self { has_precipitation, temperature, temperature_modifier, downfall, } } /// This is an expensive function and should be cached pub fn compute_temperature(&self, x: f64, y: i32, z: f64, sea_level: i32) -> f32 { let modified_temperature = self.temperature_modifier .convert_temperature(x, z, self.temperature); let offset_sea_level = sea_level + 17; if y > offset_sea_level { let temperature_noise = (TEMPERATURE_NOISE.sample(x / 8.0, z / 8.0, false) * 8.0) as f32; modified_temperature - (temperature_noise + y as f32 - offset_sea_level as f32) * 0.05f32 / 40.0f32 } else { modified_temperature } } }