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" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "a7a70ba024b9dc04c27ea2f0c0548feb474ec5c54bba33a7f72f873a39d07b24" 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]] [[package]]
name = "mach2" name = "mach2"
version = "0.4.2" version = "0.4.2"
@ -2022,6 +2041,7 @@ dependencies = [
"futures", "futures",
"itertools 0.13.0", "itertools 0.13.0",
"log", "log",
"lz4",
"noise", "noise",
"num-derive", "num-derive",
"num-traits", "num-traits",

View File

@ -14,7 +14,12 @@ derive_more.workspace = true
itertools.workspace = true itertools.workspace = true
thiserror = "1.0" thiserror = "1.0"
futures = "0.3" futures = "0.3"
# Compression
flate2 = "1.0" flate2 = "1.0"
lz4 = "1.11.1"
serde.workspace = true serde.workspace = true
serde_json = "1.0" serde_json = "1.0"
log.workspace = true log.workspace = true

View File

@ -26,41 +26,60 @@ impl AnvilChunkReader {
#[derive(Debug, Clone, Copy, PartialEq, Eq)] #[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub enum Compression { pub enum Compression {
Gzip, /// GZip Compression
Zlib, GZip,
/// ZLib Compression
ZLib,
/// Uncompressed (since a version before 1.15.1)
None, None,
/// LZ4 Compression (since 24w04a)
LZ4, LZ4,
/// Custom compression algorithm (since 24w05a)
Custom,
} }
impl Compression { impl Compression {
pub fn from_byte(byte: u8) -> Option<Self> { pub fn from_byte(byte: u8) -> Option<Self> {
match byte { match byte {
1 => Some(Self::Gzip), 1 => Some(Self::GZip),
2 => Some(Self::Zlib), 2 => Some(Self::ZLib),
3 => Some(Self::None), 3 => Some(Self::None),
4 => Some(Self::LZ4), 4 => Some(Self::LZ4),
// Creative i guess?
127 => Some(Self::Custom),
_ => None, _ => None,
} }
} }
fn decompress_data(&self, compressed_data: Vec<u8>) -> Result<Vec<u8>, CompressionError> { fn decompress_data(&self, compressed_data: Vec<u8>) -> Result<Vec<u8>, CompressionError> {
match self { match self {
Compression::Gzip => { Compression::GZip => {
let mut z = GzDecoder::new(&compressed_data[..]); let mut decoder = GzDecoder::new(&compressed_data[..]);
let mut chunk_data = Vec::with_capacity(compressed_data.len()); let mut chunk_data = Vec::new();
z.read_to_end(&mut chunk_data) decoder
.read_to_end(&mut chunk_data)
.map_err(CompressionError::GZipError)?; .map_err(CompressionError::GZipError)?;
Ok(chunk_data) Ok(chunk_data)
} }
Compression::Zlib => { Compression::ZLib => {
let mut z = ZlibDecoder::new(&compressed_data[..]); let mut decoder = ZlibDecoder::new(&compressed_data[..]);
let mut chunk_data = Vec::with_capacity(compressed_data.len()); let mut chunk_data = Vec::new();
z.read_to_end(&mut chunk_data) decoder
.read_to_end(&mut chunk_data)
.map_err(CompressionError::ZlibError)?; .map_err(CompressionError::ZlibError)?;
Ok(chunk_data) Ok(chunk_data)
} }
Compression::None => Ok(compressed_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), ZlibError(std::io::Error),
#[error("Error while working with Gzip compression: {0}")] #[error("Error while working with Gzip compression: {0}")]
GZipError(std::io::Error), GZipError(std::io::Error),
#[error("Error while working with LZ4 compression: {0}")]
LZ4Error(std::io::Error),
} }
pub struct ChunkData { pub struct ChunkData {

View File

@ -3,7 +3,6 @@ use std::{collections::HashMap, path::PathBuf, sync::Arc};
use parking_lot::Mutex; use parking_lot::Mutex;
use pumpkin_core::math::vector2::Vector2; use pumpkin_core::math::vector2::Vector2;
use rayon::prelude::*; use rayon::prelude::*;
use thiserror::Error;
use tokio::sync::mpsc; use tokio::sync::mpsc;
use crate::{ use crate::{
@ -33,9 +32,6 @@ pub struct SaveFile {
pub region_folder: PathBuf, pub region_folder: PathBuf,
} }
#[derive(Error, Debug)]
pub enum WorldError {}
impl Level { impl Level {
pub fn from_root_folder(root_folder: PathBuf) -> Self { pub fn from_root_folder(root_folder: PathBuf) -> Self {
let world_gen = get_world_gen(Seed(0)); // TODO Read Seed from config. let world_gen = get_world_gen(Seed(0)); // TODO Read Seed from config.
@ -79,7 +75,7 @@ impl Level {
pub fn fetch_chunks( pub fn fetch_chunks(
&self, &self,
chunks: &[Vector2<i32>], chunks: &[Vector2<i32>],
channel: mpsc::Sender<Result<Arc<ChunkData>, WorldError>>, channel: mpsc::Sender<Arc<ChunkData>>,
is_alive: bool, is_alive: bool,
) { ) {
chunks.into_par_iter().for_each(|at| { chunks.into_par_iter().for_each(|at| {
@ -92,7 +88,7 @@ impl Level {
// Check if chunks is already loaded // Check if chunks is already loaded
if loaded_chunks.contains_key(at) { if loaded_chunks.contains_key(at) {
channel channel
.blocking_send(Ok(loaded_chunks.get(at).unwrap().clone())) .blocking_send(loaded_chunks.get(at).unwrap().clone())
.expect("Failed sending ChunkData."); .expect("Failed sending ChunkData.");
return; return;
} }
@ -116,7 +112,7 @@ impl Level {
.unwrap(); .unwrap();
let data = Arc::new(data); let data = Arc::new(data);
channel channel
.blocking_send(Ok(data.clone())) .blocking_send(data.clone())
.expect("Failed sending ChunkData."); .expect("Failed sending ChunkData.");
loaded_chunks.insert(at, data); loaded_chunks.insert(at, data);
}) })

View File

@ -235,10 +235,6 @@ impl World {
while let Some(chunk_data) = chunk_receiver.recv().await { while let Some(chunk_data) = chunk_receiver.recv().await {
// dbg!(chunk_pos); // dbg!(chunk_pos);
let chunk_data = match chunk_data {
Ok(d) => d,
Err(_) => continue,
};
#[cfg(debug_assertions)] #[cfg(debug_assertions)]
if chunk_data.position == (0, 0).into() { if chunk_data.position == (0, 0).into() {
use pumpkin_protocol::bytebuf::ByteBuffer; use pumpkin_protocol::bytebuf::ByteBuffer;