diff --git a/src-tauri/Cargo.lock b/src-tauri/Cargo.lock index 69ca4bc..00a7ef6 100644 --- a/src-tauri/Cargo.lock +++ b/src-tauri/Cargo.lock @@ -8,6 +8,17 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "aes" +version = "0.8.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b169f7a6d4742236a0a00c541b845991d0ac43e546831af1249753ab4c3aa3a0" +dependencies = [ + "cfg-if", + "cipher", + "cpufeatures", +] + [[package]] name = "ahash" version = "0.7.8" @@ -79,6 +90,7 @@ checksum = "a23eb6b1614318a8071c9b2521f36b424b2c83db5eb3a0fead4a6c0809af6e61" name = "app" version = "0.1.0" dependencies = [ + "async-runtime", "log", "network-interface", "serde", @@ -88,6 +100,18 @@ dependencies = [ "tauri-plugin-dialog", "tauri-plugin-fs", "tauri-plugin-log", + "thiserror 2.0.17", + "tokio", + "zip", +] + +[[package]] +name = "arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c3d036a3c4ab069c7b410a2ce876bd74808d2d0888a82667669f8e783a898bf1" +dependencies = [ + "derive_arbitrary", ] [[package]] @@ -140,6 +164,12 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "async-runtime" +version = "0.0.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "47480253cb834453b5c18d7a1fa50afdc6eb330cc90f7788c79368e7d0f61ec9" + [[package]] name = "async-trait" version = "0.1.89" @@ -356,6 +386,15 @@ dependencies = [ "serde", ] +[[package]] +name = "bzip2" +version = "0.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f3a53fac24f34a81bc9954b5d6cfce0c21e18ec6959f44f56e8e90e4bb7c346c" +dependencies = [ + "libbz2-rs-sys", +] + [[package]] name = "cairo-rs" version = "0.18.5" @@ -430,6 +469,8 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "37521ac7aabe3d13122dc382493e20c9416f299d2ccd5b3a5340a2570cdeb0f3" dependencies = [ "find-msvc-tools", + "jobserver", + "libc", "shlex", ] @@ -484,6 +525,16 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "cipher" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "773f3b9af64447d2ce9850330c473515014aa235e6a783b02db81ff39e4a3dad" +dependencies = [ + "crypto-common", + "inout", +] + [[package]] name = "combine" version = "4.6.7" @@ -503,6 +554,12 @@ dependencies = [ "crossbeam-utils", ] +[[package]] +name = "constant_time_eq" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7c74b8349d32d297c9134b8c88677813a227df8f779daa29bfc29c183fe3dca6" + [[package]] name = "convert_case" version = "0.4.0" @@ -674,6 +731,12 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "deflate64" +version = "0.1.10" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "26bf8fc351c5ed29b5c2f0cbbac1b209b74f60ecd62e675a998df72c49af5204" + [[package]] name = "deranged" version = "0.5.5" @@ -684,6 +747,17 @@ dependencies = [ "serde_core", ] +[[package]] +name = "derive_arbitrary" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1e567bd82dcff979e4b03460c307b3cdc9e96fde3d73bed1496d2bc75d9dd62a" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "derive_more" version = "0.99.20" @@ -705,6 +779,7 @@ checksum = "9ed9a281f7bc9b7576e61468ba615a66a5c8cfdff42420a70aa82701a3b1e292" dependencies = [ "block-buffer", "crypto-common", + "subtle", ] [[package]] @@ -983,6 +1058,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "bfe33edd8e85a12a67454e37f8c75e730830d83e313556ab9ebf9ee7fbeb3bfb" dependencies = [ "crc32fast", + "libz-rs-sys", "miniz_oxide", ] @@ -1462,6 +1538,15 @@ version = "0.4.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7f24254aa9a54b5c858eaee2f5bccdb46aaf0e486a595ed5fd8f86ba55232a70" +[[package]] +name = "hmac" +version = "0.12.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c49c37c09c17a53d937dfbb742eb3a961d65a994e6bcdcf37e7399d0cc8ab5e" +dependencies = [ + "digest", +] + [[package]] name = "html5ever" version = "0.29.1" @@ -1733,6 +1818,15 @@ dependencies = [ "cfb", ] +[[package]] +name = "inout" +version = "0.1.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "879f10e63c20629ecabbb64a8010319738c66a5cd0c29b02d63d272b03751d01" +dependencies = [ + "generic-array", +] + [[package]] name = "ipnet" version = "2.11.0" @@ -1800,6 +1894,16 @@ version = "0.3.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "8eaf4bc02d17cbdd7ff4c7438cafcdf7fb9a4613313ad11b4f8fefe7d3fa0130" +[[package]] +name = "jobserver" +version = "0.1.34" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "9afb3de4395d6b3e67a780b6de64b51c978ecf11cb9a462c66be7d4ca9039d33" +dependencies = [ + "getrandom 0.3.4", + "libc", +] + [[package]] name = "js-sys" version = "0.3.82" @@ -1885,6 +1989,12 @@ dependencies = [ "once_cell", ] +[[package]] +name = "libbz2-rs-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2c4a545a15244c7d945065b5d392b2d2d7f21526fba56ce51467b06ed445e8f7" + [[package]] name = "libc" version = "0.2.177" @@ -1901,6 +2011,26 @@ dependencies = [ "winapi", ] +[[package]] +name = "liblzma" +version = "0.4.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "73c36d08cad03a3fbe2c4e7bb3a9e84c57e4ee4135ed0b065cade3d98480c648" +dependencies = [ + "liblzma-sys", +] + +[[package]] +name = "liblzma-sys" +version = "0.4.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "01b9596486f6d60c3bbe644c0e1be1aa6ccc472ad630fe8927b456973d7cb736" +dependencies = [ + "cc", + "libc", + "pkg-config", +] + [[package]] name = "libredox" version = "0.1.10" @@ -1911,6 +2041,15 @@ dependencies = [ "libc", ] +[[package]] +name = "libz-rs-sys" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "840db8cf39d9ec4dd794376f38acc40d0fc65eec2a8f484f7fd375b84602becd" +dependencies = [ + "zlib-rs", +] + [[package]] name = "linux-raw-sys" version = "0.11.0" @@ -2494,6 +2633,16 @@ dependencies = [ "windows-link 0.2.1", ] +[[package]] +name = "pbkdf2" +version = "0.12.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f8ed6a7761f76e3b9f92dfb0a60a6a6477c61024b775147ff0973a02653abaf2" +dependencies = [ + "digest", + "hmac", +] + [[package]] name = "percent-encoding" version = "2.3.2" @@ -2693,6 +2842,12 @@ version = "0.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "439ee305def115ba05938db6eb1644ff94165c5ab5e9420d1c1bcedbba909391" +[[package]] +name = "ppmd-rust" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d558c559f0450f16f2a27a1f017ef38468c1090c9ce63c8e51366232d53717b4" + [[package]] name = "ppv-lite86" version = "0.2.21" @@ -3444,6 +3599,17 @@ dependencies = [ "stable_deref_trait", ] +[[package]] +name = "sha1" +version = "0.10.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3bf829a2d51ab4a5ddf1352d8470c140cadc8301b2ae1789db023f01cedd6ba" +dependencies = [ + "cfg-if", + "cpufeatures", + "digest", +] + [[package]] name = "sha2" version = "0.10.9" @@ -3607,6 +3773,12 @@ version = "0.11.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" +[[package]] +name = "subtle" +version = "2.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "13c2bddecc57b384dee18652358fb23172facb8a2c51ccc10d74c157bdea3292" + [[package]] name = "swift-rs" version = "1.0.7" @@ -5469,6 +5641,26 @@ dependencies = [ "synstructure", ] +[[package]] +name = "zeroize" +version = "1.8.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b97154e67e32c85465826e8bcc1c59429aaaf107c1e4a9e53c8d8ccd5eff88d0" +dependencies = [ + "zeroize_derive", +] + +[[package]] +name = "zeroize_derive" +version = "1.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ce36e65b0d2999d2aafac989fb249189a141aee1f53c612c1f37d72631959f69" +dependencies = [ + "proc-macro2", + "quote", + "syn 2.0.108", +] + [[package]] name = "zerotrie" version = "0.2.3" @@ -5502,6 +5694,79 @@ dependencies = [ "syn 2.0.108", ] +[[package]] +name = "zip" +version = "4.6.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "caa8cd6af31c3b31c6631b8f483848b91589021b28fffe50adada48d4f4d2ed1" +dependencies = [ + "aes", + "arbitrary", + "bzip2", + "constant_time_eq", + "crc32fast", + "deflate64", + "flate2", + "getrandom 0.3.4", + "hmac", + "indexmap 2.12.0", + "liblzma", + "memchr", + "pbkdf2", + "ppmd-rust", + "sha1", + "time", + "zeroize", + "zopfli", + "zstd", +] + +[[package]] +name = "zlib-rs" +version = "0.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2f06ae92f42f5e5c42443fd094f245eb656abf56dd7cce9b8b263236565e00f2" + +[[package]] +name = "zopfli" +version = "0.8.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f05cd8797d63865425ff89b5c4a48804f35ba0ce8d125800027ad6017d2b5249" +dependencies = [ + "bumpalo", + "crc32fast", + "log", + "simd-adler32", +] + +[[package]] +name = "zstd" +version = "0.13.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e91ee311a569c327171651566e07972200e76fcfe2242a4fa446149a3881c08a" +dependencies = [ + "zstd-safe", +] + +[[package]] +name = "zstd-safe" +version = "7.2.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "8f49c4d5f0abb602a93fb8736af2a4f4dd9512e36f7f570d66e65ff867ed3b9d" +dependencies = [ + "zstd-sys", +] + +[[package]] +name = "zstd-sys" +version = "2.0.16+zstd.1.5.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "91e19ebc2adc8f83e43039e79776e3fda8ca919132d68a1fed6a5faca2683748" +dependencies = [ + "cc", + "pkg-config", +] + [[package]] name = "zvariant" version = "5.8.0" diff --git a/src-tauri/Cargo.toml b/src-tauri/Cargo.toml index 93c0edd..267836e 100644 --- a/src-tauri/Cargo.toml +++ b/src-tauri/Cargo.toml @@ -26,3 +26,7 @@ tauri-plugin-log = "2" network-interface = "2.0.3" tauri-plugin-fs = "2" tauri-plugin-dialog = "2" +thiserror = "2.0.17" +zip = "4.2.0" +async-runtime = "0.0.0" +tokio = { version = "1.48.0", features = ["time"] } diff --git a/src-tauri/src/gameins.rs b/src-tauri/src/gameins.rs index e69de29..7e07bb3 100644 --- a/src-tauri/src/gameins.rs +++ b/src-tauri/src/gameins.rs @@ -0,0 +1,149 @@ +// 只在 Windows 编译 +#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")] + +// --- 1. 导入所需模块 --- +use thiserror::Error; +use zip::ZipArchive; +use std::fs::{self, File}; +use std::io; +use std::path::PathBuf; +use serde::Serialize; +use tauri::Emitter; +use tokio::time::{sleep, Duration}; + +// --- 2. (新增) 定义事件的有效负载 (Payload) --- +// 这个结构体将作为事件发送给 Svelte +#[derive(Clone, serde::Serialize)] +struct InstallProgress { + message: String, + percentage: f32, // 0.0 到 100.0 +} + +// --- 3. 错误定义 --- +#[derive(Debug, Error)] +pub enum InstallError { + #[error("IO 错误: {0}")] + Io(#[from] std::io::Error), + + #[error("Zip 解压错误: {0}")] + Zip(#[from] zip::result::ZipError), + + #[error("找不到 data.bin 文件: {0}")] + DataFileNotFound(String), + + +} + + +impl Serialize for InstallError { + fn serialize(&self, serializer: S) -> Result + where + S: serde::Serializer, + { + serializer.serialize_str(self.to_string().as_ref()) + } +} + + +#[tauri::command] +// --- 5. (修改) 添加 window 参数 --- +pub async fn install_game(window: tauri::Window, target_dir: String) -> Result { + + println!("Rust 后端收到命令:目标目录 {}", target_dir); + + // --- 6. 核心改动:从文件系统读取 data.bin --- + + // --- 6a. (新增) 发送启动事件 --- + window.emit("install_progress", InstallProgress { + message: "安装开始...".into(), + percentage: 0.0 + }).ok(); + + // 1. 获取 app.exe 所在的目录 + let exe_path = std::env::current_exe()?; + let exe_dir = exe_path.parent() + .ok_or_else(|| InstallError::Io(io::Error::new(io::ErrorKind::NotFound, "无法获取执行文件所在目录")))?; + + // 2. 构造 data.bin 的路径 + let data_bin_path = exe_dir.join("data.bin"); + + println!("正在查找数据文件: {:?}", data_bin_path); + window.emit("install_progress", InstallProgress { + message: format!("正在查找数据文件: {:?}", data_bin_path), + percentage: 1.0 // 1% + }).ok(); + + + if !data_bin_path.exists() { + // 返回错误,Svelte 的 catch 块会捕获它 + return Err(InstallError::DataFileNotFound( + format!("未在 {:?} 找到 data.bin", data_bin_path) + )); + } + + // 3. 从硬盘打开文件 + let archive_file = File::open(&data_bin_path)?; + println!("成功打开 data.bin。"); + window.emit("install_progress", InstallProgress { + message: "成功打开 data.bin。".into(), + percentage: 5.0 // 5% + }).ok(); + + + // 4. ZipArchive 现在读取文件 + let mut archive = ZipArchive::new(archive_file)?; + + let total_files = archive.len() as f32; + println!("在压缩包中找到 {} 个文件。", total_files); + window.emit("install_progress", InstallProgress { + message: format!("包中找到 {} 个文件。", total_files), + percentage: 10.0 // 10% + }).ok(); + + + // --- 7. 解压循环 (核心改动: 添加 emit) --- + let install_path = PathBuf::from(target_dir); + fs::create_dir_all(&install_path)?; + + for i in 0..archive.len() { + let mut file = archive.by_index(i)?; + + let outpath = match file.enclosed_name() { + Some(path) => install_path.join(path), + None => continue, + }; + + // --- 7a. (核心) 计算百分比并发送事件 --- + let current_file_index = i as f32; + let percentage = 10.0 + (current_file_index / total_files) * 85.0; // (10% + 85% = 95%) + let message = format!("安装中 [{}/{}]: {}", i + 1, total_files as u32, file.name()); + + window.emit("install_progress", InstallProgress { message, percentage }) + .ok(); + + // --- 2. (新增) 关键修复 --- + // 释放线程 1 毫秒,给 Svelte 留出渲染时间 + sleep(Duration::from_millis(1)).await; + + if (&*file.name()).ends_with('/') { + fs::create_dir_all(&outpath)?; + } else { + if let Some(p) = outpath.parent() { + if !p.exists() { + fs::create_dir_all(p)?; + } + } + let mut outfile = File::create(&outpath)?; + io::copy(&mut file, &mut outfile)?; + } + } // --- 循环结束 --- + + println!("Rust 后端:解压成功。"); + window.emit("install_progress", InstallProgress { + message: "✅ 解压完成。".into(), + percentage: 100.0 // 100% + }).ok(); + + Ok(format!("成功解压 {} 个文件到指定目录!", total_files as u32)) +} + diff --git a/src-tauri/src/lib.rs b/src-tauri/src/lib.rs index 61fdbb3..e068209 100644 --- a/src-tauri/src/lib.rs +++ b/src-tauri/src/lib.rs @@ -1,5 +1,6 @@ mod network; mod gameins; + #[cfg_attr(mobile, tauri::mobile_entry_point)] pub fn run() { tauri::Builder::default() @@ -15,7 +16,10 @@ pub fn run() { } Ok(()) }) - .invoke_handler(tauri::generate_handler![network::get_network_interfaces]) + .invoke_handler(tauri::generate_handler![ + network::get_network_interfaces, + gameins::install_game + ]) .run(tauri::generate_context!()) .expect("error while running tauri application"); } diff --git a/src/routes/install/+page.svelte b/src/routes/install/+page.svelte index e02cc46..37f8a7e 100644 --- a/src/routes/install/+page.svelte +++ b/src/routes/install/+page.svelte @@ -1,17 +1,47 @@