Skip to content

Commit

Permalink
Merge pull request Grasscutters#195 from fnr1r/linux/main
Browse files Browse the repository at this point in the history
Linux support
  • Loading branch information
SpikeHD authored and NotThorny committed Sep 10, 2023
1 parent 50d6fae commit e76e366
Show file tree
Hide file tree
Showing 15 changed files with 1,351 additions and 224 deletions.
552 changes: 481 additions & 71 deletions src-tauri/Cargo.lock

Large diffs are not rendered by default.

14 changes: 13 additions & 1 deletion src-tauri/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,12 @@ registry = "1.2.1"
[target.'cfg(unix)'.dependencies]
sudo = "0.6.0"

[target.'cfg(target_os = "linux")'.dependencies]
anyhow = "1.0.58"
os_type = "2.6"
term-detect = "0.1.7"
which = "4.4"

[dependencies]
serde = { version = "1.0", features = ["derive"] }
tauri = { version = "1.0.9", features = ["api-all"] }
Expand Down Expand Up @@ -53,7 +59,7 @@ serde_json = "1"

# Dependencies for the HTTP(S) proxy.
http = "0.2"
hudsucker = "0.19.1"
hudsucker = "0.19.2"
tracing = "0.1.21"
tokio-rustls = "0.23.0"
tokio-tungstenite = "0.17.0"
Expand All @@ -71,6 +77,12 @@ file_diff = "1.0.0"
rust-ini = "0.18.0"
ctrlc = "3.2.3"

[target.'cfg(target_os = "linux")'.dependencies.anime-launcher-sdk]
git = "https://github.com/an-anime-team/anime-launcher-sdk.git"
tag = "1.11.1"
default-features = false
features = ["all", "genshin"]

