You cannot select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
minecraft-regions-tool/src/world_folder.rs

77 lines
2.2 KiB
Rust

use crate::region_file::RegionFile;
use crate::scan::ScanStatistics;
use indicatif::{ProgressBar, ProgressStyle};
use rayon::prelude::*;
use std::fs;
use std::fs::{File, OpenOptions};
use std::io;
use std::io::{BufReader, BufWriter};
use std::ops::Add;
use std::path::PathBuf;
use std::sync::{Arc, Mutex};
pub struct WorldFolder {
path: PathBuf,
}
impl WorldFolder {
pub fn new(path: PathBuf) -> Self {
Self { path }
}
/// Counts all chunks of a world
pub fn count_chunks(&self) -> io::Result<u64> {
let mut count = 0u64;
for file in self.region_file_paths() {
let f = File::open(file)?;
let region_file = RegionFile::new(BufReader::new(f))?;
count += region_file.count_chunks() as u64;
}
Ok(count)
}
pub fn scan_files(&self, fix: bool) -> io::Result<()> {
let paths = self.region_file_paths();
let bar = Arc::new(Mutex::new(ProgressBar::new(paths.len() as u64)));
bar.lock().unwrap().set_style(
ProgressStyle::default_bar().template("[{eta_precise}] {wide_bar} {pos}/{len} "),
);
let statistic: ScanStatistics = paths
.par_iter()
.filter_map(|file| {
let f = OpenOptions::new().read(true).open(file).ok()?;
let mut region_file = RegionFile::new(BufReader::new(f)).ok()?;
let result = region_file.scan_chunks().ok()?;
if fix {
let f = OpenOptions::new().write(true).open(file).ok()?;
let mut writer = BufWriter::new(f);
region_file.write(&mut writer).ok()?;
}
bar.lock().unwrap().inc(1);
Some(result)
})
.reduce(|| ScanStatistics::new(), |a, b| a.add(b));
bar.lock().unwrap().finish_and_clear();
println!("{}", statistic);
Ok(())
}
/// Returns a list of region file paths for the world folder
fn region_file_paths(&self) -> Vec<PathBuf> {
let region_file_path = self.path.join(PathBuf::from("region"));
fs::read_dir(region_file_path)
.unwrap()
.filter_map(|e| e.ok().map(|e| e.path()))
.collect()
}
}