mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-04 17:23:33 +01:00
core: merge entity data for all regions into one file
Introduce the EntityCollector, using the TileCollector and TileMerger traits.
This commit is contained in:
parent
1143396068
commit
cde6a4b6e6
3 changed files with 132 additions and 1 deletions
|
@ -141,6 +141,8 @@ pub struct Config {
|
||||||
pub processed_dir: PathBuf,
|
pub processed_dir: PathBuf,
|
||||||
/// Path for storage of processed entity data files
|
/// Path for storage of processed entity data files
|
||||||
pub entities_dir: PathBuf,
|
pub entities_dir: PathBuf,
|
||||||
|
/// Path for storage of the final merged processed entity data file
|
||||||
|
pub entities_path_final: PathBuf,
|
||||||
/// Path of viewer metadata file
|
/// Path of viewer metadata file
|
||||||
pub metadata_path: PathBuf,
|
pub metadata_path: PathBuf,
|
||||||
}
|
}
|
||||||
|
@ -157,7 +159,8 @@ impl Config {
|
||||||
let region_dir = [&args.input_dir, Path::new("region")].iter().collect();
|
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 level_dat_path = [&args.input_dir, Path::new("level.dat")].iter().collect();
|
||||||
let processed_dir: PathBuf = [&args.output_dir, Path::new("processed")].iter().collect();
|
let processed_dir: PathBuf = [&args.output_dir, Path::new("processed")].iter().collect();
|
||||||
let entities_dir = [&processed_dir, Path::new("entities")].iter().collect();
|
let entities_dir: PathBuf = [&processed_dir, Path::new("entities")].iter().collect();
|
||||||
|
let entities_path_final = [&entities_dir, Path::new("entities.bin")].iter().collect();
|
||||||
let metadata_path = [&args.output_dir, Path::new("info.json")].iter().collect();
|
let metadata_path = [&args.output_dir, Path::new("info.json")].iter().collect();
|
||||||
|
|
||||||
Config {
|
Config {
|
||||||
|
@ -167,6 +170,7 @@ impl Config {
|
||||||
output_dir: args.output_dir.clone(),
|
output_dir: args.output_dir.clone(),
|
||||||
processed_dir,
|
processed_dir,
|
||||||
entities_dir,
|
entities_dir,
|
||||||
|
entities_path_final,
|
||||||
metadata_path,
|
metadata_path,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
123
src/core/entity_collector.rs
Normal file
123
src/core/entity_collector.rs
Normal file
|
@ -0,0 +1,123 @@
|
||||||
|
//! The [EntityCollector]
|
||||||
|
|
||||||
|
use std::path::Path;
|
||||||
|
|
||||||
|
use anyhow::{Context, Result};
|
||||||
|
use tracing::{info, warn};
|
||||||
|
|
||||||
|
use super::{common::*, tile_collector::TileCollector, tile_merger::TileMerger};
|
||||||
|
use crate::io::{fs, storage};
|
||||||
|
|
||||||
|
/// Generates mipmap tiles from full-resolution tile images
|
||||||
|
pub struct EntityCollector<'a> {
|
||||||
|
/// Common MinedMap configuration from command line
|
||||||
|
config: &'a Config,
|
||||||
|
/// List of populated tiles for base mipmap level (level 0)
|
||||||
|
regions: &'a [TileCoords],
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TileMerger for EntityCollector<'a> {
|
||||||
|
fn file_meta_version(&self) -> fs::FileMetaVersion {
|
||||||
|
ENTITIES_FILE_META_VERSION
|
||||||
|
}
|
||||||
|
|
||||||
|
fn tile_path(&self, level: usize, coords: TileCoords) -> std::path::PathBuf {
|
||||||
|
self.config.entities_path(level, coords)
|
||||||
|
}
|
||||||
|
|
||||||
|
fn write_tile(
|
||||||
|
&self,
|
||||||
|
file: &mut std::io::BufWriter<std::fs::File>,
|
||||||
|
sources: &[super::tile_merger::Source],
|
||||||
|
) -> Result<()> {
|
||||||
|
Self::merge_entity_lists(file, sources.iter().map(|source| &source.1))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> TileCollector for EntityCollector<'a> {
|
||||||
|
type CollectOutput = ();
|
||||||
|
|
||||||
|
fn tiles(&self) -> &[TileCoords] {
|
||||||
|
self.regions
|
||||||
|
}
|
||||||
|
|
||||||
|
fn prepare(&self, level: usize) -> Result<()> {
|
||||||
|
fs::create_dir_all(&self.config.entities_dir(level))
|
||||||
|
}
|
||||||
|
|
||||||
|
fn finish(
|
||||||
|
&self,
|
||||||
|
_level: usize,
|
||||||
|
_outputs: impl Iterator<Item = Self::CollectOutput>,
|
||||||
|
) -> Result<()> {
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
fn collect_one(
|
||||||
|
&self,
|
||||||
|
level: usize,
|
||||||
|
coords: TileCoords,
|
||||||
|
prev: &TileCoordMap,
|
||||||
|
) -> Result<Self::CollectOutput> {
|
||||||
|
self.merge_tiles(level, coords, prev)?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<'a> EntityCollector<'a> {
|
||||||
|
/// Constructs a new EntityCollector
|
||||||
|
pub fn new(config: &'a Config, regions: &'a [TileCoords]) -> Self {
|
||||||
|
EntityCollector { config, regions }
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Merges multiple entity lists into one
|
||||||
|
fn merge_entity_lists<P: AsRef<Path>>(
|
||||||
|
file: &mut std::io::BufWriter<std::fs::File>,
|
||||||
|
sources: impl Iterator<Item = P>,
|
||||||
|
) -> Result<()> {
|
||||||
|
let mut output = ProcessedEntities::default();
|
||||||
|
|
||||||
|
for source_path in sources {
|
||||||
|
let mut source: ProcessedEntities =
|
||||||
|
match storage::read_file(source_path.as_ref(), storage::Format::Json) {
|
||||||
|
Ok(source) => source,
|
||||||
|
Err(err) => {
|
||||||
|
warn!(
|
||||||
|
"Failed to read entity data file {}: {:?}",
|
||||||
|
source_path.as_ref().display(),
|
||||||
|
err,
|
||||||
|
);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
output.block_entities.append(&mut source.block_entities);
|
||||||
|
}
|
||||||
|
|
||||||
|
storage::write(file, &output, storage::Format::Json).context("Failed to write entity data")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Runs the mipmap generation
|
||||||
|
pub fn run(self) -> Result<()> {
|
||||||
|
info!("Collecting entity data...");
|
||||||
|
|
||||||
|
let tile_stack = self.collect_tiles()?;
|
||||||
|
|
||||||
|
// Final merge
|
||||||
|
let level = tile_stack.len() - 1;
|
||||||
|
let tile_map = &tile_stack[level];
|
||||||
|
let sources: Vec<_> = [(-1, -1), (-1, 0), (0, -1), (0, 0)]
|
||||||
|
.into_iter()
|
||||||
|
.map(|(x, z)| TileCoords { x, z })
|
||||||
|
.filter(|&coords| tile_map.contains(coords))
|
||||||
|
.map(|coords| self.tile_path(level, coords))
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
fs::create_with_tmpfile(&self.config.entities_path_final, |file| {
|
||||||
|
Self::merge_entity_lists(file, sources.iter())
|
||||||
|
})?;
|
||||||
|
|
||||||
|
info!("Collected entity data.");
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
}
|
|
@ -1,6 +1,7 @@
|
||||||
//! Core functions of the MinedMap CLI
|
//! Core functions of the MinedMap CLI
|
||||||
|
|
||||||
mod common;
|
mod common;
|
||||||
|
mod entity_collector;
|
||||||
mod metadata_writer;
|
mod metadata_writer;
|
||||||
mod region_group;
|
mod region_group;
|
||||||
mod region_processor;
|
mod region_processor;
|
||||||
|
@ -21,6 +22,8 @@ use region_processor::RegionProcessor;
|
||||||
use tile_mipmapper::TileMipmapper;
|
use tile_mipmapper::TileMipmapper;
|
||||||
use tile_renderer::TileRenderer;
|
use tile_renderer::TileRenderer;
|
||||||
|
|
||||||
|
use self::entity_collector::EntityCollector;
|
||||||
|
|
||||||
/// MinedMap version number
|
/// MinedMap version number
|
||||||
const VERSION: &str = git_version!(
|
const VERSION: &str = git_version!(
|
||||||
args = ["--abbrev=7", "--match=v*", "--dirty=-modified"],
|
args = ["--abbrev=7", "--match=v*", "--dirty=-modified"],
|
||||||
|
@ -77,6 +80,7 @@ pub fn cli() -> Result<()> {
|
||||||
let regions = RegionProcessor::new(&config).run()?;
|
let regions = RegionProcessor::new(&config).run()?;
|
||||||
TileRenderer::new(&config, &rt, ®ions).run()?;
|
TileRenderer::new(&config, &rt, ®ions).run()?;
|
||||||
let tiles = TileMipmapper::new(&config, ®ions).run()?;
|
let tiles = TileMipmapper::new(&config, ®ions).run()?;
|
||||||
|
EntityCollector::new(&config, ®ions).run()?;
|
||||||
MetadataWriter::new(&config, &tiles).run()?;
|
MetadataWriter::new(&config, &tiles).run()?;
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
Loading…
Add table
Reference in a new issue