From 1d671504d1904011f2a84bbb2c1ec46c0872f057 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Wed, 29 Apr 2026 23:18:24 +0200 Subject: [PATCH] fix: tests --- pumpkin-util/src/random/mod.rs | 9 +- pumpkin-util/src/random/xoroshiro128.rs | 2 +- pumpkin-world/src/biome/mod.rs | 50 ++-- pumpkin-world/src/biome/multi_noise.rs | 47 +--- pumpkin-world/src/chunk_system/generation.rs | 23 +- .../src/chunk_system/generation_cache.rs | 67 ++--- .../src/chunk_system/worker_logic.rs | 35 +-- pumpkin-world/src/generation/generator/mod.rs | 28 +- .../src/generation/noise/aquifer_sampler.rs | 256 +++++++++--------- pumpkin-world/src/generation/noise/perlin.rs | 32 ++- pumpkin-world/src/generation/proto_chunk.rs | 144 ++++------ pumpkin-world/src/lib.rs | 96 +++---- 12 files changed, 369 insertions(+), 420 deletions(-) diff --git a/pumpkin-util/src/random/mod.rs b/pumpkin-util/src/random/mod.rs index 7ad8c285a..009c6af49 100644 --- a/pumpkin-util/src/random/mod.rs +++ b/pumpkin-util/src/random/mod.rs @@ -231,14 +231,15 @@ pub trait RandomDeriverImpl { /// # Returns /// A 64-bit hash value. #[must_use] -pub fn hash_block_pos(x: i32, y: i32, z: i32) -> i64 { - let l = i64::from(x.wrapping_mul(3129871)) - ^ (i64::from(z).wrapping_mul(116129781i64)) - ^ i64::from(y); +pub const fn hash_block_pos(x: i32, y: i32, z: i32) -> i64 { + let l = + ((x.wrapping_mul(3129871)) as i64) ^ ((z as i64).wrapping_mul(116129781i64)) ^ (y as i64); + let l = l .wrapping_mul(l) .wrapping_mul(42317861i64) .wrapping_add(l.wrapping_mul(11i64)); + l >> 16 } diff --git a/pumpkin-util/src/random/xoroshiro128.rs b/pumpkin-util/src/random/xoroshiro128.rs index 7828b1101..bf39c61c8 100644 --- a/pumpkin-util/src/random/xoroshiro128.rs +++ b/pumpkin-util/src/random/xoroshiro128.rs @@ -240,7 +240,7 @@ impl XoroshiroSplitter { } #[must_use] - pub fn split_pos(&self, x: i32, y: i32, z: i32) -> Xoroshiro { + pub const fn split_pos(&self, x: i32, y: i32, z: i32) -> Xoroshiro { let l = hash_block_pos(x, y, z) as u64; let m = l ^ self.lo; diff --git a/pumpkin-world/src/biome/mod.rs b/pumpkin-world/src/biome/mod.rs index e2f9e0a19..b3bb0c15d 100644 --- a/pumpkin-world/src/biome/mod.rs +++ b/pumpkin-world/src/biome/mod.rs @@ -51,19 +51,15 @@ pub fn hash_seed(seed: u64) -> i64 { #[cfg(test)] mod test { - use pumpkin_data::{ - chunk::Biome, chunk_gen_settings::GenerationSettings, dimension::Dimension, - noise_router::OVERWORLD_BASE_NOISE_ROUTER, - }; + use pumpkin_data::{chunk::Biome, dimension::Dimension}; use pumpkin_util::read_data_from_file; use serde::Deserialize; use crate::{ - GlobalRandomConfig, ProtoChunk, + ProtoChunk, chunk::palette::BIOME_NETWORK_MAX_BITS, - generation::noise::router::{ - multi_noise_sampler::{MultiNoiseSampler, MultiNoiseSamplerBuilderOptions}, - proto_noise_router::ProtoNoiseRouters, + generation::noise::router::multi_noise_sampler::{ + MultiNoiseSampler, MultiNoiseSamplerBuilderOptions, }, }; @@ -71,20 +67,19 @@ mod test { #[test] fn biome_desert() { + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; + use pumpkin_util::world_seed::Seed; let seed = 13579; - let random_config = GlobalRandomConfig::new(seed, false); - let noise_router = - ProtoNoiseRouters::generate(&OVERWORLD_BASE_NOISE_ROUTER, &random_config); + let generator = VanillaGenerator::new(Seed(seed as u64), Dimension::OVERWORLD); let multi_noise_config = MultiNoiseSamplerBuilderOptions::new(1, 1, 1); let mut sampler = - MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config); + 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::biome::hash_seed; use crate::generation::noise::router::multi_noise_sampler::{ MultiNoiseSampler, MultiNoiseSamplerBuilderOptions, }; @@ -100,28 +95,15 @@ mod test { read_data_from_file!("../../assets/biome_no_blend_no_beard_0.json"); let seed = 0; - let random_config = GlobalRandomConfig::new(seed, false); - let noise_router = - ProtoNoiseRouters::generate(&OVERWORLD_BASE_NOISE_ROUTER, &random_config); - let surface_settings = GenerationSettings::from_dimension(&Dimension::OVERWORLD); - - //let _terrain_cache = TerrainCache::from_random(&random_config); - let default_block = surface_settings.default_block; + 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; - // Calculate biome mixer seed - let biome_mixer_seed = hash_seed(random_config.seed); - - let mut chunk = ProtoChunk::new( - chunk_x, - chunk_z, - &Dimension::OVERWORLD, - default_block, - biome_mixer_seed, - ); + let mut chunk = ProtoChunk::new(chunk_x, chunk_z, &generator); // Create MultiNoiseSampler for populate_biomes @@ -134,10 +116,12 @@ mod test { biome_coords::from_block(start_z), horizontal_biome_end as usize, ); - let mut multi_noise_sampler = - MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config); + let mut multi_noise_sampler = MultiNoiseSampler::generate( + &generator.base_router.multi_noise, + &multi_noise_config, + ); - chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler); + 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); diff --git a/pumpkin-world/src/biome/multi_noise.rs b/pumpkin-world/src/biome/multi_noise.rs index 859bbce86..41856e93e 100644 --- a/pumpkin-world/src/biome/multi_noise.rs +++ b/pumpkin-world/src/biome/multi_noise.rs @@ -32,31 +32,25 @@ impl NoiseValuePoint { #[cfg(test)] mod test { - use pumpkin_data::{ - chunk::Biome, chunk_gen_settings::GenerationSettings, dimension::Dimension, - noise_router::OVERWORLD_BASE_NOISE_ROUTER, - }; + use pumpkin_data::{chunk::Biome, dimension::Dimension}; use pumpkin_util::read_data_from_file; use crate::{ - GlobalRandomConfig, ProtoChunk, + ProtoChunk, biome::{BiomeSupplier, MultiNoiseBiomeSupplier}, - generation::{ - noise::router::{ - multi_noise_sampler::{MultiNoiseSampler, MultiNoiseSamplerBuilderOptions}, - proto_noise_router::ProtoNoiseRouters, - }, - proto_chunk::TerrainCache, + generation::noise::router::multi_noise_sampler::{ + MultiNoiseSampler, MultiNoiseSamplerBuilderOptions, }, }; #[test] fn sample_value() { - use crate::biome::hash_seed; + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; use crate::generation::noise::router::multi_noise_sampler::{ MultiNoiseSampler, MultiNoiseSamplerBuilderOptions, }; use crate::generation::{biome_coords, positions::chunk_pos}; + use pumpkin_util::world_seed::Seed; type PosToPoint = (i32, i32, i32, i64, i64, i64, i64, i64, i64); let expected_data: Vec = read_data_from_file!("../../assets/multi_noise_sample_no_blend_no_beard_0_0_0.json"); @@ -65,23 +59,9 @@ mod test { let chunk_x = 0; let chunk_z = 0; - let random_config = GlobalRandomConfig::new(seed, false); - let noise_router = - ProtoNoiseRouters::generate(&OVERWORLD_BASE_NOISE_ROUTER, &random_config); + let generator = VanillaGenerator::new(Seed(seed as u64), Dimension::OVERWORLD); - let surface_config = GenerationSettings::from_dimension(&Dimension::OVERWORLD); - - let _terrain_cache = TerrainCache::from_random(&random_config); - // Calculate biome mixer seed - let biome_mixer_seed = hash_seed(random_config.seed); - - let _chunk = ProtoChunk::new( - chunk_x, - chunk_z, - &Dimension::OVERWORLD, - surface_config.default_block, - biome_mixer_seed, - ); + let _chunk = ProtoChunk::new(chunk_x, chunk_z, &generator); let start_x = chunk_pos::start_block_x(chunk_x); let start_z = chunk_pos::start_block_z(chunk_z); @@ -92,7 +72,7 @@ mod test { horizontal_biome_end as usize, ); let mut multi_noise_sampler = - MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config); + MultiNoiseSampler::generate(&generator.base_router.multi_noise, &multi_noise_config); for (x, y, z, tem, hum, con, ero, dep, wei) in expected_data { let point = multi_noise_sampler.sample(x, y, z); @@ -107,16 +87,17 @@ mod test { #[test] fn sample_multinoise_biome() { + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; + use pumpkin_util::world_seed::Seed; + let expected_data: Vec<(i32, i32, i32, u8)> = read_data_from_file!("../../assets/multi_noise_biome_source_test.json"); let seed = 0; - let random_config = GlobalRandomConfig::new(seed, false); - let noise_router = - ProtoNoiseRouters::generate(&OVERWORLD_BASE_NOISE_ROUTER, &random_config); + let generator = VanillaGenerator::new(Seed(seed as u64), Dimension::OVERWORLD); let mut sampler = MultiNoiseSampler::generate( - &noise_router.multi_noise, + &generator.base_router.multi_noise, &MultiNoiseSamplerBuilderOptions::new(0, 0, 4), ); diff --git a/pumpkin-world/src/chunk_system/generation.rs b/pumpkin-world/src/chunk_system/generation.rs index 68a2c4372..52d061711 100644 --- a/pumpkin-world/src/chunk_system/generation.rs +++ b/pumpkin-world/src/chunk_system/generation.rs @@ -1,4 +1,3 @@ -use pumpkin_data::chunk_gen_settings::GenerationSettings; use pumpkin_data::dimension::Dimension; use crate::ProtoChunk; @@ -9,15 +8,14 @@ use pumpkin_config::lighting::LightingEngineConfig; use super::{Cache, Chunk, StagedChunkEnum}; pub fn generate_single_chunk( - dimension: &Dimension, - biome_mixer_seed: i64, + _dimension: &Dimension, + _biome_mixer_seed: i64, generator: &VanillaGenerator, block_registry: &dyn BlockRegistryExt, chunk_x: i32, chunk_z: i32, target_stage: StagedChunkEnum, ) -> Chunk { - let settings = GenerationSettings::from_dimension(dimension); let radius = target_stage.get_direct_radius(); let mut cache = Cache::new(chunk_x - radius, chunk_z - radius, radius * 2 + 1); @@ -27,13 +25,7 @@ pub fn generate_single_chunk( let new_x = chunk_x + dx; let new_z = chunk_z + dz; - let proto_chunk = Box::new(ProtoChunk::new( - new_x, - new_z, - dimension, - generator.default_block, - biome_mixer_seed, - )); + let proto_chunk = Box::new(ProtoChunk::new(new_x, new_z, generator)); cache.chunks.push(Chunk::Proto(proto_chunk)); } @@ -57,14 +49,9 @@ pub fn generate_single_chunk( cache.advance( stage, - &LightingEngineConfig::Default, + generator, block_registry, - settings, - &generator.random_config, - &generator.terrain_cache, - &generator.base_router, - *dimension, - &generator.global_structure_cache, + &LightingEngineConfig::Default, ); } diff --git a/pumpkin-world/src/chunk_system/generation_cache.rs b/pumpkin-world/src/chunk_system/generation_cache.rs index db2102598..8c1df464b 100644 --- a/pumpkin-world/src/chunk_system/generation_cache.rs +++ b/pumpkin-world/src/chunk_system/generation_cache.rs @@ -1,16 +1,14 @@ use super::chunk_state::{Chunk, StagedChunkEnum}; use crate::block::RawBlockState; use crate::chunk::ChunkHeightmapType; +use crate::generation::generator; use crate::generation::height_limit::HeightLimitView; -use crate::generation::proto_chunk::{GenerationCache, TerrainCache}; -use crate::generation::structure::placement::GlobalStructureCache; +use crate::generation::proto_chunk::GenerationCache; use crate::world::{BlockAccessor, BlockRegistryExt}; -use crate::{BlockStateId, GlobalRandomConfig, ProtoChunk, ProtoNoiseRouters}; +use crate::{BlockStateId, ProtoChunk}; use pumpkin_config::lighting::LightingEngineConfig; use pumpkin_data::biome::Biome; use pumpkin_data::block_properties::is_air; -use pumpkin_data::chunk_gen_settings::GenerationSettings; -use pumpkin_data::dimension::Dimension; use pumpkin_data::fluid::{Fluid, FluidState}; use pumpkin_data::{Block, BlockState}; use pumpkin_nbt::compound::NbtCompound; @@ -340,54 +338,41 @@ impl Cache { chunks: Vec::with_capacity((size * size) as usize), } } - #[expect(clippy::too_many_arguments)] pub fn advance( &mut self, stage: StagedChunkEnum, - lighting_config: &LightingEngineConfig, + generator: &generator::VanillaGenerator, block_registry: &dyn BlockRegistryExt, - settings: &GenerationSettings, - random_config: &GlobalRandomConfig, - terrain_cache: &TerrainCache, - noise_router: &ProtoNoiseRouters, - dimension: Dimension, - global_structure_cache: &GlobalStructureCache, // <--- NEW PARAMETER HERE + lighting_config: &LightingEngineConfig, ) { let mid = ((self.size * self.size) >> 1) as usize; match stage { StagedChunkEnum::Empty => panic!("empty stage"), StagedChunkEnum::StructureStart => { - self.chunks[mid].get_proto_chunk_mut().set_structure_starts( - random_config, - settings, - global_structure_cache, - ); + self.chunks[mid] + .get_proto_chunk_mut() + .set_structure_starts(generator); + } + StagedChunkEnum::StructureReferences => { + self.chunks[mid] + .get_proto_chunk_mut() + .set_structure_references(generator); } - StagedChunkEnum::StructureReferences => self.chunks[mid] - .get_proto_chunk_mut() - .set_structure_references( - random_config, - settings, - &dimension, - noise_router, - global_structure_cache, - ), // <--- PASSED HERE StagedChunkEnum::Biomes => self.chunks[mid] .get_proto_chunk_mut() - .step_to_biomes(dimension, noise_router), - StagedChunkEnum::Noise => self.chunks[mid].get_proto_chunk_mut().step_to_noise( - settings, - random_config, - noise_router, - ), - StagedChunkEnum::Surface => self.chunks[mid].get_proto_chunk_mut().step_to_surface( - settings, - random_config, - terrain_cache, - noise_router, - ), + .step_to_biomes(generator), + StagedChunkEnum::Noise => self.chunks[mid] + .get_proto_chunk_mut() + .step_to_noise(generator), + StagedChunkEnum::Surface => self.chunks[mid] + .get_proto_chunk_mut() + .step_to_surface(generator), StagedChunkEnum::Features => { - ProtoChunk::generate_features_and_structure(self, block_registry, random_config); + ProtoChunk::generate_features_and_structure( + self, + block_registry, + &generator.random_config, + ); } StagedChunkEnum::Lighting => { let mut engine = crate::lighting::LightEngine::new(); @@ -405,7 +390,7 @@ impl Cache { let chunk = self.chunks[mid].get_proto_chunk_mut(); debug_assert_eq!(chunk.stage, StagedChunkEnum::Lighting); chunk.stage = StagedChunkEnum::Full; - self.chunks[mid].upgrade_to_level_chunk(&dimension, lighting_config); + self.chunks[mid].upgrade_to_level_chunk(&generator.dimension, lighting_config); } StagedChunkEnum::None => {} } diff --git a/pumpkin-world/src/chunk_system/worker_logic.rs b/pumpkin-world/src/chunk_system/worker_logic.rs index 217867e27..73652a612 100644 --- a/pumpkin-world/src/chunk_system/worker_logic.rs +++ b/pumpkin-world/src/chunk_system/worker_logic.rs @@ -59,10 +59,7 @@ pub async fn io_read_work( level: Arc, lock: IOLock, ) { - use crate::biome::hash_seed; debug!("io read thread start"); - let biome_mixer_seed = hash_seed(level.world_gen.random_config.seed); - let dimension = &level.world_gen.dimension; // Cleaner loop and async recv while let Ok(batch) = recv.recv().await { @@ -108,12 +105,7 @@ pub async fn io_read_work( ); // Create ProtoChunk using the async method - let mut proto = ProtoChunk::from_chunk_data( - &chunk, - dimension, - level.world_gen.default_block, - biome_mixer_seed, - ); + let mut proto = ProtoChunk::from_chunk_data(&chunk, &level.world_gen); // Clear all lighting data let section_count = proto.light.sky_light.len(); @@ -144,13 +136,9 @@ pub async fn io_read_work( } } else { // Standard ProtoChunk handling for non-full chunks - let val = - RecvChunk::IO(Chunk::Proto(Box::new(ProtoChunk::from_chunk_data( - &chunk, - dimension, - level.world_gen.default_block, - biome_mixer_seed, - )))); + let val = RecvChunk::IO(Chunk::Proto(Box::new( + ProtoChunk::from_chunk_data(&chunk, &level.world_gen), + ))); if send.send((pos, val)).is_err() { break; } @@ -163,9 +151,7 @@ pub async fn io_read_work( RecvChunk::IO(Chunk::Proto(Box::new(ProtoChunk::new( pos.x, pos.y, - dimension, - level.world_gen.default_block, - biome_mixer_seed, + &level.world_gen, )))), )) .is_err() @@ -241,20 +227,15 @@ pub fn run_generation( mut cache: Cache, stage: StagedChunkEnum, level: &Level, - settings: &GenerationSettings, + _settings: &GenerationSettings, ) -> RecvChunk { // Run generation with panic catching let result = std::panic::catch_unwind(std::panic::AssertUnwindSafe(|| { cache.advance( stage, - &level.lighting_config, + &level.world_gen, level.block_registry.as_ref(), - settings, - &level.world_gen.random_config, - &level.world_gen.terrain_cache, - &level.world_gen.base_router, - level.world_gen.dimension, - &level.world_gen.global_structure_cache, + &level.lighting_config, ); cache // Return cache on success })); diff --git a/pumpkin-world/src/generation/generator/mod.rs b/pumpkin-world/src/generation/generator/mod.rs index c5afffcae..dcde0ecc8 100644 --- a/pumpkin-world/src/generation/generator/mod.rs +++ b/pumpkin-world/src/generation/generator/mod.rs @@ -15,23 +15,29 @@ pub trait GeneratorInit { fn new(seed: Seed, dimension: Dimension) -> Self; } +use pumpkin_data::structures::{StructurePlacementCalculator, StructureSet}; +use rustc_hash::FxHashMap; + pub struct VanillaGenerator { pub random_config: GlobalRandomConfig, pub base_router: ProtoNoiseRouters, pub dimension: Dimension, + pub settings: &'static GenerationSettings, + pub biome_mixer_seed: i64, pub terrain_cache: TerrainCache, pub default_block: &'static BlockState, pub global_structure_cache: crate::generation::structure::placement::GlobalStructureCache, + pub structure_calculator: StructurePlacementCalculator, + pub structure_allowed_biomes: FxHashMap>, } impl GeneratorInit for VanillaGenerator { fn new(seed: Seed, dimension: Dimension) -> Self { - let generation_settings = GenerationSettings::from_dimension(&dimension); - let random_config = - GlobalRandomConfig::new(seed.0, generation_settings.legacy_random_source); + let settings = GenerationSettings::from_dimension(&dimension); + let random_config = GlobalRandomConfig::new(seed.0, settings.legacy_random_source); // TODO: The generation settings contains (part of?) the noise routers too; do we keep the separate or // use only the generation settings? @@ -46,16 +52,30 @@ impl GeneratorInit for VanillaGenerator { }; let terrain_cache = TerrainCache::from_random(&random_config); - let default_block = generation_settings.default_block; + let default_block = settings.default_block; let base_router = ProtoNoiseRouters::generate(&base, &random_config); + let biome_mixer_seed = crate::biome::hash_seed(seed.0); + + let mut structure_allowed_biomes = FxHashMap::default(); + for (i, set) in StructureSet::ALL.iter().enumerate() { + structure_allowed_biomes.insert( + i, + crate::generation::proto_chunk::ProtoChunk::get_allowed_biomes(set), + ); + } + Self { random_config, base_router, dimension, + settings, + biome_mixer_seed, terrain_cache, default_block, global_structure_cache: crate::generation::structure::placement::GlobalStructureCache::new(), + structure_calculator: StructurePlacementCalculator::new(seed.0 as i64), + structure_allowed_biomes, } } } diff --git a/pumpkin-world/src/generation/noise/aquifer_sampler.rs b/pumpkin-world/src/generation/noise/aquifer_sampler.rs index 87e18084f..b7e8c82fa 100644 --- a/pumpkin-world/src/generation/noise/aquifer_sampler.rs +++ b/pumpkin-world/src/generation/noise/aquifer_sampler.rs @@ -451,149 +451,159 @@ impl WorldAquiferSampler { density: f64, ) -> Option<&'static BlockState> { if density > 0f64 { - None - } else { - let sample_x = pos.x; - let sample_y = pos.y; - let sample_z = pos.z; + return None; + } - let fluid_level = self - .fluid_level_sampler - .get_fluid_level(sample_x, sample_y, sample_z); - if fluid_level.get_block(sample_y) == &LAVA_BLOCK { - Some(LAVA_BLOCK.default_state) - } else { - let scaled_x = local_xz!(sample_x - 5); - let scaled_y = local_y!(sample_y + 1); - let scaled_z = local_xz!(sample_z - 5); + let sample_x = pos.x; + let sample_y = pos.y; + let sample_z = pos.z; - let mut random_positions_and_hypot = [(0, i32::MAX); 3]; - for packed_random in self.random_positions_for_pos(scaled_x, scaled_y, scaled_z) { - let unpacked_x = block_pos::unpack_x(packed_random); - let unpacked_y = block_pos::unpack_y(packed_random); - let unpacked_z = block_pos::unpack_z(packed_random); + let fluid_level = self + .fluid_level_sampler + .get_fluid_level(sample_x, sample_y, sample_z); + if fluid_level.get_block(sample_y) == &LAVA_BLOCK { + return Some(LAVA_BLOCK.default_state); + } - let local_x = unpacked_x - sample_x; - let local_y = unpacked_y - sample_y; - let local_z = unpacked_z - sample_z; + let scaled_x = local_xz!(sample_x - 5); + let scaled_y = local_y!(sample_y + 1); + let scaled_z = local_xz!(sample_z - 5); - let hypot_squared = local_x * local_x + local_y * local_y + local_z * local_z; + // Inline random_positions_for_pos: read directly from packed_positions with a + // single bounds check instead of stack-allocating and copying a [i64; 12]. + let sy = self.size_y; + let syz = sy * self.size_z; + let i00 = self.packed_position_index(scaled_x, scaled_y - 1, scaled_z); + let i01 = i00 + sy; + let i10 = i00 + syz; + let i11 = i10 + sy; - if random_positions_and_hypot[2].1 > hypot_squared { - random_positions_and_hypot[2] = (packed_random, hypot_squared); - } + let p = &self.packed_positions; + // i11 + 2 is the largest index we ever access; all others are strictly smaller. + assert!(i11 + 2 < p.len(), "Index out of bounds"); - if random_positions_and_hypot[1].1 > hypot_squared { - random_positions_and_hypot[2] = random_positions_and_hypot[1]; - random_positions_and_hypot[1] = (packed_random, hypot_squared); - } + let mut nearest = [(0i64, i32::MAX); 3]; - if random_positions_and_hypot[0].1 > hypot_squared { - random_positions_and_hypot[1] = random_positions_and_hypot[0]; - random_positions_and_hypot[0] = (packed_random, hypot_squared); - } + // SAFETY: every index passed to this macro is <= i11 + 2, checked by the assert above. + macro_rules! process { + ($idx:expr) => {{ + let packed = unsafe { *p.get_unchecked($idx) }; + let dx = block_pos::unpack_x(packed) - sample_x; + let dy = block_pos::unpack_y(packed) - sample_y; + let dz = block_pos::unpack_z(packed) - sample_z; + let h = dx * dx + dy * dy + dz * dz; + if nearest[2].1 > h { + nearest[2] = (packed, h); } - let fluid_level2 = self - .get_water_level( - random_positions_and_hypot[0].0, - router, - height_estimator, - sample_options, - ) - .clone(); - let d = Self::max_distance( - random_positions_and_hypot[0].1, - random_positions_and_hypot[1].1, - ); - let block_state = fluid_level2.get_block(sample_y); + if nearest[1].1 > h { + nearest[2] = nearest[1]; + nearest[1] = (packed, h); + } + if nearest[0].1 > h { + nearest[1] = nearest[0]; + nearest[0] = (packed, h); + } + }}; + } - if d <= 0f64 { - // TODO: Handle fluid tick + // Same insertion order as the original array literal — sort behaviour is preserved. + process!(i11 + 2); + process!(i10 + 2); + process!(i01 + 2); + process!(i00 + 2); + process!(i11 + 1); + process!(i10 + 1); + process!(i01 + 1); + process!(i00 + 1); + process!(i11); + process!(i10); + process!(i01); + process!(i00); - Some(block_state.default_state) - } else if block_state == &WATER_BLOCK - && self - .fluid_level_sampler - .get_fluid_level(sample_x, sample_y - 1, sample_z) - .get_block(sample_y - 1) - == &LAVA_BLOCK - { - Some(block_state.default_state) - } else { - let mut barrier_sample = None; - let fluid_level3 = self - .get_water_level( - random_positions_and_hypot[1].0, - router, - height_estimator, - sample_options, - ) - .clone(); - let e = d * Self::calculate_density( + // Precompute all three pairwise distances before fetching any water levels so we + // can skip the third get_water_level call entirely when neither f nor g_dist > 0. + let d = Self::max_distance(nearest[0].1, nearest[1].1); + let f = Self::max_distance(nearest[0].1, nearest[2].1); + let g_dist = Self::max_distance(nearest[1].1, nearest[2].1); + + let fluid_level2 = self + .get_water_level(nearest[0].0, router, height_estimator, sample_options) + .clone(); + let block_state = fluid_level2.get_block(sample_y); + + if d <= 0f64 { + // TODO: Handle fluid tick + return Some(block_state.default_state); + } + + if block_state == &WATER_BLOCK + && self + .fluid_level_sampler + .get_fluid_level(sample_x, sample_y - 1, sample_z) + .get_block(sample_y - 1) + == &LAVA_BLOCK + { + return Some(block_state.default_state); + } + + let mut barrier_sample = None; + let fluid_level3 = self + .get_water_level(nearest[1].0, router, height_estimator, sample_options) + .clone(); + let e = d * Self::calculate_density( + &mut barrier_sample, + pos, + router, + sample_options, + &fluid_level2, + &fluid_level3, + ); + + if density + e > 0f64 { + return None; + } + + // Only pay for the cache/noise lookup when at least one distance weight is positive; + // when both are <= 0 the third centre cannot affect the result. + if f > 0f64 || g_dist > 0f64 { + let fluid_level4 = + self.get_water_level(nearest[2].0, router, height_estimator, sample_options); + + if f > 0f64 { + let contrib = d + * f + * Self::calculate_density( &mut barrier_sample, pos, router, sample_options, &fluid_level2, - &fluid_level3, + fluid_level4, ); + if density + contrib > 0f64 { + return None; + } + } - if density + e > 0f64 { - None - } else { - let fluid_level4 = self.get_water_level( - random_positions_and_hypot[2].0, - router, - height_estimator, - sample_options, - ); - let f = Self::max_distance( - random_positions_and_hypot[0].1, - random_positions_and_hypot[2].1, - ); - if f > 0f64 { - let g = d - * f - * Self::calculate_density( - &mut barrier_sample, - pos, - router, - sample_options, - &fluid_level2, - fluid_level4, - ); - if density + g > 0f64 { - return None; - } - } - - let g = Self::max_distance( - random_positions_and_hypot[1].1, - random_positions_and_hypot[2].1, - ); - if g > 0f64 { - let h = d - * g - * Self::calculate_density( - &mut barrier_sample, - pos, - router, - sample_options, - &fluid_level3, - fluid_level4, - ); - if density + h > 0f64 { - return None; - } - } - - //TODO Handle fluid tick - - Some(block_state.default_state) - } + if g_dist > 0f64 { + let contrib = d + * g_dist + * Self::calculate_density( + &mut barrier_sample, + pos, + router, + sample_options, + &fluid_level3, + fluid_level4, + ); + if density + contrib > 0f64 { + return None; } } } + + // TODO: Handle fluid tick + Some(block_state.default_state) } } diff --git a/pumpkin-world/src/generation/noise/perlin.rs b/pumpkin-world/src/generation/noise/perlin.rs index ce6eb23ed..8bdda39ee 100644 --- a/pumpkin-world/src/generation/noise/perlin.rs +++ b/pumpkin-world/src/generation/noise/perlin.rs @@ -32,6 +32,20 @@ impl DoublePerlinNoiseSampler { ) } + pub fn get_amplitude(amplitudes: &[f64]) -> f64 { + let mut j = i32::MAX; + let mut k = i32::MIN; + + for (index, amplitude) in amplitudes.iter().enumerate() { + if *amplitude != 0f64 { + j = i32::min(j, index as i32); + k = i32::max(k, index as i32); + } + } + + 0.16666666666666666f64 / Self::create_amplitude(k - j) + } + pub fn new( rand: &mut impl RandomImpl, first_octave: i32, @@ -76,7 +90,14 @@ mod double_perlin_noise_sampler_test { assert_eq!(rand.next_i32(), -1302745855); let mut rand_gen = RandomGenerator::Legacy(rand); - let params = DoublePerlinNoiseParameters::new(0, 0, &[4f64], 1, 1, 1.0); + let params = DoublePerlinNoiseParameters::new( + 0, + 0, + &[4f64], + 0, + 0, + DoublePerlinNoiseSampler::get_amplitude(&[4f64]), + ); let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, true); let values = [ @@ -174,7 +195,14 @@ mod double_perlin_noise_sampler_test { let mut rand_gen = RandomGenerator::Xoroshiro(rand); - let params = DoublePerlinNoiseParameters::new(0, 1, &[2f64, 4f64], 1, 1, 1.0); + let params = DoublePerlinNoiseParameters::new( + 0, + 1, + &[2f64, 4f64], + 0, + 0, + DoublePerlinNoiseSampler::get_amplitude(&[2f64, 4f64]), + ); let sampler = DoublePerlinNoiseSampler::from_params(&mut rand_gen, ¶ms, false); diff --git a/pumpkin-world/src/generation/proto_chunk.rs b/pumpkin-world/src/generation/proto_chunk.rs index c8a2076d2..c1d97e0c4 100644 --- a/pumpkin-world/src/generation/proto_chunk.rs +++ b/pumpkin-world/src/generation/proto_chunk.rs @@ -3,12 +3,10 @@ use std::sync::Arc; use pumpkin_data::block_properties::is_air; use pumpkin_data::chunk::DoublePerlinNoiseParameters; -use pumpkin_data::chunk_gen_settings::GenerationSettings; use pumpkin_data::dimension::Dimension; use pumpkin_data::fluid::{Fluid, FluidState}; use pumpkin_data::structures::{ - Structure, StructureKeys, StructurePlacementCalculator, StructurePlacementType, StructureSet, - WeightedEntry, + Structure, StructureKeys, StructurePlacementType, StructureSet, WeightedEntry, }; use pumpkin_data::tag; use pumpkin_data::tag::RegistryKey; @@ -45,7 +43,6 @@ use crate::generation::noise::router::multi_noise_sampler::MultiNoiseSamplerBuil use crate::generation::noise::router::surface_height_sampler::SurfaceHeightSamplerBuilderOptions; use crate::generation::noise::{CHUNK_DIM, ChunkNoiseGenerator, LAVA_BLOCK, WATER_BLOCK}; use crate::generation::structure::lazily_generate_structure; -use crate::generation::structure::placement::GlobalStructureCache; use crate::generation::structure::placement::should_generate_structure; use crate::generation::structure::structures::{ StructureGeneratorContext, StructureInstance, create_chunk_random, @@ -53,7 +50,7 @@ use crate::generation::structure::structures::{ use crate::generation::structure::try_generate_structure; use crate::generation::surface::evaluate_surface_rule; use crate::{ - BlockStateId, ProtoNoiseRouters, + BlockStateId, block::RawBlockState, chunk::CHUNK_AREA, generation::{biome, positions::chunk_pos}, @@ -205,13 +202,8 @@ impl TerrainCache { impl ProtoChunk { #[must_use] - pub fn new( - x: i32, - z: i32, - dimension: &Dimension, - default_block: &'static BlockState, - biome_mixer_seed: i64, - ) -> Self { + pub fn new(x: i32, z: i32, generator: &super::generator::VanillaGenerator) -> Self { + let dimension = &generator.dimension; let height = dimension.logical_height as u16; let section_count = (height as usize) / 16; @@ -219,7 +211,8 @@ impl ProtoChunk { Self { x, z, - default_block, + default_block: generator.default_block, + biome_mixer_seed: generator.biome_mixer_seed, flat_block_map: vec![0; CHUNK_AREA * height as usize].into_boxed_slice(), flat_biome_map: vec![ Biome::PLAINS.id; @@ -228,7 +221,6 @@ impl ProtoChunk { * biome_coords::from_block(height as i32) as usize ] .into_boxed_slice(), - biome_mixer_seed, flat_surface_height_map: default_heightmap.clone(), flat_ocean_floor_height_map: default_heightmap.clone(), flat_motion_blocking_height_map: default_heightmap.clone(), @@ -241,38 +233,29 @@ impl ProtoChunk { sky_light: (0..section_count) .map(|_| { if dimension.has_skylight { - // Pre-allocate full arrays for sky light in dimensions with skylight - // Initialize to 0 - lighting engine will calculate proper values - LightContainer::new_filled(0) + // Sky light starts at 0 and is calculated by the lighting engine + LightContainer::new_empty(0) } else { - // No skylight in Nether/End, can use Empty + // No skylight in Nether/End LightContainer::new_empty(0) } }) .collect(), block_light: (0..section_count) - // Pre-allocate full arrays for block light - // Initialize to 0 - lighting engine will set emissive blocks - .map(|_| LightContainer::new_filled(0)) + // Block light starts at 0 and is set by emissive blocks + .map(|_| LightContainer::new_empty(0)) .collect(), }, pending_block_entities: Vec::new(), } } - + #[must_use] pub fn from_chunk_data( chunk_data: &ChunkData, - dimension: &Dimension, - default_block: &'static BlockState, - biome_mixer_seed: i64, + generator: &super::generator::VanillaGenerator, ) -> Self { - let mut proto_chunk = Self::new( - chunk_data.x, - chunk_data.z, - dimension, - default_block, - biome_mixer_seed, - ); + let mut proto_chunk = Self::new(chunk_data.x, chunk_data.z, generator); + proto_chunk.light = chunk_data.light_engine.lock().unwrap().clone(); let section_data = &chunk_data.section; @@ -549,7 +532,7 @@ impl ProtoChunk { self.flat_biome_map[index] } - pub fn step_to_biomes(&mut self, dimension: Dimension, noise_router: &ProtoNoiseRouters) { + pub fn step_to_biomes(&mut self, generator: &super::generator::VanillaGenerator) { let start_x = start_block_x(self.x); let start_z = start_block_z(self.z); let horizontal_biome_end = biome_coords::from_block(16); @@ -560,19 +543,15 @@ impl ProtoChunk { horizontal_biome_end as usize, ); let mut multi_noise_sampler = - MultiNoiseSampler::generate(&noise_router.multi_noise, &multi_noise_config); - self.populate_biomes(dimension, &mut multi_noise_sampler); + MultiNoiseSampler::generate(&generator.base_router.multi_noise, &multi_noise_config); + self.populate_biomes(generator, &mut multi_noise_sampler); self.stage = StagedChunkEnum::Biomes; } - pub fn step_to_noise( - &mut self, - settings: &GenerationSettings, - random_config: &GlobalRandomConfig, - noise_router: &ProtoNoiseRouters, - ) { + pub fn step_to_noise(&mut self, generator: &super::generator::VanillaGenerator) { //debug_assert_eq!(self.stage, StagedChunkEnum::Biomes); + let settings = generator.settings; let generation_shape = &settings.shape; let horizontal_cell_count = CHUNK_DIM / generation_shape.horizontal_cell_block_count(); let start_x = start_block_x(self.x); @@ -587,8 +566,8 @@ impl ProtoChunk { ); let mut noise_sampler = ChunkNoiseGenerator::new( - &noise_router.noise, - random_config, + &generator.base_router.noise, + &generator.random_config, horizontal_cell_count as usize, start_x, start_z, @@ -610,30 +589,25 @@ impl ProtoChunk { generation_shape.vertical_cell_block_count() as usize, ); let mut surface_height_estimate_sampler = SurfaceHeightEstimateSampler::generate( - &noise_router.surface_estimator, + &generator.base_router.surface_estimator, &surface_config, ); self.populate_noise( + generator, &mut noise_sampler, - &random_config.ore_random_deriver, + &generator.random_config.ore_random_deriver, &mut surface_height_estimate_sampler, ); self.stage = StagedChunkEnum::Noise; } - pub fn step_to_surface( - &mut self, - settings: &GenerationSettings, - random_config: &GlobalRandomConfig, - terrain_cache: &TerrainCache, - noise_router: &ProtoNoiseRouters, - ) { + pub fn step_to_surface(&mut self, generator: &super::generator::VanillaGenerator) { debug_assert_eq!(self.stage, StagedChunkEnum::Noise); // Build surface let start_x = start_block_x(self.x); let start_z = start_block_z(self.z); - let generation_shape = &settings.shape; + let generation_shape = &generator.settings.shape; let horizontal_cell_count = CHUNK_DIM / generation_shape.horizontal_cell_block_count(); let horizontal_biome_end = biome_coords::from_block( @@ -648,24 +622,20 @@ impl ProtoChunk { generation_shape.vertical_cell_block_count() as usize, ); let mut surface_height_estimate_sampler = SurfaceHeightEstimateSampler::generate( - &noise_router.surface_estimator, + &generator.base_router.surface_estimator, &surface_config, ); - self.build_surface( - settings, - random_config, - terrain_cache, - &mut surface_height_estimate_sampler, - ); + self.build_surface(generator, &mut surface_height_estimate_sampler); self.stage = StagedChunkEnum::Surface; } pub fn populate_biomes( &mut self, - dimension: Dimension, + generator: &super::generator::VanillaGenerator, multi_noise_sampler: &mut MultiNoiseSampler, ) { + let dimension = generator.dimension; // Instantiate ONLY the supplier we actually need let active_supplier = if dimension == Dimension::THE_END { ActiveSupplier::End(TheEndBiomeSupplier) @@ -721,6 +691,7 @@ impl ProtoChunk { #[expect(clippy::similar_names)] pub fn populate_noise( &mut self, + generator: &super::generator::VanillaGenerator, noise_sampler: &mut ChunkNoiseGenerator, ore_random_deriver: &XoroshiroSplitter, surface_height_estimate_sampler: &mut SurfaceHeightEstimateSampler, @@ -773,7 +744,7 @@ impl ProtoChunk { local_z, surface_height_estimate_sampler, ) - .unwrap_or(self.default_block); + .unwrap_or(generator.default_block); self.set_block_state(block_x, block_y, block_z, block_state); } } @@ -798,6 +769,7 @@ impl ProtoChunk { self.get_biome_id(seed_biome_pos.x, seed_biome_pos.y, seed_biome_pos.z) } + #[must_use] pub fn get_terrain_gen_biome(&self, x: i32, y: i32, z: i32) -> &'static Biome { Biome::from_id(self.get_terrain_gen_biome_id(x, y, z)).unwrap() @@ -809,15 +781,17 @@ impl ProtoChunk { /// It is crucial that biome assignments are determined before this process begins. pub fn build_surface( &mut self, - settings: &GenerationSettings, - random_config: &GlobalRandomConfig, - terrain_cache: &TerrainCache, + generator: &super::generator::VanillaGenerator, surface_height_estimate_sampler: &mut SurfaceHeightEstimateSampler, ) { let start_x = chunk_pos::start_block_x(self.x); let start_z = chunk_pos::start_block_z(self.z); let min_y = self.bottom_y(); + let settings = generator.settings; + let random_config = &generator.random_config; + let terrain_cache = &generator.terrain_cache; + let random = &random_config.base_random_deriver; let mut context = MaterialRuleContext::new( min_y, @@ -1100,7 +1074,7 @@ impl ProtoChunk { } } - fn get_allowed_biomes(set: &StructureSet) -> Vec { + pub fn get_allowed_biomes(set: &StructureSet) -> Vec { let mut allowed_biomes = Vec::new(); for entry in set.structures { let structure = Structure::get(&entry.structure); @@ -1117,26 +1091,25 @@ impl ProtoChunk { allowed_biomes } - pub fn set_structure_starts( - &mut self, - random_config: &GlobalRandomConfig, - settings: &GenerationSettings, - global_cache: &GlobalStructureCache, - ) { - let seed = random_config.seed; - let calculator = StructurePlacementCalculator::new(seed as i64); + pub fn set_structure_starts(&mut self, generator: &super::generator::VanillaGenerator) { + let random_config = &generator.random_config; + let settings = generator.settings; + let global_cache = &generator.global_structure_cache; + let calculator = &generator.structure_calculator; - for set in StructureSet::ALL { - let allowed_biomes = Self::get_allowed_biomes(set); + let seed = random_config.seed; + + for (i, set) in StructureSet::ALL.iter().enumerate() { + let allowed_biomes = &generator.structure_allowed_biomes[&i]; if !should_generate_structure( &set.placement, - &calculator, + calculator, self.x, self.z, global_cache, self, - &allowed_biomes, + allowed_biomes, ) { continue; } @@ -1205,14 +1178,13 @@ impl ProtoChunk { false } - pub fn set_structure_references( - &mut self, - random_config: &GlobalRandomConfig, - settings: &GenerationSettings, - dimension: &Dimension, - noise_router: &ProtoNoiseRouters, - global_cache: &GlobalStructureCache, - ) { + pub fn set_structure_references(&mut self, generator: &super::generator::VanillaGenerator) { + let random_config = &generator.random_config; + let settings = generator.settings; + let dimension = &generator.dimension; + let noise_router = &generator.base_router; + let global_cache = &generator.global_structure_cache; + let start_x = chunk_pos::start_block_x(self.x); let start_z = chunk_pos::start_block_z(self.z); let end_x = start_x + 15; diff --git a/pumpkin-world/src/lib.rs b/pumpkin-world/src/lib.rs index c3b2c4df0..c306b239c 100644 --- a/pumpkin-world/src/lib.rs +++ b/pumpkin-world/src/lib.rs @@ -55,22 +55,24 @@ use crate::generation::{ }; pub fn bench_create_and_populate_noise( - base_router: &ProtoNoiseRouters, + _base_router: &ProtoNoiseRouters, random_config: &GlobalRandomConfig, - settings: &GenerationSettings, + _settings: &GenerationSettings, _terrain_cache: &TerrainCache, - default_block: &'static BlockState, + _default_block: &'static BlockState, ) { - use crate::biome::hash_seed; + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; use crate::generation::noise::router::surface_height_sampler::{ SurfaceHeightEstimateSampler, SurfaceHeightSamplerBuilderOptions, }; use crate::generation::proto_chunk::StandardChunkFluidLevelSampler; + use pumpkin_util::world_seed::Seed; - let biome_mixer_seed = hash_seed(random_config.seed); - let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed); + let generator = VanillaGenerator::new(Seed(random_config.seed), Dimension::OVERWORLD); + let mut chunk = ProtoChunk::new(0, 0, &generator); // Create noise sampler and other required components + let settings = generator.settings; let generation_shape = &settings.shape; let horizontal_cell_count = CHUNK_DIM / generation_shape.horizontal_cell_block_count(); let sampler = StandardChunkFluidLevelSampler::new( @@ -85,8 +87,8 @@ pub fn bench_create_and_populate_noise( let start_z = chunk_pos::start_block_z(0); let mut noise_sampler = ChunkNoiseGenerator::new( - &base_router.noise, - random_config, + &generator.base_router.noise, + &generator.random_config, horizontal_cell_count as usize, start_x, start_z, @@ -112,63 +114,63 @@ pub fn bench_create_and_populate_noise( generation_shape.max_y() as i32, generation_shape.vertical_cell_block_count() as usize, ); - let mut surface_height_estimate_sampler = - SurfaceHeightEstimateSampler::generate(&base_router.surface_estimator, &surface_config); + let mut surface_height_estimate_sampler = SurfaceHeightEstimateSampler::generate( + &generator.base_router.surface_estimator, + &surface_config, + ); chunk.populate_noise( + &generator, &mut noise_sampler, - &random_config.ore_random_deriver, + &generator.random_config.ore_random_deriver, &mut surface_height_estimate_sampler, ); } pub fn bench_create_and_populate_biome( - base_router: &ProtoNoiseRouters, + _base_router: &ProtoNoiseRouters, random_config: &GlobalRandomConfig, - settings: &GenerationSettings, + _settings: &GenerationSettings, _terrain_cache: &TerrainCache, - default_block: &'static BlockState, + _default_block: &'static BlockState, ) { - use crate::biome::hash_seed; + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; use crate::generation::noise::router::multi_noise_sampler::{ MultiNoiseSampler, MultiNoiseSamplerBuilderOptions, }; use crate::generation::{biome_coords, positions::chunk_pos}; + use pumpkin_util::world_seed::Seed; - let biome_mixer_seed = hash_seed(random_config.seed); - let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed); + let generator = VanillaGenerator::new(Seed(random_config.seed), Dimension::OVERWORLD); + let mut chunk = ProtoChunk::new(0, 0, &generator); // Create multi-noise sampler - let generation_shape = &settings.shape; - let horizontal_cell_count = CHUNK_DIM / generation_shape.horizontal_cell_block_count(); let start_x = chunk_pos::start_block_x(0); let start_z = chunk_pos::start_block_z(0); let biome_pos = Vector2::new( biome_coords::from_block(start_x), biome_coords::from_block(start_z), ); - let horizontal_biome_end = biome_coords::from_block( - horizontal_cell_count as i32 * generation_shape.horizontal_cell_block_count() as i32, - ); + let horizontal_biome_end = biome_coords::from_block(16); let multi_noise_config = MultiNoiseSamplerBuilderOptions::new( biome_pos.x, biome_pos.y, horizontal_biome_end as usize, ); let mut multi_noise_sampler = - MultiNoiseSampler::generate(&base_router.multi_noise, &multi_noise_config); + MultiNoiseSampler::generate(&generator.base_router.multi_noise, &multi_noise_config); - chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler); + chunk.populate_biomes(&generator, &mut multi_noise_sampler); } pub fn bench_create_and_populate_noise_with_surface( - base_router: &ProtoNoiseRouters, + _base_router: &ProtoNoiseRouters, random_config: &GlobalRandomConfig, - settings: &GenerationSettings, - terrain_cache: &TerrainCache, - default_block: &'static BlockState, + _settings: &GenerationSettings, + _terrain_cache: &TerrainCache, + _default_block: &'static BlockState, ) { - use crate::biome::hash_seed; + use crate::generation::generator::{GeneratorInit, VanillaGenerator}; use crate::generation::noise::router::{ multi_noise_sampler::{MultiNoiseSampler, MultiNoiseSamplerBuilderOptions}, surface_height_sampler::{ @@ -176,11 +178,13 @@ pub fn bench_create_and_populate_noise_with_surface( }, }; use crate::generation::proto_chunk::StandardChunkFluidLevelSampler; + use pumpkin_util::world_seed::Seed; - let biome_mixer_seed = hash_seed(random_config.seed); - let mut chunk = ProtoChunk::new(0, 0, &Dimension::OVERWORLD, default_block, biome_mixer_seed); + let generator = VanillaGenerator::new(Seed(random_config.seed), Dimension::OVERWORLD); + let mut chunk = ProtoChunk::new(0, 0, &generator); // Create all required components + let settings = generator.settings; let generation_shape = &settings.shape; let horizontal_cell_count = CHUNK_DIM / generation_shape.horizontal_cell_block_count(); let start_x = chunk_pos::start_block_x(0); @@ -191,16 +195,14 @@ pub fn bench_create_and_populate_noise_with_surface( biome_coords::from_block(start_x), biome_coords::from_block(start_z), ); - let horizontal_biome_end = biome_coords::from_block( - horizontal_cell_count as i32 * generation_shape.horizontal_cell_block_count() as i32, - ); + let horizontal_biome_end = biome_coords::from_block(16); let multi_noise_config = MultiNoiseSamplerBuilderOptions::new( biome_pos.x, biome_pos.y, horizontal_biome_end as usize, ); let mut multi_noise_sampler = - MultiNoiseSampler::generate(&base_router.multi_noise, &multi_noise_config); + MultiNoiseSampler::generate(&generator.base_router.multi_noise, &multi_noise_config); // Noise sampler let sampler = StandardChunkFluidLevelSampler::new( @@ -208,12 +210,12 @@ pub fn bench_create_and_populate_noise_with_surface( settings.sea_level, Block::from_state_id(settings.default_fluid.id), ), - FluidLevel::new(-54, &pumpkin_data::Block::LAVA), + FluidLevel::new(-54, &Block::LAVA), ); let mut noise_sampler = ChunkNoiseGenerator::new( - &base_router.noise, - random_config, + &generator.base_router.noise, + &generator.random_config, horizontal_cell_count as usize, start_x, start_z, @@ -232,19 +234,17 @@ pub fn bench_create_and_populate_noise_with_surface( generation_shape.max_y() as i32, generation_shape.vertical_cell_block_count() as usize, ); - let mut surface_height_estimate_sampler = - SurfaceHeightEstimateSampler::generate(&base_router.surface_estimator, &surface_config); + let mut surface_height_estimate_sampler = SurfaceHeightEstimateSampler::generate( + &generator.base_router.surface_estimator, + &surface_config, + ); - chunk.populate_biomes(Dimension::OVERWORLD, &mut multi_noise_sampler); + chunk.populate_biomes(&generator, &mut multi_noise_sampler); chunk.populate_noise( + &generator, &mut noise_sampler, - &random_config.ore_random_deriver, - &mut surface_height_estimate_sampler, - ); - chunk.build_surface( - settings, - random_config, - terrain_cache, + &generator.random_config.ore_random_deriver, &mut surface_height_estimate_sampler, ); + chunk.build_surface(&generator, &mut surface_height_estimate_sampler); }