[features]
# by default Tauri runs in production mode
# when `tauri dev` runs it is executed with `cargo run --no-default-features` if `devPath` is an URL
Expand Down
7 changes: 5 additions & 2 deletions src-tauri/lang/en.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
"horny_mode": "Horny Mode",
"auto_mongodb": "Automatically Start MongoDB",
"un_elevated": "Run the game non-elevated (no admin)",
"redirect_more": "Also redirect other MHY games"
"redirect_more": "Also redirect other MHY games",
"check_aagl": "For more options, check the other launcher",
"grasscutter_elevation": "Method of running GC on restricted ports"
},
"downloads": {
"grasscutter_fullbuild": "Download Grasscutter All-in-One",
Expand Down Expand Up @@ -85,7 +87,8 @@
"use_proxy": "Use the Cultivation internal proxy. You should have this enabled unless you use something like Fiddler",
"patch_rsa": "Patch and unpatch your game RSA automatically. Unless playing with old/non-official versions (3.0 and older), this should be enabled.",
"add_delay": "Set delay in 3dmigoto loader! \nThis should fix loading issues, but will add a small delay to when 3dmigoto is loaded upon launching the game. \nYou can now launch with 3dmigoto again.",
"migoto": "For importing models from GameBanana"
"migoto": "For importing models from GameBanana",
"grasscutter_elevation_help_text": "The method used to allow Grasscutter to bind port 443 (which is not allowed for regular users on Linux)\nAvailable methods:\n Capability - grant the Java Virtual Machine the capability to bind ports below 1024. This also allows all other programs running on that JVM to bind these ports.\n Root - run GC as root. This also allows the GC server, its plugins and the JVM to do pretty much anything, including sending your nudes to the NSA, CIA, and the alphabet boys.\n None - for no method. This requires you to change the GC Dispatch port."
},
"swag": {
"akebi_name": "Akebi",
Expand Down
7 changes: 5 additions & 2 deletions src-tauri/lang/pl.json
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,9 @@
"horny_mode": "Tryb 34",
"auto_mongodb": "Automatycznie uruchamiaj MongoDB",
"un_elevated": "Uruchamiaj grę bez uprawnień administratora/roota",
"redirect_more": "Przekieruj też inne gry MHY"
"redirect_more": "Przekieruj też inne gry MHY",
"check_aagl": "Więcej opcji znajdziesz w drugim launcherze",
"grasscutter_elevation": "Sposób uruchomienia GC na ograniczonym porcie"
},
"downloads": {
"grasscutter_fullbuild": "Pobierz Grasscutter (wszystko w jednym)",
Expand Down Expand Up @@ -85,7 +87,8 @@
"use_proxy": "Używaj wewnętrznego proxy Cultivation. To powinno być włączone, chyba że używasz czegoś jak np. Fiddler",
"patch_rsa": "Patchuj i odpatchuj RSA gry automatycznie. Jeżeli nie grasz w starą lub nieoficjalną wersję (3.0 lub starszą), to powinno być włączone.",
"add_delay": "Ustaw opóźnienie 3dmigoto loadera! \nTo powinno naprawić problemy z ładowaniem, ale doda małe opóźnienie do czasu ładowania 3dmigoto do gry. \nTeraz możecie uruchamiać grę z 3dmigoto.",
"migoto": "Do importowania modeli z GameBanana"
"migoto": "Do importowania modeli z GameBanana",
"grasscutter_elevation_help_text": "Metoda używana przez Grasscuttera do zbindowania portu 443 (co nie jest dozwolone dla zywkłych użytkowników w Linuxie)\nDostępne metody:\n Capability - daje wirtualnej maszynie Javy możliwość zbindowania portów poniżej 1024. To też pozwala wszystkim innym programom odpalonym na tej maszynie JVM zbindować te porty.\n Root - uruchamia GC jako root. To pozwala serwerowi GC, jego pluginom i maszynie JVM zrobić praktycznie wszystko, wliczając w to wysyłanie twoich nudesów do ABW, CBŚ, i innych trzyliterowych służb.\n None - czyli żadna metoda. Ta opcja wymaga zmiana portu Dispatch serwera GC."
},
"swag": {
"akebi_name": "Akebi",
Expand Down
3 changes: 0 additions & 3 deletions src-tauri/src/admin.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,8 +18,5 @@ pub fn reopen_as_admin() {
exit(0);
}

#[cfg(target_os = "linux")]
pub fn reopen_as_admin() {}

#[cfg(target_os = "macos")]
pub fn reopen_as_admin() {}
63 changes: 54 additions & 9 deletions src-tauri/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -11,14 +11,22 @@ use proxy::set_proxy_addr;
use std::fs;
use std::io::Write;
use std::{collections::HashMap, sync::Mutex};
use system_helpers::is_elevated;
use tauri::api::path::data_dir;
use tauri::async_runtime::block_on;

use std::thread;
use sysinfo::{Pid, ProcessExt, System, SystemExt};

#[cfg(target_os = "windows")]
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;
Expand All @@ -37,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(())
}
Expand Down Expand Up @@ -157,6 +168,7 @@ fn main() -> Result<(), ArgsError> {
let args: Vec<String> = std::env::args().collect();
let parsed_args = block_on(parse_args(&args)).unwrap();

#[cfg(target_os = "windows")]
if !is_elevated() && !parsed_args.value_of("no-admin")? {
println!("===============================================================================");
println!("You running as a non-elevated user. Some stuff will almost definitely not work.");
Expand Down Expand Up @@ -202,6 +214,7 @@ fn main() -> Result<(), ArgsError> {
system_helpers::service_status,
system_helpers::stop_service,
system_helpers::run_jar,
system_helpers::run_jar_root,
system_helpers::open_in_browser,
system_helpers::install_location,
system_helpers::is_elevated,
Expand All @@ -210,6 +223,10 @@ fn main() -> Result<(), ArgsError> {
system_helpers::wipe_registry,
system_helpers::get_platform,
system_helpers::run_un_elevated,
system_helpers::jvm_add_cap,
system_helpers::jvm_remove_cap,
patch::patch_game,
patch::unpatch_game,
proxy::set_proxy_addr,
proxy::generate_ca_files,
proxy::set_redirect_more,
Expand Down Expand Up @@ -267,6 +284,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;
Expand Down Expand Up @@ -312,6 +330,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
Expand Down Expand Up @@ -361,7 +414,6 @@ fn restart_grasscutter(_window: tauri::Window) {
}
}

#[cfg(windows)]
#[tauri::command]
fn enable_grasscutter_watcher(window: tauri::Window, process: String) {
let grasscutter_name = process.clone();
Expand Down Expand Up @@ -422,13 +474,6 @@ fn enable_grasscutter_watcher(window: tauri::Window, process: String) {
});
}

#[cfg(unix)]
#[tauri::command]
fn enable_grasscutter_watcher(_window: tauri::Window, _process: String) {
let gc_pid = Pid::from(696969);
*GC_PID.lock().unwrap() = gc_pid.into();
}

#[tauri::command]
async fn connect(port: u16, certificate_path: String) {
// Log message to console.
Expand Down
Loading

0 comments on commit e76e366

Please sign in to comment.