mirror of
https://github.com/neocturne/MinedMap.git
synced 2025-03-04 17:23:33 +01:00
world: hide unknown block/biome type warnings by default
While using MinedMap with modded Minecraft version is not officially supported, it should still work reasonably well if you're okay with custom block types being invisible and custom biomes using default grass/color/foliage colors. Avoid spamming the log with messages for each section in this case without --verbose, and instead just print a single warning at the end of processing.
This commit is contained in:
parent
1e41e1bc6a
commit
e8165aa47d
4 changed files with 120 additions and 68 deletions
|
@ -2,6 +2,12 @@
|
|||
|
||||
## [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
|
||||
|
||||
### Added
|
||||
|
|
|
@ -1,6 +1,14 @@
|
|||
//! 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 rayon::prelude::*;
|
||||
|
@ -32,6 +40,8 @@ fn parse_region_filename(file_name: &OsStr) -> Option<TileCoords> {
|
|||
enum RegionProcessorStatus {
|
||||
/// Region was processed
|
||||
Ok,
|
||||
/// Region was processed, unknown blocks or biomes were encountered
|
||||
OkWithUnknown,
|
||||
/// Region was unchanged and skipped
|
||||
Skipped,
|
||||
/// Reading the region failed, previous processed data is reused
|
||||
|
@ -68,6 +78,8 @@ struct SingleRegionProcessor<'a> {
|
|||
processed_region: ProcessedRegion,
|
||||
/// Lightmap intermediate data
|
||||
lightmap: image::GrayAlphaImage,
|
||||
/// True if any unknown block or biome types were encountered during processing
|
||||
has_unknown: bool,
|
||||
}
|
||||
|
||||
impl<'a> SingleRegionProcessor<'a> {
|
||||
|
@ -104,6 +116,7 @@ impl<'a> SingleRegionProcessor<'a> {
|
|||
lightmap_needed,
|
||||
processed_region,
|
||||
lightmap,
|
||||
has_unknown: false,
|
||||
})
|
||||
}
|
||||
|
||||
|
@ -162,8 +175,10 @@ impl<'a> SingleRegionProcessor<'a> {
|
|||
|
||||
/// Processes a single chunk
|
||||
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) =
|
||||
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 {
|
||||
blocks,
|
||||
biomes,
|
||||
|
@ -231,7 +246,11 @@ impl<'a> SingleRegionProcessor<'a> {
|
|||
self.save_region()?;
|
||||
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 (error_send, error_recv) = mpsc::channel();
|
||||
|
||||
let has_unknown = AtomicBool::new(false);
|
||||
|
||||
self.collect_regions()?.par_iter().try_for_each(|&coords| {
|
||||
let ret = self
|
||||
.process_region(coords)
|
||||
|
@ -311,6 +332,10 @@ impl<'a> RegionProcessor<'a> {
|
|||
|
||||
match ret {
|
||||
RegionProcessorStatus::Ok => processed_send.send(()).unwrap(),
|
||||
RegionProcessorStatus::OkWithUnknown => {
|
||||
has_unknown.store(true, Ordering::Relaxed);
|
||||
processed_send.send(()).unwrap();
|
||||
}
|
||||
RegionProcessorStatus::Skipped => {}
|
||||
RegionProcessorStatus::ErrorOk | RegionProcessorStatus::ErrorMissing => {
|
||||
error_send.send(()).unwrap()
|
||||
|
@ -335,6 +360,16 @@ impl<'a> RegionProcessor<'a> {
|
|||
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
|
||||
regions.sort_unstable_by_key(|&TileCoords { x, z }| (x, if x % 2 == 0 { z } else { -z }));
|
||||
|
||||
|
|
|
@ -56,7 +56,7 @@ impl<'a> Chunk<'a> {
|
|||
data: &'a de::Chunk,
|
||||
block_types: &'a BlockTypes,
|
||||
biome_types: &'a BiomeTypes,
|
||||
) -> Result<Self> {
|
||||
) -> Result<(Self, bool)> {
|
||||
let data_version = data.data_version.unwrap_or_default();
|
||||
|
||||
match &data.chunk {
|
||||
|
@ -75,8 +75,9 @@ impl<'a> Chunk<'a> {
|
|||
sections: &'a Vec<de::SectionV1_18>,
|
||||
block_types: &'a BlockTypes,
|
||||
biome_types: &'a BiomeTypes,
|
||||
) -> Result<Self> {
|
||||
) -> Result<(Self, bool)> {
|
||||
let mut section_map = BTreeMap::new();
|
||||
let mut has_unknown = false;
|
||||
|
||||
for section in sections {
|
||||
match §ion.section {
|
||||
|
@ -85,22 +86,27 @@ impl<'a> Chunk<'a> {
|
|||
biomes,
|
||||
block_light,
|
||||
} => {
|
||||
section_map.insert(
|
||||
SectionY(section.y),
|
||||
(
|
||||
SectionV1_13::new(
|
||||
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)
|
||||
})?,
|
||||
.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(
|
||||
SectionY(section.y),
|
||||
(
|
||||
loaded_section,
|
||||
loaded_biomes,
|
||||
BlockLight::new(block_light.as_deref()).with_context(|| {
|
||||
format!("Failed to load section block light at Y={}", section.y)
|
||||
})?,
|
||||
|
@ -111,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
|
||||
|
@ -120,9 +127,10 @@ impl<'a> Chunk<'a> {
|
|||
level: &'a de::LevelV0,
|
||||
block_types: &'a BlockTypes,
|
||||
biome_types: &'a BiomeTypes,
|
||||
) -> Result<Self> {
|
||||
) -> Result<(Self, bool)> {
|
||||
let mut section_map_v1_13 = BTreeMap::new();
|
||||
let mut section_map_v0 = BTreeMap::new();
|
||||
let mut has_unknown = false;
|
||||
|
||||
for section in &level.sections {
|
||||
let block_light =
|
||||
|
@ -134,21 +142,13 @@ impl<'a> Chunk<'a> {
|
|||
block_states,
|
||||
palette,
|
||||
} => {
|
||||
section_map_v1_13.insert(
|
||||
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)
|
||||
})?,
|
||||
block_light,
|
||||
),
|
||||
);
|
||||
let (loaded_section, unknown_blocks) =
|
||||
SectionV1_13::new(data_version, Some(block_states), palette, block_types)
|
||||
.with_context(|| format!("Failed to load section at Y={}", section.y))?;
|
||||
has_unknown |= unknown_blocks;
|
||||
|
||||
section_map_v1_13
|
||||
.insert(SectionY(section.y.into()), (loaded_section, block_light));
|
||||
}
|
||||
de::SectionV0Variant::V0 { blocks, data } => {
|
||||
section_map_v0.insert(
|
||||
|
@ -166,9 +166,7 @@ impl<'a> Chunk<'a> {
|
|||
}
|
||||
|
||||
let biomes = BiomesV0::new(level.biomes.as_ref(), biome_types);
|
||||
|
||||
Ok(
|
||||
match (section_map_v1_13.is_empty(), section_map_v0.is_empty()) {
|
||||
let chunk = match (section_map_v1_13.is_empty(), section_map_v0.is_empty()) {
|
||||
(true, true) => Chunk::Empty,
|
||||
(false, true) => Chunk::V1_13 {
|
||||
section_map: section_map_v1_13,
|
||||
|
@ -181,8 +179,9 @@ impl<'a> Chunk<'a> {
|
|||
(false, false) => {
|
||||
bail!("Mixed section versions");
|
||||
}
|
||||
},
|
||||
)
|
||||
};
|
||||
|
||||
Ok((chunk, has_unknown))
|
||||
}
|
||||
|
||||
/// Returns true if the chunk does not contain any sections
|
||||
|
|
|
@ -7,7 +7,7 @@ use std::fmt::Debug;
|
|||
|
||||
use anyhow::{bail, Context, Result};
|
||||
use num_integer::div_rem;
|
||||
use tracing::warn;
|
||||
use tracing::debug;
|
||||
|
||||
use super::de;
|
||||
use crate::{
|
||||
|
@ -73,7 +73,7 @@ impl<'a> SectionV1_13<'a> {
|
|||
block_states: Option<&'a [i64]>,
|
||||
palette: &'a [de::BlockStatePaletteEntry],
|
||||
block_types: &'a BlockTypes,
|
||||
) -> Result<Self> {
|
||||
) -> Result<(Self, bool)> {
|
||||
let aligned_blocks = data_version >= 2529;
|
||||
|
||||
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
|
||||
.iter()
|
||||
.map(|entry| {
|
||||
let block_type = block_types.get(&entry.name);
|
||||
if block_type.is_none() {
|
||||
warn!("Unknown block type: {}", entry.name);
|
||||
debug!("Unknown block type: {}", entry.name);
|
||||
has_unknown = true;
|
||||
}
|
||||
block_type
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(Self {
|
||||
Ok((
|
||||
Self {
|
||||
block_states,
|
||||
palette: palette_types,
|
||||
bits,
|
||||
aligned_blocks,
|
||||
})
|
||||
},
|
||||
has_unknown,
|
||||
))
|
||||
}
|
||||
|
||||
/// Looks up the block type palette index at the given coordinates
|
||||
|
@ -231,7 +237,7 @@ impl<'a> BiomesV1_18<'a> {
|
|||
biomes: Option<&'a [i64]>,
|
||||
palette: &'a [String],
|
||||
biome_types: &'a BiomeTypes,
|
||||
) -> Result<Self> {
|
||||
) -> Result<(Self, bool)> {
|
||||
let bits = palette_bits(palette.len(), 1, 6).context("Unsupported block palette size")?;
|
||||
|
||||
if let Some(biomes) = biomes {
|
||||
|
@ -242,22 +248,28 @@ impl<'a> BiomesV1_18<'a> {
|
|||
}
|
||||
}
|
||||
|
||||
let mut has_unknown = false;
|
||||
|
||||
let palette_types = palette
|
||||
.iter()
|
||||
.map(|entry| {
|
||||
let biome_type = biome_types.get(entry);
|
||||
if biome_type.is_none() {
|
||||
warn!("Unknown biome type: {}", entry);
|
||||
debug!("Unknown biome type: {}", entry);
|
||||
has_unknown = true;
|
||||
}
|
||||
biome_type
|
||||
})
|
||||
.collect();
|
||||
|
||||
Ok(BiomesV1_18 {
|
||||
Ok((
|
||||
BiomesV1_18 {
|
||||
biomes,
|
||||
palette: palette_types,
|
||||
bits,
|
||||
})
|
||||
},
|
||||
has_unknown,
|
||||
))
|
||||
}
|
||||
|
||||
/// Looks up the block type palette index at the given coordinates
|
||||
|
|
Loading…
Add table
Reference in a new issue