From 37126f69fcb9d6d5bbd31ad0a0b34fd522a733bb Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 13 Feb 2025 20:10:50 +0100 Subject: [PATCH] MetadataWriter: add fallback to level.dat_old Looking at inotify dumps, it appears like because of bad implementation choices, Minecraft's level.dat may not exist for a brief moment between moving the old file to level.dat_old and moving a new version into place. Add a fallback to level.dat_old, so generation will not fail if were unlucky enough to hit this moment. --- src/core/common.rs | 6 ++++++ src/core/metadata_writer.rs | 9 ++++++++- 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/src/core/common.rs b/src/core/common.rs index edefcb3..d311773 100644 --- a/src/core/common.rs +++ b/src/core/common.rs @@ -139,6 +139,8 @@ pub struct Config { pub region_dir: PathBuf, /// Path of input `level.dat` file pub level_dat_path: PathBuf, + /// Path of input `level.dat_old` file + pub level_dat_old_path: PathBuf, /// Base path for storage of rendered tile data pub output_dir: PathBuf, /// Path for storage of intermediate processed data files @@ -170,6 +172,9 @@ impl Config { let region_dir = [&args.input_dir, Path::new("region")].iter().collect(); let level_dat_path = [&args.input_dir, Path::new("level.dat")].iter().collect(); + let level_dat_old_path = [&args.input_dir, Path::new("level.dat_old")] + .iter() + .collect(); let processed_dir: PathBuf = [&args.output_dir, Path::new("processed")].iter().collect(); let entities_dir: PathBuf = [&processed_dir, Path::new("entities")].iter().collect(); let entities_path_final = [&entities_dir, Path::new("entities.bin")].iter().collect(); @@ -186,6 +191,7 @@ impl Config { num_threads, region_dir, level_dat_path, + level_dat_old_path, output_dir: args.output_dir.clone(), processed_dir, entities_dir, diff --git a/src/core/metadata_writer.rs b/src/core/metadata_writer.rs index 92d8566..eb5f59f 100644 --- a/src/core/metadata_writer.rs +++ b/src/core/metadata_writer.rs @@ -124,7 +124,14 @@ impl<'a> MetadataWriter<'a> { /// Reads and deserializes the `level.dat` of the Minecraft save data fn read_level_dat(&self) -> Result { - crate::nbt::data::from_file(&self.config.level_dat_path).context("Failed to read level.dat") + let res = crate::nbt::data::from_file(&self.config.level_dat_path); + if res.is_err() { + if let Ok(level_dat_old) = crate::nbt::data::from_file(&self.config.level_dat_old_path) + { + return Ok(level_dat_old); + } + } + res.context("Failed to read level.dat") } /// Generates [Spawn] data from a [de::LevelDat]