Skip to content

Commit

Permalink
Merge pull request #53 from neocturne/empty-region-fixes
Browse files Browse the repository at this point in the history
Empty region fixes
  • Loading branch information
neocturne authored Jun 14, 2024
2 parents d435643 + e74e7be commit 4eb963f
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 39 deletions.
11 changes: 11 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,17 @@

## [Unreleased] - ReleaseDate

### Fixed

- Fix crash due to incorrect counting in info message

The calculation of the number of skipped regions could underflow when more invalid than valid
regions were encountered.
- Ignore empty region files instead of treating them as invalid

Minecraft generates empty region files in some cases. Just ignore them instead of printing an
error message every time.

## [2.1.0] - 2024-01-27

### Added
Expand Down
21 changes: 21 additions & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ pre-release-replacements = [
anyhow = "1.0.68"
bincode = "1.3.3"
clap = { version = "4.1.4", features = ["derive", "wrap_help"] }
enum-map = "2.7.3"
fastnbt = "2.3.2"
futures-util = "0.3.28"
git-version = "0.3.5"
Expand Down
71 changes: 32 additions & 39 deletions src/core/region_processor.rs
Original file line number Diff line number Diff line change
@@ -1,16 +1,9 @@
//! The [RegionProcessor] and related functions
use std::{
ffi::OsStr,
path::PathBuf,
sync::{
atomic::{AtomicBool, Ordering},
mpsc,
},
time::SystemTime,
};
use std::{ffi::OsStr, path::PathBuf, sync::mpsc, time::SystemTime};

use anyhow::{Context, Result};
use enum_map::{Enum, EnumMap};
use rayon::prelude::*;
use tracing::{debug, info, warn};

Expand All @@ -36,7 +29,7 @@ fn parse_region_filename(file_name: &OsStr) -> Option<TileCoords> {
}

/// [RegionProcessor::process_region] return values
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Enum)]
enum RegionProcessorStatus {
/// Region was processed
Ok,
Expand Down Expand Up @@ -344,11 +337,20 @@ impl<'a> RegionProcessor<'a> {
})?
.filter_map(|entry| entry.ok())
.filter(|entry| {
// We are only interested in regular files
matches!(
entry.file_type().map(|file_type| file_type.is_file()),
Ok(true)
)
(|| {
// We are only interested in regular files
let file_type = entry.file_type().ok()?;
if !file_type.is_file() {
return None;
}

let metadata = entry.metadata().ok()?;
if metadata.len() == 0 {
return None;
}
Some(())
})()
.is_some()
})
.filter_map(|entry| parse_region_filename(&entry.file_name()))
.collect())
Expand All @@ -363,58 +365,49 @@ impl<'a> RegionProcessor<'a> {
///
/// Returns a list of the coordinates of all processed regions
pub fn run(self) -> Result<Vec<TileCoords>> {
use RegionProcessorStatus as Status;

fs::create_dir_all(&self.config.processed_dir)?;
fs::create_dir_all(&self.config.tile_dir(TileKind::Lightmap, 0))?;
fs::create_dir_all(&self.config.entities_dir(0))?;

info!("Processing region files...");

let (region_send, region_recv) = mpsc::channel();
let (processed_send, processed_recv) = mpsc::channel();
let (error_send, error_recv) = mpsc::channel();

let has_unknown = AtomicBool::new(false);
let (status_send, status_recv) = mpsc::channel();

self.collect_regions()?.par_iter().try_for_each(|&coords| {
let ret = self
.process_region(coords)
.with_context(|| format!("Failed to process region {:?}", coords))?;

if ret != RegionProcessorStatus::ErrorMissing {
if ret != Status::ErrorMissing {
region_send.send(coords).unwrap();
}

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()
}
}
status_send.send(ret).unwrap();

anyhow::Ok(())
})?;

drop(region_send);
let mut regions: Vec<_> = region_recv.into_iter().collect();

drop(processed_send);
let processed = processed_recv.into_iter().count();
drop(error_send);
let errors = error_recv.into_iter().count();
drop(status_send);

let mut status = EnumMap::<_, usize>::default();
for ret in status_recv {
status[ret] += 1;
}

info!(
"Processed region files ({} processed, {} unchanged, {} errors)",
processed,
regions.len() - processed - errors,
errors,
status[Status::Ok] + status[Status::OkWithUnknown],
status[Status::Skipped],
status[Status::ErrorOk] + status[Status::ErrorMissing],
);

if has_unknown.into_inner() {
if status[Status::OkWithUnknown] > 0 {
warn!("Unknown block or biome types found during processing");
eprint!(concat!(
"\n",
Expand Down

0 comments on commit 4eb963f

Please sign in to comment.