From 5a6c06c8a3dea11e5f10a491a40687b8ddcccba1 Mon Sep 17 00:00:00 2001 From: Jai A Date: Sat, 18 Dec 2021 22:55:03 -0700 Subject: [PATCH] Host all loaders for forge, fix stable markers, add java version to daedalus --- .idea/runConfigurations.xml | 10 --- daedalus/Cargo.toml | 2 +- daedalus/src/minecraft.rs | 12 ++++ daedalus/src/modded.rs | 16 ++--- daedalus_client/Cargo.toml | 2 +- daedalus_client/src/fabric.rs | 90 ++++++++++++++++-------- daedalus_client/src/forge.rs | 116 ++++++++++++++++++++----------- daedalus_client/src/main.rs | 31 ++++++--- daedalus_client/src/minecraft.rs | 7 +- 9 files changed, 180 insertions(+), 106 deletions(-) delete mode 100644 .idea/runConfigurations.xml diff --git a/.idea/runConfigurations.xml b/.idea/runConfigurations.xml deleted file mode 100644 index 797acea53..000000000 --- a/.idea/runConfigurations.xml +++ /dev/null @@ -1,10 +0,0 @@ - - - - - - \ No newline at end of file diff --git a/daedalus/Cargo.toml b/daedalus/Cargo.toml index f5e583bae..38aee9792 100644 --- a/daedalus/Cargo.toml +++ b/daedalus/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "daedalus" -version = "0.1.7" +version = "0.1.8" authors = ["Jai A "] edition = "2018" license = "MIT" diff --git a/daedalus/src/minecraft.rs b/daedalus/src/minecraft.rs index 0e9a863bf..250262cdc 100644 --- a/daedalus/src/minecraft.rs +++ b/daedalus/src/minecraft.rs @@ -229,6 +229,15 @@ pub struct LibraryExtract { pub exclude: Option>, } +#[derive(Serialize, Deserialize, Debug)] +/// Information about the java version the game needs +pub struct JavaVersion { + /// The component needed for the Java installation + component: String, + /// The major Java version number + major_version: u32, +} + #[derive(Serialize, Deserialize, Debug)] /// A library which the game relies on to run pub struct Library { @@ -311,6 +320,9 @@ pub struct VersionInfo { pub downloads: HashMap, /// The version ID of the version pub id: String, + + /// The Java version this version supports + pub java_version: JavaVersion, /// Libraries that the version depends on pub libraries: Vec, /// The classpath to the main class to launch the game diff --git a/daedalus/src/modded.rs b/daedalus/src/modded.rs index 41289f343..ea3e07c96 100644 --- a/daedalus/src/modded.rs +++ b/daedalus/src/modded.rs @@ -112,6 +112,7 @@ pub fn merge_partial_version(partial: PartialVersionInfo, merge: VersionInfo) -> assets: merge.assets, downloads: merge.downloads, id: partial.id, + java_version: merge.java_version, libraries: partial .libraries .into_iter() @@ -140,24 +141,13 @@ pub struct Manifest { pub game_versions: Vec, } -#[derive(Serialize, Deserialize, Debug, Eq, PartialEq, Hash, Clone)] -#[serde(rename_all = "camelCase")] -/// The version type of the loader -pub enum LoaderType { - /// The latest type is for experimental loader versions that may not be ready for normal use - Latest, - /// The stable type is for the most stable but recent loader version. For the forge mod loader, - /// this is never used - Stable, -} - #[derive(Serialize, Deserialize, Debug, Clone)] /// A game version of Minecraft pub struct Version { /// The minecraft version ID pub id: String, /// A map that contains loader versions for the game version - pub loaders: HashMap, + pub loaders: Vec, } #[derive(Serialize, Deserialize, Debug, Clone)] @@ -167,6 +157,8 @@ pub struct LoaderVersion { pub id: String, /// The URL of the version's manifest pub url: String, + /// Whether the loader is stable or not + pub stable: bool, } /// Fetches the manifest of a mod loader diff --git a/daedalus_client/Cargo.toml b/daedalus_client/Cargo.toml index f30de5b53..77ae6fd46 100644 --- a/daedalus_client/Cargo.toml +++ b/daedalus_client/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "daedalus_client" -version = "0.1.4" +version = "0.1.8" authors = ["Jai A "] edition = "2018" diff --git a/daedalus_client/src/fabric.rs b/daedalus_client/src/fabric.rs index 0024a6ab2..514252c96 100644 --- a/daedalus_client/src/fabric.rs +++ b/daedalus_client/src/fabric.rs @@ -1,15 +1,17 @@ use crate::{format_url, upload_file_to_bucket, Error}; use daedalus::download_file; -use daedalus::minecraft::Library; -use daedalus::modded::{LoaderType, LoaderVersion, Manifest, PartialVersionInfo, Version}; +use daedalus::minecraft::{Library, VersionManifest}; +use daedalus::modded::{LoaderVersion, Manifest, PartialVersionInfo, Version}; use log::info; use serde::{Deserialize, Serialize}; -use std::collections::HashMap; use std::sync::Arc; use std::time::{Duration, Instant}; -use tokio::sync::Mutex; +use tokio::sync::{Mutex, RwLock}; -pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error> { +pub async fn retrieve_data( + minecraft_versions: &VersionManifest, + uploaded_files: &mut Vec, +) -> Result<(), Error> { let mut list = fetch_fabric_versions(None).await?; let old_manifest = daedalus::modded::fetch_manifest(&*format!( "fabric/v{}/manifest.json", @@ -27,24 +29,28 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error let uploaded_files_mutex = Arc::new(Mutex::new(Vec::new())); if let Some(latest) = list.loader.get(0) { - let loaders_mutex = Arc::new(Mutex::new(HashMap::new())); + let loaders_mutex = Arc::new(RwLock::new(Vec::new())); let visited_artifacts_mutex = Arc::new(Mutex::new(Vec::new())); { - let mut loaders = loaders_mutex.lock().await; + let mut loaders = loaders_mutex.write().await; - loaders.insert(LoaderType::Latest, latest.version.clone()); + // for loader in &list.loader { + // loaders.push((Box::new(loader.stable), loader.version.clone())) + // } + + loaders.push((Box::new(latest.stable), latest.version.clone())); if !latest.stable { if let Some(stable) = list.loader.iter().find(|x| x.stable) { - loaders.insert(LoaderType::Stable, stable.version.clone()); + loaders.push((Box::new(stable.stable), stable.version.clone())); } } list.loader = list .loader .into_iter() - .filter(|x| loaders.values().any(|val| val == &x.version)) + .filter(|x| loaders.iter().any(|val| val.1 == x.version)) .collect(); } @@ -57,19 +63,16 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error let versions_mutex = Arc::clone(&versions); version_futures.push(async move { - let loader_version_mutex = Mutex::new(HashMap::new()); + let loader_version_mutex = Mutex::new(Vec::new()); let versions = futures::future::try_join_all( - loaders_mutex.lock().await.clone().into_iter().map( - |(type_, loader)| async { + loaders_mutex.read().await.clone().into_iter().map( + |(stable, loader)| async { { if versions_mutex.lock().await.iter().any(|x| { x.id == game_version.version - && x.loaders - .get(&type_) - .map(|x| x.id == loader) - .unwrap_or(false) + && x.loaders.iter().any(|x| x.id == loader) }) { return Ok(None); } @@ -78,8 +81,8 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error let version = fetch_fabric_version(&*game_version.version, &*loader).await?; - Ok::, Error>(Some( - (type_, loader, version), + Ok::, String, PartialVersionInfo)>, Error>(Some( + (stable, loader, version), )) }, ), @@ -88,7 +91,7 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error .into_iter() .flatten(); - futures::future::try_join_all(versions.map(|(type_, loader, version)| async { + futures::future::try_join_all(versions.map(|(stable, loader, version)| async { let libs = futures::future::try_join_all(version.libraries.into_iter().map( |mut lib| async { { @@ -164,13 +167,11 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error { let mut loader_version_map = loader_version_mutex.lock().await; async move { - loader_version_map.insert( - type_, - LoaderVersion { - id: format!("{}-{}", inherits_from, loader), - url: format_url(&*version_path), - }, - ); + loader_version_map.push(LoaderVersion { + id: format!("{}-{}", inherits_from, loader), + url: format_url(&*version_path), + stable: *stable, + }); } .await; } @@ -207,13 +208,46 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error } if let Ok(versions) = Arc::try_unwrap(versions) { + let mut versions = versions.into_inner(); + + versions.sort_by(|x, y| { + minecraft_versions + .versions + .iter() + .position(|z| x.id == z.id) + .unwrap_or_default() + .cmp( + &minecraft_versions + .versions + .iter() + .position(|z| y.id == z.id) + .unwrap_or_default(), + ) + }); + + for version in &mut versions { + version.loaders.sort_by(|x, y| { + list.loader + .iter() + .position(|z| x.id == z.version) + .unwrap_or_default() + .cmp( + &list + .loader + .iter() + .position(|z| y.id == z.version) + .unwrap_or_default(), + ) + }) + } + upload_file_to_bucket( format!( "fabric/v{}/manifest.json", daedalus::modded::CURRENT_FABRIC_FORMAT_VERSION, ), serde_json::to_vec(&Manifest { - game_versions: versions.into_inner(), + game_versions: versions, })?, Some("application/json".to_string()), uploaded_files_mutex.as_ref(), diff --git a/daedalus_client/src/forge.rs b/daedalus_client/src/forge.rs index baa816733..f8f8e188d 100644 --- a/daedalus_client/src/forge.rs +++ b/daedalus_client/src/forge.rs @@ -1,10 +1,8 @@ use crate::{format_url, upload_file_to_bucket, Error}; use chrono::{DateTime, Utc}; use daedalus::download_file; -use daedalus::minecraft::{Argument, ArgumentType, Library, VersionType}; -use daedalus::modded::{ - LoaderType, LoaderVersion, Manifest, PartialVersionInfo, Processor, SidedDataEntry, -}; +use daedalus::minecraft::{Argument, ArgumentType, Library, VersionManifest, VersionType}; +use daedalus::modded::{LoaderVersion, Manifest, PartialVersionInfo, Processor, SidedDataEntry}; use lazy_static::lazy_static; use log::info; use semver::{Version, VersionReq}; @@ -25,7 +23,10 @@ lazy_static! { static ref FORGE_MANIFEST_V3_QUERY: VersionReq = VersionReq::parse(">=37.0.0").unwrap(); } -pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error> { +pub async fn retrieve_data( + minecraft_versions: &VersionManifest, + uploaded_files: &mut Vec, +) -> Result<(), Error> { let maven_metadata = fetch_maven_metadata(None).await?; let old_manifest = daedalus::modded::fetch_manifest(&*format_url(&*format!( "forge/v{}/manifest.json", @@ -34,18 +35,20 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error .await .ok(); - let versions = Arc::new(Mutex::new(if let Some(old_manifest) = old_manifest { + let old_versions = Arc::new(Mutex::new(if let Some(old_manifest) = old_manifest { old_manifest.game_versions } else { Vec::new() })); + let versions = Arc::new(Mutex::new(Vec::new())); + let visited_assets_mutex = Arc::new(Mutex::new(Vec::new())); let uploaded_files_mutex = Arc::new(Mutex::new(Vec::new())); let mut version_futures = Vec::new(); - for (minecraft_version, loader_versions) in maven_metadata { + for (minecraft_version, loader_versions) in maven_metadata.clone() { let mut loaders = Vec::new(); for loader_version_full in loader_versions { @@ -77,22 +80,21 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error } } } - - if let Some((loader_version_full, version)) = loaders.into_iter().last() { - version_futures.push(async { - let versions_mutex = Arc::clone(&versions); + version_futures.push(async { + let loaders_versions = futures::future::try_join_all(loaders.into_iter().map(|(loader_version_full, version)| async { + let versions_mutex = Arc::clone(&old_versions); let visited_assets = Arc::clone(&visited_assets_mutex); let uploaded_files_mutex = Arc::clone(&uploaded_files_mutex); + let minecraft_version = minecraft_version.clone(); + async move { { - if versions_mutex.lock().await.iter().any(|x| { - x.id == minecraft_version - && x.loaders - .get(&LoaderType::Latest) - .map(|x| x.id == loader_version_full) - .unwrap_or(false) - }) { - return Ok(()); + let versions = versions_mutex.lock().await; + let version = versions.iter().find(|x| + x.id == minecraft_version).map(|x| x.loaders.iter().find(|x| x.id == loader_version_full)).flatten(); + + if let Some(version) = version { + return Ok::, Error>(Some(version.clone())); } } @@ -199,15 +201,11 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error uploaded_files_mutex.as_ref() ).await?; - let mut map = HashMap::new(); - map.insert(LoaderType::Latest, LoaderVersion { + return Ok(Some(LoaderVersion { id: loader_version_full, - url: format_url(&*version_path) - }); - versions_mutex.lock().await.push(daedalus::modded::Version { - id: minecraft_version, - loaders: map - }) + url: format_url(&*version_path), + stable: false + })); } else if FORGE_MANIFEST_V2_QUERY_P1.matches(&version) || FORGE_MANIFEST_V2_QUERY_P2.matches(&version) || FORGE_MANIFEST_V3_QUERY.matches(&version) { let mut archive_clone = archive.clone(); let mut profile = tokio::task::spawn_blocking(move || { @@ -342,7 +340,7 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error let artifact_bytes = if let Some(ref mut downloads) = lib.downloads { if let Some(ref mut artifact) = downloads.artifact { - let res = if artifact.url.is_empty() { + let res = if artifact.url.is_empty() { local_libs.get(&lib.name).cloned() } else { Some(daedalus::download_file( @@ -418,24 +416,25 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error uploaded_files_mutex.as_ref() ).await?; - let mut map = HashMap::new(); - map.insert(LoaderType::Latest, LoaderVersion { + return Ok(Some(LoaderVersion { id: loader_version_full, - url: format_url(&*version_path) - }); - versions_mutex.lock().await.push(daedalus::modded::Version { - id: minecraft_version, - loaders: map - }) + url: format_url(&*version_path), + stable: false + })); } } - Ok::<(), Error>(()) - }.await?; + Ok(None) + }.await + })).await?.into_iter().flatten().collect(); - Ok::<(), Error>(()) + versions.lock().await.push(daedalus::modded::Version { + id: minecraft_version, + loaders: loaders_versions }); - } + + Ok::<(), Error>(()) + }); } { @@ -458,13 +457,48 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error } if let Ok(versions) = Arc::try_unwrap(versions) { + let mut versions = versions.into_inner(); + + versions.sort_by(|x, y| { + minecraft_versions + .versions + .iter() + .position(|z| x.id == z.id) + .unwrap_or_default() + .cmp( + &minecraft_versions + .versions + .iter() + .position(|z| y.id == z.id) + .unwrap_or_default(), + ) + }); + + for version in &mut versions { + let loader_versions = maven_metadata.get(&version.id); + if let Some(loader_versions) = loader_versions { + version.loaders.sort_by(|x, y| { + loader_versions + .iter() + .position(|z| &y.id == z) + .unwrap_or_default() + .cmp( + &loader_versions + .iter() + .position(|z| &x.id == z) + .unwrap_or_default(), + ) + }) + } + } + upload_file_to_bucket( format!( "forge/v{}/manifest.json", daedalus::modded::CURRENT_FORGE_FORMAT_VERSION, ), serde_json::to_vec(&Manifest { - game_versions: versions.into_inner(), + game_versions: versions, })?, Some("application/json".to_string()), uploaded_files_mutex.as_ref(), diff --git a/daedalus_client/src/main.rs b/daedalus_client/src/main.rs index 123e2b4f2..5729cd157 100644 --- a/daedalus_client/src/main.rs +++ b/daedalus_client/src/main.rs @@ -30,6 +30,8 @@ pub enum Error { ZipError(#[from] zip::result::ZipError), #[error("Error while reading zip file: {0}")] IoError(#[from] std::io::Error), + #[error("Error while obtaining strong reference to Arc")] + ArcError, } #[tokio::main] @@ -49,19 +51,26 @@ async fn main() { tokio::spawn(async { let mut uploaded_files = Vec::new(); - match fabric::retrieve_data(&mut uploaded_files).await { - Ok(..) => {} - Err(err) => error!("{:?}", err), - }; - match minecraft::retrieve_data(&mut uploaded_files).await { - Ok(..) => {} - Err(err) => error!("{:?}", err), - }; - match forge::retrieve_data(&mut uploaded_files).await { - Ok(..) => {} - Err(err) => error!("{:?}", err), + let versions = match minecraft::retrieve_data(&mut uploaded_files).await { + Ok(res) => Some(res), + Err(err) => { + error!("{:?}", err); + + None + } }; + if let Some(manifest) = versions { + match fabric::retrieve_data(&manifest, &mut uploaded_files).await { + Ok(..) => {} + Err(err) => error!("{:?}", err), + }; + match forge::retrieve_data(&manifest, &mut uploaded_files).await { + Ok(..) => {} + Err(err) => error!("{:?}", err), + }; + } + match purge_digitalocean_cache(uploaded_files).await { Ok(..) => {} Err(err) => error!("{:?}", err), diff --git a/daedalus_client/src/minecraft.rs b/daedalus_client/src/minecraft.rs index babb6a189..d3f7c72fc 100644 --- a/daedalus_client/src/minecraft.rs +++ b/daedalus_client/src/minecraft.rs @@ -1,11 +1,12 @@ use crate::{format_url, upload_file_to_bucket, Error}; use daedalus::download_file; +use daedalus::minecraft::VersionManifest; use log::info; use std::sync::Arc; use std::time::{Duration, Instant}; use tokio::sync::Mutex; -pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error> { +pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result { let old_manifest = daedalus::minecraft::fetch_version_manifest(Some(&*crate::format_url(&*format!( "minecraft/v{}/manifest.json", @@ -167,5 +168,7 @@ pub async fn retrieve_data(uploaded_files: &mut Vec) -> Result<(), Error let elapsed = now.elapsed(); info!("Elapsed: {:.2?}", elapsed); - Ok(()) + Ok(Arc::try_unwrap(cloned_manifest) + .map_err(|_| Error::ArcError)? + .into_inner()) }