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

View file

@ -1,175 +0,0 @@
//! Common data types and functions used by multiple generation steps
use std::{
collections::{BTreeMap, BTreeSet},
fmt::Debug,
path::{Path, PathBuf},
};
use indexmap::IndexSet;
use serde::{Deserialize, Serialize};
use super::core::{io::fs::FileMetaVersion, resource::Biome, types::*, world::layer};
/// MinedMap data version number
///
/// Increase to force regeneration of all output files
pub const FILE_META_VERSION: FileMetaVersion = FileMetaVersion(0);
/// Coordinate pair of a generated tile
///
/// Each tile corresponds to one Minecraft region file
#[derive(Clone, Copy, PartialEq, Eq, PartialOrd, Ord, Hash)]
pub struct TileCoords {
/// The X coordinate
pub x: i32,
/// The Z coordinate
pub z: i32,
}
impl Debug for TileCoords {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
write!(f, "({}, {})", self.x, self.z)
}
}
/// Set of tile coordinates
///
/// Used to store list of populated tiles for each mipmap level in the
/// viewer metadata file.
#[derive(Debug, Clone, Default, Serialize)]
#[serde(transparent)]
pub struct TileCoordMap(pub BTreeMap<i32, BTreeSet<i32>>);
impl TileCoordMap {
/// Checks whether the map contains a given coordinate pair
pub fn contains(&self, coords: TileCoords) -> bool {
let Some(xs) = self.0.get(&coords.z) else {
return false;
};
xs.contains(&coords.x)
}
}
/// Data structure for storing chunk data between processing and rendering steps
#[derive(Debug, Clone, Serialize, Deserialize)]
pub struct ProcessedChunk {
/// Block type data
pub blocks: Box<layer::BlockArray>,
/// Biome data
pub biomes: Box<layer::BiomeArray>,
/// Block height/depth data
pub depths: Box<layer::DepthArray>,
}
/// Data structure for storing region data between processing and rendering steps
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
pub struct ProcessedRegion {
/// List of biomes used in the region
///
/// Indexed by [ProcessedChunk] biome data
pub biome_list: IndexSet<Biome>,
/// Processed chunk data
pub chunks: ChunkArray<Option<Box<ProcessedChunk>>>,
}
/// Derives a filename from region coordinates and a file extension
///
/// Can be used for input regions, processed data or rendered tiles
fn coord_filename(coords: TileCoords, ext: &str) -> String {
format!("r.{}.{}.{}", coords.x, coords.z, ext)
}
/// Tile kind corresponding to a map layer
#[derive(Debug, Clone, Copy)]
pub enum TileKind {
/// Regular map tile contains block colors
Map,
/// Lightmap tile for illumination layer
Lightmap,
}
/// Common configuration based on command line arguments
pub struct Config {
/// Number of threads for parallel processing
pub num_threads: usize,
/// Path of input region directory
pub region_dir: PathBuf,
/// Path of input `level.dat` file
pub level_dat_path: PathBuf,
/// Base path for storage of rendered tile data
pub output_dir: PathBuf,
/// Path for storage of intermediate processed data files
pub processed_dir: PathBuf,
/// Path of viewer metadata file
pub metadata_path: PathBuf,
}
impl Config {
/// Crates a new [Config] from [command line arguments](super::Args)
pub fn new(args: &super::Args) -> Self {
let num_threads = match args.jobs {
Some(0) => num_cpus::get(),
Some(threads) => threads,
None => 1,
};
let region_dir = [&args.input_dir, Path::new("region")].iter().collect();
let level_dat_path = [&args.input_dir, Path::new("level.dat")].iter().collect();
let processed_dir = [&args.output_dir, Path::new("processed")].iter().collect();
let metadata_path = [&args.output_dir, Path::new("info.json")].iter().collect();
Config {
num_threads,
region_dir,
level_dat_path,
output_dir: args.output_dir.clone(),
processed_dir,
metadata_path,
}
}
/// Constructs the path to an input region file
pub fn region_path(&self, coords: TileCoords) -> PathBuf {
let filename = coord_filename(coords, "mca");
[&self.region_dir, Path::new(&filename)].iter().collect()
}
/// Constructs the path of an intermediate processed region file
pub fn processed_path(&self, coords: TileCoords) -> PathBuf {
let filename = coord_filename(coords, "bin");
[&self.processed_dir, Path::new(&filename)].iter().collect()
}
/// Constructs the base output path for a [TileKind] and mipmap level
pub fn tile_dir(&self, kind: TileKind, level: usize) -> PathBuf {
let prefix = match kind {
TileKind::Map => "map",
TileKind::Lightmap => "light",
};
let dir = format!("{}/{}", prefix, level);
[&self.output_dir, Path::new(&dir)].iter().collect()
}
/// Constructs the path of an output tile image
pub fn tile_path(&self, kind: TileKind, level: usize, coords: TileCoords) -> PathBuf {
let filename = coord_filename(coords, "png");
let dir = self.tile_dir(kind, level);
[Path::new(&dir), Path::new(&filename)].iter().collect()
}
}
/// Copies a chunk image into a region tile
pub fn overlay_chunk<I, J>(image: &mut I, chunk: &J, coords: ChunkCoords)
where
I: image::GenericImage,
J: image::GenericImageView<Pixel = I::Pixel>,
{
image::imageops::overlay(
image,
chunk,
coords.x.0 as i64 * BLOCKS_PER_CHUNK as i64,
coords.z.0 as i64 * BLOCKS_PER_CHUNK as i64,
);
}