diff --git a/3rdparty/EmulatorExtras b/3rdparty/EmulatorExtras index 42442b1183..54d3a3ad44 160000 --- a/3rdparty/EmulatorExtras +++ b/3rdparty/EmulatorExtras @@ -1 +1 @@ -Subproject commit 42442b11835844ee1ff01371e6537d0291ca9505 +Subproject commit 54d3a3ad448f0541df3759ae91b571a6762daaf1 diff --git a/MAA.sln.DotSettings b/MAA.sln.DotSettings index 5080c45946..10229301c4 100644 --- a/MAA.sln.DotSettings +++ b/MAA.sln.DotSettings @@ -69,6 +69,8 @@ True True True + True + True True True True diff --git a/src/MaaCore/Controller/AdbController.cpp b/src/MaaCore/Controller/AdbController.cpp index b9169d9041..2db136cd2a 100644 --- a/src/MaaCore/Controller/AdbController.cpp +++ b/src/MaaCore/Controller/AdbController.cpp @@ -216,6 +216,23 @@ void asst::AdbController::init_mumu_extras(const AdbCfg& adb_cfg [[maybe_unused] #endif } +void asst::AdbController::init_ld_extras(const AdbCfg& adb_cfg [[maybe_unused]]) +{ +#if !ASST_WITH_EMULATOR_EXTRAS + Log.error("MaaCore is not compiled with ASST_WITH_EMULATOR_EXTRAS"); +#else + if (adb_cfg.extras.empty()) { + LogWarn << "adb_cfg.extras is empty"; + return; + } + + std::filesystem::path ld_path = utils::path(adb_cfg.extras.get("path", "")); + int ld_index = adb_cfg.extras.get("index", 0); + int ld_pid = adb_cfg.extras.get("pid", 0); + m_ld_extras.init(ld_path, ld_index, ld_pid, m_width, m_height); +#endif +} + void asst::AdbController::close_socket() noexcept { m_platform_io->close_socket(); @@ -458,10 +475,10 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect auto min_cost = milliseconds(LLONG_MAX); clear_lf_info(); - auto start_time = high_resolution_clock::now(); + auto start_time = steady_clock::now(); if (m_support_socket && m_server_started && screencap(m_adb.screencap_raw_by_nc, decode_raw, allow_reconnect, true, 5000)) { - auto duration = duration_cast(high_resolution_clock::now() - start_time); + auto duration = duration_cast(steady_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawByNc; m_inited = true; @@ -474,9 +491,9 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect } clear_lf_info(); - start_time = high_resolution_clock::now(); + start_time = steady_clock::now(); if (screencap(m_adb.screencap_raw_with_gzip, decode_raw_with_gzip, allow_reconnect)) { - auto duration = duration_cast(high_resolution_clock::now() - start_time); + auto duration = duration_cast(steady_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::RawWithGzip; m_inited = true; @@ -489,9 +506,9 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect } clear_lf_info(); - start_time = high_resolution_clock::now(); + start_time = steady_clock::now(); if (screencap(m_adb.screencap_encode, decode_encode, allow_reconnect)) { - auto duration = duration_cast(high_resolution_clock::now() - start_time); + auto duration = duration_cast(steady_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::Encode; m_inited = true; @@ -505,10 +522,10 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect #if ASST_WITH_EMULATOR_EXTRAS if (m_mumu_extras.inited()) { - start_time = high_resolution_clock::now(); + start_time = steady_clock::now(); if (m_mumu_extras.screencap()) { auto duration = - duration_cast(high_resolution_clock::now() - start_time); + duration_cast(steady_clock::now() - start_time); if (duration < min_cost) { m_adb.screencap_method = AdbProperty::ScreencapMethod::MumuExtras; m_inited = true; @@ -520,6 +537,22 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect Log.info("MumuExtras is not supported"); } } + if (m_ld_extras.inited()) { + start_time = steady_clock::now(); + if (m_ld_extras.screencap()) { + auto duration = duration_cast(steady_clock::now() - start_time); + if (duration < min_cost) { + m_adb.screencap_method = AdbProperty::ScreencapMethod::LDExtras; + m_inited = true; + min_cost = duration; + } + Log.info("LDExtras cost", duration.count(), "ms"); + } + else { + Log.info("LDExtras is not supported"); + } + + } #endif static const std::unordered_map MethodName = { @@ -529,6 +562,7 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect { AdbProperty::ScreencapMethod::Encode, "Encode" }, #if ASST_WITH_EMULATOR_EXTRAS { AdbProperty::ScreencapMethod::MumuExtras, "MumuExtras" }, + { AdbProperty::ScreencapMethod::LDExtras, "LDExtras" }, #endif }; Log.info( @@ -577,6 +611,20 @@ bool asst::AdbController::screencap(cv::Mat& image_payload, bool allow_reconnect screencap_ret = img_opt.has_value(); } + if (screencap_ret) { + image_payload = img_opt.value(); + } + } break; + case AdbProperty::ScreencapMethod::LDExtras: { + auto img_opt = m_ld_extras.screencap(); + screencap_ret = img_opt.has_value(); + + if (!screencap_ret && allow_reconnect) { + m_ld_extras.reload(); + img_opt = m_ld_extras.screencap(); + screencap_ret = img_opt.has_value(); + } + if (screencap_ret) { image_payload = img_opt.value(); } @@ -986,6 +1034,9 @@ bool asst::AdbController::connect( if (config == "MuMuEmulator12") { init_mumu_extras(adb_cfg); } + else if (config == "LDPlayer") { + init_ld_extras(adb_cfg); + } if (need_exit()) { return false; diff --git a/src/MaaCore/Controller/AdbController.h b/src/MaaCore/Controller/AdbController.h index 0408c19ddd..6aae708e28 100644 --- a/src/MaaCore/Controller/AdbController.h +++ b/src/MaaCore/Controller/AdbController.h @@ -13,6 +13,7 @@ #include "Config/GeneralConfig.h" #include "InstHelper.h" #include "MumuExtras.h" +#include "LDExtras.h" namespace asst { @@ -103,6 +104,7 @@ protected: virtual void clear_info() noexcept; void callback(AsstMsg msg, const json::value& details); void init_mumu_extras(const AdbCfg& adb_cfg); + void init_ld_extras(const AdbCfg& adb_cfg); // 转换 data 中的 CRLF 为 LF:有些模拟器自带的 adb,exec-out 输出的 \n 会被替换成 \r\n, // 导致解码错误,所以这里转一下回来(点名批评 mumu 和雷电) @@ -158,6 +160,7 @@ protected: Encode, #if ASST_WITH_EMULATOR_EXTRAS MumuExtras, + LDExtras, #endif } screencap_method = ScreencapMethod::UnknownYet; } m_adb; @@ -178,6 +181,7 @@ protected: #if ASST_WITH_EMULATOR_EXTRAS MumuExtras m_mumu_extras; + LDExtras m_ld_extras; #endif }; } // namespace asst diff --git a/src/MaaCore/LDExtras.cpp b/src/MaaCore/LDExtras.cpp new file mode 100644 index 0000000000..3b2ca95ec1 --- /dev/null +++ b/src/MaaCore/LDExtras.cpp @@ -0,0 +1,124 @@ +#include "LDExtras.h" + +#if ASST_WITH_EMULATOR_EXTRAS + +#include "Utils/Logger.hpp" +#include "Utils/NoWarningCV.h" +#include "Utils/Platform/SafeWindows.h" +#include +#include +#include + +namespace asst +{ +LDExtras::~LDExtras() +{ + uninit(); +} + +bool LDExtras::init(const std::filesystem::path& ld_path, unsigned int ld_inst_index, unsigned int ld_pid, int width, int height) +{ + const bool same = ld_inst_index == ld_inst_index_ && ld_pid == ld_pid_; + + if (same && inited_) { + return true; + } + + ld_inst_index_ = ld_inst_index; + ld_path_ = ld_path; + ld_pid_ = ld_pid; + display_width_ = width; + display_height_ = height; + + inited_ = load_ld_library() && connect_ld() && init_screencap(); + + return inited_; +} + +bool LDExtras::reload() +{ + inited_ = load_ld_library() && connect_ld() && init_screencap(); + LogInfo << "Reload LDExtras: " << VAR(inited_); + return inited_; +} + +void LDExtras::uninit() +{ + inited_ = false; + disconnect_ld(); +} + +std::optional LDExtras::screencap() const +{ + if (!screenshot_instance_) { + LogError << "screenshot_instance_ is null"; + return std::nullopt; + } + + void* pixels = screenshot_instance_->cap(); + if (!pixels) { + LogError << "Failed to capture screen"; + return std::nullopt; + } + + const cv::Mat raw(display_height_, display_width_, CV_8UC3, pixels); + cv::Mat dst; + cv::flip(raw, dst, 0); + + return dst; +} + +bool LDExtras::load_ld_library() +{ + auto lib_path = ld_path_ / "ldopengl64.dll"; + + if (!load_library(lib_path)) { + LogError << "Failed to load library" << VAR(lib_path); + return false; + } + + create_screenshot_instance_func_ = get_function(kCreateScreenShotInstanceFuncName); + if (!create_screenshot_instance_func_) { + LogError << "Failed to get function" << VAR(kCreateScreenShotInstanceFuncName); + return false; + } + + return true; +} + +bool LDExtras::connect_ld() +{ + LogInfo << VAR(ld_inst_index_) << VAR(ld_pid_); + + screenshot_instance_ = create_screenshot_instance_func_(ld_inst_index_, ld_pid_); + if (!screenshot_instance_) { + LogError << "Failed to create screenshot instance" << VAR(ld_inst_index_); + return false; + } + + return true; +} + +bool LDExtras::init_screencap() +{ + if (!screenshot_instance_) { + LogError << "screenshot_instance_ is null"; + return false; + } + + LogDebug << VAR(display_width_) << VAR(display_height_); + return true; +} + +void LDExtras::disconnect_ld() +{ + LogInfo << "Disconnecting LD"; + + if (screenshot_instance_) { + screenshot_instance_->release(); + screenshot_instance_ = nullptr; + } +} + +} +#endif diff --git a/src/MaaCore/LDExtras.h b/src/MaaCore/LDExtras.h new file mode 100644 index 0000000000..3cd516f895 --- /dev/null +++ b/src/MaaCore/LDExtras.h @@ -0,0 +1,58 @@ +#pragma once + +#include "Common/AsstConf.h" + +#if ASST_WITH_EMULATOR_EXTRAS + +#include +#include +#include +#include "Utils/Platform/SafeWindows.h" + +#include "LD/dnopengl/dnopengl.h" + +#include "Utils/LibraryHolder.hpp" +#include "Utils/NoWarningCVMat.h" + +namespace asst +{ +class LDExtras : public LibraryHolder +{ +public: + LDExtras() = default; + + virtual ~LDExtras(); + + bool inited() const { return inited_; } + + bool init(const std::filesystem::path& ld_path, unsigned int ld_inst_index, unsigned int ld_pid, int width, int height); + bool reload(); + void uninit(); + + std::optional screencap() const; + +private: + bool load_ld_library(); + bool connect_ld(); + bool init_screencap(); + void disconnect_ld(); + +private: + unsigned int ld_inst_index_ = 0; + unsigned int ld_pid_ = 0; + + IScreenShotClass* screenshot_instance_ = nullptr; + int display_width_ = 0; + int display_height_ = 0; + + bool inited_ = false; + +private: + std::filesystem::path ld_path_; + inline static const std::string kCreateScreenShotInstanceFuncName = "CreateScreenShotInstance"; + +private: + std::function create_screenshot_instance_func_; +}; +} +#endif diff --git a/src/MaaCore/MaaCore.vcxproj b/src/MaaCore/MaaCore.vcxproj index 3d7a9f339d..95c3f965bc 100644 --- a/src/MaaCore/MaaCore.vcxproj +++ b/src/MaaCore/MaaCore.vcxproj @@ -69,6 +69,7 @@ + @@ -260,6 +261,7 @@ + diff --git a/src/MaaCore/MaaCore.vcxproj.filters b/src/MaaCore/MaaCore.vcxproj.filters index f483ad3978..a83810b404 100644 --- a/src/MaaCore/MaaCore.vcxproj.filters +++ b/src/MaaCore/MaaCore.vcxproj.filters @@ -728,6 +728,9 @@ Source\Task\Roguelike + + Source\Controller + @@ -1221,5 +1224,8 @@ Source\Resource\Roguelike + + Source\Controller + \ No newline at end of file diff --git a/src/MaaWpfGui/Constants/ConfigurationKeys.cs b/src/MaaWpfGui/Constants/ConfigurationKeys.cs index a44df19c86..04adf42c95 100755 --- a/src/MaaWpfGui/Constants/ConfigurationKeys.cs +++ b/src/MaaWpfGui/Constants/ConfigurationKeys.cs @@ -64,6 +64,9 @@ namespace MaaWpfGui.Constants public const string MuMu12EmulatorPath = "Connect.MuMu12EmulatorPath"; public const string MuMu12Index = "Connect.MuMu12Index"; public const string MuMu12Display = "Connect.MuMu12Display"; + public const string LdPlayerExtrasEnabled = "Connect.LdPlayerExtras.Enabled"; + public const string LdPlayerEmulatorPath = "Connect.LdPlayerEmulatorPath"; + public const string LdPlayerIndex = "Connect.LdPlayerIndex"; public const string RetryOnAdbDisconnected = "Connect.RetryOnDisconnected"; public const string AllowAdbRestart = "Connect.AllowADBRestart"; public const string AllowAdbHardRestart = "Connect.AllowADBHardRestart"; diff --git a/src/MaaWpfGui/Constants/UILogColor.cs b/src/MaaWpfGui/Constants/UILogColor.cs index 81f36ef1ca..7b2cc17406 100644 --- a/src/MaaWpfGui/Constants/UILogColor.cs +++ b/src/MaaWpfGui/Constants/UILogColor.cs @@ -64,6 +64,11 @@ namespace MaaWpfGui.Constants /// public const string MuMuSpecialScreenshot = "MuMuSpecialScreenshot"; + /// + /// The recommended color for LD special screenshot. + /// + public const string LdSpecialScreenshot = "LdSpecialScreenshot"; + // 颜色在MaaWpfGui\Res\Themes中定义 // Brush are defined in MaaWpfGui\Res\Themes } diff --git a/src/MaaWpfGui/Main/AsstProxy.cs b/src/MaaWpfGui/Main/AsstProxy.cs index e58055d090..795fca5cb3 100644 --- a/src/MaaWpfGui/Main/AsstProxy.cs +++ b/src/MaaWpfGui/Main/AsstProxy.cs @@ -119,6 +119,11 @@ namespace MaaWpfGui.Main AsstSetConnectionExtras("MuMuEmulator12", extras); } + private static void AsstSetConnectionExtrasLdPlayer(string extras) + { + AsstSetConnectionExtras("LDPlayer", extras); + } + private static unsafe AsstTaskId AsstAppendTask(AsstHandle handle, string type, string taskParams) { fixed (byte* ptr1 = EncodeNullTerminatedUtf8(type), @@ -534,6 +539,20 @@ namespace MaaWpfGui.Main method = "MuMuExtras"; } + break; + case "LDPlayer": + if (Instances.SettingsViewModel.LdPlayerExtras.Enable && method != "LDExtras") + { + Instances.TaskQueueViewModel.AddLog(LocalizationHelper.GetString("LdExtrasNotEnabledMessage"), UiLogColor.Error); + Instances.CopilotViewModel.AddLog(LocalizationHelper.GetString("LdExtrasNotEnabledMessage"), UiLogColor.Error, showTime: false); + needToStop = true; + } + else if (timeCost < 100) + { + color = UiLogColor.LdSpecialScreenshot; + method = "LDExtras"; + } + break; } @@ -1766,6 +1785,9 @@ namespace MaaWpfGui.Main case "MuMuEmulator12": AsstSetConnectionExtrasMuMu12(Instances.SettingsViewModel.MuMuEmulator12Extras.Config); break; + case "LDPlayer": + AsstSetConnectionExtrasLdPlayer(Instances.SettingsViewModel.LdPlayerExtras.Config); + break; } if (Instances.SettingsViewModel.AutoDetectConnection) diff --git a/src/MaaWpfGui/Res/Localizations/en-us.xaml b/src/MaaWpfGui/Res/Localizations/en-us.xaml index 749b9dfae7..db4a7799b4 100644 --- a/src/MaaWpfGui/Res/Localizations/en-us.xaml +++ b/src/MaaWpfGui/Res/Localizations/en-us.xaml @@ -395,6 +395,22 @@ Only supports Official(CN) and Bilibili server. Login account is not supported.< Instance Number Display Number Mumu screenshot enhancement not enabled, please check related settings + Enable LD's screenshot enhancement mode + + Requires LDPlayer 9 V9.0.78 or later.\n + It is strongly recommended to perform a screenshot test before using this feature for the first time.\n\n + Please provide the following information:\n\n + 1. Emulator path: (e.g., C:\\leidian\\LDPlayer9)\n + The emulator path should be the folder where the emulator application is located, for example, if the application path is\n + "C:\\leidian\\LDPlayer9\\ldconsole.exe"\n + You should fill in\n + "C:\\leidian\\LDPlayer9".\n\n + 2. Instance number: (e.g., 0)\n + The instance number can be found in the LDPlayer multi-instance manager, default is 0. If there are multiple instances, the number can be found in the ID column under Version/ID.\n + + LD Emulator exec path + Instance Number + LD screenshot enhancement not enabled, please check related settings Retry launching the emulator when ADB connection fails Try restarting the emulator after 20 failed reconnect attempts, must be checked when using a background timed task and setting the task to close the emulator when finished Emulator path is empty! Please fill in "Launch Settings - Emulator Path" and reselect. diff --git a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml index df1f1d3610..a850030e88 100644 --- a/src/MaaWpfGui/Res/Localizations/ja-jp.xaml +++ b/src/MaaWpfGui/Res/Localizations/ja-jp.xaml @@ -395,6 +395,21 @@ インスタンス番号 表示番号 MuMu スクリーンショットの強化 が有効になっていません。関連する設定を確認してください + LD のスクリーンショット拡張モードを有効にする + + LDPlayer 9 V9.0.78 以降のバージョンが必要です。\n + この機能を初めて使用する前に、スクリーンショットテストを行うことを強くお勧めします。\n\n + 以下の情報を入力してください:\n\n + 1. エミュレーターのパス:(例:C:\\leidian\\LDPlayer9)\n + エミュレーターのパスは、エミュレーターアプリケーションが存在するフォルダのパスを入力してください。例えば、アプリケーションパスが\n + 「C:\\leidian\\LDPlayer9\\ldconsole.exe」の場合、\n + 「C:\\leidian\\LDPlayer9」と入力してください。\n\n + 2. インスタンス番号:(例:0)\n + インスタンス番号は、LDPlayerのマルチインスタンスマネージャーで確認できます。デフォルトは0です。複数のインスタンスがある場合、バージョン/番号のID列に番号が表示されます。\n + + LD エミュレータパス + インスタンス番号 + LD スクリーンショットの強化 が有効になっていません。関連する設定を確認してください ADB接続が失敗した場合、エミュレータの起動を試みる 再接続に20回失敗した後、エミュレータを再起動してみてください,バックグラウンドのタイムドタスクを使用し、終了時にエミュレータを終了させるタスクを設定する場合は、必ずチェックを入れること エミュレータのパスが空です!「起動設定-エミュレータのパス」を入力してから再度選択してください。 diff --git a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml index 341f7a7efc..c0517195e5 100644 --- a/src/MaaWpfGui/Res/Localizations/ko-kr.xaml +++ b/src/MaaWpfGui/Res/Localizations/ko-kr.xaml @@ -396,6 +396,21 @@ OF-1을 해금하지 않았다면 선택하지 말아 주세요. 인스턴스 번호 표시 번호 MuMu의 스크린샷 향상가 활성화되지 않았습니다. 관련 설정을 확인하세요 + LD 스크린샷 향상 모드 활성화 + + LDPlayer 9 V9.0.78 이상 버전이 필요합니다.\n + 이 기능을 처음 사용하기 전에 스크린샷 테스트를 수행하는 것이 좋습니다.\n\n + 다음 정보를 입력하십시오:\n\n + 1. 에뮬레이터 경로: (예: C:\\leidian\\LDPlayer9)\n + 에뮬레이터 경로는 에뮬레이터 응용 프로그램이 있는 폴더 경로여야 합니다. 예를 들어, 응용 프로그램 경로가\n + "C:\\leidian\\LDPlayer9\\ldconsole.exe"인 경우,\n + "C:\\leidian\\LDPlayer9"를 입력해야 합니다。\n\n + 2. 인스턴스 번호: (예: 0)\n + 인스턴스 번호는 LDPlayer 다중 인스턴스 관리자에서 확인할 수 있습니다. 기본값은 0입니다. 여러 인스턴스가 있는 경우, 버전/번호의 ID 열에서 번호를 찾을 수 있습니다。\n + + LD 에뮬레이터 경로 + 인스턴스 번호 + LD 의 스크린샷 향상가 활성화되지 않았습니다. 관련 설정을 확인하세요 ADB 연결이 실패하면 에뮬레이터를 다시 시도합니다 재연결을 20회 시도해도 실패하면 에뮬레이터를 다시 시작합니다. 백그라운드 예약을 사용하고 작업이 완료되면 에뮬레이터가 종료되도록 설정하려면 반드시 선택해야 합니다 에뮬레이터 경로가 비어 있습니다!「연결 설정/에뮬레이터 경로」를 입력한 후 다시 선택하세요. diff --git a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml index 1356402572..d960000961 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-cn.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-cn.xaml @@ -395,6 +395,22 @@ 实例编号 屏幕编号 Mumu 截图增强未生效,请检查相关设置 + 启用 LD 截图增强模式 + + 需使用 LDPlayer 9 V9.0.78 及更新版本。\n + 强烈建议在开启本功能后的首次使用之前进行截图测试。\n\n + 请填写以下信息:\n\n + 1. 模拟器路径:(例如:C:\\leidian\\LDPlayer9)\n + 模拟器路径应填写模拟器应用所在文件夹路径,例如应用路径为\n + 「C:\\leidian\\LDPlayer9\\ldconsole.exe」\n + 应填写\n + 「C:\\leidian\\LDPlayer9」。\n\n + 2. 实例编号:(例如:0)\n + 实例编号可在 LDPlayer 多开器中查看,默认为 0,若有多开实例,编号见 版本/编号 中的 ID。\n + + LD 安装路径 + 实例编号 + LD 截图增强未生效,请检查相关设置 ADB 连接失败时尝试启动模拟器 重连失败 20 次后尝试重启模拟器,使用后台定时任务且设置任务完成关闭模拟器时请勾选 模拟器路径为空!请填写「启动设置-模拟器路径」后重新勾选。 diff --git a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml index 2ed1a62832..69cb3c1f04 100644 --- a/src/MaaWpfGui/Res/Localizations/zh-tw.xaml +++ b/src/MaaWpfGui/Res/Localizations/zh-tw.xaml @@ -395,6 +395,22 @@ 實例號碼 螢幕號碼 Mumu 截圖增強未生效,请檢查相關設定 + 啟用 LD 截圖增強模式 + + 需使用 LDPlayer 9 V9.0.78 及更新版本。\n + 強烈建議在開啟本功能後的首次使用之前進行截圖測試。\n\n + 請填寫以下信息:\n\n + 1. 模擬器路徑:(例如:C:\\leidian\\LDPlayer9)\n + 模擬器路徑應填寫模擬器應用所在文件夾路徑,例如應用路徑為\n + 「C:\\leidian\\LDPlayer9\\ldconsole.exe」\n + 應填寫\n + 「C:\\leidian\\LDPlayer9」。\n\n + 2. 實例編號:(例如:0)\n + 實例編號可在 LDPlayer 多開器中查看,默認為 0,若有多開實例,編號見 版本/編號 中的 ID。\n + + LD 模擬器路徑 + 實例號碼 + LD 截圖增強未生效,请檢查相關設定 ADB 連線失敗時嘗試啟動模擬器 重連失敗 20 次後嘗試重開模擬器,使用後台定時任務且設定任務完成關閉模擬器時必須勾選 模擬器路徑為空!請填寫「啟動設定-模擬器路徑」後重新勾選。 diff --git a/src/MaaWpfGui/Res/Themes/Dark.xaml b/src/MaaWpfGui/Res/Themes/Dark.xaml index 38e50c261d..c614fef3f2 100644 --- a/src/MaaWpfGui/Res/Themes/Dark.xaml +++ b/src/MaaWpfGui/Res/Themes/Dark.xaml @@ -44,4 +44,5 @@ + diff --git a/src/MaaWpfGui/Res/Themes/Light.xaml b/src/MaaWpfGui/Res/Themes/Light.xaml index eb56be8288..f211506eb7 100644 --- a/src/MaaWpfGui/Res/Themes/Light.xaml +++ b/src/MaaWpfGui/Res/Themes/Light.xaml @@ -26,4 +26,5 @@ + diff --git a/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs b/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs index d3605f7502..2fbf5e8ef5 100755 --- a/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs +++ b/src/MaaWpfGui/ViewModels/UI/SettingsViewModel.cs @@ -4305,6 +4305,144 @@ namespace MaaWpfGui.ViewModels.UI public MuMuEmulator12ConnectionExtras MuMuEmulator12Extras { get; set; } = new(); + public class LdPlayerConnectionExtras : PropertyChangedBase + { + private bool _enable = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerExtrasEnabled, bool.FalseString)); + + public bool Enable + { + get => _enable; + set + { + if (!SetAndNotify(ref _enable, value)) + { + return; + } + + if (value) + { + MessageBoxHelper.Show(LocalizationHelper.GetString("LdExtrasEnabledTip")); + } + + Instances.AsstProxy.Connected = false; + ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerExtrasEnabled, value.ToString()); + } + } + + private static readonly string _configuredPath = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerEmulatorPath, @"C:\leidian\LDPlayer9"); + private string _emulatorPath = Directory.Exists(_configuredPath) ? _configuredPath : string.Empty; + + /// + /// Gets or sets a value indicating the path of the emulator. + /// + public string EmulatorPath + { + get => _emulatorPath; + set + { + if (_enable && !string.IsNullOrEmpty(value) && !Directory.Exists(value)) + { + MessageBoxHelper.Show("LD Emulator Path Not Found"); + value = string.Empty; + } + + Instances.AsstProxy.Connected = false; + SetAndNotify(ref _emulatorPath, value); + ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerEmulatorPath, value); + } + } + + private string _index = ConfigurationHelper.GetValue(ConfigurationKeys.LdPlayerIndex, "0"); + + /// + /// Gets or sets the index of the emulator. + /// + public string Index + { + get => _index; + set + { + Instances.AsstProxy.Connected = false; + SetAndNotify(ref _index, value); + ConfigurationHelper.SetValue(ConfigurationKeys.LdPlayerIndex, value); + } + } + + private int GetEmulatorPid(int index) + { + string emulatorPath = $@"{EmulatorPath}\ldconsole.exe"; + if (!File.Exists(emulatorPath)) + { + MessageBoxHelper.Show("LD Emulator Path Not Found"); + return 0; + } + + ProcessStartInfo startInfo = new ProcessStartInfo + { + FileName = emulatorPath, + Arguments = "list2", + RedirectStandardOutput = true, + UseShellExecute = false, + CreateNoWindow = true, + }; + + using Process? process = Process.Start(startInfo); + if (process == null) + { + _logger.Warning("Failed to start ldconsole list2"); + return 0; + } + + using StreamReader reader = process.StandardOutput; + string result = reader.ReadToEnd(); + string[] lines = result.Split([Environment.NewLine], StringSplitOptions.RemoveEmptyEntries); + + if (lines.Length <= 0) + { + _logger.Warning("Failed to get emulator PID."); + return 0; + } + + foreach (string line in lines) + { + string[] parts = line.Split(','); + if (parts.Length < 6 || !int.TryParse(parts[0], out int currentIndex) || currentIndex != index) + { + continue; + } + + if (int.TryParse(parts[5], out int pid)) + { + return pid; + } + } + + _logger.Warning("Failed to get emulator PID."); + return 0; + } + + public string Config + { + get + { + if (!Enable) + { + return JsonConvert.SerializeObject(new JObject()); + } + + var configObject = new JObject + { + ["path"] = EmulatorPath, + ["index"] = int.TryParse(Index, out var indexParse) ? indexParse : 0, + ["pid"] = GetEmulatorPid(indexParse), + }; + return JsonConvert.SerializeObject(configObject); + } + } + } + + public LdPlayerConnectionExtras LdPlayerExtras { get; set; } = new(); + private bool _retryOnDisconnected = Convert.ToBoolean(ConfigurationHelper.GetValue(ConfigurationKeys.RetryOnAdbDisconnected, bool.FalseString)); /// diff --git a/src/MaaWpfGui/Views/UserControl/ConnectSettingsUserControl.xaml b/src/MaaWpfGui/Views/UserControl/ConnectSettingsUserControl.xaml index 98286d2dee..1a0b0124a1 100644 --- a/src/MaaWpfGui/Views/UserControl/ConnectSettingsUserControl.xaml +++ b/src/MaaWpfGui/Views/UserControl/ConnectSettingsUserControl.xaml @@ -53,8 +53,8 @@ + HorizontalAlignment="Center" + Orientation="Horizontal"> - - - - - + + + + + + + + + + + + + +