Merge pull request #2811 from MaaAssistantArknights/dev

Release v4.7.0-beta.1
This commit is contained in:
MistEO
2022-11-19 22:51:09 +08:00
committed by GitHub
6 changed files with 149 additions and 36 deletions

View File

@@ -1,8 +1,7 @@
**若更新后滑动操作没反应、自动战斗没反应、肉鸽不上人等,请进入 `设置` - `连接设置` - `强制替换 ADB`**
- 修复 使用中文路径时minitouch 出现的一系列错误 @MistEO
- 修复 使用竖屏、旋转 180° 等时,minitouch 的操作错误 @MistEO
- 修复 POSIX 下 socket 超时时间过长的问题 @aa889788
- 优化 自定义基建 内置 243 3 换作业 @Black1312
- 新增 自定义基建 `description_post` 字段,整理内置作业格式 @MistEO
- 更新 文档 @DavidWang19
- 新增 macOS 对 minitouch 的支持(但没完全支持 @horror-proton @hguandl
- 修复 minitouch 在部署竖屏模拟器上的操作错误 @MistEO
- 修复 模拟器断开重连后minitouch 无法继续工作的问题 @MistEO
- 修复 界面 基建设置心情阈值显示错误的问题 @ABA2396
- Fix a dead loop when recruiting opers in the auto-IS function of EN client @MistEO

View File

@@ -17,7 +17,7 @@
[NoAVX](../3rdparty/ppocr_noavx.zip)バージョンの `PaddleOCR` をダウンロードして解凍し、このアプリで同じ名前のファイルに置き換えてください。これは、`AVX` 命令セットをサポートしていないCPUのユーザー向けのパフォーマンス低下の代替手段であり、必要でない限り使用しないでください。
_具体的には、[CPU-Z](https://www.cpuid.com/softwares/cpu-z.html)をダウンロードし、「命令セット」に `AVX` があるかどうかで判断できます。_
_具体的には、[CPU-Z](https://www.cpuid.com/softwares/cpu-z.html) をダウンロードし、「命令セット」に `AVX` があるかどうかで判断できます。_
### 可能性3ほかのランタイムライブラリの問題

View File

@@ -162,6 +162,9 @@
"Storage full"
]
},
"Phantom@Roguelike@StageEncounterOptionUnknown": {
"templThreshold": 0.9
},
"BattleStageName": {
"Doc": "该任务的 ocrReplace 被所有涉及Rouge-like的English识别任务复用",
"ocrReplace": [

View File

@@ -7,7 +7,11 @@
#include <ws2tcpip.h>
#else
#include <fcntl.h>
#include <signal.h>
#include <sys/errno.h>
#ifndef __APPLE__
#include <sys/prctl.h>
#endif
#include <sys/wait.h>
#include <unistd.h>
#endif
@@ -412,6 +416,7 @@ std::optional<std::string> asst::Controller::call_command(const std::string& cmd
is_reconnect_success = reconnect_str.find("error") == std::string::npos;
}
if (is_reconnect_success) {
call_and_hup_minitouch(m_adb.call_minitouch);
auto recall_ret = call_command(cmd, timeout, false /* 禁止重连避免无限递归 */, recv_by_socket);
if (recall_ret) {
// 重连并成功执行了
@@ -447,12 +452,20 @@ void asst::Controller::callback(AsstMsg msg, const json::value& details)
bool asst::Controller::call_and_hup_minitouch(const std::string& cmd)
{
LogTraceFunction;
release_minitouch(true);
Log.info(cmd);
m_minitouch_avaiable = false;
constexpr int PipeReadBuffSize = 4096ULL;
constexpr int PipeWriteBuffSize = 64 * 1024ULL;
std::string pipe_str;
auto check_timeout = [&](const auto& start_time) -> bool {
using namespace std::chrono_literals;
return std::chrono::steady_clock::now() - start_time < 3s;
};
#ifdef _WIN32
SECURITY_ATTRIBUTES sa_attr_inherit {
.nLength = sizeof(SECURITY_ATTRIBUTES),
@@ -489,20 +502,17 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd)
if (!create_ret) {
DWORD err = GetLastError();
Log.error("Failed to create process for minitouch, err", err);
release_minitouch(true);
return false;
}
auto start_time = std::chrono::steady_clock::now();
auto check_timeout = [&]() -> bool {
using namespace std::chrono_literals;
return std::chrono::steady_clock::now() - start_time < 3s;
};
auto pipe_buffer = std::make_unique<char[]>(PipeReadBuffSize);
OVERLAPPED pipeov { .hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr) };
std::ignore = ReadFile(pipe_parent_read, pipe_buffer.get(), PipeReadBuffSize, nullptr, &pipeov);
while (!need_exit() && check_timeout()) {
while (!need_exit() && check_timeout(start_time)) {
if (pipe_str.find('$') != std::string::npos) {
break;
}
@@ -518,12 +528,86 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd)
pipe_parent_read = INVALID_HANDLE_VALUE;
m_minitouch_parent_write = pipe_parent_write;
#else // !_WIN32
// TODO
std::ignore = pipe_str;
std::ignore = PipeReadBuffSize;
std::ignore = PipeWriteBuffSize;
return false;
#else // !_WIN32
int pipe_to_child[2];
int pipe_from_child[2];
if (::pipe(pipe_to_child)) return false;
if (::pipe(pipe_from_child)) {
::close(pipe_to_child[0]);
::close(pipe_to_child[1]);
return false;
}
::pid_t pid = fork();
if (pid < 0) {
Log.error("failed to create process");
return false;
}
if (pid == 0) { // child process
if (::dup2(pipe_to_child[0], STDIN_FILENO) < 0 || ::close(pipe_to_child[1]) < 0 ||
::close(pipe_from_child[0]) < 0 || ::dup2(pipe_from_child[1], STDOUT_FILENO) < 0 ||
::dup2(pipe_from_child[1], STDERR_FILENO) < 0) {
::exit(-1);
}
// set stdin of child to blocking
if (int val = ::fcntl(STDIN_FILENO, F_GETFL); val != -1 && (val & O_NONBLOCK)) {
val &= ~O_NONBLOCK;
::fcntl(STDIN_FILENO, F_SETFL, val);
}
#ifndef __APPLE__
::prctl(PR_SET_PDEATHSIG, SIGTERM);
#endif
::execlp("/bin/sh", "sh", "-c", cmd.c_str(), nullptr);
exit(-1);
}
m_minitouch_process = pid;
m_write_to_minitouch_fd = pipe_to_child[1];
if (::close(pipe_from_child[1]) < 0 || ::close(pipe_to_child[0]) < 0) {
release_minitouch(true);
return false;
}
// set stdout to non blocking
if (int val = ::fcntl(pipe_from_child[0], F_GETFL); val != -1) {
val |= O_NONBLOCK;
::fcntl(pipe_from_child[0], F_SETFL, val);
}
else {
release_minitouch(true);
return false;
}
const auto start_time = std::chrono::steady_clock::now();
while (true) {
if (need_exit()) {
release_minitouch(true);
return false;
}
if (!check_timeout(start_time)) {
Log.info("unable to find $ from pipe_str:", Logger::separator::newline, pipe_str);
release_minitouch(true);
return false;
}
if (pipe_str.find('$') != std::string::npos) {
break;
}
char buf_from_child[PipeReadBuffSize];
ssize_t ret = ::read(pipe_from_child[0], buf_from_child, PipeReadBuffSize);
if (ret <= 0) continue;
pipe_str.insert(pipe_str.end(), buf_from_child, buf_from_child + ret);
}
::dup2(::open("/dev/null", O_WRONLY), pipe_from_child[0]);
#endif // _WIN32
Log.info("pipe str", Logger::separator::newline, pipe_str);
@@ -538,13 +622,19 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd)
}
std::string key_info = pipe_str.substr(s_pos + 1, e_pos - s_pos - 1);
Log.info("minitouch key props", key_info);
int size_1 = 0, size_2 = 0;
std::stringstream ss;
ss << key_info;
ss >> m_minitouch_props.max_contacts;
ss >> m_minitouch_props.max_x;
ss >> m_minitouch_props.max_y;
ss >> size_1;
ss >> size_2;
ss >> m_minitouch_props.max_pressure;
// 有些模拟器在竖屏分辨率时,这里的输出是反过来的
// 考虑到应该没人竖屏玩明日方舟,所以取较大值为 x较小值为 y
m_minitouch_props.max_x = std::max(size_1, size_2);
m_minitouch_props.max_y = std::min(size_1, size_2);
m_minitouch_props.x_scaling = static_cast<double>(m_minitouch_props.max_x) / m_width;
m_minitouch_props.y_scaling = static_cast<double>(m_minitouch_props.max_y) / m_height;
@@ -554,9 +644,15 @@ bool asst::Controller::call_and_hup_minitouch(const std::string& cmd)
bool asst::Controller::input_to_minitouch(const std::string& cmd)
{
// Log.info("Input to minitouch", Logger::separator::newline, cmd);
#ifdef ASST_DEBUG
Log.info("Input to minitouch", Logger::separator::newline, cmd);
#endif
#ifdef _WIN32
if (m_minitouch_parent_write == INVALID_HANDLE_VALUE) {
Log.error("minitouch write handle invalid", m_minitouch_parent_write);
return false;
}
DWORD written = 0;
if (!WriteFile(m_minitouch_parent_write, cmd.c_str(),
static_cast<DWORD>(cmd.size() * sizeof(std::string::value_type)), &written, NULL)) {
@@ -567,6 +663,9 @@ bool asst::Controller::input_to_minitouch(const std::string& cmd)
return cmd.size() == written;
#else
if (m_minitouch_process < 0 || m_write_to_minitouch_fd < 0) return false;
if (::write(m_write_to_minitouch_fd, cmd.c_str(), cmd.length()) >= 0) return true;
Log.error("Failed to write to minitouch, err", errno);
return false;
#endif
}
@@ -582,19 +681,28 @@ void asst::Controller::release_minitouch(bool force)
#ifdef _WIN32
if (m_minitouch_process_info.hProcess) {
if (m_minitouch_process_info.hProcess != INVALID_HANDLE_VALUE) {
CloseHandle(m_minitouch_process_info.hProcess);
m_minitouch_process_info.hProcess = nullptr;
m_minitouch_process_info.hProcess = INVALID_HANDLE_VALUE;
}
if (m_minitouch_process_info.hThread) {
if (m_minitouch_process_info.hThread != INVALID_HANDLE_VALUE) {
CloseHandle(m_minitouch_process_info.hThread);
m_minitouch_process_info.hThread = nullptr;
m_minitouch_process_info.hThread = INVALID_HANDLE_VALUE;
}
if (m_minitouch_parent_write) {
if (m_minitouch_parent_write != INVALID_HANDLE_VALUE) {
CloseHandle(m_minitouch_parent_write);
m_minitouch_parent_write = nullptr;
m_minitouch_parent_write = INVALID_HANDLE_VALUE;
}
#else
if (m_write_to_minitouch_fd != -1) {
::close(m_write_to_minitouch_fd);
m_write_to_minitouch_fd = -1;
}
if (m_minitouch_process > 0) {
::kill(m_minitouch_process, SIGTERM);
if (force) ::kill(m_minitouch_process, SIGKILL);
m_minitouch_process = -1;
}
#endif // _WIN32
}
@@ -750,8 +858,8 @@ std::optional<unsigned short> asst::Controller::init_socket(const std::string& l
socklen_t addrlen = sizeof(m_server_sock_addr);
int getname_ret = ::getsockname(m_server_sock, reinterpret_cast<sockaddr*>(&m_server_sock_addr), &addrlen);
int listen_ret = ::listen(m_server_sock, 3);
struct timeval timeout = {6,0};
int timeout_ret = ::setsockopt(m_server_sock, SOL_SOCKET, SO_RCVTIMEO, (char *)&timeout, sizeof(struct timeval));
struct timeval timeout = { 6, 0 };
int timeout_ret = ::setsockopt(m_server_sock, SOL_SOCKET, SO_RCVTIMEO, (char*)&timeout, sizeof(struct timeval));
server_start = bind_ret == 0 && getname_ret == 0 && listen_ret == 0 && timeout_ret == 0;
#endif
@@ -1186,7 +1294,6 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a
{
m_adb.connect = cmd_replace(adb_cfg.connect);
auto connect_ret = call_command(m_adb.connect, 60LL * 1000, false /* adb 连接时不允许重试 */);
// 端口即使错误命令仍然会返回0TODO 对connect_result进行判断
bool is_connect_success = false;
if (connect_ret) {
auto& connect_str = connect_ret.value();
@@ -1419,7 +1526,8 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a
call_command(minitouch_cmd_rep(adb_cfg.push_minitouch));
call_command(minitouch_cmd_rep(adb_cfg.chmod_minitouch));
call_and_hup_minitouch(minitouch_cmd_rep(adb_cfg.call_minitouch));
m_adb.call_minitouch = minitouch_cmd_rep(adb_cfg.call_minitouch);
call_and_hup_minitouch(m_adb.call_minitouch);
std::string orientation_str = call_command(cmd_replace(adb_cfg.orientation)).value_or("0");
auto [beg, end] = ranges::remove_if(orientation_str, [](char ch) -> bool { return !std::isdigit(ch); });

View File

@@ -4,6 +4,7 @@
#include "Utils/Platform/SafeWindows.h"
#include <mswsock.h>
#else
#include <fcntl.h>
#include <netinet/in.h>
#include <sys/socket.h>
#endif
@@ -13,7 +14,6 @@
#include <atomic>
#include <condition_variable>
#include <filesystem>
#include <format>
#include <memory>
#include <mutex>
#include <optional>
@@ -134,6 +134,7 @@ namespace asst
{
/* command */
std::string connect;
std::string call_minitouch;
std::string click;
std::string swipe;
@@ -168,11 +169,13 @@ namespace asst
bool m_minitouch_avaiable = false; // 状态
#ifdef _WIN32
HANDLE m_minitouch_parent_write = nullptr;
HANDLE m_minitouch_parent_write = INVALID_HANDLE_VALUE;
ASST_AUTO_DEDUCED_ZERO_INIT_START
PROCESS_INFORMATION m_minitouch_process_info = { nullptr };
PROCESS_INFORMATION m_minitouch_process_info = { INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE, 0, 0 };
ASST_AUTO_DEDUCED_ZERO_INIT_END
#else
::pid_t m_minitouch_process = -1;
int m_write_to_minitouch_fd = -1;
// TODO
#endif

View File

@@ -536,8 +536,8 @@ namespace MeoAsstGui
get => _dormThreshold;
set
{
DormThresholdLabel = Localization.GetString("DormThreshold") + ": " + _dormThreshold + "%";
SetAndNotify(ref _dormThreshold, value);
DormThresholdLabel = Localization.GetString("DormThreshold") + ": " + _dormThreshold + "%";
ViewStatusStorage.Set("Infrast.DormThreshold", value.ToString());
}
}