MCModpackManager/mcmpmgr/src/modpack.rs

150 lines
4.5 KiB
Rust
Raw Normal View History

2024-08-16 00:31:02 +01:00
use crate::mod_meta::{ModMeta, ModProvider};
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
error::Error,
path::{Path, PathBuf},
};
2024-08-14 20:51:42 +01:00
2024-08-16 00:31:02 +01:00
const MODPACK_FILENAME: &str = "modpack.toml";
2024-08-13 23:56:57 +01:00
#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
2024-08-13 23:56:57 +01:00
pub enum ModLoader {
Forge,
Fabric,
}
impl ToString for ModLoader {
fn to_string(&self) -> String {
match self {
ModLoader::Forge => "Forge",
ModLoader::Fabric => "Fabric",
}
.into()
}
}
impl std::str::FromStr for ModLoader {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s {
"Fabric" => Ok(Self::Fabric),
"Forge" => Ok(Self::Forge),
_ => Err(format!("Invalid mod launcher: {}", s)),
}
}
}
2024-08-17 16:11:04 +01:00
#[derive(Debug, Serialize, Deserialize, Clone)]
2024-08-13 23:56:57 +01:00
pub struct ModpackMeta {
pub pack_name: String,
2024-08-17 16:11:04 +01:00
pub mc_version: String,
pub modloader: ModLoader,
2024-08-17 23:38:40 +01:00
pub mods: HashMap<String, ModMeta>,
2024-08-17 16:11:04 +01:00
pub default_providers: Vec<ModProvider>,
pub forbidden_mods: HashSet<String>,
2024-08-14 20:51:42 +01:00
}
impl ModpackMeta {
2024-08-14 21:28:40 +01:00
pub fn new(pack_name: &str, mc_version: &str, modloader: ModLoader) -> Self {
2024-08-14 20:51:42 +01:00
Self {
2024-08-14 21:28:40 +01:00
pack_name: pack_name.into(),
2024-08-14 20:51:42 +01:00
mc_version: mc_version.into(),
modloader: modloader,
..Default::default()
}
}
pub fn iter_mods(&self) -> std::collections::hash_map::Values<String, ModMeta> {
2024-08-16 00:31:02 +01:00
self.mods.values().into_iter()
}
pub fn load_from_directory(directory: &Path) -> Result<Self, Box<dyn Error>> {
let modpack_meta_file_path = directory.join(PathBuf::from(MODPACK_FILENAME));
2024-08-14 22:32:45 +01:00
if !modpack_meta_file_path.exists() {
return Err(format!(
"Directory '{}' does not seem to be a valid modpack project directory.",
directory.display()
)
.into());
};
let modpack_contents = std::fs::read_to_string(modpack_meta_file_path)?;
Ok(toml::from_str(&modpack_contents)?)
}
pub fn load_from_current_directory() -> Result<Self, Box<dyn Error>> {
Self::load_from_directory(&std::env::current_dir()?)
}
2024-08-14 20:51:42 +01:00
pub fn provider(mut self, provider: ModProvider) -> Self {
if !self.default_providers.contains(&provider) {
self.default_providers.push(provider);
}
self
}
pub fn add_mod(mut self, mod_meta: &ModMeta) -> Result<Self, Box<dyn Error>> {
if self.forbidden_mods.contains(&mod_meta.name) {
return Err(format!("Cannot add forbidden mod {} to modpack", mod_meta.name).into());
} else {
self.mods
.insert(mod_meta.name.to_string(), mod_meta.clone());
}
Ok(self)
}
pub fn forbid_mod(&mut self, mod_name: &str) {
self.forbidden_mods.insert(mod_name.into());
println!("Mod {} has been forbidden from the modpack", mod_name);
2024-08-14 20:51:42 +01:00
}
2024-08-14 21:28:40 +01:00
2024-08-17 23:38:40 +01:00
pub fn remove_mod(mut self, mod_name: &str) -> Self {
self.mods.remove(mod_name);
self
}
pub fn init_project(&self, directory: &Path) -> Result<(), Box<dyn Error>> {
let modpack_meta_file_path = directory.join(PathBuf::from(MODPACK_FILENAME));
2024-08-14 21:28:40 +01:00
if modpack_meta_file_path.exists() {
return Err(format!(
"{MODPACK_FILENAME} already exists at {}",
2024-08-14 21:28:40 +01:00
modpack_meta_file_path.display()
)
.into());
}
2024-08-14 22:32:45 +01:00
self.save_to_file(&modpack_meta_file_path)?;
println!("MC modpack project initialized at {}", directory.display());
Ok(())
}
pub fn save_to_file(&self, path: &PathBuf) -> Result<(), Box<dyn Error>> {
2024-08-14 21:28:40 +01:00
std::fs::write(
2024-08-14 22:32:45 +01:00
path,
toml::to_string(self).expect("MC Modpack Meta should be serializable"),
2024-08-14 21:28:40 +01:00
)?;
2024-08-17 22:34:06 +01:00
// println!("Saved modpack metadata to {}", path.display());
2024-08-14 22:32:45 +01:00
Ok(())
}
2024-08-14 21:28:40 +01:00
2024-08-14 22:32:45 +01:00
pub fn save_current_dir_project(&self) -> Result<(), Box<dyn Error>> {
let modpack_meta_file_path = std::env::current_dir()?.join(PathBuf::from(MODPACK_FILENAME));
self.save_to_file(&modpack_meta_file_path)?;
2024-08-14 21:28:40 +01:00
Ok(())
}
2024-08-13 23:56:57 +01:00
}
impl std::default::Default for ModpackMeta {
fn default() -> Self {
Self {
2024-08-14 21:28:40 +01:00
pack_name: "my_modpack".into(),
2024-08-13 23:56:57 +01:00
mc_version: "1.20.1".into(),
modloader: ModLoader::Forge,
mods: Default::default(),
2024-08-14 20:51:42 +01:00
default_providers: vec![ModProvider::Modrinth],
forbidden_mods: Default::default(),
2024-08-13 23:56:57 +01:00
}
}
}