mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-04 17:23:33 +01:00
Merge pull request #44 from neocturne/hide-unknown-warnings
Hide unknown block/biome type warnings by default
This commit is contained in:
commit
f08acd06e2
5 changed files with 177 additions and 128 deletions
11
CHANGELOG.md
11
CHANGELOG.md
|
@ -2,13 +2,22 @@
|
||||||
|
|
||||||
## [Unreleased] - ReleaseDate
|
## [Unreleased] - ReleaseDate
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Without `--verbose`, only a single warning is printed at the end of
|
||||||
|
processing for unknown block/biome types, rather than once for every
|
||||||
|
section where such a block/biome is encountered.
|
||||||
|
|
||||||
## [2.0.2] - 2024-01-07
|
## [2.0.2] - 2024-01-07
|
||||||
|
|
||||||
### Updated
|
### Added
|
||||||
|
|
||||||
- Added support for Minecraft 1.20.3+
|
- Added support for Minecraft 1.20.3+
|
||||||
|
|
||||||
Minecraft 1.20.3 renamed the `grass` block type to `short_grass`.
|
Minecraft 1.20.3 renamed the `grass` block type to `short_grass`.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
- Updated [Leaflet](https://leafletjs.com/) to 1.9.4
|
- Updated [Leaflet](https://leafletjs.com/) to 1.9.4
|
||||||
- Updated attribution URL to https://github.com/neocturne/MinedMap
|
- Updated attribution URL to https://github.com/neocturne/MinedMap
|
||||||
|
|
||||||
|
|
46
Cargo.lock
generated
46
Cargo.lock
generated
|
@ -161,9 +161,9 @@ checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap"
|
name = "clap"
|
||||||
version = "4.4.13"
|
version = "4.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "52bdc885e4cacc7f7c9eedc1ef6da641603180c783c41a15c264944deeaab642"
|
checksum = "33e92c5c1a78c62968ec57dbc2440366a2d6e5a23faf829970ff1585dc6b18e2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"clap_builder",
|
"clap_builder",
|
||||||
"clap_derive",
|
"clap_derive",
|
||||||
|
@ -171,9 +171,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "clap_builder"
|
name = "clap_builder"
|
||||||
version = "4.4.12"
|
version = "4.4.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fb7fb5e4e979aec3be7791562fcba452f94ad85e954da024396433e0e25a79e9"
|
checksum = "f4323769dc8a61e2c39ad7dc26f6f2800524691a44d74fe3d1071a5c24db6370"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anstream",
|
"anstream",
|
||||||
"anstyle",
|
"anstyle",
|
||||||
|
@ -231,34 +231,28 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-deque"
|
name = "crossbeam-deque"
|
||||||
version = "0.8.4"
|
version = "0.8.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "fca89a0e215bab21874660c67903c5f143333cab1da83d041c7ded6053774751"
|
checksum = "613f8cc01fe9cf1a3eb3d7f488fd2fa8388403e97039e2f73692932e291a770d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-epoch",
|
"crossbeam-epoch",
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-epoch"
|
name = "crossbeam-epoch"
|
||||||
version = "0.9.17"
|
version = "0.9.18"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0e3681d554572a651dda4186cd47240627c3d0114d45a95f6ad27f2f22e7548d"
|
checksum = "5b82ac4a3c2ca9c3460964f020e1402edd5753411d7737aa39c3714ad1b5420e"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"autocfg",
|
|
||||||
"cfg-if",
|
|
||||||
"crossbeam-utils",
|
"crossbeam-utils",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "crossbeam-utils"
|
name = "crossbeam-utils"
|
||||||
version = "0.8.18"
|
version = "0.8.19"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c3a430a770ebd84726f584a90ee7f020d28db52c6d02138900f22341f866d39c"
|
checksum = "248e3bacc7dc6baa3b21e405ee045c3047101a49145e7e9eca583ab4c2ca5345"
|
||||||
dependencies = [
|
|
||||||
"cfg-if",
|
|
||||||
]
|
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "either"
|
name = "either"
|
||||||
|
@ -473,15 +467,15 @@ checksum = "e2abad23fbc42b3700f2f279844dc832adb2b2eb069b2df918f455c4e18cc646"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libc"
|
name = "libc"
|
||||||
version = "0.2.151"
|
version = "0.2.152"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "302d7ab3130588088d277783b1e2d2e10c9e9e4a16dd9050e6ec93fb3e7048f4"
|
checksum = "13e3bf6590cbc649f4d1a3eefc9d5d6eb746f5200ffb04e5e142700b8faa56e7"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "libz-ng-sys"
|
name = "libz-ng-sys"
|
||||||
version = "1.1.12"
|
version = "1.1.14"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "3dd9f43e75536a46ee0f92b758f6b63846e594e86638c61a9251338a65baea63"
|
checksum = "81157dde2fd4ad2b45ea3a4bb47b8193b52a6346b678840d91d80d3c2cd166c5"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cmake",
|
"cmake",
|
||||||
"libc",
|
"libc",
|
||||||
|
@ -713,9 +707,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "proc-macro2"
|
name = "proc-macro2"
|
||||||
version = "1.0.75"
|
version = "1.0.76"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "907a61bd0f64c2f29cd1cf1dc34d05176426a3f504a78010f08416ddb7b13708"
|
checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"unicode-ident",
|
"unicode-ident",
|
||||||
]
|
]
|
||||||
|
@ -784,9 +778,9 @@ checksum = "94143f37725109f92c262ed2cf5e59bce7498c01bcc1502d7b9afe439a4e9f49"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde"
|
name = "serde"
|
||||||
version = "1.0.194"
|
version = "1.0.195"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "0b114498256798c94a0689e1a15fec6005dee8ac1f41de56404b67afc2a4b773"
|
checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde_derive",
|
"serde_derive",
|
||||||
]
|
]
|
||||||
|
@ -802,9 +796,9 @@ dependencies = [
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "serde_derive"
|
name = "serde_derive"
|
||||||
version = "1.0.194"
|
version = "1.0.195"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "a3385e45322e8f9931410f01b3031ec534c3947d0e94c18049af4d9f9907d4e0"
|
checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
|
|
|
@ -1,6 +1,14 @@
|
||||||
//! The [RegionProcessor] and related functions
|
//! The [RegionProcessor] and related functions
|
||||||
|
|
||||||
use std::{ffi::OsStr, path::PathBuf, sync::mpsc, time::SystemTime};
|
use std::{
|
||||||
|
ffi::OsStr,
|
||||||
|
path::PathBuf,
|
||||||
|
sync::{
|
||||||
|
atomic::{AtomicBool, Ordering},
|
||||||
|
mpsc,
|
||||||
|
},
|
||||||
|
time::SystemTime,
|
||||||
|
};
|
||||||
|
|
||||||
use anyhow::{Context, Result};
|
use anyhow::{Context, Result};
|
||||||
use rayon::prelude::*;
|
use rayon::prelude::*;
|
||||||
|
@ -32,6 +40,8 @@ fn parse_region_filename(file_name: &OsStr) -> Option<TileCoords> {
|
||||||
enum RegionProcessorStatus {
|
enum RegionProcessorStatus {
|
||||||
/// Region was processed
|
/// Region was processed
|
||||||
Ok,
|
Ok,
|
||||||
|
/// Region was processed, unknown blocks or biomes were encountered
|
||||||
|
OkWithUnknown,
|
||||||
/// Region was unchanged and skipped
|
/// Region was unchanged and skipped
|
||||||
Skipped,
|
Skipped,
|
||||||
/// Reading the region failed, previous processed data is reused
|
/// Reading the region failed, previous processed data is reused
|
||||||
|
@ -68,6 +78,8 @@ struct SingleRegionProcessor<'a> {
|
||||||
processed_region: ProcessedRegion,
|
processed_region: ProcessedRegion,
|
||||||
/// Lightmap intermediate data
|
/// Lightmap intermediate data
|
||||||
lightmap: image::GrayAlphaImage,
|
lightmap: image::GrayAlphaImage,
|
||||||
|
/// True if any unknown block or biome types were encountered during processing
|
||||||
|
has_unknown: bool,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<'a> SingleRegionProcessor<'a> {
|
impl<'a> SingleRegionProcessor<'a> {
|
||||||
|
@ -104,6 +116,7 @@ impl<'a> SingleRegionProcessor<'a> {
|
||||||
lightmap_needed,
|
lightmap_needed,
|
||||||
processed_region,
|
processed_region,
|
||||||
lightmap,
|
lightmap,
|
||||||
|
has_unknown: false,
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -162,8 +175,10 @@ impl<'a> SingleRegionProcessor<'a> {
|
||||||
|
|
||||||
/// Processes a single chunk
|
/// Processes a single chunk
|
||||||
fn process_chunk(&mut self, chunk_coords: ChunkCoords, data: world::de::Chunk) -> Result<()> {
|
fn process_chunk(&mut self, chunk_coords: ChunkCoords, data: world::de::Chunk) -> Result<()> {
|
||||||
let chunk = world::chunk::Chunk::new(&data, self.block_types, self.biome_types)
|
let (chunk, has_unknown) =
|
||||||
.with_context(|| format!("Failed to decode chunk {:?}", chunk_coords))?;
|
world::chunk::Chunk::new(&data, self.block_types, self.biome_types)
|
||||||
|
.with_context(|| format!("Failed to decode chunk {:?}", chunk_coords))?;
|
||||||
|
self.has_unknown |= has_unknown;
|
||||||
let Some(layer::LayerData {
|
let Some(layer::LayerData {
|
||||||
blocks,
|
blocks,
|
||||||
biomes,
|
biomes,
|
||||||
|
@ -231,7 +246,11 @@ impl<'a> SingleRegionProcessor<'a> {
|
||||||
self.save_region()?;
|
self.save_region()?;
|
||||||
self.save_lightmap()?;
|
self.save_lightmap()?;
|
||||||
|
|
||||||
Ok(RegionProcessorStatus::Ok)
|
Ok(if self.has_unknown {
|
||||||
|
RegionProcessorStatus::OkWithUnknown
|
||||||
|
} else {
|
||||||
|
RegionProcessorStatus::Ok
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -300,6 +319,8 @@ impl<'a> RegionProcessor<'a> {
|
||||||
let (processed_send, processed_recv) = mpsc::channel();
|
let (processed_send, processed_recv) = mpsc::channel();
|
||||||
let (error_send, error_recv) = mpsc::channel();
|
let (error_send, error_recv) = mpsc::channel();
|
||||||
|
|
||||||
|
let has_unknown = AtomicBool::new(false);
|
||||||
|
|
||||||
self.collect_regions()?.par_iter().try_for_each(|&coords| {
|
self.collect_regions()?.par_iter().try_for_each(|&coords| {
|
||||||
let ret = self
|
let ret = self
|
||||||
.process_region(coords)
|
.process_region(coords)
|
||||||
|
@ -311,6 +332,10 @@ impl<'a> RegionProcessor<'a> {
|
||||||
|
|
||||||
match ret {
|
match ret {
|
||||||
RegionProcessorStatus::Ok => processed_send.send(()).unwrap(),
|
RegionProcessorStatus::Ok => processed_send.send(()).unwrap(),
|
||||||
|
RegionProcessorStatus::OkWithUnknown => {
|
||||||
|
has_unknown.store(true, Ordering::Relaxed);
|
||||||
|
processed_send.send(()).unwrap();
|
||||||
|
}
|
||||||
RegionProcessorStatus::Skipped => {}
|
RegionProcessorStatus::Skipped => {}
|
||||||
RegionProcessorStatus::ErrorOk | RegionProcessorStatus::ErrorMissing => {
|
RegionProcessorStatus::ErrorOk | RegionProcessorStatus::ErrorMissing => {
|
||||||
error_send.send(()).unwrap()
|
error_send.send(()).unwrap()
|
||||||
|
@ -335,6 +360,16 @@ impl<'a> RegionProcessor<'a> {
|
||||||
errors,
|
errors,
|
||||||
);
|
);
|
||||||
|
|
||||||
|
if has_unknown.into_inner() {
|
||||||
|
warn!("Unknown block or biome types found during processing");
|
||||||
|
eprint!(concat!(
|
||||||
|
"\n",
|
||||||
|
" If you're encountering this issue with an unmodified Minecraft version supported by MinedMap,\n",
|
||||||
|
" please file a bug report including the output with the --verbose flag.\n",
|
||||||
|
"\n",
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
// Sort regions in a zig-zag pattern to optimize cache usage
|
// Sort regions in a zig-zag pattern to optimize cache usage
|
||||||
regions.sort_unstable_by_key(|&TileCoords { x, z }| (x, if x % 2 == 0 { z } else { -z }));
|
regions.sort_unstable_by_key(|&TileCoords { x, z }| (x, if x % 2 == 0 { z } else { -z }));
|
||||||
|
|
||||||
|
|
|
@ -50,46 +50,13 @@ pub enum Chunk<'a> {
|
||||||
Empty,
|
Empty,
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Inner data structure of [SectionIter]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
enum SectionIterInner<'a> {
|
|
||||||
/// Iterator over sections of [Chunk::V1_18]
|
|
||||||
V1_18 {
|
|
||||||
/// Inner iterator into section map
|
|
||||||
iter: btree_map::Iter<'a, SectionY, (SectionV1_13<'a>, BiomesV1_18<'a>, BlockLight<'a>)>,
|
|
||||||
},
|
|
||||||
/// Iterator over sections of [Chunk::V1_13]
|
|
||||||
V1_13 {
|
|
||||||
/// Inner iterator into section map
|
|
||||||
iter: btree_map::Iter<'a, SectionY, (SectionV1_13<'a>, BlockLight<'a>)>,
|
|
||||||
/// Chunk biome data
|
|
||||||
biomes: &'a BiomesV0<'a>,
|
|
||||||
},
|
|
||||||
/// Iterator over sections of [Chunk::V0]
|
|
||||||
V0 {
|
|
||||||
/// Inner iterator into section map
|
|
||||||
iter: btree_map::Iter<'a, SectionY, (SectionV0<'a>, BlockLight<'a>)>,
|
|
||||||
/// Chunk biome data
|
|
||||||
biomes: &'a BiomesV0<'a>,
|
|
||||||
},
|
|
||||||
/// Empty iterator over an unpopulated chunk ([Chunk::Empty])
|
|
||||||
Empty,
|
|
||||||
}
|
|
||||||
|
|
||||||
/// Iterator over the sections of a [Chunk]
|
|
||||||
#[derive(Debug, Clone)]
|
|
||||||
pub struct SectionIter<'a> {
|
|
||||||
/// Inner iterator enum
|
|
||||||
inner: SectionIterInner<'a>,
|
|
||||||
}
|
|
||||||
|
|
||||||
impl<'a> Chunk<'a> {
|
impl<'a> Chunk<'a> {
|
||||||
/// Creates a new [Chunk] from a deserialized [de::Chunk]
|
/// Creates a new [Chunk] from a deserialized [de::Chunk]
|
||||||
pub fn new(
|
pub fn new(
|
||||||
data: &'a de::Chunk,
|
data: &'a de::Chunk,
|
||||||
block_types: &'a BlockTypes,
|
block_types: &'a BlockTypes,
|
||||||
biome_types: &'a BiomeTypes,
|
biome_types: &'a BiomeTypes,
|
||||||
) -> Result<Self> {
|
) -> Result<(Self, bool)> {
|
||||||
let data_version = data.data_version.unwrap_or_default();
|
let data_version = data.data_version.unwrap_or_default();
|
||||||
|
|
||||||
match &data.chunk {
|
match &data.chunk {
|
||||||
|
@ -108,8 +75,9 @@ impl<'a> Chunk<'a> {
|
||||||
sections: &'a Vec<de::SectionV1_18>,
|
sections: &'a Vec<de::SectionV1_18>,
|
||||||
block_types: &'a BlockTypes,
|
block_types: &'a BlockTypes,
|
||||||
biome_types: &'a BiomeTypes,
|
biome_types: &'a BiomeTypes,
|
||||||
) -> Result<Self> {
|
) -> Result<(Self, bool)> {
|
||||||
let mut section_map = BTreeMap::new();
|
let mut section_map = BTreeMap::new();
|
||||||
|
let mut has_unknown = false;
|
||||||
|
|
||||||
for section in sections {
|
for section in sections {
|
||||||
match §ion.section {
|
match §ion.section {
|
||||||
|
@ -118,22 +86,27 @@ impl<'a> Chunk<'a> {
|
||||||
biomes,
|
biomes,
|
||||||
block_light,
|
block_light,
|
||||||
} => {
|
} => {
|
||||||
|
let (loaded_section, unknown_blocks) = SectionV1_13::new(
|
||||||
|
data_version,
|
||||||
|
block_states.data.as_deref(),
|
||||||
|
&block_states.palette,
|
||||||
|
block_types,
|
||||||
|
)
|
||||||
|
.with_context(|| format!("Failed to load section at Y={}", section.y))?;
|
||||||
|
has_unknown |= unknown_blocks;
|
||||||
|
|
||||||
|
let (loaded_biomes, unknown_biomes) =
|
||||||
|
BiomesV1_18::new(biomes.data.as_deref(), &biomes.palette, biome_types)
|
||||||
|
.with_context(|| {
|
||||||
|
format!("Failed to load section biomes at Y={}", section.y)
|
||||||
|
})?;
|
||||||
|
has_unknown |= unknown_biomes;
|
||||||
|
|
||||||
section_map.insert(
|
section_map.insert(
|
||||||
SectionY(section.y),
|
SectionY(section.y),
|
||||||
(
|
(
|
||||||
SectionV1_13::new(
|
loaded_section,
|
||||||
data_version,
|
loaded_biomes,
|
||||||
block_states.data.as_deref(),
|
|
||||||
&block_states.palette,
|
|
||||||
block_types,
|
|
||||||
)
|
|
||||||
.with_context(|| {
|
|
||||||
format!("Failed to load section at Y={}", section.y)
|
|
||||||
})?,
|
|
||||||
BiomesV1_18::new(biomes.data.as_deref(), &biomes.palette, biome_types)
|
|
||||||
.with_context(|| {
|
|
||||||
format!("Failed to load section biomes at Y={}", section.y)
|
|
||||||
})?,
|
|
||||||
BlockLight::new(block_light.as_deref()).with_context(|| {
|
BlockLight::new(block_light.as_deref()).with_context(|| {
|
||||||
format!("Failed to load section block light at Y={}", section.y)
|
format!("Failed to load section block light at Y={}", section.y)
|
||||||
})?,
|
})?,
|
||||||
|
@ -144,7 +117,8 @@ impl<'a> Chunk<'a> {
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
Ok(Chunk::V1_18 { section_map })
|
let chunk = Chunk::V1_18 { section_map };
|
||||||
|
Ok((chunk, has_unknown))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// [Chunk::new] implementation for all pre-1.18 chunk variants
|
/// [Chunk::new] implementation for all pre-1.18 chunk variants
|
||||||
|
@ -153,9 +127,10 @@ impl<'a> Chunk<'a> {
|
||||||
level: &'a de::LevelV0,
|
level: &'a de::LevelV0,
|
||||||
block_types: &'a BlockTypes,
|
block_types: &'a BlockTypes,
|
||||||
biome_types: &'a BiomeTypes,
|
biome_types: &'a BiomeTypes,
|
||||||
) -> Result<Self> {
|
) -> Result<(Self, bool)> {
|
||||||
let mut section_map_v1_13 = BTreeMap::new();
|
let mut section_map_v1_13 = BTreeMap::new();
|
||||||
let mut section_map_v0 = BTreeMap::new();
|
let mut section_map_v0 = BTreeMap::new();
|
||||||
|
let mut has_unknown = false;
|
||||||
|
|
||||||
for section in &level.sections {
|
for section in &level.sections {
|
||||||
let block_light =
|
let block_light =
|
||||||
|
@ -167,21 +142,13 @@ impl<'a> Chunk<'a> {
|
||||||
block_states,
|
block_states,
|
||||||
palette,
|
palette,
|
||||||
} => {
|
} => {
|
||||||
section_map_v1_13.insert(
|
let (loaded_section, unknown_blocks) =
|
||||||
SectionY(section.y.into()),
|
SectionV1_13::new(data_version, Some(block_states), palette, block_types)
|
||||||
(
|
.with_context(|| format!("Failed to load section at Y={}", section.y))?;
|
||||||
SectionV1_13::new(
|
has_unknown |= unknown_blocks;
|
||||||
data_version,
|
|
||||||
Some(block_states),
|
section_map_v1_13
|
||||||
palette,
|
.insert(SectionY(section.y.into()), (loaded_section, block_light));
|
||||||
block_types,
|
|
||||||
)
|
|
||||||
.with_context(|| {
|
|
||||||
format!("Failed to load section at Y={}", section.y)
|
|
||||||
})?,
|
|
||||||
block_light,
|
|
||||||
),
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
de::SectionV0Variant::V0 { blocks, data } => {
|
de::SectionV0Variant::V0 { blocks, data } => {
|
||||||
section_map_v0.insert(
|
section_map_v0.insert(
|
||||||
|
@ -199,23 +166,22 @@ impl<'a> Chunk<'a> {
|
||||||
}
|
}
|
||||||
|
|
||||||
let biomes = BiomesV0::new(level.biomes.as_ref(), biome_types);
|
let biomes = BiomesV0::new(level.biomes.as_ref(), biome_types);
|
||||||
|
let chunk = match (section_map_v1_13.is_empty(), section_map_v0.is_empty()) {
|
||||||
Ok(
|
(true, true) => Chunk::Empty,
|
||||||
match (section_map_v1_13.is_empty(), section_map_v0.is_empty()) {
|
(false, true) => Chunk::V1_13 {
|
||||||
(true, true) => Chunk::Empty,
|
section_map: section_map_v1_13,
|
||||||
(false, true) => Chunk::V1_13 {
|
biomes: biomes?,
|
||||||
section_map: section_map_v1_13,
|
|
||||||
biomes: biomes?,
|
|
||||||
},
|
|
||||||
(true, false) => Chunk::V0 {
|
|
||||||
section_map: section_map_v0,
|
|
||||||
biomes: biomes?,
|
|
||||||
},
|
|
||||||
(false, false) => {
|
|
||||||
bail!("Mixed section versions");
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
)
|
(true, false) => Chunk::V0 {
|
||||||
|
section_map: section_map_v0,
|
||||||
|
biomes: biomes?,
|
||||||
|
},
|
||||||
|
(false, false) => {
|
||||||
|
bail!("Mixed section versions");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok((chunk, has_unknown))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns true if the chunk does not contain any sections
|
/// Returns true if the chunk does not contain any sections
|
||||||
|
@ -283,6 +249,39 @@ impl<'a, T> SectionIterTrait<'a> for T where
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Inner data structure of [SectionIter]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
enum SectionIterInner<'a> {
|
||||||
|
/// Iterator over sections of [Chunk::V1_18]
|
||||||
|
V1_18 {
|
||||||
|
/// Inner iterator into section map
|
||||||
|
iter: btree_map::Iter<'a, SectionY, (SectionV1_13<'a>, BiomesV1_18<'a>, BlockLight<'a>)>,
|
||||||
|
},
|
||||||
|
/// Iterator over sections of [Chunk::V1_13]
|
||||||
|
V1_13 {
|
||||||
|
/// Inner iterator into section map
|
||||||
|
iter: btree_map::Iter<'a, SectionY, (SectionV1_13<'a>, BlockLight<'a>)>,
|
||||||
|
/// Chunk biome data
|
||||||
|
biomes: &'a BiomesV0<'a>,
|
||||||
|
},
|
||||||
|
/// Iterator over sections of [Chunk::V0]
|
||||||
|
V0 {
|
||||||
|
/// Inner iterator into section map
|
||||||
|
iter: btree_map::Iter<'a, SectionY, (SectionV0<'a>, BlockLight<'a>)>,
|
||||||
|
/// Chunk biome data
|
||||||
|
biomes: &'a BiomesV0<'a>,
|
||||||
|
},
|
||||||
|
/// Empty iterator over an unpopulated chunk ([Chunk::Empty])
|
||||||
|
Empty,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Iterator over the sections of a [Chunk]
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub struct SectionIter<'a> {
|
||||||
|
/// Inner iterator enum
|
||||||
|
inner: SectionIterInner<'a>,
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> SectionIter<'a> {
|
impl<'a> SectionIter<'a> {
|
||||||
/// Helper to run a closure on the inner section iterator
|
/// Helper to run a closure on the inner section iterator
|
||||||
fn with_iter<F, T>(&mut self, f: F) -> T
|
fn with_iter<F, T>(&mut self, f: F) -> T
|
||||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt::Debug;
|
||||||
|
|
||||||
use anyhow::{bail, Context, Result};
|
use anyhow::{bail, Context, Result};
|
||||||
use num_integer::div_rem;
|
use num_integer::div_rem;
|
||||||
use tracing::warn;
|
use tracing::debug;
|
||||||
|
|
||||||
use super::de;
|
use super::de;
|
||||||
use crate::{
|
use crate::{
|
||||||
|
@ -73,7 +73,7 @@ impl<'a> SectionV1_13<'a> {
|
||||||
block_states: Option<&'a [i64]>,
|
block_states: Option<&'a [i64]>,
|
||||||
palette: &'a [de::BlockStatePaletteEntry],
|
palette: &'a [de::BlockStatePaletteEntry],
|
||||||
block_types: &'a BlockTypes,
|
block_types: &'a BlockTypes,
|
||||||
) -> Result<Self> {
|
) -> Result<(Self, bool)> {
|
||||||
let aligned_blocks = data_version >= 2529;
|
let aligned_blocks = data_version >= 2529;
|
||||||
|
|
||||||
let bits = palette_bits(palette.len(), 4, 12).context("Unsupported block palette size")?;
|
let bits = palette_bits(palette.len(), 4, 12).context("Unsupported block palette size")?;
|
||||||
|
@ -90,23 +90,29 @@ impl<'a> SectionV1_13<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut has_unknown = false;
|
||||||
|
|
||||||
let palette_types = palette
|
let palette_types = palette
|
||||||
.iter()
|
.iter()
|
||||||
.map(|entry| {
|
.map(|entry| {
|
||||||
let block_type = block_types.get(&entry.name);
|
let block_type = block_types.get(&entry.name);
|
||||||
if block_type.is_none() {
|
if block_type.is_none() {
|
||||||
warn!("Unknown block type: {}", entry.name);
|
debug!("Unknown block type: {}", entry.name);
|
||||||
|
has_unknown = true;
|
||||||
}
|
}
|
||||||
block_type
|
block_type
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(Self {
|
Ok((
|
||||||
block_states,
|
Self {
|
||||||
palette: palette_types,
|
block_states,
|
||||||
bits,
|
palette: palette_types,
|
||||||
aligned_blocks,
|
bits,
|
||||||
})
|
aligned_blocks,
|
||||||
|
},
|
||||||
|
has_unknown,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up the block type palette index at the given coordinates
|
/// Looks up the block type palette index at the given coordinates
|
||||||
|
@ -231,7 +237,7 @@ impl<'a> BiomesV1_18<'a> {
|
||||||
biomes: Option<&'a [i64]>,
|
biomes: Option<&'a [i64]>,
|
||||||
palette: &'a [String],
|
palette: &'a [String],
|
||||||
biome_types: &'a BiomeTypes,
|
biome_types: &'a BiomeTypes,
|
||||||
) -> Result<Self> {
|
) -> Result<(Self, bool)> {
|
||||||
let bits = palette_bits(palette.len(), 1, 6).context("Unsupported block palette size")?;
|
let bits = palette_bits(palette.len(), 1, 6).context("Unsupported block palette size")?;
|
||||||
|
|
||||||
if let Some(biomes) = biomes {
|
if let Some(biomes) = biomes {
|
||||||
|
@ -242,22 +248,28 @@ impl<'a> BiomesV1_18<'a> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
let mut has_unknown = false;
|
||||||
|
|
||||||
let palette_types = palette
|
let palette_types = palette
|
||||||
.iter()
|
.iter()
|
||||||
.map(|entry| {
|
.map(|entry| {
|
||||||
let biome_type = biome_types.get(entry);
|
let biome_type = biome_types.get(entry);
|
||||||
if biome_type.is_none() {
|
if biome_type.is_none() {
|
||||||
warn!("Unknown biome type: {}", entry);
|
debug!("Unknown biome type: {}", entry);
|
||||||
|
has_unknown = true;
|
||||||
}
|
}
|
||||||
biome_type
|
biome_type
|
||||||
})
|
})
|
||||||
.collect();
|
.collect();
|
||||||
|
|
||||||
Ok(BiomesV1_18 {
|
Ok((
|
||||||
biomes,
|
BiomesV1_18 {
|
||||||
palette: palette_types,
|
biomes,
|
||||||
bits,
|
palette: palette_types,
|
||||||
})
|
bits,
|
||||||
|
},
|
||||||
|
has_unknown,
|
||||||
|
))
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Looks up the block type palette index at the given coordinates
|
/// Looks up the block type palette index at the given coordinates
|
||||||
|
|
Loading…
Add table
Reference in a new issue