summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ozone-cli/src/main.rs2
-rw-r--r--src/assets.rs84
-rw-r--r--src/launcher.rs15
-rw-r--r--src/launcher/constants.rs2
-rw-r--r--src/lib.rs1
5 files changed, 98 insertions, 6 deletions
diff --git a/ozone-cli/src/main.rs b/ozone-cli/src/main.rs
index d14d2a1..45c53cd 100644
--- a/ozone-cli/src/main.rs
+++ b/ozone-cli/src/main.rs
@@ -15,7 +15,7 @@ async fn main() -> Result<(), Box<dyn Error>> {
let launcher = o3launcher::launcher::Launcher::new(PathBuf::from("./work").as_path(), true).await?;
let profile = Profile {
- version_id: "1.21.4".into(),
+ version_id: "25w02a".into(),
java_runtime: None,
instance: "".into()
};
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<Asset>
+}
+
+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<Vec<T>, D::Error>
+where
+ D: Deserializer<'de>,
+ T: SetName + Deserialize<'de>
+{
+ struct AssetVisitor<T>(PhantomData<T>);
+
+ impl<'de, T> Visitor<'de> for AssetVisitor<T>
+ where
+ T: SetName + Deserialize<'de>
+ {
+ type Value = Vec<T>;
+
+ fn expecting(&self, formatter: &mut Formatter) -> std::fmt::Result {
+ formatter.write_str("asset objects map")
+ }
+
+ fn visit_map<A>(self, mut map: A) -> Result<Self::Value, A::Error>
+ where
+ A: MapAccess<'de>,
+ {
+ let mut out = Vec::new();
+
+ while let Some((key, mut asset)) = map.next_entry::<String, T>()? {
+ 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::<AssetIndex>(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<Option<String>, 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;