Skip to content

Commit

Permalink
write x_pos and z_pos
Browse files Browse the repository at this point in the history
  • Loading branch information
Snowiiii committed Dec 23, 2024
1 parent 9b184f7 commit 6d49ba8
Show file tree
Hide file tree
Showing 2 changed files with 78 additions and 52 deletions.
70 changes: 42 additions & 28 deletions pumpkin-world/src/chunk/anvil.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ use std::{
use bytes::*;
use fastnbt::LongArray;
use flate2::bufread::{GzDecoder, GzEncoder, ZlibDecoder, ZlibEncoder};
use pumpkin_core::math::ceil_log2;

use crate::{
block::block_registry::BLOCK_ID_TO_REGISTRY_ID, chunk::ChunkWritingError, level::LevelFolder,
Expand Down Expand Up @@ -219,19 +220,7 @@ impl ChunkWriter for AnvilChunkFormat {
at: &pumpkin_core::math::vector2::Vector2<i32>,
) -> Result<(), super::ChunkWritingError> {
// TODO: update timestamp

let bytes = self
.to_bytes(chunk_data)
.map_err(|err| ChunkWritingError::ChunkSerializingError(err.to_string()))?;
// TODO: config
let compression = Compression::ZLib;
let bytes = compression
// TODO: config
.compress_data(&bytes, 6)
.map_err(ChunkWritingError::Compression)?;

let region = (at.x >> 5, at.z >> 5);

let mut region_file = OpenOptions::new()
.read(true)
.write(true)
Expand All @@ -244,15 +233,26 @@ impl ChunkWriter for AnvilChunkFormat {
)
.map_err(|err| ChunkWritingError::IoError(err.kind()))?;

let bytes = self
.to_bytes(chunk_data)
.map_err(|err| ChunkWritingError::ChunkSerializingError(err.to_string()))?;
// TODO: config
let compression = Compression::ZLib;
let bytes = compression
// TODO: config
.compress_data(&bytes, 6)
.map_err(ChunkWritingError::Compression)?;

let mut location_table: [u8; 4096] = [0; 4096];
let mut timestamp_table: [u8; 4096] = [0; 4096];

let file_meta = region_file
.metadata()
.map_err(|err| ChunkWritingError::IoError(err.kind()))?;

// The header consists of 8 KiB of data
// fill the location and timestamp tables if they exist
if file_meta.len() >= 4096 * 2 {
if file_meta.len() >= 8192 {
region_file
.read_exact(&mut location_table)
.map_err(|err| ChunkWritingError::IoError(err.kind()))?;
Expand Down Expand Up @@ -390,8 +390,11 @@ impl ChunkWriter for AnvilChunkFormat {
)
});

let sector_count = (bytes.len() + 4).div_ceil(4096) * 4096;

// padding
region_file
.write_all(&vec![0u8; 4096])
.write_all(&vec![0u8; sector_count])
.expect("Failed to add padding");

Ok(())
Expand All @@ -418,22 +421,31 @@ impl AnvilChunkFormat {
}),
);

let block_bit_size = {
let size = 64 - (palette.len() as i64 - 1).leading_zeros();
std::cmp::max(4, size)
} as usize;
let blocks_in_pack = 64 / block_bit_size;
let mut section_longs = Vec::new();

let mut current_pack_long = 0i64;
let block_bit_size = if palette.len() < 16 {
4
} else {
ceil_log2(palette.len() as u32).max(4)
};
let _blocks_in_pack = 64 / block_bit_size;

for block_pack in blocks.chunks(blocks_in_pack) {
for block in block_pack {
let index = palette.get(block).expect("Just added all unique").1;
current_pack_long = current_pack_long << block_bit_size | index as i64;
let mut section_longs = Vec::new();
let mut current_pack_long: i64 = 0;
let mut bits_used_in_pack: u32 = 0;

for block in blocks {
let index = palette.get(block).expect("Just added all unique").1;
current_pack_long |= (index as i64) << bits_used_in_pack;
bits_used_in_pack += block_bit_size as u32;

if bits_used_in_pack >= 64 {
section_longs.push(current_pack_long);
current_pack_long = 0;
bits_used_in_pack = 0;
}
}

if bits_used_in_pack > 0 {
section_longs.push(current_pack_long);
current_pack_long = 0;
}

sections.push(ChunkSection {
Expand All @@ -444,7 +456,7 @@ impl AnvilChunkFormat {
.into_iter()
.map(|entry| PaletteEntry {
name: entry.1 .0.clone(),
_properties: None,
properties: None,
})
.collect(),
}),
Expand All @@ -453,6 +465,8 @@ impl AnvilChunkFormat {

let nbt = ChunkNbt {
data_version: WORLD_DATA_VERSION,
x_pos: chunk_data.position.x,
z_pos: chunk_data.position.z,
status: super::ChunkStatus::Full,
heightmaps: chunk_data.blocks.heightmap.clone(),
sections,
Expand Down
60 changes: 36 additions & 24 deletions pumpkin-world/src/chunk/mod.rs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
use fastnbt::LongArray;
use pumpkin_core::math::vector2::Vector2;
use pumpkin_core::math::{ceil_log2, vector2::Vector2};
use serde::{Deserialize, Serialize};
use std::cmp::max;
use std::collections::HashMap;
use std::ops::Index;
use thiserror::Error;
Expand Down Expand Up @@ -92,15 +91,9 @@ pub struct ChunkBlocks {
#[derive(Serialize, Deserialize, Debug, Clone)]
#[serde(rename_all = "PascalCase")]
struct PaletteEntry {
// bloc name
name: String,
_properties: Option<HashMap<String, String>>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct ChunkSectionBlockStates {
// #[serde(with = "LongArray")]
data: Option<LongArray>,
palette: Vec<PaletteEntry>,
properties: Option<HashMap<String, String>>,
}

#[derive(Deserialize, Serialize, Debug, Clone)]
Expand All @@ -119,17 +112,24 @@ struct ChunkSection {
block_states: Option<ChunkSectionBlockStates>,
}

#[derive(Serialize, Deserialize, Debug, Clone)]
struct ChunkSectionBlockStates {
// #[serde(with = "LongArray")]
data: Option<LongArray>,
palette: Vec<PaletteEntry>,
}

#[derive(Serialize, Deserialize, Debug)]
#[serde(rename_all = "PascalCase")]
struct ChunkNbt {
data_version: i32,
status: ChunkStatus,
// #[serde(rename = "xPos")]
// x_pos: i32,
#[serde(rename = "xPos")]
x_pos: i32,
// #[serde(rename = "yPos")]
// y_pos: i32,
// #[serde(rename = "zPos")]
// z_pos: i32,
//y_pos: i32,
#[serde(rename = "zPos")]
z_pos: i32,
status: ChunkStatus,
#[serde(rename = "sections")]
sections: Vec<ChunkSection>,
heightmaps: ChunkHeightmaps,
Expand Down Expand Up @@ -262,7 +262,10 @@ pub struct ChunkStatusWrapper {
}

impl ChunkData {
pub fn from_bytes(chunk_data: &[u8], at: Vector2<i32>) -> Result<Self, ChunkParsingError> {
pub fn from_bytes(
chunk_data: &[u8],
position: Vector2<i32>,
) -> Result<Self, ChunkParsingError> {
if fastnbt::from_bytes::<ChunkStatusWrapper>(chunk_data)
.map_err(|_| ChunkParsingError::FailedReadStatus)?
.status
Expand All @@ -274,6 +277,17 @@ impl ChunkData {
let chunk_data = fastnbt::from_bytes::<ChunkNbt>(chunk_data)
.map_err(|e| ChunkParsingError::ErrorDeserializingChunk(e.to_string()))?;

if chunk_data.x_pos != position.x || chunk_data.z_pos != position.z {
log::error!(
"Expected chunk at {}:{}, but got {}:{}",
position.x,
position.z,
chunk_data.x_pos,
chunk_data.z_pos
);
// lets still continue
}

// this needs to be boxed, otherwise it will cause a stack-overflow
let mut blocks = ChunkBlocks::empty_with_heightmap(chunk_data.heightmaps);
let mut block_index = 0; // which block we're currently at
Expand Down Expand Up @@ -305,9 +319,10 @@ impl ChunkData {
};

// How many bits each block has in one of the palette u64s
let block_bit_size = {
let size = 64 - (palette.len() as i64 - 1).leading_zeros();
max(4, size)
let block_bit_size = if palette.len() < 16 {
4
} else {
ceil_log2(palette.len() as u32).max(4)
};
// How many blocks there are in one of the palettes u64s
let blocks_in_palette = 64 / block_bit_size;
Expand Down Expand Up @@ -341,10 +356,7 @@ impl ChunkData {
}
}

Ok(ChunkData {
blocks,
position: at,
})
Ok(ChunkData { blocks, position })
}
}

Expand Down

0 comments on commit 6d49ba8

Please sign in to comment.