diff --git a/daedalus_client/lwjgl-config.json b/daedalus_client/lwjgl-config.json deleted file mode 100644 index 54612f4..0000000 --- a/daedalus_client/lwjgl-config.json +++ /dev/null @@ -1,131 +0,0 @@ -{ - "accept": [ - { - "match": "4abf9e55d73bb6502e84cb9eff5d9ab2e2895a33", - "_comment": "#3.3.3 (2024-06-13 08:24:03 UTC) natives: [] Split: true", - "equals": "73974b3af2afeb5b272ffbadcd7963014387c84f / # 3.3.3 (2024-05-22 16:25:41+00:00)" - }, - { - "match": "edf84455ebc424de91d9c740033301801cd3ff93", - "_comment": "#3.3.2 (2024-04-01 11:07:19 UTC) natives: [] Split: true", - "equals": "765b4ab443051d286bdbb1c19cd7dc86b0792dce / # 3.3.2 (2024-01-17 13:19:20+00:00)" - }, - { - "match": "454646b137b4de147e253040d0fbaaad1001b69b", - "_comment": "#3.3.1 (2022-12-05 13:21:34 UTC) natives: [] Split: true", - "equals": "??" - }, - { - "match": "5b89cf6b701884ebd2e4880d98a86bbf647cc8f2", - "_comment": "#3.2.2 (2019-07-11 10:52:33 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "ea4973ebc9eadf059f30f0958c89f330898bff51 / # 3.2.2 (2019-07-04 14:41:05+00:00) will be patched, missing tinyfd" - }, - { - "match": "84ced01dbaa11d56ec304cd615ea346538f8107b", - "_comment": "#3.2.1 (2019-06-03 14:34:20 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "235fc413bc4c76b269c207f7bca6464f1e1f1d80 / # 3.2.1 (2019-02-13 16:12:08+00:00)" - }, - { - "match": "b41a756fdccd3a804c9e5485ababde79ca956beb", - "_comment": "#3.1.6 (2018-07-16 14:17:42 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "deb1a436d806413207350735a00e04b54d113916 / # 3.1.6 (2018-10-18 14:46:12+00:00)" - }, - { - "match": "1c0813dd0f1e3a65ada7e58aeb0122499d7e8258", - "_comment": "#3.1.2 (2018-06-21 12:57:11 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "3e47f0f742fb759401754769fa59c508fd8fda75 / # 3.1.2 (2018-06-21 12:57:11+00:00)" - }, - { - "match": "68d9ced1347c06a731a0ada3ca7d5624364f6074", - "_comment": "#2.9.4-nightly-20150209 (2015-06-05 10:10:44 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "a3f254df5a63a0a1635755733022029e8cfae1b3 / # 2.9.4-nightly-20150209 (2016-12-20 14:05:34+00:00)" - }, - { - "match": "ffeec04297e8ab99b43d3bc8dc145e9d402adc52", - "_comment": "#2.9.3 (2015-01-30 11:58:24 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "879be09c0bd0d4bafc2ea4ea3d2ab8607a0d976c / # 2.9.3 (2015-01-30 11:58:24+00:00)" - }, - { - "match": "b6d0206457b37b8663f3d2f24dfa9ace2099a247", - "_comment": "#2.9.1 (2015-01-16 14:19:59 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "8d4951d00253dfaa36a0faf1c8be541431861c30 / # 2.9.1 (2014-05-22 14:44:33+00:00)" - }, - { - "match": "78b7c6bde1a9e1cdc916679cd723c2ad3c5d5a50", - "_comment": "#2.9.1-nightly-20131120 (2013-12-09 12:28:10 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "cf58c9f92fed06cb041a7244c6b4b667e6d544cc / # 2.9.1-nightly-20131120 (2013-12-06 13:55:34+00:00)" - }, - { - "match": "006718e3459b13572cc23d91dc7b25718fde46ba", - "_comment": "#2.9.0 (2013-10-11 15:09:17 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "27dcadcba29a1a7127880ca1a77efa9ece866f24 / # 2.9.0 (2013-09-06 12:31:58+00:00)" - } - ], - "reject": [ - { - "match": "465d40d8db05f5e04055ddf0582ab143d10e0e9f", - "_comment": "#3.3.3 (2024-05-29 12:04:43 UTC) natives: [] Split: true", - "equals": "6f32ef730d05562ede7db0b845b72ea16dd239d5 / # 3.3.3 (2024-05-29 12:04:43+00:00) missing os rule for freetype natives-macos-patch" - }, - { - "match": "ca23e095136a624d43d992f8c1fbf64b58fa8ddd", - "_comment": "#3.3.3 (2024-04-18 11:45:40 UTC) natives: [] Split: true", - "equals": "8a9b08f11271eb4de3b50e5d069949500b2c7bc1 / # 3.3.3 (2024-04-03 11:49:39+00:00) seems to have a broken libfreetype for macOS x86_64" - }, - { - "match": "16f25339f4dd208a77f968c7399e41cda4abea4a", - "_comment": "#3.3.2 (2023-12-18 15:39:14 UTC) natives: [] Split: true", - "equals": "79bde9e46e9ad9accebda11e8293ed08d80dbdc3 / # 3.3.2 (2023-08-30 11:24:35+00:00) does not have lwjgl-freetype" - }, - { - "match": "4320441f17a1c53bbab32e31b530651d972d998a", - "_comment": "#3.3.1 (2023-08-17 11:39:08 UTC) natives: [] Split: true", - "equals": "??" - }, - { - "match": "7719b93913cd34c1055d34824f4aa44159ad60a7", - "_comment": "#3.3.1 (2022-05-12 15:36:11 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: true", - "equals": "??" - }, - { - "match": "8572ad80f0a5755aa645cecf66b8be3012fd32f0", - "_comment": "#3.3.1 (2022-04-27 15:54:15 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "??" - }, - { - "match": "236a22a6deafe4747e1066fadd4bc83faf6d557a", - "_comment": "#3.2.2 (2022-04-13 15:41:17 UTC) natives: [[Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux]] Split: false", - "equals": "??" - }, - { - "match": "c09f4588dd082778cae54ea93f4168498d26299a", - "_comment": "#3.2.2 (2019-11-08 12:42:44 UTC) natives: [[Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux]] Split: false", - "equals": "??" - }, - { - "match": "d454d79d4cba8009196d8ccef4f51aca56047f13", - "_comment": "#3.2.2 (2021-10-13 15:23:23 UTC) natives: [[Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux], [Windows, Linux]] Split: false", - "equals": "??" - }, - { - "match": "cc6675018d4c9f2bef861ea94e539b7418d108ad", - "_comment": "#3.2.1 (2019-04-18 11:05:19 UTC) natives: [[Osx, Windows], [Osx, Windows], [Osx, Windows], [Osx, Windows], [Osx, Windows], [Osx, Windows]] Split: false", - "equals": "854649a5bd1455b89117593ae82ff90c8132cacf / # 3.2.1 (2019-04-18 11:05:19+00:00) only osx, windows" - }, - { - "match": "4b9626be3dfe53f8008235c9d995b572bee5a8fd", - "_comment": "#3.1.6 (2019-04-17 15:31:12 UTC) natives: [[Linux], [Linux], [Linux], [Linux], [Linux], [Linux]] Split: false", - "equals": "89fcb489261b05f622e8052fe0b588b0cfe49c24 / # 3.1.6 (2019-04-18 11:05:19+00:00) only linux" - }, - { - "match": "1c0cd87ba39e60b16fbe379b19a709beb35ce08e", - "_comment": "#2.9.0 (2013-10-25 13:00:00 UTC) natives: [[Osx, Windows, Linux], [Windows, Linux]] Split: false", - "equals": "f04052162b50fa1433f67e1a90bc79466c4ab776 / # 2.9.0 (2013-10-21 16:34:47+00:00) only linux, windows" - }, - { - "match": "7c776ed8420502f4839717fd1cfecab062f1f9b2", - "_comment": "#2.9.0 (2013-04-25 15:45:00 UTC) natives: [[Osx, Windows, Linux], [Osx, Windows, Linux], [Osx, Windows, Linux]] Split: false", - "equals": "6442fc475f501fbd0fc4244fd1c38c02d9ebaf7e / # 2.9.0 (2011-03-30 22:00:00+00:00) fine but newer variant available" - } - ] -} diff --git a/daedalus_client/src/minecraft/lwjgl.rs b/daedalus_client/src/minecraft/lwjgl.rs deleted file mode 100644 index 206a31f..0000000 --- a/daedalus_client/src/minecraft/lwjgl.rs +++ /dev/null @@ -1,210 +0,0 @@ -//! LWJGL variant processing and validation system -//! -//! This module handles: -//! - Processing LWJGL variant libraries -//! - Validating native classifiers for different operating systems -//! - Managing LWJGL version variants across Minecraft versions -//! - Filtering and identifying compatible LWJGL configurations - -use crate::minecraft::library_patches::patch_library; -use crate::minecraft::types::{LibraryPatch, LWJGLVariantConfig}; -use daedalus::minecraft::{Dependency, LWJGLEntry, LibraryGroup, Os}; -use std::collections::{BTreeMap, HashSet}; -use std::sync::Arc; -use tokio::sync::Mutex; -use tracing::{debug, info, warn}; - -/// Process a single LWJGL variant and validate its structure -/// -/// This function: -/// 1. Applies library patches to the variant -/// 2. Sets up LWJGL 2 vs LWJGL 3 configuration with conflicts -/// 3. Filters out unneeded libraries (jutils, jinput for LWJGL 3) -/// 4. Validates native classifiers for all platforms (Linux, Windows, macOS) -/// -/// # Arguments -/// - `variant`: The LWJGL library group to process -/// - `patches`: Library patches to apply -/// -/// # Returns -/// - `Ok(Some((path, library_group)))` if the variant is valid and should be uploaded -/// - `Ok(None)` if the variant is invalid (missing classifiers or downloads) -/// - `Err` if an unknown LWJGL version is encountered -pub fn process_single_lwjgl_variant( - variant: &LibraryGroup, - patches: &Vec, -) -> Result, crate::infrastructure::error::Error> { - let lwjgl_version = variant.version.clone(); - - info!("Processing LWJGL variant {}", lwjgl_version); - - let mut lwjgl = variant.clone(); - - let mut new_libraries = Vec::new(); - - for library in lwjgl.libraries.clone() { - let mut libs = patch_library(patches, library); - new_libraries.append(&mut libs); - } - lwjgl.libraries = new_libraries; - - let version_path = if lwjgl_version.starts_with("2") { - lwjgl.id = "LWJGL 2".to_string(); - lwjgl.uid = "org.lwjgl2".to_string(); - lwjgl.conflicts = Some(vec![Dependency { - name: "lwjgl".to_string(), - uid: "org.lwjgl3".to_string(), - rule: None, - }]); - - format!( - "minecraft/v{}/libraries/org.lwjgl2/{}.json", - daedalus::minecraft::CURRENT_FORMAT_VERSION, - lwjgl_version - ) - } else if lwjgl_version.starts_with('3') { - lwjgl.id = "LWJGL 3".to_string(); - lwjgl.uid = "org.lwjgl3".to_string(); - lwjgl.conflicts = Some(vec![Dependency { - name: "lwjgl".to_string(), - uid: "org.lwjgl2".to_string(), - rule: None, - }]); - - let unneeded: HashSet<&str> = vec!["jutils", "jinput"].into_iter().collect(); - let filtered_libs = lwjgl - .libraries - .into_iter() - .filter(|lib| !unneeded.contains(lib.name.artifact.as_str())) - .collect::>(); - lwjgl.libraries = filtered_libs; - - format!( - "minecraft/v{}/libraries/org.lwjgl3/{}.json", - daedalus::minecraft::CURRENT_FORMAT_VERSION, - lwjgl_version - ) - } else { - return Err(crate::infrastructure::error::invalid_input(format!( - "Unknown LWJGL version {}", - lwjgl_version - ))); - }; - - let mut good = true; - for lib in &lwjgl.libraries { - if lib.patched { - continue; - } - if let Some(natives) = &lib.natives { - let checked: HashSet<&Os> = vec![&Os::Linux, &Os::Windows, &Os::Osx] - .into_iter() - .collect(); - if !checked.is_subset(&natives.clone().keys().collect()) { - warn!( - "LWJGL variant library missing system classifier: {} {} {:?}", - lwjgl.version, - lib.name, - natives.keys() - ); - good = false; - break; - } - if lib.downloads.is_some() { - if let Some(classifiers) = &lib - .downloads - .clone() - .expect("Unwrap to be safe inside is_some") - .classifiers - { - for entry in checked { - let baked_entry = natives.get(entry); - if let Some(baked_entry) = baked_entry { - if !classifiers.contains_key(baked_entry) { - warn!( - "LWJGL variant library missing download for classifier: {} {} {:?} {:?}", - lwjgl.version, - lib.name, - baked_entry, - classifiers.keys().collect::>() - ); - good = false; - break; - } - } - } - } else { - warn!( - "LWJGL variant library missing downloads classifiers: {} {}", - lwjgl.version, lib.name - ); - good = false; - break; - } - } - } - } - if good { - Ok(Some((version_path, lwjgl))) - } else { - Ok(None) - } -} - -/// Add an LWJGL version to the variants collection -/// -/// This function tracks different LWJGL variants (with the same version but different -/// library configurations) and updates release times as newer variants are discovered. -/// -/// # Arguments -/// - `variants_mutex`: Shared map of LWJGL version to variant entries -/// - `lwjgl`: The library group to add as a variant -pub async fn add_lwjgl_version( - variants_mutex: Arc>>>, - lwjgl: &LibraryGroup, -) { - let mut lwjgl_copy = lwjgl.clone(); - lwjgl_copy.libraries.sort_by(|x, y| x.name.cmp(&y.name)); - - let entry = LWJGLEntry::from_group(lwjgl_copy); - let current_sha1 = entry.sha1.clone(); - let version = entry.group.version.clone(); - let mut found = false; - - let mut version_variants = variants_mutex.lock().await; - - let variants = version_variants - .entry(version.clone()) - .or_insert_with(Vec::new); - for variant in variants.iter_mut() { - if entry.sha1 == variant.sha1 { - found = true; - if entry.group.release_time > variant.group.release_time { - variant.group.release_time = entry.group.release_time; - } - break; - } - } - - if !found { - info!( - "!! New variant for LWJGL version {:?} : {}", - version, current_sha1 - ); - debug!("New LWLGL variant {:?}", &lwjgl); - variants.push(entry); - } -} - -/// Fetch LWJGL variant configuration from embedded JSON file -/// -/// The configuration contains lists of accepted and rejected LWJGL variant SHA1 hashes, -/// used to filter out known bad variants and only accept validated ones. -/// -/// # Returns -/// The LWJGL variant configuration with accept/reject lists -pub async fn get_lwjgl_config( -) -> Result { - let config = include_bytes!("../../lwjgl-config.json"); - Ok(serde_json::from_slice(config)?) -} diff --git a/daedalus_client/src/minecraft/mod.rs b/daedalus_client/src/minecraft/mod.rs index 7f29e15..d57fd26 100644 --- a/daedalus_client/src/minecraft/mod.rs +++ b/daedalus_client/src/minecraft/mod.rs @@ -2,19 +2,17 @@ //! //! This module handles the complete Minecraft version processing pipeline: //! - Fetching and processing vanilla Minecraft versions -//! - LWJGL library variant detection and validation //! - Log4j security patching (CVE-2021-44228, CVE-2021-44832, CVE-2021-45046) -//! - Library patching and dependency management +//! - Library patching and dependency management (including LWJGL fixes) //! - Split natives handling //! - Assets index processing and CAS upload //! //! # Module Structure //! -//! - `types`: Type definitions for patches and LWJGL configuration +//! - `types`: Type definitions for library patches //! - `log4j`: Security patching for Log4j vulnerabilities //! - `library_patches`: Library patching system with override and injection //! - `helpers`: Utility functions for version and library processing -//! - `lwjgl`: LWJGL variant processing and validation //! //! # Main Entry Point //! @@ -24,39 +22,35 @@ pub mod helpers; pub mod library_patches; pub mod log4j; -pub mod lwjgl; pub mod types; // Re-export commonly used types -pub use types::{LibraryPatch, LWJGLVariantConfig, LWJGLVariantMarker}; +pub use types::LibraryPatch; use crate::download_file; use crate::format_url; use crate::services::upload::BatchUploader; use dashmap::DashSet; -use daedalus::minecraft::{ - Dependency, DependencyRule, JavaVersion, LWJGLEntry, Library, LibraryDownload, - LibraryDownloads, LibraryGroup, MinecraftJavaProfile, Os, Rule, RuleAction, VersionInfo, - VersionManifest, VersionType, -}; -use daedalus::{get_hash, GradleSpecifier}; -use std::collections::{BTreeMap, HashMap, HashSet}; +use daedalus::minecraft::{JavaVersion, MinecraftJavaProfile, VersionManifest}; +use futures::future::join_all; use std::convert::TryFrom; use std::sync::Arc; use std::time::Instant; use tokio::sync::{Mutex, Semaphore}; -use tracing::{debug, error, info, warn}; +use tracing::{info, warn}; /// Retrieve and process all Minecraft version data /// /// This is the main entry point for Minecraft version processing. It: /// 1. Fetches the Minecraft version manifest /// 2. Processes each version in parallel (with chunking) -/// 3. Handles LWJGL variant detection and validation -/// 4. Applies Log4j security patches -/// 5. Applies library patches -/// 6. Processes assets and uploads to CAS -/// 7. Builds the final manifest with all processed versions +/// 3. Applies Log4j security patches +/// 4. Applies library patches (e.g., LWJGL-related fixes via generic patching; no LWJGL variant processing) +/// 5. Processes assets and uploads to CAS +/// 6. Builds the final manifest with all processed versions +/// +/// LWJGL libraries are kept inline in version manifests and fixed via library patches, +/// not extracted as separate components. /// /// # Arguments /// - `uploader`: Batch uploader for CAS uploads @@ -92,32 +86,12 @@ pub async fn retrieve_data( let cloned_manifest = Arc::new(Mutex::new(manifest.clone())); - let patches = library_patches::get_library_patches().await?; - let cloned_patches = Arc::new(&patches); - - let lwjgl_config = lwjgl::get_lwjgl_config().await?; + // Own the patches and share as an Arc slice to avoid borrowed refs in futures + let patches: Arc<[LibraryPatch]> = + Arc::from(library_patches::get_library_patches().await?.into_boxed_slice()); let visited_assets = Arc::new(DashSet::new()); - let lwjgl_version_variants_mutex: Arc>>> = - Arc::new(Mutex::new(BTreeMap::new())); - let lwjgl_reject_reasons: HashMap> = lwjgl_config - .reject - .clone() - .into_iter() - .map(|mark| (mark.match_, mark.reason)) - .collect(); - let reject_lwjgl_variants: HashSet = lwjgl_config - .reject - .into_iter() - .map(|mark| mark.match_) - .collect(); - let accept_lwjgl_variants: HashSet = lwjgl_config - .accept - .into_iter() - .map(|mark| mark.match_) - .collect(); - let now = Instant::now(); let mut version_futures = Vec::new(); @@ -139,23 +113,18 @@ pub async fn retrieve_data( let visited_assets = Arc::clone(&visited_assets); let cloned_manifest_mutex = Arc::clone(&cloned_manifest); let semaphore = Arc::clone(&semaphore); - let patches = Arc::clone(&cloned_patches); - - let lwjgl_version_variants_mutex = Arc::clone(&lwjgl_version_variants_mutex); + let patches = Arc::clone(&patches); let assets_hash = old_version.and_then(|x| x.assets_index_sha1.clone()); async move { let mut version_info = daedalus::minecraft::fetch_version_info(version).await?; - let has_split_natives = helpers::version_has_split_natives(&version_info); - let mut is_lwjgl_3 = false; - let mut lwjgl_buckets: HashMap>, LibraryGroup> = - HashMap::new(); - + // Process libraries: apply patches (including LWJGL fixes) let mut new_libraries = Vec::new(); info!("Processing libraries for version {}", version_info.id); for library in version_info.libraries.iter_mut() { + // Handle split natives (modern Minecraft native library format) if helpers::lib_is_split_natives(library) { if let Some(identifier) = &library.name.identifier { info!( @@ -167,176 +136,40 @@ pub async fn retrieve_data( library.name.identifier = None; } } - let spec = &mut library.name; - - if spec.is_lwjgl() { - let mut rules = None; - let set_version: Option = if has_split_natives { - // implies lwjgl3 - is_lwjgl_3 = true; - debug!( - "lwlgl library {} has split natives, version {}", - spec, spec.version - ); - Some(spec.version.clone()) - } else { - debug!("lwlgl library {} is not split, package: {} artifact:{} version: {}", spec, spec.package, spec.artifact, spec.version); - rules = library.rules.clone(); - library.rules = None; - if helpers::is_macos_only(&rules) { - info!( - "Candidate library {} is only for macOS and is therefore ignored", - spec - ); - continue; - } - if spec.package == "org.lwjgl.lwjgl" && spec.artifact == "lwjgl" { - Some(spec.version.clone()) - } else if spec.package == "org.lwjgl" && spec.artifact == "lwjgl" { - is_lwjgl_3 = true; - Some(spec.version.clone()) - } else { - None - } - }; - debug!("lwjgl library {} is setting version {:?}", spec, set_version); - - let version_id = &version_info.id; - let version_release_time = version_info.release_time; - - info!( - "Setting lwjgl bucket {:?} for {} with release {}", - &rules, version_id, version_release_time - ); - let bucket = lwjgl_buckets.entry(rules.clone()).or_insert_with(|| { - LibraryGroup { - id: "LWJGL".to_string(), - version: "undetermined".to_string(), - uid: "org.lwjgl".to_string(), - release_time: version_release_time, - libraries: Vec::new(), - requires: None, - conflicts: None, - type_: VersionType::Release, - has_split_natives: Some(has_split_natives), - } - }); - bucket.has_split_natives = Some(has_split_natives); + let spec = &library.name; - if let Some(version) = set_version { - debug!( - "Setting bucket version {} for {}", - version, version_info.id - ); - bucket.version = version; - } - bucket.libraries.push(library.clone()); - if version_info.release_time > bucket.release_time { - bucket.release_time = version_info.release_time; - } - } else if spec.is_log4j() { + // Handle log4j security patches (CVE-2021-44228, CVE-2021-44832, CVE-2021-45046) + if spec.is_log4j() { if let Some((version_override, maven_override)) = log4j::map_log4j_artifact(&spec.version)? { - let replacement_library = log4j::create_log4j_replacement_library( + let mut replacement_library = log4j::create_log4j_replacement_library( &spec.artifact, &version_override, &maven_override, library.include_in_classpath, )?; - new_libraries.push(replacement_library); + // Mark for traceability and run through patcher for consistency + replacement_library.patched = true; + let mut libs = library_patches::patch_library( + Arc::as_ref(&patches), + replacement_library, + ); + new_libraries.append(&mut libs); } else { new_libraries.push(library.clone()) } } else { - let mut libs = library_patches::patch_library(&patches, library.clone()); - new_libraries.append(&mut libs) - } - } - - if lwjgl_buckets.len() == 1 { - for (key, lwjgl) in lwjgl_buckets.iter_mut() { - lwjgl.libraries.sort_by_key(|lib| lib.name.clone()); - lwjgl::add_lwjgl_version(lwjgl_version_variants_mutex.clone(), lwjgl) - .await; - info!("Found only candidate LWJGL {:?} {:?}", lwjgl.version, key); - } - } else { - let common_bucket = lwjgl_buckets.get(&None).cloned(); - for (key, lwjgl) in lwjgl_buckets.iter_mut() { - if key.is_none() { - continue; - } - if let Some(mut common_bucket) = common_bucket.clone() { - lwjgl.libraries.append(&mut common_bucket.libraries); - } - lwjgl.libraries.sort_by_key(|lib| lib.name.clone()); - lwjgl::add_lwjgl_version(lwjgl_version_variants_mutex.clone(), lwjgl) - .await; - info!("Found candidate LWJGL {:?} {:?}", lwjgl.version, key); + // Apply library patches to ALL libraries (including LWJGL!) + // Patches handle: ARM64 natives, missing tinyfd, bad LWJGL variants, etc. + let mut libs = library_patches::patch_library(Arc::as_ref(&patches), library.clone()); + new_libraries.append(&mut libs); } - lwjgl_buckets.remove(&None); } version_info.libraries = new_libraries; - let suggested_lwjgl_version = if lwjgl_buckets.len() == 1 { - if is_lwjgl_3 { - Ok(lwjgl_buckets - .values() - .next() - .expect("Safe to unwrap because there is one item present") - .version - .clone()) - } else { - Ok("2.9.4-nightly-20150209".to_string()) - } - } else { - let bad_versions: HashSet<&str> = - vec!["3.1.6", "3.2.1"].into_iter().collect(); - let our_versions: HashSet<&str> = lwjgl_buckets - .values() - .map(|lwjgl| lwjgl.version.as_str()) - .collect(); - - if our_versions == bad_versions { - info!( - "Found broken 3.1.6/3.2.1 LWJGL combo in version {} , forcing LWJGL. 3.2.1", - &version_info.id - ); - Ok("3.2.1".to_string()) - } else { - Err(crate::infrastructure::error::invalid_input(format!( - "Can not determine a single suggested LWJGL version in version {} from among {:?}", - &version_info.id, our_versions - ))) - } - }?; - - let lwjgl_dependency = if is_lwjgl_3 { - Dependency { - name: "lwjgl".to_string(), - uid: "org.lwjgl3".to_string(), - rule: Some(DependencyRule::Suggests(suggested_lwjgl_version)), - } - } else { - Dependency { - name: "lwjgl".to_string(), - uid: "org.lwjgl2".to_string(), - rule: Some(DependencyRule::Suggests(suggested_lwjgl_version)), - } - }; - - if version_info.requires.is_none() { - version_info.requires = Some(Vec::new()); - } - version_info - .requires - .as_mut() - .expect("Safe to unwrap because we just ensured it's creation") - .push(lwjgl_dependency); - // Patch java version version_info.java_version = { if let Some(java_version) = &version_info.java_version { @@ -510,8 +343,9 @@ pub async fn retrieve_data( let chunk: Vec<_> = versions.by_ref().take(100).collect(); - for future in chunk { - match future.await { + // Process chunk concurrently (semaphore controls actual I/O parallelism) + for result in join_all(chunk).await { + match result { Ok(_) => { successful += 1; } @@ -537,149 +371,6 @@ pub async fn retrieve_data( ); } - { - let lwjgl_version_variants = lwjgl_version_variants_mutex.lock().await; - - info!("Processing LWJGL variants"); - for (lwjgl_version_variant, lwjgl_variant_entries) in lwjgl_version_variants.iter() { - info!( - "{} variant(s) for LWJGL {}", - lwjgl_variant_entries.len(), - lwjgl_version_variant - ); - - let mut decided_variant = None; - let mut accepted_variants = 0; - let mut unknown_variants = 0; - - for variant in lwjgl_variant_entries { - if reject_lwjgl_variants.contains(&variant.sha1) { - let reason = lwjgl_reject_reasons - .get(&variant.sha1) - .expect("Unwrap to be safe because sha was present in config") - .clone() - .unwrap_or("unspecified".to_string()); - info!("LWJGL Variant {} for version {} ignored because it was marked as bad. Reason: {}", variant.sha1, lwjgl_version_variant, &reason); - continue; - } - if accept_lwjgl_variants.contains(&variant.sha1) { - info!( - "LWJGL Variant {} for version {} accepted", - variant.sha1, lwjgl_version_variant - ); - decided_variant = Some(variant); - accepted_variants += 1; - continue; - } - - let natives = variant - .group - .libraries - .iter() - .filter_map(|lib| { - lib.natives - .as_ref() - .map(|natives| natives.keys().cloned().collect::>()) - }) - .collect::>(); - - #[cfg(feature = "sentry")] - sentry::capture_message( - &format!( - "Unmarked LWJGL variant {}, #{} ({}) natives: {:?} Split: {}", - variant.sha1, - lwjgl_version_variant, - variant.group.release_time, - natives, - variant - .group - .has_split_natives - .map_or("unknown".to_string(), |b| b.to_string()), - ), - sentry::Level::Warning, - ); - - warn!( - "Unmarked LWJGL variant {}, #{} ({}) natives: {:?} Split: {}", - variant.sha1, - lwjgl_version_variant, - variant.group.release_time, - natives, - variant - .group - .has_split_natives - .map_or("unknown".to_string(), |b| b.to_string()), - ); - unknown_variants += 1; - } - - let patches = Arc::clone(&cloned_patches); - let semaphore = semaphore.clone(); - - async move { - if decided_variant.is_some() && accepted_variants == 1 && unknown_variants == 0 { - if let Some((lwjgl_path, lwjgl)) = lwjgl::process_single_lwjgl_variant( - &decided_variant - .expect("Unwrap to be safe inside is_some") - .group, - &patches, - )? { - debug!("Uploading {}", lwjgl_path); - - let lwjgl_bytes = serde_json::to_vec(&lwjgl)?; - let lwjgl_hash = uploader - .upload_cas( - lwjgl_bytes.clone(), - Some("application/json".to_string()), - s3_client, - semaphore.clone(), - ) - .await?; - - let loader = if lwjgl.version.starts_with("2") { - "minecraft-lwjgl2" - } else if lwjgl.version.starts_with("3") { - "minecraft-lwjgl3" - } else { - return Err(crate::infrastructure::error::invalid_input(format!( - "Unknown LWJGL version {}", - lwjgl.version - ))); - }; - - manifest_builder.add_version( - loader, - lwjgl.version.clone(), - lwjgl_hash, - lwjgl_bytes.len() as u64, - ); - } else { - info!( - "Skipped LWJGL {}", - &decided_variant - .expect("Unwrap to be safe inside is_some") - .group - .version - ); - } - } else { - #[cfg(feature = "sentry")] - sentry::capture_message( - &format!( - "No variant decided for version {} of out {} possible and {} unknown", - lwjgl_version_variant, accepted_variants, unknown_variants - ), - sentry::Level::Warning, - ); - error!("No variant decided for version {} of out {} possible and {} unknown", lwjgl_version_variant, accepted_variants, unknown_variants); - } - - Ok::<(), crate::infrastructure::error::Error>(()) - } - .await? - } - } - let elapsed = now.elapsed(); info!("Elapsed: {:.2?}", elapsed); diff --git a/daedalus_client/src/minecraft/types.rs b/daedalus_client/src/minecraft/types.rs index e1e0798..22addbc 100644 --- a/daedalus_client/src/minecraft/types.rs +++ b/daedalus_client/src/minecraft/types.rs @@ -16,22 +16,3 @@ pub struct LibraryPatch { pub override_: Option, pub patch_additional_libraries: Option, } - -/// Marker for LWJGL variant acceptance/rejection configuration -#[derive(Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct LWJGLVariantMarker { - #[serde(rename = "match")] - pub match_: String, - #[serde(rename = "_comment")] - pub _comment: String, - pub reason: Option, -} - -/// Configuration for LWJGL variant filtering -#[derive(Deserialize, Debug, Clone)] -#[serde(rename_all = "camelCase")] -pub struct LWJGLVariantConfig { - pub accept: Vec, - pub reject: Vec, -}