Anvil: Added LV4 Compression
This commit is contained in:
parent
df80ac2837
commit
3eacf1e6c0
20
Cargo.lock
generated
20
Cargo.lock
generated
@ -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",
|
||||||
|
|||||||
@ -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
|
||||||
|
|||||||
@ -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!(),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -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 {
|
||||||
|
|||||||
@ -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);
|
||||||
})
|
})
|
||||||
|
|||||||
@ -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;
|
||||||
|
|||||||
Loading…
Reference in New Issue
Block a user