Minor Chunk gen speed gains

This commit is contained in:
Alexander Medvedev 2025-07-28 12:18:54 +02:00
parent f80650c36c
commit eaf5959f2b
6 changed files with 60 additions and 60 deletions

View File

@ -5,7 +5,7 @@
![CI](https://github.com/Snowiiii/Pumpkin/actions/workflows/rust.yml/badge.svg) ![CI](https://github.com/Snowiiii/Pumpkin/actions/workflows/rust.yml/badge.svg)
[![Discord](https://img.shields.io/discord/1268592337445978193.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/wT8XjrjKkf) [![Discord](https://img.shields.io/discord/1268592337445978193.svg?label=&logo=discord&logoColor=ffffff&color=7389D8&labelColor=6A7EC2)](https://discord.gg/wT8XjrjKkf)
[![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT)
![Current version)](https://img.shields.io/badge/current_version-1.21.7-blue) ![Current version)](https://img.shields.io/badge/current_version-1.21.8-blue)
</div> </div>

View File

@ -94,7 +94,7 @@ pub struct ChunkEntityData {
#[derive(Debug, Clone)] #[derive(Debug, Clone)]
pub struct ChunkSections { pub struct ChunkSections {
pub sections: Box<[SubChunk]>, pub sections: Box<[SubChunk]>,
min_y: i32, pub min_y: i32,
} }
impl ChunkSections { impl ChunkSections {
@ -179,18 +179,19 @@ impl ChunkSections {
} }
} }
/// Returns the replaced block state ID
pub fn set_block_absolute_y( pub fn set_block_absolute_y(
&mut self, &mut self,
relative_x: usize, relative_x: usize,
y: i32, y: i32,
relative_z: usize, relative_z: usize,
block_state: BlockStateId, block_state: BlockStateId,
) { ) -> BlockStateId {
let y = y - self.min_y; let y = y - self.min_y;
debug_assert!(y >= 0); debug_assert!(y >= 0);
let relative_y = y as usize; let relative_y = y as usize;
self.set_relative_block(relative_x, relative_y, relative_z, block_state); self.set_relative_block(relative_x, relative_y, relative_z, block_state)
} }
/// Gets the given block in the chunk /// Gets the given block in the chunk
@ -210,7 +211,7 @@ impl ChunkSections {
.map(|section| section.block_states.get(relative_x, relative_y, relative_z)) .map(|section| section.block_states.get(relative_x, relative_y, relative_z))
} }
/// Sets the given block in the chunk, returning the old block /// Sets the given block in the chunk, returning the old block state ID
#[inline] #[inline]
pub fn set_relative_block( pub fn set_relative_block(
&mut self, &mut self,
@ -218,9 +219,9 @@ impl ChunkSections {
relative_y: usize, relative_y: usize,
relative_z: usize, relative_z: usize,
block_state_id: BlockStateId, block_state_id: BlockStateId,
) { ) -> BlockStateId {
// TODO @LUK_ESC? update the heightmap // TODO @LUK_ESC? update the heightmap
self.set_block_no_heightmap_update(relative_x, relative_y, relative_z, block_state_id); self.set_block_no_heightmap_update(relative_x, relative_y, relative_z, block_state_id)
} }
/// Sets the given block in the chunk, returning the old block /// Sets the given block in the chunk, returning the old block
@ -234,20 +235,20 @@ impl ChunkSections {
relative_y: usize, relative_y: usize,
relative_z: usize, relative_z: usize,
block_state_id: BlockStateId, block_state_id: BlockStateId,
) { ) -> BlockStateId {
debug_assert!(relative_x < BlockPalette::SIZE); debug_assert!(relative_x < BlockPalette::SIZE);
debug_assert!(relative_z < BlockPalette::SIZE); debug_assert!(relative_z < BlockPalette::SIZE);
let section_index = relative_y / BlockPalette::SIZE; let section_index = relative_y / BlockPalette::SIZE;
let relative_y = relative_y % BlockPalette::SIZE; let relative_y = relative_y % BlockPalette::SIZE;
if let Some(section) = self.sections.get_mut(section_index) { if let Some(section) = self.sections.get_mut(section_index) {
section return section
.block_states .block_states
.set(relative_x, relative_y, relative_z, block_state_id); .set(relative_x, relative_y, relative_z, block_state_id);
} }
0
} }
/// Sets the given block in the chunk, returning the old block
pub fn set_relative_biome( pub fn set_relative_biome(
&mut self, &mut self,
relative_x: usize, relative_x: usize,
@ -260,11 +261,13 @@ impl ChunkSections {
let section_index = relative_y / BiomePalette::SIZE; let section_index = relative_y / BiomePalette::SIZE;
let relative_y = relative_y % BiomePalette::SIZE; let relative_y = relative_y % BiomePalette::SIZE;
self.sections[section_index] if let Some(section) = self.sections.get_mut(section_index) {
section
.biomes .biomes
.set(relative_x, relative_y, relative_z, biome_id); .set(relative_x, relative_y, relative_z, biome_id);
} }
} }
}
impl ChunkData { impl ChunkData {
/// Gets the given block in the chunk /// Gets the given block in the chunk

View File

@ -29,7 +29,8 @@ impl<V: Hash + Eq + Copy, const DIM: usize> HeterogeneousPaletteData<V, DIM> {
self.cube[y][z][x] self.cube[y][z][x]
} }
fn set(&mut self, x: usize, y: usize, z: usize, value: V) { /// Returns the Original
fn set(&mut self, x: usize, y: usize, z: usize, value: V) -> V {
debug_assert!(x < DIM); debug_assert!(x < DIM);
debug_assert!(y < DIM); debug_assert!(y < DIM);
debug_assert!(z < DIM); debug_assert!(z < DIM);
@ -48,6 +49,7 @@ impl<V: Hash + Eq + Copy, const DIM: usize> HeterogeneousPaletteData<V, DIM> {
.entry(value) .entry(value)
.and_modify(|count| *count += 1) .and_modify(|count| *count += 1)
.or_insert(1); .or_insert(1);
original
} }
} }
@ -191,24 +193,27 @@ impl<V: Hash + Eq + Copy + Default, const DIM: usize> PalettedContainer<V, DIM>
} }
} }
pub fn set(&mut self, x: usize, y: usize, z: usize, value: V) { pub fn set(&mut self, x: usize, y: usize, z: usize, value: V) -> V {
debug_assert!(x < Self::SIZE); debug_assert!(x < Self::SIZE);
debug_assert!(y < Self::SIZE); debug_assert!(y < Self::SIZE);
debug_assert!(z < Self::SIZE); debug_assert!(z < Self::SIZE);
match self { match self {
Self::Homogeneous(original) => { Self::Homogeneous(original) => {
if value != *original { let original = *original;
let mut cube = Box::new([[[*original; DIM]; DIM]; DIM]); if value != original {
let mut cube = Box::new([[[original; DIM]; DIM]; DIM]);
cube[y][z][x] = value; cube[y][z][x] = value;
*self = Self::from_cube(cube); *self = Self::from_cube(cube);
} }
original
} }
Self::Heterogeneous(data) => { Self::Heterogeneous(data) => {
data.set(x, y, z, value); let original = data.set(x, y, z, value);
if data.counts.len() == 1 { if data.counts.len() == 1 {
*self = Self::Homogeneous(*data.counts.keys().next().unwrap()); *self = Self::Homogeneous(*data.counts.keys().next().unwrap());
} }
original
} }
} }
} }

