diff --git a/src-tauri/src/launcher/manifest.rs b/src-tauri/src/launcher/manifest.rs index 954f92b..694105d 100644 --- a/src-tauri/src/launcher/manifest.rs +++ b/src-tauri/src/launcher/manifest.rs @@ -46,7 +46,7 @@ pub async fn get_version_from_manifest<'a>(manifest: &'a VersionManifestV2, game pub struct VersionDetail { arguments: Map, #[serde(rename(serialize = "assetIndex", deserialize = "assetIndex"))] - asset_index: Map, + pub asset_index: AssetIndex, assets: String, downloads: Map, id: String, @@ -60,6 +60,16 @@ pub struct VersionDetail { v_type: VersionType } +#[derive(Serialize, Deserialize)] +pub struct AssetIndex { + pub id: i32, + pub sha1: String, + pub size: usize, + #[serde(rename(serialize = "totalSize", deserialize = "totalSize"))] + pub total_size: usize, + pub url: String +} + #[derive(Serialize, Deserialize)] pub struct Library { pub downloads: LibraryDownload, @@ -108,4 +118,13 @@ pub async fn get_version_detail(reqwest: &Client, version : &Version) -> Result< .json() .await?; Ok(received) +} + +#[derive(Serialize, Deserialize)] +pub struct AssetsManifest { + objects: Map, +} + +pub async fn get_version_assets(assets_index: &AssetIndex) -> Result<()> { + bail!("Not yet implemented") } \ No newline at end of file diff --git a/src-tauri/src/launcher/mod.rs b/src-tauri/src/launcher/mod.rs index bb49564..0129b9a 100644 --- a/src-tauri/src/launcher/mod.rs +++ b/src-tauri/src/launcher/mod.rs @@ -1,16 +1,15 @@ mod manifest; -use std::path::{Path, self}; +use std::path::{Path, self, PathBuf}; use anyhow::{Result, bail}; use reqwest::{Client, StatusCode}; use serde::{Serialize, Deserialize}; -use tauri::Manager; -use tokio::{fs, io::{AsyncWriteExt, AsyncSeekExt}}; +use tokio::{fs, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc}; use crate::authentification::GameProfile; -use self::manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName}; +use self::manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName, get_version_assets}; #[cfg(target_os="windows")] @@ -20,8 +19,8 @@ const ACTUAL_OS: OSName = OSName::Linux; #[cfg(target_os="macos")] const ACTUAL_OS: OSName = OSName::MacOsX; -#[derive(Clone, serde::Serialize)] -struct ProgressMessage { +#[derive(Clone, serde::Serialize, Debug)] +pub struct ProgressMessage { p_type: String, current: usize, total: usize, @@ -29,6 +28,7 @@ struct ProgressMessage { pub struct ClientOptions<'a> { pub authorization: GameProfile, + pub log_channel: mpsc::Sender, pub root_path: &'a Path, pub java_path: &'a Path, pub version_number: String, @@ -60,10 +60,11 @@ impl<'a> MinecraftClient<'_> { let manifest = get_version_manifest(&reqwest_client).await?; let version = get_version_from_manifest(&manifest, opts.version_number.clone(), &opts.version_type).await?; let details = get_version_detail(&reqwest_client, version).await?; + // let version_assets = get_version_assets(&details.asset_index).await?; Ok(details) } - pub async fn download_assets(&mut self, app: tauri::AppHandle) -> Result<()> { + pub async fn download_requirements(&mut self) -> Result<()> { // create root folder if it doesn't exist if !self.opts.root_path.exists() { fs::create_dir_all(self.opts.root_path).await?; @@ -72,6 +73,12 @@ impl<'a> MinecraftClient<'_> { if !lib.exists() { fs::create_dir(lib).await?; } + self.download_libraries(lib).await?; + self.opts.log_channel.closed().await; + Ok(()) + } + + async fn download_libraries(&mut self, lib: &PathBuf) -> Result<()> { self.filter_non_necessary_librairies(); let total = self.details.libraries.len(); for (progress, i) in self.details.libraries.iter().enumerate() { @@ -121,9 +128,8 @@ impl<'a> MinecraftClient<'_> { } else { println!("{} already downloaded", i.name); } - app.emit_all("progress", ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total })?; + self.opts.log_channel.send( ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total }).await?; } - Ok(()) } @@ -132,6 +138,10 @@ impl<'a> MinecraftClient<'_> { self.details.libraries.retain(|e| { Self::should_use_library(e) }); } + async fn download_assets(&mut self) -> Result<()> { + bail!("Not yet implemented") + } + fn should_use_library(library: &Library) -> bool { match &library.rules { Some(rules) => { diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index d5d7c73..0244372 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -11,7 +11,9 @@ use std::sync::Mutex; use authentification::{Authentification, Prompt, GameProfile}; use anyhow::Result; use directories::BaseDirs; -use launcher::{MinecraftClient, ClientOptions}; +use launcher::{MinecraftClient, ClientOptions, ProgressMessage}; +use tauri::Manager; +use tokio::sync::mpsc; struct CustomState (Option); @@ -54,8 +56,10 @@ async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex { - match client.download_assets(app).await { - Ok(_) => { - Ok("Content downloaded".to_string()) - }, - Err(err) => { - Err(err.to_string()) - } - } - }, - Err(err) => { - Err(err.to_string()) - } - } + let res = tokio::join!( + download_libraries(opts), + read_channel(receiver, app), + + ); + res.0 } else { Err("Cannot download files".to_string()) } } + +async fn download_libraries(opts: ClientOptions<'_>) -> Result { + let client = MinecraftClient::new(&opts).await; + match client { + Ok(mut client) => { + match client.download_requirements().await { + Ok(_) => { + Ok("Content downloaded".to_string()) + }, + Err(err) => { + Err(err.to_string()) + } + } + }, + Err(err) => { + Err(err.to_string()) + } + } +} + +async fn read_channel(mut receiver: mpsc::Receiver, app: tauri::AppHandle) -> Result<()> { + loop { + match receiver.recv().await { + Some(msg) => app.emit_all("progress", msg)?, + None => break Ok(()) + } + } +} + #[tokio::main] async fn main() { tauri::Builder::default()