fix: tests
This commit is contained in:
parent
427df56935
commit
1d671504d1
@ -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
|
||||
}
|
||||
|
||||
|
||||
@ -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;
|
||||
|
||||
|
||||
@ -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);
|
||||
|
||||
@ -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<PosToPoint> =
|
||||
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),
|
||||
);
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@ -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,
|
||||
);
|
||||
}
|
||||
StagedChunkEnum::StructureReferences => self.chunks[mid]
|
||||
self.chunks[mid]
|
||||
.get_proto_chunk_mut()
|
||||
.set_structure_references(
|
||||
random_config,
|
||||
settings,
|
||||
&dimension,
|
||||
noise_router,
|
||||
global_structure_cache,
|
||||
), // <--- PASSED HERE
|
||||
.set_structure_starts(generator);
|
||||
}
|
||||
StagedChunkEnum::StructureReferences => {
|
||||
self.chunks[mid]
|
||||
.get_proto_chunk_mut()
|
||||
.set_structure_references(generator);
|
||||
}
|
||||
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 => {}
|
||||
}
|
||||
|
||||
@ -59,10 +59,7 @@ pub async fn io_read_work(
|
||||
level: Arc<Level>,
|
||||
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
|
||||
}));
|
||||
|
||||
@ -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<usize, Vec<u16>>,
|
||||
}
|
||||
|
||||
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,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -451,8 +451,9 @@ impl WorldAquiferSampler {
|
||||
density: f64,
|
||||
) -> Option<&'static BlockState> {
|
||||
if density > 0f64 {
|
||||
None
|
||||
} else {
|
||||
return None;
|
||||
}
|
||||
|
||||
let sample_x = pos.x;
|
||||
let sample_y = pos.y;
|
||||
let sample_z = pos.z;
|
||||
@ -461,73 +462,93 @@ impl WorldAquiferSampler {
|
||||
.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 {
|
||||
return Some(LAVA_BLOCK.default_state);
|
||||
}
|
||||
|
||||
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 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);
|
||||
// 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;
|
||||
|
||||
let local_x = unpacked_x - sample_x;
|
||||
let local_y = unpacked_y - sample_y;
|
||||
let local_z = unpacked_z - sample_z;
|
||||
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");
|
||||
|
||||
let hypot_squared = local_x * local_x + local_y * local_y + local_z * local_z;
|
||||
let mut nearest = [(0i64, i32::MAX); 3];
|
||||
|
||||
if random_positions_and_hypot[2].1 > hypot_squared {
|
||||
random_positions_and_hypot[2] = (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);
|
||||
}
|
||||
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 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);
|
||||
}
|
||||
// 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);
|
||||
|
||||
// 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);
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
let fluid_level2 = self
|
||||
.get_water_level(
|
||||
random_positions_and_hypot[0].0,
|
||||
router,
|
||||
height_estimator,
|
||||
sample_options,
|
||||
)
|
||||
.get_water_level(nearest[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 d <= 0f64 {
|
||||
// TODO: Handle fluid tick
|
||||
return Some(block_state.default_state);
|
||||
}
|
||||
|
||||
Some(block_state.default_state)
|
||||
} else if block_state == &WATER_BLOCK
|
||||
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 {
|
||||
return Some(block_state.default_state);
|
||||
}
|
||||
|
||||
let mut barrier_sample = None;
|
||||
let fluid_level3 = self
|
||||
.get_water_level(
|
||||
random_positions_and_hypot[1].0,
|
||||
router,
|
||||
height_estimator,
|
||||
sample_options,
|
||||
)
|
||||
.get_water_level(nearest[1].0, router, height_estimator, sample_options)
|
||||
.clone();
|
||||
let e = d * Self::calculate_density(
|
||||
&mut barrier_sample,
|
||||
@ -539,20 +560,17 @@ impl WorldAquiferSampler {
|
||||
);
|
||||
|
||||
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,
|
||||
);
|
||||
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 g = d
|
||||
let contrib = d
|
||||
* f
|
||||
* Self::calculate_density(
|
||||
&mut barrier_sample,
|
||||
@ -562,18 +580,14 @@ impl WorldAquiferSampler {
|
||||
&fluid_level2,
|
||||
fluid_level4,
|
||||
);
|
||||
if density + g > 0f64 {
|
||||
if density + contrib > 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
|
||||
if g_dist > 0f64 {
|
||||
let contrib = d
|
||||
* g_dist
|
||||
* Self::calculate_density(
|
||||
&mut barrier_sample,
|
||||
pos,
|
||||
@ -582,19 +596,15 @@ impl WorldAquiferSampler {
|
||||
&fluid_level3,
|
||||
fluid_level4,
|
||||
);
|
||||
if density + h > 0f64 {
|
||||
if density + contrib > 0f64 {
|
||||
return None;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
//TODO Handle fluid tick
|
||||
|
||||
// TODO: Handle fluid tick
|
||||
Some(block_state.default_state)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl AquiferSamplerImpl for WorldAquiferSampler {
|
||||
|
||||
@ -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);
|
||||
|
||||
|
||||
@ -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<u16> {
|
||||
pub fn get_allowed_biomes(set: &StructureSet) -> Vec<u16> {
|
||||
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;
|
||||
|
||||
@ -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);
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user