From e117c769375ff67317749650d513efeec6c4360b Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Fri, 7 Apr 2023 09:29:01 +0200 Subject: [PATCH] world: pass biome data into chunk/section structures --- src/main.rs | 4 +++- src/world/chunk.rs | 31 ++++++++++++++++++++++--------- src/world/section.rs | 35 ++++++++++++++++++++++++++--------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/main.rs b/src/main.rs index a0afa43..fcd588d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -96,6 +96,7 @@ where /// Type with methods for processing the regions of a Minecraft save directory struct RegionProcessor<'a> { block_types: resource::BlockTypes, + biome_types: resource::BiomeTypes, config: &'a Config, } @@ -103,6 +104,7 @@ impl<'a> RegionProcessor<'a> { fn new(config: &'a Config) -> Self { RegionProcessor { block_types: resource::BlockTypes::default(), + biome_types: resource::BiomeTypes::default(), config, } } @@ -128,7 +130,7 @@ impl<'a> RegionProcessor<'a> { Box, )>, > { - let chunk = world::chunk::Chunk::new(&data, &self.block_types)?; + let chunk = world::chunk::Chunk::new(&data, &self.block_types, &self.biome_types)?; world::layer::top_layer(&chunk) } diff --git a/src/world/chunk.rs b/src/world/chunk.rs index a9a5c6b..aa6c9a7 100644 --- a/src/world/chunk.rs +++ b/src/world/chunk.rs @@ -6,7 +6,10 @@ use std::{ use anyhow::{bail, Context, Result}; use super::{de, section::*}; -use crate::{resource::BlockTypes, types::*}; +use crate::{ + resource::{BiomeTypes, BlockTypes}, + types::*, +}; /// Chunk data structure wrapping a [de::Chunk] for convenient access to /// block and biome data @@ -64,14 +67,20 @@ pub struct SectionIter<'a> { impl<'a> Chunk<'a> { /// Creates a new [Chunk] from a deserialized [de::Chunk] - pub fn new(data: &'a de::Chunk, block_types: &'a BlockTypes) -> Result { + pub fn new( + data: &'a de::Chunk, + block_types: &'a BlockTypes, + biome_types: &'a BiomeTypes, + ) -> Result { let data_version = data.data_version.unwrap_or_default(); match &data.chunk { de::ChunkVariants::V1_18 { sections } => { - Self::new_v1_18(data_version, sections, block_types) + Self::new_v1_18(data_version, sections, block_types, biome_types) + } + de::ChunkVariants::V0 { level } => { + Self::new_v0(data_version, level, block_types, biome_types) } - de::ChunkVariants::V0 { level } => Self::new_v0(data_version, level, block_types), } } @@ -80,6 +89,7 @@ impl<'a> Chunk<'a> { data_version: u32, sections: &'a Vec, block_types: &'a BlockTypes, + biome_types: &'a BiomeTypes, ) -> Result { let mut section_map = BTreeMap::new(); @@ -94,10 +104,12 @@ impl<'a> Chunk<'a> { block_types, ) .with_context(|| format!("Failed to load section at Y={}", section.y))?, - BiomesV18::new(section.biomes.data.as_deref(), §ion.biomes.palette) - .with_context(|| { - format!("Failed to load section biomes at Y={}", section.y) - })?, + BiomesV18::new( + section.biomes.data.as_deref(), + §ion.biomes.palette, + biome_types, + ) + .with_context(|| format!("Failed to load section biomes at Y={}", section.y))?, BlockLight::new(section.block_light.as_deref()).with_context(|| { format!("Failed to load section block light at Y={}", section.y) })?, @@ -113,6 +125,7 @@ impl<'a> Chunk<'a> { data_version: u32, level: &'a de::LevelV0, block_types: &'a BlockTypes, + biome_types: &'a BiomeTypes, ) -> Result { let mut section_map_v1_13 = BTreeMap::new(); let mut section_map_v0 = BTreeMap::new(); @@ -158,7 +171,7 @@ impl<'a> Chunk<'a> { } } - let biomes = BiomesV0::new(level.biomes.as_ref()); + let biomes = BiomesV0::new(level.biomes.as_ref(), biome_types); Ok( match (section_map_v1_13.is_empty(), section_map_v0.is_empty()) { diff --git a/src/world/section.rs b/src/world/section.rs index 1aa8b7f..c943e11 100644 --- a/src/world/section.rs +++ b/src/world/section.rs @@ -5,7 +5,7 @@ use num_integer::div_rem; use super::de; use crate::{ - resource::{BlockType, BlockTypes}, + resource::{BiomeTypes, BlockType, BlockTypes}, types::*, }; @@ -183,7 +183,11 @@ pub struct BiomesV18<'a> { impl<'a> BiomesV18<'a> { /// Constructs a new [BiomesV18] from deserialized data structures - pub fn new(biomes: Option<&'a [i64]>, palette: &'a [String]) -> Result { + pub fn new( + biomes: Option<&'a [i64]>, + palette: &'a [String], + _biome_types: &'a BiomeTypes, + ) -> Result { let bits = palette_bits(palette.len(), 1, 6).context("Unsupported block palette size")?; if let Some(biomes) = biomes { @@ -208,14 +212,23 @@ impl<'a> BiomesV18<'a> { /// different pre-v1.18 Minecraft versions #[derive(Debug)] pub enum BiomesV0<'a> { - IntArrayV15(&'a fastnbt::IntArray), - IntArrayV0(&'a fastnbt::IntArray), - ByteArray(&'a fastnbt::ByteArray), + IntArrayV15 { + data: &'a fastnbt::IntArray, + biome_types: &'a BiomeTypes, + }, + IntArrayV0 { + data: &'a fastnbt::IntArray, + biome_types: &'a BiomeTypes, + }, + ByteArray { + data: &'a fastnbt::ByteArray, + biome_types: &'a BiomeTypes, + }, } impl<'a> BiomesV0<'a> { /// Constructs a new [BiomesV0] from deserialized data structures - pub fn new(biomes: Option<&'a de::BiomesV0>) -> Result { + pub fn new(biomes: Option<&'a de::BiomesV0>, biome_types: &'a BiomeTypes) -> Result { const N: usize = BLOCKS_PER_CHUNK; const MAXY: usize = 256; const BN: usize = N >> 2; @@ -223,10 +236,14 @@ impl<'a> BiomesV0<'a> { Ok(match biomes { Some(de::BiomesV0::IntArray(data)) if data.len() == BN * BN * BMAXY => { - BiomesV0::IntArrayV15(data) + BiomesV0::IntArrayV15 { data, biome_types } + } + Some(de::BiomesV0::IntArray(data)) if data.len() == N * N => { + BiomesV0::IntArrayV0 { data, biome_types } + } + Some(de::BiomesV0::ByteArray(data)) if data.len() == N * N => { + BiomesV0::ByteArray { data, biome_types } } - Some(de::BiomesV0::IntArray(data)) if data.len() == N * N => BiomesV0::IntArrayV0(data), - Some(de::BiomesV0::ByteArray(data)) if data.len() == N * N => BiomesV0::ByteArray(data), _ => bail!("Invalid biome data"), }) }