View File

@ -90,24 +90,34 @@ impl WorldGenerator for VanillaGenerator {
proto_chunk.generate_features(level, block_registry); proto_chunk.generate_features(level, block_registry);
for y in 0..biome_coords::from_block(generation_settings.shape.height) { for y in 0..biome_coords::from_block(generation_settings.shape.height) {
let relative_y = y as usize;
let section_index = relative_y / BiomePalette::SIZE;
let relative_y = relative_y % BiomePalette::SIZE;
if let Some(section) = sections.sections.get_mut(section_index) {
for z in 0..BiomePalette::SIZE { for z in 0..BiomePalette::SIZE {
for x in 0..BiomePalette::SIZE { for x in 0..BiomePalette::SIZE {
let absolute_y = let absolute_y =
biome_coords::from_block(generation_settings.shape.min_y as i32) + y as i32; biome_coords::from_block(generation_settings.shape.min_y as i32)
+ y as i32;
let biome = let biome =
proto_chunk.get_biome(&Vector3::new(x as i32, absolute_y, z as i32)); proto_chunk.get_biome(&Vector3::new(x as i32, absolute_y, z as i32));
sections.set_relative_biome(x, y as usize, z, biome.id); section.biomes.set(x, relative_y, z, biome.id);
}
} }
} }
} }
for y in 0..generation_settings.shape.height { for y in 0..generation_settings.shape.height {
let relative_y = (y as i32 - sections.min_y) as usize;
let section_index = relative_y / BlockPalette::SIZE;
let relative_y = relative_y % BlockPalette::SIZE;
if let Some(section) = sections.sections.get_mut(section_index) {
for z in 0..BlockPalette::SIZE { for z in 0..BlockPalette::SIZE {
for x in 0..BlockPalette::SIZE { for x in 0..BlockPalette::SIZE {
let absolute_y = generation_settings.shape.min_y as i32 + y as i32; let absolute_y = generation_settings.shape.min_y as i32 + y as i32;
let block = let block = proto_chunk
proto_chunk.get_block_state(&Vector3::new(x as i32, absolute_y, z as i32)); .get_block_state(&Vector3::new(x as i32, absolute_y, z as i32));
sections.set_relative_block(x, y as usize, z, block.0); section.block_states.set(x, relative_y, z, block.0);
}
} }
} }
} }

View File

@ -621,23 +621,15 @@ impl Level {
let chunk = self.get_chunk(chunk_coordinate).await; let chunk = self.get_chunk(chunk_coordinate).await;
let mut chunk = chunk.write().await; let mut chunk = chunk.write().await;
let replaced_block_state_id = chunk let replaced_block_state_id = chunk.section.set_block_absolute_y(
.section
.get_block_absolute_y(relative.x as usize, relative.y, relative.z as usize)
.unwrap();
if replaced_block_state_id == block_state_id {
return block_state_id;
}
chunk.mark_dirty(true);
chunk.section.set_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
relative.z as usize, relative.z as usize,
block_state_id, block_state_id,
); );
if replaced_block_state_id != block_state_id {
chunk.mark_dirty(true);
}
replaced_block_state_id replaced_block_state_id
} }

View File

@ -1836,7 +1836,6 @@ impl World {
} }
/// Sets a block and returns the old block id /// Sets a block and returns the old block id
#[expect(clippy::too_many_lines)]
pub async fn set_block_state( pub async fn set_block_state(
self: &Arc<Self>, self: &Arc<Self>,
position: &BlockPos, position: &BlockPos,
@ -1850,26 +1849,17 @@ impl World {
else { else {
panic!("Timed out while waiting to acquire chunk write lock") panic!("Timed out while waiting to acquire chunk write lock")
}; };
let Some(replaced_block_state_id) = chunk.section.get_block_absolute_y( let replaced_block_state_id = chunk.section.set_block_absolute_y(
relative.x as usize,
relative.y,
relative.z as usize,
) else {
return block_state_id;
};
if replaced_block_state_id == block_state_id {
return block_state_id;
}
chunk.mark_dirty(true);
chunk.section.set_block_absolute_y(
relative.x as usize, relative.x as usize,
relative.y, relative.y,
relative.z as usize, relative.z as usize,
block_state_id, block_state_id,
); );
if replaced_block_state_id == block_state_id {
return block_state_id;
}
chunk.mark_dirty(true);
self.unsent_block_changes self.unsent_block_changes
.lock() .lock()
.await .await