From 7db451eab4de13ac2dfd1b570a9e01a6afded919 Mon Sep 17 00:00:00 2001 From: bigfoot547 Date: Wed, 15 Jan 2025 00:55:05 -0600 Subject: get started on assets --- src/assets.rs | 84 +++++++++++++++++++++++++++++++++++++++++++++++ src/launcher.rs | 15 ++++++--- src/launcher/constants.rs | 2 ++ src/lib.rs | 1 + 4 files changed, 97 insertions(+), 5 deletions(-) create mode 100644 src/assets.rs (limited to 'src') diff --git a/src/assets.rs b/src/assets.rs new file mode 100644 index 0000000..9b0b7a7 --- /dev/null +++ b/src/assets.rs @@ -0,0 +1,84 @@ +use std::fmt::Formatter; +use std::marker::PhantomData; +use serde::{Deserialize, Deserializer}; +use serde::de::{MapAccess, Visitor}; +use sha1_smol::Digest; + +#[derive(Debug, Deserialize)] +pub struct Asset { + #[serde(skip)] + pub name: String, + pub hash: Digest, + pub size: usize +} + +#[derive(Debug, Deserialize)] +pub struct AssetIndex { + #[serde(rename = "virtual", default)] + pub virtual_assets: bool, + #[serde(default)] + pub map_to_resources: bool, + + #[serde(deserialize_with = "deserialize_assets")] + pub objects: Vec +} + +trait SetName { + fn set_name(&mut self, name: String); +} + +impl SetName for Asset { + fn set_name(&mut self, name: String) { + self.name = name; + } +} + +fn deserialize_assets<'de, D, T>(deserializer: D) -> Result, D::Error> +where + D: Deserializer<'de>, + T: SetName + Deserialize<'de> +{ + struct AssetVisitor(PhantomData); + + impl<'de, T> Visitor<'de> for AssetVisitor + where + T: SetName + Deserialize<'de> + { + type Value = Vec; + + fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result { + formatter.write_str("asset objects map") + } + + fn visit_map(self, mut map: A) -> Result + where + A: MapAccess<'de>, + { + let mut out = Vec::new(); + + while let Some((key, mut asset)) = map.next_entry::()? { + asset.set_name(key); + out.push(asset); + } + + Ok(out) + } + } + + deserializer.deserialize_any(AssetVisitor(PhantomData)) +} + +mod tests { + use super::*; + + #[test] + fn test_it() { + dbg!(serde_json::from_str::(r#"{ + "virtual": true, + "objects": { + "object1": { "hash": "0d000710b71ca9aafabd8f587768431d0b560b32", "size": 100 }, + "object2/abc": { "hash": "0e000710b71ca9aafabd8f587768431d0b560b32", "size": 10000 } + } + }"#).unwrap()); + } +} diff --git a/src/launcher.rs b/src/launcher.rs index 96ba3bd..970386a 100644 --- a/src/launcher.rs +++ b/src/launcher.rs @@ -225,6 +225,8 @@ impl Launcher { } async fn log_config_ensure(&self, config: &Logging) -> Result, LogConfigError> { + info!("Ensuring log configuration exists and is valid."); + if config.client.log_type != "log4j2-xml" { return Err(LogConfigError::UnknownType(config.client.log_type.clone())); } @@ -349,9 +351,9 @@ impl Launcher { * - (done) redownload necessary libraries * - (if offline mode and there are libraries to download, then explode violently) * - extract natives - * - logging - * - download the config if present and necessary - * - (explode if offline mode and we need to download stuff) + * - (done) logging + * - (done) download the config if present and necessary + * - (done) (explode if offline mode and we need to download stuff) * - assets * - get asset index (check if our local copy is good and redownload if not) * - check what ones are good and what needs to be downloaded @@ -364,6 +366,8 @@ impl Launcher { * - launch the game * - build argument list and whatnot also */ + info!("Preparing launch for \"{}\"...", profile.version_id); + let ver_res = self.versions.get_version_lazy(&profile.version_id); let ver = match ver_res { VersionResult::Remote(mv) => Cow::Owned(self.versions.load_remote_version(mv).await.map_err(|e| LaunchError::LoadVersion(e))?), @@ -375,6 +379,8 @@ impl Launcher { let ver = self.versions.resolve_version(ver.as_ref()).await.map_err(|e| LaunchError::ResolveVersion(e))?; ver.rules_apply(&self.system_info, |_| false).map_err(|e| LaunchError::IncompatibleVersion(e))?; + + info!("Resolved launch version {}!", ver.id); let mut libs = Vec::new(); let mut downloads = Vec::new(); @@ -406,7 +412,7 @@ impl Launcher { debug!("Verifying library {}", dl.get_path().display()); util::verify_file(dl.get_path(), dl.get_expect_size(), dl.get_expect_sha1()).await })) - .try_buffer_unordered(5) + .try_buffer_unordered(8) .try_fold((), |_, _| async {Ok(())}) .await .map_err(|e| { @@ -418,7 +424,6 @@ impl Launcher { let log_arg; if let Some(logging) = ver.logging.as_ref() { - info!("Ensuring log configuration exists and is valid."); log_arg = self.log_config_ensure(logging).await .map_err(|e| LaunchError::LogConfig(e))?; } else { diff --git a/src/launcher/constants.rs b/src/launcher/constants.rs index 698081b..83611c9 100644 --- a/src/launcher/constants.rs +++ b/src/launcher/constants.rs @@ -6,3 +6,5 @@ const CRATE_NAME: &str = env!("CARGO_CRATE_NAME"); 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"; diff --git a/src/lib.rs b/src/lib.rs index c369ed5..255d914 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,3 +1,4 @@ mod util; pub mod version; +pub mod assets; pub mod launcher; -- cgit v1.2.3-70-g09d2