style: 删除界面上关于自动编队特别关注的提示

This commit is contained in:
MistEO
2022-08-20 02:42:33 +08:00
parent b36fdbde1c
commit 69dc78ea2b
4 changed files with 1778 additions and 8 deletions

View File

@@ -0,0 +1,180 @@
#pragma once
#include "AsstConf.h"
#include <optional>
#include <random>
#include <string>
#include <condition_variable>
#include <memory>
#include <mutex>
#include <queue>
#include <shared_mutex>
#include <thread>
#include <atomic>
#ifdef _WIN32
#include <Windows.h>
#endif
#include "NoWarningCVMat.h"
#include "AsstTypes.h"
#include "AsstMsg.h"
namespace asst
{
class Controller
{
public:
Controller(AsstCallback callback, void* callback_arg);
Controller(const Controller&) = delete;
Controller(Controller&&) = delete;
~Controller();
bool connect(const std::string& adb_path, const std::string& address, const std::string& config);
bool release();
bool inited() const noexcept;
const std::string& get_uuid() const;
cv::Mat get_image(bool raw = false);
std::vector<uchar> get_image_encode() const;
/* 开启游戏、点击和滑动都是异步执行返回该任务的id */
std::optional<int> start_game(const std::string& client_type, bool block = true);
std::optional<int> stop_game(bool block = true);
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);
constexpr static 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<int, int> get_scale_size() const noexcept;
Controller& operator=(const Controller&) = delete;
Controller& operator=(Controller&&) = delete;
private:
void pipe_working_proc();
std::optional<std::vector<uchar>> call_command(const std::string& cmd, int64_t timeout = 20000, bool recv_by_socket = false);
int push_cmd(const std::string& cmd);
std::optional<unsigned short> try_to_init_socket(const std::string& local_address, unsigned short try_port, unsigned short try_times = 10U);
using DecodeFunc = std::function<bool(std::vector<uchar>&)>;
bool screencap();
bool screencap(const std::string& cmd, const DecodeFunc& decode_func, bool by_nc = false);
void clear_lf_info();
cv::Mat get_resized_image() const;
Point rand_point_in_rect(const Rect& rect);
void random_delay() const;
void clear_info() noexcept;
// 转换data中所有的crlf为lf有些模拟器自带的adbexec-out输出的\n会被替换成\r\n导致解码错误所以这里转一下回来点名批评mumu
static void convert_lf(std::vector<uchar>& data);
AsstCallback m_callback;
void* m_callback_arg = nullptr;
std::minstd_rand m_rand_engine;
constexpr static int PipeBuffSize = 4 * 1024 * 1024; // 管道缓冲区大小
constexpr static int SocketBuffSize = 4 * 1024 * 1024; // socket 缓冲区大小
std::unique_ptr<uchar[]> m_pipe_buffer = nullptr;
std::mutex m_pipe_mutex;
std::unique_ptr<char[]> m_socket_buffer = nullptr;
std::mutex m_socket_mutex;
#ifdef _WIN32
HANDLE m_pipe_read = nullptr; // 读管道句柄
HANDLE m_pipe_write = nullptr; // 写管道句柄
HANDLE m_pipe_child_read = nullptr; // 子进程的读管道句柄
HANDLE m_pipe_child_write = nullptr; // 子进程的写管道句柄
ASST_AUTO_DEDUCED_ZERO_INIT_START
SECURITY_ATTRIBUTES m_pipe_sec_attr = { 0 }; // 管道安全描述符
STARTUPINFOA m_child_startup_info = { 0 }; // 子进程启动信息
WSADATA m_wsa_data = { 0 };
SOCKET m_server_sock = 0ULL;
sockaddr_in m_server_addr = { 0 };
ASST_AUTO_DEDUCED_ZERO_INIT_END
#else
constexpr static int PIPE_READ = 0;
constexpr static int PIPE_WRITE = 1;
int m_pipe_in[2] = { 0 };
int m_pipe_out[2] = { 0 };
int m_child = 0;
#endif
struct AdbProperty
{
/* command */
std::string connect;
std::string click;
std::string swipe;
std::string screencap_raw_by_nc;
std::string screencap_raw_with_gzip;
std::string screencap_encode;
std::string release;
std::string start;
std::string stop;
/* properties */
enum class ScreencapEndOfLine
{
UnknownYet,
CRLF,
LF,
CR
} screencap_end_of_line = ScreencapEndOfLine::UnknownYet;
enum class ScreencapMethod
{
UnknownYet,
//Default,
RawByNc,
RawWithGzip,
Encode
} screencap_method = ScreencapMethod::UnknownYet;
} m_adb;
std::string m_uuid;
std::pair<int, int> m_scale_size = { WindowWidthDefault, WindowHeightDefault };
double m_control_scale = 1.0;
int m_width = 0;
int m_height = 0;
bool m_support_socket = false;
bool m_server_started = false;
bool m_inited = false;
inline static int m_instance_count = 0;
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<std::string> m_cmd_queue;
std::atomic<unsigned> m_completed_id = 0;
unsigned m_push_id = 0; // push_id的自增总是伴随着queue的push肯定是要上锁的所以没必要原子
std::thread m_cmd_thread;
};
}

