diff --git a/src/main.rs b/src/main.rs index bede293..adbb646 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,12 @@ enum Commands { /// Whether to ignore exact transitive mod versions #[arg(long, short, action)] ignore_transitive_versions: bool, + /// Minecraft version override + #[arg(long, short)] + mc_version: Option, + /// Modloader override + #[arg(long, short)] + modloader: Option, }, /// Remove a mod from the modpack Remove { @@ -106,7 +112,8 @@ async fn main() -> Result<(), Box> { mc_modpack_meta = mc_modpack_meta.provider(provider); } mc_modpack_meta.init_project(&dir)?; - let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir, false).await?; + let modpack_lock = + resolver::PinnedPackMeta::load_from_directory(&dir, false).await?; modpack_lock.save_to_dir(&dir)?; } Commands::New { @@ -129,7 +136,8 @@ async fn main() -> Result<(), Box> { } mc_modpack_meta.init_project(&dir)?; - let modpack_lock = resolver::PinnedPackMeta::load_from_directory(&dir, false).await?; + let modpack_lock = + resolver::PinnedPackMeta::load_from_directory(&dir, false).await?; modpack_lock.save_to_dir(&dir)?; } Commands::Add { @@ -137,11 +145,22 @@ async fn main() -> Result<(), Box> { providers, url, ignore_transitive_versions, + mc_version, + modloader, } => { let mut modpack_meta = ModpackMeta::load_from_current_directory()?; let old_modpack_meta = modpack_meta.clone(); let mut mod_meta = ModMeta::new(&name)?; + + if let Some(modloader) = modloader { + mod_meta = mod_meta.modloader(modloader); + } + + if let Some(mc_version) = mc_version { + mod_meta = mod_meta.mc_version(&mc_version); + } + if let Some(url) = url { mod_meta = mod_meta.url(&url); } @@ -159,7 +178,11 @@ async fn main() -> Result<(), Box> { panic!("Reverted modpack meta:\n{}", e); }; - match resolver::PinnedPackMeta::load_from_current_directory(ignore_transitive_versions).await { + match resolver::PinnedPackMeta::load_from_current_directory( + ignore_transitive_versions, + ) + .await + { Ok(mut modpack_lock) => { let pin_result = modpack_lock .pin_mod_and_deps(&mod_meta, &modpack_meta, ignore_transitive_versions) diff --git a/src/mod_meta.rs b/src/mod_meta.rs index 46f2f40..49ae5c7 100644 --- a/src/mod_meta.rs +++ b/src/mod_meta.rs @@ -2,6 +2,8 @@ use std::{borrow::BorrowMut, error::Error}; use serde::{Deserialize, Serialize}; +use crate::modpack::ModLoader; + #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)] pub enum ModProvider { /// Get mods from CurseForge @@ -25,14 +27,25 @@ impl std::str::FromStr for ModProvider { } } -#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] +#[derive(Debug, Clone, Serialize, Deserialize, Hash)] pub struct ModMeta { pub name: String, pub version: String, pub providers: Option>, + pub mc_version: Option, + pub loader: Option, download_url: Option, } +impl PartialEq for ModMeta { + fn eq(&self, other: &Self) -> bool { + // Only compare mod metadata by name and version + self.name == other.name && self.version == other.version + } +} + +impl Eq for ModMeta {} + impl ModMeta { pub fn new(mod_name: &str) -> Result> { if mod_name.contains("@") { @@ -72,6 +85,16 @@ impl ModMeta { self.version = version_constraint.into(); self } + + pub fn modloader(mut self, modloader: ModLoader) -> Self { + self.loader = Some(modloader); + self + } + + pub fn mc_version(mut self, mc_version: &str) -> Self { + self.mc_version = Some(mc_version.into()); + self + } } impl Default for ModMeta { @@ -81,6 +104,8 @@ impl Default for ModMeta { version: "*".into(), providers: None, download_url: Default::default(), + mc_version: None, + loader: None, } } -} \ No newline at end of file +} diff --git a/src/modpack.rs b/src/modpack.rs index 06a7390..92d9fa6 100644 --- a/src/modpack.rs +++ b/src/modpack.rs @@ -4,7 +4,7 @@ use crate::mod_meta::{ModMeta, ModProvider}; const MODPACK_FILENAME: &str = "modpack.toml"; -#[derive(Debug, Clone, Serialize, Deserialize)] +#[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)] pub enum ModLoader { Forge, Fabric, diff --git a/src/providers/modrinth.rs b/src/providers/modrinth.rs index 36d40ea..7afc3b7 100644 --- a/src/providers/modrinth.rs +++ b/src/providers/modrinth.rs @@ -4,7 +4,7 @@ use std::{collections::HashSet, error::Error}; use super::PinnedMod; use crate::{ mod_meta::{ModMeta, ModProvider}, - modpack::ModpackMeta, + modpack::{ModLoader, ModpackMeta}, providers::FileSource, }; @@ -101,9 +101,17 @@ impl Modrinth { project_id: &str, project_version: Option<&str>, pack_meta: &ModpackMeta, + loader_override: Option, + game_version_override: Option, ) -> Result> { let project_versions = self - .get_project_versions(project_id, pack_meta, true) + .get_project_versions( + project_id, + pack_meta, + true, + loader_override, + game_version_override, + ) .await?; let project_slug = self.get_project_slug(project_id).await?; @@ -129,7 +137,13 @@ impl Modrinth { pack_meta: &ModpackMeta, ) -> Result> { let versions = self - .get_project_versions(&mod_meta.name, pack_meta, false) + .get_project_versions( + &mod_meta.name, + pack_meta, + false, + mod_meta.loader.clone(), + mod_meta.mc_version.clone(), + ) .await?; let package = if mod_meta.version == "*" { @@ -154,8 +168,14 @@ impl Modrinth { if let Some(deps) = &package.dependencies { for dep in deps.iter().filter(|dep| dep.dependency_type == "required") { deps_meta.insert( - self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta) - .await?, + self.get_mod_meta( + &dep.project_id, + dep.version_id.as_deref(), + pack_meta, + mod_meta.loader.clone(), + mod_meta.mc_version.clone(), + ) + .await?, ); } } @@ -188,16 +208,20 @@ impl Modrinth { mod_id: &str, pack_meta: &ModpackMeta, ignore_game_version_and_loader: bool, // For deps we might as well let them use anything + loader_override: Option, + game_version_override: Option, ) -> Result, Box> { + let loader = loader_override + .unwrap_or(pack_meta.modloader.clone()) + .to_string() + .to_lowercase(); + let game_version = game_version_override.unwrap_or(pack_meta.mc_version.clone()); let query_vec = if ignore_game_version_and_loader { &vec![] } else { &vec![ - ( - "loaders", - format!("[\"{}\"]", pack_meta.modloader.to_string().to_lowercase()), - ), - ("game_versions", format!("[\"{}\"]", pack_meta.mc_version)), + ("loaders", format!("[\"{}\"]", loader)), + ("game_versions", format!("[\"{}\"]", game_version)), ] };