mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-05 17:44:52 +01:00
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%.
This commit is contained in:
parent
0b392d7a3a
commit
31eb92864c
4 changed files with 45 additions and 43 deletions
|
@ -1,14 +1,18 @@
|
||||||
use std::path::{Path, PathBuf};
|
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 RegionCoords = (i32, i32);
|
||||||
pub type ProcessedRegion = ChunkArray<
|
|
||||||
Option<(
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
Box<world::layer::BlockInfoArray>,
|
pub struct ProcessedChunk {
|
||||||
Box<world::layer::BiomeArray>,
|
pub blocks: Box<layer::BlockArray>,
|
||||||
)>,
|
pub biomes: Box<layer::BiomeArray>,
|
||||||
>;
|
pub depths: Box<layer::DepthArray>,
|
||||||
|
}
|
||||||
|
pub type ProcessedRegion = ChunkArray<Option<ProcessedChunk>>;
|
||||||
|
|
||||||
pub struct Config {
|
pub struct Config {
|
||||||
pub region_dir: PathBuf,
|
pub region_dir: PathBuf,
|
||||||
|
|
|
@ -6,7 +6,10 @@ use minedmap::{
|
||||||
io::storage,
|
io::storage,
|
||||||
resource,
|
resource,
|
||||||
types::*,
|
types::*,
|
||||||
world::{self, layer::LayerData},
|
world::{
|
||||||
|
self,
|
||||||
|
layer::{self, LayerData},
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::common::*;
|
use super::common::*;
|
||||||
|
@ -104,15 +107,19 @@ impl<'a> RegionProcessor<'a> {
|
||||||
|
|
||||||
minedmap::io::region::from_file(path)?.foreach_chunk(
|
minedmap::io::region::from_file(path)?.foreach_chunk(
|
||||||
|chunk_coords, data: world::de::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)
|
.process_chunk(data)
|
||||||
.with_context(|| format!("Failed to process chunk {:?}", chunk_coords))?
|
.with_context(|| format!("Failed to process chunk {:?}", chunk_coords))?
|
||||||
else {
|
else {
|
||||||
return Ok(());
|
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);
|
overlay_chunk(&mut lightmap, &chunk_lightmap, chunk_coords);
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
|
|
|
@ -2,7 +2,7 @@ use std::fs;
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
|
|
||||||
use minedmap::{io::storage, resource::block_color, types::*, world};
|
use minedmap::{io::storage, resource::block_color, types::*};
|
||||||
|
|
||||||
use super::common::*;
|
use super::common::*;
|
||||||
|
|
||||||
|
@ -20,12 +20,7 @@ impl<'a> TileRenderer<'a> {
|
||||||
storage::read(&processed_path).context("Failed to load processed region data")
|
storage::read(&processed_path).context("Failed to load processed region data")
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_chunk(
|
fn render_chunk(image: &mut image::RgbaImage, coords: ChunkCoords, chunk: &ProcessedChunk) {
|
||||||
image: &mut image::RgbaImage,
|
|
||||||
coords: ChunkCoords,
|
|
||||||
blocks: &world::layer::BlockInfoArray,
|
|
||||||
biomes: &world::layer::BiomeArray,
|
|
||||||
) {
|
|
||||||
const N: u32 = BLOCKS_PER_CHUNK as u32;
|
const N: u32 = BLOCKS_PER_CHUNK as u32;
|
||||||
|
|
||||||
let chunk_image = image::RgbaImage::from_fn(N, N, |x, z| {
|
let chunk_image = image::RgbaImage::from_fn(N, N, |x, z| {
|
||||||
|
@ -33,28 +28,29 @@ impl<'a> TileRenderer<'a> {
|
||||||
x: BlockX(x as u8),
|
x: BlockX(x as u8),
|
||||||
z: BlockZ(z as u8),
|
z: BlockZ(z as u8),
|
||||||
};
|
};
|
||||||
image::Rgba(match (&blocks[coords], &biomes[coords]) {
|
image::Rgba(
|
||||||
(
|
match (
|
||||||
world::layer::BlockInfo {
|
&chunk.blocks[coords],
|
||||||
block_type: Some(block_type),
|
&chunk.biomes[coords],
|
||||||
depth: Some(depth),
|
&chunk.depths[coords],
|
||||||
..
|
) {
|
||||||
},
|
(Some(block), Some(biome), Some(depth)) => {
|
||||||
Some(biome),
|
block_color(*block, biome, depth.0 as f32)
|
||||||
) => block_color(*block_type, biome, depth.0 as f32),
|
}
|
||||||
_ => [0, 0, 0, 0],
|
_ => [0, 0, 0, 0],
|
||||||
})
|
},
|
||||||
|
)
|
||||||
});
|
});
|
||||||
overlay_chunk(image, &chunk_image, coords);
|
overlay_chunk(image, &chunk_image, coords);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn render_region(image: &mut image::RgbaImage, region: &ProcessedRegion) {
|
fn render_region(image: &mut image::RgbaImage, region: &ProcessedRegion) {
|
||||||
for (coords, chunk) in region.iter() {
|
for (coords, chunk) in region.iter() {
|
||||||
let Some((blocks, biomes)) = chunk else {
|
let Some(chunk) = chunk else {
|
||||||
continue;
|
continue;
|
||||||
};
|
};
|
||||||
|
|
||||||
Self::render_chunk(image, coords, blocks, biomes);
|
Self::render_chunk(image, coords, chunk);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,15 +25,10 @@ impl BlockHeight {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Debug, Clone, Copy, Default, Serialize, Deserialize)]
|
pub type BlockArray = LayerBlockArray<Option<BlockType>>;
|
||||||
pub struct BlockInfo {
|
|
||||||
pub block_type: Option<BlockType>,
|
|
||||||
pub depth: Option<BlockHeight>,
|
|
||||||
}
|
|
||||||
|
|
||||||
pub type BlockInfoArray = LayerBlockArray<BlockInfo>;
|
|
||||||
pub type BiomeArray = LayerBlockArray<Option<Biome>>;
|
pub type BiomeArray = LayerBlockArray<Option<Biome>>;
|
||||||
pub type BlockLightArray = LayerBlockArray<u8>;
|
pub type BlockLightArray = LayerBlockArray<u8>;
|
||||||
|
pub type DepthArray = LayerBlockArray<Option<BlockHeight>>;
|
||||||
|
|
||||||
struct LayerEntry<'a> {
|
struct LayerEntry<'a> {
|
||||||
block: &'a mut Option<BlockType>,
|
block: &'a mut Option<BlockType>,
|
||||||
|
@ -80,19 +75,19 @@ impl<'a> LayerEntry<'a> {
|
||||||
|
|
||||||
#[derive(Debug, Default)]
|
#[derive(Debug, Default)]
|
||||||
pub struct LayerData {
|
pub struct LayerData {
|
||||||
pub blocks: Box<BlockInfoArray>,
|
pub blocks: Box<BlockArray>,
|
||||||
pub biomes: Box<BiomeArray>,
|
pub biomes: Box<BiomeArray>,
|
||||||
pub block_light: Box<BlockLightArray>,
|
pub block_light: Box<BlockLightArray>,
|
||||||
|
pub depths: Box<DepthArray>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl LayerData {
|
impl LayerData {
|
||||||
fn entry(&mut self, coords: LayerBlockCoords) -> LayerEntry {
|
fn entry(&mut self, coords: LayerBlockCoords) -> LayerEntry {
|
||||||
let block_info = &mut self.blocks[coords];
|
|
||||||
LayerEntry {
|
LayerEntry {
|
||||||
block: &mut block_info.block_type,
|
block: &mut self.blocks[coords],
|
||||||
biome: &mut self.biomes[coords],
|
biome: &mut self.biomes[coords],
|
||||||
block_light: &mut self.block_light[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<Option<LayerData>> {
|
||||||
|
|
||||||
for section in chunk.sections().rev() {
|
for section in chunk.sections().rev() {
|
||||||
for y in BlockY::iter().rev() {
|
for y in BlockY::iter().rev() {
|
||||||
for xz in BlockInfoArray::keys() {
|
for xz in LayerBlockArray::<()>::keys() {
|
||||||
let mut entry = ret.entry(xz);
|
let mut entry = ret.entry(xz);
|
||||||
if entry.done() {
|
if entry.done() {
|
||||||
continue;
|
continue;
|
||||||
|
|
Loading…
Add table
Reference in a new issue