summaryrefslogtreecommitdiffstats
path: root/src/launcher.rs
diff options
context:
space:
mode:
Diffstat (limited to 'src/launcher.rs')
-rw-r--r--src/launcher.rs55
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> {