diff --git a/src/lib.rs b/src/lib.rs index 146b296..54ea8b7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,2 +1,3 @@ pub mod io; pub mod types; +pub mod world; diff --git a/src/main.rs b/src/main.rs index a30eb95..2f104ed 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,20 @@ -fn main() { - println!("Hello, world!"); +use std::path::PathBuf; + +use anyhow::Result; +use clap::Parser; + +#[derive(Debug, Parser)] +struct Args { + /// Filename to dump + file: PathBuf, +} + +fn main() -> Result<()> { + let args = Args::parse(); + + minedmap::io::region::from_file(args.file.as_path())?.foreach_chunk( + |coords, value: minedmap::world::de::Chunk| { + println!("Chunk {:?}: {:#?}", coords, value); + }, + ) } diff --git a/src/world/de.rs b/src/world/de.rs new file mode 100644 index 0000000..ead4687 --- /dev/null +++ b/src/world/de.rs @@ -0,0 +1,101 @@ +//! Data structures used to deserialize Minecraft save data + +use serde::Deserialize; + +/// Element of the `palette` list of 1.18+ [block states](BlockStatesV1_18) +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct BlockStatePaletteEntry { + pub name: String, +} + +/// 1.18+ `block_states` element found in a [section](SectionV1_18) +#[derive(Debug, Deserialize)] +pub struct BlockStatesV1_18 { + pub palette: Vec, + pub data: Option, +} + +/// 1.18+ `biomes` element found in a [section](SectionV1_18) +#[derive(Debug, Deserialize)] +pub struct BiomesV1_18 { + pub palette: Vec, + pub data: Option, +} + +/// Element of the 1.18+ `sections` list found in a [Chunk] +#[derive(Debug, Deserialize)] +pub struct SectionV1_18 { + #[serde(rename = "Y")] + pub y: i32, + pub block_states: BlockStatesV1_18, + pub biomes: BiomesV1_18, + #[serde(rename = "BlockLight")] + pub block_light: Option, +} + +/// Version-specific part of a pre-1.18 [Section](SectionOld) +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum SectionOldVariants { + #[serde(rename_all = "PascalCase")] + V1_13 { + block_states: fastnbt::LongArray, + palette: Vec, + }, + #[serde(rename_all = "PascalCase")] + Old { + blocks: fastnbt::ByteArray, + data: fastnbt::ByteArray, + }, + Empty {}, +} + +/// Pre-1.18 section element found in the [Level](LevelOld) compound +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct SectionOld { + pub y: i8, + pub block_light: Option, + #[serde(flatten)] + pub section: SectionOldVariants, +} + +/// Pre-1.18 biome fields found in the [Level](LevelOld) compound +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum BiomesOld { + IntArray(fastnbt::IntArray), + ByteArray(fastnbt::ByteArray), +} + +/// `Level` compound element found in pre-1.18 [chunks](Chunk) +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct LevelOld { + #[serde(default)] + pub sections: Vec, + pub biomes: Option, +} + +/// Version-specific part of a [Chunk] compound +#[derive(Debug, Deserialize)] +#[serde(untagged)] +pub enum ChunkVariants { + V1_18 { + sections: Vec, + }, + #[serde(rename_all = "PascalCase")] + Old { + level: LevelOld, + }, +} + +/// Toplevel compound element of a Minecraft chunk +#[derive(Debug, Deserialize)] +#[serde(rename_all = "PascalCase")] +pub struct Chunk { + pub data_version: Option, + #[serde(flatten)] + pub chunk: ChunkVariants, +} diff --git a/src/world/mod.rs b/src/world/mod.rs new file mode 100644 index 0000000..7bbc60f --- /dev/null +++ b/src/world/mod.rs @@ -0,0 +1 @@ +pub mod de;