Implement end biome generation

This commit is contained in:
Alexander Medvedev 2025-06-08 22:04:17 +02:00
parent 87bb594025
commit 4b893b7286
4 changed files with 79 additions and 9 deletions

View File

@ -0,0 +1,51 @@
use pumpkin_data::chunk::Biome;
use pumpkin_util::math::vector3::Vector3;
use crate::{
biome::BiomeSupplier,
dimension::Dimension,
generation::{
biome_coords, noise_router::multi_noise_sampler::MultiNoiseSampler, section_coords,
},
};
pub struct TheEndBiomeSupplier;
impl TheEndBiomeSupplier {
const CENTER_BIOME: Biome = Biome::THE_END;
const HIGHLANDS_BIOME: Biome = Biome::END_HIGHLANDS;
const MIDLANDS_BIOME: Biome = Biome::END_MIDLANDS;
const SMALL_ISLANDS_BIOME: Biome = Biome::SMALL_END_ISLANDS;
const BARRENS_BIOME: Biome = Biome::END_BARRENS;
}
impl BiomeSupplier for TheEndBiomeSupplier {
fn biome(
global_biome_pos: &Vector3<i32>,
noise: &mut MultiNoiseSampler<'_>,
_dimension: Dimension,
) -> &'static Biome {
let x = biome_coords::to_block(global_biome_pos.x);
let y = biome_coords::to_block(global_biome_pos.y);
let z = biome_coords::to_block(global_biome_pos.z);
let section_x = section_coords::block_to_section(x);
let section_z = section_coords::block_to_section(z);
if section_x * section_x + section_z * section_z <= 4096 {
return &Self::CENTER_BIOME;
}
let x = (section_x * 2 + 1) * 8;
let z = (section_z * 2 + 1) * 8;
let noise = noise.sample_erosion(x, y, z);
if noise > 0.25 {
return &Self::HIGHLANDS_BIOME;
}
if noise >= -0.0625 {
return &Self::MIDLANDS_BIOME;
}
if noise < -0.21875 {
return &Self::SMALL_ISLANDS_BIOME;
}
&Self::BARRENS_BIOME
}
}

View File

@ -8,6 +8,7 @@ use pumpkin_util::math::vector3::Vector3;
use crate::{
dimension::Dimension, generation::noise_router::multi_noise_sampler::MultiNoiseSampler,
};
pub mod end;
pub mod multi_noise;
thread_local! {
@ -26,8 +27,6 @@ pub trait BiomeSupplier {
pub struct MultiNoiseBiomeSupplier;
// TODO: Add Nether & End supplier
impl BiomeSupplier for MultiNoiseBiomeSupplier {
fn biome(
global_biome_pos: &Vector3<i32>,
@ -37,7 +36,7 @@ impl BiomeSupplier for MultiNoiseBiomeSupplier {
let source: &'static BiomeTree = match dimension {
Dimension::Overworld => &OVERWORLD_BIOME_SOURCE,
Dimension::Nether => &NETHER_BIOME_SOURCE,
Dimension::End => &OVERWORLD_BIOME_SOURCE, // TODO: this is wrong, end has its own thing
Dimension::End => unreachable!(), // Use TheEndBiomeSupplier
};
let point = noise.sample(global_biome_pos.x, global_biome_pos.y, global_biome_pos.z);
let point_list = point.convert_to_list();

View File

@ -101,6 +101,18 @@ impl<'a> MultiNoiseSampler<'a> {
}
}
pub fn sample_erosion(&mut self, block_x: i32, block_y: i32, block_z: i32) -> f64 {
let pos = UnblendedNoisePos::new(block_x, block_y, block_z);
let sample_options =
ChunkNoiseFunctionSampleOptions::new(false, SampleAction::SkipCellCaches, 0, 0, 0);
ChunkNoiseFunctionComponent::sample_from_stack(
&mut self.component_stack[..=self.erosion],
&pos,
&sample_options,
)
}
pub fn generate(
base: &'a ProtoMultiNoiseRouter,
build_options: &MultiNoiseSamplerBuilderOptions,

View File

@ -18,7 +18,7 @@ use pumpkin_util::{
use crate::{
HeightMap,
biome::{BiomeSupplier, MultiNoiseBiomeSupplier, hash_seed},
biome::{BiomeSupplier, MultiNoiseBiomeSupplier, end::TheEndBiomeSupplier, hash_seed},
block::RawBlockState,
chunk::CHUNK_AREA,
dimension::Dimension,
@ -427,11 +427,19 @@ impl<'a> ProtoChunk<'a> {
// panic!("{}:{}", start_y, y);
let biome_pos =
Vector3::new(start_biome_x + x, start_biome_y + y, start_biome_z + z);
let biome = MultiNoiseBiomeSupplier::biome(
&biome_pos,
&mut self.multi_noise_sampler,
dimension,
);
let biome = if dimension == Dimension::End {
TheEndBiomeSupplier::biome(
&biome_pos,
&mut self.multi_noise_sampler,
dimension,
)
} else {
MultiNoiseBiomeSupplier::biome(
&biome_pos,
&mut self.multi_noise_sampler,
dimension,
)
};
//panic!("Populating biome: {:?} -> {:?}", biome_pos, biome);
let local_biome_pos = Vector3 {