diff --git a/include/AsstCaller.h b/include/AsstCaller.h index 435002cbe4..76900c7ad1 100644 --- a/include/AsstCaller.h +++ b/include/AsstCaller.h @@ -20,7 +20,7 @@ extern "C" #ifdef __cplusplus typedef asst::Assistant* AsstHandle; #else - typedef void* AsstHandle; +typedef void* AsstHandle; #endif typedef int TaskId; typedef void(ASST_CALL* AsstApiCallback)(int msg, const char* detail_json, void* custom_arg); @@ -41,7 +41,7 @@ extern "C" bool ASSTAPI AsstStop(AsstHandle handle); bool ASSTAPI AsstRunning(AsstHandle handle); - bool ASSTAPI AsstCtrlerClick(AsstHandle handle, int x, int y, bool block); + bool ASSTAPI AsstClick(AsstHandle handle, int x, int y); unsigned long long ASSTAPI AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size); unsigned long long ASSTAPI AsstGetUUID(AsstHandle handle, char* buff, unsigned long long buff_size); unsigned long long ASSTAPI AsstGetTasksList(AsstHandle handle, TaskId* buff, unsigned long long buff_size); diff --git a/src/MeoAssistant/Assistant.cpp b/src/MeoAssistant/Assistant.cpp index 016d49a59a..ce52b131b3 100644 --- a/src/MeoAssistant/Assistant.cpp +++ b/src/MeoAssistant/Assistant.cpp @@ -166,15 +166,15 @@ std::vector asst::Assistant::get_image() const if (!inited()) { return {}; } - return m_ctrler->get_image_encode(); + return m_ctrler->get_encoded_image_cache(); } -bool asst::Assistant::ctrler_click(int x, int y, bool block) +bool asst::Assistant::ctrler_click(int x, int y) { if (!inited()) { return false; } - m_ctrler->click(Point(x, y), block); + m_ctrler->click(Point(x, y)); return true; } diff --git a/src/MeoAssistant/Assistant.h b/src/MeoAssistant/Assistant.h index 4c3473c98c..4d9e578e59 100644 --- a/src/MeoAssistant/Assistant.h +++ b/src/MeoAssistant/Assistant.h @@ -45,7 +45,7 @@ namespace asst bool running(); std::vector get_image() const; - bool ctrler_click(int x, int y, bool block = true); + bool ctrler_click(int x, int y); std::string get_uuid() const; std::vector get_tasks_list() const; diff --git a/src/MeoAssistant/AsstCaller.cpp b/src/MeoAssistant/AsstCaller.cpp index 57290c3364..7d58ef6ac9 100644 --- a/src/MeoAssistant/AsstCaller.cpp +++ b/src/MeoAssistant/AsstCaller.cpp @@ -135,12 +135,12 @@ bool AsstSetTaskParams(AsstHandle handle, TaskId id, const char* params) return handle->set_task_params(id, params ? params : ""); } -bool AsstCtrlerClick(AsstHandle handle, int x, int y, bool block) +bool AsstClick(AsstHandle handle, int x, int y) { if (!inited || handle == nullptr) { return false; } - return handle->ctrler_click(x, y, block); + return handle->ctrler_click(x, y); } unsigned long long AsstGetImage(AsstHandle handle, void* buff, unsigned long long buff_size) diff --git a/src/MeoAssistant/Controller.cpp b/src/MeoAssistant/Controller.cpp index de86fb5acf..b072256350 100644 --- a/src/MeoAssistant/Controller.cpp +++ b/src/MeoAssistant/Controller.cpp @@ -48,96 +48,32 @@ asst::Controller::Controller(AsstCallback callback, void* callback_arg) } #else - int pipe_in_ret = pipe(m_pipe_in); - int pipe_out_ret = pipe(m_pipe_out); - fcntl(m_pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); + int pipe_in_ret = ::pipe(m_pipe_in); + int pipe_out_ret = ::pipe(m_pipe_out); + ::fcntl(m_pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); if (pipe_in_ret < 0 || pipe_out_ret < 0) { Log.error(__FUNCTION__, "controller pipe created failed", pipe_in_ret, pipe_out_ret); } m_support_socket = true; #endif - - m_cmd_thread = std::thread(&Controller::pipe_working_proc, this); } asst::Controller::~Controller() { LogTraceFunction; - m_thread_exit = true; - // m_thread_idle = true; - m_cmd_condvar.notify_all(); - m_completed_id = UINT_MAX; // make all WinMacor::wait to exit - - if (m_cmd_thread.joinable()) { - m_cmd_thread.join(); - } - set_inited(false); kill_adb_daemon(); #ifndef _WIN32 - close(m_pipe_in[PIPE_READ]); - close(m_pipe_in[PIPE_WRITE]); - close(m_pipe_out[PIPE_READ]); - close(m_pipe_out[PIPE_WRITE]); + ::close(m_pipe_in[PIPE_READ]); + ::close(m_pipe_in[PIPE_WRITE]); + ::close(m_pipe_out[PIPE_READ]); + ::close(m_pipe_out[PIPE_WRITE]); #endif } -// asst::Rect asst::Controller::shaped_correct(const Rect & rect) const -//{ -// if (rect.empty() -// || m_scale_size.first == 0 -// || m_scale_size.second == 0) { -// return rect; -// } -// // 明日方舟在异形屏上,有的地方是按比例缩放的,有的地方又是直接位移。没法整,这里简单粗暴一点截一个长条 -// Rect dst = rect; -// if (m_scale_size.first != WindowWidthDefault) { // 说明是宽屏 -// if (rect.width <= WindowWidthDefault / 2) { -// if (rect.x + rect.width <= WindowWidthDefault / 2) { // 整个矩形都在左半边 -// dst.x = 0; -// dst.width = m_scale_size.first / 2; -// } -// else if (rect.x >= WindowWidthDefault / 2) { // 整个矩形都在右半边 -// dst.x = m_scale_size.first / 2; -// dst.width = m_scale_size.first / 2; -// } -// else { // 整个矩形横跨了中线 -// dst.x = 0; -// dst.width = m_scale_size.first; -// } -// } -// else { -// dst.x = 0; -// dst.width = m_scale_size.first; -// } -// } -// else if (m_scale_size.second != WindowHeightDefault) { // 说明是偏方形屏 -// if (rect.height <= WindowHeightDefault / 2) { -// if (rect.y + rect.height <= WindowHeightDefault / 2) { // 整个矩形都在上半边 -// dst.y = 0; -// dst.height = m_scale_size.second / 2; -// } -// else if (rect.y >= WindowHeightDefault / 2) { // 整个矩形都在下半边 -// dst.y = m_scale_size.second / 2; -// dst.height = m_scale_size.second / 2; // 整个矩形横跨了中线 -// } -// else { -// dst.y = 0; -// dst.height = m_scale_size.second; -// } -// } -// -// else { -// dst.y = 0; -// dst.height = m_scale_size.second; -// } -// } -// return dst; -// } - std::pair asst::Controller::get_scale_size() const noexcept { return m_scale_size; @@ -148,40 +84,6 @@ bool asst::Controller::need_exit() const return m_exit_flag != nullptr && *m_exit_flag; } -void asst::Controller::pipe_working_proc() -{ - LogTraceFunction; - - while (!m_thread_exit) { - std::unique_lock cmd_queue_lock(m_cmd_queue_mutex); - - if (!m_cmd_queue.empty()) { // 队列中有任务就执行任务 - std::string cmd = m_cmd_queue.front(); - m_cmd_queue.pop(); - cmd_queue_lock.unlock(); - // todo 判断命令是否执行成功 - call_command(cmd); - ++m_completed_id; - } - // else if (!m_thread_idle) { // 队列中没有任务,又不是闲置的时候,就去截图 - // cmd_queue_lock.unlock(); - // auto start_time = std::chrono::steady_clock::now(); - // screencap(); - // cmd_queue_lock.lock(); - // if (!m_cmd_queue.empty()) { - // continue; - // } - // m_cmd_condvar.wait_until( - // cmd_queue_lock, - // start_time + std::chrono::milliseconds(1000)); // todo 时间写到配置文件里 - // } - else { - // m_cmd_condvar.wait(cmd_queue_lock, [&]() -> bool {return !m_thread_idle; }); - m_cmd_condvar.wait(cmd_queue_lock); - } - } -} - std::optional asst::Controller::call_command(const std::string& cmd, int64_t timeout, bool allow_reconnect, bool recv_by_socket) { @@ -247,9 +149,9 @@ std::optional asst::Controller::call_command(const std::string& cmd sockov.hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr); client_socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); DWORD dummy; - if (!m_AcceptEx(m_server_sock, client_socket, sock_buffer.value().get(), - (DWORD)sock_buffer.value().size() - ((sizeof(sockaddr_in) + 16) * 2), sizeof(sockaddr_in) + 16, - sizeof(sockaddr_in) + 16, &dummy, &sockov)) { + if (!m_server_accept_ex(m_server_sock, client_socket, sock_buffer.value().get(), + (DWORD)sock_buffer.value().size() - ((sizeof(sockaddr_in) + 16) * 2), + sizeof(sockaddr_in) + 16, sizeof(sockaddr_in) + 16, &dummy, &sockov)) { err = WSAGetLastError(); if (err == ERROR_IO_PENDING) { accept_pending = true; @@ -258,15 +160,12 @@ std::optional asst::Controller::call_command(const std::string& cmd Log.trace("AcceptEx failed, err:", err); accept_pending = false; socket_eof = true; - closesocket(client_socket); + ::closesocket(client_socket); } } } - while (true) { - if (need_exit()) { - break; - } + while (!need_exit()) { wait_handles.clear(); if (process_running) wait_handles.push_back(process_info.hProcess); if (!pipe_eof) wait_handles.push_back(pipeov.hEvent); @@ -346,7 +245,7 @@ std::optional asst::Controller::call_command(const std::string& cmd if (len == 0) { socket_eof = true; - closesocket(client_socket); + ::closesocket(client_socket); } else { // reset the overlapped since we reuse it for different handle @@ -367,7 +266,7 @@ std::optional asst::Controller::call_command(const std::string& cmd sock_data.insert(sock_data.end(), sock_buffer.value().get(), sock_buffer.value().get() + len); if (len == 0) { socket_eof = true; - closesocket(client_socket); + ::closesocket(client_socket); } else { (void)ReadFile(reinterpret_cast(client_socket), sock_buffer.value().get(), @@ -377,7 +276,7 @@ std::optional asst::Controller::call_command(const std::string& cmd else { // err = GetLastError(); socket_eof = true; - closesocket(client_socket); + ::closesocket(client_socket); } } } @@ -400,13 +299,13 @@ std::optional asst::Controller::call_command(const std::string& cmd }; int exit_ret = 0; - m_child = fork(); + m_child = ::fork(); if (m_child == 0) { // child process - dup2(m_pipe_in[PIPE_READ], STDIN_FILENO); - dup2(m_pipe_out[PIPE_WRITE], STDOUT_FILENO); - dup2(m_pipe_out[PIPE_WRITE], STDERR_FILENO); + ::dup2(m_pipe_in[PIPE_READ], STDIN_FILENO); + ::dup2(m_pipe_out[PIPE_WRITE], STDOUT_FILENO); + ::dup2(m_pipe_out[PIPE_WRITE], STDERR_FILENO); // all these are for use by parent only // close(m_pipe_in[PIPE_READ]); @@ -415,7 +314,7 @@ std::optional asst::Controller::call_command(const std::string& cmd // close(m_pipe_out[PIPE_WRITE]); exit_ret = execlp("sh", "sh", "-c", cmd.c_str(), nullptr); - exit(exit_ret); + ::exit(exit_ret); } else if (m_child > 0) { // parent process @@ -446,7 +345,7 @@ std::optional asst::Controller::call_command(const std::string& cmd while (read_num > 0) { pipe_data.insert(pipe_data.end(), pipe_buffer.get(), pipe_buffer.get() + read_num); - read_num = read(m_pipe_out[PIPE_READ], pipe_buffer.get(), pipe_buffer.size()); + read_num = ::read(m_pipe_out[PIPE_READ], pipe_buffer.get(), pipe_buffer.size()); } } while (::waitpid(m_child, &exit_ret, WNOHANG) == 0 && !check_timeout()); } @@ -628,22 +527,12 @@ void asst::Controller::clear_info() noexcept m_scale_size = { WindowWidthDefault, WindowHeightDefault }; } -int asst::Controller::push_cmd(const std::string& cmd) -{ - random_delay(); - - std::unique_lock lock(m_cmd_queue_mutex); - m_cmd_queue.emplace(cmd); - m_cmd_condvar.notify_one(); - return static_cast(++m_push_id); -} - -void asst::Controller::try_to_close_socket() noexcept +void asst::Controller::close_socket(SOCKET& sock) noexcept { #ifdef _WIN32 - if (m_server_sock != INVALID_SOCKET) { - ::closesocket(m_server_sock); - m_server_sock = INVALID_SOCKET; + if (sock != INVALID_SOCKET) { + ::closesocket(sock); + sock = INVALID_SOCKET; } #else if (m_server_sock >= 0) { @@ -654,7 +543,7 @@ void asst::Controller::try_to_close_socket() noexcept m_server_started = false; } -std::optional asst::Controller::try_to_init_socket(const std::string& local_address) +std::optional asst::Controller::init_socket(const std::string& local_address) { LogTraceFunction; @@ -666,18 +555,18 @@ std::optional asst::Controller::try_to_init_socket(const std::st } } - DWORD dummy; - GUID GuidAcceptEx = WSAID_ACCEPTEX; - auto err = WSAIoctl(m_server_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &GuidAcceptEx, sizeof(GuidAcceptEx), - &m_AcceptEx, sizeof(m_AcceptEx), &dummy, NULL, NULL); + DWORD dummy = 0; + GUID guid_accept_ex = WSAID_ACCEPTEX; + int err = WSAIoctl(m_server_sock, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid_accept_ex, sizeof(guid_accept_ex), + &m_server_accept_ex, sizeof(m_server_accept_ex), &dummy, NULL, NULL); if (err == SOCKET_ERROR) { err = WSAGetLastError(); Log.error("failed to resolve AcceptEx, err:", err); - closesocket(m_server_sock); + ::closesocket(m_server_sock); return std::nullopt; } - m_server_addr.sin_family = PF_INET; - inet_pton(AF_INET, local_address.c_str(), &m_server_addr.sin_addr); + m_server_sock_addr.sin_family = PF_INET; + ::inet_pton(AF_INET, local_address.c_str(), &m_server_sock_addr.sin_addr); #else m_server_sock = socket(AF_INET, SOCK_STREAM, 0); if (m_server_sock < 0) { @@ -692,10 +581,10 @@ std::optional asst::Controller::try_to_init_socket(const std::st uint16_t port_result = 0; #ifdef _WIN32 - m_server_addr.sin_port = htons(0); - int bind_ret = ::bind(m_server_sock, reinterpret_cast(&m_server_addr), sizeof(SOCKADDR)); - int addrlen = sizeof(m_server_addr); - int getname_ret = getsockname(m_server_sock, reinterpret_cast(&m_server_addr), &addrlen); + m_server_sock_addr.sin_port = ::htons(0); + int bind_ret = ::bind(m_server_sock, reinterpret_cast(&m_server_sock_addr), sizeof(SOCKADDR)); + int addrlen = sizeof(m_server_sock_addr); + int getname_ret = ::getsockname(m_server_sock, reinterpret_cast(&m_server_sock_addr), &addrlen); int listen_ret = ::listen(m_server_sock, 3); server_start = bind_ret == 0 && getname_ret == 0 && listen_ret == 0; #else @@ -708,34 +597,18 @@ std::optional asst::Controller::try_to_init_socket(const std::st #endif if (!server_start) { - Log.info("not supports netcat"); + Log.info("not supports socket"); return std::nullopt; } port_result = ntohs(m_server_addr.sin_port); - Log.info("server_start", local_address, port_result); + Log.info("command server start", local_address, port_result); return port_result; } -void asst::Controller::wait(unsigned id) const noexcept -{ - using namespace std::chrono_literals; - static constexpr auto delay = 10ms; - while (id > m_completed_id) { - std::this_thread::sleep_for(delay); - } -} - bool asst::Controller::screencap(bool allow_reconnect) { - // if (true) { - // m_inited = true; - // std::unique_lock image_lock(m_image_mutex); - // m_cache_image = cv::imread("err/1.png"); - // return true; - // } - DecodeFunc decode_raw = [&](std::string_view data) -> bool { if (data.empty()) { return false; @@ -907,7 +780,7 @@ void asst::Controller::clear_lf_info() m_adb.screencap_end_of_line = AdbProperty::ScreencapEndOfLine::UnknownYet; } -cv::Mat asst::Controller::get_resized_image() const +cv::Mat asst::Controller::get_resized_image_cache() const { const static cv::Size d_size(m_scale_size.first, m_scale_size.second); @@ -921,67 +794,55 @@ cv::Mat asst::Controller::get_resized_image() const return resized_mat; } -std::optional asst::Controller::start_game(const std::string& client_type, bool block) +bool asst::Controller::start_game(const std::string& client_type) { if (client_type.empty()) { - return std::nullopt; + return false; } - if (auto intent_name = Configer.get_intent_name(client_type)) { - std::string cur_cmd = utils::string_replace_all(m_adb.start, "[Intent]", intent_name.value()); - int id = push_cmd(cur_cmd); - if (block) { - wait(id); - } - return id; + auto intent_name = Configer.get_intent_name(client_type); + if (!intent_name) { + return false; } - return std::nullopt; + std::string cur_cmd = utils::string_replace_all(m_adb.start, "[Intent]", intent_name.value()); + return call_command(cur_cmd).has_value(); } -std::optional asst::Controller::stop_game(bool block) +bool asst::Controller::stop_game() { - std::string cur_cmd = m_adb.stop; - int id = push_cmd(cur_cmd); - if (block) { - wait(id); - } - return id; + return call_command(m_adb.stop).has_value(); } -int asst::Controller::click(const Point& p, bool block) +bool asst::Controller::click(const Point& p) { int x = static_cast(p.x * m_control_scale); int y = static_cast(p.y * m_control_scale); // log.trace("Click, raw:", p.x, p.y, "corr:", x, y); - return click_without_scale(Point(x, y), block); + return click_without_scale(Point(x, y)); } -int asst::Controller::click(const Rect& rect, bool block) +bool asst::Controller::click(const Rect& rect) { - return click(rand_point_in_rect(rect), block); + return click(rand_point_in_rect(rect)); } -int asst::Controller::click_without_scale(const Point& p, bool block) +bool asst::Controller::click_without_scale(const Point& p) { if (p.x < 0 || p.x >= m_width || p.y < 0 || p.y >= m_height) { Log.error("click point out of range"); } std::string cur_cmd = utils::string_replace_all(m_adb.click, { { "[x]", std::to_string(p.x) }, { "[y]", std::to_string(p.y) } }); - int id = push_cmd(cur_cmd); - if (block) { - wait(id); - } - return id; + + return call_command(cur_cmd).has_value(); } -int asst::Controller::click_without_scale(const Rect& rect, bool block) +bool asst::Controller::click_without_scale(const Rect& rect) { - return click_without_scale(rand_point_in_rect(rect), block); + return click_without_scale(rand_point_in_rect(rect)); } -int asst::Controller::swipe(const Point& p1, const Point& p2, int duration, bool block, int extra_delay, - bool extra_swipe) +bool asst::Controller::swipe(const Point& p1, const Point& p2, int duration, bool extra_swipe) { int x1 = static_cast(p1.x * m_control_scale); int y1 = static_cast(p1.y * m_control_scale); @@ -989,16 +850,15 @@ int asst::Controller::swipe(const Point& p1, const Point& p2, int duration, bool int y2 = static_cast(p2.y * m_control_scale); // log.trace("Swipe, raw:", p1.x, p1.y, p2.x, p2.y, "corr:", x1, y1, x2, y2); - return swipe_without_scale(Point(x1, y1), Point(x2, y2), duration, block, extra_delay, extra_swipe); + return swipe_without_scale(Point(x1, y1), Point(x2, y2), duration, extra_swipe); } -int asst::Controller::swipe(const Rect& r1, const Rect& r2, int duration, bool block, int extra_delay, bool extra_swipe) +bool asst::Controller::swipe(const Rect& r1, const Rect& r2, int duration, bool extra_swipe) { - return swipe(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, extra_swipe); + return swipe(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, extra_swipe); } -int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int duration, bool block, int extra_delay, - bool extra_swipe) +bool asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int duration, bool extra_swipe) { int x1 = p1.x, y1 = p1.y; int x2 = p2.x, y2 = p2.y; @@ -1018,8 +878,8 @@ int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int { "[y2]", std::to_string(y2) }, { "[duration]", duration <= 0 ? "" : std::to_string(duration) }, }); + bool ret = call_command(cur_cmd).has_value(); - int id = 0; // 额外的滑动:adb有bug,同样的参数,偶尔会划得非常远。额外做一个短程滑动,把之前的停下来 const auto& opt = Configer.get_options(); if (extra_swipe && opt.adb_extra_swipe_duration > 0) { @@ -1031,25 +891,14 @@ int asst::Controller::swipe_without_scale(const Point& p1, const Point& p2, int { "[y2]", std::to_string(y2 - opt.adb_extra_swipe_dist /* * m_control_scale*/) }, { "[duration]", std::to_string(opt.adb_extra_swipe_duration) }, }); - push_cmd(cur_cmd); - id = push_cmd(extra_cmd); + ret &= call_command(extra_cmd).has_value(); } - else { - id = push_cmd(cur_cmd); - } - - if (block) { - wait(id); - std::this_thread::sleep_for(std::chrono::milliseconds(extra_delay)); - } - return id; + return ret; } -int asst::Controller::swipe_without_scale(const Rect& r1, const Rect& r2, int duration, bool block, int extra_delay, - bool extra_swipe) +bool asst::Controller::swipe_without_scale(const Rect& r1, const Rect& r2, int duration, bool extra_swipe) { - return swipe_without_scale(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, block, extra_delay, - extra_swipe); + return swipe_without_scale(rand_point_in_rect(r1), rand_point_in_rect(r2), duration, extra_swipe); } bool asst::Controller::connect(const std::string& adb_path, const std::string& address, const std::string& config) @@ -1292,22 +1141,17 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a bind_address = "127.0.0.1"; } - // Todo: detect remote address, and check remote port // reference from // https://github.com/ArknightsAutoHelper/ArknightsAutoHelper/blob/master/automator/connector/ADBConnector.py#L436 auto nc_address_ret = call_command(cmd_replace(adb_cfg.nc_address)); - if (nc_address_ret) { + if (nc_address_ret && !m_server_started) { auto& nc_result_str = nc_address_ret.value(); if (auto pos = nc_result_str.find(' '); pos != std::string::npos) { nc_address = nc_result_str.substr(0, pos); } } - if (need_exit()) { - return false; - } - - auto socket_opt = try_to_init_socket(bind_address); + auto socket_opt = init_socket(bind_address); if (socket_opt) { nc_port = socket_opt.value(); m_adb.screencap_raw_by_nc = cmd_replace(adb_cfg.screencap_raw_by_nc); @@ -1318,6 +1162,10 @@ bool asst::Controller::connect(const std::string& adb_path, const std::string& a } } + if (need_exit()) { + return false; + } + // try to find the fastest way if (!screencap()) { Log.error("Cannot find a proper way to screencap!"); @@ -1364,7 +1212,8 @@ void asst::Controller::kill_adb_daemon() bool asst::Controller::release() { - try_to_close_socket(); + close_socket(m_server_sock); + m_server_started = false; #ifndef _WIN32 if (m_child) @@ -1439,14 +1288,14 @@ cv::Mat asst::Controller::get_image(bool raw) return copy; } - return get_resized_image(); + return get_resized_image_cache(); } -std::vector asst::Controller::get_image_encode() const +std::vector asst::Controller::get_encoded_image_cache() const { - cv::Mat img = get_resized_image(); + cv::Mat img = get_resized_image_cache(); std::vector buf; cv::imencode(".png", img, buf); return buf; -} +} \ No newline at end of file diff --git a/src/MeoAssistant/Controller.h b/src/MeoAssistant/Controller.h index eab152986a..f1d0b5a4e6 100644 --- a/src/MeoAssistant/Controller.h +++ b/src/MeoAssistant/Controller.h @@ -43,32 +43,21 @@ namespace asst const std::string& get_uuid() const; cv::Mat get_image(bool raw = false); - std::vector get_image_encode() const; + std::vector get_encoded_image_cache() const; - /* 开启游戏、点击和滑动都是异步执行,返回该任务的id */ + bool start_game(const std::string& client_type); + bool stop_game(); - std::optional start_game(const std::string& client_type, bool block = true); - std::optional stop_game(bool block = true); + bool click(const Point& p); + bool click(const Rect& rect); + bool click_without_scale(const Point& p); + bool click_without_scale(const Rect& rect); - int click(const Point& p, bool block = true); - int click(const Rect& rect, bool block = true); - int click_without_scale(const Point& p, bool block = true); - int click_without_scale(const Rect& rect, bool block = true); + bool swipe(const Point& p1, const Point& p2, int duration = 0, bool extra_swipe = false); + bool swipe(const Rect& r1, const Rect& r2, int duration = 0, bool extra_swipe = false); + bool swipe_without_scale(const Point& p1, const Point& p2, int duration = 0, bool extra_swipe = false); + bool swipe_without_scale(const Rect& r1, const Rect& r2, int duration = 0, bool extra_swipe = false); - static constexpr int SwipeExtraDelayDefault = 1000; - int swipe(const Point& p1, const Point& p2, int duration = 0, bool block = true, - int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, - int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe_without_scale(const Point& p1, const Point& p2, int duration = 0, bool block = true, - int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - int swipe_without_scale(const Rect& r1, const Rect& r2, int duration = 0, bool block = true, - int extra_delay = SwipeExtraDelayDefault, bool extra_swipe = false); - - void wait(unsigned id) const noexcept; - - // 异形屏矫正 - // Rect shaped_correct(const Rect& rect) const; std::pair get_scale_size() const noexcept; Controller& operator=(const Controller&) = delete; @@ -76,23 +65,21 @@ namespace asst private: bool need_exit() const; - void pipe_working_proc(); std::optional call_command(const std::string& cmd, int64_t timeout = 20000, bool allow_reconnect = true, bool recv_by_socket = false); - int push_cmd(const std::string& cmd); bool release(); void kill_adb_daemon(); bool set_inited(bool inited); - void try_to_close_socket() noexcept; - std::optional try_to_init_socket(const std::string& local_address); + void close_socket(SOCKET& sock) noexcept; + std::optional init_socket(const std::string& local_address); using DecodeFunc = std::function; bool screencap(bool allow_reconnect = false); bool screencap(const std::string& cmd, const DecodeFunc& decode_func, bool allow_reconnect = false, bool by_socket = false); void clear_lf_info(); - cv::Mat get_resized_image() const; + cv::Mat get_resized_image_cache() const; Point rand_point_in_rect(const Rect& rect); @@ -111,13 +98,14 @@ namespace asst std::minstd_rand m_rand_engine; std::mutex m_callcmd_mutex; + #ifdef _WIN32 ASST_AUTO_DEDUCED_ZERO_INIT_START WSADATA m_wsa_data {}; SOCKET m_server_sock = INVALID_SOCKET; - sockaddr_in m_server_addr {}; - LPFN_ACCEPTEX m_AcceptEx = nullptr; + sockaddr_in m_server_sock_addr {}; + LPFN_ACCEPTEX m_server_accept_ex = nullptr; ASST_AUTO_DEDUCED_ZERO_INIT_END #else @@ -180,15 +168,6 @@ namespace asst mutable std::shared_mutex m_image_mutex; cv::Mat m_cache_image; - bool m_thread_exit = false; - // bool m_thread_idle = true; - std::mutex m_cmd_queue_mutex; - std::condition_variable m_cmd_condvar; - std::queue m_cmd_queue; - std::atomic m_completed_id = 0; - unsigned m_push_id = 0; // push_id的自增总是伴随着queue的push,肯定是要上锁的,所以没必要原子 - std::thread m_cmd_thread; - private: #ifdef _WIN32 // for Windows socket diff --git a/src/MeoAssistant/Task/Plugin/RoguelikeBattleTaskPlugin.cpp b/src/MeoAssistant/Task/Plugin/RoguelikeBattleTaskPlugin.cpp index 86e1e79924..5481eccfac 100644 --- a/src/MeoAssistant/Task/Plugin/RoguelikeBattleTaskPlugin.cpp +++ b/src/MeoAssistant/Task/Plugin/RoguelikeBattleTaskPlugin.cpp @@ -719,15 +719,16 @@ bool asst::RoguelikeBattleTaskPlugin::auto_battle() placed_point, { opt_oper.rect.x + opt_oper.rect.width / 2, opt_oper.rect.y + opt_oper.rect.height / 2 })); // 1000 是随便取的一个系数,把整数的 pre_delay 转成小数用的 int duration = static_cast(swipe_oper_task_ptr->pre_delay / 800.0 * dist * log10(dist)); - m_ctrler->swipe(opt_oper.rect, placed_rect, duration, true, 0); + m_ctrler->swipe(opt_oper.rect, placed_rect, duration); sleep(use_oper_task_ptr->post_delay); // 将方向转换为实际的 swipe end 坐标点 if (direction != Point::zero()) { constexpr int coeff = 500; Point end_point = placed_point + (direction * coeff); - m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->post_delay, true, 100); + m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->post_delay); } + sleep(Task.get("BattleUseOper")->post_delay); if (opt_oper.role == BattleRole::Drone) { cancel_oper_selection(); diff --git a/src/MeoAssistant/Task/Plugin/StartGameTaskPlugin.cpp b/src/MeoAssistant/Task/Plugin/StartGameTaskPlugin.cpp index df84d47381..6584bc5d5e 100644 --- a/src/MeoAssistant/Task/Plugin/StartGameTaskPlugin.cpp +++ b/src/MeoAssistant/Task/Plugin/StartGameTaskPlugin.cpp @@ -9,7 +9,7 @@ bool StartGameTaskPlugin::_run() if (m_client_type.empty()) { return false; } - return m_ctrler->start_game(m_client_type).has_value(); + return m_ctrler->start_game(m_client_type); } StartGameTaskPlugin& StartGameTaskPlugin::set_client_type(std::string client_type) noexcept diff --git a/src/MeoAssistant/Task/Plugin/StopGameTaskPlugin.cpp b/src/MeoAssistant/Task/Plugin/StopGameTaskPlugin.cpp index bf5c198c01..7bcf408c38 100644 --- a/src/MeoAssistant/Task/Plugin/StopGameTaskPlugin.cpp +++ b/src/MeoAssistant/Task/Plugin/StopGameTaskPlugin.cpp @@ -6,5 +6,5 @@ using namespace asst; bool StopGameTaskPlugin::_run() { - return m_ctrler->stop_game().has_value(); + return m_ctrler->stop_game(); } diff --git a/src/MeoAssistant/Task/Sub/BattleProcessTask.cpp b/src/MeoAssistant/Task/Sub/BattleProcessTask.cpp index cf36a153e1..0124a9ca15 100644 --- a/src/MeoAssistant/Task/Sub/BattleProcessTask.cpp +++ b/src/MeoAssistant/Task/Sub/BattleProcessTask.cpp @@ -520,7 +520,7 @@ bool asst::BattleProcessTask::oper_deploy(const BattleAction& action) Point::distance(placed_point, { oper_rect.x + oper_rect.width / 2, oper_rect.y + oper_rect.height / 2 })); // 1000 是随便取的一个系数,把整数的 pre_delay 转成小数用的 int duration = static_cast(swipe_oper_task_ptr->pre_delay / 1000.0 * dist * log10(dist)); - m_ctrler->swipe(oper_rect, placed_rect, duration, true, 0); + m_ctrler->swipe(oper_rect, placed_rect, duration); sleep(use_oper_task_ptr->post_delay); @@ -539,7 +539,8 @@ bool asst::BattleProcessTask::oper_deploy(const BattleAction& action) constexpr int coeff = 500; Point end_point = placed_point + (direction * coeff); - m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->post_delay, true, 100); + m_ctrler->swipe(placed_point, end_point, swipe_oper_task_ptr->post_delay); + sleep(Task.get("BattleUseOper")->post_delay); } m_used_opers[iter->first] = @@ -910,4 +911,4 @@ std::optional> asst::BattleProce } return return_value; -} \ No newline at end of file +} diff --git a/src/MeoAssistant/Task/Sub/ProcessTask.cpp b/src/MeoAssistant/Task/Sub/ProcessTask.cpp index e335720614..19416e9ed1 100644 --- a/src/MeoAssistant/Task/Sub/ProcessTask.cpp +++ b/src/MeoAssistant/Task/Sub/ProcessTask.cpp @@ -307,5 +307,5 @@ void ProcessTask::exec_click_task(const Rect& matched_rect) void asst::ProcessTask::exec_swipe_task(const Rect& r1, const Rect& r2, int duration, bool extra_swipe) { - m_ctrler->swipe(r1, r2, duration, true, 0, extra_swipe); + m_ctrler->swipe(r1, r2, duration, extra_swipe); } diff --git a/src/MeoAssistant/Task/Sub/ReportDataTask.cpp b/src/MeoAssistant/Task/Sub/ReportDataTask.cpp index db39d40c83..68720da008 100644 --- a/src/MeoAssistant/Task/Sub/ReportDataTask.cpp +++ b/src/MeoAssistant/Task/Sub/ReportDataTask.cpp @@ -196,7 +196,7 @@ asst::http::Response asst::ReportDataTask::escape_and_request(const std::string& utils::string_replace_all(format, { { "[body]", body_escape }, { "[extra]", m_extra_param } }); Log.info("request:\n" + cmd_line); - std::string response = utils::callcmd(cmd_line); + std::string response = utils::call_command(cmd_line); Log.info("response:\n" + response); // Log.info("response:\n" + utils::string_replace_all(response, { diff --git a/src/MeoAssistant/Utils/Platform.hpp b/src/MeoAssistant/Utils/Platform.hpp index a6af922693..1a21a6f4f3 100644 --- a/src/MeoAssistant/Utils/Platform.hpp +++ b/src/MeoAssistant/Utils/Platform.hpp @@ -19,7 +19,7 @@ namespace asst::utils using platform::path_to_utf8_string; using platform::to_osstring; - using platform::callcmd; + using platform::call_command; namespace path_literals { @@ -29,5 +29,4 @@ namespace asst::utils return asst::utils::path(std::string(std::string_view(utf8_str, len))); } } - -} // namespace asst::utils +} // namespace asst::utils \ No newline at end of file diff --git a/src/MeoAssistant/Utils/Platform/AsstPlatform.h b/src/MeoAssistant/Utils/Platform/AsstPlatform.h index c3695d8d62..06e3702619 100644 --- a/src/MeoAssistant/Utils/Platform/AsstPlatform.h +++ b/src/MeoAssistant/Utils/Platform/AsstPlatform.h @@ -9,7 +9,7 @@ namespace asst::platform { - std::string callcmd(const std::string&); + std::string call_command(const std::string& cmdline, bool* exit_flag = nullptr); using os_string = std::filesystem::path::string_type; diff --git a/src/MeoAssistant/Utils/Platform/AsstPlatformPosix.cpp b/src/MeoAssistant/Utils/Platform/AsstPlatformPosix.cpp index cdfd1c2da2..d2ccef77e8 100644 --- a/src/MeoAssistant/Utils/Platform/AsstPlatformPosix.cpp +++ b/src/MeoAssistant/Utils/Platform/AsstPlatformPosix.cpp @@ -21,10 +21,10 @@ void* asst::platform::aligned_alloc(size_t len, size_t align) void asst::platform::aligned_free(void* ptr) { - free(ptr); + ::free(ptr); } -std::string asst::platform::callcmd(const std::string& cmdline) +std::string asst::platform::call_command(const std::string& cmdline, bool* exit_flag) { constexpr int PipeBuffSize = 4096; std::string pipe_str; @@ -39,49 +39,49 @@ std::string asst::platform::callcmd(const std::string& cmdline) if (pipe_in_ret != 0 || pipe_out_ret != 0) { return {}; } - fcntl(pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); + ::fcntl(pipe_out[PIPE_READ], F_SETFL, O_NONBLOCK); int exit_ret = 0; - int child = fork(); + int child = ::fork(); if (child == 0) { // child process - dup2(pipe_in[PIPE_READ], STDIN_FILENO); - dup2(pipe_out[PIPE_WRITE], STDOUT_FILENO); - dup2(pipe_out[PIPE_WRITE], STDERR_FILENO); + ::dup2(pipe_in[PIPE_READ], STDIN_FILENO); + ::dup2(pipe_out[PIPE_WRITE], STDOUT_FILENO); + ::dup2(pipe_out[PIPE_WRITE], STDERR_FILENO); // all these are for use by parent only - close(pipe_in[PIPE_READ]); - close(pipe_in[PIPE_WRITE]); - close(pipe_out[PIPE_READ]); - close(pipe_out[PIPE_WRITE]); + ::close(pipe_in[PIPE_READ]); + ::close(pipe_in[PIPE_WRITE]); + ::close(pipe_out[PIPE_READ]); + ::close(pipe_out[PIPE_WRITE]); exit_ret = execlp("sh", "sh", "-c", cmdline.c_str(), nullptr); - exit(exit_ret); + ::exit(exit_ret); } else if (child > 0) { // parent process // close unused file descriptors, these are for child only - close(pipe_in[PIPE_READ]); - close(pipe_out[PIPE_WRITE]); + ::close(pipe_in[PIPE_READ]); + ::close(pipe_out[PIPE_WRITE]); do { - ssize_t read_num = read(pipe_out[PIPE_READ], pipe_buffer.get(), PipeBuffSize); + ssize_t read_num = ::read(pipe_out[PIPE_READ], pipe_buffer.get(), PipeBuffSize); while (read_num > 0) { pipe_str.append(pipe_buffer.get(), pipe_buffer.get() + read_num); - read_num = read(pipe_out[PIPE_READ], pipe_buffer.get(), PipeBuffSize); + read_num = ::read(pipe_out[PIPE_READ], pipe_buffer.get(), PipeBuffSize); }; - } while (::waitpid(child, &exit_ret, WNOHANG) == 0); + } while (::waitpid(child, &exit_ret, WNOHANG) == 0 && !(exit_flag && *exit_flag)); - close(pipe_in[PIPE_WRITE]); - close(pipe_out[PIPE_READ]); + ::close(pipe_in[PIPE_WRITE]); + ::close(pipe_out[PIPE_READ]); } else { // failed to create child process - close(pipe_in[PIPE_READ]); - close(pipe_in[PIPE_WRITE]); - close(pipe_out[PIPE_READ]); - close(pipe_out[PIPE_WRITE]); + ::close(pipe_in[PIPE_READ]); + ::close(pipe_in[PIPE_WRITE]); + ::close(pipe_out[PIPE_READ]); + ::close(pipe_out[PIPE_WRITE]); } return pipe_str; } diff --git a/src/MeoAssistant/Utils/Platform/AsstPlatformWin32.cpp b/src/MeoAssistant/Utils/Platform/AsstPlatformWin32.cpp index f8af1a6f53..5ba9a351d3 100644 --- a/src/MeoAssistant/Utils/Platform/AsstPlatformWin32.cpp +++ b/src/MeoAssistant/Utils/Platform/AsstPlatformWin32.cpp @@ -120,7 +120,7 @@ std::string asst::platform::from_osstring(const os_string& os_str) return result; } -std::string asst::platform::callcmd(const std::string& cmdline) +std::string asst::platform::call_command(const std::string& cmdline, bool* exit_flag) { constexpr int PipeBuffSize = 4096; auto pipe_buffer = std::make_unique(PipeBuffSize); @@ -164,7 +164,7 @@ std::string asst::platform::callcmd(const std::string& cmdline) OVERLAPPED pipeov { .hEvent = CreateEventW(nullptr, TRUE, FALSE, nullptr) }; (void)ReadFile(pipe_parent_read, pipe_buffer.get(), PipeBuffSize, nullptr, &pipeov); - while (true) { + while (!(exit_flag && *exit_flag)) { wait_handles.clear(); if (process_running) wait_handles.push_back(process_info.hProcess); if (!pipe_eof) wait_handles.push_back(pipeov.hEvent);