diff --git a/daedalus/src/modded.rs b/daedalus/src/modded.rs index 83c579a..d678c1e 100644 --- a/daedalus/src/modded.rs +++ b/daedalus/src/modded.rs @@ -4,7 +4,7 @@ use crate::minecraft::{ Argument, ArgumentType, Library, VersionInfo, VersionType, }; use chrono::{DateTime, Utc}; -use serde::{Deserialize, Serialize}; +use serde::{Deserialize, Deserializer, Serialize}; use std::collections::HashMap; #[cfg(feature = "bincode")] @@ -32,6 +32,21 @@ pub struct SidedDataEntry { pub server: String, } +fn deserialize_date<'de, D>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, +{ + let s = String::deserialize(deserializer)?; + + DateTime::parse_from_rfc3339(&s) + .map(|dt| dt.with_timezone(&Utc)) + .or_else(|_| { + DateTime::parse_from_str(&s, "%Y-%m-%dT%H:%M:%S%.f") + .map(|dt| dt.with_timezone(&Utc)) + }) + .map_err(serde::de::Error::custom) +} + #[cfg_attr(feature = "bincode", derive(Encode, Decode))] #[derive(Serialize, Deserialize, Debug)] #[serde(rename_all = "camelCase")] @@ -43,9 +58,11 @@ pub struct PartialVersionInfo { pub inherits_from: String, /// The time that the version was released #[cfg_attr(feature = "bincode", bincode(with_serde))] + #[serde(deserialize_with = "deserialize_date")] pub release_time: DateTime, /// The latest time a file in this version was updated #[cfg_attr(feature = "bincode", bincode(with_serde))] + #[serde(deserialize_with = "deserialize_date")] pub time: DateTime, #[serde(skip_serializing_if = "Option::is_none")] /// The classpath to the main class to launch the game diff --git a/daedalus_client/src/fabric.rs b/daedalus_client/src/fabric.rs index c7e55fa..1a997da 100644 --- a/daedalus_client/src/fabric.rs +++ b/daedalus_client/src/fabric.rs @@ -12,7 +12,7 @@ pub async fn retrieve_data( uploaded_files: &mut Vec, semaphore: Arc, ) -> Result<(), Error> { - let mut list = fetch_fabric_versions(None, semaphore.clone()).await?; + let list = fetch_fabric_versions(None, semaphore.clone()).await?; let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!( "fabric/v{}/manifest.json", daedalus::modded::CURRENT_FABRIC_FORMAT_VERSION, @@ -51,9 +51,6 @@ pub async fn retrieve_data( )) } } - - list.loader - .retain(|x| loaders.iter().any(|val| val.1 == x.version)) } const DUMMY_GAME_VERSION: &str = "1.19.4-rc2"; diff --git a/daedalus_client/src/minecraft.rs b/daedalus_client/src/minecraft.rs index 99ed51b..1f0e5b7 100644 --- a/daedalus_client/src/minecraft.rs +++ b/daedalus_client/src/minecraft.rs @@ -141,18 +141,39 @@ pub async fn retrieve_data( let mut cloned_manifest = cloned_manifest_mutex.lock().await; - let position = cloned_manifest + if let Some(position) = cloned_manifest .versions .iter() .position(|x| version.id == x.id) - .unwrap(); - cloned_manifest.versions[position].url = - format_url(&version_path); - cloned_manifest.versions[position].assets_index_sha1 = - Some(version_info.asset_index.sha1.clone()); - cloned_manifest.versions[position].assets_index_url = - Some(format_url(&assets_path)); - cloned_manifest.versions[position].sha1 = version_info_hash; + { + cloned_manifest.versions[position].url = + format_url(&version_path); + cloned_manifest.versions[position].assets_index_sha1 = + Some(version_info.asset_index.sha1.clone()); + cloned_manifest.versions[position].assets_index_url = + Some(format_url(&assets_path)); + cloned_manifest.versions[position].sha1 = + version_info_hash; + } else { + cloned_manifest.versions.insert( + 0, + daedalus::minecraft::Version { + id: version_info.id.clone(), + type_: version_info.type_.clone(), + url: format_url(&version_path), + time: version_info.time, + release_time: version_info.release_time, + sha1: version_info_hash, + compliance_level: 1, + assets_index_url: Some( + version_info.asset_index.sha1.clone(), + ), + assets_index_sha1: Some( + version_info.asset_index.sha1.clone(), + ), + }, + ) + } } let mut download_assets = false; diff --git a/daedalus_client/src/neo.rs b/daedalus_client/src/neo.rs index fd4c6bb..ddc0756 100644 --- a/daedalus_client/src/neo.rs +++ b/daedalus_client/src/neo.rs @@ -17,7 +17,7 @@ pub async fn retrieve_data( uploaded_files: &mut Vec, semaphore: Arc, ) -> Result<(), Error> { - let maven_metadata = fetch_maven_metadata(None, semaphore.clone()).await?; + let maven_metadata = fetch_maven_metadata(semaphore.clone()).await?; let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!( "neo/v{}/manifest.json", daedalus::modded::CURRENT_NEOFORGE_FORMAT_VERSION, @@ -42,10 +42,10 @@ pub async fn retrieve_data( for (minecraft_version, loader_versions) in maven_metadata.clone() { let mut loaders = Vec::new(); - for (full, loader_version) in loader_versions { + for (full, loader_version, new_forge) in loader_versions { let version = Version::parse(&loader_version)?; - loaders.push((full, version)) + loaders.push((full, version, new_forge.to_string())) } if !loaders.is_empty() { @@ -53,7 +53,7 @@ pub async fn retrieve_data( let mut loaders_versions = Vec::new(); { - let loaders_futures = loaders.into_iter().map(|(loader_version_full, _)| async { + let loaders_futures = loaders.into_iter().map(|(loader_version_full, _, new_forge)| 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); @@ -72,13 +72,13 @@ pub async fn retrieve_data( } info!("Forge - Installer Start {}", loader_version_full.clone()); - let bytes = download_file(&format!("https://maven.neoforged.net/net/neoforged/forge/{0}/forge-{0}-installer.jar", loader_version_full), None, semaphore.clone()).await?; + let bytes = download_file(&format!("https://maven.neoforged.net/net/neoforged/{1}/{0}/{1}-{0}-installer.jar", loader_version_full, if &*new_forge == "true" { "neoforge" } else { "forge" }), None, semaphore.clone()).await?; let reader = std::io::Cursor::new(bytes); if let Ok(archive) = zip::ZipArchive::new(reader) { let mut archive_clone = archive.clone(); - let mut profile = tokio::task::spawn_blocking(move || { + let mut profile = tokio::task::spawn_blocking(move || { let mut install_profile = archive_clone.by_name("install_profile.json")?; let mut contents = String::new(); @@ -404,8 +404,10 @@ pub async fn retrieve_data( Ok(()) } -const DEFAULT_MAVEN_METADATA_URL: &str = +const DEFAULT_MAVEN_METADATA_URL_1: &str = "https://maven.neoforged.net/net/neoforged/forge/maven-metadata.xml"; +const DEFAULT_MAVEN_METADATA_URL_2: &str = + "https://maven.neoforged.net/net/neoforged/neoforge/maven-metadata.xml"; #[derive(Debug, Deserialize)] struct Metadata { @@ -423,32 +425,55 @@ struct Versions { } pub async fn fetch_maven_metadata( - url: Option<&str>, semaphore: Arc, -) -> Result>, Error> { - let values = serde_xml_rs::from_str::( - &String::from_utf8( - download_file( - url.unwrap_or(DEFAULT_MAVEN_METADATA_URL), - None, - semaphore, +) -> Result>, Error> { + async fn fetch_values( + url: &str, + semaphore: Arc, + ) -> Result { + Ok(serde_xml_rs::from_str( + &String::from_utf8( + download_file(url, None, semaphore).await?.to_vec(), ) - .await? - .to_vec(), - ) - .unwrap_or_default(), - )?; + .unwrap_or_default(), + )?) + } + + let forge_values = + fetch_values(DEFAULT_MAVEN_METADATA_URL_1, semaphore.clone()).await?; + let neo_values = + fetch_values(DEFAULT_MAVEN_METADATA_URL_2, semaphore).await?; - let mut map: HashMap> = HashMap::new(); + let mut map: HashMap> = HashMap::new(); - for value in values.versioning.versions.version { + for value in forge_values.versioning.versions.version { let original = value.clone(); let parts: Vec<&str> = value.split('-').collect(); if parts.len() == 2 { - map.entry(parts[0].to_string()) - .or_default() - .push((original, parts[1].to_string())); + map.entry(parts[0].to_string()).or_default().push(( + original, + parts[1].to_string(), + false, + )); + } + } + + for value in neo_values.versioning.versions.version { + let original = value.clone(); + + let mut parts = value.split('.'); + + if let Some(major) = parts.next() { + if let Some(minor) = parts.next() { + let game_version = format!("1.{}.{}", major, minor); + + map.entry(game_version.clone()).or_default().push(( + original.clone(), + format!("{}-{}", game_version, original), + true, + )); + } } } diff --git a/daedalus_client/src/quilt.rs b/daedalus_client/src/quilt.rs index caa4a67..cd0df2d 100644 --- a/daedalus_client/src/quilt.rs +++ b/daedalus_client/src/quilt.rs @@ -12,7 +12,7 @@ pub async fn retrieve_data( uploaded_files: &mut Vec, semaphore: Arc, ) -> Result<(), Error> { - let mut list = fetch_quilt_versions(None, semaphore.clone()).await?; + let list = fetch_quilt_versions(None, semaphore.clone()).await?; let old_manifest = daedalus::modded::fetch_manifest(&format_url(&format!( "quilt/v{}/manifest.json", daedalus::modded::CURRENT_QUILT_FORMAT_VERSION, @@ -51,9 +51,6 @@ pub async fn retrieve_data( )) } } - - list.loader - .retain(|x| loaders.iter().any(|val| val.1 == x.version)) } const DUMMY_GAME_VERSION: &str = "1.19.4-rc2";