兼容MuMu模拟器

This commit is contained in:
MistEO
2021-07-25 02:42:32 +08:00
parent a195f559b8
commit eb6eb55161
5 changed files with 82 additions and 31 deletions

View File

@@ -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;

View File

@@ -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 };
}

View File

@@ -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()

View File

@@ -45,14 +45,14 @@ A game assistance for Arknights
#### 腾讯手游助手
兼容但需要手动设置分辨率设置中心——引擎设置——分辨率设置——1280x720——保存后重启模拟器
理论上完美兼容,未多做测试
#### MuMu模拟器
MuMu是个奇葩它的所有的窗口句柄均不响应SendMessage鼠标消息
- MuMu模拟器
兼容使用了adb控制的方式。但需要手动设置分辨率设置中心——界面——分辨率设置——1280x720——保存后重启模拟器
完美兼容专门单独做了一套基于Adb控制逻辑
- MuMu手游助手星云引擎
不兼容,正在想办法……

View File

@@ -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",