Anvil: Added LV4 Compression

This commit is contained in:
Snowiiii 2024-10-14 16:24:52 +02:00
parent df80ac2837
commit 3eacf1e6c0
6 changed files with 62 additions and 24 deletions

20
Cargo.lock generated
View File

@ -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",

View File

@ -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

View File

@ -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<Self> {
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<u8>) -> Result<Vec<u8>, 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!(),
}
}
}

View File

@ -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 {

View File

@ -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<i32>],
channel: mpsc::Sender<Result<Arc<ChunkData>, WorldError>>,
channel: mpsc::Sender<Arc<ChunkData>>,
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);
})

View File

@ -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;