Changed FTP access to HTTPS access
This commit is contained in:
parent
d5ce6e4fc8
commit
f88a5bffe1
@ -22,6 +22,8 @@ dirs = "5.0.1"
|
|||||||
gethostname = "0.4.3"
|
gethostname = "0.4.3"
|
||||||
self_update = "0.40.0"
|
self_update = "0.40.0"
|
||||||
parking_lot = "0.12.3"
|
parking_lot = "0.12.3"
|
||||||
|
reqwest = { version = "0.12.5", features = ["stream"] }
|
||||||
|
futures-util = "0.3.30"
|
||||||
|
|
||||||
[features]
|
[features]
|
||||||
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
# This feature is used for production builds or when a dev server is not specified, DO NOT REMOVE!!
|
||||||
|
@ -1,15 +1,13 @@
|
|||||||
use crate::ftp::{self, test_cred};
|
|
||||||
|
|
||||||
static USERNAME: parking_lot::Mutex<String> = parking_lot::const_mutex(String::new());
|
static USERNAME: parking_lot::Mutex<String> = parking_lot::const_mutex(String::new());
|
||||||
static PASSWORD: parking_lot::Mutex<String> = parking_lot::const_mutex(String::new());
|
static PASSWORD: parking_lot::Mutex<String> = parking_lot::const_mutex(String::new());
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn login(username: String, password: String, window: tauri::Window) {
|
pub fn login(username: String, password: String, window: tauri::Window) {
|
||||||
if(test_cred(username.as_str(), password.as_str())){
|
//if(test_cred(username.as_str(), password.as_str())){
|
||||||
*USERNAME.lock() = username;
|
//*USERNAME.lock() = username;
|
||||||
*PASSWORD.lock() = password;
|
//*PASSWORD.lock() = password;
|
||||||
window.emit("Login_Success", {});
|
//window.emit("Login_Success", {});
|
||||||
}else{
|
//}else{
|
||||||
window.emit("Login_Failed", {});
|
window.emit("Login_Failed", {});
|
||||||
}
|
//}
|
||||||
}
|
}
|
39
FCLauncher/src-tauri/src/https.rs
Normal file
39
FCLauncher/src-tauri/src/https.rs
Normal file
@ -0,0 +1,39 @@
|
|||||||
|
use std::io::Write;
|
||||||
|
use std::path::PathBuf;
|
||||||
|
use futures_util::StreamExt;
|
||||||
|
use std::cmp::min;
|
||||||
|
use serde::Serialize;
|
||||||
|
|
||||||
|
|
||||||
|
#[derive(Clone, Serialize)]
|
||||||
|
pub struct DownloadStatus {
|
||||||
|
downloaded: usize,
|
||||||
|
total: usize,
|
||||||
|
time_elapsed: usize,
|
||||||
|
download_name: String
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
pub async fn download(window: Option<tauri::Window>, url: String , mut writer: impl Write, downloadName: String) -> Result<(), String> {
|
||||||
|
let client = reqwest::Client::new();
|
||||||
|
let res = client.get(url).send().await.or(Err(format!("Failed to fetch from URL!")))?;
|
||||||
|
let total_size = res.content_length().ok_or(format!("Failed to get content length"))?;
|
||||||
|
let mut downloaded: u64 = 0;
|
||||||
|
let mut stream = res.bytes_stream();
|
||||||
|
while let Some(item) = stream.next().await {
|
||||||
|
let chunk = item.or(Err(format!("Error while downloading file!")))?;
|
||||||
|
writer.write_all(&chunk).or(Err("Error writing to stream!"))?;
|
||||||
|
let new = min(downloaded + (chunk.len() as u64), total_size);
|
||||||
|
downloaded = new;
|
||||||
|
println!("Downloading {}: {}MB / {}MB", downloadName.clone(), downloaded/(1024*1024), total_size/(1024*1024));
|
||||||
|
if let Some(window) = window.clone() {
|
||||||
|
if downloaded != total_size {
|
||||||
|
window.emit("download_progress", DownloadStatus{downloaded: downloaded as usize, total: total_size as usize, time_elapsed: 0, download_name: downloadName.clone()}).or(Err(format!("Unable to signal window")))?;
|
||||||
|
} else {
|
||||||
|
window.emit("download_finished", true).or(Err(format!("Unable to signal window!")))?;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
@ -6,7 +6,7 @@ use tar::Archive;
|
|||||||
|
|
||||||
|
|
||||||
use crate::system_dirs::get_local_data_directory;
|
use crate::system_dirs::get_local_data_directory;
|
||||||
use crate::ftp::{self, ftp_get_size};
|
use crate::https;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
|
|
||||||
fn check_java(version: u8) -> bool {
|
fn check_java(version: u8) -> bool {
|
||||||
@ -14,14 +14,14 @@ fn check_java(version: u8) -> bool {
|
|||||||
dir.exists()
|
dir.exists()
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn install_java(version: u8, window: tauri::Window) {
|
pub async fn install_java(version: u8, window: tauri::Window) {
|
||||||
if check_java(version) {
|
if check_java(version) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
let ftp_dir = PathBuf::new().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"}));
|
//let ftp_dir = PathBuf::new().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"}));
|
||||||
let mut buff = Cursor::new(vec![]);
|
let mut buff = Cursor::new(vec![]);
|
||||||
ftp::ftp_retr(Some(window), ftp_dir, &mut buff, |window, data, size| util::download_callback(format!("Java {}", version), window,data, size)).unwrap();
|
//ftp::ftp_retr(Some(window), ftp_dir, &mut buff, |window, data, size| util::download_callback(format!("Java {}", version), window,data, size)).unwrap();
|
||||||
|
https::download(Some(window.clone()), format!("https://gitea.piwalker.net/fclauncher/java/java-{}-{}", version, if env::consts::OS == "windows" { "win.zip" } else {"lin.tar.gz"}), &mut buff, format!("Java {}", version)).await;
|
||||||
std::fs::create_dir_all(get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"}))).unwrap();
|
std::fs::create_dir_all(get_local_data_directory().join("java").join(format!("java-{}-{}", version, if env::consts::OS == "windows" { "win" } else {"lin"}))).unwrap();
|
||||||
buff.rewind().unwrap();
|
buff.rewind().unwrap();
|
||||||
if env::consts::OS != "windows" {
|
if env::consts::OS != "windows" {
|
||||||
|
@ -9,13 +9,14 @@ use serde_json::{Map, Result, Value};
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
|
|
||||||
mod ftp;
|
//mod ftp;
|
||||||
mod java;
|
mod java;
|
||||||
mod prism;
|
mod prism;
|
||||||
mod system_dirs;
|
mod system_dirs;
|
||||||
mod util;
|
mod util;
|
||||||
mod modpack;
|
mod modpack;
|
||||||
mod admin;
|
mod admin;
|
||||||
|
mod https;
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize)]
|
#[derive(Serialize, Deserialize)]
|
||||||
struct ModpackEntry{
|
struct ModpackEntry{
|
||||||
@ -31,7 +32,7 @@ fn greet(name: &str) -> String {
|
|||||||
|
|
||||||
|
|
||||||
fn main() {
|
fn main() {
|
||||||
modpack::get_modpacks();
|
//modpack::get_modpacks();
|
||||||
//prism::install_prism();
|
//prism::install_prism();
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.invoke_handler(tauri::generate_handler![greet, modpack::get_modpacks, modpack::launch_modpack, prism::launch_prism, prism::install_prism, admin::login])
|
.invoke_handler(tauri::generate_handler![greet, modpack::get_modpacks, modpack::launch_modpack, prism::launch_prism, prism::install_prism, admin::login])
|
||||||
|
@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
use crate::{ftp, java};
|
use crate::{java};
|
||||||
use crate::system_dirs::{get_data_directory, get_java_executable, get_local_data_directory, get_prism_executable};
|
use crate::system_dirs::{get_data_directory, get_java_executable, get_local_data_directory, get_prism_executable};
|
||||||
use std::time::Duration;
|
use std::time::Duration;
|
||||||
use std::{env, thread};
|
use std::{env, thread};
|
||||||
@ -7,12 +7,14 @@ use std::fs::File;
|
|||||||
use std::process::Command;
|
use std::process::Command;
|
||||||
use std::{io::Cursor, path::PathBuf};
|
use std::{io::Cursor, path::PathBuf};
|
||||||
use std::io::{Read, Seek, Write};
|
use std::io::{Read, Seek, Write};
|
||||||
|
use reqwest::IntoUrl;
|
||||||
use serde::de::value::Error;
|
use serde::de::value::Error;
|
||||||
use serde_json::Value;
|
use serde_json::Value;
|
||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
use serde::Deserialize;
|
use serde::Deserialize;
|
||||||
use crate::util;
|
use crate::util;
|
||||||
use std::fs;
|
use std::fs;
|
||||||
|
use crate::https;
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@ -29,8 +31,8 @@ pub struct VersionEntry{
|
|||||||
date: String
|
date: String
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_modpack_name(id: String) -> String {
|
async fn get_modpack_name(id: String) -> String {
|
||||||
let modpacks = get_modpacks();
|
let modpacks = get_modpacks().await;
|
||||||
let mut instance_name = String::new();
|
let mut instance_name = String::new();
|
||||||
for pack in modpacks {
|
for pack in modpacks {
|
||||||
if pack.id == id {
|
if pack.id == id {
|
||||||
@ -42,13 +44,13 @@ fn get_modpack_name(id: String) -> String {
|
|||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn check_modpack_needs_update(id: String) -> bool{
|
async fn check_modpack_needs_update(id: String) -> bool{
|
||||||
let mut instance_name = get_modpack_name(id.clone());
|
let mut instance_name = get_modpack_name(id.clone()).await;
|
||||||
if !get_local_data_directory().join("prism").join("instances").join(&mut instance_name).exists() {
|
if !get_local_data_directory().join("prism").join("instances").join(&mut instance_name).exists() {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
let versions = get_versions(id);
|
let versions = get_versions(id).await;
|
||||||
if !versions.is_ok() {
|
if !versions.is_ok() {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -70,23 +72,24 @@ fn check_modpack_needs_update(id: String) -> bool{
|
|||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub async fn launch_modpack(window: tauri::Window, id: String){
|
pub async fn launch_modpack(window: tauri::Window, id: String){
|
||||||
|
|
||||||
if check_modpack_needs_update(id.clone()) {
|
if check_modpack_needs_update(id.clone()).await {
|
||||||
install_modpack(window, id.clone());
|
install_modpack(window, id.clone()).await;
|
||||||
}
|
}
|
||||||
// Launch
|
// Launch
|
||||||
let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-l").arg(get_modpack_name(id)).spawn().unwrap();
|
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();
|
||||||
}
|
}
|
||||||
|
|
||||||
fn install_modpack(window: tauri::Window, id: String){
|
async fn install_modpack(window: tauri::Window, id: String){
|
||||||
let versions = get_versions(id.clone()).unwrap();
|
let versions = get_versions(id.clone()).await.unwrap();
|
||||||
let path = env::temp_dir().join(format!("{}.mrpack", get_modpack_name(id.clone())));
|
let path = env::temp_dir().join(format!("{}.mrpack", get_modpack_name(id.clone()).await));
|
||||||
let mut file = File::create(path.clone()).unwrap();
|
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());
|
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());
|
println!("Downloading file {}", ftp_path.to_str().unwrap());
|
||||||
ftp::ftp_retr(Some(window.clone()), ftp_path, &mut file, |window, data, size| util::download_callback(get_modpack_name(id.clone()), window, data, size)).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();
|
let mut child = Command::new(get_local_data_directory().join("prism").join(get_prism_executable())).arg("-I").arg(path).spawn().unwrap();
|
||||||
loop {
|
loop {
|
||||||
let version_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join(".minecraft").join("version.txt");
|
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() {
|
if version_path.clone().exists() {
|
||||||
let mut ver_file = File::open(version_path).unwrap();
|
let mut ver_file = File::open(version_path).unwrap();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
@ -99,7 +102,7 @@ fn install_modpack(window: tauri::Window, id: String){
|
|||||||
}
|
}
|
||||||
thread::sleep(Duration::from_secs(1));
|
thread::sleep(Duration::from_secs(1));
|
||||||
child.kill();
|
child.kill();
|
||||||
let info_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join("mmc-pack.json");
|
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 mut info_file = File::open(info_path.clone()).unwrap();
|
||||||
let info_json: Value = serde_json::from_reader(info_file).unwrap();
|
let info_json: Value = serde_json::from_reader(info_file).unwrap();
|
||||||
let mut mc_version = "0.0";
|
let mut mc_version = "0.0";
|
||||||
@ -109,9 +112,9 @@ fn install_modpack(window: tauri::Window, id: String){
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
let java = get_java_version(mc_version);
|
let java = get_java_version(mc_version);
|
||||||
java::install_java(java, window.clone());
|
java::install_java(java, window.clone()).await;
|
||||||
|
|
||||||
let option_path = get_local_data_directory().join("prism").join("instances").join(get_modpack_name(id.clone())).join("instance.cfg");
|
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 option_file = File::open(option_path.clone()).unwrap();
|
||||||
let mut buf = String::new();
|
let mut buf = String::new();
|
||||||
option_file.read_to_string(&mut buf);
|
option_file.read_to_string(&mut buf);
|
||||||
@ -134,44 +137,46 @@ fn install_modpack(window: tauri::Window, id: String){
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
pub fn get_modpacks() -> Vec<ModpackEntry> {
|
pub async fn get_modpacks() -> Vec<ModpackEntry> {
|
||||||
unsafe{
|
//unsafe{
|
||||||
static mut modpacks: Vec<ModpackEntry> = Vec::new();
|
let mut modpacks: Vec<ModpackEntry> = Vec::new();
|
||||||
if modpacks.is_empty() {
|
//if modpacks.is_empty() {
|
||||||
let mut buf = Cursor::new(vec![]);
|
let mut buf = Cursor::new(vec![]);
|
||||||
ftp::ftp_retr(None, PathBuf::new().join("modpacks.json"), &mut buf, |_, _, _| return);
|
//ftp::ftp_retr(None, PathBuf::new().join("modpacks.json"), &mut buf, |_, _, _| return);
|
||||||
buf.rewind();
|
https::download(None, format!("https://gitea.piwalker.net/fclauncher/modpacks.json"), &mut buf, format!("modpacks.json")).await;
|
||||||
let res = serde_json::from_reader(buf);
|
buf.rewind();
|
||||||
if !res.is_ok() {
|
let res = serde_json::from_reader(buf);
|
||||||
let paths = fs::read_dir(get_local_data_directory().join("prism").join("instances")).unwrap();
|
if !res.is_ok() {
|
||||||
for path in paths {
|
let paths = fs::read_dir(get_local_data_directory().join("prism").join("instances")).unwrap();
|
||||||
let path = path.unwrap();
|
for path in paths {
|
||||||
if fs::metadata(path.path()).unwrap().is_file() {
|
let path = path.unwrap();
|
||||||
continue;
|
if fs::metadata(path.path()).unwrap().is_file() {
|
||||||
}
|
continue;
|
||||||
let name = path.file_name().into_string().unwrap();
|
}
|
||||||
if name.starts_with(".") {
|
let name = path.file_name().into_string().unwrap();
|
||||||
continue;
|
if name.starts_with(".") {
|
||||||
}
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
modpacks.push(ModpackEntry{name: name.clone(), id: name})
|
modpacks.push(ModpackEntry{name: name.clone(), id: name})
|
||||||
}
|
|
||||||
return modpacks.clone()
|
|
||||||
}
|
|
||||||
let v: Value = 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()});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
return modpacks.clone();
|
return modpacks.clone()
|
||||||
}
|
}
|
||||||
|
let v: Value = 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()});
|
||||||
|
}
|
||||||
|
//}
|
||||||
|
return modpacks.clone();
|
||||||
|
//}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_versions(id: String) -> Result<Vec<VersionEntry>,Box<dyn std::error::Error>> {
|
async fn get_versions(id: String) -> Result<Vec<VersionEntry>,Box<dyn std::error::Error>> {
|
||||||
let mut versions: Vec<VersionEntry> = Vec::new();
|
let mut versions: Vec<VersionEntry> = Vec::new();
|
||||||
let mut buf = Cursor::new(vec![]);
|
let mut buf = Cursor::new(vec![]);
|
||||||
ftp::ftp_retr(None, PathBuf::new().join(id).join("versions.json"), &mut buf, |_, _, _| return);
|
//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();
|
buf.rewind();
|
||||||
let v: Value = serde_json::from_reader(buf)?;
|
let v: Value = serde_json::from_reader(buf)?;
|
||||||
for version in v.as_array().unwrap() {
|
for version in v.as_array().unwrap() {
|
||||||
|
@ -3,7 +3,7 @@ use flate2::read::GzDecoder;
|
|||||||
use tar::Archive;
|
use tar::Archive;
|
||||||
use tauri::api::file;
|
use tauri::api::file;
|
||||||
|
|
||||||
use crate::{ftp, java, system_dirs::{get_local_data_directory, get_prism_executable}, util};
|
use crate::{https, java, system_dirs::{get_local_data_directory, get_prism_executable}, util};
|
||||||
|
|
||||||
|
|
||||||
pub fn check_prism() -> bool {
|
pub fn check_prism() -> bool {
|
||||||
@ -16,12 +16,11 @@ pub async fn install_prism(window: tauri::Window){
|
|||||||
if check_prism() {
|
if check_prism() {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
java::install_java(21, window.clone());
|
java::install_java(21, window.clone()).await;
|
||||||
let path = PathBuf::new().join("prism").join(format!("prism-{}",if env::consts::OS == "windows" {"win.zip"} else {"lin.tar.gz"}));
|
|
||||||
let size = ftp::ftp_get_size(path.clone()).unwrap();
|
|
||||||
let mut buff = Cursor::new(vec![]);
|
let mut buff = Cursor::new(vec![]);
|
||||||
let mut total = 0;
|
let mut total = 0;
|
||||||
ftp::ftp_retr(Some(window.clone()), path, &mut buff, |window: Option<tauri::Window>, data, size| util::download_callback("Prism Launcher".to_string(),window, data, size)).unwrap();
|
//ftp::ftp_retr(Some(window.clone()), path, &mut buff, |window: Option<tauri::Window>, data, size| util::download_callback("Prism Launcher".to_string(),window, data, size)).unwrap();
|
||||||
|
https::download(Some(window.clone()), format!("https://gitea.piwalker.net/fclauncher/prism/prism-{}", if env::consts::OS == "windows" {"win.zip"} else {"lin.tar.gz"}), &mut buff, format!("Prism Launcher")).await;
|
||||||
std::fs::create_dir_all(get_local_data_directory().join("prism")).unwrap();
|
std::fs::create_dir_all(get_local_data_directory().join("prism")).unwrap();
|
||||||
buff.rewind().unwrap();
|
buff.rewind().unwrap();
|
||||||
if env::consts::OS != "windows" {
|
if env::consts::OS != "windows" {
|
||||||
@ -37,7 +36,8 @@ pub async fn install_prism(window: tauri::Window){
|
|||||||
}
|
}
|
||||||
|
|
||||||
let mut buff = Cursor::new(vec![]);
|
let mut buff = Cursor::new(vec![]);
|
||||||
ftp::ftp_retr(Some(window.clone()), PathBuf::new().join("prism").join("prismlauncher.cfg"), &mut buff, |_, _, _| return).unwrap();
|
//ftp::ftp_retr(Some(window.clone()), PathBuf::new().join("prism").join("prismlauncher.cfg"), &mut buff, |_, _, _| return).unwrap();
|
||||||
|
https::download(None, format!("https://gitea.piwalker.net/fclauncher/prism/prismlauncher.cfg"), &mut buff, format!("prismlauncher.cfg")).await;
|
||||||
buff.rewind();
|
buff.rewind();
|
||||||
let mut file = File::create(get_local_data_directory().join("prism").join("prismlauncher.cfg")).unwrap();
|
let mut file = File::create(get_local_data_directory().join("prism").join("prismlauncher.cfg")).unwrap();
|
||||||
loop {
|
loop {
|
||||||
|
Loading…
Reference in New Issue
Block a user