mirror of
https://git.ahines.net/joeyahines/Albatross.git
synced 2026-11-08 09:13:57 +00:00
Initial Commit
+ Handles overworld back up of regions + Needs to do player data backup and + Support for other world types needed as well
This commit is contained in:
commit
bb38e05479
6 files changed
+718
No files matched your search
+184
@@ -0,0 +1,184 @@
|
||||
extern crate serde;
|
||||
|
||||
#[macro_use]
|
||||
extern crate serde_derive;
|
||||
|
||||
use chrono::Utc;
|
||||
use clap::{App, Arg};
|
||||
use regex::Regex;
|
||||
use std::fs::{copy, create_dir, create_dir_all};
|
||||
use std::path::PathBuf;
|
||||
|
||||
mod albatross_config;
|
||||
|
||||
use albatross_config::{AlbatrossConfig, WorldConfig, WorldType};
|
||||
|
||||
struct Region {
|
||||
x: i64,
|
||||
y: i64,
|
||||
}
|
||||
|
||||
impl Region {
|
||||
fn from_string(string: String) -> Option<Self> {
|
||||
let re = Regex::new(r"r\.(?P<x>-?[0-9])+\.(?P<y>-?[0-9])").unwrap();
|
||||
if re.is_match(string.as_str()) {
|
||||
let captures = re.captures(string.as_str()).unwrap();
|
||||
|
||||
return Some(Region {
|
||||
x: captures["x"].parse::<i64>().unwrap(),
|
||||
y: captures["y"].parse::<i64>().unwrap(),
|
||||
});
|
||||
}
|
||||
|
||||
None
|
||||
}
|
||||
}
|
||||
|
||||
fn backup_dir(
|
||||
dir_name: &str,
|
||||
world_path: &PathBuf,
|
||||
backup_path: &PathBuf,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mut src_dir = world_path.clone();
|
||||
src_dir.push(dir_name);
|
||||
let mut backup_dir = backup_path.clone();
|
||||
backup_dir.push(dir_name);
|
||||
create_dir(&backup_dir)?;
|
||||
|
||||
for entry in src_dir.read_dir().unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let mut target = backup_dir.clone();
|
||||
target.push(entry.file_name());
|
||||
|
||||
copy(entry.path(), target)?;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn backup_region(
|
||||
dir_name: &str,
|
||||
save_radius: u64,
|
||||
world_path: &PathBuf,
|
||||
backup_path: &PathBuf,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mut src_dir = world_path.clone();
|
||||
src_dir.push(dir_name);
|
||||
let mut backup_dir = backup_path.clone();
|
||||
backup_dir.push(dir_name);
|
||||
create_dir(&backup_dir)?;
|
||||
|
||||
let save_radius = if save_radius < 512 {
|
||||
1 as i64
|
||||
} else {
|
||||
(save_radius / 512) as i64
|
||||
};
|
||||
|
||||
for entry in src_dir.read_dir().unwrap() {
|
||||
let entry = entry.unwrap();
|
||||
let file_name = entry.file_name().to_str().unwrap().to_string();
|
||||
|
||||
if let Some(region) = Region::from_string(file_name) {
|
||||
if region.x.abs() < save_radius && region.y.abs() < save_radius {
|
||||
let mut target = backup_dir.clone();
|
||||
target.push(entry.file_name());
|
||||
|
||||
copy(entry.path(), target)?;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn backup_world(
|
||||
world_path: PathBuf,
|
||||
backup_path: PathBuf,
|
||||
world_config: &WorldConfig,
|
||||
) -> Result<(), std::io::Error> {
|
||||
let mut backup_path = backup_path.clone();
|
||||
backup_path.push(&world_config.world_name);
|
||||
create_dir(backup_path.as_path())?;
|
||||
|
||||
backup_region("poi", world_config.save_radius, &world_path, &backup_path)?;
|
||||
backup_region(
|
||||
"region",
|
||||
world_config.save_radius,
|
||||
&world_path,
|
||||
&backup_path,
|
||||
)?;
|
||||
backup_dir("data", &world_path, &backup_path)?;
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn backup_overworld(
|
||||
world_path: PathBuf,
|
||||
backup_path: PathBuf,
|
||||
world_config: &WorldConfig,
|
||||
) -> Result<(), std::io::Error> {
|
||||
backup_world(world_path, backup_path, world_config)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn do_backup(cfg: AlbatrossConfig) -> Result<(), std::io::Error> {
|
||||
let server_base_dir = cfg.backup.minecraft_dir.clone();
|
||||
let worlds = cfg.world_config.unwrap().clone();
|
||||
let time_str = Utc::now().format("%d-%m-%y_%H:%M%S").to_string();
|
||||
let backup_name = format!("{}-backup", time_str);
|
||||
let mut tmp_dir = cfg.backup.output_dir.clone();
|
||||
tmp_dir.push(backup_name);
|
||||
|
||||
create_dir_all(tmp_dir.clone()).unwrap();
|
||||
|
||||
for world in worlds {
|
||||
let mut world_dir = server_base_dir.clone();
|
||||
let world_name = world.world_name.clone();
|
||||
let world_type = match world.world_type.clone() {
|
||||
Some(world_type) => world_type,
|
||||
None => WorldType::OVERWORLD,
|
||||
};
|
||||
world_dir.push(world_name.clone());
|
||||
|
||||
if world_dir.exists() && world_dir.is_dir() {
|
||||
match world_type {
|
||||
WorldType::OVERWORLD => {
|
||||
backup_overworld(world_dir, tmp_dir.clone(), &world)?;
|
||||
}
|
||||
_ => {}
|
||||
};
|
||||
} else {
|
||||
println!("World \"{}\" not found", world_name.clone());
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn main() {
|
||||
let mut app = App::new("Albatross").about("Backup your worlds").arg(
|
||||
Arg::with_name("config")
|
||||
.index(1)
|
||||
.short("c")
|
||||
.long("config")
|
||||
.value_name("CONFIG_PATH")
|
||||
.help("Config file path"),
|
||||
);
|
||||
// Get arg parser
|
||||
let matches = app.clone().get_matches();
|
||||
|
||||
if let Some(cfg_path) = matches.value_of("config") {
|
||||
let cfg = AlbatrossConfig::new(cfg_path).expect("Config not found");
|
||||
|
||||
if cfg.world_config.is_some() {
|
||||
match do_backup(cfg) {
|
||||
Err(e) => println!("Error doing backup: {}", e),
|
||||
_ => {}
|
||||
}
|
||||
} else {
|
||||
println!("No worlds specified to backed up!")
|
||||
}
|
||||
} else {
|
||||
app.print_help().expect("Unable to print help");
|
||||
}
|
||||
}
|
||||
Reference in new issue
Block a user