diff --git a/crates/maa-cli/src/config/asst.rs b/crates/maa-cli/src/config/asst.rs index 8baf2f07..ff0e5362 100644 --- a/crates/maa-cli/src/config/asst.rs +++ b/crates/maa-cli/src/config/asst.rs @@ -78,6 +78,10 @@ pub struct ConnectionConfig { pub(super) address: Option, #[serde(default)] pub(super) config: Option, + #[serde(default)] + pub(super) emulator_path: Option, + #[serde(default)] + pub(super) emulator_index: Option, } impl ConnectionConfig { @@ -115,6 +119,10 @@ impl ConnectionConfig { (adb_path, address, config) } + + pub fn extra_args(&self) -> (&Option, &Option) { + (&self.emulator_path, &self.emulator_index) + } } #[cfg_attr(test, derive(Debug, PartialEq))] @@ -123,6 +131,8 @@ pub enum Preset { MuMuPro, PlayCover, Waydroid, + MuMuEmulator12, + LDPlayer, #[default] Adb, } @@ -150,6 +160,8 @@ impl<'de> Deserialize<'de> for Preset { "PlayCover" | "PlayTools" => Ok(Preset::PlayCover), "ADB" | "Adb" | "adb" => Ok(Preset::Adb), "Waydroid" | "waydroid" => Ok(Preset::Waydroid), + "MuMuEmulator12" | "MuMuEmulator" => Ok(Preset::MuMuEmulator12), + "LDPlayer" => Ok(Preset::LDPlayer), _ => { warn!("Unknown connection preset: {value}, ignoring"); Ok(Preset::Adb) @@ -169,7 +181,7 @@ impl Preset { "/Applications/MuMuPlayer.app/Contents/MacOS/MuMuEmulator.app/Contents/MacOS/tools/adb" } Preset::PlayCover => "", - Preset::Waydroid | Preset::Adb => "adb", + Preset::Waydroid | Preset::Adb | Preset::MuMuEmulator12 | Preset::LDPlayer => "adb", } } @@ -177,23 +189,27 @@ impl Preset { match self { Preset::MuMuPro => "127.0.0.1:16384".into(), Preset::PlayCover => "127.0.0.1:1717".into(), - Preset::Waydroid | Preset::Adb => std::process::Command::new(adb_path) - .arg("devices") - .output() - .ok() - .and_then(|output| String::from_utf8(output.stdout).ok()) - .and_then(parse_adb_devices) - .map(Cow::Owned) - .unwrap_or_else(|| { - warn!("Failed to detect device address, using emulator-5554"); - "emulator-5554".into() - }), + Preset::Waydroid | Preset::Adb | Preset::MuMuEmulator12 | Preset::LDPlayer => { + std::process::Command::new(adb_path) + .arg("devices") + .output() + .ok() + .and_then(|output| String::from_utf8(output.stdout).ok()) + .and_then(parse_adb_devices) + .map(Cow::Owned) + .unwrap_or_else(|| { + warn!("Failed to detect device address, using emulator-5554"); + "emulator-5554".into() + }) + } } } fn default_config(self) -> &'static str { match self { Preset::Waydroid => "Waydroid", + Preset::MuMuEmulator12 => "MuMuEmulator12", + Preset::LDPlayer => "LDPlayer", // May be preset specific in the future Preset::MuMuPro | Preset::PlayCover | Preset::Adb => config_based_on_os(), } @@ -540,6 +556,8 @@ mod tests { adb_path: Some(String::from("adb")), address: Some(String::from("emulator-5554")), config: Some(String::from("CompatMac")), + emulator_path: None, + emulator_index: None, }, resource: ResourceConfig { resource_base_dirs: { @@ -616,6 +634,8 @@ mod tests { adb_path: Some(String::from("/path/to/adb")), address: Some(String::from("127.0.0.1:5555")), config: Some(String::from("SomeConfig")), + emulator_path: None, + emulator_index: None, }, &[ Token::Map { len: Some(4) }, @@ -821,6 +841,8 @@ mod tests { adb_path: None, address: None, config: None, + emulator_path: None, + emulator_index: None, }); } @@ -880,6 +902,8 @@ mod tests { adb_path: None, address: None, config: None, + emulator_path: None, + emulator_index: None, } .connect_args(), ( @@ -895,6 +919,8 @@ mod tests { adb_path: None, address: None, config: None, + emulator_path: None, + emulator_index: None, } .connect_args(), ("", "127.0.0.1:1717", config_based_on_os()), @@ -906,6 +932,8 @@ mod tests { adb_path: None, address: None, config: None, + emulator_path: None, + emulator_index: None, } .connect_args(), ("adb", &device, "Waydroid"), @@ -917,6 +945,8 @@ mod tests { adb_path: Some("/path/to/adb".to_owned()), address: Some("127.0.0.1:11111".to_owned()), config: Some("SomeConfig".to_owned()), + emulator_path: None, + emulator_index: None, } .connect_args(), ("/path/to/adb", "127.0.0.1:11111", "SomeConfig"), diff --git a/crates/maa-cli/src/run/extra/ldplayer.rs b/crates/maa-cli/src/run/extra/ldplayer.rs new file mode 100644 index 00000000..35f5b4cb --- /dev/null +++ b/crates/maa-cli/src/run/extra/ldplayer.rs @@ -0,0 +1,52 @@ +use std::process::Command; + +use serde_json; + +pub fn ld_extra( + emulator_path: &Option, + emulator_index: &Option, +) -> anyhow::Result { + let path = emulator_path + .as_ref() + .ok_or_else(|| anyhow::anyhow!("emulator_path is required for LDPlayer"))?; + let index = emulator_index.unwrap_or(0); + let mut ldconsole_path = std::path::PathBuf::from(path); + ldconsole_path.push("ldconsole.exe"); + if !ldconsole_path.exists() { + return Err(anyhow::anyhow!( + "ldconsole.exe not found in the specified emulator_path" + )); + } + let output = match Command::new(&ldconsole_path).arg("list2").output() { + Ok(output) => output, + Err(e) => { + return Err(anyhow::anyhow!( + "Failed to execute ldconsole.exe: {}", + e.to_string() + )); + } + }; + let stdout = String::from_utf8_lossy(&output.stdout); + let mut pid_found: Option = None; + let index_str = index.to_string(); + for line in stdout.lines() { + let parts: Vec<&str> = line.split(',').collect(); + if parts.len() >= 6 && parts[0] == index_str { + pid_found = parts[5].parse::().ok(); + break; + } + } + if let Some(pid) = pid_found { + let object = serde_json::json!({ + "path": path, + "index": index, + "pid": pid, + }); + Ok(serde_json::to_string(&object)?) + } else { + Err(anyhow::anyhow!( + "No running instance found for LDPlayer with index {}", + index + )) + } +} diff --git a/crates/maa-cli/src/run/extra/mod.rs b/crates/maa-cli/src/run/extra/mod.rs new file mode 100644 index 00000000..fc8eb213 --- /dev/null +++ b/crates/maa-cli/src/run/extra/mod.rs @@ -0,0 +1,11 @@ +#[cfg(target_os = "windows")] +pub mod mumu; + +#[cfg(target_os = "windows")] +pub use mumu::mumu_extra; + +#[cfg(target_os = "windows")] +pub mod ldplayer; + +#[cfg(target_os = "windows")] +pub use ldplayer::ld_extra; diff --git a/crates/maa-cli/src/run/extra/mumu.rs b/crates/maa-cli/src/run/extra/mumu.rs new file mode 100644 index 00000000..71f76a67 --- /dev/null +++ b/crates/maa-cli/src/run/extra/mumu.rs @@ -0,0 +1,18 @@ +use anyhow::{Result, anyhow}; +use serde_json; + +pub fn mumu_extra(emulator_path: &Option, emulator_index: &Option) -> Result { + let mut json_map = serde_json::Map::new(); + if let Some(path) = &emulator_path { + json_map.insert("path".to_string(), serde_json::Value::String(path.clone())); + } else { + return Err(anyhow!("emulator_path is required for MuMu emulator")); + } + if let Some(index) = &emulator_index { + json_map.insert( + "index".to_string(), + serde_json::Value::Number(serde_json::Number::from(*index)), + ); + } + Ok(serde_json::to_string(&json_map)?) +} diff --git a/crates/maa-cli/src/run/mod.rs b/crates/maa-cli/src/run/mod.rs index 4c4ae432..f2ec8494 100644 --- a/crates/maa-cli/src/run/mod.rs +++ b/crates/maa-cli/src/run/mod.rs @@ -5,6 +5,7 @@ mod callback; use callback::summary; mod external; +mod extra; pub mod preset; @@ -177,6 +178,7 @@ where if !args.dry_run { // Prepare connection let (adb_path, address, config) = asst_config.connection.connect_args(); + let (emulator_path, emulator_index) = asst_config.connection.extra_args(); // Launch external apps let app: Option> = match asst_config.connection.preset() { @@ -192,6 +194,24 @@ where _ => None, }; + match asst_config.connection.preset() { + #[cfg(target_os = "windows")] + crate::config::asst::Preset::MuMuEmulator12 => { + Assistant::set_connection_extras( + "MuMuEmulator12", + extra::mumu_extra(emulator_path, emulator_index)?.as_str(), + )?; + } + #[cfg(target_os = "windows")] + crate::config::asst::Preset::LDPlayer => { + Assistant::set_connection_extras( + "LDPlayer", + extra::ld_extra(emulator_path, emulator_index)?.as_str(), + )?; + } + _ => {} + } + // Startup external app let need_reconfigure = if let (Some(app), true) = (app.as_deref(), task_config.start_app) { !app.open().context("Failed to open external app")?