Added downloading java
This commit is contained in:
parent
6ec89497cb
commit
affa6d8535
25
src-tauri/Cargo.lock
generated
25
src-tauri/Cargo.lock
generated
@ -68,6 +68,17 @@ version = "1.6.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
checksum = "bddcadddf5e9015d310179a59bb28c4d4b9920ad0f11e8e14dbadf654890c9a6"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "async-trait"
|
||||||
|
version = "0.1.73"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "bc00ceb34980c03614e35a3a4e218276a0a824e911d07651cd0d858a51e8c0f0"
|
||||||
|
dependencies = [
|
||||||
|
"proc-macro2",
|
||||||
|
"quote",
|
||||||
|
"syn 2.0.37",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "atk"
|
name = "atk"
|
||||||
version = "0.15.1"
|
version = "0.15.1"
|
||||||
@ -1593,6 +1604,7 @@ dependencies = [
|
|||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
|
"sha256",
|
||||||
"tauri",
|
"tauri",
|
||||||
"tauri-build",
|
"tauri-build",
|
||||||
"tokio",
|
"tokio",
|
||||||
@ -2890,6 +2902,19 @@ dependencies = [
|
|||||||
"digest",
|
"digest",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "sha256"
|
||||||
|
version = "1.4.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "7895c8ae88588ccead14ff438b939b0c569cd619116f14b4d13fdff7b8333386"
|
||||||
|
dependencies = [
|
||||||
|
"async-trait",
|
||||||
|
"bytes",
|
||||||
|
"hex",
|
||||||
|
"sha2",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "sharded-slab"
|
name = "sharded-slab"
|
||||||
version = "0.1.6"
|
version = "0.1.6"
|
||||||
|
@ -26,6 +26,7 @@ warp = "0.3.3"
|
|||||||
anyhow = "1.0.66"
|
anyhow = "1.0.66"
|
||||||
rand = "0.8.5"
|
rand = "0.8.5"
|
||||||
directories = "5.0.0"
|
directories = "5.0.0"
|
||||||
|
sha256 = "1.4.0"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# by default Tauri runs in production mode
|
# by default Tauri runs in production mode
|
||||||
|
@ -106,6 +106,7 @@ pub enum OSName {
|
|||||||
Windows
|
Windows
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
pub struct LibraryArtifact {
|
pub struct LibraryArtifact {
|
||||||
pub path: String,
|
pub path: String,
|
||||||
|
@ -6,11 +6,11 @@ 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::{self, File}, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
|
use tokio::{fs::{self, File, OpenOptions}, io::{AsyncWriteExt, AsyncSeekExt}, sync::mpsc};
|
||||||
|
|
||||||
use crate::authentification::GameProfile;
|
use crate::authentification::GameProfile;
|
||||||
|
|
||||||
use self::manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName, get_version_assets, AssetsManifest};
|
use self::{manifest::{VersionDetail, get_version_manifest, get_version_from_manifest, get_version_detail, Library, OSName, get_version_assets, AssetsManifest}, altarik::Chapter};
|
||||||
|
|
||||||
|
|
||||||
#[cfg(target_os="windows")]
|
#[cfg(target_os="windows")]
|
||||||
@ -20,6 +20,9 @@ const ACTUAL_OS: OSName = OSName::Linux;
|
|||||||
#[cfg(target_os="macos")]
|
#[cfg(target_os="macos")]
|
||||||
const ACTUAL_OS: OSName = OSName::MacOsX;
|
const ACTUAL_OS: OSName = OSName::MacOsX;
|
||||||
|
|
||||||
|
#[cfg(not(any(target_arch="x86_64", target_arch="x86")))]
|
||||||
|
compile_error!("Your architecture is not supported");
|
||||||
|
|
||||||
#[derive(Clone, serde::Serialize, Debug)]
|
#[derive(Clone, serde::Serialize, Debug)]
|
||||||
pub struct ProgressMessage {
|
pub struct ProgressMessage {
|
||||||
p_type: String,
|
p_type: String,
|
||||||
@ -32,6 +35,7 @@ pub struct ClientOptions<'a> {
|
|||||||
pub log_channel: mpsc::Sender<ProgressMessage>,
|
pub log_channel: mpsc::Sender<ProgressMessage>,
|
||||||
pub root_path: &'a Path,
|
pub root_path: &'a Path,
|
||||||
pub java_path: &'a Path,
|
pub java_path: &'a Path,
|
||||||
|
/// deprecated, will be remove
|
||||||
pub version_number: String,
|
pub version_number: String,
|
||||||
pub version_type: VersionType,
|
pub version_type: VersionType,
|
||||||
// version_custom: String, // for a next update
|
// version_custom: String, // for a next update
|
||||||
@ -73,7 +77,8 @@ impl<'a> MinecraftClient<'_> {
|
|||||||
let folders = vec![
|
let folders = vec![
|
||||||
self.opts.root_path.join("libraries"),
|
self.opts.root_path.join("libraries"),
|
||||||
self.opts.root_path.join("assets").join("objects"),
|
self.opts.root_path.join("assets").join("objects"),
|
||||||
self.opts.root_path.join("assets").join("indexes")
|
self.opts.root_path.join("assets").join("indexes"),
|
||||||
|
self.opts.root_path.join("runtime").join("download"),
|
||||||
];
|
];
|
||||||
let mut tasks = Vec::with_capacity(folders.len());
|
let mut tasks = Vec::with_capacity(folders.len());
|
||||||
for folder in folders {
|
for folder in folders {
|
||||||
@ -102,18 +107,73 @@ impl<'a> MinecraftClient<'_> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub async fn download_requirements(&mut self) -> Result<()> {
|
pub async fn download_requirements(&mut self, chapter: Chapter) -> Result<()> {
|
||||||
// create root folder if it doesn't exist
|
// create root folder if it doesn't exist
|
||||||
self.create_dirs().await?;
|
self.create_dirs().await?;
|
||||||
let lib = &self.opts.root_path.join("libraries");
|
let lib = &self.opts.root_path.join("libraries");
|
||||||
let asset = &self.opts.root_path.join("assets").join("objects");
|
let asset = &self.opts.root_path.join("assets").join("objects");
|
||||||
self.save_version_index().await?;
|
self.save_version_index().await?;
|
||||||
|
self.download_java(chapter).await?;
|
||||||
self.download_libraries(lib).await?;
|
self.download_libraries(lib).await?;
|
||||||
self.download_assets(asset).await?;
|
self.download_assets(asset).await?;
|
||||||
self.opts.log_channel.send(ProgressMessage { p_type: "completed".to_string(), current: 0, total: 0 }).await?;
|
self.opts.log_channel.send(ProgressMessage { p_type: "completed".to_string(), current: 0, total: 0 }).await?;
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn download_java(&mut self, chapter: Chapter) -> Result<()> {
|
||||||
|
let download_path = self.opts.root_path.join("runtime").join("download");
|
||||||
|
// let extract_path = self.opts.root_path.join("runtime");
|
||||||
|
let (url, extension) = match ACTUAL_OS {
|
||||||
|
OSName::Linux => {
|
||||||
|
(chapter.java.platform.linux, "tar.gz")
|
||||||
|
},
|
||||||
|
OSName::Windows => {
|
||||||
|
(chapter.java.platform.win32, "zip")
|
||||||
|
},
|
||||||
|
_ => {
|
||||||
|
bail!("Your current is not supported")
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let url = match url {
|
||||||
|
Some(url) => url,
|
||||||
|
None => bail!("No available executable available for your platform")
|
||||||
|
};
|
||||||
|
|
||||||
|
let filepath = download_path.join(format!("{}.{}", url.x64.name.clone(), extension));
|
||||||
|
let mut should_download = false;
|
||||||
|
if !filepath.exists() {
|
||||||
|
should_download = true;
|
||||||
|
} else {
|
||||||
|
let hash = sha256::try_digest(filepath.clone());
|
||||||
|
match hash {
|
||||||
|
Ok(hash) => {
|
||||||
|
if hash != url.x64.sha256sum {
|
||||||
|
println!("Hash of java archive is not correct, redownloading");
|
||||||
|
should_download = true;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(_) => should_download = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if should_download {
|
||||||
|
println!("Downloading java");
|
||||||
|
if filepath.exists() {
|
||||||
|
fs::remove_file(filepath.clone()).await?; // remove content before writing and appending to it
|
||||||
|
}
|
||||||
|
let mut file = OpenOptions::new()
|
||||||
|
.write(true)
|
||||||
|
.create(true)
|
||||||
|
.open(filepath)
|
||||||
|
.await?;
|
||||||
|
let b = self.reqwest_client.get(url.x64.link.clone()).send().await?.bytes().await?;
|
||||||
|
file.write(&b).await?;
|
||||||
|
println!("{} downloaded", url.x64.name)
|
||||||
|
} else {
|
||||||
|
println!("{} already downloaded", url.x64.name)
|
||||||
|
}
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
async fn download_libraries(&mut self, lib: &PathBuf) -> Result<()> {
|
async fn download_libraries(&mut self, lib: &PathBuf) -> Result<()> {
|
||||||
self.filter_non_necessary_librairies();
|
self.filter_non_necessary_librairies();
|
||||||
let total = self.details.libraries.len();
|
let total = self.details.libraries.len();
|
||||||
|
@ -11,7 +11,7 @@ use std::sync::Mutex;
|
|||||||
use authentification::{Authentification, Prompt, GameProfile};
|
use authentification::{Authentification, Prompt, GameProfile};
|
||||||
use anyhow::Result;
|
use anyhow::Result;
|
||||||
use directories::BaseDirs;
|
use directories::BaseDirs;
|
||||||
use launcher::{MinecraftClient, ClientOptions, ProgressMessage, altarik::AltarikManifest};
|
use launcher::{MinecraftClient, ClientOptions, ProgressMessage, altarik::{AltarikManifest, Chapter}};
|
||||||
use reqwest::Client;
|
use reqwest::Client;
|
||||||
use tauri::Manager;
|
use tauri::Manager;
|
||||||
use tokio::sync::mpsc;
|
use tokio::sync::mpsc;
|
||||||
@ -62,7 +62,23 @@ async fn load_altarik_manifest(state: tauri::State<'_, Mutex<CustomState>>) -> R
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
async fn download(game_version: String, app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomState>>) -> Result<String, String> {
|
async fn download(selected_chapter: usize, app: tauri::AppHandle, state: tauri::State<'_, Mutex<CustomState>>) -> Result<String, String> {
|
||||||
|
let chapter = match state.lock() {
|
||||||
|
Ok(lock) => {
|
||||||
|
match &lock.1 {
|
||||||
|
Some(manifest) => {
|
||||||
|
match manifest.chapters.get(selected_chapter) {
|
||||||
|
Some(val) => {
|
||||||
|
val.clone()
|
||||||
|
},
|
||||||
|
None => return Err("Selected chapter doesn't exist".to_string())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
None => return Err("Cannot load altarik manifest".to_string())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
Err(err) => return Err(err.to_string())
|
||||||
|
};
|
||||||
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();
|
||||||
@ -80,14 +96,14 @@ async fn download(game_version: String, app: tauri::AppHandle, state: tauri::Sta
|
|||||||
log_channel: sender.clone(),
|
log_channel: sender.clone(),
|
||||||
root_path,
|
root_path,
|
||||||
java_path: &java_path.as_path(),
|
java_path: &java_path.as_path(),
|
||||||
version_number: game_version,
|
version_number: chapter.minecraft_version.clone(),
|
||||||
version_type: launcher::VersionType::Release,
|
version_type: launcher::VersionType::Release,
|
||||||
memory_min: "2G".to_string(),
|
memory_min: "2G".to_string(),
|
||||||
memory_max: "4G".to_string(),
|
memory_max: "4G".to_string(),
|
||||||
};
|
};
|
||||||
drop(sender);
|
drop(sender);
|
||||||
let res = tokio::join!(
|
let res = tokio::join!(
|
||||||
download_libraries(opts),
|
download_libraries(opts, chapter),
|
||||||
read_channel(receiver, app),
|
read_channel(receiver, app),
|
||||||
);
|
);
|
||||||
res.0
|
res.0
|
||||||
@ -97,11 +113,11 @@ async fn download(game_version: String, app: tauri::AppHandle, state: tauri::Sta
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
async fn download_libraries(opts: ClientOptions<'_>) -> Result<String, String> {
|
async fn download_libraries(opts: ClientOptions<'_>, chapter: Chapter) -> Result<String, String> {
|
||||||
let client = MinecraftClient::new(&opts).await;
|
let client = MinecraftClient::new(&opts).await;
|
||||||
let res = match client {
|
let res = match client {
|
||||||
Ok(mut client) => {
|
Ok(mut client) => {
|
||||||
match client.download_requirements().await {
|
match client.download_requirements(chapter).await {
|
||||||
Ok(_) => {
|
Ok(_) => {
|
||||||
Ok("Content downloaded".to_string())
|
Ok("Content downloaded".to_string())
|
||||||
},
|
},
|
||||||
|
@ -55,7 +55,7 @@ export default function LoginPage() {
|
|||||||
async function download() {
|
async function download() {
|
||||||
if(isLogged) {
|
if(isLogged) {
|
||||||
if(selectedChapter !== -1 && altarikManifest !== undefined) {
|
if(selectedChapter !== -1 && altarikManifest !== undefined) {
|
||||||
invoke("download", { gameVersion: altarikManifest?.chapters[selectedChapter].minecraftVersion }).then(value => {
|
invoke("download", { selectedChapter: selectedChapter }).then(value => {
|
||||||
setGreetMessage(String(value))
|
setGreetMessage(String(value))
|
||||||
}).catch(err => {
|
}).catch(err => {
|
||||||
console.log("An error occured")
|
console.log("An error occured")
|
||||||
|
Reference in New Issue
Block a user