diff --git a/config_examples/asst.toml b/config_examples/asst.toml index 7dca9bac..bd703f33 100644 --- a/config_examples/asst.toml +++ b/config_examples/asst.toml @@ -1,3 +1,4 @@ +user_resource = true resources = ["platform_diff/macOS"] [connection] @@ -7,7 +8,7 @@ device = "emulator-5554" config = "CompatMac" [instance_options] -touch_mode = "MiniTouch" +touch_mode = "MAATouch" deployment_with_pause = false adb_lite_enabled = false kill_adb_on_exit = false diff --git a/maa-cli/src/config/asst.rs b/maa-cli/src/config/asst.rs index 7c81ac64..29c2f4bc 100644 --- a/maa-cli/src/config/asst.rs +++ b/maa-cli/src/config/asst.rs @@ -3,6 +3,8 @@ use serde::Deserialize; #[cfg_attr(test, derive(Debug, PartialEq))] #[derive(Deserialize, Default)] pub struct AsstConfig { + #[serde(default)] + pub user_resource: bool, #[serde(default)] pub resources: Vec, #[serde(default)] @@ -123,6 +125,7 @@ mod tests { assert_eq!( config, AsstConfig { + user_resource: true, resources: vec![String::from("platform_diff/macOS")], connection: Connection::ADB { adb_path: String::from("adb"), @@ -130,7 +133,7 @@ mod tests { config: String::from("CompatMac"), }, instance_options: InstanceOption { - touch_mode: Some(TouchMode::MiniTouch), + touch_mode: Some(TouchMode::MAATouch), deployment_with_pause: Some(false), adb_lite_enabled: Some(false), kill_adb_on_exit: Some(false), @@ -145,6 +148,7 @@ mod tests { assert_eq!( config, AsstConfig { + user_resource: false, resources: vec![], connection: Connection::ADB { adb_path: String::from("adb"), diff --git a/maa-cli/src/main.rs b/maa-cli/src/main.rs index 49b1724f..1bb3546d 100644 --- a/maa-cli/src/main.rs +++ b/maa-cli/src/main.rs @@ -175,21 +175,25 @@ enum CLI { /// and then you can specify the address of MaaTools here. #[clap(short, long, verbatim_doc_comment)] addr: Option, - /// Load resources from the user config directory + /// Load resources from the config directory /// - /// By default, MaaCore loads resources from the data directory, - /// which is shipped with the program. - /// If you want to load resources from the user config directory, - /// you can use this option. - /// The `resource` directory must be in the config directory - /// and the resources must be in the `resource` directory. + /// By default, MaaCore loads resources from the resource installed with MaaCore. + /// If you want to modify some configuration of MaaCore or you want to use your own resources, + /// you can use this option to load resources from the `resource` directory, + /// which is a subdirectory of the config directory. /// - /// Note: user resources will be loaded at the end, - /// so if there are resources with the same name, - /// the user resources will overwrite the default resources. - /// use at your own risk! + /// This option can alse be enabled by setting the value of the key `user_resource` to true + /// in the asst configure file `$MAA_CONFIG_DIR/asst.toml`. + /// + /// Note: + /// CLI will load resources shipped with MaaCore firstly, + /// then some client specific or platform specific when needed, + /// lastly, it will load resources from the config directory. + /// MAACore will overwrite the resources loaded before, + /// if there are some resources with the same name. + /// Use at your own risk! #[clap(long, verbatim_doc_comment)] - user_resource: bool, + user_resource: Option, /// Output more information, repeat to increase verbosity /// /// This option is used to control the log level of this program and MaaCore. diff --git a/maa-cli/src/run/mod.rs b/maa-cli/src/run/mod.rs index 7b32de1a..6d4cc071 100644 --- a/maa-cli/src/run/mod.rs +++ b/maa-cli/src/run/mod.rs @@ -7,7 +7,7 @@ use crate::{ task::{ task_type::{TaskOrUnknown, TaskType}, value::input::enable_batch_mode, - TaskList, Value, + TaskList, }, Error as ConfigError, FindFile, }, @@ -17,7 +17,7 @@ use crate::{ {debug, error, normal, warning}, }; -use std::path::{Path, PathBuf}; +use std::path::PathBuf; use std::sync::Arc; use anyhow::{anyhow, bail, Context, Result}; @@ -28,7 +28,7 @@ pub fn run( dirs: &Dirs, task: String, addr: Option, - user_resource: bool, + user_resource: Option, verbose: u8, quiet: u8, batch: bool, @@ -108,7 +108,9 @@ pub fn run( let mut start_app: bool = false; // start iOS app before connect let mut close_app: bool = false; // close iOS app after disconnect - let mut app_name: Option = None; + let mut app_name: Option<&str> = None; + + let mut client_resource: Option<&str> = None; for task in task_list.tasks { if task.is_active() { @@ -127,7 +129,9 @@ pub fn run( } if let Some(client_type) = params.get("client_type") { - app_name = Some(client_name(client_type, &resource_dir)?); + let client_name = String::try_from(client_type)?; + app_name = match_app_name(&client_name); + client_resource = match_resource(&client_name); }; } TaskType::CloseDown if playtools => { @@ -180,20 +184,29 @@ pub fn run( "No client type specified, ", format!("using default app name {}", "明日方舟") ); - Some(PlayCoverApp::from("明日方舟")) + Some(PlayCoverApp::new("明日方舟")) } } } else { None }; - /*------------------- Load Additional resource -----------------*/ + /*------------------------ Load Resource -----------------------*/ + // Cilent specific resource + if let Some(resource) = client_resource { + debug!("Loading additional resource for client", resource); + Assistant::load_resource(resource_dir.join("global").join(resource)) + .with_context(|| format!("Failed to load additional resource {}!", resource))?; + } + + // Platform specific resource if playtools { debug!("Load additional resource for PlayTools"); Assistant::load_resource(resource_dir.join("platform_diff/iOS")) - .context("Failed to load additional resource!")?; + .context("Failed to load additional resource for iOS App!")?; } + // User specified additional resource for resource in asst_config.resources.iter() { let path = PathBuf::from(resource); let path = if path.is_absolute() { @@ -207,12 +220,13 @@ pub fn run( .with_context(|| format!("Failed to load additional resource {}!", path.display()))?; } - if user_resource { + // User resource in config directory + if user_resource.unwrap_or(asst_config.user_resource) { if config_dir.join("resource").exists() { debug!("Loading user resource:", config_dir.display()); Assistant::load_resource(config_dir).context("Failed to load user resource!")?; } else { - warning!("`--user-resource` is specified, but no user resource found!"); + warning!("`User resource` is enabled, but no resource directory found!"); } } @@ -313,12 +327,12 @@ pub fn core_version<'a>(dirs: &Dirs) -> Result<&'a str> { Ok(Assistant::get_version()?) } -struct PlayCoverApp { - name: String, +struct PlayCoverApp<'n> { + name: &'n str, } -impl PlayCoverApp { - pub fn new(name: String) -> Self { +impl<'n> PlayCoverApp<'n> { + pub fn new(name: &'n str) -> Self { Self { name } } @@ -334,7 +348,7 @@ impl PlayCoverApp { normal!("Starting game..."); std::process::Command::new("open") .arg("-a") - .arg(&self.name) + .arg(self.name) .status() .context("Failed to start game!")?; Ok(()) @@ -350,34 +364,27 @@ impl PlayCoverApp { } } -impl From<&str> for PlayCoverApp { - fn from(name: &str) -> Self { - Self::new(name.into()) - } -} - -fn client_name(client: &Value, resource_dir: &Path) -> Result { - let client = String::try_from(client)?; - - let (resource, app) = match client.as_str() { - "Official" | "Bilibili" | "" => (None, None), - "txwy" => (Some("txwy"), None), - "YoStarEN" => (Some("YoStarEN"), Some("Arknights")), - "YoStarJP" => (Some("YoStarJP"), Some("アークナイツ")), - "YoStarKR" => (Some("YoStarKR"), Some("명일방주")), +fn match_app_name(client: &str) -> Option<&'static str> { + match client { + "Official" | "Bilibili" | "txwy" | "" => None, + "YoStarEN" => Some("Arknights"), + "YoStarJP" => Some("アークナイツ"), + "YoStarKR" => Some("명일방주"), _ => { error!("Unknown client type", client); - (None, None) + None } - }; - - if let Some(resource) = resource { - debug!("Loading additional resource for global client", resource); - Assistant::load_resource(resource_dir.join("global").join(resource)) - .context("Failed to load additional resource!")?; } +} - Ok(app.unwrap_or("明日方舟").to_string()) +fn match_resource(client: &str) -> Option<&'static str> { + match client { + "txwy" => Some("txwy"), + "YoStarEN" => Some("YoStarEN"), + "YoStarJP" => Some("YoStarJP"), + "YoStarKR" => Some("YoStarKR"), + _ => None, + } } fn load_core(dirs: &Dirs) {