From 31eb92864ccb253319b8822c9cb89c1f23dc207f Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Sat, 6 May 2023 00:44:00 +0200 Subject: [PATCH] Split up BlockInfo type By storing block types and depth values separately, the processed world data can be compressed better, decreasing data size by ~10%. --- src/bin/minedmap/common.rs | 18 ++++++++------ src/bin/minedmap/region_processor.rs | 15 ++++++++---- src/bin/minedmap/tile_renderer.rs | 36 +++++++++++++--------------- src/world/layer.rs | 19 ++++++--------- 4 files changed, 45 insertions(+), 43 deletions(-) diff --git a/src/bin/minedmap/common.rs b/src/bin/minedmap/common.rs index ae645d1..eda782d 100644 --- a/src/bin/minedmap/common.rs +++ b/src/bin/minedmap/common.rs @@ -1,14 +1,18 @@ use std::path::{Path, PathBuf}; -use minedmap::{types::*, world}; +use serde::{Deserialize, Serialize}; + +use minedmap::{types::*, world::layer}; pub type RegionCoords = (i32, i32); -pub type ProcessedRegion = ChunkArray< - Option<( - Box, - Box, - )>, ->; + +#[derive(Debug, Clone, Serialize, Deserialize)] +pub struct ProcessedChunk { + pub blocks: Box, + pub biomes: Box, + pub depths: Box, +} +pub type ProcessedRegion = ChunkArray>; pub struct Config { pub region_dir: PathBuf, diff --git a/src/bin/minedmap/region_processor.rs b/src/bin/minedmap/region_processor.rs index 415cca0..e1ea187 100644 --- a/src/bin/minedmap/region_processor.rs +++ b/src/bin/minedmap/region_processor.rs @@ -6,7 +6,10 @@ use minedmap::{ io::storage, resource, types::*, - world::{self, layer::LayerData}, + world::{ + self, + layer::{self, LayerData}, + }, }; use super::common::*; @@ -104,15 +107,19 @@ impl<'a> RegionProcessor<'a> { minedmap::io::region::from_file(path)?.foreach_chunk( |chunk_coords, data: world::de::Chunk| { - let Some(layer_data) = self + let Some(layer::LayerData{ blocks, biomes, block_light, depths }) = self .process_chunk(data) .with_context(|| format!("Failed to process chunk {:?}", chunk_coords))? else { return Ok(()); }; - processed_region[chunk_coords] = Some((layer_data.blocks, layer_data.biomes)); + processed_region[chunk_coords] = Some(ProcessedChunk { + blocks, + biomes, + depths, + }); - let chunk_lightmap = Self::render_chunk_lightmap(layer_data.block_light); + let chunk_lightmap = Self::render_chunk_lightmap(block_light); overlay_chunk(&mut lightmap, &chunk_lightmap, chunk_coords); Ok(()) diff --git a/src/bin/minedmap/tile_renderer.rs b/src/bin/minedmap/tile_renderer.rs index ac1193a..3ae51c6 100644 --- a/src/bin/minedmap/tile_renderer.rs +++ b/src/bin/minedmap/tile_renderer.rs @@ -2,7 +2,7 @@ use std::fs; use anyhow::{Context, Result}; -use minedmap::{io::storage, resource::block_color, types::*, world}; +use minedmap::{io::storage, resource::block_color, types::*}; use super::common::*; @@ -20,12 +20,7 @@ impl<'a> TileRenderer<'a> { storage::read(&processed_path).context("Failed to load processed region data") } - fn render_chunk( - image: &mut image::RgbaImage, - coords: ChunkCoords, - blocks: &world::layer::BlockInfoArray, - biomes: &world::layer::BiomeArray, - ) { + fn render_chunk(image: &mut image::RgbaImage, coords: ChunkCoords, chunk: &ProcessedChunk) { const N: u32 = BLOCKS_PER_CHUNK as u32; let chunk_image = image::RgbaImage::from_fn(N, N, |x, z| { @@ -33,28 +28,29 @@ impl<'a> TileRenderer<'a> { x: BlockX(x as u8), z: BlockZ(z as u8), }; - image::Rgba(match (&blocks[coords], &biomes[coords]) { - ( - world::layer::BlockInfo { - block_type: Some(block_type), - depth: Some(depth), - .. - }, - Some(biome), - ) => block_color(*block_type, biome, depth.0 as f32), - _ => [0, 0, 0, 0], - }) + image::Rgba( + match ( + &chunk.blocks[coords], + &chunk.biomes[coords], + &chunk.depths[coords], + ) { + (Some(block), Some(biome), Some(depth)) => { + block_color(*block, biome, depth.0 as f32) + } + _ => [0, 0, 0, 0], + }, + ) }); overlay_chunk(image, &chunk_image, coords); } fn render_region(image: &mut image::RgbaImage, region: &ProcessedRegion) { for (coords, chunk) in region.iter() { - let Some((blocks, biomes)) = chunk else { + let Some(chunk) = chunk else { continue; }; - Self::render_chunk(image, coords, blocks, biomes); + Self::render_chunk(image, coords, chunk); } } diff --git a/src/world/layer.rs b/src/world/layer.rs index 4a5fe46..440c137 100644 --- a/src/world/layer.rs +++ b/src/world/layer.rs @@ -25,15 +25,10 @@ impl BlockHeight { } } -#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)] -pub struct BlockInfo { - pub block_type: Option, - pub depth: Option, -} - -pub type BlockInfoArray = LayerBlockArray; +pub type BlockArray = LayerBlockArray>; pub type BiomeArray = LayerBlockArray>; pub type BlockLightArray = LayerBlockArray; +pub type DepthArray = LayerBlockArray>; struct LayerEntry<'a> { block: &'a mut Option, @@ -80,19 +75,19 @@ impl<'a> LayerEntry<'a> { #[derive(Debug, Default)] pub struct LayerData { - pub blocks: Box, + pub blocks: Box, pub biomes: Box, pub block_light: Box, + pub depths: Box, } impl LayerData { fn entry(&mut self, coords: LayerBlockCoords) -> LayerEntry { - let block_info = &mut self.blocks[coords]; LayerEntry { - block: &mut block_info.block_type, + block: &mut self.blocks[coords], biome: &mut self.biomes[coords], block_light: &mut self.block_light[coords], - depth: &mut block_info.depth, + depth: &mut self.depths[coords], } } } @@ -116,7 +111,7 @@ pub fn top_layer(chunk: &Chunk) -> Result> { for section in chunk.sections().rev() { for y in BlockY::iter().rev() { - for xz in BlockInfoArray::keys() { + for xz in LayerBlockArray::<()>::keys() { let mut entry = ret.entry(xz); if entry.done() { continue;