diff --git a/package.json b/package.json index 4a13950..70c6d67 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "cultivation", - "version": "1.0.10", + "version": "1.0.23", "private": true, "dependencies": { "@tauri-apps/api": "^1.0.0-rc.5", diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 58155eb..0b1bad7 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -768,6 +768,7 @@ dependencies = [ "tokio-tungstenite 0.17.2", "tracing", "unrar", + "windows-service", "zip 0.6.2", "zip-extract", ] @@ -1058,7 +1059,7 @@ dependencies = [ "cfg-if", "libc", "redox_syscall", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2111,7 +2112,7 @@ dependencies = [ "libc", "log", "wasi 0.11.0+wasi-snapshot-preview1", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2465,7 +2466,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f23a407004a1033f53e93f9b45580d14de23928faad187384f891507c9b0c045" dependencies = [ "pathdiff", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -2630,7 +2631,7 @@ dependencies = [ "libc", "redox_syscall", "smallvec", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -3406,7 +3407,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "88d6731146462ea25d9244b2ed5fd1d716d25c52e4d54aa4fb0f3c4e9854dbe2" dependencies = [ "lazy_static", - "windows-sys", + "windows-sys 0.36.1", ] [[package]] @@ -4888,6 +4889,12 @@ dependencies = [ "cc", ] +[[package]] +name = "widestring" +version = "1.0.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "653f141f39ec16bba3c5abe400a0c60da7468261cc2cbf36805022876bc721a8" + [[package]] name = "wildmatch" version = "2.1.1" @@ -4990,6 +4997,17 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "4f33f2b90a6664e369c41ab5ff262d06f048fc9685d9bf8a0e99a47750bb0463" +[[package]] +name = "windows-service" +version = "0.6.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "cd9db37ecb5b13762d95468a2fc6009d4b2c62801243223aabd44fca13ad13c8" +dependencies = [ + "bitflags", + "widestring", + "windows-sys 0.45.0", +] + [[package]] name = "windows-sys" version = "0.36.1" @@ -5003,12 +5021,42 @@ dependencies = [ "windows_x86_64_msvc 0.36.1", ] +[[package]] +name = "windows-sys" +version = "0.45.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "75283be5efb2831d37ea142365f009c02ec203cd29a3ebecbc093d52315b66d0" +dependencies = [ + "windows-targets", +] + +[[package]] +name = "windows-targets" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8e5180c00cd44c9b1c88adb3693291f1cd93605ded80c250a75d472756b4d071" +dependencies = [ + "windows_aarch64_gnullvm", + "windows_aarch64_msvc 0.42.2", + "windows_i686_gnu 0.42.2", + "windows_i686_msvc 0.42.2", + "windows_x86_64_gnu 0.42.2", + "windows_x86_64_gnullvm", + "windows_x86_64_msvc 0.42.2", +] + [[package]] name = "windows-tokens" version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3263d25f1170419995b78ff10c06b949e8a986c35c208dc24333c64753a87169" +[[package]] +name = "windows_aarch64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "597a5118570b68bc08d8d59125332c54f1ba9d9adeedeef5b99b02ba2b0698f8" + [[package]] name = "windows_aarch64_msvc" version = "0.32.0" @@ -5027,6 +5075,12 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2623277cb2d1c216ba3b578c0f3cf9cdebeddb6e66b1b218bb33596ea7769c3a" +[[package]] +name = "windows_aarch64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e08e8864a60f06ef0d0ff4ba04124db8b0fb3be5776a5cd47641e942e58c4d43" + [[package]] name = "windows_i686_gnu" version = "0.24.0" @@ -5051,6 +5105,12 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d3925fd0b0b804730d44d4b6278c50f9699703ec49bcd628020f46f4ba07d9e1" +[[package]] +name = "windows_i686_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c61d927d8da41da96a81f029489353e68739737d3beca43145c8afec9a31a84f" + [[package]] name = "windows_i686_msvc" version = "0.24.0" @@ -5075,6 +5135,12 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ce907ac74fe331b524c1298683efbf598bb031bc84d5e274db2083696d07c57c" +[[package]] +name = "windows_i686_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "44d840b6ec649f480a41c8d80f9c65108b92d89345dd94027bfe06ac444d1060" + [[package]] name = "windows_x86_64_gnu" version = "0.24.0" @@ -5099,6 +5165,18 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2babfba0828f2e6b32457d5341427dcbb577ceef556273229959ac23a10af33d" +[[package]] +name = "windows_x86_64_gnu" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8de912b8b8feb55c064867cf047dda097f92d51efad5b491dfb98f6bbb70cb36" + +[[package]] +name = "windows_x86_64_gnullvm" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26d41b46a36d453748aedef1486d5c7a85db22e56aff34643984ea85514e94a3" + [[package]] name = "windows_x86_64_msvc" version = "0.24.0" @@ -5123,6 +5201,12 @@ version = "0.37.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f4dd6dc7df2d84cf7b33822ed5b86318fb1781948e9663bacd047fc9dd52259d" +[[package]] +name = "windows_x86_64_msvc" +version = "0.42.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9aec5da331524158c6d1a4ac0ab1541149c0b9505fde06423b02f5ef0106b9f0" + [[package]] name = "winreg" version = "0.10.1" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 1b3527b..a46e6d7 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -41,6 +41,9 @@ once_cell = "1.13.0" open = "3.0.2" duct = "0.13.5" +# Services +windows-service = "0.6.0" + # Serialization. serde_json = "1" diff --git a/src-tauri/lang/chs.json b/src-tauri/lang/chs.json index 1bfb5a7..d80490f 100644 --- a/src-tauri/lang/chs.json +++ b/src-tauri/lang/chs.json @@ -28,7 +28,8 @@ "patch_rsa": "自动修改RSA", "use_proxy": "使用内置代理", "wipe_login": "清除登录缓存", - "horny_mode": "Horny 模式" + "horny_mode": "Horny 模式", + "auto_mongodb": "自动启动 MongoDB" }, "downloads": { "grasscutter_fullbuild": "下载 Grasscutter 一体化", diff --git a/src-tauri/lang/cht.json b/src-tauri/lang/cht.json index 38c0b56..74642f0 100644 --- a/src-tauri/lang/cht.json +++ b/src-tauri/lang/cht.json @@ -28,7 +28,8 @@ "patch_rsa": "自動修補RSA", "use_proxy": "使用內建代理伺服器", "wipe_login": "擦除登錄緩存", - "horny_mode": "Horny模式" + "horny_mode": "Horny模式", + "auto_mongodb": "自動啟動 MongoDB" }, "downloads": { "grasscutter_fullbuild": "下載Grasscutter多合一下載", diff --git a/src-tauri/lang/de.json b/src-tauri/lang/de.json index 5177487..991a4cf 100644 --- a/src-tauri/lang/de.json +++ b/src-tauri/lang/de.json @@ -27,7 +27,8 @@ "patch_rsa": "RSA automatisch patchen", "use_proxy": "Gebruik interne proxy", "wipe_login": "Wis de inlogcache", - "horny_mode": "Geile modus" + "horny_mode": "Geile modus", + "auto_mongodb": "Start automatisch MongoDB" }, "downloads": { "grasscutter_fullbuild": "Alles in Einem Grasscutter Daten herunterladen", diff --git a/src-tauri/lang/en.json b/src-tauri/lang/en.json index f6a8ad4..755186f 100644 --- a/src-tauri/lang/en.json +++ b/src-tauri/lang/en.json @@ -28,7 +28,8 @@ "patch_rsa": "Automatically Patch RSA", "use_proxy": "Use Internal Proxy", "wipe_login": "Wipe Login Cache", - "horny_mode": "Horny Mode" + "horny_mode": "Horny Mode", + "auto_mongodb": "Automatically Start MongoDB" }, "downloads": { "grasscutter_fullbuild": "Download Grasscutter All-in-One", diff --git a/src-tauri/lang/es.json b/src-tauri/lang/es.json index f365221..b7c1e66 100644 --- a/src-tauri/lang/es.json +++ b/src-tauri/lang/es.json @@ -26,9 +26,10 @@ "background": "Establecer Fondo Personalizado (link o archivo de imagen)", "patch_rsa": "Parchear RSA automáticamente", "theme": "Establecer Tema", - "use_proxy": "Use Internal Proxy", - "wipe_login": "Wipe Login Cache", - "horny_mode": "Horny Mode" + "use_proxy": "Usar proxy interno", + "wipe_login": "Borrar caché de inicio de sesión", + "horny_mode": "Modo cachondo", + "auto_mongodb": "Iniciar automáticamente MongoDB" }, "downloads": { "grasscutter_fullbuild": "Descargar Datos todo en uno de Grasscutter", diff --git a/src-tauri/lang/fr.json b/src-tauri/lang/fr.json index fba0b76..0ae207c 100644 --- a/src-tauri/lang/fr.json +++ b/src-tauri/lang/fr.json @@ -28,7 +28,8 @@ "patch_rsa": "Corriger automatiquement les RSA", "use_proxy": "Utiliser un proxy interne", "wipe_login": "Effacer le cache de connexion", - "horny_mode": "Mode excitation" + "horny_mode": "Mode excitation", + "auto_mongodb": "Démarrer automatiquement MongoDB" }, "downloads": { "grasscutter_fullbuild": "Telecharger Grasscutter tout-en-un", diff --git a/src-tauri/lang/id.json b/src-tauri/lang/id.json index 2123e2f..48a0c45 100644 --- a/src-tauri/lang/id.json +++ b/src-tauri/lang/id.json @@ -27,7 +27,8 @@ "patch_rsa": "Automatically Patch RSA", "use_proxy": "Gunakan Proxy Internal", "wipe_login": "Menghapus Cache Login", - "horny_mode": "Mode Terangsang" + "horny_mode": "Mode Terangsang", + "auto_mongodb": "Mulai MongoDB secara otomatis" }, "downloads": { "grasscutter_fullbuild": "Sedang Mendownload Grasscutter Semua Dalam Satu", diff --git a/src-tauri/lang/ko.json b/src-tauri/lang/ko.json index 8f68c14..4c2fd98 100644 --- a/src-tauri/lang/ko.json +++ b/src-tauri/lang/ko.json @@ -28,7 +28,8 @@ "patch_rsa": "RSA 패치 자동 적용", "use_proxy": "내부 프록시 사용", "wipe_login": "로그인 캐시 지우기", - "horny_mode": "Horny 모드" + "horny_mode": "Horny 모드", + "auto_mongodb": "MongoDB 자동 시작" }, "downloads": { "grasscutter_fullbuild": "올인원 Grasscutter 다운로드", diff --git a/src-tauri/lang/lv.json b/src-tauri/lang/lv.json index 3cd85be..b693641 100644 --- a/src-tauri/lang/lv.json +++ b/src-tauri/lang/lv.json @@ -26,7 +26,8 @@ "patch_rsa": "Automātiski ielāpot RSA", "use_proxy": "Izmantot iekšējo starpniekserveri", "wipe_login": "Noslaucīt pieteikšanās kešatmiņu", - "horny_mode": "Uzbudināts režīms" + "horny_mode": "Uzbudināts režīms", + "auto_mongodb": "Automātiski startējiet MongoDB" }, "downloads": { "grasscutter_fullbuild": "Lejupielādējiet Grasscutter viss vienā", diff --git a/src-tauri/lang/nl.json b/src-tauri/lang/nl.json index 9ca3fdf..7090d50 100644 --- a/src-tauri/lang/nl.json +++ b/src-tauri/lang/nl.json @@ -27,7 +27,8 @@ "patch_rsa": "RSA Automatisch Bijwerken", "use_proxy": "Gebruik Interne Proxy", "wipe_login": "Login cache wissen", - "horny_mode": "Geile modus" + "horny_mode": "Geile modus", + "auto_mongodb": "Start automatisch MongoDB" }, "downloads": { "grasscutter_fullbuild": "Grasscutter Alles-in-één Downloaden", diff --git a/src-tauri/lang/ru.json b/src-tauri/lang/ru.json index 417a01d..151c89b 100644 --- a/src-tauri/lang/ru.json +++ b/src-tauri/lang/ru.json @@ -27,7 +27,8 @@ "patch_rsa": "Автоматическое исправление RSA", "use_proxy": "Использовать встроенный Прокси", "wipe_login": "Очистить кэш входа в систему", - "horny_mode": "роговой режим" + "horny_mode": "роговой режим", + "auto_mongodb": "Автоматически запускать MongoDB" }, "downloads": { "grasscutter_fullbuild": "Скачать все в одном Grasscutter", diff --git a/src-tauri/lang/vi.json b/src-tauri/lang/vi.json index a4912eb..23ade69 100644 --- a/src-tauri/lang/vi.json +++ b/src-tauri/lang/vi.json @@ -28,7 +28,8 @@ "patch_rsa": "Tự động vá RSA", "use_proxy": "Sử dụng proxy nội bộ", "wipe_login": "Tẩy sạch cache đăng nhập", - "horny_mode": "Chế độ hứng tình" + "horny_mode": "Chế độ hứng tình", + "auto_mongodb": "Tự động khởi động MongoDB" }, "downloads": { "grasscutter_fullbuild": "Tải Grasscutter tất cả trong một", diff --git a/src-tauri/src/admin.rs b/src-tauri/src/admin.rs index 66daa49..203eb8a 100644 --- a/src-tauri/src/admin.rs +++ b/src-tauri/src/admin.rs @@ -1,5 +1,7 @@ #[cfg(windows)] pub fn reopen_as_admin() { + use std::process::{exit, Command}; + let install = std::env::current_exe().unwrap(); println!("Opening as admin: {}", install.to_str().unwrap()); diff --git a/src-tauri/src/main.rs b/src-tauri/src/main.rs index a7bb3ca..c2e0fe7 100644 --- a/src-tauri/src/main.rs +++ b/src-tauri/src/main.rs @@ -13,7 +13,7 @@ use tauri::api::path::data_dir; use tauri::async_runtime::block_on; use std::thread; -use sysinfo::{System, SystemExt}; +use sysinfo::{Pid, ProcessExt, System, SystemExt}; use crate::admin::reopen_as_admin; @@ -28,6 +28,8 @@ mod unzip; mod web; static WATCH_GAME_PROCESS: Lazy> = Lazy::new(|| Mutex::new(String::new())); +static WATCH_GRASSCUTTER_PROCESS: Lazy> = Lazy::new(|| Mutex::new(String::new())); +static GC_PID: std::sync::Mutex = Mutex::new(696969); fn try_flush() { std::io::stdout().flush().unwrap_or(()) @@ -81,14 +83,20 @@ fn main() { tauri::Builder::default() .invoke_handler(tauri::generate_handler![ enable_process_watcher, + enable_grasscutter_watcher, connect, disconnect, req_get, is_game_running, + is_grasscutter_running, + restart_grasscutter, get_theme_list, system_helpers::run_command, system_helpers::run_program, system_helpers::run_program_relative, + system_helpers::start_service, + system_helpers::service_status, + system_helpers::stop_service, system_helpers::run_jar, system_helpers::open_in_browser, system_helpers::install_location, @@ -185,6 +193,104 @@ fn enable_process_watcher(window: tauri::Window, process: String) { }); } +#[tauri::command] +fn is_grasscutter_running() -> bool { + // Grab the grasscutter process name + let proc = WATCH_GRASSCUTTER_PROCESS.lock().unwrap().to_string(); + + !proc.is_empty() +} + +#[tauri::command] +fn restart_grasscutter(window: tauri::Window) -> bool { + let pid: usize = *GC_PID.lock().unwrap(); + let system = System::new_all(); + // Get the process + if let Some(process) = system.process(Pid::from(pid)) { + // Kill it + if process.kill() { + // Also kill the cmd it was open in + if let Some(parent) = system.process(Pid::from(process.parent().unwrap())) { + parent.kill(); + } + for process_gc in system.processes_by_name("java") { + if process_gc.cmd().last().unwrap().contains(&"grasscutter") { + process_gc.kill(); + } + } + window.emit("disable_grasscutter_watcher", &()).unwrap(); + thread::sleep(std::time::Duration::from_secs(2)); + // Start again + window.emit("start_grasscutter", &()).unwrap(); + true + } else { + false + } + } else { + false + } +} + +#[tauri::command] +fn enable_grasscutter_watcher(window: tauri::Window, process: String) { + let grasscutter_name = process.clone(); + let mut gc_pid = Pid::from(696969); + + *WATCH_GRASSCUTTER_PROCESS.lock().unwrap() = process; + + window.listen("disable_grasscutter_watcher", |_e| { + *WATCH_GRASSCUTTER_PROCESS.lock().unwrap() = "".to_string(); + }); + + println!("Starting grasscutter watcher..."); + + thread::spawn(move || { + // Initial sleep for 1 second while Grasscutter opens + std::thread::sleep(std::time::Duration::from_secs(3)); + + let mut system = System::new_all(); + + for process_gc in system.processes_by_name("java") { + if process_gc.cmd().last().unwrap().contains(&grasscutter_name) { + gc_pid = process_gc.pid(); + *GC_PID.lock().unwrap() = gc_pid.into(); + window + .emit("grasscutter_started", gc_pid.to_string()) + .unwrap(); + } + } + + loop { + // Shorten loop timer to avoid user closing Cultivation before automatic stuff + thread::sleep(std::time::Duration::from_secs(2)); + + // Refresh system info + system.refresh_all(); + + // Grab the grasscutter process name + let proc = WATCH_GRASSCUTTER_PROCESS.lock().unwrap().to_string(); + + if !proc.is_empty() { + let mut exists = true; + + if system.process(gc_pid).is_none() { + exists = false; + } + + // If the grasscutter process closes. + if !exists { + println!("Grasscutter closed"); + + *WATCH_GRASSCUTTER_PROCESS.lock().unwrap() = "".to_string(); + + window.emit("grasscutter_closed", &()).unwrap(); + break; + } + } + } + }); +} + #[tauri::command] async fn connect(port: u16, certificate_path: String) { // Log message to console. diff --git a/src-tauri/src/system_helpers.rs b/src-tauri/src/system_helpers.rs index 5495b27..5eb249e 100644 --- a/src-tauri/src/system_helpers.rs +++ b/src-tauri/src/system_helpers.rs @@ -1,6 +1,9 @@ use duct::cmd; use ini::Ini; +use std::ffi::OsStr; use std::path::PathBuf; +use windows_service::service::{ServiceAccess, ServiceState::Stopped}; +use windows_service::service_manager::{ServiceManager, ServiceManagerAccess}; #[cfg(windows)] use registry::{Data, Hive, Security}; @@ -94,7 +97,7 @@ pub fn install_location() -> String { } #[tauri::command] -pub fn set_migoto_target(_path: String, migoto_path: String) -> bool { +pub fn set_migoto_target(migoto_path: String) -> bool { let mut migoto_pathbuf = PathBuf::from(migoto_path); migoto_pathbuf.pop(); @@ -152,6 +155,72 @@ pub fn wipe_registry(exec_name: String) { } } +#[cfg(windows)] +#[tauri::command] +pub fn service_status(service: String) -> bool { + let manager = match ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::CONNECT) { + Ok(manager) => manager, + Err(_e) => return false, + }; + let my_service = match manager.open_service(service.clone(), ServiceAccess::QUERY_STATUS) { + Ok(my_service) => my_service, + Err(_e) => { + println!("{} service not found! Not installed?", service); + return false; + } + }; + let status_result = my_service.query_status(); + if status_result.is_ok() { + let status = status_result.unwrap(); + println!("{} service status: {:?}", service, status.current_state); + if status.current_state == Stopped { + // Start the service if it is stopped + start_service(service); + } + true + } else { + false + } +} + +#[cfg(windows)] +#[tauri::command] +pub fn start_service(service: String) -> bool { + println!("Starting service: {}", service); + let manager = match ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::CONNECT) { + Ok(manager) => manager, + Err(_e) => return false, + }; + let my_service = match manager.open_service(service, ServiceAccess::START) { + Ok(my_service) => my_service, + Err(_e) => return false, + }; + match my_service.start(&[OsStr::new("Started service!")]) { + Ok(_s) => true, + Err(_e) => return false, + }; + true +} + +#[cfg(windows)] +#[tauri::command] +pub fn stop_service(service: String) -> bool { + println!("Stopping service: {}", service); + let manager = match ServiceManager::local_computer(None::<&str>, ServiceManagerAccess::CONNECT) { + Ok(manager) => manager, + Err(_e) => return false, + }; + let my_service = match manager.open_service(service, ServiceAccess::STOP) { + Ok(my_service) => my_service, + Err(_e) => return false, + }; + match my_service.stop() { + Ok(_s) => true, + Err(_e) => return false, + }; + true +} + #[cfg(unix)] #[tauri::command] pub fn wipe_registry(_exec_name: String) {} diff --git a/src-tauri/src/unzip.rs b/src-tauri/src/unzip.rs index 703c681..7e0b9b2 100644 --- a/src-tauri/src/unzip.rs +++ b/src-tauri/src/unzip.rs @@ -97,7 +97,7 @@ pub fn unzip( } // If downloading full build, emit that the jar was extracted with it - if zipfile.ends_with("Culti3.4.zip") { + if zipfile.contains("GrasscutterCulti") { window .emit("jar_extracted", destpath.to_string() + "grasscutter.jar") .unwrap(); diff --git a/src-tauri/tauri.conf.json b/src-tauri/tauri.conf.json index 148038d..1df0e36 100644 --- a/src-tauri/tauri.conf.json +++ b/src-tauri/tauri.conf.json @@ -7,7 +7,7 @@ }, "package": { "productName": "Cultivation", - "version": "1.0.10" + "version": "1.0.23" }, "tauri": { "allowlist": { diff --git a/src/ui/Main.tsx b/src/ui/Main.tsx index 5886aca..37c50ce 100644 --- a/src/ui/Main.tsx +++ b/src/ui/Main.tsx @@ -78,6 +78,15 @@ export class Main extends React.Component { } }) + // Emitted for automatic processes + listen('grasscutter_closed', async () => { + const autoService = await getConfigOption('auto_mongodb') + + if (autoService) { + await invoke('stop_service', { service: 'MongoDB' }) + } + }) + let min = false // periodically check if we need to min/max based on whether the game is open diff --git a/src/ui/components/ServerLaunchSection.tsx b/src/ui/components/ServerLaunchSection.tsx index 237dad1..d5b5663 100644 --- a/src/ui/components/ServerLaunchSection.tsx +++ b/src/ui/components/ServerLaunchSection.tsx @@ -12,8 +12,9 @@ import Plus from '../../resources/icons/plus.svg' import './ServerLaunchSection.css' import { dataDir } from '@tauri-apps/api/path' -import { getGameExecutable, getGameVersion } from '../../utils/game' +import { getGameExecutable, getGameVersion, getGrasscutterJar } from '../../utils/game' import { patchGame, unpatchGame } from '../../utils/rsa' +import { listen } from '@tauri-apps/api/event' interface IProps { openExtras: (playGame: () => void) => void @@ -25,6 +26,7 @@ interface IState { checkboxLabel: string ip: string port: string + launchServer: (proc_name?: string) => void ipPlaceholder: string portPlaceholder: string @@ -54,6 +56,9 @@ export default class ServerLaunchSection extends React.Component portHelpText: '', httpsLabel: '', httpsEnabled: false, + launchServer: () => { + alert('Error launching grasscutter') + }, swag: false, akebiSet: false, migotoSet: false, @@ -64,6 +69,11 @@ export default class ServerLaunchSection extends React.Component this.setIp = this.setIp.bind(this) this.setPort = this.setPort.bind(this) this.toggleHttps = this.toggleHttps.bind(this) + this.launchServer = this.launchServer.bind(this) + + listen('start_grasscutter', async () => { + this.launchServer() + }) } async componentDidMount() { @@ -159,16 +169,7 @@ export default class ServerLaunchSection extends React.Component // Open server as well if the options are set if (config.grasscutter_with_game) { - const jarFolderArr = config.grasscutter_path.replace(/\\/g, '/').split('/') - jarFolderArr.pop() - - const jarFolder = jarFolderArr.join('/') - - await invoke('run_jar', { - path: config.grasscutter_path, - executeIn: jarFolder, - javaPath: config.java_path || '', - }) + this.launchServer() } } else { await unpatchGame() @@ -191,11 +192,24 @@ export default class ServerLaunchSection extends React.Component else alert('Game not found! At: ' + (exe || config.game_install_path)) } - async launchServer() { + async launchServer(proc_name?: string) { + if (await invoke('is_grasscutter_running')) { + alert('Grasscutter already running!') + return + } const config = await getConfig() if (!config.grasscutter_path) return alert('Grasscutter not installed or set!') + if (config.auto_mongodb) { + const grasscutter_jar = await getGrasscutterJar() + await invoke('enable_grasscutter_watcher', { + process: proc_name || grasscutter_jar, + }) + // Check if MongoDB is running and start it if not + await invoke('service_status', { service: 'MongoDB' }) + } + let jarFolder = config.grasscutter_path if (jarFolder.includes('/')) { diff --git a/src/ui/components/menu/Downloads.tsx b/src/ui/components/menu/Downloads.tsx index 356eeca..433b691 100644 --- a/src/ui/components/menu/Downloads.tsx +++ b/src/ui/components/menu/Downloads.tsx @@ -13,12 +13,12 @@ import { invoke } from '@tauri-apps/api' import { listen } from '@tauri-apps/api/event' import HelpButton from '../common/HelpButton' -const FULL_BUILD_DOWNLOAD = 'https://cdn.discordapp.com/attachments/615655311960965130/1079203157294460958/GrasscutterCulti3.4.zip' +const FULL_BUILD_DOWNLOAD = 'https://github.com/NotThorny/Grasscutter/releases/download/culti-aio/GrasscutterCulti.zip' // Change to link that can be updated without modifying here const STABLE_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/stable.zip' const DEV_REPO_DOWNLOAD = 'https://github.com/Grasscutters/Grasscutter/archive/refs/heads/development.zip' const STABLE_DOWNLOAD = 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/stable/Grasscutter.zip' const DEV_DOWNLOAD = 'https://nightly.link/Grasscutters/Grasscutter/workflows/build/development/Grasscutter.zip' -const RESOURCES_DOWNLOAD = 'https://gitlab.com/YuukiPS/GC-Resources/-/archive/3.4/GC-Resources-3.4.zip' // Use Yuuki res as grasscutter crepe res are broken +const RESOURCES_DOWNLOAD = 'https://gitlab.com/YuukiPS/GC-Resources/-/archive/3.5/GC-Resources-3.5.zip' // Use Yuuki res as grasscutter crepe res are broken interface IProps { closeFn: () => void @@ -115,8 +115,8 @@ export default class Downloads extends React.Component { async downloadGrasscutterFullBuild() { const folder = await this.getGrasscutterFolder() - this.props.downloadManager.addDownload(FULL_BUILD_DOWNLOAD, folder + '\\GrasscutterCulti3.4.zip', async () => { - await unzip(folder + '\\GrasscutterCulti3.4.zip', folder + '\\', true) + this.props.downloadManager.addDownload(FULL_BUILD_DOWNLOAD, folder + '\\GrasscutterCulti.zip', async () => { + await unzip(folder + '\\GrasscutterCulti.zip', folder + '\\', true) this.toggleButtons() }) @@ -172,7 +172,6 @@ export default class Downloads extends React.Component { async downloadResources() { const folder = await this.getGrasscutterFolder() this.props.downloadManager.addDownload(RESOURCES_DOWNLOAD, folder + '\\resources.zip', async () => { - // Tell the user this takes some time alert( 'Extracting resources can take time! If your resources appear to be "stuck" extracting for less than 15-20 mins, they likely still are extracting.' @@ -218,7 +217,6 @@ export default class Downloads extends React.Component { render() { return ( -
@@ -226,9 +224,7 @@ export default class Downloads extends React.Component {
- +
diff --git a/src/ui/components/menu/Options.tsx b/src/ui/components/menu/Options.tsx index aa897ed..1d0a9b3 100644 --- a/src/ui/components/menu/Options.tsx +++ b/src/ui/components/menu/Options.tsx @@ -37,6 +37,7 @@ interface IState { use_internal_proxy: boolean wipe_login: boolean horny_mode: boolean + auto_mongodb: boolean swag: boolean platform: string @@ -66,6 +67,7 @@ export default class Options extends React.Component { wipe_login: false, horny_mode: false, swag: false, + auto_mongodb: false, platform: '', // Swag stuff @@ -113,6 +115,7 @@ export default class Options extends React.Component { wipe_login: config.wipe_login || false, horny_mode: config.horny_mode || false, swag: config.swag_mode || false, + auto_mongodb: config.auto_mongodb || false, platform, // Swag stuff @@ -188,7 +191,6 @@ export default class Options extends React.Component { // Set game exe in Migoto ini invoke('set_migoto_target', { - path: this.state.game_install_path, migotoPath: value, }) } @@ -265,7 +267,11 @@ export default class Options extends React.Component { ), }) - alert('Restart Grasscutter to apply encryption settings! If it is already closed, just start as normal.') + // Check if Grasscutter is running, and restart if so to apply changes + if (await invoke('is_grasscutter_running')) { + alert('Automatically restarting Grasscutter to apply encryption changes!') + await invoke('restart_grasscutter') + } } async removeRSA() { @@ -356,6 +362,18 @@ export default class Options extends React.Component { />
+ diff --git a/src/utils/configuration.ts b/src/utils/configuration.ts index 97c7dfb..70f3e7b 100644 --- a/src/utils/configuration.ts +++ b/src/utils/configuration.ts @@ -24,6 +24,7 @@ let defaultConfig: Configuration use_internal_proxy: true, wipe_login: false, horny_mode: false, + auto_mongodb: false, } })() @@ -51,6 +52,7 @@ export interface Configuration { wipe_login: boolean horny_mode: boolean swag_mode?: boolean + auto_mongodb: boolean // Swag stuff akebi_path?: string diff --git a/src/utils/download.ts b/src/utils/download.ts index e6e727a..c9ed7c6 100644 --- a/src/utils/download.ts +++ b/src/utils/download.ts @@ -106,7 +106,7 @@ export default class DownloadHandler { downloadingFullBuild() { // Kinda hacky but it works - return this.downloads.some((d) => d.path.includes('GrasscutterCulti3.4.zip')) + return this.downloads.some((d) => d.path.includes('GrasscutterCulti')) } downloadingResources() { diff --git a/src/utils/game.ts b/src/utils/game.ts index 748c034..9d933ee 100644 --- a/src/utils/game.ts +++ b/src/utils/game.ts @@ -12,6 +12,17 @@ export async function getGameExecutable() { return pathArr[pathArr.length - 1] } +export async function getGrasscutterJar() { + const config = await getConfig() + + if (!config.grasscutter_path) { + return null + } + + const pathArr = config.grasscutter_path.replace(/\\/g, '/').split('/') + return pathArr[pathArr.length - 1] +} + export async function getGameFolder() { const config = await getConfig()