Allow for per mod loader and mc version overrides

This commit is contained in:
Warren Hood 2024-08-18 02:16:23 +02:00
parent 86fa34d9a2
commit b1f9007f10
4 changed files with 88 additions and 16 deletions

View file

@ -62,6 +62,12 @@ enum Commands {
/// Whether to ignore exact transitive mod versions /// Whether to ignore exact transitive mod versions
#[arg(long, short, action)] #[arg(long, short, action)]
ignore_transitive_versions: bool, ignore_transitive_versions: bool,
/// Minecraft version override
#[arg(long, short)]
mc_version: Option<String>,
/// Modloader override
#[arg(long, short)]
modloader: Option<modpack::ModLoader>,
}, },
/// Remove a mod from the modpack /// Remove a mod from the modpack
Remove { Remove {
@ -106,7 +112,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
mc_modpack_meta = mc_modpack_meta.provider(provider); mc_modpack_meta = mc_modpack_meta.provider(provider);
} }
mc_modpack_meta.init_project(&dir)?; 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)?; modpack_lock.save_to_dir(&dir)?;
} }
Commands::New { Commands::New {
@ -129,7 +136,8 @@ async fn main() -> Result<(), Box<dyn Error>> {
} }
mc_modpack_meta.init_project(&dir)?; 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)?; modpack_lock.save_to_dir(&dir)?;
} }
Commands::Add { Commands::Add {
@ -137,11 +145,22 @@ async fn main() -> Result<(), Box<dyn Error>> {
providers, providers,
url, url,
ignore_transitive_versions, ignore_transitive_versions,
mc_version,
modloader,
} => { } => {
let mut modpack_meta = ModpackMeta::load_from_current_directory()?; let mut modpack_meta = ModpackMeta::load_from_current_directory()?;
let old_modpack_meta = modpack_meta.clone(); let old_modpack_meta = modpack_meta.clone();
let mut mod_meta = ModMeta::new(&name)?; 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 { if let Some(url) = url {
mod_meta = mod_meta.url(&url); mod_meta = mod_meta.url(&url);
} }
@ -159,7 +178,11 @@ async fn main() -> Result<(), Box<dyn Error>> {
panic!("Reverted modpack meta:\n{}", e); 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) => { Ok(mut modpack_lock) => {
let pin_result = modpack_lock let pin_result = modpack_lock
.pin_mod_and_deps(&mod_meta, &modpack_meta, ignore_transitive_versions) .pin_mod_and_deps(&mod_meta, &modpack_meta, ignore_transitive_versions)

View file

@ -2,6 +2,8 @@ use std::{borrow::BorrowMut, error::Error};
use serde::{Deserialize, Serialize}; use serde::{Deserialize, Serialize};
use crate::modpack::ModLoader;
#[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)] #[derive(Debug, Serialize, Deserialize, PartialEq, Eq, Hash, Clone)]
pub enum ModProvider { pub enum ModProvider {
/// Get mods from CurseForge /// 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 struct ModMeta {
pub name: String, pub name: String,
pub version: String, pub version: String,
pub providers: Option<Vec<ModProvider>>, pub providers: Option<Vec<ModProvider>>,
pub mc_version: Option<String>,
pub loader: Option<ModLoader>,
download_url: Option<String>, download_url: Option<String>,
} }
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 { impl ModMeta {
pub fn new(mod_name: &str) -> Result<Self, Box<dyn Error>> { pub fn new(mod_name: &str) -> Result<Self, Box<dyn Error>> {
if mod_name.contains("@") { if mod_name.contains("@") {
@ -72,6 +85,16 @@ impl ModMeta {
self.version = version_constraint.into(); self.version = version_constraint.into();
self 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 { impl Default for ModMeta {
@ -81,6 +104,8 @@ impl Default for ModMeta {
version: "*".into(), version: "*".into(),
providers: None, providers: None,
download_url: Default::default(), download_url: Default::default(),
mc_version: None,
loader: None,
} }
} }
} }

View file

@ -4,7 +4,7 @@ use crate::mod_meta::{ModMeta, ModProvider};
const MODPACK_FILENAME: &str = "modpack.toml"; const MODPACK_FILENAME: &str = "modpack.toml";
#[derive(Debug, Clone, Serialize, Deserialize)] #[derive(Debug, Clone, Serialize, Deserialize, PartialEq, Eq, Hash)]
pub enum ModLoader { pub enum ModLoader {
Forge, Forge,
Fabric, Fabric,

View file

@ -4,7 +4,7 @@ use std::{collections::HashSet, error::Error};
use super::PinnedMod; use super::PinnedMod;
use crate::{ use crate::{
mod_meta::{ModMeta, ModProvider}, mod_meta::{ModMeta, ModProvider},
modpack::ModpackMeta, modpack::{ModLoader, ModpackMeta},
providers::FileSource, providers::FileSource,
}; };
@ -101,9 +101,17 @@ impl Modrinth {
project_id: &str, project_id: &str,
project_version: Option<&str>, project_version: Option<&str>,
pack_meta: &ModpackMeta, pack_meta: &ModpackMeta,
loader_override: Option<ModLoader>,
game_version_override: Option<String>,
) -> Result<ModMeta, Box<dyn Error>> { ) -> Result<ModMeta, Box<dyn Error>> {
let project_versions = self 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?; .await?;
let project_slug = self.get_project_slug(project_id).await?; let project_slug = self.get_project_slug(project_id).await?;
@ -129,7 +137,13 @@ impl Modrinth {
pack_meta: &ModpackMeta, pack_meta: &ModpackMeta,
) -> Result<PinnedMod, Box<dyn Error>> { ) -> Result<PinnedMod, Box<dyn Error>> {
let versions = self 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?; .await?;
let package = if mod_meta.version == "*" { let package = if mod_meta.version == "*" {
@ -154,8 +168,14 @@ impl Modrinth {
if let Some(deps) = &package.dependencies { if let Some(deps) = &package.dependencies {
for dep in deps.iter().filter(|dep| dep.dependency_type == "required") { for dep in deps.iter().filter(|dep| dep.dependency_type == "required") {
deps_meta.insert( deps_meta.insert(
self.get_mod_meta(&dep.project_id, dep.version_id.as_deref(), pack_meta) self.get_mod_meta(
.await?, &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, mod_id: &str,
pack_meta: &ModpackMeta, pack_meta: &ModpackMeta,
ignore_game_version_and_loader: bool, // For deps we might as well let them use anything ignore_game_version_and_loader: bool, // For deps we might as well let them use anything
loader_override: Option<ModLoader>,
game_version_override: Option<String>,
) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> { ) -> Result<Vec<ModrinthProjectVersion>, Box<dyn Error>> {
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 { let query_vec = if ignore_game_version_and_loader {
&vec![] &vec![]
} else { } else {
&vec![ &vec![
( ("loaders", format!("[\"{}\"]", loader)),
"loaders", ("game_versions", format!("[\"{}\"]", game_version)),
format!("[\"{}\"]", pack_meta.modloader.to_string().to_lowercase()),
),
("game_versions", format!("[\"{}\"]", pack_meta.mc_version)),
] ]
}; };