Skip to content

Commit

Permalink
Add more comment about Mojang's implementation
Browse files Browse the repository at this point in the history
  • Loading branch information
KAIYOHUGO committed May 15, 2024
1 parent fcefa22 commit 7b0b9ca
Showing 1 changed file with 24 additions and 13 deletions.
37 changes: 24 additions & 13 deletions examples/mcpe/src/main.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,16 @@
use miniz_oxide::deflate::{compress_to_vec, compress_to_vec_zlib};
use miniz_oxide::deflate::{compress_to_vec, compress_to_vec_zlib, CompressionLevel};
use miniz_oxide::inflate::{decompress_to_vec, decompress_to_vec_zlib};
use rusty_leveldb::compressor::NoneCompressor;
use rusty_leveldb::{Compressor, CompressorList, Options, DB};
use std::rc::Rc;

/// A zlib compressor that with zlib wrapper
///
/// This is use for old world format
struct ZlibCompressor(u8);

impl ZlibCompressor {
/// level 0-10
/// compression level 0-10
pub fn new(level: u8) -> Self {
assert!(level <= 10);
Self(level)
Expand All @@ -34,13 +36,13 @@ impl Compressor for ZlibCompressor {
/// >
/// > From [zlib manual](https://zlib.net/manual.html)
///
/// It seems like mojang use this most
///
/// A copy of mojang's implementation can be find [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/db/zlib_compressor.cc#L119).
/// It seems like Mojang use this for newer version
///
/// A copy of Mojang's implementation can be find [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/db/zlib_compressor.cc#L119).
struct RawZlibCompressor(u8);

impl RawZlibCompressor {
/// level 0-10
/// compression level 0-10
pub fn new(level: u8) -> Self {
assert!(level <= 10);
Self(level)
Expand All @@ -63,30 +65,39 @@ impl Compressor for RawZlibCompressor {
pub fn mcpe_options(compression_level: u8) -> Options {
let mut opt = Options::default();

// compressor id list can be find in [mojang's implementation](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/include/leveldb/c.h#L194-L200)
// And it seems like mojang don't use slippy or zstd of minecraft bedrock
// Mojang create a custom [compressor list](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/include/leveldb/options.h#L123)
// Sample config for compressor list can be find in [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/mcpe_sample_setup.cpp#L24-L28)
//
// If you need to open old world, old world fallback compressor can be find [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/bedrock_leveldb.c#L152-L153)
// Their compression id can be find in [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/include/leveldb/zlib_compressor.h#L38)
// and [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/include/leveldb/zlib_compressor.h#L48)
//
// Compression id will be use in [here](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/table/format.cc#L125-L150)
let mut list = CompressorList::new();
list.set_with_id(0, NoneCompressor::default());
list.set_with_id(2, ZlibCompressor::new(compression_level));
list.set_with_id(4, RawZlibCompressor::new(compression_level));
opt.compressor_list = Rc::new(list);

// Set compressor
// Minecraft bedrock may use other id than 4
// Minecraft bedrock may use other id than 4 however default is 4. [Mojang's implementation](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/table/table_builder.cc#L152)
//
// There is a bug in this library that you have to open a database with the same compression type as it was written to.
// If raw data is smaller than compression, Mojang will use raw data. [Mojang's implementation](https://github.com/reedacartwright/rbedrock/blob/fb32a899da4e15c1aaa0d6de2b459e914e183516/src/leveldb-mcpe/table/table_builder.cc#L155-L165)
// There is a small chance that compression id 0 exists, you should use compression id 0 to write it.
opt.compressor = 4;

opt
}

/// Path to world's db folder
const PATH: &str = "mcpe_db";

/// Mojang use `DefaultLevel` for world compression
const COMPRESSION_LEVEL: u8 = CompressionLevel::DefaultLevel as u8;

fn main() {
let path = "mcpe_db";
const COMPRESSION_LEVEL: u8 = 10;
let opt = mcpe_options(COMPRESSION_LEVEL);
let mut db = DB::open(path, opt).unwrap();
let mut db = DB::open(PATH, opt).unwrap();
db.put(b"~local_player", b"NBT data goes here").unwrap();
let value = db.get(b"~local_player").unwrap();
assert_eq!(&value, b"NBT data goes here")
Expand Down

0 comments on commit 7b0b9ca

Please sign in to comment.