mirror of
https://github.com/MaaAssistantArknights/MaaAssistantArknights.git
synced 2026-07-15 17:30:27 +08:00
兼容MuMu模拟器
This commit is contained in:
@@ -2,6 +2,7 @@
|
||||
|
||||
#include <string>
|
||||
#include <random>
|
||||
#include <optional>
|
||||
#include <Windows.h>
|
||||
|
||||
#include "AsstDef.h"
|
||||
@@ -33,7 +34,7 @@ namespace asst {
|
||||
static double getScreenScale();
|
||||
private:
|
||||
bool findHandle();
|
||||
unsigned long callCmd(const std::string& cmd, int wait_time = 1000);
|
||||
std::optional<std::string> callCmd(const std::string& cmd, bool use_pipe = true);
|
||||
|
||||
const EmulatorInfo m_emulator_info;
|
||||
const HandleType m_handle_type;
|
||||
|
||||
@@ -78,7 +78,7 @@ std::optional<std::string> Assistance::set_emulator(const std::string& emulator_
|
||||
else {
|
||||
ret = create_handles(m_configer.m_handles[emulator_name]);
|
||||
}
|
||||
if (ret && m_pWindow->showWindow()) {
|
||||
if (ret && m_pWindow->showWindow() && m_pWindow->resizeWindow()) {
|
||||
m_inited = true;
|
||||
return cor_name;
|
||||
}
|
||||
@@ -170,7 +170,6 @@ void Assistance::working_proc(Assistance* pThis)
|
||||
std::unique_lock<std::mutex> lock(pThis->m_mutex);
|
||||
if (pThis->m_thread_running) {
|
||||
auto && [scale, cur_image] = pThis->get_format_image();
|
||||
DebugTrace("Scale", scale);
|
||||
pThis->m_pCtrl->setControlScale(scale);
|
||||
|
||||
if (cur_image.empty()) {
|
||||
@@ -178,7 +177,7 @@ void Assistance::working_proc(Assistance* pThis)
|
||||
pThis->stop(false);
|
||||
continue;
|
||||
}
|
||||
if (cur_image.cols < pThis->m_configer.DefaultWindowWidth || cur_image.rows < pThis->m_configer.DefaultWindowHeight) {
|
||||
if (cur_image.rows < 100) {
|
||||
DebugTraceInfo("Window Could not be minimized!!!");
|
||||
pThis->m_pWindow->showWindow();
|
||||
pThis->m_condvar.wait_for(lock,
|
||||
@@ -320,7 +319,7 @@ void Assistance::working_proc(Assistance* pThis)
|
||||
std::pair<double, cv::Mat> asst::Assistance::get_format_image()
|
||||
{
|
||||
auto && cur_image = m_pView->getImage(m_pView->getWindowRect());
|
||||
if (cur_image.empty() || cur_image.cols < m_configer.DefaultWindowWidth || cur_image.rows < m_configer.DefaultWindowHeight) {
|
||||
if (cur_image.empty() || cur_image.rows < 100) {
|
||||
DebugTraceError("Window image error");
|
||||
return { 0, cur_image };
|
||||
}
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
|
||||
#include "AsstDef.h"
|
||||
#include "Logger.hpp"
|
||||
#include "Configer.h"
|
||||
|
||||
using namespace asst;
|
||||
|
||||
@@ -98,11 +99,21 @@ bool WinMacro::findHandle()
|
||||
adb_dir = '"' + StringReplaceAll(m_emulator_info.adb.path, "[EmulatorPath]", adb_dir) + '"';
|
||||
std::string connect_cmd = adb_dir + m_emulator_info.adb.connect;
|
||||
|
||||
auto ret = callCmd(connect_cmd, 10000);
|
||||
if (ret != 0) {
|
||||
DebugTraceError("Connect ADB Error", ret);
|
||||
if (!callCmd(connect_cmd)) {
|
||||
DebugTraceError("Connect Adb Error");
|
||||
return false;
|
||||
}
|
||||
auto display_ret = callCmd(adb_dir + m_emulator_info.adb.display);
|
||||
if (display_ret) {
|
||||
std::string pipe_str = std::move(display_ret).value();
|
||||
sscanf_s(pipe_str.c_str(), m_emulator_info.adb.display_regex.c_str(),
|
||||
&m_emulator_info.adb.display_width, &m_emulator_info.adb.display_height);
|
||||
}
|
||||
else {
|
||||
DebugTraceError("Get Display Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
m_click_cmd = adb_dir + m_emulator_info.adb.click;
|
||||
}
|
||||
DebugTrace("Handle:", m_handle, "Name:", m_emulator_info.name, "Type:", m_handle_type);
|
||||
@@ -115,31 +126,69 @@ bool WinMacro::findHandle()
|
||||
}
|
||||
}
|
||||
|
||||
unsigned long asst::WinMacro::callCmd(const std::string& cmd, int wait_time)
|
||||
std::optional<std::string> asst::WinMacro::callCmd(const std::string& cmd, bool use_pipe)
|
||||
{
|
||||
// int ret = system(cmd.c_str());
|
||||
// 初始化管道
|
||||
constexpr int PipeBuffSize = 1024;
|
||||
HANDLE pipe_read = NULL;
|
||||
HANDLE pipe_write = NULL;
|
||||
SECURITY_ATTRIBUTES sa_out_pipe;
|
||||
::ZeroMemory(&sa_out_pipe, sizeof(sa_out_pipe));
|
||||
sa_out_pipe.nLength = sizeof(SECURITY_ATTRIBUTES);
|
||||
sa_out_pipe.lpSecurityDescriptor = NULL;
|
||||
sa_out_pipe.bInheritHandle = TRUE;
|
||||
BOOL pipe_ret = FALSE;
|
||||
if (use_pipe) {
|
||||
pipe_ret = ::CreatePipe(&pipe_read, &pipe_write, &sa_out_pipe, PipeBuffSize);
|
||||
DebugTrace("Create Pipe ret", pipe_ret);
|
||||
}
|
||||
|
||||
// 准备启动ADB进程
|
||||
STARTUPINFOA startup_info;
|
||||
PROCESS_INFORMATION process_info;
|
||||
ZeroMemory(&startup_info, sizeof(startup_info));
|
||||
ZeroMemory(&process_info, sizeof(process_info));
|
||||
startup_info.cb = sizeof(STARTUPINFO);
|
||||
startup_info.dwFlags = STARTF_USESTDHANDLES | STARTF_USESHOWWINDOW;
|
||||
startup_info.hStdOutput = pipe_write;
|
||||
startup_info.hStdError = pipe_write;
|
||||
startup_info.wShowWindow = SW_HIDE;
|
||||
|
||||
DWORD ret = -1;
|
||||
|
||||
if (!::CreateProcessA(NULL, const_cast<LPSTR>(cmd.c_str()), NULL, NULL, FALSE, CREATE_NO_WINDOW, NULL, NULL, &startup_info, &process_info)) {
|
||||
if (!::CreateProcessA(NULL, const_cast<LPSTR>(cmd.c_str()), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &startup_info, &process_info)) {
|
||||
DebugTraceError("Create process error");
|
||||
return ret;
|
||||
return std::nullopt;
|
||||
}
|
||||
::WaitForSingleObject(process_info.hProcess, 30000);
|
||||
|
||||
::WaitForSingleObject(process_info.hProcess, wait_time);
|
||||
std::string pipe_str;
|
||||
if (use_pipe && pipe_ret) {
|
||||
DWORD read_num = 0;
|
||||
DWORD std_num = 0;
|
||||
if (::PeekNamedPipe(pipe_read, NULL, 0, NULL, &read_num, NULL) && read_num > 0) {
|
||||
char pipe_buffer[PipeBuffSize] = { 0 };
|
||||
::ReadFile(pipe_read, pipe_buffer, read_num, &std_num, NULL);
|
||||
pipe_str = std::string(pipe_buffer, std_num);
|
||||
}
|
||||
}
|
||||
|
||||
::GetExitCodeProcess(process_info.hProcess, &ret);
|
||||
|
||||
::CloseHandle(process_info.hProcess);
|
||||
::CloseHandle(process_info.hThread);
|
||||
DebugTrace("Call", cmd, "—— ret", ret);
|
||||
DebugTrace("Call", cmd, "ret", ret);
|
||||
if (use_pipe) {
|
||||
DebugTrace("Pipe:", pipe_str);
|
||||
}
|
||||
|
||||
return ret;
|
||||
if (pipe_read != NULL) {
|
||||
::CloseHandle(pipe_read);
|
||||
}
|
||||
if (pipe_write != NULL) {
|
||||
::CloseHandle(pipe_write);
|
||||
}
|
||||
|
||||
return pipe_str;
|
||||
}
|
||||
|
||||
bool WinMacro::resizeWindow(int width, int height)
|
||||
@@ -217,24 +266,19 @@ bool WinMacro::click(const Point& p)
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = p.x * m_control_scale;
|
||||
int y = p.y * m_control_scale;
|
||||
DebugTrace("Click, raw:", p.x, p.y, "corr:", x, y);
|
||||
|
||||
if (m_is_adb) {
|
||||
int x = p.x * m_control_scale;
|
||||
int y = p.y * m_control_scale;
|
||||
std::string cur_cmd = StringReplaceAll(m_click_cmd, "[x]", std::to_string(x));
|
||||
cur_cmd = StringReplaceAll(cur_cmd, "[y]", std::to_string(y));
|
||||
auto ret = callCmd(cur_cmd);
|
||||
return !ret;
|
||||
return callCmd(cur_cmd, false).has_value();
|
||||
}
|
||||
else {
|
||||
int x = p.x / m_control_scale;
|
||||
int y = p.y / m_control_scale;
|
||||
DebugTrace("Click, raw:", p.x, p.y, "corr:", x, y);
|
||||
|
||||
LPARAM lparam = MAKELPARAM(x, y);
|
||||
|
||||
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
|
||||
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -268,7 +312,12 @@ bool WinMacro::click(const Rect& rect)
|
||||
|
||||
void asst::WinMacro::setControlScale(double scale)
|
||||
{
|
||||
m_control_scale = scale;
|
||||
if (m_is_adb) {
|
||||
m_control_scale = scale * scale * Configer::DefaultWindowWidth / m_emulator_info.adb.display_width;
|
||||
}
|
||||
else {
|
||||
m_control_scale = scale;
|
||||
}
|
||||
}
|
||||
|
||||
Rect WinMacro::getWindowRect()
|
||||
|
||||
@@ -45,14 +45,14 @@ A game assistance for Arknights
|
||||
|
||||
#### 腾讯手游助手
|
||||
|
||||
兼容,但需要手动设置分辨率:设置中心——引擎设置——分辨率设置——1280x720——保存后重启模拟器
|
||||
理论上完美兼容,未多做测试
|
||||
|
||||
#### MuMu模拟器
|
||||
|
||||
MuMu是个奇葩,它的所有的窗口句柄均不响应SendMessage鼠标消息
|
||||
|
||||
- MuMu模拟器
|
||||
兼容(使用了adb控制的方式)。但需要手动设置分辨率:设置中心——界面——分辨率设置——1280x720——保存后重启模拟器
|
||||
完美兼容,专门单独做了一套基于Adb的控制逻辑
|
||||
- MuMu手游助手(星云引擎)
|
||||
不兼容,正在想办法……
|
||||
|
||||
|
||||
@@ -211,8 +211,8 @@
|
||||
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
|
||||
"connect": " connect 127.0.0.1:7555",
|
||||
"click": " shell input tap [x] [y]",
|
||||
"display": " shell 'dumpsys window displays | grep init='",
|
||||
"displayRegex": "cur=[width]x[height]"
|
||||
"display": " shell dumpsys window displays | grep init= | awk ' { print $3 } '",
|
||||
"displayRegex": "cur=%dx%d"
|
||||
},
|
||||
"width": 1280,
|
||||
"height": 809,
|
||||
@@ -376,6 +376,8 @@
|
||||
},
|
||||
"ReturnToFriends": {
|
||||
"filename": "Return.png",
|
||||
"threshold": 0.85,
|
||||
"cacheThreshold": 0.85,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"Friends",
|
||||
|
||||
Reference in New Issue
Block a user