Fix softlock, add assets download

This commit is contained in:
Quentin Legot 2023-05-01 01:58:37 +02:00
parent 7a4eb4694b
commit cdbf1bdcef
4 changed files with 44 additions and 42 deletions

View File

@ -123,7 +123,6 @@ impl Authentification {
received = listener => { received = listener => {
match received { match received {
Ok(received) => { Ok(received) => {
println!("received code");
second_window.close()?; second_window.close()?;
if received.state != state { if received.state != state {
@ -137,7 +136,6 @@ impl Authentification {
} }
}, },
_ = receiver.recv() => { _ = receiver.recv() => {
println!("window closed");
bail!("You closed the window before completion") bail!("You closed the window before completion")
} }
} }

View File

@ -64,7 +64,7 @@ pub struct VersionDetail {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct AssetIndex { pub struct AssetIndex {
pub id: i32, pub id: String,
pub sha1: String, pub sha1: String,
pub size: usize, pub size: usize,
#[serde(rename(serialize = "totalSize", deserialize = "totalSize"))] #[serde(rename(serialize = "totalSize", deserialize = "totalSize"))]
@ -130,7 +130,7 @@ pub struct AssetsManifest {
#[derive(Serialize, Deserialize)] #[derive(Serialize, Deserialize)]
pub struct AssetObject { pub struct AssetObject {
pub hash: String, pub hash: String,
pub size: usize, pub size: u64,
} }
pub async fn get_version_assets(reqwest: &Client , assets_index: &AssetIndex) -> Result<AssetsManifest> { pub async fn get_version_assets(reqwest: &Client , assets_index: &AssetIndex) -> Result<AssetsManifest> {

View File

@ -5,7 +5,7 @@ use std::path::{Path, self, PathBuf};
use anyhow::{Result, bail}; use anyhow::{Result, bail};
use reqwest::{Client, StatusCode}; use reqwest::{Client, StatusCode};
use serde::{Serialize, Deserialize}; use serde::{Serialize, Deserialize};
use tokio::{fs, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc}; use tokio::{fs::{self, File}, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
use crate::authentification::GameProfile; use crate::authentification::GameProfile;
@ -82,7 +82,7 @@ impl<'a> MinecraftClient<'_> {
fs::create_dir_all(asset).await?; fs::create_dir_all(asset).await?;
} }
self.download_libraries(lib).await?; self.download_libraries(lib).await?;
self.opts.log_channel.closed().await; self.download_assets(asset).await?;
Ok(()) Ok(())
} }
@ -97,15 +97,7 @@ impl<'a> MinecraftClient<'_> {
let p = &lib.join(p); let p = &lib.join(p);
fs::create_dir_all(p).await?; fs::create_dir_all(p).await?;
let file_path = p.join(filename); let file_path = p.join(filename);
let mut file = if (&file_path).exists() { let mut file = Self::select_file_option(&file_path, i.downloads.artifact.size).await?;
let f = fs::File::open(&file_path).await;
match f {
Ok(mut f) => { if f.seek(std::io::SeekFrom::End(0)).await? == i.downloads.artifact.size { f } else { fs::File::create(file_path).await? } },
Err(err) => bail!(err),
}
} else {
fs::File::create(file_path).await?
};
let size = file.seek(std::io::SeekFrom::End(0)).await?; let size = file.seek(std::io::SeekFrom::End(0)).await?;
file.seek(std::io::SeekFrom::Start(0)).await?; file.seek(std::io::SeekFrom::Start(0)).await?;
@ -136,19 +128,31 @@ impl<'a> MinecraftClient<'_> {
} else { } else {
println!("{} already downloaded", i.name); println!("{} already downloaded", i.name);
} }
println!("Sending message");
self.opts.log_channel.send( ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total }).await?; self.opts.log_channel.send( ProgressMessage { p_type: "libraries".to_string(), current: progress + 1, total }).await?;
} }
Ok(()) Ok(())
} }
async fn select_file_option(file_path: &PathBuf, expected_size: u64) -> Result<File> {
if (&file_path).exists() {
let f = fs::File::open(&file_path).await;
match f {
Ok(mut f) => { if f.seek(std::io::SeekFrom::End(0)).await? == expected_size { Ok(f) } else { Ok(fs::File::create(file_path).await?) } },
Err(err) => bail!(err),
}
} else {
Ok(fs::File::create(file_path).await?)
}
}
/// Filter non necessary librairies for the current OS /// Filter non necessary librairies for the current OS
fn filter_non_necessary_librairies(&mut self) { fn filter_non_necessary_librairies(&mut self) {
self.details.libraries.retain(|e| { Self::should_use_library(e) }); self.details.libraries.retain(|e| { Self::should_use_library(e) });
} }
async fn download_assets(&mut self, object_folder: PathBuf) -> Result<()> { async fn download_assets(&mut self, object_folder: &PathBuf) -> Result<()> {
for (_, (key, value)) in self.assets.objects.iter().enumerate() { let total: usize = self.assets.objects.len();
for (progress, (_, value)) in self.assets.objects.iter().enumerate() {
let hash = value.hash.clone(); let hash = value.hash.clone();
let two_hex = hash.chars().take(2).collect::<String>(); let two_hex = hash.chars().take(2).collect::<String>();
let hex_folder = object_folder.join(&two_hex); let hex_folder = object_folder.join(&two_hex);
@ -157,26 +161,26 @@ impl<'a> MinecraftClient<'_> {
} }
let file_path = hex_folder.join(&hash); let file_path = hex_folder.join(&hash);
let mut file = if (&file_path).exists() { let mut file = Self::select_file_option(&file_path, value.size).await?;
let f = fs::File::open(&file_path).await; let size = file.seek(std::io::SeekFrom::End(0)).await?;
match f { file.seek(std::io::SeekFrom::Start(0)).await?;
Ok(f) => f,
Err(err) => bail!(err),
}
} else {
fs::File::create(file_path).await?
};
let url = format!("https://resources.download.minecraft.net/{}/{}", two_hex, hash); if size != value.size {
let received = self.reqwest_client let url = format!("https://resources.download.minecraft.net/{}/{}", two_hex, hash);
.get(url) let received = self.reqwest_client
.send() .get(url)
.await? .send()
.bytes() .await?
.await?; .bytes()
.await?;
file.write_all(&received).await?;
println!("{} downloaded", value.hash);
} else {
println!("{} already downloaded", value.hash);
}
self.opts.log_channel.send( ProgressMessage { p_type: "assets".to_string(), current: progress + 1, total }).await?;
} }
bail!("Not yet implemented") Ok(())
} }
fn should_use_library(library: &Library) -> bool { fn should_use_library(library: &Library) -> bool {

View File

@ -45,7 +45,6 @@ async fn login(app: tauri::AppHandle, _window: tauri::Window, state: tauri::Stat
#[tauri::command] #[tauri::command]
async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomState>>) -> Result<String, String> { async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomState>>) -> Result<String, String> {
println!("starting download");
if let Some(base_dir) = BaseDirs::new() { if let Some(base_dir) = BaseDirs::new() {
let data_folder = base_dir.data_dir().join(".altarik_test"); let data_folder = base_dir.data_dir().join(".altarik_test");
let root_path = data_folder.as_path(); let root_path = data_folder.as_path();
@ -71,10 +70,8 @@ async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomSta
let res = tokio::join!( let res = tokio::join!(
download_libraries(opts), download_libraries(opts),
read_channel(receiver, app), read_channel(receiver, app),
); );
res.0 res.0
} else { } else {
Err("Cannot download files".to_string()) Err("Cannot download files".to_string())
} }
@ -83,7 +80,7 @@ async fn download(app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomSta
async fn download_libraries(opts: ClientOptions<'_>) -> Result<String, String> { async fn download_libraries(opts: ClientOptions<'_>) -> Result<String, String> {
let client = MinecraftClient::new(&opts).await; let client = MinecraftClient::new(&opts).await;
match client { let res = match client {
Ok(mut client) => { Ok(mut client) => {
match client.download_requirements().await { match client.download_requirements().await {
Ok(_) => { Ok(_) => {
@ -97,13 +94,16 @@ async fn download_libraries(opts: ClientOptions<'_>) -> Result<String, String> {
Err(err) => { Err(err) => {
Err(err.to_string()) Err(err.to_string())
} }
} };
opts.log_channel.closed().await;
res
} }
async fn read_channel(mut receiver: mpsc::Receiver<ProgressMessage>, app: tauri::AppHandle) -> Result<()> { async fn read_channel(mut receiver: mpsc::Receiver<ProgressMessage>, app: tauri::AppHandle) -> Result<()> {
loop { loop {
match receiver.recv().await { match receiver.recv().await {
Some(msg) => { println!("received {:?}", msg); app.emit_all("progress", msg)? }, Some(msg) => { app.emit_all("progress", msg)? },
None => break Ok(()) None => break Ok(())
} }
} }