Compare commits
No commits in common. "366b6fbca7a5ad7e763a8de8e05eb9b949485040" and "d69cf115c8aa300e473b529d9de1acf426adb8cb" have entirely different histories.
366b6fbca7
...
d69cf115c8
162
Cargo.lock
generated
162
Cargo.lock
generated
@ -316,7 +316,7 @@ dependencies = [
|
|||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
"quote",
|
"quote",
|
||||||
"regex",
|
"regex",
|
||||||
"rustc-hash",
|
"rustc-hash 1.1.0",
|
||||||
"shlex",
|
"shlex",
|
||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
"which",
|
"which",
|
||||||
@ -539,9 +539,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "cargo_toml"
|
name = "cargo_toml"
|
||||||
version = "0.22.1"
|
version = "0.21.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "02260d489095346e5cafd04dea8e8cb54d1d74fcd759022a9b72986ebe9a1257"
|
checksum = "5fbd1fe9db3ebf71b89060adaf7b0504c2d6a425cf061313099547e382c2e472"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"serde",
|
"serde",
|
||||||
"toml",
|
"toml",
|
||||||
@ -1575,8 +1575,10 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
checksum = "c4567c8db10ae91089c99af84c68c38da3ec2f087c3f82960bcdbf3656b6f4d7"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"wasi 0.11.0+wasi-snapshot-preview1",
|
"wasi 0.11.0+wasi-snapshot-preview1",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1586,9 +1588,11 @@ source = "registry+https://github.com/rust-lang/crates.io-index"
|
|||||||
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
checksum = "73fea8450eea4bac3940448fb7ae50d91f034f941199fcd9d909a5a07aa455f0"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cfg-if",
|
"cfg-if",
|
||||||
|
"js-sys",
|
||||||
"libc",
|
"libc",
|
||||||
"r-efi",
|
"r-efi",
|
||||||
"wasi 0.14.2+wasi-0.2.4",
|
"wasi 0.14.2+wasi-0.2.4",
|
||||||
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
@ -1886,6 +1890,24 @@ dependencies = [
|
|||||||
"want",
|
"want",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "hyper-rustls"
|
||||||
|
version = "0.27.5"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2d191583f3da1305256f22463b9bb0471acad48a4e534a5218b9963e9c1f59b2"
|
||||||
|
dependencies = [
|
||||||
|
"futures-util",
|
||||||
|
"http",
|
||||||
|
"hyper",
|
||||||
|
"hyper-util",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
|
"tower-service",
|
||||||
|
"webpki-roots",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "hyper-util"
|
name = "hyper-util"
|
||||||
version = "0.1.10"
|
version = "0.1.10"
|
||||||
@ -3448,6 +3470,60 @@ dependencies = [
|
|||||||
"memchr",
|
"memchr",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quinn"
|
||||||
|
version = "0.11.7"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "c3bd15a6f2967aef83887dcb9fec0014580467e33720d073560cf015a5683012"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"cfg_aliases",
|
||||||
|
"pin-project-lite",
|
||||||
|
"quinn-proto",
|
||||||
|
"quinn-udp",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"rustls",
|
||||||
|
"socket2",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tokio",
|
||||||
|
"tracing",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quinn-proto"
|
||||||
|
version = "0.11.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "b820744eb4dc9b57a3398183639c511b5a26d2ed702cedd3febaa1393caa22cc"
|
||||||
|
dependencies = [
|
||||||
|
"bytes",
|
||||||
|
"getrandom 0.3.2",
|
||||||
|
"rand 0.9.0",
|
||||||
|
"ring",
|
||||||
|
"rustc-hash 2.1.1",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pki-types",
|
||||||
|
"slab",
|
||||||
|
"thiserror 2.0.12",
|
||||||
|
"tinyvec",
|
||||||
|
"tracing",
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "quinn-udp"
|
||||||
|
version = "0.5.10"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "e46f3055866785f6b92bc6164b76be02ca8f2eb4b002c0354b28cf4c119e5944"
|
||||||
|
dependencies = [
|
||||||
|
"cfg_aliases",
|
||||||
|
"libc",
|
||||||
|
"once_cell",
|
||||||
|
"socket2",
|
||||||
|
"tracing",
|
||||||
|
"windows-sys 0.59.0",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "quote"
|
name = "quote"
|
||||||
version = "1.0.40"
|
version = "1.0.40"
|
||||||
@ -3673,6 +3749,7 @@ dependencies = [
|
|||||||
"http-body",
|
"http-body",
|
||||||
"http-body-util",
|
"http-body-util",
|
||||||
"hyper",
|
"hyper",
|
||||||
|
"hyper-rustls",
|
||||||
"hyper-util",
|
"hyper-util",
|
||||||
"ipnet",
|
"ipnet",
|
||||||
"js-sys",
|
"js-sys",
|
||||||
@ -3681,11 +3758,16 @@ dependencies = [
|
|||||||
"once_cell",
|
"once_cell",
|
||||||
"percent-encoding",
|
"percent-encoding",
|
||||||
"pin-project-lite",
|
"pin-project-lite",
|
||||||
|
"quinn",
|
||||||
|
"rustls",
|
||||||
|
"rustls-pemfile",
|
||||||
|
"rustls-pki-types",
|
||||||
"serde",
|
"serde",
|
||||||
"serde_json",
|
"serde_json",
|
||||||
"serde_urlencoded",
|
"serde_urlencoded",
|
||||||
"sync_wrapper",
|
"sync_wrapper",
|
||||||
"tokio",
|
"tokio",
|
||||||
|
"tokio-rustls",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
"tower",
|
"tower",
|
||||||
"tower-service",
|
"tower-service",
|
||||||
@ -3694,6 +3776,7 @@ dependencies = [
|
|||||||
"wasm-bindgen-futures",
|
"wasm-bindgen-futures",
|
||||||
"wasm-streams",
|
"wasm-streams",
|
||||||
"web-sys",
|
"web-sys",
|
||||||
|
"webpki-roots",
|
||||||
"windows-registry",
|
"windows-registry",
|
||||||
]
|
]
|
||||||
|
|
||||||
@ -3793,6 +3876,12 @@ version = "1.1.0"
|
|||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
checksum = "08d43f7aa6b08d49f382cde6a7982047c3426db949b1424bc4b7ec9ae12c6ce2"
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "rustc-hash"
|
||||||
|
version = "2.1.1"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "357703d41365b4b27c590e3ed91eabb1b663f07c4c084095e60cbed4362dff0d"
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustc_version"
|
name = "rustc_version"
|
||||||
version = "0.4.1"
|
version = "0.4.1"
|
||||||
@ -3837,6 +3926,7 @@ dependencies = [
|
|||||||
"aws-lc-rs",
|
"aws-lc-rs",
|
||||||
"log",
|
"log",
|
||||||
"once_cell",
|
"once_cell",
|
||||||
|
"ring",
|
||||||
"rustls-pki-types",
|
"rustls-pki-types",
|
||||||
"rustls-webpki",
|
"rustls-webpki",
|
||||||
"subtle",
|
"subtle",
|
||||||
@ -3857,6 +3947,9 @@ name = "rustls-pki-types"
|
|||||||
version = "1.11.0"
|
version = "1.11.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
checksum = "917ce264624a4b4db1c364dcc35bfca9ded014d0a958cd47ad3e960e988ea51c"
|
||||||
|
dependencies = [
|
||||||
|
"web-time",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "rustls-webpki"
|
name = "rustls-webpki"
|
||||||
@ -4707,9 +4800,9 @@ checksum = "61c41af27dd6d1e27b1b16b489db798443478cef1f06a660c96db617ba5de3b1"
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri"
|
name = "tauri"
|
||||||
version = "2.4.0"
|
version = "2.3.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "511dd38065a5d3b36c33cdba4362b99a40a5103bebcd4aebb930717e7c8ba292"
|
checksum = "3be747b26bf28674977fac47bdf6963fd9c7578271c3fbeb25d8686de6596f35"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"bytes",
|
"bytes",
|
||||||
@ -4757,9 +4850,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-build"
|
name = "tauri-build"
|
||||||
version = "2.1.0"
|
version = "2.0.6"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "7ffa8732a66f90903f5a585215f3cf1e87988d0359bc88c18a502efe7572c1de"
|
checksum = "51a2e96f3c0baa0581656bb58e6fdd0f7c9c31eaf6721a0c08689d938fe85f2d"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"cargo_toml",
|
"cargo_toml",
|
||||||
@ -4779,9 +4872,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-codegen"
|
name = "tauri-codegen"
|
||||||
version = "2.1.0"
|
version = "2.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "c266a247f14d63f40c6282c2653a8bac5cc3d482ca562a003a88513653ea817a"
|
checksum = "e357ec3daf8faad1029bc7109e7f5b308ceb63b6073d110d7388923a4cce5e55"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"base64 0.22.1",
|
"base64 0.22.1",
|
||||||
"brotli",
|
"brotli",
|
||||||
@ -4806,9 +4899,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-macros"
|
name = "tauri-macros"
|
||||||
version = "2.1.0"
|
version = "2.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "f47a1cf94b3bd6c4dc37dce1a43fc96120ff29a91757f0ab3cf713c7ad846e7c"
|
checksum = "447ee4dd94690d77f1422f2b57e783c654ba75c535ad6f6e727887330804fff2"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"heck 0.5.0",
|
"heck 0.5.0",
|
||||||
"proc-macro2",
|
"proc-macro2",
|
||||||
@ -4820,9 +4913,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-plugin"
|
name = "tauri-plugin"
|
||||||
version = "2.1.0"
|
version = "2.0.5"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9972871fcbddf16618f70412d965d4d845cd4b76d03fff168709961ef71e5cdf"
|
checksum = "0ad3021d8e60ec7672f51ecb67c5e1a514a4d7a9a5ffc9d85090739378047502"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
"anyhow",
|
||||||
"glob",
|
"glob",
|
||||||
@ -4937,11 +5030,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime"
|
name = "tauri-runtime"
|
||||||
version = "2.5.0"
|
version = "2.4.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "9e9c7bce5153f1ca7bc45eba37349b31ba50e975e28edc8b5766c5ec02b0b63a"
|
checksum = "e758a405ab39e25f4d1235c5f06fe563f44b01ee18bbe38ddec5356d4f581908"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"cookie",
|
|
||||||
"dpi",
|
"dpi",
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@ -4957,9 +5049,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-runtime-wry"
|
name = "tauri-runtime-wry"
|
||||||
version = "2.5.0"
|
version = "2.4.1"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "087188020fd6facb8578fe9b38e81fa0fe5fb85744c73da51a299f94a530a1e3"
|
checksum = "8b2beb90decade4c71e8b09c9e4a9245837a8a97693f945b77e32baf13f51fec"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"gtk",
|
"gtk",
|
||||||
"http",
|
"http",
|
||||||
@ -4984,11 +5076,10 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tauri-utils"
|
name = "tauri-utils"
|
||||||
version = "2.3.0"
|
version = "2.2.0"
|
||||||
source = "registry+https://github.com/rust-lang/crates.io-index"
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
checksum = "82dcced4014e59af9790cc22f5d271df3be09ecd6728ec68861642553c8d01b7"
|
checksum = "107a959dbd5ff53d89a98f6f2e3e987c611334141a43630caae1d80e79446dd6"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"anyhow",
|
|
||||||
"brotli",
|
"brotli",
|
||||||
"cargo_metadata",
|
"cargo_metadata",
|
||||||
"ctor",
|
"ctor",
|
||||||
@ -5198,6 +5289,16 @@ dependencies = [
|
|||||||
"syn 2.0.100",
|
"syn 2.0.100",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "tokio-rustls"
|
||||||
|
version = "0.26.2"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "8e727b36a1a0e8b74c376ac2211e40c2c8af09fb4013c60d910495810f008e9b"
|
||||||
|
dependencies = [
|
||||||
|
"rustls",
|
||||||
|
"tokio",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "tokio-stream"
|
name = "tokio-stream"
|
||||||
version = "0.1.17"
|
version = "0.1.17"
|
||||||
@ -5731,6 +5832,16 @@ dependencies = [
|
|||||||
"wasm-bindgen",
|
"wasm-bindgen",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "web-time"
|
||||||
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "5a6580f308b1fad9207618087a65c04e7a10bc77e02c8e84e9b00dd4b12fa0bb"
|
||||||
|
dependencies = [
|
||||||
|
"js-sys",
|
||||||
|
"wasm-bindgen",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webkit2gtk"
|
name = "webkit2gtk"
|
||||||
version = "2.0.1"
|
version = "2.0.1"
|
||||||
@ -5775,6 +5886,15 @@ dependencies = [
|
|||||||
"system-deps",
|
"system-deps",
|
||||||
]
|
]
|
||||||
|
|
||||||
|
[[package]]
|
||||||
|
name = "webpki-roots"
|
||||||
|
version = "0.26.8"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "2210b291f7ea53617fbafcc4939f10914214ec15aace5ba62293a668f322c5c9"
|
||||||
|
dependencies = [
|
||||||
|
"rustls-pki-types",
|
||||||
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "webview2-com"
|
name = "webview2-com"
|
||||||
version = "0.36.0"
|
version = "0.36.0"
|
||||||
|
@ -1,487 +1,487 @@
|
|||||||
use std::{
|
use std::{
|
||||||
collections::HashSet,
|
collections::HashSet,
|
||||||
net::SocketAddr,
|
net::SocketAddr,
|
||||||
path::{Path, PathBuf},
|
path::{Path, PathBuf},
|
||||||
sync::Arc,
|
sync::Arc,
|
||||||
};
|
};
|
||||||
|
|
||||||
use eyre::bail;
|
use eyre::bail;
|
||||||
use lanspread_client::{ClientCommand, ClientEvent};
|
use lanspread_client::{ClientCommand, ClientEvent};
|
||||||
use lanspread_db::db::{Game, GameDB};
|
use lanspread_db::db::{Game, GameDB};
|
||||||
use lanspread_mdns::{LANSPREAD_INSTANCE_NAME, LANSPREAD_SERVICE_TYPE, discover_service};
|
use lanspread_mdns::{LANSPREAD_INSTANCE_NAME, LANSPREAD_SERVICE_TYPE, discover_service};
|
||||||
use tauri::{AppHandle, Emitter as _, Manager};
|
use tauri::{AppHandle, Emitter as _, Manager};
|
||||||
use tauri_plugin_shell::{ShellExt, process::Command};
|
use tauri_plugin_shell::{ShellExt, process::Command};
|
||||||
use tokio::sync::{Mutex, mpsc::UnboundedSender};
|
use tokio::sync::{Mutex, mpsc::UnboundedSender};
|
||||||
|
|
||||||
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
// Learn more about Tauri commands at https://tauri.app/develop/calling-rust/
|
||||||
|
|
||||||
struct LanSpreadState {
|
struct LanSpreadState {
|
||||||
server_addr: Mutex<Option<SocketAddr>>,
|
server_addr: Mutex<Option<SocketAddr>>,
|
||||||
client_ctrl: UnboundedSender<ClientCommand>,
|
client_ctrl: UnboundedSender<ClientCommand>,
|
||||||
games: Arc<Mutex<GameDB>>,
|
games: Arc<Mutex<GameDB>>,
|
||||||
games_in_download: Arc<Mutex<HashSet<String>>>,
|
games_in_download: Arc<Mutex<HashSet<String>>>,
|
||||||
games_folder: Arc<Mutex<String>>,
|
games_folder: Arc<Mutex<String>>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn request_games(state: tauri::State<LanSpreadState>) {
|
fn request_games(state: tauri::State<LanSpreadState>) {
|
||||||
log::debug!("request_games");
|
log::debug!("request_games");
|
||||||
|
|
||||||
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::ListGames) {
|
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::ListGames) {
|
||||||
log::error!("Failed to send message to client: {e:?}");
|
log::error!("Failed to send message to client: {e:?}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn install_game(id: String, state: tauri::State<LanSpreadState>) -> bool {
|
fn install_game(id: String, state: tauri::State<LanSpreadState>) -> bool {
|
||||||
let already_in_download = tauri::async_runtime::block_on(async {
|
let already_in_download = tauri::async_runtime::block_on(async {
|
||||||
if state.inner().games_in_download.lock().await.contains(&id) {
|
if state.inner().games_in_download.lock().await.contains(&id) {
|
||||||
log::warn!("Game is already downloading: {id}");
|
log::warn!("Game is already downloading: {id}");
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
false
|
false
|
||||||
});
|
});
|
||||||
|
|
||||||
if already_in_download {
|
if already_in_download {
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::GetGame(id)) {
|
if let Err(e) = state.inner().client_ctrl.send(ClientCommand::GetGame(id)) {
|
||||||
log::error!("Failed to send message to client: {e:?}");
|
log::error!("Failed to send message to client: {e:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
true
|
true
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn run_as_admin(file: &str, params: &str, dir: &str) -> bool {
|
fn run_as_admin(file: &str, params: &str, dir: &str) -> bool {
|
||||||
use std::{ffi::OsStr, os::windows::ffi::OsStrExt};
|
use std::{ffi::OsStr, os::windows::ffi::OsStrExt};
|
||||||
|
|
||||||
use windows::{Win32::UI::Shell::ShellExecuteW, core::PCWSTR};
|
use windows::{Win32::UI::Shell::ShellExecuteW, core::PCWSTR};
|
||||||
|
|
||||||
let file_wide: Vec<u16> = OsStr::new(file).encode_wide().chain(Some(0)).collect();
|
let file_wide: Vec<u16> = OsStr::new(file).encode_wide().chain(Some(0)).collect();
|
||||||
let params_wide: Vec<u16> = OsStr::new(params).encode_wide().chain(Some(0)).collect();
|
let params_wide: Vec<u16> = OsStr::new(params).encode_wide().chain(Some(0)).collect();
|
||||||
let dir_wide: Vec<u16> = OsStr::new(dir).encode_wide().chain(Some(0)).collect();
|
let dir_wide: Vec<u16> = OsStr::new(dir).encode_wide().chain(Some(0)).collect();
|
||||||
let runas_wide: Vec<u16> = OsStr::new("runas").encode_wide().chain(Some(0)).collect();
|
let runas_wide: Vec<u16> = OsStr::new("runas").encode_wide().chain(Some(0)).collect();
|
||||||
|
|
||||||
let result = unsafe {
|
let result = unsafe {
|
||||||
ShellExecuteW(
|
ShellExecuteW(
|
||||||
None,
|
None,
|
||||||
PCWSTR::from_raw(runas_wide.as_ptr()),
|
PCWSTR::from_raw(runas_wide.as_ptr()),
|
||||||
PCWSTR::from_raw(file_wide.as_ptr()),
|
PCWSTR::from_raw(file_wide.as_ptr()),
|
||||||
PCWSTR::from_raw(params_wide.as_ptr()),
|
PCWSTR::from_raw(params_wide.as_ptr()),
|
||||||
PCWSTR::from_raw(dir_wide.as_ptr()),
|
PCWSTR::from_raw(dir_wide.as_ptr()),
|
||||||
windows::Win32::UI::WindowsAndMessaging::SW_HIDE,
|
windows::Win32::UI::WindowsAndMessaging::SW_SHOWNORMAL,
|
||||||
)
|
)
|
||||||
};
|
};
|
||||||
|
|
||||||
(result.0 as usize) > 32 // Success if greater than 32
|
(result.0 as usize) > 32 // Success if greater than 32
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
fn run_game_windows(id: String, state: tauri::State<LanSpreadState>) {
|
fn run_game_windows(id: String, state: tauri::State<LanSpreadState>) {
|
||||||
use std::fs::File;
|
use std::fs::File;
|
||||||
|
|
||||||
const FIRST_START_DONE_FILE: &str = ".softlan_first_start_done";
|
const FIRST_START_DONE_FILE: &str = ".softlan_first_start_done";
|
||||||
|
|
||||||
let games_folder =
|
let games_folder =
|
||||||
tauri::async_runtime::block_on(async { state.inner().games_folder.lock().await.clone() });
|
tauri::async_runtime::block_on(async { state.inner().games_folder.lock().await.clone() });
|
||||||
|
|
||||||
let games_folder = PathBuf::from(games_folder);
|
let games_folder = PathBuf::from(games_folder);
|
||||||
if !games_folder.exists() {
|
if !games_folder.exists() {
|
||||||
log::error!("games_folder {games_folder:?} does not exist");
|
log::error!("games_folder {games_folder:?} does not exist");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
let game_path = games_folder.join(id.clone());
|
let game_path = games_folder.join(id.clone());
|
||||||
|
|
||||||
let game_setup_bin = game_path.join("game_setup.cmd");
|
let game_setup_bin = game_path.join("game_setup.cmd");
|
||||||
let game_start_bin = game_path.join("game_start.cmd");
|
let game_start_bin = game_path.join("game_start.cmd");
|
||||||
|
|
||||||
let first_start_done_file = game_path.join(FIRST_START_DONE_FILE);
|
let first_start_done_file = game_path.join(FIRST_START_DONE_FILE);
|
||||||
if !first_start_done_file.exists() && game_setup_bin.exists() {
|
if !first_start_done_file.exists() && game_setup_bin.exists() {
|
||||||
let result = run_as_admin(
|
let result = run_as_admin(
|
||||||
"cmd.exe",
|
"cmd.exe",
|
||||||
&format!(
|
&format!(
|
||||||
r#"/c "{} local {} de playername""#,
|
r#"/c "{} local {} de playername""#,
|
||||||
game_setup_bin.display(),
|
game_setup_bin.display(),
|
||||||
&id
|
&id
|
||||||
),
|
),
|
||||||
&game_path.display().to_string(),
|
&game_path.display().to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !result {
|
if !result {
|
||||||
log::error!("failed to run game_setup.cmd");
|
log::error!("failed to run game_setup.cmd");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if let Err(e) = File::create(&first_start_done_file) {
|
if let Err(e) = File::create(&first_start_done_file) {
|
||||||
log::error!("failed to create {first_start_done_file:?}: {e}");
|
log::error!("failed to create {first_start_done_file:?}: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if game_start_bin.exists() {
|
if game_start_bin.exists() {
|
||||||
let result = run_as_admin(
|
let result = run_as_admin(
|
||||||
"cmd.exe",
|
"cmd.exe",
|
||||||
&format!(
|
&format!(
|
||||||
r#"/c "{} local {} de playername""#,
|
r#"/c "{} local {} de playername""#,
|
||||||
game_start_bin.display(),
|
game_start_bin.display(),
|
||||||
&id
|
&id
|
||||||
),
|
),
|
||||||
&game_path.display().to_string(),
|
&game_path.display().to_string(),
|
||||||
);
|
);
|
||||||
|
|
||||||
if !result {
|
if !result {
|
||||||
log::error!("failed to run game_start.cmd");
|
log::error!("failed to run game_start.cmd");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn run_game(id: String, state: tauri::State<LanSpreadState>) {
|
fn run_game(id: String, state: tauri::State<LanSpreadState>) {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
run_game_windows(id, state);
|
run_game_windows(id, state);
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
log::error!("run_game not implemented for this platform: id={id}, state={state:?}");
|
log::error!("run_game not implemented for this platform: id={id}, state={state:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
fn set_game_install_state_from_path(game_db: &mut GameDB, path: &Path, installed: bool) {
|
fn set_game_install_state_from_path(game_db: &mut GameDB, path: &Path, installed: bool) {
|
||||||
if let Some(file_name) = path.file_name() {
|
if let Some(file_name) = path.file_name() {
|
||||||
if let Some(file_name) = file_name.to_str() {
|
if let Some(file_name) = file_name.to_str() {
|
||||||
if let Some(game) = game_db.get_mut_game_by_id(file_name) {
|
if let Some(game) = game_db.get_mut_game_by_id(file_name) {
|
||||||
if installed {
|
if installed {
|
||||||
log::debug!("Game is installed: {game}");
|
log::debug!("Game is installed: {game}");
|
||||||
} else {
|
} else {
|
||||||
log::error!("Game is missing: {game}");
|
log::error!("Game is missing: {game}");
|
||||||
}
|
}
|
||||||
game.installed = installed;
|
game.installed = installed;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[tauri::command]
|
#[tauri::command]
|
||||||
fn update_game_directory(app_handle: tauri::AppHandle, path: String) {
|
fn update_game_directory(app_handle: tauri::AppHandle, path: String) {
|
||||||
log::info!("update_game_directory: {path}");
|
log::info!("update_game_directory: {path}");
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.client_ctrl
|
.client_ctrl
|
||||||
.send(ClientCommand::SetGameDir(path.clone()))
|
.send(ClientCommand::SetGameDir(path.clone()))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
{
|
{
|
||||||
tauri::async_runtime::block_on(async {
|
tauri::async_runtime::block_on(async {
|
||||||
let mut games_folder = app_handle
|
let mut games_folder = app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games_folder
|
.games_folder
|
||||||
.lock()
|
.lock()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
*games_folder = path.clone();
|
*games_folder = path.clone();
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
let path = PathBuf::from(path);
|
let path = PathBuf::from(path);
|
||||||
if !path.exists() {
|
if !path.exists() {
|
||||||
log::error!("game dir {path:?} does not exist");
|
log::error!("game dir {path:?} does not exist");
|
||||||
}
|
}
|
||||||
|
|
||||||
let entries = match path.read_dir() {
|
let entries = match path.read_dir() {
|
||||||
Ok(entries) => entries,
|
Ok(entries) => entries,
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::error!("Failed to read game dir: {e}");
|
log::error!("Failed to read game dir: {e}");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
let mut game_db = app_handle
|
let mut game_db = app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games
|
.games
|
||||||
.lock()
|
.lock()
|
||||||
.await;
|
.await;
|
||||||
|
|
||||||
// Reset all games to uninstalled
|
// Reset all games to uninstalled
|
||||||
game_db.set_all_uninstalled();
|
game_db.set_all_uninstalled();
|
||||||
|
|
||||||
// update game_db with installed games from real game directory
|
// update game_db with installed games from real game directory
|
||||||
entries.into_iter().for_each(|entry| {
|
entries.into_iter().for_each(|entry| {
|
||||||
if let Ok(entry) = entry {
|
if let Ok(entry) = entry {
|
||||||
if let Ok(path_type) = entry.file_type() {
|
if let Ok(path_type) = entry.file_type() {
|
||||||
if path_type.is_dir() {
|
if path_type.is_dir() {
|
||||||
let path = entry.path();
|
let path = entry.path();
|
||||||
if path.join("version.ini").exists() {
|
if path.join("version.ini").exists() {
|
||||||
set_game_install_state_from_path(&mut game_db, &path, true);
|
set_game_install_state_from_path(&mut game_db, &path, true);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
if let Err(e) = app_handle.emit("games-list-updated", Some(game_db.all_games())) {
|
if let Err(e) = app_handle.emit("games-list-updated", Some(game_db.all_games())) {
|
||||||
log::error!("Failed to emit games-list-updated event: {e}");
|
log::error!("Failed to emit games-list-updated event: {e}");
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn find_server(app: AppHandle) {
|
async fn find_server(app: AppHandle) {
|
||||||
log::info!("Looking for server...");
|
log::info!("Looking for server...");
|
||||||
|
|
||||||
loop {
|
loop {
|
||||||
match discover_service(LANSPREAD_SERVICE_TYPE, Some(LANSPREAD_INSTANCE_NAME)) {
|
match discover_service(LANSPREAD_SERVICE_TYPE, Some(LANSPREAD_INSTANCE_NAME)) {
|
||||||
Ok(server_addr) => {
|
Ok(server_addr) => {
|
||||||
log::info!("Found server at {server_addr}");
|
log::info!("Found server at {server_addr}");
|
||||||
let state: tauri::State<LanSpreadState> = app.state();
|
let state: tauri::State<LanSpreadState> = app.state();
|
||||||
{
|
{
|
||||||
// mutex scope
|
// mutex scope
|
||||||
let mut addr = state.server_addr.lock().await;
|
let mut addr = state.server_addr.lock().await;
|
||||||
*addr = Some(server_addr);
|
*addr = Some(server_addr);
|
||||||
}
|
}
|
||||||
state
|
state
|
||||||
.client_ctrl
|
.client_ctrl
|
||||||
.send(ClientCommand::ServerAddr(server_addr))
|
.send(ClientCommand::ServerAddr(server_addr))
|
||||||
.unwrap();
|
.unwrap();
|
||||||
request_games(state);
|
request_games(state);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
Err(e) => {
|
Err(e) => {
|
||||||
log::warn!("Failed to find server: {e} - retrying...");
|
log::warn!("Failed to find server: {e} - retrying...");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn update_game_db(games: Vec<Game>, app: AppHandle) {
|
async fn update_game_db(games: Vec<Game>, app: AppHandle) {
|
||||||
for game in &games {
|
for game in &games {
|
||||||
log::trace!("client event ListGames iter: {game:?}");
|
log::trace!("client event ListGames iter: {game:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
let state = app.state::<LanSpreadState>();
|
let state = app.state::<LanSpreadState>();
|
||||||
|
|
||||||
// Store games list
|
// Store games list
|
||||||
let mut state_games = state.games.lock().await;
|
let mut state_games = state.games.lock().await;
|
||||||
*state_games = GameDB::from(games.clone());
|
*state_games = GameDB::from(games.clone());
|
||||||
|
|
||||||
// Tell Frontend about new games list
|
// Tell Frontend about new games list
|
||||||
if let Err(e) = app.emit("games-list-updated", Some(games)) {
|
if let Err(e) = app.emit("games-list-updated", Some(games)) {
|
||||||
log::error!("Failed to emit games-list-updated event: {e}");
|
log::error!("Failed to emit games-list-updated event: {e}");
|
||||||
} else {
|
} else {
|
||||||
log::info!("Emitted games-list-updated event");
|
log::info!("Emitted games-list-updated event");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn add_final_slash(path: &str) -> String {
|
fn add_final_slash(path: &str) -> String {
|
||||||
#[cfg(target_os = "windows")]
|
#[cfg(target_os = "windows")]
|
||||||
const SLASH_CHAR: char = '\\';
|
const SLASH_CHAR: char = '\\';
|
||||||
|
|
||||||
#[cfg(not(target_os = "windows"))]
|
#[cfg(not(target_os = "windows"))]
|
||||||
const SLASH_CHAR: char = '/';
|
const SLASH_CHAR: char = '/';
|
||||||
|
|
||||||
if path.ends_with(SLASH_CHAR) {
|
if path.ends_with(SLASH_CHAR) {
|
||||||
path.to_string()
|
path.to_string()
|
||||||
} else {
|
} else {
|
||||||
format!("{path}{SLASH_CHAR}")
|
format!("{path}{SLASH_CHAR}")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn do_unrar(sidecar: Command, rar_file: &Path, dest_dir: &Path) -> eyre::Result<()> {
|
async fn do_unrar(sidecar: Command, rar_file: &Path, dest_dir: &Path) -> eyre::Result<()> {
|
||||||
if let Ok(()) = std::fs::create_dir_all(dest_dir) {
|
if let Ok(()) = std::fs::create_dir_all(dest_dir) {
|
||||||
if let Ok(rar_file) = rar_file.canonicalize() {
|
if let Ok(rar_file) = rar_file.canonicalize() {
|
||||||
if let Ok(dest_dir) = dest_dir.canonicalize() {
|
if let Ok(dest_dir) = dest_dir.canonicalize() {
|
||||||
let dest_dir = dest_dir
|
let dest_dir = dest_dir
|
||||||
.to_str()
|
.to_str()
|
||||||
.ok_or_else(|| eyre::eyre!("failed to get str of dest_dir"))?;
|
.ok_or_else(|| eyre::eyre!("failed to get str of dest_dir"))?;
|
||||||
|
|
||||||
log::info!(
|
log::info!(
|
||||||
"unrar game: {} to {}",
|
"unrar game: {} to {}",
|
||||||
rar_file.canonicalize()?.display(),
|
rar_file.canonicalize()?.display(),
|
||||||
dest_dir
|
dest_dir
|
||||||
);
|
);
|
||||||
|
|
||||||
let out = sidecar
|
let out = sidecar
|
||||||
.arg("x") // extract files
|
.arg("x") // extract files
|
||||||
.arg(rar_file.canonicalize()?)
|
.arg(rar_file.canonicalize()?)
|
||||||
.arg("-y") // Assume Yes on all queries
|
.arg("-y") // Assume Yes on all queries
|
||||||
.arg("-o") // Set overwrite mode
|
.arg("-o") // Set overwrite mode
|
||||||
.arg(add_final_slash(dest_dir))
|
.arg(add_final_slash(dest_dir))
|
||||||
.output()
|
.output()
|
||||||
.await?;
|
.await?;
|
||||||
|
|
||||||
if !out.status.success() {
|
if !out.status.success() {
|
||||||
log::error!("unrar stderr: {}", String::from_utf8_lossy(&out.stderr));
|
log::error!("unrar stderr: {}", String::from_utf8_lossy(&out.stderr));
|
||||||
}
|
}
|
||||||
|
|
||||||
return Ok(());
|
return Ok(());
|
||||||
} else {
|
} else {
|
||||||
log::error!("dest_dir canonicalize failed: {:?}", &dest_dir);
|
log::error!("dest_dir canonicalize failed: {:?}", &dest_dir);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("rar_file canonicalize failed: {:?}", &rar_file);
|
log::error!("rar_file canonicalize failed: {:?}", &rar_file);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
log::error!("failed to create dest_dir: {:?}", &dest_dir);
|
log::error!("failed to create dest_dir: {:?}", &dest_dir);
|
||||||
}
|
}
|
||||||
|
|
||||||
bail!("failed to create directory: {dest_dir:?}");
|
bail!("failed to create directory: {dest_dir:?}");
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn unpack_game(id: &str, sidecar: Command, games_folder: String) {
|
async fn unpack_game(id: &str, sidecar: Command, games_folder: String) {
|
||||||
let game_path = PathBuf::from(games_folder).join(id);
|
let game_path = PathBuf::from(games_folder).join(id);
|
||||||
let eti_rar = game_path.join(format!("{id}.eti"));
|
let eti_rar = game_path.join(format!("{id}.eti"));
|
||||||
let local_path = game_path.join("local");
|
let local_path = game_path.join("local");
|
||||||
|
|
||||||
if let Err(e) = do_unrar(sidecar, &eti_rar, &local_path).await {
|
if let Err(e) = do_unrar(sidecar, &eti_rar, &local_path).await {
|
||||||
log::error!("{eti_rar:?} -> {local_path:?}: {e}");
|
log::error!("{eti_rar:?} -> {local_path:?}: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
#[cfg_attr(mobile, tauri::mobile_entry_point)]
|
||||||
pub fn run() {
|
pub fn run() {
|
||||||
let tauri_logger_builder = tauri_plugin_log::Builder::new()
|
let tauri_logger_builder = tauri_plugin_log::Builder::new()
|
||||||
.clear_targets()
|
.clear_targets()
|
||||||
.target(tauri_plugin_log::Target::new(
|
.target(tauri_plugin_log::Target::new(
|
||||||
tauri_plugin_log::TargetKind::Stdout,
|
tauri_plugin_log::TargetKind::Stdout,
|
||||||
))
|
))
|
||||||
.level(log::LevelFilter::Info)
|
.level(log::LevelFilter::Info)
|
||||||
.level_for("mdns_sd::service_daemon", log::LevelFilter::Off);
|
.level_for("mdns_sd::service_daemon", log::LevelFilter::Off);
|
||||||
|
|
||||||
// channel to pass commands to the client
|
// channel to pass commands to the client
|
||||||
let (tx_client_control, rx_client_control) =
|
let (tx_client_control, rx_client_control) =
|
||||||
tokio::sync::mpsc::unbounded_channel::<ClientCommand>();
|
tokio::sync::mpsc::unbounded_channel::<ClientCommand>();
|
||||||
|
|
||||||
// channel to receive events from the client
|
// channel to receive events from the client
|
||||||
let (tx_client_event, mut rx_client_event) =
|
let (tx_client_event, mut rx_client_event) =
|
||||||
tokio::sync::mpsc::unbounded_channel::<ClientEvent>();
|
tokio::sync::mpsc::unbounded_channel::<ClientEvent>();
|
||||||
|
|
||||||
let lanspread_state = LanSpreadState {
|
let lanspread_state = LanSpreadState {
|
||||||
server_addr: Mutex::new(None),
|
server_addr: Mutex::new(None),
|
||||||
client_ctrl: tx_client_control,
|
client_ctrl: tx_client_control,
|
||||||
games: Arc::new(Mutex::new(GameDB::empty())),
|
games: Arc::new(Mutex::new(GameDB::empty())),
|
||||||
games_in_download: Arc::new(Mutex::new(HashSet::new())),
|
games_in_download: Arc::new(Mutex::new(HashSet::new())),
|
||||||
games_folder: Arc::new(Mutex::new("".to_string())),
|
games_folder: Arc::new(Mutex::new("".to_string())),
|
||||||
};
|
};
|
||||||
|
|
||||||
tauri::Builder::default()
|
tauri::Builder::default()
|
||||||
.plugin(tauri_plugin_store::Builder::new().build())
|
.plugin(tauri_plugin_store::Builder::new().build())
|
||||||
.plugin(tauri_plugin_dialog::init())
|
.plugin(tauri_plugin_dialog::init())
|
||||||
.plugin(tauri_logger_builder.build())
|
.plugin(tauri_logger_builder.build())
|
||||||
.plugin(tauri_plugin_shell::init())
|
.plugin(tauri_plugin_shell::init())
|
||||||
.invoke_handler(tauri::generate_handler![
|
.invoke_handler(tauri::generate_handler![
|
||||||
request_games,
|
request_games,
|
||||||
install_game,
|
install_game,
|
||||||
run_game,
|
run_game,
|
||||||
update_game_directory
|
update_game_directory
|
||||||
])
|
])
|
||||||
.manage(lanspread_state)
|
.manage(lanspread_state)
|
||||||
.setup(|app| {
|
.setup(|app| {
|
||||||
let app_handle = app.handle().clone();
|
let app_handle = app.handle().clone();
|
||||||
// discover server
|
// discover server
|
||||||
tauri::async_runtime::spawn(async move { find_server(app_handle).await });
|
tauri::async_runtime::spawn(async move { find_server(app_handle).await });
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
lanspread_client::run(rx_client_control, tx_client_event).await
|
lanspread_client::run(rx_client_control, tx_client_event).await
|
||||||
});
|
});
|
||||||
|
|
||||||
let app_handle = app.handle().clone();
|
let app_handle = app.handle().clone();
|
||||||
tauri::async_runtime::spawn(async move {
|
tauri::async_runtime::spawn(async move {
|
||||||
while let Some(event) = rx_client_event.recv().await {
|
while let Some(event) = rx_client_event.recv().await {
|
||||||
match event {
|
match event {
|
||||||
ClientEvent::ListGames(games) => {
|
ClientEvent::ListGames(games) => {
|
||||||
log::info!("ClientEvent::ListGames received");
|
log::info!("ClientEvent::ListGames received");
|
||||||
update_game_db(games, app_handle.clone()).await;
|
update_game_db(games, app_handle.clone()).await;
|
||||||
}
|
}
|
||||||
ClientEvent::GotGameFiles { id, file_descriptions } => {
|
ClientEvent::GotGameFiles { id, file_descriptions } => {
|
||||||
log::info!("ClientEvent::GotGameFiles received");
|
log::info!("ClientEvent::GotGameFiles received");
|
||||||
|
|
||||||
if let Err(e) = app_handle.emit(
|
if let Err(e) = app_handle.emit(
|
||||||
"game-download-pre",
|
"game-download-pre",
|
||||||
Some(id.clone()),
|
Some(id.clone()),
|
||||||
) {
|
) {
|
||||||
log::error!("ClientEvent::GotGameFiles: Failed to emit game-download-pre event: {e}");
|
log::error!("ClientEvent::GotGameFiles: Failed to emit game-download-pre event: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.client_ctrl
|
.client_ctrl
|
||||||
.send(ClientCommand::DownloadGameFiles{
|
.send(ClientCommand::DownloadGameFiles{
|
||||||
id,
|
id,
|
||||||
file_descriptions,
|
file_descriptions,
|
||||||
})
|
})
|
||||||
.unwrap();
|
.unwrap();
|
||||||
|
|
||||||
}
|
}
|
||||||
ClientEvent::DownloadGameFilesBegin { id } => {
|
ClientEvent::DownloadGameFilesBegin { id } => {
|
||||||
log::info!("ClientEvent::DownloadGameFilesBegin received");
|
log::info!("ClientEvent::DownloadGameFilesBegin received");
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games_in_download
|
.games_in_download
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.insert(id.clone());
|
.insert(id.clone());
|
||||||
|
|
||||||
if let Err(e) = app_handle.emit("game-download-begin", Some(id)) {
|
if let Err(e) = app_handle.emit("game-download-begin", Some(id)) {
|
||||||
log::error!("ClientEvent::DownloadGameFilesBegin: Failed to emit game-download-begin event: {e}");
|
log::error!("ClientEvent::DownloadGameFilesBegin: Failed to emit game-download-begin event: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientEvent::DownloadGameFilesFinished { id } => {
|
ClientEvent::DownloadGameFilesFinished { id } => {
|
||||||
log::info!("ClientEvent::DownloadGameFilesFinished received");
|
log::info!("ClientEvent::DownloadGameFilesFinished received");
|
||||||
if let Err(e) = app_handle.emit("game-download-finished", Some(id.clone())) {
|
if let Err(e) = app_handle.emit("game-download-finished", Some(id.clone())) {
|
||||||
log::error!("ClientEvent::DownloadGameFilesFinished: Failed to emit game-download-finished event: {e}");
|
log::error!("ClientEvent::DownloadGameFilesFinished: Failed to emit game-download-finished event: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games_in_download
|
.games_in_download
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.remove(&id.clone());
|
.remove(&id.clone());
|
||||||
|
|
||||||
|
|
||||||
let games_folder = app_handle
|
let games_folder = app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games_folder
|
.games_folder
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.clone();
|
.clone();
|
||||||
|
|
||||||
if let Ok(sidecar) = app_handle.shell().sidecar("unrar") {
|
if let Ok(sidecar) = app_handle.shell().sidecar("unrar") {
|
||||||
unpack_game(&id, sidecar, games_folder).await;
|
unpack_game(&id, sidecar, games_folder).await;
|
||||||
|
|
||||||
log::info!("ClientEvent::UnpackGameFinished received");
|
log::info!("ClientEvent::UnpackGameFinished received");
|
||||||
if let Err(e) = app_handle.emit("game-unpack-finished", Some(id.clone())) {
|
if let Err(e) = app_handle.emit("game-unpack-finished", Some(id.clone())) {
|
||||||
log::error!("ClientEvent::UnpackGameFinished: Failed to emit game-unpack-finished event: {e}");
|
log::error!("ClientEvent::UnpackGameFinished: Failed to emit game-unpack-finished event: {e}");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ClientEvent::DownloadGameFilesFailed { id } => {
|
ClientEvent::DownloadGameFilesFailed { id } => {
|
||||||
log::warn!("ClientEvent::DownloadGameFilesFailed received");
|
log::warn!("ClientEvent::DownloadGameFilesFailed received");
|
||||||
|
|
||||||
if let Err(e) = app_handle.emit("game-download-failed", Some(id.clone())) {
|
if let Err(e) = app_handle.emit("game-download-failed", Some(id.clone())) {
|
||||||
log::error!("Failed to emit game-download-failed event: {e}");
|
log::error!("Failed to emit game-download-failed event: {e}");
|
||||||
}
|
}
|
||||||
|
|
||||||
app_handle
|
app_handle
|
||||||
.state::<LanSpreadState>()
|
.state::<LanSpreadState>()
|
||||||
.inner()
|
.inner()
|
||||||
.games_in_download
|
.games_in_download
|
||||||
.lock()
|
.lock()
|
||||||
.await
|
.await
|
||||||
.remove(&id.clone());
|
.remove(&id.clone());
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
Ok(())
|
Ok(())
|
||||||
})
|
})
|
||||||
.run(tauri::generate_context!())
|
.run(tauri::generate_context!())
|
||||||
.expect("error while running tauri application");
|
.expect("error while running tauri application");
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user