Implement launching the game on Linux

This commit is contained in:
fnrir
2023-08-18 13:31:18 +02:00
parent ef576e36b8
commit 3ecc4f4231
8 changed files with 557 additions and 100 deletions

View File

@@ -22,6 +22,12 @@ use crate::admin::reopen_as_admin;
#[cfg(target_os = "windows")]
use system_helpers::is_elevated;
#[cfg(target_os = "linux")]
use std::{
thread::{sleep, JoinHandle},
time::{Duration, Instant},
};
mod admin;
mod config;
mod downloader;
@@ -39,6 +45,9 @@ static WATCH_GAME_PROCESS: Lazy<Mutex<String>> = Lazy::new(|| Mutex::new(String:
static WATCH_GRASSCUTTER_PROCESS: Lazy<Mutex<String>> = Lazy::new(|| Mutex::new(String::new()));
static GC_PID: std::sync::Mutex<usize> = Mutex::new(696969);
#[cfg(target_os = "linux")]
pub static AAGL_THREAD: Lazy<Mutex<Option<JoinHandle<()>>>> = Lazy::new(|| Mutex::new(None));
fn try_flush() {
std::io::stdout().flush().unwrap_or(())
}
@@ -270,6 +279,7 @@ fn is_game_running() -> bool {
!proc.is_empty()
}
#[cfg(target_os = "windows")]
#[tauri::command]
fn enable_process_watcher(window: tauri::Window, process: String) {
*WATCH_GAME_PROCESS.lock().unwrap() = process;
@@ -315,6 +325,41 @@ fn enable_process_watcher(window: tauri::Window, process: String) {
});
}
// The library takes care of it
#[cfg(target_os = "linux")]
#[tauri::command]
fn enable_process_watcher(window: tauri::Window, process: String) {
drop(process);
thread::spawn(move || {
let end_time = Instant::now() + Duration::from_secs(60);
let game_thread = loop {
let mut lock = AAGL_THREAD.lock().unwrap();
if lock.is_some() {
break lock.take().unwrap();
}
drop(lock);
if end_time < Instant::now() {
// If more than 60 seconds pass something has gone wrong
println!("Waiting for game thread timed out");
return;
}
// Otherwhise wait in order to not use too many CPU cycles
sleep(Duration::from_millis(128));
};
game_thread.join().unwrap();
println!("Game closed");
*WATCH_GAME_PROCESS.lock().unwrap() = "".to_string();
disconnect();
window.emit("game_closed", &()).unwrap();
});
}
#[cfg(target_os = "macos")]
#[tauri::command]
fn enable_process_watcher(window: tauri::Window, process: String) {}
#[tauri::command]
fn is_grasscutter_running() -> bool {
// Grab the grasscutter process name

View File

@@ -26,6 +26,9 @@ use tauri::{api::path::data_dir, http::Uri};
#[cfg(windows)]
use registry::{Data, Hive, Security};
#[cfg(target_os = "linux")]
use anime_launcher_sdk::{config::ConfigExt, genshin::config::Config};
async fn shutdown_signal() {
tokio::signal::ctrl_c()
.await
@@ -281,24 +284,23 @@ pub fn connect_to_proxy(proxy_port: u16) {
println!("Connected to the proxy.");
}
#[cfg(unix)]
#[cfg(target_os = "linux")]
pub fn connect_to_proxy(proxy_port: u16) {
// Edit /etc/environment to set $http_proxy and $https_proxy
let mut env_file = match fs::read_to_string("/etc/environment") {
Ok(f) => f,
Err(e) => {
println!("Error opening /etc/environment: {}", e);
return;
}
};
// Append the proxy configuration.
// We will not remove the current proxy config if it exists, so we can just remove these last lines when we disconnect
env_file += format!("\nhttps_proxy=127.0.0.1:{}", proxy_port).as_str();
env_file += format!("\nhttp_proxy=127.0.0.1:{}", proxy_port).as_str();
// Save
fs::write("/etc/environment", env_file).unwrap();
let mut config = Config::get().unwrap();
let proxy_addr = format!("127.0.0.1:{}", proxy_port);
if !config.game.environment.contains_key("http_proxy") {
config
.game
.environment
.insert("http_proxy".to_string(), proxy_addr.clone());
}
if !config.game.environment.contains_key("https_proxy") {
config
.game
.environment
.insert("https_proxy".to_string(), proxy_addr);
}
Config::update(config);
}
#[cfg(target_od = "macos")]
@@ -327,21 +329,14 @@ pub fn disconnect_from_proxy() {
#[cfg(target_os = "linux")]
pub fn disconnect_from_proxy() {
println!("Re-writing environment variables");
let regexp = regex::Regex::new(
// This has to be specific as possible or we risk fuckin up their environment LOL
r"(https|http)_proxy=.*127.0.0.1:.*",
)
.unwrap();
let environment = &fs::read_to_string("/etc/environment").expect("Failed to open environment");
let new_environment = regexp.replace_all(environment, "").to_string();
// Write new environment
fs::write("/etc/environment", new_environment.trim_end()).expect(
"Could not write environment, remove proxy declarations manually if they are still set",
);
let mut config = Config::get().unwrap();
if config.game.environment.contains_key("http_proxy") {
config.game.environment.remove("http_proxy");
}
if config.game.environment.contains_key("https_proxy") {
config.game.environment.remove("https_proxy");
}
Config::update(config);
}
#[cfg(target_os = "macos")]

View File

@@ -10,6 +10,13 @@ use {
windows_service::service_manager::{ServiceManager, ServiceManagerAccess},
};
#[cfg(target_os = "linux")]
use crate::AAGL_THREAD;
#[cfg(target_os = "linux")]
use anime_launcher_sdk::genshin::game;
#[cfg(target_os = "linux")]
use std::thread;
#[tauri::command]
pub fn run_program(path: String, args: Option<String>) {
// Without unwrap_or, this can crash when UAC prompt is denied
@@ -22,6 +29,7 @@ pub fn run_program(path: String, args: Option<String>) {
};
}
#[cfg(target_os = "windows")]
#[tauri::command]
pub fn run_program_relative(path: String, args: Option<String>) {
// Save the current working directory
@@ -41,6 +49,13 @@ pub fn run_program_relative(path: String, args: Option<String>) {
std::env::set_current_dir(cwd).unwrap();
}
#[cfg(target_os = "linux")]
#[tauri::command]
pub fn run_program_relative(path: String, args: Option<String>) {
// This program should not run as root
run_un_elevated(path, args)
}
#[tauri::command]
pub fn run_command(program: &str, args: Vec<&str>, relative: Option<bool>) {
let prog = program.to_string();
@@ -90,6 +105,7 @@ pub fn run_jar(path: String, execute_in: String, java_path: String) {
};
}
#[cfg(target_os = "windows")]
#[tauri::command]
pub fn run_un_elevated(path: String, args: Option<String>) {
// Open the program non-elevated.
@@ -106,6 +122,20 @@ pub fn run_un_elevated(path: String, args: Option<String>) {
};
}
#[cfg(target_os = "linux")]
#[tauri::command]
pub fn run_un_elevated(path: String, args: Option<String>) {
drop(path);
drop(args);
let t = thread::spawn(|| {
game::run().expect("doo doo");
});
{
let mut l = AAGL_THREAD.lock().unwrap();
l.replace(t);
}
}
#[tauri::command]
pub fn open_in_browser(url: String) {
// Open the URL in the default browser.