From 3eacf1e6c0e99d7b49cb193102e188d8b20e5a9b Mon Sep 17 00:00:00 2001 From: Snowiiii Date: Mon, 14 Oct 2024 16:24:52 +0200 Subject: [PATCH] Anvil: Added LV4 Compression --- Cargo.lock | 20 ++++++++++++++ pumpkin-world/Cargo.toml | 5 ++++ pumpkin-world/src/chunk/anvil.rs | 45 +++++++++++++++++++++++--------- pumpkin-world/src/chunk/mod.rs | 2 ++ pumpkin-world/src/level.rs | 10 +++---- pumpkin/src/world/mod.rs | 4 --- 6 files changed, 62 insertions(+), 24 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9411b8069..9e3533d55 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1446,6 +1446,25 @@ version = "0.4.22" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" +[[package]] +name = "lz4" +version = "1.28.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4d1febb2b4a79ddd1980eede06a8f7902197960aa0383ffcfdd62fe723036725" +dependencies = [ + "lz4-sys", +] + +[[package]] +name = "lz4-sys" +version = "1.11.1+lz4-1.10.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6bd8c0d6c6ed0cd30b3652886bb8711dc4bb01d637a68105a3d5158039b418e6" +dependencies = [ + "cc", + "libc", +] + [[package]] name = "mach2" version = "0.4.2" @@ -2022,6 +2041,7 @@ dependencies = [ "futures", "itertools 0.13.0", "log", + "lz4", "noise", "num-derive", "num-traits", diff --git a/pumpkin-world/Cargo.toml b/pumpkin-world/Cargo.toml index 519cb081d..9a06e04fc 100644 --- a/pumpkin-world/Cargo.toml +++ b/pumpkin-world/Cargo.toml @@ -14,7 +14,12 @@ derive_more.workspace = true itertools.workspace = true thiserror = "1.0" futures = "0.3" + + +# Compression flate2 = "1.0" +lz4 = "1.11.1" + serde.workspace = true serde_json = "1.0" log.workspace = true diff --git a/pumpkin-world/src/chunk/anvil.rs b/pumpkin-world/src/chunk/anvil.rs index 07a96df7b..db3ce9032 100644 --- a/pumpkin-world/src/chunk/anvil.rs +++ b/pumpkin-world/src/chunk/anvil.rs @@ -26,41 +26,60 @@ impl AnvilChunkReader { #[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum Compression { - Gzip, - Zlib, + /// GZip Compression + GZip, + /// ZLib Compression + ZLib, + /// Uncompressed (since a version before 1.15.1) None, + /// LZ4 Compression (since 24w04a) LZ4, + /// Custom compression algorithm (since 24w05a) + Custom, } impl Compression { pub fn from_byte(byte: u8) -> Option { match byte { - 1 => Some(Self::Gzip), - 2 => Some(Self::Zlib), + 1 => Some(Self::GZip), + 2 => Some(Self::ZLib), 3 => Some(Self::None), 4 => Some(Self::LZ4), + // Creative i guess? + 127 => Some(Self::Custom), _ => None, } } fn decompress_data(&self, compressed_data: Vec) -> Result, CompressionError> { match self { - Compression::Gzip => { - let mut z = GzDecoder::new(&compressed_data[..]); - let mut chunk_data = Vec::with_capacity(compressed_data.len()); - z.read_to_end(&mut chunk_data) + Compression::GZip => { + let mut decoder = GzDecoder::new(&compressed_data[..]); + let mut chunk_data = Vec::new(); + decoder + .read_to_end(&mut chunk_data) .map_err(CompressionError::GZipError)?; Ok(chunk_data) } - Compression::Zlib => { - let mut z = ZlibDecoder::new(&compressed_data[..]); - let mut chunk_data = Vec::with_capacity(compressed_data.len()); - z.read_to_end(&mut chunk_data) + Compression::ZLib => { + let mut decoder = ZlibDecoder::new(&compressed_data[..]); + let mut chunk_data = Vec::new(); + decoder + .read_to_end(&mut chunk_data) .map_err(CompressionError::ZlibError)?; Ok(chunk_data) } Compression::None => Ok(compressed_data), - Compression::LZ4 => todo!(), + Compression::LZ4 => { + let mut decoder = lz4::Decoder::new(compressed_data.as_slice()) + .map_err(CompressionError::LZ4Error)?; + let mut decompressed_data = Vec::new(); + decoder + .read_to_end(&mut decompressed_data) + .map_err(CompressionError::LZ4Error)?; + Ok(decompressed_data) + } + Compression::Custom => todo!(), } } } diff --git a/pumpkin-world/src/chunk/mod.rs b/pumpkin-world/src/chunk/mod.rs index 6deb462eb..6a272d6a0 100644 --- a/pumpkin-world/src/chunk/mod.rs +++ b/pumpkin-world/src/chunk/mod.rs @@ -50,6 +50,8 @@ pub enum CompressionError { ZlibError(std::io::Error), #[error("Error while working with Gzip compression: {0}")] GZipError(std::io::Error), + #[error("Error while working with LZ4 compression: {0}")] + LZ4Error(std::io::Error), } pub struct ChunkData { diff --git a/pumpkin-world/src/level.rs b/pumpkin-world/src/level.rs index d4024fb0c..c210232ce 100644 --- a/pumpkin-world/src/level.rs +++ b/pumpkin-world/src/level.rs @@ -3,7 +3,6 @@ use std::{collections::HashMap, path::PathBuf, sync::Arc}; use parking_lot::Mutex; use pumpkin_core::math::vector2::Vector2; use rayon::prelude::*; -use thiserror::Error; use tokio::sync::mpsc; use crate::{ @@ -33,9 +32,6 @@ pub struct SaveFile { pub region_folder: PathBuf, } -#[derive(Error, Debug)] -pub enum WorldError {} - impl Level { pub fn from_root_folder(root_folder: PathBuf) -> Self { let world_gen = get_world_gen(Seed(0)); // TODO Read Seed from config. @@ -79,7 +75,7 @@ impl Level { pub fn fetch_chunks( &self, chunks: &[Vector2], - channel: mpsc::Sender, WorldError>>, + channel: mpsc::Sender>, is_alive: bool, ) { chunks.into_par_iter().for_each(|at| { @@ -92,7 +88,7 @@ impl Level { // Check if chunks is already loaded if loaded_chunks.contains_key(at) { channel - .blocking_send(Ok(loaded_chunks.get(at).unwrap().clone())) + .blocking_send(loaded_chunks.get(at).unwrap().clone()) .expect("Failed sending ChunkData."); return; } @@ -116,7 +112,7 @@ impl Level { .unwrap(); let data = Arc::new(data); channel - .blocking_send(Ok(data.clone())) + .blocking_send(data.clone()) .expect("Failed sending ChunkData."); loaded_chunks.insert(at, data); }) diff --git a/pumpkin/src/world/mod.rs b/pumpkin/src/world/mod.rs index 58ce26082..50c0c75d4 100644 --- a/pumpkin/src/world/mod.rs +++ b/pumpkin/src/world/mod.rs @@ -235,10 +235,6 @@ impl World { while let Some(chunk_data) = chunk_receiver.recv().await { // dbg!(chunk_pos); - let chunk_data = match chunk_data { - Ok(d) => d, - Err(_) => continue, - }; #[cfg(debug_assertions)] if chunk_data.position == (0, 0).into() { use pumpkin_protocol::bytebuf::ByteBuffer;