Pumpkin/pumpkin-world/src/biome/mod.rs
Alexander Medvedev 1d671504d1 fix: tests
2026-04-29 23:18:24 +02:00

163 lines
5.3 KiB
Rust

use sha2::{Digest, Sha256};
use std::cell::RefCell;
use enum_dispatch::enum_dispatch;
use pumpkin_data::chunk::{Biome, BiomeTree, NETHER_BIOME_SOURCE, OVERWORLD_BIOME_SOURCE};
use crate::generation::noise::router::multi_noise_sampler::MultiNoiseSampler;
pub mod end;
pub mod multi_noise;
pub mod position_finder;
thread_local! {
/// A shortcut; check if last used biome is what we should use
static LAST_RESULT_NODE: RefCell<Option<&'static BiomeTree>> = const {RefCell::new(None) };
}
#[enum_dispatch]
pub trait BiomeSupplier {
fn biome(&self, x: i32, y: i32, z: i32, noise: &mut MultiNoiseSampler<'_>) -> &'static Biome;
}
#[derive(Clone, Copy)]
pub struct MultiNoiseBiomeSupplier {
source: &'static BiomeTree,
}
impl MultiNoiseBiomeSupplier {
pub const OVERWORLD: Self = Self::new(&OVERWORLD_BIOME_SOURCE);
pub const NETHER: Self = Self::new(&NETHER_BIOME_SOURCE);
const fn new(source: &'static BiomeTree) -> Self {
Self { source }
}
}
impl BiomeSupplier for MultiNoiseBiomeSupplier {
fn biome(&self, x: i32, y: i32, z: i32, noise: &mut MultiNoiseSampler<'_>) -> &'static Biome {
let point = noise.sample(x, y, z);
let point_list = point.convert_to_list();
LAST_RESULT_NODE.with_borrow_mut(|last_result| self.source.get(&point_list, last_result))
}
}
#[must_use]
pub fn hash_seed(seed: u64) -> i64 {
let mut hasher = Sha256::new();
hasher.update(seed.to_le_bytes());
let result = hasher.finalize();
i64::from_le_bytes(result[..8].try_into().unwrap())
}
#[cfg(test)]
mod test {
use pumpkin_data::{chunk::Biome, dimension::Dimension};
use pumpkin_util::read_data_from_file;
use serde::Deserialize;
use crate::{
ProtoChunk,
chunk::palette::BIOME_NETWORK_MAX_BITS,
generation::noise::router::multi_noise_sampler::{
MultiNoiseSampler, MultiNoiseSamplerBuilderOptions,
},
};
use super::{BiomeSupplier, MultiNoiseBiomeSupplier, hash_seed};
#[test]
fn biome_desert() {
use crate::generation::generator::{GeneratorInit, VanillaGenerator};
use pumpkin_util::world_seed::Seed;
let seed = 13579;
let generator = VanillaGenerator::new(Seed(seed as u64), Dimension::OVERWORLD);
let multi_noise_config = MultiNoiseSamplerBuilderOptions::new(1, 1, 1);
let mut sampler =
MultiNoiseSampler::generate(&generator.base_router.multi_noise, &multi_noise_config);
let biome = MultiNoiseBiomeSupplier::OVERWORLD.biome(-24, 1, 8, &mut sampler);
assert_eq!(biome, &Biome::DESERT);
}
#[test]
fn wide_area_surface() {
use crate::generation::noise::router::multi_noise_sampler::{
MultiNoiseSampler, MultiNoiseSamplerBuilderOptions,
};
use crate::generation::{biome_coords, positions::chunk_pos};
#[derive(Deserialize)]
struct BiomeData {
x: i32,
z: i32,
data: Vec<(i32, i32, i32, u8)>,
}
let expected_data: Vec<BiomeData> =
read_data_from_file!("../../assets/biome_no_blend_no_beard_0.json");
let seed = 0;
use crate::generation::generator::{GeneratorInit, VanillaGenerator};
use pumpkin_util::world_seed::Seed;
let generator = VanillaGenerator::new(Seed(seed as u64), Dimension::OVERWORLD);
for data in expected_data {
let chunk_x = data.x;
let chunk_z = data.z;
let mut chunk = ProtoChunk::new(chunk_x, chunk_z, &generator);
// Create MultiNoiseSampler for populate_biomes
let start_x = chunk_pos::start_block_x(chunk_x);
let start_z = chunk_pos::start_block_z(chunk_z);
let horizontal_biome_end = biome_coords::from_block(16);
let multi_noise_config = MultiNoiseSamplerBuilderOptions::new(
biome_coords::from_block(start_x),
biome_coords::from_block(start_z),
horizontal_biome_end as usize,
);
let mut multi_noise_sampler = MultiNoiseSampler::generate(
&generator.base_router.multi_noise,
&multi_noise_config,
);
chunk.populate_biomes(&generator, &mut multi_noise_sampler);
for (biome_x, biome_y, biome_z, biome_id) in data.data {
let calculated_biome = chunk.get_biome(biome_x, biome_y, biome_z);
assert_eq!(
biome_id,
calculated_biome.id,
"Expected {:?} was {:?} at {},{},{} ({},{})",
Biome::from_id(biome_id),
calculated_biome,
biome_x,
biome_y,
biome_z,
data.x,
data.z
);
}
}
}
#[test]
fn hash_seed_test() {
let hashed_seed = hash_seed(0);
assert_eq!(8794265229978523055, hashed_seed);
let hashed_seed = hash_seed((-777i64) as u64);
assert_eq!(-1087248400229165450, hashed_seed);
}
#[test]
fn proper_network_bits_per_entry() {
let id_to_test = 1 << BIOME_NETWORK_MAX_BITS;
assert!(
Biome::from_id(id_to_test).is_none(),
"We need to update our constants!"
);
}
}