From 16af479b833b86b1c0169085a56be7d252a767a9 Mon Sep 17 00:00:00 2001 From: Jai A Date: Sun, 17 Oct 2021 23:22:23 -0700 Subject: [PATCH] Legacy Forge Support --- LICENSE | 0 README.md | 0 daedalus/Cargo.toml | 9 ++++++++- daedalus/README.md | 6 ++++++ daedalus/src/fabric.rs | 8 ++++++-- daedalus/src/forge.rs | 21 +++++++++++++++++++++ daedalus/src/lib.rs | 27 ++++++++++++++++++++++++++- daedalus/src/minecraft.rs | 21 ++++++++++++--------- daedalus_client/src/forge.rs | 0 9 files changed, 79 insertions(+), 13 deletions(-) create mode 100644 LICENSE create mode 100644 README.md create mode 100644 daedalus/README.md create mode 100644 daedalus/src/forge.rs create mode 100644 daedalus_client/src/forge.rs diff --git a/LICENSE b/LICENSE new file mode 100644 index 00000000..e69de29b diff --git a/README.md b/README.md new file mode 100644 index 00000000..e69de29b diff --git a/daedalus/Cargo.toml b/daedalus/Cargo.toml index a52c207f..def9e0dc 100644 --- a/daedalus/Cargo.toml +++ b/daedalus/Cargo.toml @@ -3,6 +3,13 @@ name = "daedalus" version = "0.1.0" authors = ["Jai A "] edition = "2018" +license = "MIT" +description = "Utilities for querying and parsing Minecraft metadata" +repository = "https://github.com/modrinth/daedalus/" +include = ["Cargo.toml", "src/**/*.rs", "README.md", "LICENSE"] +keywords = ["minecraft", "launcher"] +categories = ["game-development", "api-bindings"] +readme = "README.md" # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html @@ -14,4 +21,4 @@ chrono = { version = "0.4", features = ["serde"] } bytes = "1" thiserror = "1.0" tokio = { version = "1", features = ["full"] } -sha1 = { version = "0.6.0", features = ["std"]} \ No newline at end of file +sha1 = { version = "0.6.0", features = ["std"]} diff --git a/daedalus/README.md b/daedalus/README.md new file mode 100644 index 00000000..fb57d0f0 --- /dev/null +++ b/daedalus/README.md @@ -0,0 +1,6 @@ +# Daedalus + +Daedalus (the rust library) is a library providing model structs and methods for requesting and parsing things +from Minecraft and other mod loaders meta APIs. + +This is a work in progress! \ No newline at end of file diff --git a/daedalus/src/fabric.rs b/daedalus/src/fabric.rs index 052486ff..d63705a7 100644 --- a/daedalus/src/fabric.rs +++ b/daedalus/src/fabric.rs @@ -20,7 +20,7 @@ pub struct PartialVersionInfo { /// The latest time a file in this version was updated pub time: DateTime, /// The classpath to the main class to launch the game - pub main_class: String, + pub main_class: Option, /// Arguments passed to the game or JVM pub arguments: Option>>, /// Libraries that the version depends on @@ -51,7 +51,11 @@ pub fn merge_partial_version(partial: PartialVersionInfo, merge: VersionInfo) -> .into_iter() .chain(merge.libraries) .collect::>(), - main_class: partial.main_class, + main_class: if let Some(main_class) = partial.main_class { + main_class + } else { + merge.main_class + }, minecraft_arguments: merge.minecraft_arguments, minimum_launcher_version: merge.minimum_launcher_version, release_time: partial.release_time, diff --git a/daedalus/src/forge.rs b/daedalus/src/forge.rs new file mode 100644 index 00000000..4381f030 --- /dev/null +++ b/daedalus/src/forge.rs @@ -0,0 +1,21 @@ +use crate::{download_file, Error}; + +use std::collections::HashMap; + +/// The latest version of the format the model structs deserialize to +pub const CURRENT_FORMAT_VERSION: usize = 0; + +const DEFAULT_MAVEN_METADATA_URL: &str = + "https://files.minecraftforge.net/net/minecraftforge/forge/maven-metadata.json"; + +/// Fetches the forge maven metadata from the specified URL. If no URL is specified, the default is used. +/// Returns a hashmap specifying the versions of the forge mod loader +/// The hashmap key is a Minecraft version, and the value is the loader versions that work on +/// the specified Minecraft version +pub async fn fetch_maven_metadata( + url: Option<&str>, +) -> Result>, Error> { + Ok(serde_json::from_slice( + &download_file(url.unwrap_or(DEFAULT_MAVEN_METADATA_URL), None).await?, + )?) +} diff --git a/daedalus/src/lib.rs b/daedalus/src/lib.rs index 92ff542f..4f314755 100644 --- a/daedalus/src/lib.rs +++ b/daedalus/src/lib.rs @@ -6,6 +6,8 @@ /// Models and methods for fetching metadata for the Fabric mod loader pub mod fabric; +/// Models and methods for fetching metadata for the Forge mod loader +pub mod forge; /// Models and methods for fetching metadata for Minecraft pub mod minecraft; @@ -56,18 +58,41 @@ pub fn get_path_from_artifact(artifact: &str) -> Result { })?; Ok(format!( - "{}/{}/{}-{}.jar", + "{}/{}/{}/{}-{}.jar", package.replace(".", "/"), + name, version, name, version )) } +/// Downloads a file from specified mirrors +pub async fn download_file_mirrors( + base: &str, + mirrors: &[&str], + sha1: Option<&str>, +) -> Result { + if mirrors.is_empty() { + return Err(Error::ParseError("No mirrors provided!".to_string())); + } + + for (index, mirror) in mirrors.iter().enumerate() { + let result = download_file(&*format!("{}{}", mirror, base), sha1).await; + + if result.is_ok() || (result.is_err() && index == (mirrors.len() - 1)) { + return result; + } + } + + unreachable!() +} + /// Downloads a file with retry and checksum functionality pub async fn download_file(url: &str, sha1: Option<&str>) -> Result { let client = reqwest::Client::builder() .tcp_keepalive(Some(std::time::Duration::from_secs(10))) + .timeout(std::time::Duration::from_secs(30)) .build() .map_err(|err| Error::FetchError { inner: err, diff --git a/daedalus/src/minecraft.rs b/daedalus/src/minecraft.rs index e90e8f4d..d345f04c 100644 --- a/daedalus/src/minecraft.rs +++ b/daedalus/src/minecraft.rs @@ -69,7 +69,7 @@ pub struct LatestVersion { } #[derive(Serialize, Deserialize, Debug, Clone)] -/// Data of all game versions of Minecrafat +/// Data of all game versions of Minecraft pub struct VersionManifest { /// A struct containing the latest snapshot and release of the game pub latest: LatestVersion, @@ -154,7 +154,7 @@ pub struct LibraryDownloads { pub classifiers: Option>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(rename_all = "snake_case")] /// The action a rule can follow pub enum RuleAction { @@ -164,7 +164,7 @@ pub enum RuleAction { Disallow, } -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)] #[serde(rename_all = "snake_case")] /// An enum representing the different types of operating systems pub enum Os { @@ -178,7 +178,7 @@ pub enum Os { Unknown, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] /// A rule which depends on what OS the user is on pub struct OsRule { #[serde(skip_serializing_if = "Option::is_none")] @@ -192,7 +192,7 @@ pub struct OsRule { pub arch: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] /// A rule which depends on the toggled features of the launcher pub struct FeatureRule { #[serde(skip_serializing_if = "Option::is_none")] @@ -203,7 +203,7 @@ pub struct FeatureRule { pub has_demo_resolution: Option, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] /// A rule deciding whether a file is downloaded, an argument is used, etc. pub struct Rule { /// The action the rule takes @@ -244,9 +244,12 @@ pub struct Library { #[serde(skip_serializing_if = "Option::is_none")] /// Rules deciding whether the library should be downloaded or not pub rules: Option>, + #[serde(skip_serializing_if = "Option::is_none")] + /// SHA1 Checksums for validating the library's integrity. Only present for forge libraries + pub checksums: Option>, } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] /// A container for an argument or multiple arguments pub enum ArgumentValue { @@ -256,7 +259,7 @@ pub enum ArgumentValue { Many(Vec), } -#[derive(Serialize, Deserialize, Debug)] +#[derive(Serialize, Deserialize, Debug, Clone)] #[serde(untagged)] /// A command line argument passed to a program pub enum Argument { @@ -271,7 +274,7 @@ pub enum Argument { }, } -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash)] +#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone, Copy)] #[serde(rename_all = "snake_case")] /// The type of argument pub enum ArgumentType { diff --git a/daedalus_client/src/forge.rs b/daedalus_client/src/forge.rs new file mode 100644 index 00000000..e69de29b