From 4b893b7286fd0b2f94a07410ed32f2f5277d2de7 Mon Sep 17 00:00:00 2001 From: Alexander Medvedev Date: Sun, 8 Jun 2025 22:04:17 +0200 Subject: [PATCH] Implement end biome generation --- pumpkin-world/src/biome/end.rs | 51 +++++++++++++++++++ pumpkin-world/src/biome/mod.rs | 5 +- .../noise_router/multi_noise_sampler.rs | 12 +++++ pumpkin-world/src/generation/proto_chunk.rs | 20 +++++--- 4 files changed, 79 insertions(+), 9 deletions(-) create mode 100644 pumpkin-world/src/biome/end.rs diff --git a/pumpkin-world/src/biome/end.rs b/pumpkin-world/src/biome/end.rs new file mode 100644 index 000000000..065ae24bc --- /dev/null +++ b/pumpkin-world/src/biome/end.rs @@ -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, + 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 + } +} diff --git a/pumpkin-world/src/biome/mod.rs b/pumpkin-world/src/biome/mod.rs index bed161915..ae3cd3228 100644 --- a/pumpkin-world/src/biome/mod.rs +++ b/pumpkin-world/src/biome/mod.rs @@ -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, @@ -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(); diff --git a/pumpkin-world/src/generation/noise_router/multi_noise_sampler.rs b/pumpkin-world/src/generation/noise_router/multi_noise_sampler.rs index 4400c0f12..09ae6b53e 100644 --- a/pumpkin-world/src/generation/noise_router/multi_noise_sampler.rs +++ b/pumpkin-world/src/generation/noise_router/multi_noise_sampler.rs @@ -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, diff --git a/pumpkin-world/src/generation/proto_chunk.rs b/pumpkin-world/src/generation/proto_chunk.rs index f6a5319cb..e79113dfb 100644 --- a/pumpkin-world/src/generation/proto_chunk.rs +++ b/pumpkin-world/src/generation/proto_chunk.rs @@ -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 {