View File

@@ -0,0 +1,343 @@
#include "Assistant.h"
#include "AsstRanges.hpp"
#include <meojson/json.hpp>
#include "AsstUtils.hpp"
#include "Controller.h"
#include "Logger.hpp"
#include "Resource.h"
#include "RuntimeStatus.h"
#include "FightTask.h"
#include "StartUpTask.h"
#include "CloseDownTask.h"
#include "AwardTask.h"
#include "VisitTask.h"
#include "MallTask.h"
#include "InfrastTask.h"
#include "RecruitTask.h"
#include "RoguelikeTask.h"
#include "CopilotTask.h"
#include "DepotTask.h"
#ifdef ASST_DEBUG
#include "DebugTask.h"
#endif
using namespace asst;
Assistant::Assistant(AsstApiCallback callback, void* callback_arg)
: m_callback(callback),
m_callback_arg(callback_arg)
{
LogTraceFunction;
m_status = std::make_shared<RuntimeStatus>();
m_ctrler = std::make_shared<Controller>(task_callback, static_cast<void*>(this));
m_working_thread = std::thread(&Assistant::working_proc, this);
m_msg_thread = std::thread(&Assistant::msg_proc, this);
}
Assistant::~Assistant()
{
LogTraceFunction;
m_thread_exit = true;
m_thread_idle = true;
m_condvar.notify_all();
m_msg_condvar.notify_all();
if (m_working_thread.joinable()) {
m_working_thread.join();
}
if (m_msg_thread.joinable()) {
m_msg_thread.join();
}
}
bool asst::Assistant::connect(const std::string& adb_path, const std::string& address, const std::string& config)
{
LogTraceFunction;
std::unique_lock<std::mutex> lock(m_mutex);
stop(false);
bool ret = m_ctrler->connect(adb_path, address, config.empty() ? "General" : config);
if (ret) {
m_uuid = m_ctrler->get_uuid();
}
return ret;
}
asst::Assistant::TaskId asst::Assistant::append_task(const std::string& type, const std::string& params)
{
Log.info(__FUNCTION__, type, params);
auto ret = json::parse(params.empty() ? "{}" : params);
if (!ret) {
return 0;
}
std::shared_ptr<PackageTask> ptr = nullptr;
#define ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(TASK) \
else if (type == TASK::TaskType) { ptr = std::make_shared<TASK>(task_callback, static_cast<void*>(this)); }
if constexpr (false) {}
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(FightTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(StartUpTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(CloseDownTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(AwardTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(VisitTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(MallTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(InfrastTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(RecruitTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(RoguelikeTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(CopilotTask)
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(DepotTask)
#ifdef ASST_DEBUG
ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH(DebugTask)
#endif
else {
Log.error(__FUNCTION__, "| invalid type:", type);
return 0;
}
#undef ASST_ASSISTANT_APPEND_TASK_FROM_STRING_IF_BRANCH
auto& json = ret.value();
bool enable = json.get("enable", true);
ptr->set_enable(enable);
bool params_ret = ptr->set_params(json);
if (!params_ret) {
return 0;
}
std::unique_lock<std::mutex> lock(m_mutex);
++m_task_id;
ptr->set_task_id(m_task_id);
m_tasks_list.emplace_back(m_task_id, ptr);
return m_task_id;
}
bool asst::Assistant::set_task_params(TaskId task_id, const std::string& params)
{
Log.info(__FUNCTION__, task_id, params);
if (task_id <= 0) {
return false;
}
auto ret = json::parse(params.empty() ? "{}" : params);
if (!ret) {
return false;
}
auto& json = ret.value();
bool is_set = false;
std::unique_lock<std::mutex> lock(m_mutex);
for (auto&& [id, ptr] : m_tasks_list) {
if (id != task_id) {
continue;
}
bool enable = json.get("enable", true);
ptr->set_enable(enable);
is_set = ptr->set_params(json);
break;
}
return is_set;
}
std::vector<uchar> asst::Assistant::get_image() const
{
if (!inited()) {
return {};
}
return m_ctrler->get_image_encode();
}
bool asst::Assistant::ctrler_click(int x, int y, bool block)
{
if (!inited()) {
return false;
}
m_ctrler->click(Point(x, y), block);
return true;
}
std::string asst::Assistant::get_uuid() const
{
return m_uuid;
}
std::vector<Assistant::TaskId> asst::Assistant::get_tasks_list() const
{
std::unique_lock<std::mutex> lock(m_mutex);
std::vector<TaskId> result(m_tasks_list.size());
ranges::copy(m_tasks_list | views::keys, result.begin());
return result;
}
bool asst::Assistant::start(bool block)
{
LogTraceFunction;
Log.trace("Start |", block ? "block" : "non block");
if (!m_thread_idle || !inited()) {
return false;
}
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
}
m_thread_idle = false;
m_condvar.notify_one();
return true;
}
bool Assistant::stop(bool block)
{
LogTraceFunction;
Log.trace("Stop |", block ? "block" : "non block");
m_thread_idle = true;
std::unique_lock<std::mutex> lock;
if (block) { // 外部调用
lock = std::unique_lock<std::mutex>(m_mutex);
}
m_tasks_list.clear();
clear_cache();
return true;
}
void Assistant::working_proc()
{
LogTraceFunction;
std::vector<TaskId> finished_tasks;
while (!m_thread_exit) {
//LogTraceScope("Assistant::working_proc Loop");
std::unique_lock<std::mutex> lock(m_mutex);
if (!m_thread_idle && !m_tasks_list.empty()) {
const auto [id, task_ptr] = m_tasks_list.front();
lock.unlock();
// only one instance of working_proc running, unlock here to allow set_task_param to the running task
json::value callback_json = json::object{
{ "taskchain", task_ptr->get_task_chain() },
{ "taskid", id }
};
task_callback(AsstMsg::TaskChainStart, callback_json, this);
task_ptr->set_exit_flag(&m_thread_idle)
.set_ctrler(m_ctrler)
.set_status(m_status);
bool ret = task_ptr->run();
finished_tasks.emplace_back(id);
lock.lock();
if (!m_tasks_list.empty()) {
m_tasks_list.pop_front();
}
lock.unlock();
task_callback(ret ? AsstMsg::TaskChainCompleted : AsstMsg::TaskChainError, callback_json, this);
if (!m_thread_idle && m_tasks_list.empty()) {
callback_json["finished_tasks"] = json::array(finished_tasks);
task_callback(AsstMsg::AllTasksCompleted, callback_json, this);
finished_tasks.clear();
}
auto delay = Resrc.cfg().get_options().task_delay;
lock.lock();
m_condvar.wait_for(lock, std::chrono::milliseconds(delay),
[&]() -> bool { return m_thread_idle; });
}
else {
m_thread_idle = true;
finished_tasks.clear();
Log.flush();
m_condvar.wait(lock);
}
}
}
void Assistant::msg_proc()
{
LogTraceFunction;
while (!m_thread_exit) {
//LogTraceScope("Assistant::msg_proc Loop");
std::unique_lock<std::mutex> lock(m_msg_mutex);
if (!m_msg_queue.empty()) {
// 结构化绑定只能是引用后续的pop会使引用失效所以需要重新构造一份这里采用了move的方式
auto&& [temp_msg, temp_detail] = m_msg_queue.front();
AsstMsg msg = temp_msg;
json::value detail = std::move(temp_detail);
m_msg_queue.pop();
lock.unlock();
if (m_callback) {
m_callback(static_cast<int>(msg), detail.to_string().c_str(), m_callback_arg);
}
}
else {
m_msg_condvar.wait(lock);
}
}
}
void Assistant::task_callback(AsstMsg msg, const json::value& detail, void* custom_arg)
{
auto p_this = static_cast<Assistant*>(custom_arg);
json::value more_detail = detail;
if (!more_detail.contains("uuid")) {
more_detail["uuid"] = p_this->m_uuid;
}
switch (msg) {
case AsstMsg::InternalError:
case AsstMsg::InitFailed:
p_this->stop(false);
break;
default:
break;
}
Log.trace("Assistant::task_callback |", msg, more_detail.to_string());
// 加入回调消息队列,由回调消息线程外抛给外部
p_this->append_callback(msg, std::move(more_detail));
}
void asst::Assistant::append_callback(AsstMsg msg, json::value detail)
{
std::unique_lock<std::mutex> lock(m_msg_mutex);
m_msg_queue.emplace(msg, std::move(detail));
m_msg_condvar.notify_one();
}
void Assistant::clear_cache()
{
m_status->clear_number();
m_status->clear_rect();
m_status->clear_str();
}
bool asst::Assistant::inited() const noexcept
{
return m_ctrler && m_ctrler->inited();
}

File diff suppressed because it is too large Load Diff

View File

@@ -58,8 +58,8 @@ namespace MeoAsstGui
Localization.GetString("CopilotTip1") + "\n\n" +
Localization.GetString("CopilotTip2") + "\n\n" +
Localization.GetString("CopilotTip3") + "\n\n" +
Localization.GetString("CopilotTip4") + "\n\n" +
Localization.GetString("CopilotTip5"),
Localization.GetString("CopilotTip4"),
//Localization.GetString("CopilotTip5"),
LogColor.Message);
}
@@ -295,8 +295,8 @@ namespace MeoAsstGui
Localization.GetString("CopilotTip1") + "\n\n" +
Localization.GetString("CopilotTip2") + "\n\n" +
Localization.GetString("CopilotTip3") + "\n\n" +
Localization.GetString("CopilotTip4") + "\n\n" +
Localization.GetString("CopilotTip5"));
Localization.GetString("CopilotTip4"));
//Localization.GetString("CopilotTip5"));
}
catch (Exception)
{
@@ -368,10 +368,10 @@ namespace MeoAsstGui
public async void Start()
{
ClearLog();
if (_form)
{
AddLog(Localization.GetString("AutoSquadTip"), LogColor.Message);
}
//if (_form)
//{
// AddLog(Localization.GetString("AutoSquadTip"), LogColor.Message);
//}
AddLog(Localization.GetString("ConnectingToEmulator"));