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)
[![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)
![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>

View File

@@ -94,7 +94,7 @@ pub struct ChunkEntityData {
#[derive(Debug, Clone)]
pub struct ChunkSections {
pub sections: Box<[SubChunk]>,
min_y: i32,
pub min_y: i32,
}
impl ChunkSections {
@@ -179,18 +179,19 @@ impl ChunkSections {
}
}
/// Returns the replaced block state ID
pub fn set_block_absolute_y(
&mut self,
relative_x: usize,
y: i32,
relative_z: usize,
block_state: BlockStateId,
) {
) -> BlockStateId {
let y = y - self.min_y;
debug_assert!(y >= 0);
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
@@ -210,7 +211,7 @@ impl ChunkSections {
.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]
pub fn set_relative_block(
&mut self,
@@ -218,9 +219,9 @@ impl ChunkSections {
relative_y: usize,
relative_z: usize,
block_state_id: BlockStateId,
) {
) -> BlockStateId {
// 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
@@ -234,20 +235,20 @@ impl ChunkSections {
relative_y: usize,
relative_z: usize,
block_state_id: BlockStateId,
) {
) -> BlockStateId {
debug_assert!(relative_x < BlockPalette::SIZE);
debug_assert!(relative_z < BlockPalette::SIZE);
let section_index = relative_y / BlockPalette::SIZE;
let relative_y = relative_y % BlockPalette::SIZE;
if let Some(section) = self.sections.get_mut(section_index) {
section
return section
.block_states
.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(
&mut self,
relative_x: usize,
@@ -260,9 +261,11 @@ impl ChunkSections {
let section_index = relative_y / BiomePalette::SIZE;
let relative_y = relative_y % BiomePalette::SIZE;
self.sections[section_index]
.biomes
.set(relative_x, relative_y, relative_z, biome_id);
if let Some(section) = self.sections.get_mut(section_index) {
section
.biomes
.set(relative_x, relative_y, relative_z, biome_id);
}
}
}

View File

@@ -29,7 +29,8 @@ impl<V: Hash + Eq + Copy, const DIM: usize> HeterogeneousPaletteData<V, DIM> {
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!(y < DIM);
debug_assert!(z < DIM);
@@ -48,6 +49,7 @@ impl<V: Hash + Eq + Copy, const DIM: usize> HeterogeneousPaletteData<V, DIM> {
.entry(value)
.and_modify(|count| *count += 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!(y < Self::SIZE);
debug_assert!(z < Self::SIZE);
match self {
Self::Homogeneous(original) => {
if value != *original {
let mut cube = Box::new([[[*original; DIM]; DIM]; DIM]);
let original = *original;
if value != original {
let mut cube = Box::new([[[original; DIM]; DIM]; DIM]);
cube[y][z][x] = value;
*self = Self::from_cube(cube);
}
original
}
Self::Heterogeneous(data) => {
data.set(x, y, z, value);
let original = data.set(x, y, z, value);
if data.counts.len() == 1 {
*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);
for y in 0..biome_coords::from_block(generation_settings.shape.height) {
for z in 0..BiomePalette::SIZE {
for x in 0..BiomePalette::SIZE {
let absolute_y =
biome_coords::from_block(generation_settings.shape.min_y as i32) + y as i32;
let biome =
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);
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 x in 0..BiomePalette::SIZE {
let absolute_y =
biome_coords::from_block(generation_settings.shape.min_y as i32)
+ y as i32;
let biome =
proto_chunk.get_biome(&Vector3::new(x as i32, absolute_y, z as i32));
section.biomes.set(x, relative_y, z, biome.id);
}
}
}
}
for y in 0..generation_settings.shape.height {
for z in 0..BlockPalette::SIZE {
for x in 0..BlockPalette::SIZE {
let absolute_y = generation_settings.shape.min_y as i32 + y as i32;
let block =
proto_chunk.get_block_state(&Vector3::new(x as i32, absolute_y, z as i32));
sections.set_relative_block(x, y as usize, z, block.0);
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 x in 0..BlockPalette::SIZE {
let absolute_y = generation_settings.shape.min_y as i32 + y as i32;
let block = proto_chunk
.get_block_state(&Vector3::new(x as i32, absolute_y, z as i32));
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 mut chunk = chunk.write().await;
let replaced_block_state_id = chunk
.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(
let replaced_block_state_id = chunk.section.set_block_absolute_y(
relative.x as usize,
relative.y,
relative.z as usize,
block_state_id,
);
if replaced_block_state_id != block_state_id {
chunk.mark_dirty(true);
}
replaced_block_state_id
}

View File

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