use crate::backup::uncompress_backup; use crate::chunk_coordinate::ChunkCoordinate; use crate::error::Result; use anvil_region::AnvilChunkProvider; use std::fs::remove_dir_all; use std::path::PathBuf; /// Struct for manipulating a world from a backup struct RestoreAccess { /// Chunk source src_path: PathBuf, /// Chunk destination dest_path: PathBuf, } impl RestoreAccess { /// Create new RestoreAccess pub fn new(world_name: &str, src_path: &PathBuf, dest_path: &PathBuf) -> Result { let src_path = uncompress_backup(src_path)?.join(world_name).join("region"); let dest_path = dest_path.join(world_name).join("region"); Ok(RestoreAccess { src_path, dest_path, }) } /// Copy chunk from source to desination pub fn copy_chunk(&self, x: i32, z: i32) { let src_provider = AnvilChunkProvider::new(self.src_path.to_str().unwrap()); let dest_provider = AnvilChunkProvider::new(self.dest_path.to_str().unwrap()); let chunk = src_provider.load_chunk(x, z).expect("Unable to load chunk"); dest_provider .save_chunk(x, z, chunk) .expect("Unable to save chunk"); } /// Cleanup process pub fn cleanup(self) -> Result<()> { Ok(remove_dir_all("tmp")?) } } /// Restore a range of chunks from a backup pub fn restore_range_from_backup( world_name: &str, lower: ChunkCoordinate, upper: ChunkCoordinate, backup_path: &PathBuf, minecraft_dir: &PathBuf, ) -> Result { let chunk_access = RestoreAccess::new(world_name, backup_path, minecraft_dir)?; let mut count = 0; for x in lower.x..=upper.x { for z in lower.z..=upper.z { chunk_access.copy_chunk(x, z); count += 1; } } chunk_access.cleanup()?; Ok(count) } /// Restore a single chunk from a backup pub fn restore_chunk_from_backup( world_name: &str, chunk: ChunkCoordinate, backup_path: &PathBuf, minecraft_dir: &PathBuf, ) -> Result<()> { let chunk_access = RestoreAccess::new(world_name, backup_path, minecraft_dir)?; chunk_access.copy_chunk(chunk.x, chunk.z); chunk_access.cleanup()?; Ok(()) }