Add a command to forbid installing specific mods from the pack

This commit is contained in:
Warren Hood 2024-08-19 01:50:38 +02:00
parent f7862abcc6
commit 0fcfe434d5
3 changed files with 69 additions and 17 deletions

View file

@ -78,6 +78,11 @@ enum Commands {
#[arg(long, short, action)] #[arg(long, short, action)]
force: bool, force: bool,
}, },
/// Forbid a mod from the modpack
Forbid {
/// Name of the mod to remove and forbid from the modpack
name: String,
},
/// Download the mods in the pack to a specified folder /// Download the mods in the pack to a specified folder
Download { Download {
/// Mods directory /// Mods directory
@ -184,7 +189,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
for provider in providers.into_iter() { for provider in providers.into_iter() {
mod_meta = mod_meta.provider(provider); mod_meta = mod_meta.provider(provider);
} }
modpack_meta = modpack_meta.add_mod(&mod_meta); modpack_meta = modpack_meta.add_mod(&mod_meta)?;
modpack_meta.save_current_dir_project()?; modpack_meta.save_current_dir_project()?;
let revert_modpack_meta = |e| -> ! { let revert_modpack_meta = |e| -> ! {
@ -250,6 +255,38 @@ async fn main() -> Result<(), Box<dyn Error>> {
} }
}; };
} }
Commands::Forbid { name } => {
let mut modpack_meta = ModpackMeta::load_from_current_directory()?;
let old_modpack_meta = modpack_meta.clone();
modpack_meta.forbid_mod(&name);
modpack_meta = modpack_meta.remove_mod(&name);
modpack_meta.save_current_dir_project()?;
let revert_modpack_meta = |e| -> ! {
let revert_result = old_modpack_meta.save_current_dir_project();
if let Err(result) = revert_result {
panic!("Failed to revert modpack meta: {}", result);
}
panic!("Reverted modpack meta:\n{}", e);
};
match resolver::PinnedPackMeta::load_from_current_directory(true).await {
Ok(mut modpack_lock) => {
let remove_result = modpack_lock.remove_mod(&name, &modpack_meta, true);
if let Err(e) = remove_result {
revert_modpack_meta(e);
}
if let Err(e) = modpack_lock.save_current_dir_lock() {
revert_modpack_meta(e);
}
}
Err(e) => {
revert_modpack_meta(e);
}
};
}
Commands::Download { mods_dir, side } => { Commands::Download { mods_dir, side } => {
let pack_lock = resolver::PinnedPackMeta::load_from_current_directory(true).await?; let pack_lock = resolver::PinnedPackMeta::load_from_current_directory(true).await?;
pack_lock.download_mods(&mods_dir, side).await?; pack_lock.download_mods(&mods_dir, side).await?;

View file

@ -1,6 +1,10 @@
use std::{collections::HashMap, error::Error, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::mod_meta::{ModMeta, ModProvider}; use crate::mod_meta::{ModMeta, ModProvider};
use serde::{Deserialize, Serialize};
use std::{
collections::{HashMap, HashSet},
error::Error,
path::PathBuf,
};
const MODPACK_FILENAME: &str = "modpack.toml"; const MODPACK_FILENAME: &str = "modpack.toml";
@ -39,6 +43,7 @@ pub struct ModpackMeta {
pub modloader: ModLoader, pub modloader: ModLoader,
pub mods: HashMap<String, ModMeta>, pub mods: HashMap<String, ModMeta>,
pub default_providers: Vec<ModProvider>, pub default_providers: Vec<ModProvider>,
pub forbidden_mods: HashSet<String>,
} }
impl ModpackMeta { impl ModpackMeta {
@ -51,7 +56,7 @@ impl ModpackMeta {
} }
} }
pub fn iter_mods(&self) -> std::collections::hash_map::Values<String, ModMeta> { pub fn iter_mods(&self) -> std::collections::hash_map::Values<String, ModMeta> {
self.mods.values().into_iter() self.mods.values().into_iter()
} }
@ -79,18 +84,19 @@ impl ModpackMeta {
self self
} }
pub fn add_mod(mut self, mod_meta: &ModMeta) -> Self { pub fn add_mod(mut self, mod_meta: &ModMeta) -> Result<Self, Box<dyn Error>> {
// if let Some(old_mod_meta) = self.mods.get(&mod_meta.name) { if self.forbidden_mods.contains(&mod_meta.name) {
// println!("Updating {} version constraints: {} -> {}", mod_meta.name, old_mod_meta.version, mod_meta.version); return Err(format!("Cannot add forbidden mod {} to modpack", mod_meta.name).into());
// } } else {
// else { self.mods
// println!( .insert(mod_meta.name.to_string(), mod_meta.clone());
// "Adding {}@{} to modpack '{}'...", }
// mod_meta.name, mod_meta.version, self.pack_name Ok(self)
// ); }
// }
self.mods.insert(mod_meta.name.to_string(), mod_meta.clone()); pub fn forbid_mod(&mut self, mod_name: &str) {
self self.forbidden_mods.insert(mod_name.into());
println!("Mod {} has been forbidden from the modpack", mod_name);
} }
pub fn remove_mod(mut self, mod_name: &str) -> Self { pub fn remove_mod(mut self, mod_name: &str) -> Self {
@ -137,6 +143,7 @@ impl std::default::Default for ModpackMeta {
modloader: ModLoader::Forge, modloader: ModLoader::Forge,
mods: Default::default(), mods: Default::default(),
default_providers: vec![ModProvider::Modrinth], default_providers: vec![ModProvider::Modrinth],
forbidden_mods: Default::default(),
} }
} }
} }

View file

@ -191,6 +191,11 @@ impl PinnedPackMeta {
mod_metadata: &ModMeta, mod_metadata: &ModMeta,
pack_metadata: &ModpackMeta, pack_metadata: &ModpackMeta,
) -> Result<Vec<ModMeta>, Box<dyn Error>> { ) -> Result<Vec<ModMeta>, Box<dyn Error>> {
if pack_metadata.forbidden_mods.contains(&mod_metadata.name) {
println!("Skipping adding forbidden mod {}...", mod_metadata.name);
return Ok(vec![]);
}
let mod_providers = if let Some(mod_providers) = &mod_metadata.providers { let mod_providers = if let Some(mod_providers) = &mod_metadata.providers {
mod_providers mod_providers
} else { } else {
@ -262,7 +267,10 @@ impl PinnedPackMeta {
force: bool, force: bool,
) -> Result<(), Box<dyn Error>> { ) -> Result<(), Box<dyn Error>> {
if !self.mods.contains_key(mod_name) { if !self.mods.contains_key(mod_name) {
eprintln!("Skipping removing non-existent mod {} from modpack", mod_name); eprintln!(
"Skipping removing non-existent mod {} from modpack",
mod_name
);
return Ok(()); return Ok(());
} }
let dependent_mods = self.get_dependent_mods(mod_name); let dependent_mods = self.get_dependent_mods(mod_name);