325 lines
10 KiB
Rust
325 lines
10 KiB
Rust
use crate::https;
|
|
use crate::java;
|
|
use crate::system_dirs::{
|
|
get_data_directory, get_java_executable, get_local_data_directory, get_prism_executable,
|
|
};
|
|
use crate::util;
|
|
use reqwest::IntoUrl;
|
|
use serde::de::value::Error;
|
|
use serde::Deserialize;
|
|
use serde::Serialize;
|
|
use serde_json::Value;
|
|
use std::fs;
|
|
use std::fs::File;
|
|
use std::io::{Read, Seek, Write};
|
|
use std::process::Command;
|
|
use std::time::Duration;
|
|
use std::{env, thread};
|
|
use std::{io::Cursor, path::PathBuf};
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct ModpackEntry {
|
|
pub name: String,
|
|
pub id: String,
|
|
pub last_updated: String,
|
|
}
|
|
|
|
#[derive(Serialize, Deserialize, Clone)]
|
|
pub struct VersionEntry {
|
|
pub Version: String,
|
|
pub File: String,
|
|
pub Date: String,
|
|
}
|
|
|
|
async fn get_modpack_name(id: String) -> String {
|
|
let modpacks = get_modpacks().await;
|
|
let mut instance_name = String::new();
|
|
for pack in modpacks {
|
|
if pack.id == id {
|
|
instance_name = pack.name;
|
|
}
|
|
}
|
|
return instance_name;
|
|
}
|
|
|
|
async fn check_modpack_needs_update(id: String) -> bool {
|
|
let mut instance_name = get_modpack_name(id.clone()).await;
|
|
if !get_local_data_directory()
|
|
.join("prism")
|
|
.join("instances")
|
|
.join(&mut instance_name)
|
|
.exists()
|
|
{
|
|
return true;
|
|
}
|
|
|
|
let versions = get_versions(id).await;
|
|
if !versions.is_ok() {
|
|
return false;
|
|
}
|
|
let versions = versions.unwrap();
|
|
let latest = versions[versions.len() - 1].Version.clone();
|
|
|
|
let mut file = File::open(
|
|
get_local_data_directory()
|
|
.join("prism")
|
|
.join("instances")
|
|
.join(instance_name)
|
|
.join(".minecraft")
|
|
.join("version.txt"),
|
|
)
|
|
.unwrap();
|
|
let mut current = String::new();
|
|
file.read_to_string(&mut current);
|
|
|
|
if latest != current {
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn launch_modpack(window: tauri::AppHandle, id: String) {
|
|
if check_modpack_needs_update(id.clone()).await {
|
|
install_modpack(window, id.clone()).await;
|
|
}
|
|
// Launch
|
|
let mut child = Command::new(
|
|
get_local_data_directory()
|
|
.join("prism")
|
|
.join(get_prism_executable()),
|
|
)
|
|
.arg("-l")
|
|
.arg(get_modpack_name(id).await)
|
|
.spawn()
|
|
.unwrap();
|
|
}
|
|
|
|
async fn install_modpack(window: tauri::AppHandle, id: String) {
|
|
let versions = get_versions(id.clone()).await.unwrap();
|
|
let path = env::temp_dir().join(format!("{}.mrpack", get_modpack_name(id.clone()).await));
|
|
let mut file = File::create(path.clone()).unwrap();
|
|
let ftp_path = PathBuf::new()
|
|
.join(id.clone())
|
|
.join(versions[versions.len() - 1].File.clone().as_str());
|
|
println!("Downloading file {}", ftp_path.to_str().unwrap());
|
|
//ftp::ftp_retr(Some(window.clone()), ftp_path, &mut file, |window, data, size| util::download_callback(name.clone(), window, data, size)).unwrap();
|
|
https::download(
|
|
Some(window.clone()),
|
|
format!(
|
|
"https://gitea.piwalker.net/fclauncher/{}/{}",
|
|
id.clone(),
|
|
versions[versions.len() - 1].File.clone()
|
|
),
|
|
&mut file,
|
|
get_modpack_name(id.clone()).await,
|
|
)
|
|
.await;
|
|
let mut child = Command::new(
|
|
get_local_data_directory()
|
|
.join("prism")
|
|
.join(get_prism_executable()),
|
|
)
|
|
.arg("-I")
|
|
.arg(path)
|
|
.spawn()
|
|
.unwrap();
|
|
loop {
|
|
let version_path = get_local_data_directory()
|
|
.join("prism")
|
|
.join("instances")
|
|
.join(get_modpack_name(id.clone()).await)
|
|
.join(".minecraft")
|
|
.join("version.txt");
|
|
if version_path.clone().exists() {
|
|
let mut ver_file = File::open(version_path).unwrap();
|
|
let mut buf = String::new();
|
|
ver_file.read_to_string(&mut buf).unwrap();
|
|
if buf == versions[versions.len() - 1].Version.clone().as_str() {
|
|
break;
|
|
}
|
|
}
|
|
thread::sleep(Duration::from_secs(3));
|
|
}
|
|
thread::sleep(Duration::from_secs(1));
|
|
child.kill();
|
|
let info_path = get_local_data_directory()
|
|
.join("prism")
|
|
.join("instances")
|
|
.join(get_modpack_name(id.clone()).await)
|
|
.join("mmc-pack.json");
|
|
let mut info_file = File::open(info_path.clone()).unwrap();
|
|
let info_json: Value = serde_json::from_reader(info_file).unwrap();
|
|
let mut mc_version = "0.0";
|
|
for component in info_json["components"].as_array().unwrap() {
|
|
if component["uid"] == "net.minecraft" {
|
|
mc_version = component["version"].as_str().unwrap();
|
|
}
|
|
}
|
|
let java = get_java_version(mc_version);
|
|
java::install_java(java, window.clone()).await;
|
|
|
|
let option_path = get_local_data_directory()
|
|
.join("prism")
|
|
.join("instances")
|
|
.join(get_modpack_name(id.clone()).await)
|
|
.join("instance.cfg");
|
|
let mut option_file = File::open(option_path.clone()).unwrap();
|
|
let mut buf = String::new();
|
|
option_file.read_to_string(&mut buf);
|
|
let mut option_file = File::create(option_path).unwrap();
|
|
let mut set = false;
|
|
for line in buf.lines() {
|
|
if line.starts_with("JavaPath=") {
|
|
option_file.write_all(
|
|
format!(
|
|
"JavaPath={}/java-{}-{}/bin/{}\n",
|
|
get_local_data_directory()
|
|
.join("java")
|
|
.into_os_string()
|
|
.to_str()
|
|
.unwrap()
|
|
.replace("\\", "/"),
|
|
java,
|
|
if env::consts::OS == "windows" {
|
|
"win"
|
|
} else {
|
|
"lin"
|
|
},
|
|
get_java_executable()
|
|
)
|
|
.as_bytes(),
|
|
);
|
|
set = true;
|
|
} else {
|
|
option_file.write_all(format!("{}\n", line).as_bytes());
|
|
}
|
|
}
|
|
if !set {
|
|
option_file.write_all(
|
|
format!(
|
|
"JavaPath={}/java-{}-{}/bin/{}\n",
|
|
get_local_data_directory()
|
|
.join("java")
|
|
.into_os_string()
|
|
.to_str()
|
|
.unwrap()
|
|
.replace("\\", "/"),
|
|
java,
|
|
if env::consts::OS == "windows" {
|
|
"win"
|
|
} else {
|
|
"lin"
|
|
},
|
|
get_java_executable()
|
|
)
|
|
.as_bytes(),
|
|
);
|
|
option_file.write_all("OverrideJavaLocation=true\n".as_bytes());
|
|
option_file.write_all("OverrideJava=true\n".as_bytes());
|
|
}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn get_modpacks() -> Vec<ModpackEntry> {
|
|
//unsafe{
|
|
let mut modpacks: Vec<ModpackEntry> = Vec::new();
|
|
//if modpacks.is_empty() {
|
|
let mut buf = Cursor::new(vec![]);
|
|
//ftp::ftp_retr(None, PathBuf::new().join("modpacks.json"), &mut buf, |_, _, _| return);
|
|
https::download(
|
|
None,
|
|
format!("https://gitea.piwalker.net/fclauncher/modpacks.json"),
|
|
&mut buf,
|
|
format!("modpacks.json"),
|
|
)
|
|
.await;
|
|
buf.rewind();
|
|
let res = serde_json::from_reader(buf);
|
|
if !res.is_ok() {
|
|
println!("Result not ok!");
|
|
let paths =
|
|
fs::read_dir(get_local_data_directory().join("prism").join("instances")).unwrap();
|
|
for path in paths {
|
|
let path = path.unwrap();
|
|
if fs::metadata(path.path()).unwrap().is_file() {
|
|
continue;
|
|
}
|
|
let name = path.file_name().into_string().unwrap();
|
|
if name.starts_with(".") {
|
|
continue;
|
|
}
|
|
|
|
modpacks.push(ModpackEntry {
|
|
name: name.clone(),
|
|
id: name,
|
|
last_updated: format!(""),
|
|
})
|
|
}
|
|
return modpacks.clone();
|
|
}
|
|
let modpacks: Vec<ModpackEntry> = res.unwrap();
|
|
//println!("{}", v[0].name);
|
|
//for pack in v.as_array().unwrap() {
|
|
//modpacks.push(ModpackEntry{name: pack["name"].as_str().unwrap().to_string(), id: pack["id"].as_str().unwrap().to_string(), last_updated: pack["last-updated"].as_str().unwrap().to_string()});
|
|
//}
|
|
//}
|
|
return modpacks.clone();
|
|
//}
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn get_versions(id: String) -> Result<Vec<VersionEntry>, String> {
|
|
let mut versions: Vec<VersionEntry> = Vec::new();
|
|
let mut buf = Cursor::new(vec![]);
|
|
//ftp::ftp_retr(None, PathBuf::new().join(id).join("versions.json"), &mut buf, |_, _, _| return);
|
|
https::download(
|
|
None,
|
|
format!(
|
|
"https://gitea.piwalker.net/fclauncher/{}/versions.json",
|
|
id.clone()
|
|
),
|
|
&mut buf,
|
|
format!("{}/versions.json", id.clone()),
|
|
)
|
|
.await;
|
|
buf.rewind();
|
|
let versions: Vec<VersionEntry> =
|
|
serde_json::from_reader(buf).or(Err(format!("Unable to parse json")))?;
|
|
//for version in v.as_array().unwrap() {
|
|
//versions.push(VersionEntry{version: version["Version"].as_str().unwrap().to_string(), file: version["File"].as_str().unwrap().to_string(), date: version["Date"].as_str().unwrap().to_string()});
|
|
//}
|
|
return Ok(versions.clone());
|
|
}
|
|
|
|
fn get_java_version(mc_version: &str) -> u8 {
|
|
let components: Vec<&str> = mc_version.split(".").collect();
|
|
let mut java = 8;
|
|
if components[1] == "17" {
|
|
java = 17
|
|
} else if components[1] == "18" || components[1] == "19" {
|
|
java = 17
|
|
} else if components[1].parse::<i32>().unwrap() > 19 {
|
|
if components[1] == "20" && components[1].parse::<i32>().unwrap() < 5 {
|
|
java = 17
|
|
} else {
|
|
java = 21
|
|
}
|
|
}
|
|
return java;
|
|
}
|
|
|
|
#[tauri::command]
|
|
pub async fn get_latest_version(id: String) -> Result<String, String> {
|
|
let versions = get_versions(id).await.unwrap();
|
|
if (versions.len() == 0) {
|
|
return Ok(format!(""));
|
|
}
|
|
Ok(versions[versions.len() - 1].Version.clone())
|
|
}
|
|
|
|
//pub fn create_json(modpacks: Vec<ModpackEntry>) -> Result<serde_json::Value, String> {
|
|
|
|
//}
|