diff --git a/Cargo.lock b/Cargo.lock index 0ba0e7e..b1b1147 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -23,6 +23,7 @@ dependencies = [ "reqwest", "serde", "spin", + "sysinfo", "tokio", "tokio-tungstenite", "toml", @@ -1005,6 +1006,15 @@ dependencies = [ "tempfile", ] +[[package]] +name = "ntapi" +version = "0.4.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c70f219e21142367c70c0b30c6a9e3a14d55b4d12a204d897fbec83a0363f081" +dependencies = [ + "winapi", +] + [[package]] name = "num-traits" version = "0.2.19" @@ -1014,6 +1024,25 @@ dependencies = [ "autocfg", ] +[[package]] +name = "objc2-core-foundation" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2a180dd8642fa45cdb7dd721cd4c11b1cadd4929ce112ebd8b9f5803cc79d536" +dependencies = [ + "bitflags", +] + +[[package]] +name = "objc2-io-kit" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "33fafba39597d6dc1fb709123dfa8289d39406734be322956a69f0931c73bb15" +dependencies = [ + "libc", + "objc2-core-foundation", +] + [[package]] name = "once_cell" version = "1.21.3" @@ -1519,6 +1548,20 @@ dependencies = [ "syn", ] +[[package]] +name = "sysinfo" +version = "0.38.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "fe840c5b1afe259a5657392a4dbb74473a14c8db999c3ec2f4ae812e028a94da" +dependencies = [ + "libc", + "memchr", + "ntapi", + "objc2-core-foundation", + "objc2-io-kit", + "windows", +] + [[package]] name = "tempfile" version = "3.24.0" @@ -1928,6 +1971,22 @@ dependencies = [ "wasm-bindgen", ] +[[package]] +name = "winapi" +version = "0.3.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5c839a674fcd7a98952e593242ea400abe93992746761e38641405d28b00f419" +dependencies = [ + "winapi-i686-pc-windows-gnu", + "winapi-x86_64-pc-windows-gnu", +] + +[[package]] +name = "winapi-i686-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" + [[package]] name = "winapi-util" version = "0.1.11" @@ -1937,6 +1996,33 @@ dependencies = [ "windows-sys 0.61.2", ] +[[package]] +name = "winapi-x86_64-pc-windows-gnu" +version = "0.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" + +[[package]] +name = "windows" +version = "0.62.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "527fadee13e0c05939a6a05d5bd6eec6cd2e3dbd648b9f8e447c6518133d8580" +dependencies = [ + "windows-collections", + "windows-core", + "windows-future", + "windows-numerics", +] + +[[package]] +name = "windows-collections" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "23b2d95af1a8a14a3c7367e1ed4fc9c20e0a26e79551b1454d72583c97cc6610" +dependencies = [ + "windows-core", +] + [[package]] name = "windows-core" version = "0.62.2" @@ -1950,6 +2036,17 @@ dependencies = [ "windows-strings", ] +[[package]] +name = "windows-future" +version = "0.3.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e1d6f90251fe18a279739e78025bd6ddc52a7e22f921070ccdc67dde84c605cb" +dependencies = [ + "windows-core", + "windows-link", + "windows-threading", +] + [[package]] name = "windows-implement" version = "0.60.2" @@ -1978,6 +2075,16 @@ version = "0.2.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f0805222e57f7521d6a62e36fa9163bc891acd422f971defe97d64e70d0a4fe5" +[[package]] +name = "windows-numerics" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6e2e40844ac143cdb44aead537bbf727de9b044e107a0f1220392177d15b0f26" +dependencies = [ + "windows-core", + "windows-link", +] + [[package]] name = "windows-result" version = "0.4.1" @@ -2031,6 +2138,15 @@ dependencies = [ "windows_x86_64_msvc", ] +[[package]] +name = "windows-threading" +version = "0.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3949bd5b99cafdf1c7ca86b43ca564028dfe27d66958f2470940f73d86d75b37" +dependencies = [ + "windows-link", +] + [[package]] name = "windows_aarch64_gnullvm" version = "0.53.1" diff --git a/Cargo.toml b/Cargo.toml index bb8268a..764e455 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -33,6 +33,7 @@ tokio-tungstenite = "0.28.0" bytes = "1.11.0" spin = "0.10.0" chardetng = "0.1.17" +sysinfo = "0.38.0" [build-dependencies] cxx-build = "1.0.192" diff --git a/build.rs b/build.rs index d24f866..4172a7d 100644 --- a/build.rs +++ b/build.rs @@ -3,7 +3,7 @@ use std::path::{Path, PathBuf}; use std::str::FromStr; fn main() { - cxx_build::bridges(["src/lib.rs", "src/config.rs"]) + cxx_build::bridges(["src/lib.rs", "src/config.rs", "src/login.rs"]) .std("c++20") .compile("dnf_utils"); println!("cargo:rerun-if-changed=src/lib.rs"); @@ -29,7 +29,8 @@ fn main() { prost_build::Config::new() .out_dir(out_dir) - .compile_protos(&proto_list, &["proto/".to_string()]).unwrap(); + .compile_protos(&proto_list, &["proto/".to_string()]) + .unwrap(); //tonic_prost_build::configure() // .out_dir(out_dir) @@ -51,7 +52,6 @@ fn main() { ).unwrap(); } - fn get_filenames(dir: &str) -> Result, std::io::Error> { println!("cargo:rerun-if-changed=proto"); let entries = fs::read_dir(Path::new(dir))?; @@ -66,4 +66,4 @@ fn get_filenames(dir: &str) -> Result, std::io::Error> { }) .collect(); Ok(filenames) -} \ No newline at end of file +} diff --git a/src/config.rs b/src/config.rs index 52dccf4..55b0c53 100644 --- a/src/config.rs +++ b/src/config.rs @@ -40,6 +40,14 @@ mod ffi { fn is_decompose(cfg: &Box) -> bool; fn set_decompose(cfg: &mut Box, value: bool); + /// 倍攻 + fn is_attack_power(cfg: &Box) -> bool; + fn set_attack_power(cfg: &mut Box, value: bool); + + /// 装备变换 + fn is_equip_transform(cfg: &Box) -> bool; + fn set_equip_transform(cfg: &mut Box, value: bool); + /// 从配置文件中读取一个配置项 fn get_config_value( path: &CxxString, @@ -73,17 +81,23 @@ pub struct Config { is_forest: bool, /// 分解 is_decompose: bool, + /// 倍攻 + is_attack_power: bool, + /// 装备变换 + is_equip_transform: bool, } impl Default for Config { fn default() -> Self { Self { - is_daily_missions: false, - is_archipelago: false, - is_spiral_abyss: false, - is_demonic_energy: false, - is_forest: false, - is_decompose: false, + is_daily_missions: true, + is_archipelago: true, + is_spiral_abyss: true, + is_demonic_energy: true, + is_forest: true, + is_decompose: true, + is_attack_power: true, + is_equip_transform: true, } } } @@ -94,7 +108,6 @@ impl Config { // 你也可以加一个总注释、版本号等 format!( r#"# 自动生成的配置文件 -# 实现可能修改配置存储结构,请不要使用程序化工具修改此配置文件,如果非要这么做,请链接utils.lib后,使用其提供的接口。 # 做不做每日任务 is_daily_missions = {is_daily_missions} @@ -113,6 +126,12 @@ is_forest = {is_forest} # 分解 is_decompose = {is_decompose} + +# 倍攻 +is_attack_power = {is_attack_power} + +# 装备变换 +is_equip_transform = {is_equip_transform} "#, is_daily_missions = self.is_daily_missions, is_archipelago = self.is_archipelago, @@ -120,15 +139,17 @@ is_decompose = {is_decompose} is_demonic_energy = self.is_demonic_energy, is_forest = self.is_forest, is_decompose = self.is_decompose, + is_attack_power = self.is_attack_power, + is_equip_transform = self.is_equip_transform, ) } pub fn save_with_comments(&self, path: impl AsRef) -> io::Result<()> { - /*let path = path.as_ref(); + let path = path.as_ref(); if let Some(parent) = path.parent() { fs::create_dir_all(parent)?; } - fs::write(path, self.to_toml_with_comments())*/ + fs::write(path, self.to_toml_with_comments())?; Ok(()) } @@ -137,7 +158,7 @@ is_decompose = {is_decompose} /// - toml 缺字段:会自动用 Default 补齐(因为 #[serde(default)]) /// - 可选:如果你想“读取后把缺的字段补齐回写”,这里也做了回写 pub fn load_or_create(path: impl AsRef) -> Result> { - /*let path = path.as_ref(); + let path = path.as_ref(); if !path.exists() { let cfg = Self::default(); @@ -150,15 +171,15 @@ is_decompose = {is_decompose} // 可选:自动回写补全(比如用户旧版配置少字段时,补齐并带注释写回去) // 如果你不想覆盖用户文件,把下面两行删掉即可。 - cfg.save_with_comments(path)?;*/ - let cfg = Config { + cfg.save_with_comments(path)?; + /*let cfg = Config { is_daily_missions: true, is_archipelago: true, is_spiral_abyss: false, is_demonic_energy: true, is_forest: true, is_decompose: true, - }; + };*/ Ok(cfg) } @@ -227,6 +248,20 @@ pub(crate) fn set_decompose(this: &mut Box, flag: bool) { this.is_decompose = flag; } +fn is_attack_power(cfg: &Box) -> bool { + cfg.is_attack_power +} +fn set_attack_power(cfg: &mut Box, value: bool) { + cfg.is_attack_power = value; +} + +fn is_equip_transform(cfg: &Box) -> bool { + cfg.is_equip_transform +} +fn set_equip_transform(cfg: &mut Box, value: bool) { + cfg.is_equip_transform = value; +} + pub(crate) fn set_config_value( path: &CxxString, path_name: &CxxString, diff --git a/src/lib.rs b/src/lib.rs index 3d8eccd..03d709b 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -7,6 +7,7 @@ use encoding_rs::Encoding; use futures_util::SinkExt; use prost::Message as WebMessage; use spin::Mutex; +use std::ffi::CString; use std::sync::OnceLock; use std::sync::mpsc; use tokio::net::TcpStream; @@ -17,6 +18,7 @@ static LOGGER_SENDER: OnceLock> = OnceLock::new(); mod config; mod log; +mod login; mod network; pub mod protobuf; pub mod utils; diff --git a/src/login.rs b/src/login.rs new file mode 100644 index 0000000..6472f8c --- /dev/null +++ b/src/login.rs @@ -0,0 +1,116 @@ +use crate::log::get_current_dir; +use crate::utils::cxx_string_to_string; +use cxx::CxxString; +use log::info; +use serde::{Deserialize, Serialize}; +use std::fmt::Display; +use std::path::{Path, PathBuf}; +use std::process::Command; +use std::{fs, io}; +use sysinfo::{ProcessesToUpdate, System}; +use toml::Value; + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] +#[derive(Default)] +pub struct User { + username: String, + password: String, + server: String, +} + +#[derive(Debug, Clone, Serialize, Deserialize)] +#[serde(default)] +#[derive(Default)] +pub struct Login { + /// 协议登录,exe路径 + login_exe: String, + game_path: String, + list: Vec, +} + +#[cxx::bridge] +mod ffi { + extern "Rust" { + type Login; + + fn load_login_config() -> Result>; + + fn get_login_size(cfg: &Box) -> usize; + + fn get_login_exe(cfg: &Box) -> String; + + fn login_game(cfg: &Box, index: usize) -> bool; + + fn get_username(cfg: &Box, index: usize) -> String; + + fn get_password(cfg: &Box, index: usize) -> String; + + fn get_server(cfg: &Box, index: usize) -> String; + + fn is_process_running() -> bool; + } +} + +pub(crate) fn load_login_config() -> Result, Box> { + let path = PathBuf::from("C:\\Windows\\Starpoles\\login.toml"); /* get_current_dir().join("config").join("login.toml");*/ + if !path.exists() { + fs::create_dir_all(path.parent().unwrap())?; + let cfg = Login::default(); + fs::write(path, toml::to_string(&cfg).unwrap())?; + return Ok(Box::new(cfg)); + } + let text = fs::read_to_string(path)?; + let cfg: Login = toml::from_str(&text)?; + Ok(Box::new(cfg)) +} + +pub(crate) fn get_login_size(p0: &Box) -> usize { + p0.list.len() +} + +pub(crate) fn get_login_exe(p0: &Box) -> String { + p0.login_exe.clone() +} + +pub(crate) fn get_username(p0: &Box, p1: usize) -> String { + p0.list[p1].username.clone() +} + +pub(crate) fn get_password(p0: &Box, p1: usize) -> String { + p0.list[p1].password.clone() +} + +pub(crate) fn get_server(p0: &Box, p1: usize) -> String { + p0.list[p1].server.clone() +} + +pub(crate) fn login_game(p0: &Box, p1: usize) -> bool { + info!( + "协议登录:{},user:{},password:{},server:{}", + p0.login_exe, p0.list[p1].username, p0.list[p1].password, p0.list[p1].server + ); + let status = Command::new(p0.login_exe.clone()) + .args([ + "-g", + &p0.game_path, + "-u", + &p0.list[p1].username, + "-p", + &p0.list[p1].password, + "-a", + &p0.list[p1].server, + ]) + .status() + .unwrap(); + status.success() +} + +fn is_process_running() -> bool { + let mut sys = System::new(); + sys.refresh_processes(ProcessesToUpdate::All, true); + + sys.processes() + .values() + .any(|p| p.name().eq_ignore_ascii_case("dnf.exe")) +}