summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2025-01-17 01:36:33 -0600
committerLibravatar bigfoot547 <[email protected]>2025-01-17 01:36:33 -0600
commit3ef28748cb6c361cfaad2bc6639871cfe4107ff7 (patch)
tree5d47f365f28fe6031353526e6d2504eaee8b215b
parentfix bugs (diff)
building classpath
-rw-r--r--src/launcher.rs28
-rw-r--r--src/launcher/assets.rs7
-rw-r--r--src/launcher/download.rs50
3 files changed, 49 insertions, 36 deletions
diff --git a/src/launcher.rs b/src/launcher.rs
index 0b1ea90..8a68a65 100644
--- a/src/launcher.rs
+++ b/src/launcher.rs
@@ -18,12 +18,14 @@ use std::fs::FileType;
use std::io::ErrorKind;
use std::io::ErrorKind::AlreadyExists;
use std::path::{Component, Path, PathBuf};
-use std::process;
+use std::{env, process};
+use std::env::JoinPathsError;
use std::time::{SystemTime, UNIX_EPOCH};
use chrono::NaiveDateTime;
use const_format::formatcp;
use futures::{stream, FutureExt, StreamExt, TryStreamExt};
use log::{debug, info, warn};
+use reqwest::Client;
use serde::{Deserialize, Serialize};
use sha1_smol::Sha1;
use sysinfo::System;
@@ -164,6 +166,7 @@ pub enum LaunchError {
LibraryVerifyError(FileVerifyError),
LibraryDownloadError,
LibraryExtractError(extract::ZipExtractError),
+ LibraryClasspathError(JoinPathsError),
// ensure file errors
MissingURL,
@@ -191,6 +194,7 @@ impl Display for LaunchError {
LaunchError::LibraryVerifyError(e) => write!(f, "failed to verify library: {}", e),
LaunchError::LibraryDownloadError => f.write_str("library download failed (see above logs for details)"), // TODO: booo this sucks
LaunchError::LibraryExtractError(e) => write!(f, "library extract zip error: {e}"),
+ LaunchError::LibraryClasspathError(e) => write!(f, "error building classpath: {e}"),
LaunchError::MissingURL => f.write_str("cannot download required file, URL is missing"),
LaunchError::IO { what, error } => write!(f, "i/o error ({}): {}", what, error),
LaunchError::Offline => f.write_str("cannot download file in offline mode"),
@@ -213,6 +217,7 @@ impl Error for LaunchError {
LaunchError::LibraryDirError(_, e) => Some(e),
LaunchError::LibraryVerifyError(e) => Some(e),
LaunchError::LibraryExtractError(e) => Some(e),
+ LaunchError::LibraryClasspathError(e) => Some(e),
LaunchError::IO { error: e, .. } => Some(e),
LaunchError::Download { error: e, .. } => Some(e),
LaunchError::Integrity(e) => Some(e),
@@ -389,7 +394,7 @@ impl Launcher {
/* tasks 2 l;aunch the gayme!!!! :3
* - java runtime
* - normal process (good research, past figboot :3)
- * - libraries
+ * - (done) libraries
* - (done) check which libraries we actually need (some have classifiers that don't apply to us)
* - (done) of the libraries we need, check which have correct size and sha1
* - (done) redownload necessary libraries
@@ -452,15 +457,15 @@ impl Launcher {
if self.online {
info!("Downloading {} libraries...", downloads.len());
- let mut multi = MultiDownloader::new(downloads);
- multi.perform().await
+ let client = Client::new();
+ MultiDownloader::new(downloads.iter_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).await.map_err(|e| {
+ download::verify_files(downloads.iter_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)
@@ -511,6 +516,19 @@ impl Launcher {
info!("Extracting natives.");
let natives_dir = self.libraries.extract_natives(extract_jobs).await?;
+ info!("Building classpath.");
+ let classpath = env::join_paths(downloads.iter()
+ .map(|job| job.get_path())
+ .chain(client_jar_path.iter().map(|p| p.as_path())))
+ .map_err(|e| LaunchError::LibraryClasspathError(e))?
+ .into_string()
+ .unwrap_or_else(|os| {
+ warn!("Classpath contains invalid UTF-8. The game may not launch correctly.");
+ os.to_string_lossy().to_string()
+ });
+
+ info!("Classpath: {classpath}");
+
//todo!()
Ok(())
}
diff --git a/src/launcher/assets.rs b/src/launcher/assets.rs
index e732877..e540e50 100644
--- a/src/launcher/assets.rs
+++ b/src/launcher/assets.rs
@@ -6,6 +6,7 @@ use std::path::{Path, PathBuf};
use std::path::Component::Normal;
use futures::TryStreamExt;
use log::{debug, info, warn};
+use reqwest::Client;
use sha1_smol::Sha1;
use tokio::{fs, io};
use crate::assets::{Asset, AssetIndex};
@@ -215,15 +216,15 @@ impl AssetRepository {
if self.online {
info!("Downloading {} asset objects...", downloads.len());
- let mut multi = MultiDownloader::new(downloads);
- multi.perform().await
+ let client = Client::new();
+ MultiDownloader::with_concurrent(downloads.iter_mut(), 16).perform(&client).await
.inspect_err(|e| warn!("asset download failed: {e}"))
.try_fold((), |_, _| async {Ok(())})
.await
.map_err(|_| AssetError::AssetObjectDownload)?;
} else {
info!("Verifying {} asset objects...", downloads.len());
- super::download::verify_files(downloads).await.map_err(|e| AssetError::AssetVerifyError(e))?;
+ super::download::verify_files(downloads.iter_mut()).await.map_err(|e| AssetError::AssetVerifyError(e))?;
}
Ok(())
diff --git a/src/launcher/download.rs b/src/launcher/download.rs
index d8d05f7..f5469d8 100644
--- a/src/launcher/download.rs
+++ b/src/launcher/download.rs
@@ -22,9 +22,8 @@ pub trait Download: Debug + Display {
async fn finish(&mut self) -> Result<(), Box<dyn Error>>;
}
-pub struct MultiDownloader<T: Download> {
- jobs: Vec<T>,
- client: Client,
+pub struct MultiDownloader<'j, T: Download + 'j, I: Iterator<Item = &'j mut T>> {
+ jobs: I,
nconcurrent: usize
}
@@ -86,25 +85,22 @@ impl<'j, T: Download> PhaseDownloadError<'j, T> {
}
}
-impl<T: Download> MultiDownloader<T> {
- pub fn new(jobs: impl IntoIterator<Item = T>) -> MultiDownloader<T> {
+impl<'j, T: Download + 'j, I: Iterator<Item = &'j mut T>> MultiDownloader<'j, T, I> {
+ pub fn new(jobs: I) -> MultiDownloader<'j, T, I> {
Self::with_concurrent(jobs, 8)
}
- pub fn with_concurrent(jobs: impl IntoIterator<Item = T>, n: usize) -> MultiDownloader<T> {
+ pub fn with_concurrent(jobs: I, n: usize) -> MultiDownloader<'j, T, I> {
assert!(n > 0);
MultiDownloader {
- jobs: jobs.into_iter().collect(),
- client: Client::new(),
+ jobs,
nconcurrent: n
}
}
- pub async fn perform(&mut self) -> impl TryStream<Ok = (), Error = PhaseDownloadError<T>> {
- stream::iter(self.jobs.iter_mut()).map(|job| {
- let client = &self.client;
-
+ pub async fn perform(self, client: &'j Client) -> impl TryStream<Ok = (), Error = PhaseDownloadError<'j, T>> {
+ stream::iter(self.jobs.into_iter()).map(move |job| Ok(async move {
macro_rules! map_err {
($result:expr, $phase:expr, $job:expr) => {
match $result {
@@ -114,26 +110,24 @@ impl<T: Download> MultiDownloader<T> {
}
}
- async move {
- let Some(rq) = map_err!(
- job.prepare(client.request(Method::GET, job.get_url())
- .header(reqwest::header::USER_AGENT, USER_AGENT)).await, Phase::Prepare, job) else {
- return Ok(())
- };
+ let Some(rq) = map_err!(
+ job.prepare(client.request(Method::GET, job.get_url())
+ .header(reqwest::header::USER_AGENT, USER_AGENT)).await, Phase::Prepare, job) else {
+ return Ok(())
+ };
- let mut data = map_err!(map_err!(rq.send().await, Phase::Send, job).error_for_status(), Phase::Send, job).bytes_stream();
+ let mut data = map_err!(map_err!(rq.send().await, Phase::Send, job).error_for_status(), Phase::Send, job).bytes_stream();
- while let Some(bytes) = data.next().await {
- let bytes = map_err!(bytes, Phase::Receive, job);
+ while let Some(bytes) = data.next().await {
+ let bytes = map_err!(bytes, Phase::Receive, job);
- map_err!(job.handle_chunk(bytes.as_ref()).await, Phase::HandleChunk, job);
- }
+ map_err!(job.handle_chunk(bytes.as_ref()).await, Phase::HandleChunk, job);
+ }
- job.finish().await.map_err(|e| PhaseDownloadError::new(Phase::Finish, e.into(), job))?;
+ job.finish().await.map_err(|e| PhaseDownloadError::new(Phase::Finish, e.into(), job))?;
- Ok(())
- }
- }).buffer_unordered(self.nconcurrent)
+ Ok(())
+ })).try_buffer_unordered(self.nconcurrent)
}
}
@@ -282,7 +276,7 @@ impl Download for VerifiedDownload {
}
}
-pub async fn verify_files(files: Vec<VerifiedDownload>) -> Result<(), FileVerifyError> {
+pub async fn verify_files(files: impl Iterator<Item = &mut VerifiedDownload>) -> Result<(), FileVerifyError> {
stream::iter(files)
.map(|dl| Ok(async move {
debug!("Verifying library {}", dl.get_path().display());