Skip to content

Commit

Permalink
world: hide unknown block/biome type warnings by default
Browse files Browse the repository at this point in the history
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.
  • Loading branch information
neocturne committed Jan 10, 2024
1 parent 8c28935 commit 889a8fb
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 68 deletions.
6 changes: 6 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
43 changes: 39 additions & 4 deletions src/core/region_processor.rs
Original file line number Diff line number Diff line change
@@ -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::*;
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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> {
Expand Down Expand Up @@ -104,6 +116,7 @@ impl<'a> SingleRegionProcessor<'a> {
lightmap_needed,
processed_region,
lightmap,
has_unknown: false,
})
}

Expand Down Expand Up @@ -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)
.with_context(|| format!("Failed to decode chunk {:?}", chunk_coords))?;
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,
Expand Down Expand Up @@ -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
})
}
}

Expand Down Expand Up @@ -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)
Expand All @@ -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()
Expand All @@ -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 }));

Expand Down
95 changes: 47 additions & 48 deletions src/world/chunk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand All @@ -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 &section.section {
Expand All @@ -85,22 +86,27 @@ impl<'a> Chunk<'a> {
biomes,
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(
SectionY(section.y),
(
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)
})?,
BiomesV1_18::new(biomes.data.as_deref(), &biomes.palette, biome_types)
.with_context(|| {
format!("Failed to load section biomes at Y={}", 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)
})?,
Expand All @@ -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
Expand All @@ -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 =
Expand All @@ -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(
Expand All @@ -166,23 +166,22 @@ 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()) {
(true, true) => Chunk::Empty,
(false, true) => Chunk::V1_13 {
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");
}
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,
biomes: biomes?,
},
(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
Expand Down
44 changes: 28 additions & 16 deletions src/world/section.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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::{
Expand Down Expand Up @@ -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")?;
Expand All @@ -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 {
block_states,
palette: palette_types,
bits,
aligned_blocks,
})
Ok((
Self {
block_states,
palette: palette_types,
bits,
aligned_blocks,
},
has_unknown,
))
}

/// Looks up the block type palette index at the given coordinates
Expand Down Expand Up @@ -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 {
Expand All @@ -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 {
biomes,
palette: palette_types,
bits,
})
Ok((
BiomesV1_18 {
biomes,
palette: palette_types,
bits,
},
has_unknown,
))
}

/// Looks up the block type palette index at the given coordinates
Expand Down

0 comments on commit 889a8fb

Please sign in to comment.