diff options
Diffstat (limited to 'src/launcher.rs')
| -rw-r--r-- | src/launcher.rs | 55 |
1 files changed, 32 insertions, 23 deletions
diff --git a/src/launcher.rs b/src/launcher.rs index 7971c3f..5e3668b 100644 --- a/src/launcher.rs +++ b/src/launcher.rs @@ -23,6 +23,7 @@ use std::env::JoinPathsError; use std::time::{Instant, SystemTime, UNIX_EPOCH}; use const_format::formatcp; use futures::{StreamExt, TryStreamExt}; +use indexmap::IndexMap; use log::{debug, info, trace, warn}; use reqwest::Client; use sysinfo::System; @@ -31,7 +32,7 @@ use tokio_stream::wrappers::ReadDirStream; use download::{MultiDownloader, VerifiedDownload}; use rules::{CompatCheck, IncompatibleError}; use version::{VersionList, VersionResolveError, VersionResult}; -use crate::version::{Logging, Library, OSRestriction, OperatingSystem, DownloadType, DownloadInfo, LibraryExtractRule, CompleteVersion, FeatureMatcher}; +use crate::version::{Logging, Library, OSRestriction, OperatingSystem, DownloadType, DownloadInfo, LibraryExtractRule, CompleteVersion, FeatureMatcher, ClientLogging}; use assets::{AssetError, AssetRepository}; use crate::util::{self, AsJavaPath}; @@ -42,6 +43,7 @@ pub use crate::util::{EnsureFileError, FileVerifyError, IntegrityError}; use crate::assets::AssetIndex; use runner::ArgumentType; use strsub::SubFunc; +use crate::launcher::download::FileDownload; use crate::launcher::jre::{JavaRuntimeError, JavaRuntimeRepository}; use crate::version::manifest::VersionType; @@ -272,14 +274,14 @@ impl Launcher { lib.natives.as_ref().map_or(None, |n| n.get(&self.system_info.os)).map(|s| s.as_str()) } - async fn log_config_ensure(&self, config: &Logging) -> Result<String, LaunchError> { + async fn log_config_ensure(&self, config: &ClientLogging) -> Result<String, LaunchError> { info!("Ensuring log configuration exists and is valid."); - - if config.client.log_type != "log4j2-xml" { - return Err(LaunchError::UnknownLogType(config.client.log_type.clone())); + + if config.log_type != "log4j2-xml" { + return Err(LaunchError::UnknownLogType(config.log_type.clone())); } - let dlinfo = &config.client.file; + let dlinfo = &config.file; let Some(id) = dlinfo.id.as_ref() else { return Err(LaunchError::InvalidLogId(None)); }; @@ -309,7 +311,7 @@ impl Launcher { } } - Ok(strsub::replace_string(config.client.argument.as_str(), &PathSub(path.as_ref())).to_string()) + Ok(strsub::replace_string(config.argument.as_str(), &PathSub(path.as_ref())).to_string()) } pub async fn prepare_launch(&self, profile: &Profile, instance: &Instance) -> Result<Launch, LaunchError> { @@ -377,7 +379,7 @@ impl Launcher { let mut libs = Vec::new(); let mut extract_jobs = Vec::new(); - let mut downloads = Vec::new(); + let mut downloads = IndexMap::new(); for lib in ver.libraries.values() { if lib.rules_apply(&self.system_info, &feature_matcher).is_err() { @@ -386,6 +388,9 @@ impl Launcher { libs.push(lib); if let Some(dl) = self.libraries.create_download(lib, self.choose_lib_classifier(lib)) { + let canon_name = lib.get_canonical_name(); + if downloads.contains_key(&canon_name) { continue; } + dl.make_dirs().await.map_err(|e| LaunchError::LibraryDirError(dl.get_path().to_path_buf(), e))?; if lib.natives.is_some() { @@ -395,21 +400,21 @@ impl Launcher { }); } - downloads.push(dl); + downloads.insert(canon_name, dl); } } if self.online { info!("Downloading {} libraries...", downloads.len()); let client = Client::new(); - MultiDownloader::new(downloads.iter_mut()).perform(&client).await + MultiDownloader::new(downloads.values_mut()).perform(&client).await .inspect_err(|e| warn!("library download failed: {e}")) .try_fold((), |_, _| async {Ok(())}) .await .map_err(|_| LaunchError::LibraryDownloadError)?; } else { info!("Verifying {} libraries...", downloads.len()); - download::verify_files(downloads.iter_mut()).await.map_err(|e| { + download::verify_files(downloads.values_mut()).await.map_err(|e| { warn!("A library could not be verified: {}", e); warn!("Since the launcher is in offline mode, libraries cannot be downloaded. Please try again in online mode."); LaunchError::LibraryVerifyError(e) @@ -417,7 +422,7 @@ impl Launcher { } let log_arg; - if let Some(logging) = ver.logging.as_ref() { + if let Some(logging) = ver.logging.as_ref().map_or(None, |l| l.client.as_ref()) { log_arg = Some(self.log_config_ensure(logging).await?); } else { log_arg = None; @@ -476,7 +481,7 @@ impl Launcher { }; info!("Building classpath"); - let classpath = env::join_paths(downloads.iter() + let classpath = env::join_paths(downloads.values() .map(|job| job.get_path().as_java_path()) .chain(client_jar_path.iter().map(|p| p.as_path().as_java_path()))) .map_err(|e| LaunchError::LibraryClasspathError(e))? @@ -627,17 +632,21 @@ impl LibraryRepository { } fn create_download(&self, lib: &Library, classifier: Option<&str>) -> Option<VerifiedDownload> { - if lib.url.is_some() || lib.downloads.is_none() { - // TODO: derive download URL in this situation? - warn!("BUG: Deprecated case for library {}: url present or downloads missing. The launcher does not support out-of-line checksums at this time. Not downloading this library.", lib.name); - return None; + if let Some(ref url) = lib.url { + let path = Self::get_artifact_path(lib.name.as_str(), classifier)?; + let url = [url.as_str(), path.to_string_lossy().as_ref()].into_iter().collect::<String>(); + Some(VerifiedDownload::new(url.as_ref(), self.home.join(path).as_path(), lib.size, lib.sha1)) // TODO: could download sha1 + } else if let Some(ref downloads) = lib.downloads { + let dlinfo = downloads.get_download_info(classifier)?; + // drinking game: take a shot once per heap allocation + let path = self.home.join(dlinfo.path.as_ref().map(PathBuf::from).or_else(|| Self::get_artifact_path(lib.name.as_str(), classifier))?); + + Some(VerifiedDownload::new(dlinfo.url.as_ref()?, path.as_path(), dlinfo.size, dlinfo.sha1)) + } else { + let path = Self::get_artifact_path(lib.name.as_str(), classifier)?; + let url = ["https://libraries.minecraft.net/", path.to_string_lossy().as_ref()].into_iter().collect::<String>(); + Some(VerifiedDownload::new(url.as_ref(), self.home.join(path).as_path(), lib.size, lib.sha1)) // TODO: could download sha1 } - - let dlinfo = lib.downloads.as_ref()?.get_download_info(classifier)?; - // drinking game: take a shot once per heap allocation - let path = self.home.join(dlinfo.path.as_ref().map(PathBuf::from).or_else(|| Self::get_artifact_path(lib.name.as_str(), classifier))?); - - Some(VerifiedDownload::new(dlinfo.url.as_ref()?, path.as_path(), dlinfo.size, dlinfo.sha1)) } async fn clean_old_natives(&self) -> Result<usize, LaunchError> { |
