minedmap: write info.json file with tilemap metadata

With this change, the new minedmap implementation can generate all
necessary data for the frontend to work.
This commit is contained in:
Matthias Schiffer 2023-07-02 23:09:14 +02:00
parent 429b7888f6
commit 757f6ff166
Signed by: neocturne
GPG key ID: 16EF3F64CB201D9C
5 changed files with 143 additions and 2 deletions

24
Cargo.lock generated
View file

@ -325,6 +325,12 @@ dependencies = [
"either",
]
[[package]]
name = "itoa"
version = "1.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "453ad9f582a441959e5f0d088b02ce04cfe8d51a8eaf077f12ac6d3e94164ca6"
[[package]]
name = "jobserver"
version = "0.1.26"
@ -372,6 +378,7 @@ dependencies = [
"itertools",
"num-integer",
"serde",
"serde_json",
"zstd",
]
@ -471,6 +478,12 @@ dependencies = [
"windows-sys",
]
[[package]]
name = "ryu"
version = "1.0.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f91339c0467de62360649f8d3e185ca8de4224ff281f66000de5eb2a77a79041"
[[package]]
name = "serde"
version = "1.0.164"
@ -500,6 +513,17 @@ dependencies = [
"syn",
]
[[package]]
name = "serde_json"
version = "1.0.99"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "46266871c240a00b8f503b877622fe33430b3c7d963bdc0f2adc511e54a1eae3"
dependencies = [
"itoa",
"ryu",
"serde",
]
[[package]]
name = "simd-adler32"
version = "0.3.5"

View file

@ -20,6 +20,7 @@ image = { version = "0.24.5", default-features = false, features = ["png"] }
itertools = "0.11.0"
num-integer = "0.1.45"
serde = "1.0.152"
serde_json = "1.0.99"
zstd = "0.12.3"
[features]

View file

@ -20,7 +20,8 @@ impl Debug for TileCoords {
}
}
#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone, Default, Serialize)]
#[serde(transparent)]
pub struct TileCoordMap(pub BTreeMap<i32, BTreeSet<i32>>);
impl TileCoordMap {
@ -45,6 +46,8 @@ pub struct Config {
pub region_dir: PathBuf,
pub processed_dir: PathBuf,
pub output_dir: PathBuf,
pub level_dat_path: PathBuf,
pub metadata_path: PathBuf,
}
fn coord_filename(coords: TileCoords, ext: &str) -> String {
@ -61,11 +64,15 @@ impl Config {
pub fn new(args: super::Args) -> Self {
let region_dir = [&args.input_dir, Path::new("region")].iter().collect();
let processed_dir = [&args.output_dir, Path::new("processed")].iter().collect();
let level_dat_path = [&args.input_dir, Path::new("level.dat")].iter().collect();
let metadata_path = [&args.output_dir, Path::new("info.json")].iter().collect();
Config {
region_dir,
processed_dir,
output_dir: args.output_dir,
level_dat_path,
metadata_path,
}
}

View file

@ -1,4 +1,5 @@
mod common;
mod metadata_writer;
mod region_processor;
mod tile_mipmapper;
mod tile_renderer;
@ -9,6 +10,7 @@ use anyhow::Result;
use clap::Parser;
use common::Config;
use metadata_writer::MetadataWriter;
use region_processor::RegionProcessor;
use tile_mipmapper::TileMipmapper;
use tile_renderer::TileRenderer;
@ -27,7 +29,8 @@ fn main() -> Result<()> {
let regions = RegionProcessor::new(&config).run()?;
TileRenderer::new(&config).run(&regions)?;
TileMipmapper::new(&config).run(&regions)?;
let tiles = TileMipmapper::new(&config).run(&regions)?;
MetadataWriter::new(&config).run(tiles)?;
Ok(())
}

View file

@ -0,0 +1,106 @@
use anyhow::{Context, Result};
use minedmap::{io::fs, world::de};
use serde::Serialize;
use super::common::*;
pub struct MetadataWriter<'a> {
config: &'a Config,
}
#[derive(Debug, Serialize)]
#[serde(rename_all = "camelCase")]
struct Bounds {
min_x: i32,
max_x: i32,
min_z: i32,
max_z: i32,
}
#[derive(Debug, Serialize)]
struct Mipmap<'t> {
bounds: Bounds,
regions: &'t TileCoordMap,
}
#[derive(Debug, Serialize)]
struct Spawn {
x: i32,
z: i32,
}
#[derive(Debug, Serialize)]
struct Metadata<'t> {
mipmaps: Vec<Mipmap<'t>>,
spawn: Spawn,
}
impl<'a> MetadataWriter<'a> {
pub fn new(config: &'a Config) -> Self {
MetadataWriter { config }
}
fn mipmap_entry(regions: &TileCoordMap) -> Mipmap {
let mut min_x = i32::MAX;
let mut max_x = i32::MIN;
let mut min_z = i32::MAX;
let mut max_z = i32::MIN;
for (&z, xs) in &regions.0 {
if z < min_z {
min_z = z;
}
if z > max_z {
max_z = z;
}
for &x in xs {
if x < min_x {
min_x = x;
}
if x > max_x {
max_x = x;
}
}
}
Mipmap {
bounds: Bounds {
min_x,
max_x,
min_z,
max_z,
},
regions,
}
}
fn read_level_dat(&self) -> Result<de::LevelDat> {
minedmap::io::data::from_file(&self.config.level_dat_path)
.context("Failed to read level.dat")
}
fn spawn(level_dat: &de::LevelDat) -> Spawn {
Spawn {
x: level_dat.data.spawn_x,
z: level_dat.data.spawn_z,
}
}
pub fn run(&self, tiles: Vec<TileCoordMap>) -> Result<()> {
let level_dat = self.read_level_dat()?;
let mut metadata = Metadata {
mipmaps: Vec::new(),
spawn: Self::spawn(&level_dat),
};
for tile_map in tiles.iter() {
metadata.mipmaps.push(Self::mipmap_entry(tile_map));
}
fs::create_with_tmpfile(&self.config.metadata_path, |file| {
serde_json::to_writer(file, &metadata).context("Failed to write metadata")
})
}
}