Download all supported mods for sides

This commit is contained in:
Warren Hood 2024-08-19 00:32:23 +02:00
parent 82fb675b68
commit 30626b6952
4 changed files with 78 additions and 23 deletions

View file

@ -6,6 +6,7 @@ mod resolver;
use clap::{Parser, Subcommand};
use mod_meta::{ModMeta, ModProvider};
use modpack::ModpackMeta;
use providers::DownloadSide;
use std::{error::Error, path::PathBuf};
/// A Minecraft Modpack Manager
@ -78,6 +79,9 @@ enum Commands {
Download {
/// Mods directory
mods_dir: PathBuf,
/// Side to download for
#[arg(long, short, default_value_t = DownloadSide::Both)]
side: DownloadSide,
},
}
@ -183,11 +187,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
panic!("Reverted modpack meta:\n{}", e);
};
match resolver::PinnedPackMeta::load_from_current_directory(
!locked,
)
.await
{
match resolver::PinnedPackMeta::load_from_current_directory(!locked).await {
Ok(mut modpack_lock) => {
let remove_result = modpack_lock.remove_mod(&mod_meta.name, &modpack_meta);
if let Err(e) = remove_result {
@ -241,10 +241,9 @@ async fn main() -> Result<(), Box<dyn Error>> {
}
};
}
Commands::Download { mods_dir } => {
let pack_lock =
resolver::PinnedPackMeta::load_from_current_directory(true).await?;
pack_lock.download_mods(&mods_dir).await?;
Commands::Download { mods_dir, side } => {
let pack_lock = resolver::PinnedPackMeta::load_from_current_directory(true).await?;
pack_lock.download_mods(&mods_dir, side).await?;
println!("Mods updated");
}
}

View file

@ -1,14 +1,58 @@
use std::{collections::HashSet, path::PathBuf};
use serde::{Deserialize, Serialize};
use crate::mod_meta::ModMeta;
use serde::{Deserialize, Serialize};
use std::{collections::HashSet, path::PathBuf, str::FromStr};
pub mod modrinth;
pub mod raw;
#[derive(Serialize, Deserialize, Clone)]
pub enum FileSource {
Download { url: String, sha1: String, sha512: String, filename: String},
Local { path: PathBuf, sha1: String, sha512: String, filename: String },
Download {
url: String,
sha1: String,
sha512: String,
filename: String,
},
Local {
path: PathBuf,
sha1: String,
sha512: String,
filename: String,
},
}
#[derive(Debug, PartialEq, Eq, Clone, Copy)]
pub enum DownloadSide {
Both,
Server,
Client,
}
impl FromStr for DownloadSide {
type Err = String;
fn from_str(s: &str) -> Result<Self, Self::Err> {
match s.to_ascii_lowercase().as_str() {
"both" => Ok(DownloadSide::Both),
"client" => Ok(DownloadSide::Client),
"server" => Ok(DownloadSide::Server),
_ => Err(format!(
"Invalid side {}. Expected one of: both, server, clide",
s
)),
}
}
}
impl ToString for DownloadSide {
fn to_string(&self) -> String {
match self {
DownloadSide::Both => "Both",
DownloadSide::Server => "Server",
DownloadSide::Client => "Client",
}
.into()
}
}
#[derive(Serialize, Deserialize, Clone)]
@ -22,5 +66,5 @@ pub struct PinnedMod {
/// Server side
pub server_side: bool,
/// Required on client side
pub client_side: bool
pub client_side: bool,
}

View file

@ -184,8 +184,8 @@ impl Modrinth {
} else {
None
},
server_side: project.server_side != "optional",
client_side: project.client_side != "optional"
server_side: project.server_side != "unsupported",
client_side: project.client_side != "unsupported"
})
}

View file

@ -10,7 +10,7 @@ use std::{
use crate::{
mod_meta::{ModMeta, ModProvider},
modpack::ModpackMeta,
providers::{modrinth::Modrinth, PinnedMod},
providers::{modrinth::Modrinth, DownloadSide, PinnedMod},
};
const MODPACK_LOCK_FILENAME: &str = "modpack.lock";
@ -31,7 +31,11 @@ impl PinnedPackMeta {
}
/// Clears out anything not in the mods list, and then downloads anything in the mods list not present
pub async fn download_mods(&self, mods_dir: &PathBuf) -> Result<(), Box<dyn Error>> {
pub async fn download_mods(
&self,
mods_dir: &PathBuf,
download_side: DownloadSide,
) -> Result<(), Box<dyn Error>> {
let files = std::fs::read_dir(mods_dir)?;
for file in files.into_iter() {
let file = file?;
@ -41,7 +45,7 @@ impl PinnedPackMeta {
file.file_name()
);
let filename = file.file_name();
if !self.file_is_pinned(&filename) {
if !self.file_is_pinned(&filename, download_side) {
println!(
"Deleting file {:#?} as it is not in the pinned mods",
filename
@ -51,7 +55,11 @@ impl PinnedPackMeta {
}
}
for (_, pinned_mod) in self.mods.iter() {
for (_, pinned_mod) in self.mods.iter().filter(|m| {
download_side == DownloadSide::Both
|| download_side == DownloadSide::Client && m.1.client_side
|| download_side == DownloadSide::Server && m.1.server_side
}) {
for filesource in pinned_mod.source.iter() {
match filesource {
crate::providers::FileSource::Download {
@ -97,8 +105,12 @@ impl PinnedPackMeta {
Ok(())
}
pub fn file_is_pinned(&self, file_name: &OsStr) -> bool {
for (pinned_mod_name, pinned_mod) in self.mods.iter() {
pub fn file_is_pinned(&self, file_name: &OsStr, mod_side: DownloadSide) -> bool {
for (_, pinned_mod) in self.mods.iter().filter(|m| {
mod_side == DownloadSide::Both
|| mod_side == DownloadSide::Client && m.1.client_side
|| mod_side == DownloadSide::Server && m.1.server_side
}) {
for filesource in pinned_mod.source.iter() {
match filesource {
crate::providers::FileSource::Download {