summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar bigfoot547 <[email protected]>2025-01-16 19:58:49 -0600
committerLibravatar bigfoot547 <[email protected]>2025-01-16 19:58:49 -0600
commit55e314f513cdfb3ba33089621d460cfa925c20b2 (patch)
tree4447c7c8cff91960ef033c74367251efb19379e7
parentremove idea files (diff)
start on extracting libraries
-rw-r--r--Cargo.lock190
-rw-r--r--Cargo.toml3
-rw-r--r--src/launcher.rs150
-rw-r--r--src/launcher/assets.rs5
-rw-r--r--src/launcher/constants.rs8
5 files changed, 321 insertions, 35 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a5cc39c..d96e051 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -90,7 +90,7 @@ dependencies = [
"ndk-context",
"ndk-sys 0.6.0+11769913",
"num_enum",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -124,6 +124,15 @@ dependencies = [
]
[[package]]
+name = "arbitrary"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "dde20b3d026af13f561bdd0f15edf01fc734f0dafcedbaf42bba506a9517f223"
+dependencies = [
+ "derive_arbitrary",
+]
+
+[[package]]
name = "arrayref"
version = "0.3.9"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -435,6 +444,27 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "325918d6fe32f23b19878fe4b34794ae41fc19ddbe53b10571a4874d44ffd39b"
[[package]]
+name = "bzip2"
+version = "0.4.4"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "bdb116a6ef3f6c3698828873ad02c3014b3c85cadb88496095628e3ef1e347f8"
+dependencies = [
+ "bzip2-sys",
+ "libc",
+]
+
+[[package]]
+name = "bzip2-sys"
+version = "0.1.11+1.0.8"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "736a955f3fa7875102d57c82b8cac37ec45224a07fd32d58f9f7a186b6cd4cdc"
+dependencies = [
+ "cc",
+ "libc",
+ "pkg-config",
+]
+
+[[package]]
name = "calloop"
version = "0.13.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -445,7 +475,7 @@ dependencies = [
"polling",
"rustix",
"slab",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -543,7 +573,7 @@ version = "0.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "4274ea815e013e0f9f04a2633423e14194e408a0576c943ce3d14ca56c50031c"
dependencies = [
- "thiserror",
+ "thiserror 1.0.69",
"x11rb",
]
@@ -744,6 +774,21 @@ dependencies = [
]
[[package]]
+name = "crc"
+version = "3.2.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "69e6e4d7b33a94f0991c26729976b10ebde1d34c3ee82408fb536164fa10d636"
+dependencies = [
+ "crc-catalog",
+]
+
+[[package]]
+name = "crc-catalog"
+version = "2.4.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "19d374276b40fb8bbdee95aef7c7fa6b5316ec764510eb64b8dd0e2ed0d7e7f5"
+
+[[package]]
name = "crc32fast"
version = "1.4.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -839,6 +884,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "7046468a81e6a002061c01e6a7c83139daf91b11c30e66795b13217c2d885c8b"
[[package]]
+name = "deflate64"
+version = "0.1.9"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "da692b8d1080ea3045efaab14434d40468c3d8657e42abddfffca87b428f4c1b"
+
+[[package]]
name = "deranged"
version = "0.3.11"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -848,6 +899,17 @@ dependencies = [
]
[[package]]
+name = "derive_arbitrary"
+version = "1.4.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "30542c1ad912e0e3d22a1935c290e12e8a29d704a420177a31faad4a601a0800"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.93",
+]
+
+[[package]]
name = "detect-desktop-environment"
version = "0.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -1395,7 +1457,7 @@ checksum = "6f56f6318968d03c18e1bcf4857ff88c61157e9da8e47c5f29055d60e1228884"
dependencies = [
"log",
"presser",
- "thiserror",
+ "thiserror 1.0.69",
"winapi",
"windows 0.52.0",
]
@@ -1494,7 +1556,7 @@ dependencies = [
"com",
"libc",
"libloading 0.8.6",
- "thiserror",
+ "thiserror 1.0.69",
"widestring",
"winapi",
]
@@ -1669,7 +1731,7 @@ dependencies = [
"iced_renderer",
"iced_widget",
"iced_winit",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -1688,7 +1750,7 @@ dependencies = [
"palette",
"rustc-hash 2.1.0",
"smol_str",
- "thiserror",
+ "thiserror 1.0.69",
"web-time",
]
@@ -1736,7 +1798,7 @@ dependencies = [
"once_cell",
"raw-window-handle",
"rustc-hash 2.1.0",
- "thiserror",
+ "thiserror 1.0.69",
"unicode-segmentation",
]
@@ -1750,7 +1812,7 @@ dependencies = [
"iced_tiny_skia",
"iced_wgpu",
"log",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -1763,7 +1825,7 @@ dependencies = [
"iced_core",
"iced_futures",
"raw-window-handle",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -1798,7 +1860,7 @@ dependencies = [
"log",
"once_cell",
"rustc-hash 2.1.0",
- "thiserror",
+ "thiserror 1.0.69",
"wgpu",
]
@@ -1813,7 +1875,7 @@ dependencies = [
"num-traits",
"once_cell",
"rustc-hash 2.1.0",
- "thiserror",
+ "thiserror 1.0.69",
"unicode-segmentation",
]
@@ -1828,7 +1890,7 @@ dependencies = [
"iced_runtime",
"log",
"rustc-hash 2.1.0",
- "thiserror",
+ "thiserror 1.0.69",
"tracing",
"wasm-bindgen-futures",
"web-sys",
@@ -2018,7 +2080,7 @@ dependencies = [
"combine",
"jni-sys",
"log",
- "thiserror",
+ "thiserror 1.0.69",
"walkdir",
"windows-sys 0.45.0",
]
@@ -2153,6 +2215,12 @@ dependencies = [
]
[[package]]
+name = "lockfree-object-pool"
+version = "0.1.6"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "9374ef4228402d4b7e403e5838cb880d9ee663314b0a900d5a6aabf0c213552e"
+
+[[package]]
name = "log"
version = "0.4.25"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2165,6 +2233,16 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "234cf4f4a04dc1f57e24b96cc0cd600cf2af460d4161ac5ecdd0af8e1f3b2a38"
[[package]]
+name = "lzma-rs"
+version = "0.3.0"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "297e814c836ae64db86b36cf2a557ba54368d03f6afcd7d947c266692f71115e"
+dependencies = [
+ "byteorder",
+ "crc",
+]
+
+[[package]]
name = "malloc_buf"
version = "0.0.6"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -2255,7 +2333,7 @@ dependencies = [
"rustc-hash 1.1.0",
"spirv",
"termcolor",
- "thiserror",
+ "thiserror 1.0.69",
"unicode-xid",
]
@@ -2288,7 +2366,7 @@ dependencies = [
"ndk-sys 0.6.0+11769913",
"num_enum",
"raw-window-handle",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -2399,6 +2477,7 @@ dependencies = [
"chrono",
"const_format",
"futures",
+ "lazy_static",
"log",
"regex",
"reqwest",
@@ -2407,6 +2486,8 @@ dependencies = [
"sha1_smol",
"sysinfo",
"tokio",
+ "tokio-stream",
+ "zip",
]
[[package]]
@@ -3131,7 +3212,7 @@ checksum = "ba009ff324d1fc1b900bd1fdb31564febe58a8ccc8a6fdbb93b543d33b13ca43"
dependencies = [
"getrandom",
"libredox",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -3573,7 +3654,7 @@ dependencies = [
"log",
"memmap2",
"rustix",
- "thiserror",
+ "thiserror 1.0.69",
"wayland-backend",
"wayland-client",
"wayland-csd-frame",
@@ -3816,7 +3897,16 @@ version = "1.0.69"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b6aaf5339b578ea85b50e080feb250a3e8ae8cfcdff9a461c9ec2904bc923f52"
dependencies = [
- "thiserror-impl",
+ "thiserror-impl 1.0.69",
+]
+
+[[package]]
+name = "thiserror"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "d452f284b73e6d76dd36758a0c8684b1d5be31f92b89d07fd5822175732206fc"
+dependencies = [
+ "thiserror-impl 2.0.11",
]
[[package]]
@@ -3831,6 +3921,17 @@ dependencies = [
]
[[package]]
+name = "thiserror-impl"
+version = "2.0.11"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "26afc1baea8a989337eeb52b6e72a039780ce45c3edfcc9c5b9d112feeb173c2"
+dependencies = [
+ "proc-macro2",
+ "quote",
+ "syn 2.0.93",
+]
+
+[[package]]
name = "time"
version = "0.3.37"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -3975,6 +4076,17 @@ dependencies = [
]
[[package]]
+name = "tokio-stream"
+version = "0.1.17"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "eca58d7bba4a75707817a2c44174253f9236b2d5fbd055602e9d5c07c139a047"
+dependencies = [
+ "futures-core",
+ "pin-project-lite",
+ "tokio",
+]
+
+[[package]]
name = "tokio-util"
version = "0.7.13"
source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -4498,7 +4610,7 @@ dependencies = [
"raw-window-handle",
"rustc-hash 1.1.0",
"smallvec",
- "thiserror",
+ "thiserror 1.0.69",
"web-sys",
"wgpu-hal",
"wgpu-types",
@@ -4542,7 +4654,7 @@ dependencies = [
"renderdoc-sys",
"rustc-hash 1.1.0",
"smallvec",
- "thiserror",
+ "thiserror 1.0.69",
"wasm-bindgen",
"web-sys",
"wgpu-types",
@@ -4608,7 +4720,7 @@ dependencies = [
"clipboard_wayland",
"clipboard_x11",
"raw-window-handle",
- "thiserror",
+ "thiserror 1.0.69",
]
[[package]]
@@ -5251,6 +5363,40 @@ dependencies = [
]
[[package]]
+name = "zip"
+version = "2.2.2"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "ae9c1ea7b3a5e1f4b922ff856a129881167511563dc219869afe3787fc0c1a45"
+dependencies = [
+ "arbitrary",
+ "bzip2",
+ "crc32fast",
+ "crossbeam-utils",
+ "deflate64",
+ "displaydoc",
+ "flate2",
+ "indexmap",
+ "lzma-rs",
+ "memchr",
+ "thiserror 2.0.11",
+ "zopfli",
+]
+
+[[package]]
+name = "zopfli"
+version = "0.8.1"
+source = "registry+https://github.com/rust-lang/crates.io-index"
+checksum = "e5019f391bac5cf252e93bbcc53d039ffd62c7bfb7c150414d61369afe57e946"
+dependencies = [
+ "bumpalo",
+ "crc32fast",
+ "lockfree-object-pool",
+ "log",
+ "once_cell",
+ "simd-adler32",
+]
+
+[[package]]
name = "zvariant"
version = "4.2.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
diff --git a/Cargo.toml b/Cargo.toml
index 965af54..34f1eda 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -7,6 +7,7 @@ edition = "2021"
chrono = { version = "0.4.39", default-features = false, features = ["std", "alloc", "clock", "now", "serde"] }
const_format = "0.2.34"
futures = "0.3.31"
+lazy_static = "1.5.0"
log = "0.4.22"
regex = "1.11.1"
reqwest = { version = "0.12.12", features = ["json", "stream"] }
@@ -15,6 +16,8 @@ serde_json = "1.0.133"
sha1_smol = { version = "1.0.1", features = ["alloc", "std", "serde"] }
sysinfo = { version = "0.33.1", features = ["system", "multithread"] }
tokio = { version = "1.42.0", features = ["fs", "io-util", "sync", "rt"] }
+tokio-stream = { version = "0.1.17", features = ["fs"] }
+zip = { version = "2.2.2", default-features = false, features = ["bzip2", "deflate", "deflate64", "lzma", "xz"] }
[workspace]
members = [ "ozone-cli", "ozone-ui" ]
diff --git a/src/launcher.rs b/src/launcher.rs
index 25cdcc4..f712e69 100644
--- a/src/launcher.rs
+++ b/src/launcher.rs
@@ -7,16 +7,21 @@ mod rules;
mod assets;
use std::borrow::Cow;
+use std::cmp::min;
use std::collections::HashMap;
use std::env::consts::{ARCH, OS};
use std::error::Error;
use std::ffi::OsStr;
use std::fmt::{Display, Formatter};
+use std::fs::FileType;
use std::io::ErrorKind;
use std::io::ErrorKind::AlreadyExists;
use std::path::{Component, Path, PathBuf};
+use std::process;
+use std::time::{SystemTime, UNIX_EPOCH};
+use chrono::NaiveDateTime;
use const_format::formatcp;
-use futures::TryStreamExt;
+use futures::{stream, FutureExt, StreamExt, TryStreamExt};
use log::{debug, info, warn};
use serde::{Deserialize, Serialize};
use sha1_smol::Sha1;
@@ -24,10 +29,12 @@ use sysinfo::System;
use tokio::{fs, io};
use tokio::fs::File;
use tokio::io::AsyncWriteExt;
+use tokio_stream::wrappers::ReadDirStream;
+use zip::ZipArchive;
use download::{MultiDownloader, VerifiedDownload};
use rules::{CompatCheck, IncompatibleError};
use version::{VersionList, VersionResolveError, VersionResult};
-use crate::version::{Logging, Library, OSRestriction, OperatingSystem, DownloadType, DownloadInfo};
+use crate::version::{Logging, Library, OSRestriction, OperatingSystem, DownloadType, DownloadInfo, LibraryExtractRule};
pub use profile::{Instance, Profile};
use crate::launcher::assets::{AssetError, AssetRepository};
@@ -125,7 +132,8 @@ struct SystemInfo {
}
struct LibraryRepository {
- home: PathBuf
+ home: PathBuf,
+ natives: PathBuf
}
pub struct Launcher {
@@ -154,6 +162,7 @@ pub enum LaunchError {
LibraryDirError(PathBuf, io::Error),
LibraryVerifyError(FileVerifyError),
LibraryDownloadError,
+ LibraryExtractZipError(PathBuf, zip::result::ZipError),
// ensure file errors
MissingURL,
@@ -180,6 +189,7 @@ impl Display for LaunchError {
LaunchError::LibraryDirError(path, e) => write!(f, "failed to create library directory {}: {}", path.display(), e),
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::LibraryExtractZipError(path, e) => write!(f, "library extract zip error ({}): {e}", path.display()),
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"),
@@ -201,6 +211,7 @@ impl Error for LaunchError {
LaunchError::IncompatibleVersion(e) => Some(e),
LaunchError::LibraryDirError(_, e) => Some(e),
LaunchError::LibraryVerifyError(e) => Some(e),
+ LaunchError::LibraryExtractZipError(_, e) => Some(e),
LaunchError::IO { error: e, .. } => Some(e),
LaunchError::Download { error: e, .. } => Some(e),
LaunchError::Integrity(e) => Some(e),
@@ -245,12 +256,24 @@ impl Launcher {
system_info: SystemInfo::new(),
libraries: LibraryRepository {
home: home.join("libraries"),
+ natives: home.join("natives")
},
assets: AssetRepository::new(online, &assets_path).await?,
home
})
}
+ fn choose_lib_classifier<'lib>(&self, lib: &'lib Library) -> Option<&'lib str> {
+ lib.natives.as_ref().map_or(None, |n| n.get(&self.system_info.os)).map(|s| s.as_str())
+ }
+
+ fn create_extract_job<'lib>(&self, lib: &'lib Library) -> Option<LibraryExtractJob<'lib>> {
+ Some(LibraryExtractJob {
+ source: LibraryRepository::get_artifact_path(lib.name.as_str(), self.choose_lib_classifier(lib))?,
+ rule: lib.extract.as_ref()
+ })
+ }
+
async fn ensure_file(&self, path: &Path, dlinfo: &DownloadInfo) -> Result<(), LaunchError> {
// verify the file
match util::verify_file(path, dlinfo.size, dlinfo.sha1).await {
@@ -387,7 +410,7 @@ impl Launcher {
* - (done) download them
* - (done) (if offline mode, explode)
* - if virtual or resource-mapped, copy (or perhaps hardlink? that would be cool)
- * - the actual client jar
+ * - (done) the actual client jar
* - (done) check integriddy and download if needed
* - (done) (explode if offline mode)
* - launch the game
@@ -418,7 +441,7 @@ impl Launcher {
}
libs.push(lib);
- if let Some(dl) = self.libraries.create_download(lib, self.system_info.os) {
+ if let Some(dl) = self.libraries.create_download(lib, self.choose_lib_classifier(lib)) {
dl.make_dirs().await.map_err(|e| LaunchError::LibraryDirError(dl.get_path().to_path_buf(), e))?;
downloads.push(dl);
}
@@ -477,27 +500,45 @@ impl Launcher {
client_jar_path = None;
}
+ // clean up old natives
+ let nnatives = self.libraries.clean_old_natives().await?;
+ info!("Cleaned up {} old natives directories.", nnatives);
+
+ // extract natives
+
//todo!()
Ok(())
}
}
-#[derive(Debug, Clone)]
+#[derive(Debug)]
enum LibraryError {
InvalidName(String),
- IOError(ErrorKind)
+ IO { what: &'static str, error: io::Error }
}
impl Display for LibraryError {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
LibraryError::InvalidName(name) => write!(f, "invalid name: {name}"),
- LibraryError::IOError(e) => write!(f, "io error reading library: {e}"),
+ LibraryError::IO { what, error } => write!(f, "library i/o error ({what}): {error}"),
+ }
+ }
+}
+
+impl Error for LibraryError {
+ fn source(&self) -> Option<&(dyn Error + 'static)> {
+ match self {
+ LibraryError::IO { error, .. } => Some(error),
+ _ => None
}
}
}
-impl Error for LibraryError {}
+struct LibraryExtractJob<'lib> {
+ source: PathBuf,
+ rule: Option<&'lib LibraryExtractRule>
+}
const ARCH_BITS: &'static str = formatcp!("{}", usize::BITS);
@@ -542,9 +583,7 @@ impl LibraryRepository {
Some(p)
}
- fn create_download(&self, lib: &Library, os: OperatingSystem) -> Option<VerifiedDownload> {
- let classifier = lib.natives.as_ref().map_or(None, |n| n.get(&os)).map(|s| s.as_str());
-
+ 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);
@@ -557,6 +596,93 @@ impl LibraryRepository {
Some(VerifiedDownload::new(dlinfo.url.as_ref()?, path.as_path(), dlinfo.size, dlinfo.sha1))
}
+
+ async fn clean_old_natives(&self) -> Result<usize, LaunchError> {
+ info!("Cleaning up old natives folders...");
+
+ let boot_time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs() - min(System::uptime(), 7u64*24*60*60);
+
+ let readdir = match fs::read_dir(&self.natives).await {
+ Ok(readdir) => readdir,
+ Err(e) if e.kind() == ErrorKind::NotFound => return Ok(0),
+ Err(e) => return Err(LaunchError::IO { what: "reading natives directory", error: e })
+ };
+
+ ReadDirStream::new(readdir)
+ .map(|entry| Ok(async move {
+ let entry = entry.map_err(|e| LaunchError::IO { what: "reading natives entry", error: e })?;
+ let ftype = entry.file_type().await.map_err(|e| LaunchError::IO { what: "'stat'ing natives entry", error: e })?;
+
+ if !ftype.is_dir() { return Ok(false); }
+
+ let Some(ftime) = entry.file_name().to_str()
+ .map_or(None, |s| constants::NATIVES_DIR_PATTERN.captures(s))
+ .map_or(None, |c| c.get(1))
+ .map_or(None, |cap| cap.as_str().parse::<u64>().ok()) else {
+ return Ok(false);
+ };
+
+ if ftime < boot_time {
+ let path = entry.path();
+ info!("Deleting old natives directory {}", path.display());
+
+ /*fs::remove_dir_all(&path).await.map_err(|e| LaunchError::IO {
+ what: "reading natives entry",
+ error: e
+ })?;*/
+
+ return Ok(true);
+ }
+
+ Ok(false)
+ }))
+ .try_buffer_unordered(8)
+ .try_fold(0usize, |accum, res| async move {
+ match res {
+ true => Ok(accum + 1),
+ _ => Ok(accum)
+ }
+ }).await
+ }
+
+ fn extract_natives_for<'lib>(natives: &Path, job: LibraryExtractJob<'lib>) -> Result<usize, LaunchError> {
+ /*let file = File::open(&job.source).await.map_err(|e| LaunchError::IO {
+ what: "extracting library natives (open)",
+ error: e
+ })?;
+
+ let z = ZipArchive::new(file);*/
+
+ todo!()
+ }
+
+ async fn extract_natives<'lib>(&self, libs: impl IntoIterator<Item = LibraryExtractJob<'lib>>) -> Result<PathBuf, LaunchError> {
+ fs::create_dir_all(&self.natives).await.map_err(|e| LaunchError::IO {
+ what: "creating natives directory",
+ error: e
+ })?;
+
+ let time = SystemTime::now().duration_since(UNIX_EPOCH).unwrap().as_secs();
+ let natives_dir = self.natives.join(format!("{}{}-{}", constants::NATIVES_PREFIX, time, process::id()));
+
+ // create_dir_all suppresses "AlreadyExists", but this is a fatal error here.
+ fs::create_dir(&natives_dir).await.map_err(|e| LaunchError::IO {
+ what: "creating natives directory",
+ error: e
+ })?;
+
+ let natives_dir_ref = natives_dir.as_path();
+
+ stream::iter(libs)
+ .map(|lib| Ok(async move {
+ // TODO: Self::extract_natives_for(natives_dir_ref, lib)
+ todo!() as Result<usize, _>
+ }))
+ .try_buffer_unordered(8)
+ .try_fold(0usize, |accum, num| async move {Ok(accum + num)})
+ .await.inspect(|num| debug!("Extracted {} native entries to {}", num, natives_dir_ref.display()))
+ .map(|_| natives_dir)
+ }
}
impl SystemInfo {
diff --git a/src/launcher/assets.rs b/src/launcher/assets.rs
index 7ad368e..e732877 100644
--- a/src/launcher/assets.rs
+++ b/src/launcher/assets.rs
@@ -168,7 +168,10 @@ impl AssetRepository {
if let Some(expect) = index.sha1 {
let actual = Sha1::from(&idx_text).digest();
- return Err(AssetError::Integrity(IntegrityError::Sha1Mismatch { expect, actual }));
+
+ if actual != expect {
+ return Err(AssetError::Integrity(IntegrityError::Sha1Mismatch { expect, actual }));
+ }
}
debug!("Saving downloaded asset index to {}", path.display());
diff --git a/src/launcher/constants.rs b/src/launcher/constants.rs
index 83611c9..a0ef036 100644
--- a/src/launcher/constants.rs
+++ b/src/launcher/constants.rs
@@ -1,4 +1,6 @@
use const_format::formatcp;
+use lazy_static::lazy_static;
+use regex::Regex;
const PKG_NAME: &str = env!("CARGO_PKG_NAME");
const PKG_VERSION: &str = env!("CARGO_PKG_VERSION");
@@ -8,3 +10,9 @@ pub const USER_AGENT: &str = formatcp!("{PKG_NAME}/{PKG_VERSION} (in {CRATE_NAME
pub const URL_VERSION_MANIFEST: &str = "https://piston-meta.mojang.com/mc/game/version_manifest_v2.json";
pub const URL_RESOURCE_BASE: &str = "https://resources.download.minecraft.net/";
pub const URL_JRE_MANIFEST: &str = "https://launchermeta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json";
+
+pub const NATIVES_PREFIX: &str = "natives-";
+
+lazy_static! {
+ pub static ref NATIVES_DIR_PATTERN: Regex = Regex::new("^natives-(\\d+)").unwrap();
+} \ No newline at end of file