Restructure crates

Get rid of the arbitrary bin/lib split and instead move as much as
possible into the bin crate, which becomes the main crate again.

The types and NBT handling are moved into separate crates, so they can
be reused by nbtdump and regiondump.
This commit is contained in:
Matthias Schiffer 2023-08-20 16:28:10 +02:00
parent 09399f5ae9
commit 248a641035
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
21 changed files with 121 additions and 62 deletions

25
Cargo.lock generated
View file

@ -558,17 +558,16 @@ version = "0.1.0"
dependencies = [
"anyhow",
"bincode",
"bytemuck",
"clap",
"enumflags2",
"fastnbt",
"flate2",
"futures-util",
"glam",
"image",
"indexmap",
"itertools",
"lru",
"minedmap-nbt",
"minedmap-types",
"num-integer",
"num_cpus",
"rayon",
@ -579,6 +578,26 @@ dependencies = [
"zstd",
]
[[package]]
name = "minedmap-nbt"
version = "0.1.0"
dependencies = [
"anyhow",
"bytemuck",
"fastnbt",
"flate2",
"minedmap-types",
"serde",
]
[[package]]
name = "minedmap-types"
version = "0.1.0"
dependencies = [
"itertools",
"serde",
]
[[package]]
name = "miniz_oxide"
version = "0.7.1"

View file

@ -1,3 +1,6 @@
[workspace]
members = ["crates/*"]
[package]
name = "minedmap"
version = "0.1.0"
@ -5,23 +8,19 @@ edition = "2021"
license = "MIT"
default-run = "minedmap"
[lib]
name = "minedmap_core"
[dependencies]
anyhow = "1.0.68"
bincode = "1.3.3"
bytemuck = "1.13.0"
clap = { version = "4.1.4", features = ["derive"] }
enumflags2 = { version = "0.7.5", features = ["serde"] }
fastnbt = "2.3.2"
flate2 = "1.0.25"
futures-util = "0.3.28"
glam = "0.24.0"
image = { version = "0.24.5", default-features = false, features = ["png"] }
indexmap = { version = "2.0.0", features = ["serde"] }
itertools = "0.11.0"
lru = "0.11.0"
minedmap-nbt = { version = "0.1.0", path = "crates/nbt", default-features = false }
minedmap-types = { version = "0.1.0", path = "crates/types" }
num-integer = "0.1.45"
num_cpus = "1.16.0"
rayon = "1.7.0"
@ -33,4 +32,4 @@ zstd = "0.12.3"
[features]
default = ["zlib-ng"]
zlib-ng = ["flate2/zlib-ng"]
zlib-ng = ["minedmap-nbt/zlib-ng"]

17
crates/nbt/Cargo.toml Normal file
View file

@ -0,0 +1,17 @@
[package]
name = "minedmap-nbt"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
anyhow = "1.0.75"
bytemuck = "1.13.1"
fastnbt = "2.4.4"
flate2 = "1.0.27"
minedmap-types = { version = "0.1.0", path = "../types" }
serde = "1.0.183"
[features]
zlib-ng = ["flate2/zlib-ng"]

7
crates/nbt/src/lib.rs Normal file
View file

@ -0,0 +1,7 @@
//! MinedMap's of Minecraft NBT data and region files
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
pub mod data;
pub mod region;

View file

@ -10,7 +10,7 @@ use anyhow::{bail, Context, Result};
use flate2::read::ZlibDecoder;
use serde::de::DeserializeOwned;
use crate::types::*;
use minedmap_types::*;
/// Data block size of region data files
///

10
crates/types/Cargo.toml Normal file
View file

@ -0,0 +1,10 @@
[package]
name = "minedmap-types"
version = "0.1.0"
edition = "2021"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
itertools = "0.11.0"
serde = "1.0.183"

View file

@ -1,5 +1,8 @@
//! Common types used by MinedMap
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
use std::{
fmt::Debug,
iter::FusedIterator,
@ -32,6 +35,7 @@ macro_rules! coord_type {
/// Constructs a new value
///
/// Will panic if the value is not in the valid range
#[inline]
pub fn new<T: TryInto<u8>>(value: T) -> Self {
Self(
value
@ -43,6 +47,7 @@ macro_rules! coord_type {
}
/// Returns an iterator over all possible values of the type
#[inline]
pub fn iter() -> impl Iterator<Item = $t<AXIS>>
+ DoubleEndedIterator
+ ExactSizeIterator
@ -95,6 +100,7 @@ impl LayerBlockCoords {
/// Many chunk data structures store block and biome data in the same
/// order. This method computes the offset at which the data for the
/// block at a given coordinate is stored.
#[inline]
pub fn offset(&self) -> usize {
use BLOCKS_PER_CHUNK as N;
let x = self.x.0 as usize;
@ -112,12 +118,14 @@ pub struct LayerBlockArray<T>(pub [[T; BLOCKS_PER_CHUNK]; BLOCKS_PER_CHUNK]);
impl<T> Index<LayerBlockCoords> for LayerBlockArray<T> {
type Output = T;
#[inline]
fn index(&self, index: LayerBlockCoords) -> &Self::Output {
&self.0[index.z.0 as usize][index.x.0 as usize]
}
}
impl<T> IndexMut<LayerBlockCoords> for LayerBlockArray<T> {
#[inline]
fn index_mut(&mut self, index: LayerBlockCoords) -> &mut Self::Output {
&mut self.0[index.z.0 as usize][index.x.0 as usize]
}
@ -138,6 +146,7 @@ impl SectionBlockCoords {
/// Many chunk data structures store block and biome data in the same
/// order. This method computes the offset at which the data for the
/// block at a given coordinate is stored.
#[inline]
pub fn offset(&self) -> usize {
use BLOCKS_PER_CHUNK as N;
let y = self.y.0 as usize;
@ -194,16 +203,19 @@ pub struct ChunkArray<T>(pub [[T; CHUNKS_PER_REGION]; CHUNKS_PER_REGION]);
impl<T> ChunkArray<T> {
/// Iterates over all possible chunk coordinate pairs used as [ChunkArray] keys
#[inline]
pub fn keys() -> impl Iterator<Item = ChunkCoords> + Clone + Debug {
iproduct!(ChunkZ::iter(), ChunkX::iter()).map(|(z, x)| ChunkCoords { x, z })
}
/// Iterates over all values stored in the [ChunkArray]
#[inline]
pub fn values(&self) -> impl Iterator<Item = &T> + Clone + Debug {
Self::keys().map(|k| &self[k])
}
/// Iterates over pairs of chunk coordinate pairs and corresponding stored values
#[inline]
pub fn iter(&self) -> impl Iterator<Item = (ChunkCoords, &T)> + Clone + Debug {
Self::keys().map(|k| (k, &self[k]))
}
@ -212,12 +224,14 @@ impl<T> ChunkArray<T> {
impl<T> Index<ChunkCoords> for ChunkArray<T> {
type Output = T;
#[inline]
fn index(&self, index: ChunkCoords) -> &Self::Output {
&self.0[index.z.0 as usize][index.x.0 as usize]
}
}
impl<T> IndexMut<ChunkCoords> for ChunkArray<T> {
#[inline]
fn index_mut(&mut self, index: ChunkCoords) -> &mut Self::Output {
&mut self.0[index.z.0 as usize][index.x.0 as usize]
}

View file

@ -18,7 +18,7 @@ struct Args {
fn main() -> Result<()> {
let args = Args::parse();
let value: fastnbt::Value = minedmap_core::io::data::from_file(args.file.as_path())?;
let value: fastnbt::Value = minedmap_nbt::data::from_file(args.file.as_path())?;
println!("{:#x?}", value);
Ok(())

View file

@ -18,7 +18,7 @@ struct Args {
fn main() -> Result<()> {
let args = Args::parse();
minedmap_core::io::region::from_file(args.file.as_path())?.foreach_chunk(
minedmap_nbt::region::from_file(args.file.as_path())?.foreach_chunk(
|coords, value: fastnbt::Value| {
println!("Chunk {:?}: {:#x?}", coords, value);
Ok(())

View file

@ -9,7 +9,7 @@ use std::{
use indexmap::IndexSet;
use serde::{Deserialize, Serialize};
use super::core::{io::fs::FileMetaVersion, resource::Biome, types::*, world::layer};
use crate::{io::fs::FileMetaVersion, resource::Biome, types::*, world::layer};
/// MinedMap data version number
///

View file

@ -3,10 +3,7 @@
use anyhow::{Context, Result};
use serde::Serialize;
use super::{
common::*,
core::{self, io::fs, world::de},
};
use crate::{core::common::*, io::fs, world::de};
/// Minimum and maximum X and Z tile coordinates for a mipmap level
#[derive(Debug, Serialize)]
@ -101,7 +98,7 @@ impl<'a> MetadataWriter<'a> {
/// Reads and deserializes the `level.dat` of the Minecraft save data
fn read_level_dat(&self) -> Result<de::LevelDat> {
core::io::data::from_file(&self.config.level_dat_path).context("Failed to read level.dat")
crate::nbt::data::from_file(&self.config.level_dat_path).context("Failed to read level.dat")
}
/// Generates [Spawn] data from a [de::LevelDat]

View file

@ -1,7 +1,4 @@
//! The minedmap generator renders map tile images from Minecraft save data
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
//! Core functions of the MinedMap CLI
mod common;
mod metadata_writer;
@ -10,8 +7,6 @@ mod region_processor;
mod tile_mipmapper;
mod tile_renderer;
use minedmap_core as core;
use std::path::PathBuf;
use anyhow::{Context, Result};
@ -46,7 +41,8 @@ fn setup_threads(num_threads: usize) -> Result<()> {
.context("Failed to configure thread pool")
}
fn main() -> Result<()> {
/// MinedMap CLI main function
pub fn cli() -> Result<()> {
let args = Args::parse();
let config = Config::new(&args);

View file

@ -6,17 +6,14 @@ use anyhow::{Context, Result};
use indexmap::IndexSet;
use rayon::prelude::*;
use super::{
common::*,
core::{
use super::common::*;
use crate::{
io::{fs, storage},
resource::{self, Biome},
types::*,
world::{
self,
io::{fs, storage},
resource::{self, Biome},
types::*,
world::{
self,
layer::{self, LayerData},
},
layer::{self, LayerData},
},
};
@ -157,7 +154,7 @@ impl<'a> RegionProcessor<'a> {
println!("Processing region r.{}.{}.mca", coords.x, coords.z);
core::io::region::from_file(path)?.foreach_chunk(
crate::nbt::region::from_file(path)?.foreach_chunk(
|chunk_coords, data: world::de::Chunk| {
let Some(layer::LayerData {
blocks,

View file

@ -3,10 +3,8 @@
use anyhow::{Context, Result};
use rayon::prelude::*;
use super::{
common::*,
core::{io::fs, types::*},
};
use super::common::*;
use crate::{io::fs, types::*};
/// Generates mipmap tiles from full-resolution tile images
pub struct TileMipmapper<'a> {

View file

@ -13,15 +13,12 @@ use lru::LruCache;
use rayon::prelude::*;
use tokio::sync::OnceCell;
use super::{
common::*,
core::{
io::{fs, storage},
resource::{block_color, needs_biome},
types::*,
util::coord_offset,
},
region_group::RegionGroup,
use super::{common::*, region_group::RegionGroup};
use crate::{
io::{fs, storage},
resource::{block_color, needs_biome},
types::*,
util::coord_offset,
};
/// Type for referencing loaded [ProcessedRegion] data

View file

@ -1,6 +1,4 @@
//! Input/output functions
pub mod data;
pub mod fs;
pub mod region;
pub mod storage;

View file

@ -1,10 +0,0 @@
//! Common library for MinedMap generator and dump utilities
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
pub mod io;
pub mod resource;
pub mod types;
pub mod util;
pub mod world;

19
src/main.rs Normal file
View file

@ -0,0 +1,19 @@
//! The minedmap generator renders map tile images from Minecraft save data
#![warn(missing_docs)]
#![warn(clippy::missing_docs_in_private_items)]
mod core;
mod io;
mod resource;
mod util;
mod world;
use minedmap_nbt as nbt;
use minedmap_types as types;
use anyhow::Result;
fn main() -> Result<()> {
core::cli()
}

View file

@ -46,6 +46,7 @@ pub struct BlockType {
impl BlockType {
/// Checks whether a block type has a given [BlockFlag] set
#[inline]
pub fn is(&self, flag: BlockFlag) -> bool {
self.flags.contains(flag)
}