Skip to content

Commit

Permalink
use Subchunks instead of ChunkBlocks (#458)
Browse files Browse the repository at this point in the history
* first not error version, but crashibg

* small fix for not crashing

* fmt & clippy

* docs

* Update mod.rs

* Update mod.rs

* Update mod.rs

* Update mod.rs

* Update mod.rs

* Update mod.rs

Update mod.rs

Update mod.rs

Update mod.rs

Update mod.rs

* fixes

* fmt

* fixes

* fix: anvil

also improve `array_iter` function

---------

Co-authored-by: Alexander Medvedev <[email protected]>
  • Loading branch information
suprohub and Snowiiii authored Jan 9, 2025
1 parent 9cfbb32 commit 4494432
Show file tree
Hide file tree
Showing 8 changed files with 203 additions and 97 deletions.
26 changes: 14 additions & 12 deletions pumpkin-protocol/src/client/play/c_chunk_data.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,10 @@ use crate::{bytebuf::ByteBufMut, codec::bit_set::BitSet, ClientPacket, VarInt};

use bytes::{BufMut, BytesMut};
use pumpkin_macros::client_packet;
use pumpkin_world::{chunk::ChunkData, DIRECT_PALETTE_BITS};
use pumpkin_world::{
chunk::{ChunkData, SUBCHUNKS_COUNT},
DIRECT_PALETTE_BITS,
};

#[client_packet("play:level_chunk_with_light")]
pub struct CChunkData<'a>(pub &'a ChunkData);
Expand All @@ -14,19 +17,18 @@ impl ClientPacket for CChunkData<'_> {
// Chunk Z
buf.put_i32(self.0.position.z);

let heightmap_nbt =
pumpkin_nbt::serializer::to_bytes_unnamed(&self.0.blocks.heightmap).unwrap();
let heightmap_nbt = pumpkin_nbt::serializer::to_bytes_unnamed(&self.0.heightmap).unwrap();
// Heightmaps
buf.put_slice(&heightmap_nbt);

let mut data_buf = BytesMut::new();
self.0.blocks.iter_subchunks().for_each(|chunk| {
let block_count = chunk.len() as i16;
self.0.subchunks.array_iter().for_each(|subchunk| {
let block_count = subchunk.len() as i16;
// Block count
data_buf.put_i16(block_count);
//// Block states

let palette = chunk;
let palette = &subchunk;
// TODO: make dynamic block_size work
// TODO: make direct block_size work
enum PaletteType {
Expand Down Expand Up @@ -58,11 +60,11 @@ impl ClientPacket for CChunkData<'_> {
data_buf.put_var_int(&VarInt(*id as i32));
});
// Data array length
let data_array_len = chunk.len().div_ceil(64 / block_size as usize);
let data_array_len = subchunk.len().div_ceil(64 / block_size as usize);
data_buf.put_var_int(&VarInt(data_array_len as i32));

data_buf.reserve(data_array_len * 8);
for block_clump in chunk.chunks(64 / block_size as usize) {
for block_clump in subchunk.chunks(64 / block_size as usize) {
let mut out_long: i64 = 0;
for block in block_clump.iter().rev() {
let index = palette
Expand All @@ -78,11 +80,11 @@ impl ClientPacket for CChunkData<'_> {
// Bits per entry
data_buf.put_u8(DIRECT_PALETTE_BITS as u8);
// Data array length
let data_array_len = chunk.len().div_ceil(64 / DIRECT_PALETTE_BITS as usize);
let data_array_len = subchunk.len().div_ceil(64 / DIRECT_PALETTE_BITS as usize);
data_buf.put_var_int(&VarInt(data_array_len as i32));

data_buf.reserve(data_array_len * 8);
for block_clump in chunk.chunks(64 / DIRECT_PALETTE_BITS as usize) {
for block_clump in subchunk.chunks(64 / DIRECT_PALETTE_BITS as usize) {
let mut out_long: i64 = 0;
let mut shift = 0;
for block in block_clump {
Expand Down Expand Up @@ -121,8 +123,8 @@ impl ClientPacket for CChunkData<'_> {
// Empty Block Light Mask
buf.put_bit_set(&BitSet(VarInt(1), vec![0]));

buf.put_var_int(&VarInt(self.0.blocks.subchunks_len() as i32));
self.0.blocks.iter_subchunks().for_each(|chunk| {
buf.put_var_int(&VarInt(SUBCHUNKS_COUNT as i32));
self.0.subchunks.array_iter().for_each(|chunk| {
let mut chunk_light = [0u8; 2048];
for (i, _) in chunk.iter().enumerate() {
// if !block .is_air() {
Expand Down
11 changes: 4 additions & 7 deletions pumpkin-world/src/chunk/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -357,7 +357,7 @@ impl AnvilChunkFormat {
pub fn to_bytes(&self, chunk_data: &ChunkData) -> Result<Vec<u8>, ChunkSerializingError> {
let mut sections = Vec::new();

for (i, blocks) in chunk_data.blocks.iter_subchunks().enumerate() {
for (i, blocks) in chunk_data.subchunks.array_iter().enumerate() {
// get unique blocks
let unique_blocks: HashSet<_> = blocks.iter().collect();

Expand All @@ -384,7 +384,7 @@ impl AnvilChunkFormat {
// Empty data if the palette only contains one index https://minecraft.fandom.com/wiki/Chunk_format
// if palette.len() > 1 {}
// TODO: Update to write empty data. Rn or read does not handle this elegantly
for block in blocks {
for block in blocks.iter() {
// Push if next bit does not fit
if bits_used_in_pack + block_bit_size as u32 > 64 {
section_longs.push(current_pack_long);
Expand Down Expand Up @@ -430,7 +430,7 @@ impl AnvilChunkFormat {
x_pos: chunk_data.position.x,
z_pos: chunk_data.position.z,
status: super::ChunkStatus::Full,
heightmaps: chunk_data.blocks.heightmap.clone(),
heightmaps: chunk_data.heightmap.clone(),
sections,
};

Expand Down Expand Up @@ -545,10 +545,7 @@ mod tests {
.iter()
.find(|chunk| chunk.position == *at)
.expect("Missing chunk");
assert_eq!(
chunk.blocks.blocks, read_chunk.blocks.blocks,
"Chunks don't match"
);
assert_eq!(chunk.subchunks, read_chunk.subchunks, "Chunks don't match");
}
}

Expand Down
Loading

0 comments on commit 4494432

Please sign in to comment.