Compare commits
38 Commits
release.al
...
release.be
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e05430ec0e | ||
|
|
0a081d4fa2 | ||
|
|
a6488f0ea6 | ||
|
|
8844d35c2e | ||
|
|
0534e35871 | ||
|
|
107d3af5c5 | ||
|
|
1e170e6c1a | ||
|
|
f3773d22c6 | ||
|
|
7928a21051 | ||
|
|
2a89b01c1b | ||
|
|
d735404766 | ||
|
|
a8173eb82c | ||
|
|
67f52b321c | ||
|
|
6c3540b692 | ||
|
|
dd556817ea | ||
|
|
c393da2046 | ||
|
|
5657af6d94 | ||
|
|
f35ef18bd2 | ||
|
|
0fef8e2174 | ||
|
|
ee3afb440e | ||
|
|
952861c1e5 | ||
|
|
dab705a3de | ||
|
|
17f8353a97 | ||
|
|
53a1297842 | ||
|
|
e589a7498c | ||
|
|
ca412965ca | ||
|
|
adfed6d276 | ||
|
|
6fddf69e67 | ||
|
|
fb3cbb0b7a | ||
|
|
a348139df5 | ||
|
|
08db7f008d | ||
|
|
d66f178aec | ||
|
|
d51882fd1c | ||
|
|
c7b80b4603 | ||
|
|
1a0add784d | ||
|
|
70544e7809 | ||
|
|
3430be908b | ||
|
|
a617f254ff |
@@ -20,10 +20,13 @@
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="include\Assistance.h" />
|
||||
<ClInclude Include="include\AsstAux.h" />
|
||||
<ClInclude Include="include\AsstCaller.h" />
|
||||
<ClInclude Include="include\AsstDef.h" />
|
||||
<ClInclude Include="include\Configer.h" />
|
||||
<ClInclude Include="include\Identify.h" />
|
||||
<ClInclude Include="include\Logger.hpp" />
|
||||
<ClInclude Include="include\Updater.h" />
|
||||
<ClInclude Include="include\WinMacro.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -31,6 +34,7 @@
|
||||
<ClCompile Include="src\AsstCaller.cpp" />
|
||||
<ClCompile Include="src\Configer.cpp" />
|
||||
<ClCompile Include="src\Identify.cpp" />
|
||||
<ClCompile Include="src\Updater.cpp" />
|
||||
<ClCompile Include="src\WinMacro.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
@@ -145,7 +149,7 @@
|
||||
<Link>
|
||||
<SubSystem>Console</SubSystem>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opencv_world452d.lib;libmeojson.lib;WinInet.Lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
@@ -177,7 +181,7 @@
|
||||
<EnableCOMDATFolding>true</EnableCOMDATFolding>
|
||||
<OptimizeReferences>true</OptimizeReferences>
|
||||
<GenerateDebugInformation>true</GenerateDebugInformation>
|
||||
<AdditionalDependencies>opencv_core452.lib;opencv_imgcodecs452.lib;opencv_imgproc452.lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalDependencies>opencv_core452.lib;opencv_imgcodecs452.lib;opencv_imgproc452.lib;WinInet.Lib;libmeojson.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<UACExecutionLevel>RequireAdministrator</UACExecutionLevel>
|
||||
<AdditionalLibraryDirectories>$(TargetDir)</AdditionalLibraryDirectories>
|
||||
</Link>
|
||||
@@ -197,7 +201,7 @@
|
||||
</ImportGroup>
|
||||
<ProjectExtensions>
|
||||
<VisualStudio>
|
||||
<UserProperties _1_1_4resource_4config_1json__JsonSchema="https://beaujs.com/schema.json" />
|
||||
<UserProperties _1_1_4resource_4config_1json__JsonSchema="" />
|
||||
</VisualStudio>
|
||||
</ProjectExtensions>
|
||||
</Project>
|
||||
@@ -33,6 +33,15 @@
|
||||
<ClInclude Include="include\AsstCaller.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Updater.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\Logger.hpp">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="include\AsstAux.h">
|
||||
<Filter>头文件</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="src\Configer.cpp">
|
||||
@@ -50,6 +59,9 @@
|
||||
<ClCompile Include="src\AsstCaller.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="src\Updater.cpp">
|
||||
<Filter>源文件</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="..\resource\config.json">
|
||||
|
||||
@@ -20,12 +20,12 @@ namespace asst {
|
||||
~Assistance();
|
||||
|
||||
std::optional<std::string> setSimulator(const std::string & simulator_name = std::string());
|
||||
|
||||
|
||||
void start(const std::string & task);
|
||||
void stop();
|
||||
void stop(bool block = true);
|
||||
|
||||
bool setParam(const std::string& type, const std::string& param, const std::string& value);
|
||||
|
||||
std::optional<std::string> getParam(const std::string& type, const std::string& param);
|
||||
private:
|
||||
static void workingProc(Assistance* pThis);
|
||||
|
||||
|
||||
37
MeoAssistance/include/AsstAux.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <Windows.h>
|
||||
|
||||
namespace asst {
|
||||
|
||||
static std::string GetCurrentDir()
|
||||
{
|
||||
static std::string cur_dir;
|
||||
if (cur_dir.empty()) {
|
||||
char exepath_buff[_MAX_PATH] = { 0 };
|
||||
::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH);
|
||||
std::string exepath(exepath_buff);
|
||||
cur_dir = exepath.substr(0, exepath.find_last_of('\\') + 1);
|
||||
}
|
||||
return cur_dir;
|
||||
}
|
||||
|
||||
static std::string GetResourceDir()
|
||||
{
|
||||
static std::string res_dir = GetCurrentDir() + "resource\\";
|
||||
return res_dir;
|
||||
}
|
||||
|
||||
static std::string StringReplaceAll(const std::string& src, const std::string& old_value, const std::string& new_value)
|
||||
{
|
||||
std::string str = src;
|
||||
for (std::string::size_type pos(0); pos != std::string::npos; pos += new_value.length()) {
|
||||
if ((pos = str.find(old_value, pos)) != std::string::npos)
|
||||
str.replace(pos, old_value.length(), new_value);
|
||||
else
|
||||
break;
|
||||
}
|
||||
return str;
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,8 @@ extern __declspec(dllexport) bool AsstCatchSimulator(asst::Assistance* p_asst);
|
||||
extern __declspec(dllexport) void AsstStart(asst::Assistance* p_asst, const char* task);
|
||||
extern __declspec(dllexport) void AsstStop(asst::Assistance* p_asst);
|
||||
extern __declspec(dllexport) bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param, const char* value);
|
||||
extern __declspec(dllexport) bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size);
|
||||
extern __declspec(dllexport) bool CheckVersionUpdate(char * tag_buffer, int tag_bufsize, char * html_url_buffer, int html_bufsize, char * body_buffer, int body_bufsize);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
||||
@@ -1,13 +1,14 @@
|
||||
#pragma once
|
||||
|
||||
#include "json_value.h"
|
||||
#include "json_array.h"
|
||||
|
||||
#include <mutex>
|
||||
#include <process.h>
|
||||
#include <Windows.h>
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <ostream>
|
||||
|
||||
namespace asst {
|
||||
|
||||
const static std::string Version = "release.beta.02";
|
||||
|
||||
enum class HandleType
|
||||
{
|
||||
Window = 1,
|
||||
@@ -15,6 +16,43 @@ namespace asst {
|
||||
Control = 4
|
||||
};
|
||||
|
||||
static std::ostream& operator<<(std::ostream& os, const HandleType& type)
|
||||
{
|
||||
static std::unordered_map<HandleType, std::string> _type_name = {
|
||||
{HandleType::Window, "Window"},
|
||||
{HandleType::View, "View"},
|
||||
{HandleType::Control, "Control"}
|
||||
};
|
||||
return os << _type_name.at(type);
|
||||
}
|
||||
|
||||
enum class TaskType {
|
||||
Invalid = 0,
|
||||
BasicClick = 1,
|
||||
DoNothing = 2,
|
||||
Stop = 4,
|
||||
ClickSelf = 8 | BasicClick,
|
||||
ClickRect = 16 | BasicClick,
|
||||
ClickRand = 32 | BasicClick
|
||||
};
|
||||
static bool operator&(const TaskType& lhs, const TaskType& rhs)
|
||||
{
|
||||
return static_cast<std::underlying_type<TaskType>::type>(lhs) & static_cast<std::underlying_type<TaskType>::type>(rhs);
|
||||
}
|
||||
static std::ostream& operator<<(std::ostream& os, const TaskType& task)
|
||||
{
|
||||
static std::unordered_map<TaskType, std::string> _type_name = {
|
||||
{TaskType::Invalid, "Invalid"},
|
||||
{TaskType::BasicClick, "BasicClick"},
|
||||
{TaskType::ClickSelf, "ClickSelf"},
|
||||
{TaskType::ClickRect, "ClickRect"},
|
||||
{TaskType::ClickRand, "ClickRand"},
|
||||
{TaskType::DoNothing, "DoNothing"},
|
||||
{TaskType::Stop, "Stop"}
|
||||
};
|
||||
return os << _type_name.at(task);
|
||||
}
|
||||
|
||||
struct Point
|
||||
{
|
||||
Point() = default;
|
||||
@@ -32,10 +70,10 @@ namespace asst {
|
||||
{
|
||||
return { x, y, static_cast<int>(width * rhs), static_cast<int>(height * rhs) };
|
||||
}
|
||||
Rect center_zoom(double scale)
|
||||
Rect center_zoom(double scale) const
|
||||
{
|
||||
int half_width_scale = static_cast<int>(width * (1- scale) / 2) ;
|
||||
int half_hight_scale = static_cast<int>(height * (1 - scale) / 2) ;
|
||||
int half_width_scale = static_cast<int>(width * (1 - scale) / 2);
|
||||
int half_hight_scale = static_cast<int>(height * (1 - scale) / 2);
|
||||
return { x + half_width_scale, y + half_hight_scale, width - half_width_scale, height - half_hight_scale };
|
||||
}
|
||||
int x = 0;
|
||||
@@ -44,45 +82,48 @@ namespace asst {
|
||||
int height = 0;
|
||||
};
|
||||
|
||||
static Rect jsonToRect(const json::array& arr)
|
||||
{
|
||||
if (arr.size() != 4) {
|
||||
return { 0, 0, 0, 0 };
|
||||
}
|
||||
return Rect(arr[0].as_integer(), arr[1].as_integer(), arr[2].as_integer(), arr[3].as_integer());
|
||||
}
|
||||
struct HandleInfo {
|
||||
std::string className;
|
||||
std::string windowName;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
void DebugPrint(const std::string& level, Args &&... args)
|
||||
{
|
||||
static std::mutex trace_mutex;
|
||||
std::unique_lock<std::mutex> trace_lock(trace_mutex);
|
||||
struct AdbCmd {
|
||||
std::string path;
|
||||
std::string connect;
|
||||
std::string click;
|
||||
};
|
||||
|
||||
SYSTEMTIME curtime;
|
||||
GetLocalTime(&curtime);
|
||||
printf("[%04d-%02d-%02d %02d:%02d:%02d.%03d][%s][Px%x][Tx%x] ",
|
||||
curtime.wYear, curtime.wMonth, curtime.wDay,
|
||||
curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds,
|
||||
level.c_str(), _getpid(), GetCurrentThreadId());
|
||||
printf(std::forward<Args>(args)...);
|
||||
printf("\n");
|
||||
}
|
||||
struct SimulatorInfo {
|
||||
std::vector<HandleInfo> window;
|
||||
std::vector<HandleInfo> view;
|
||||
std::vector<HandleInfo> control;
|
||||
bool is_adb = false;
|
||||
AdbCmd adb;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int x_offset = 0;
|
||||
int y_offset = 0;
|
||||
};
|
||||
|
||||
template <typename... Args>
|
||||
inline void DebugTrace(Args &&... args)
|
||||
{
|
||||
//#ifdef _DEBUG
|
||||
DebugPrint("TRC", std::forward<Args>(args)...);
|
||||
//#endif
|
||||
}
|
||||
template <typename... Args>
|
||||
inline void DebugTraceInfo(Args &&... args)
|
||||
{
|
||||
DebugPrint("INF", std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename... Args>
|
||||
inline void DebugTraceError(Args &&... args)
|
||||
{
|
||||
DebugPrint("ERR", std::forward<Args>(args)...);
|
||||
}
|
||||
struct TaskInfo {
|
||||
std::string filename;
|
||||
double threshold = 0;
|
||||
double cache_threshold = 0;
|
||||
TaskType type = TaskType::Invalid;
|
||||
std::vector<std::string> next;
|
||||
int exec_times = 0;
|
||||
int max_times = INT_MAX;
|
||||
std::vector<std::string> exceeded_next;
|
||||
std::vector<std::string> reduce_other_times;
|
||||
asst::Rect specific_area;
|
||||
int pre_delay = 0;
|
||||
int rear_delay = 0;
|
||||
};
|
||||
|
||||
struct Options {
|
||||
int identify_delay = 0;
|
||||
bool identify_cache = false;
|
||||
int control_delay_lower = 0;
|
||||
int control_delay_upper = 0;
|
||||
};
|
||||
}
|
||||
@@ -3,42 +3,11 @@
|
||||
#include <string>
|
||||
#include <unordered_map>
|
||||
#include <vector>
|
||||
#include <optional>
|
||||
|
||||
#include "AsstDef.h"
|
||||
|
||||
namespace asst {
|
||||
struct HandleInfo {
|
||||
std::string className;
|
||||
std::string windowName;
|
||||
};
|
||||
struct SimulatorInfo {
|
||||
std::vector<HandleInfo> window;
|
||||
std::vector<HandleInfo> view;
|
||||
std::vector<HandleInfo> control;
|
||||
int width = 0;
|
||||
int height = 0;
|
||||
int xOffset = 0;
|
||||
int yOffset = 0;
|
||||
};
|
||||
|
||||
enum class TaskType {
|
||||
ClickSelf,
|
||||
ClickRand,
|
||||
DoNothing,
|
||||
Stop
|
||||
};
|
||||
|
||||
struct TaskInfo {
|
||||
std::string filename;
|
||||
double threshold = 0;
|
||||
TaskType type;
|
||||
std::vector<std::string> next;
|
||||
unsigned int exec_times = 0;
|
||||
unsigned int max_times = UINT_MAX;
|
||||
};
|
||||
struct Options {
|
||||
std::string delayType;
|
||||
int delayFixedTime = 0;
|
||||
bool cache = false;
|
||||
};
|
||||
|
||||
class Configer
|
||||
{
|
||||
@@ -46,8 +15,6 @@ namespace asst {
|
||||
~Configer() = default;
|
||||
|
||||
static bool reload();
|
||||
static std::string getCurDir();
|
||||
static std::string getResDir();
|
||||
|
||||
static std::string m_version;
|
||||
static Options m_options;
|
||||
@@ -55,6 +22,12 @@ namespace asst {
|
||||
static std::unordered_map<std::string, SimulatorInfo> m_handles;
|
||||
|
||||
static bool setParam(const std::string& type, const std::string& param, const std::string& value);
|
||||
static std::optional<std::string> getParam(const std::string& type, const std::string& param);
|
||||
|
||||
static void clearExecTimes();
|
||||
|
||||
constexpr static double DefaultThreshold = 0.9;
|
||||
constexpr static double DefaultCacheThreshold = 0.9;
|
||||
private:
|
||||
Configer() = default;
|
||||
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
#pragma once
|
||||
|
||||
#include "AsstDef.h"
|
||||
|
||||
#include <opencv2/opencv.hpp>
|
||||
#include <unordered_map>
|
||||
#include <utility>
|
||||
#include <tuple>
|
||||
#include <opencv2/opencv.hpp>
|
||||
|
||||
#include "AsstDef.h"
|
||||
|
||||
|
||||
namespace asst {
|
||||
|
||||
|
||||
105
MeoAssistance/include/Logger.hpp
Normal file
@@ -0,0 +1,105 @@
|
||||
#pragma once
|
||||
|
||||
#include <fstream>
|
||||
#include <mutex>
|
||||
#include <chrono>
|
||||
#include <iostream>
|
||||
|
||||
#include "AsstAux.h"
|
||||
|
||||
namespace asst {
|
||||
class Logger {
|
||||
public:
|
||||
~Logger() = default;
|
||||
|
||||
Logger(const Logger&) = delete;
|
||||
Logger(Logger&&) = delete;
|
||||
|
||||
static Logger& get_instance()
|
||||
{
|
||||
static Logger _unique_instance;
|
||||
return _unique_instance;
|
||||
}
|
||||
|
||||
template <typename... Args>
|
||||
inline void log_trace(Args &&... args)
|
||||
{
|
||||
log("TRC", std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename... Args>
|
||||
inline void log_info(Args &&... args)
|
||||
{
|
||||
log("INF", std::forward<Args>(args)...);
|
||||
}
|
||||
template <typename... Args>
|
||||
inline void log_error(Args &&... args)
|
||||
{
|
||||
log("ERR", std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
private:
|
||||
Logger() = default;
|
||||
|
||||
template <typename... Args>
|
||||
void log(const std::string& level, Args &&... args)
|
||||
{
|
||||
std::unique_lock<std::mutex> trace_lock(m_trace_mutex);
|
||||
|
||||
SYSTEMTIME curtime;
|
||||
GetLocalTime(&curtime);
|
||||
char buff[64] = { 0 };
|
||||
sprintf_s(buff, "[%04d-%02d-%02d %02d:%02d:%02d.%03d][%s][Px%x][Tx%x]",
|
||||
curtime.wYear, curtime.wMonth, curtime.wDay,
|
||||
curtime.wHour, curtime.wMinute, curtime.wSecond, curtime.wMilliseconds,
|
||||
level.c_str(), _getpid(), GetCurrentThreadId());
|
||||
|
||||
if (level == "ERR" || level == "INF"
|
||||
#ifdef _DEBUG
|
||||
|| level == "TRC"
|
||||
#endif
|
||||
) {
|
||||
stream_args(std::cout, buff, std::forward<Args>(args)...);
|
||||
}
|
||||
std::ofstream out_stream(asst::GetCurrentDir() + "asst.log", std::ios::out | std::ios::app);
|
||||
stream_args(out_stream, buff, std::forward<Args>(args)...);
|
||||
}
|
||||
|
||||
template <typename T, typename... Args>
|
||||
inline void stream_args(std::ostream& os, T&& first, Args && ...rest)
|
||||
{
|
||||
os << first << " ";
|
||||
stream_args(os, std::forward<Args>(rest)...);
|
||||
}
|
||||
|
||||
inline void stream_args(std::ostream& os)
|
||||
{
|
||||
os << std::endl;
|
||||
}
|
||||
|
||||
std::mutex m_trace_mutex;
|
||||
};
|
||||
|
||||
class LoggerAux {
|
||||
public:
|
||||
LoggerAux(const std::string& func_name)
|
||||
: m_func_name(func_name),
|
||||
m_start_time(std::chrono::system_clock::now())
|
||||
{
|
||||
Logger::get_instance().log_trace(m_func_name, " | enter");
|
||||
}
|
||||
~LoggerAux()
|
||||
{
|
||||
auto duration = std::chrono::system_clock::now() - m_start_time;
|
||||
Logger::get_instance().log_trace(m_func_name, " | leave,",
|
||||
std::chrono::duration_cast<std::chrono::milliseconds>(duration).count(), "ms");
|
||||
}
|
||||
private:
|
||||
std::string m_func_name;
|
||||
std::chrono::time_point<std::chrono::system_clock> m_start_time;
|
||||
};
|
||||
}
|
||||
|
||||
#define DebugTrace Logger::get_instance().log_trace
|
||||
#define DebugTraceInfo Logger::get_instance().log_info
|
||||
#define DebugTraceError Logger::get_instance().log_error
|
||||
#define DebugTraceFunction LoggerAux _func_aux(__FUNCTION__)
|
||||
37
MeoAssistance/include/Updater.h
Normal file
@@ -0,0 +1,37 @@
|
||||
#pragma once
|
||||
|
||||
#include <string>
|
||||
#include <optional>
|
||||
#include <mutex>
|
||||
|
||||
namespace asst {
|
||||
struct __declspec(dllexport) VersionInfo {
|
||||
std::string tag_name;
|
||||
std::string html_url;
|
||||
std::string down_url;
|
||||
std::string author_name;
|
||||
std::string created_time;
|
||||
std::string body;
|
||||
};
|
||||
|
||||
class __declspec(dllexport) Updater
|
||||
{
|
||||
static const std::string GithubReleaseLastestApiUrl;
|
||||
static const std::string GithubReleaseApiUrl;
|
||||
public:
|
||||
~Updater() = default;
|
||||
|
||||
static Updater& instance();
|
||||
|
||||
bool has_new_version();
|
||||
const VersionInfo & get_version_info() const noexcept;
|
||||
|
||||
private:
|
||||
Updater() = default;
|
||||
std::optional<std::string> request_github_api();
|
||||
|
||||
bool m_has_new_version = false;
|
||||
VersionInfo m_lastest_version;
|
||||
std::mutex m_mutex;
|
||||
};
|
||||
}
|
||||
@@ -30,10 +30,12 @@ namespace asst {
|
||||
const std::string m_simulator_name;
|
||||
const HandleType m_handle_type;
|
||||
HWND m_handle = NULL;
|
||||
bool m_is_adb = false;
|
||||
std::string m_click_cmd;
|
||||
std::minstd_rand m_rand_engine;
|
||||
int m_width = 0;
|
||||
int m_height = 0;
|
||||
int m_xOffset = 0;
|
||||
int m_yOffset = 0;
|
||||
int m_x_offset = 0;
|
||||
int m_y_offset = 0;
|
||||
};
|
||||
}
|
||||
|
||||
@@ -3,19 +3,23 @@
|
||||
#include "WinMacro.h"
|
||||
#include "Configer.h"
|
||||
#include "Identify.h"
|
||||
#include "Logger.hpp"
|
||||
#include "AsstAux.h"
|
||||
|
||||
using namespace asst;
|
||||
|
||||
Assistance::Assistance()
|
||||
{
|
||||
DebugTraceFunction;
|
||||
|
||||
Configer::reload();
|
||||
|
||||
m_pIder = std::make_shared<Identify>();
|
||||
for (auto&& [name, info] : Configer::m_tasks)
|
||||
{
|
||||
m_pIder->addImage(name, Configer::getResDir() + info.filename);
|
||||
m_pIder->addImage(name, GetResourceDir() + info.filename);
|
||||
}
|
||||
m_pIder->setUseCache(Configer::m_options.cache);
|
||||
m_pIder->setUseCache(Configer::m_options.identify_cache);
|
||||
|
||||
m_working_thread = std::thread(workingProc, this);
|
||||
|
||||
@@ -23,6 +27,8 @@ Assistance::Assistance()
|
||||
|
||||
Assistance::~Assistance()
|
||||
{
|
||||
DebugTraceFunction;
|
||||
|
||||
if (m_pWindow != nullptr) {
|
||||
m_pWindow->showWindow();
|
||||
}
|
||||
@@ -38,6 +44,8 @@ Assistance::~Assistance()
|
||||
|
||||
std::optional<std::string> Assistance::setSimulator(const std::string& simulator_name)
|
||||
{
|
||||
DebugTraceFunction;
|
||||
|
||||
stop();
|
||||
|
||||
auto create_handles = [&](const std::string& name) -> bool {
|
||||
@@ -65,7 +73,7 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
|
||||
else {
|
||||
ret = create_handles(simulator_name);
|
||||
}
|
||||
if (ret && m_pWindow->resizeWindow()) {
|
||||
if (ret && m_pWindow->showWindow() && m_pWindow->resizeWindow()) {
|
||||
m_inited = true;
|
||||
return cor_name;
|
||||
}
|
||||
@@ -77,11 +85,17 @@ std::optional<std::string> Assistance::setSimulator(const std::string& simulator
|
||||
|
||||
void Assistance::start(const std::string& task)
|
||||
{
|
||||
DebugTraceFunction;
|
||||
DebugTrace("Start |", task);
|
||||
|
||||
|
||||
if (m_thread_running || !m_inited) {
|
||||
return;
|
||||
}
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
|
||||
Configer::clearExecTimes();
|
||||
m_pIder->clear_cache();
|
||||
m_next_tasks.clear();
|
||||
m_next_tasks.emplace_back(task);
|
||||
@@ -89,10 +103,16 @@ void Assistance::start(const std::string& task)
|
||||
m_condvar.notify_one();
|
||||
}
|
||||
|
||||
void Assistance::stop()
|
||||
void Assistance::stop(bool block)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
DebugTraceFunction;
|
||||
DebugTrace("Stop |", block);
|
||||
|
||||
std::unique_lock<std::mutex> lock;
|
||||
if (block) { // Íⲿµ÷ÓÃ
|
||||
lock = std::unique_lock<std::mutex>(m_mutex);
|
||||
Configer::clearExecTimes();
|
||||
}
|
||||
m_thread_running = false;
|
||||
m_next_tasks.clear();
|
||||
m_pIder->clear_cache();
|
||||
@@ -100,11 +120,23 @@ void Assistance::stop()
|
||||
|
||||
bool Assistance::setParam(const std::string& type, const std::string& param, const std::string& value)
|
||||
{
|
||||
DebugTraceFunction;
|
||||
DebugTrace("SetParam |", type, param, value);
|
||||
|
||||
return Configer::setParam(type, param, value);
|
||||
}
|
||||
|
||||
std::optional<std::string> Assistance::getParam(const std::string& type, const std::string& param)
|
||||
{
|
||||
// DebugTraceFunction;
|
||||
|
||||
return Configer::getParam(type, param);
|
||||
}
|
||||
|
||||
void Assistance::workingProc(Assistance* pThis)
|
||||
{
|
||||
DebugTraceFunction;
|
||||
|
||||
while (!pThis->m_thread_exit) {
|
||||
std::unique_lock<std::mutex> lock(pThis->m_mutex);
|
||||
if (pThis->m_thread_running) {
|
||||
@@ -113,12 +145,13 @@ void Assistance::workingProc(Assistance* pThis)
|
||||
std::string matched_task;
|
||||
Rect matched_rect;
|
||||
for (auto&& task_name : pThis->m_next_tasks) {
|
||||
double threshold = Configer::m_tasks[task_name].threshold;
|
||||
auto&& task = Configer::m_tasks[task_name];
|
||||
double threshold = task.threshold;
|
||||
auto&& [algorithm, value, rect] = pThis->m_pIder->findImage(curImg, task_name, threshold);
|
||||
DebugTrace("%-20s Type:%d, Value:%f", task_name.c_str(), algorithm, value);
|
||||
DebugTrace(task_name, "Type:", algorithm, "Value:", value);
|
||||
if (algorithm == 0 ||
|
||||
(algorithm == 1 && value >= threshold)
|
||||
|| (algorithm == 2 && value >= 0.9999)) {
|
||||
|| (algorithm == 2 && value >= task.cache_threshold)) {
|
||||
matched_task = task_name;
|
||||
matched_rect = rect;
|
||||
break;
|
||||
@@ -126,46 +159,82 @@ void Assistance::workingProc(Assistance* pThis)
|
||||
}
|
||||
|
||||
if (!matched_task.empty()) {
|
||||
auto task = Configer::m_tasks[matched_task];
|
||||
DebugTraceInfo("Matched: %s, Type: %d", matched_task.c_str(), task.type);
|
||||
auto&& task = Configer::m_tasks[matched_task];
|
||||
DebugTraceInfo("***Matched***", matched_task, "Type:", task.type);
|
||||
if (task.pre_delay > 0) {
|
||||
DebugTrace("PreDelay", task.pre_delay);
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(task.pre_delay));
|
||||
bool cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.pre_delay),
|
||||
[&]() -> bool { return !pThis->m_thread_running; });
|
||||
if (cv_ret) { continue; }
|
||||
}
|
||||
|
||||
switch (task.type) {
|
||||
case TaskType::ClickSelf:
|
||||
if (task.exec_times >= task.max_times) {
|
||||
pThis->m_thread_running = false;
|
||||
pThis->m_next_tasks.clear();
|
||||
continue;
|
||||
if (task.max_times != INT_MAX) {
|
||||
DebugTrace("CurTimes:", task.exec_times, "MaxTimes:", task.max_times);
|
||||
}
|
||||
if (task.exec_times < task.max_times) {
|
||||
if ((task.type & TaskType::BasicClick)
|
||||
&& Configer::m_options.control_delay_upper != 0) {
|
||||
static std::default_random_engine rand_engine(std::chrono::system_clock::now().time_since_epoch().count());
|
||||
static std::uniform_int_distribution<unsigned> rand_uni(Configer::m_options.control_delay_lower, Configer::m_options.control_delay_upper);
|
||||
int delay = rand_uni(rand_engine);
|
||||
DebugTraceInfo("Random Delay", delay, "ms");
|
||||
bool cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(delay),
|
||||
[&]() -> bool { return !pThis->m_thread_running; });
|
||||
if (cv_ret) { continue; }
|
||||
}
|
||||
switch (task.type) {
|
||||
case TaskType::ClickRect:
|
||||
matched_rect = task.specific_area;
|
||||
[[fallthrough]];
|
||||
case TaskType::ClickSelf:
|
||||
pThis->m_pCtrl->clickRange(matched_rect);
|
||||
break;
|
||||
case TaskType::ClickRand:
|
||||
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
|
||||
break;
|
||||
case TaskType::DoNothing:
|
||||
break;
|
||||
case TaskType::Stop:
|
||||
DebugTrace("TaskType is Stop");
|
||||
pThis->stop(false);
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
DebugTraceError("Unknown option type:", task.type);
|
||||
break;
|
||||
}
|
||||
pThis->m_pCtrl->clickRange(matched_rect);
|
||||
++task.exec_times;
|
||||
break;
|
||||
case TaskType::ClickRand:
|
||||
pThis->m_pCtrl->clickRange(pThis->m_pCtrl->getWindowRect());
|
||||
break;
|
||||
case TaskType::DoNothing:
|
||||
break;
|
||||
case TaskType::Stop:
|
||||
DebugTrace("TaskType is Stop");
|
||||
pThis->m_thread_running = false;
|
||||
pThis->m_next_tasks.clear();
|
||||
continue;
|
||||
break;
|
||||
default:
|
||||
DebugTraceError("Unknown option type: %d", task.type);
|
||||
break;
|
||||
for (auto&& reduce : task.reduce_other_times) {
|
||||
--Configer::m_tasks[reduce].exec_times;
|
||||
DebugTrace("Reduce exec times", reduce, Configer::m_tasks[reduce].exec_times);
|
||||
}
|
||||
if (task.rear_delay > 0) {
|
||||
DebugTrace("RearDelay", task.rear_delay);
|
||||
// std::this_thread::sleep_for(std::chrono::milliseconds(task.rear_delay));
|
||||
auto cv_ret = pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(task.rear_delay),
|
||||
[&]() -> bool { return !pThis->m_thread_running; });
|
||||
if (cv_ret) { continue; }
|
||||
}
|
||||
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
|
||||
}
|
||||
else {
|
||||
DebugTraceInfo("Reached limit");
|
||||
pThis->m_next_tasks = Configer::m_tasks[matched_task].exceeded_next;
|
||||
}
|
||||
|
||||
pThis->m_next_tasks = Configer::m_tasks[matched_task].next;
|
||||
std::string nexts;
|
||||
std::string nexts_str;
|
||||
for (auto&& name : pThis->m_next_tasks) {
|
||||
nexts += name + ",";
|
||||
nexts_str += name + ",";
|
||||
}
|
||||
if (nexts.back() == ',') {
|
||||
nexts.pop_back();
|
||||
if (nexts_str.back() == ',') {
|
||||
nexts_str.pop_back();
|
||||
}
|
||||
DebugTrace("Next: %s", nexts.c_str());
|
||||
DebugTrace("Next:", nexts_str);
|
||||
}
|
||||
pThis->m_condvar.wait_for(lock, std::chrono::milliseconds(Configer::m_options.delayFixedTime));
|
||||
pThis->m_condvar.wait_for(lock,
|
||||
std::chrono::milliseconds(Configer::m_options.identify_delay),
|
||||
[&]() -> bool { return !pThis->m_thread_running; });
|
||||
}
|
||||
else {
|
||||
pThis->m_condvar.wait(lock);
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
#include "AsstCaller.h"
|
||||
#include "Updater.h"
|
||||
|
||||
#include <string.h>
|
||||
|
||||
asst::Assistance* CreateAsst()
|
||||
{
|
||||
@@ -54,5 +56,31 @@ bool AsstSetParam(asst::Assistance* p_asst, const char* type, const char* param,
|
||||
return false;
|
||||
}
|
||||
|
||||
p_asst->setParam(type, param, value);
|
||||
return p_asst->setParam(type, param, value);
|
||||
}
|
||||
|
||||
bool AsstGetParam(asst::Assistance* p_asst, const char* type, const char* param, char * buffer, int buffer_size)
|
||||
{
|
||||
if (p_asst == NULL) {
|
||||
return false;
|
||||
}
|
||||
auto ret = p_asst->getParam(type, param);
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
strcpy_s(buffer, buffer_size, ret.value().c_str());
|
||||
return true;
|
||||
}
|
||||
|
||||
bool CheckVersionUpdate(char* tag_buffer, int tag_bufsize, char* html_url_buffer, int html_bufsize, char* body_buffer, int body_bufsize)
|
||||
{
|
||||
bool ret = asst::Updater::instance().has_new_version();
|
||||
if (!ret) {
|
||||
return false;
|
||||
}
|
||||
auto && info = asst::Updater::instance().get_version_info();
|
||||
strcpy_s(tag_buffer, tag_bufsize, info.tag_name.c_str());
|
||||
strcpy_s(html_url_buffer, html_bufsize, info.html_url.c_str());
|
||||
strcpy_s(body_buffer, body_bufsize, info.body.c_str());
|
||||
return true;
|
||||
}
|
||||
@@ -7,6 +7,8 @@
|
||||
|
||||
#include "json.h"
|
||||
#include "AsstDef.h"
|
||||
#include "AsstAux.h"
|
||||
#include "Logger.hpp"
|
||||
|
||||
using namespace asst;
|
||||
|
||||
@@ -18,7 +20,7 @@ std::unordered_map<std::string, SimulatorInfo> Configer::m_handles;
|
||||
|
||||
bool Configer::reload()
|
||||
{
|
||||
std::string filename = getResDir() + "config.json";
|
||||
std::string filename = GetResourceDir() + "config.json";
|
||||
std::ifstream ifs(filename, std::ios::in);
|
||||
if (!ifs.is_open()) {
|
||||
return false;
|
||||
@@ -39,15 +41,27 @@ bool Configer::reload()
|
||||
m_version = root["version"].as_string();
|
||||
|
||||
auto options_obj = root["options"].as_object();
|
||||
m_options.delayType = options_obj["delay"]["type"].as_string();
|
||||
m_options.delayFixedTime = options_obj["delay"]["fixedTime"].as_integer();
|
||||
m_options.cache = options_obj["cache"].as_boolean();
|
||||
m_options.identify_delay = options_obj["identifyDelay"].as_integer();
|
||||
m_options.identify_cache = options_obj["identifyCache"].as_boolean();
|
||||
m_options.control_delay_lower = options_obj["controlDelayRange"][0].as_integer();
|
||||
m_options.control_delay_upper = options_obj["controlDelayRange"][1].as_integer();
|
||||
|
||||
auto tasks_obj = root["tasks"].as_object();
|
||||
for (auto&& [name, task_json] : tasks_obj) {
|
||||
TaskInfo task_info;
|
||||
task_info.filename = task_json["filename"].as_string();
|
||||
task_info.threshold = task_json["threshold"].as_double();
|
||||
if (task_json.exist("threshold")) {
|
||||
task_info.threshold = task_json["threshold"].as_double();
|
||||
}
|
||||
else {
|
||||
task_info.threshold = DefaultThreshold;
|
||||
}
|
||||
if (task_json.exist("cache_threshold")) {
|
||||
task_info.cache_threshold = task_json["cache_threshold"].as_double();
|
||||
}
|
||||
else {
|
||||
task_info.cache_threshold = DefaultCacheThreshold;
|
||||
}
|
||||
std::string type = task_json["type"].as_string();
|
||||
std::transform(type.begin(), type.end(), type.begin(), std::tolower);
|
||||
if (type == "clickself") {
|
||||
@@ -62,13 +76,45 @@ bool Configer::reload()
|
||||
else if (type == "stop") {
|
||||
task_info.type = TaskType::Stop;
|
||||
}
|
||||
else if (type == "clickrect") {
|
||||
task_info.type = TaskType::ClickRect;
|
||||
auto area_json = task_json["specificArea"].as_array();
|
||||
task_info.specific_area = Rect(
|
||||
area_json[0].as_integer(),
|
||||
area_json[1].as_integer(),
|
||||
area_json[2].as_integer(),
|
||||
area_json[3].as_integer());
|
||||
}
|
||||
else {
|
||||
DebugTraceError("Task: %s 's type error: %s", name.c_str(), type.c_str());
|
||||
DebugTraceError("Task:", name, "error:", type);
|
||||
return false;
|
||||
}
|
||||
if (task_json.as_object().exist("maxTimes")) {
|
||||
if (task_json.exist("maxTimes")) {
|
||||
task_info.max_times = task_json["maxTimes"].as_integer();
|
||||
}
|
||||
if (task_json.exist("exceededNext")) {
|
||||
auto next_arr = task_json["exceededNext"].as_array();
|
||||
for (auto&& name : next_arr) {
|
||||
task_info.exceeded_next.emplace_back(name.as_string());
|
||||
}
|
||||
}
|
||||
else {
|
||||
task_info.exceeded_next.emplace_back("Stop");
|
||||
}
|
||||
if (task_json.exist("preDelay")) {
|
||||
task_info.pre_delay = task_json["preDelay"].as_integer();
|
||||
}
|
||||
if (task_json.exist("rearDelay")) {
|
||||
task_info.rear_delay = task_json["rearDelay"].as_integer();
|
||||
}
|
||||
if (task_json.exist("reduceOtherTimes")) {
|
||||
auto reduce_arr = task_json["reduceOtherTimes"].as_array();
|
||||
for (auto&& reduce : reduce_arr) {
|
||||
task_info.reduce_other_times.emplace_back(reduce.as_string());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
auto next_arr = task_json["next"].as_array();
|
||||
for (auto&& name : next_arr) {
|
||||
task_info.next.emplace_back(name.as_string());
|
||||
@@ -102,16 +148,23 @@ bool Configer::reload()
|
||||
handle_info.windowName = info["window"].as_string();
|
||||
simulator_info.control.emplace_back(handle_info);
|
||||
}
|
||||
if (simulator_json.exist("adbControl")) {
|
||||
simulator_info.is_adb = true;
|
||||
// meojson的bug,暂时没空修,先转个字符串
|
||||
simulator_info.adb.path = StringReplaceAll(simulator_json["adbControl"]["path"].as_string(), "\\\\", "\\");
|
||||
simulator_info.adb.connect = simulator_json["adbControl"]["connect"].as_string();
|
||||
simulator_info.adb.click = simulator_json["adbControl"]["click"].as_string();
|
||||
}
|
||||
simulator_info.width = simulator_json["width"].as_integer();
|
||||
simulator_info.height = simulator_json["height"].as_integer();
|
||||
simulator_info.xOffset = simulator_json["xOffset"].as_integer();
|
||||
simulator_info.yOffset = simulator_json["yOffset"].as_integer();
|
||||
simulator_info.x_offset = simulator_json["xOffset"].as_integer();
|
||||
simulator_info.y_offset = simulator_json["yOffset"].as_integer();
|
||||
|
||||
m_handles.emplace(name, simulator_info);
|
||||
}
|
||||
}
|
||||
catch (json::exception& e) {
|
||||
DebugTraceError("Load config json error!: %s", e.what());
|
||||
DebugTraceError("Load config json error!", e.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -139,8 +192,11 @@ bool Configer::setParam(const std::string& type, const std::string& param, const
|
||||
else if (type == "stop") {
|
||||
task_info.type = TaskType::Stop;
|
||||
}
|
||||
else if (type == "clickrect") {
|
||||
task_info.type = TaskType::ClickRect;
|
||||
}
|
||||
else {
|
||||
DebugTraceError("Task: %s 's type error: %s", param.c_str(), type.c_str());
|
||||
DebugTraceError("Task", param, "'s type error:", type);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -153,18 +209,17 @@ bool Configer::setParam(const std::string& type, const std::string& param, const
|
||||
return true;
|
||||
}
|
||||
|
||||
std::string Configer::getCurDir()
|
||||
std::optional<std::string> Configer::getParam(const std::string& type, const std::string& param)
|
||||
{
|
||||
if (m_curDir.empty()) {
|
||||
char exepath_buff[_MAX_PATH] = { 0 };
|
||||
::GetModuleFileNameA(NULL, exepath_buff, _MAX_PATH);
|
||||
std::string exepath(exepath_buff);
|
||||
m_curDir = exepath.substr(0, exepath.find_last_of('\\') + 1);
|
||||
if (type == "task.execTimes" && m_tasks.find(param) != m_tasks.cend()) {
|
||||
return std::to_string(m_tasks.at(param).exec_times);
|
||||
}
|
||||
return m_curDir;
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
std::string Configer::getResDir()
|
||||
void Configer::clearExecTimes()
|
||||
{
|
||||
return getCurDir() + "resource\\";
|
||||
}
|
||||
for (auto&& t : m_tasks) {
|
||||
t.second.exec_times = 0;
|
||||
}
|
||||
}
|
||||
@@ -48,7 +48,8 @@ Mat Identify::image2Hist(const cv::Mat& src)
|
||||
|
||||
double Identify::imageHistComp(const cv::Mat& src, const cv::MatND& hist)
|
||||
{
|
||||
return compareHist(image2Hist(src), hist, CV_COMP_CORREL);
|
||||
// keep the interface return value unchanged
|
||||
return 1 - compareHist(image2Hist(src), hist, CV_COMP_BHATTACHARYYA);
|
||||
}
|
||||
|
||||
std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv::Mat& templ)
|
||||
@@ -59,7 +60,7 @@ std::pair<double, cv::Point> Identify::findImage(const cv::Mat& image, const cv:
|
||||
cvtColor(templ, templ_hsv, COLOR_BGR2HSV);
|
||||
|
||||
Mat matched;
|
||||
matchTemplate(image_hsv, templ_hsv, matched, cv::TM_CCORR_NORMED);
|
||||
matchTemplate(image_hsv, templ_hsv, matched, cv::TM_CCOEFF_NORMED);
|
||||
|
||||
double minVal = 0, maxVal = 0;
|
||||
cv::Point minLoc, maxLoc;
|
||||
@@ -82,7 +83,7 @@ std::tuple<int, double, asst::Rect> Identify::findImage(const Mat& cur, const st
|
||||
auto&& templ_mat = m_mat_map.at(templ);
|
||||
auto&& [value, point] = findImage(cur, templ_mat);
|
||||
cv::Rect raw_rect(point.x, point.y, templ_mat.cols, templ_mat.rows);
|
||||
|
||||
|
||||
if (m_use_cache && value >= threshold) {
|
||||
m_cache_map.emplace(templ, std::make_pair(raw_rect, image2Hist(cur(raw_rect))));
|
||||
}
|
||||
|
||||
98
MeoAssistance/src/Updater.cpp
Normal file
@@ -0,0 +1,98 @@
|
||||
#include "Updater.h"
|
||||
|
||||
#include <stdio.h>
|
||||
#include <Windows.h>
|
||||
#include <WinInet.h>
|
||||
|
||||
#include "json.h"
|
||||
#include "AsstDef.h"
|
||||
#include "Logger.hpp"
|
||||
|
||||
using namespace asst;
|
||||
|
||||
const std::string Updater::GithubReleaseLastestApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
|
||||
const std::string Updater::GithubReleaseApiUrl = "https://api.github.com/repos/MistEO/MeoAssistance/releases/latest";
|
||||
|
||||
Updater& Updater::instance()
|
||||
{
|
||||
static Updater unique_instance;
|
||||
return unique_instance;
|
||||
}
|
||||
|
||||
bool Updater::has_new_version()
|
||||
{
|
||||
auto req_ret = request_github_api();
|
||||
if (!req_ret) {
|
||||
DebugTraceInfo("Requeset Error");
|
||||
return false;
|
||||
}
|
||||
auto parse_ret = json::parser::parse(req_ret.value());
|
||||
if (!parse_ret) {
|
||||
DebugTraceInfo("Parse Error");
|
||||
return false;
|
||||
}
|
||||
|
||||
json::value root = std::move(parse_ret).value();
|
||||
|
||||
std::unique_lock<std::mutex> lock(m_mutex);
|
||||
try {
|
||||
m_lastest_version.tag_name = root["tag_name"].as_string();
|
||||
m_lastest_version.html_url = root["html_url"].as_string();
|
||||
m_lastest_version.author_name = root["author"]["login"].as_string();
|
||||
m_lastest_version.created_time = root["created_at"].as_string();
|
||||
m_lastest_version.body = root["body"].as_string();
|
||||
|
||||
auto assets = root["assets"].as_array();
|
||||
if (assets.size() == 1) {
|
||||
m_lastest_version.down_url = assets[0]["browser_download_url"].as_string();
|
||||
}
|
||||
}
|
||||
catch (json::exception& exp) {
|
||||
DebugTraceError("Json Error", exp.what());
|
||||
return false;
|
||||
}
|
||||
|
||||
if (m_lastest_version.tag_name > Version) {
|
||||
m_has_new_version = true;
|
||||
return true;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
const VersionInfo & Updater::get_version_info() const noexcept
|
||||
{
|
||||
return m_lastest_version;
|
||||
}
|
||||
|
||||
std::optional<std::string> Updater::request_github_api()
|
||||
{
|
||||
HINTERNET h_session = ::InternetOpenA("GithubRelease", INTERNET_OPEN_TYPE_PRECONFIG, NULL, NULL, 0);
|
||||
if (h_session == NULL) {
|
||||
return std::nullopt;
|
||||
}
|
||||
HINTERNET h_http = ::InternetOpenUrlA(h_session, GithubReleaseLastestApiUrl.c_str(), NULL, 0, INTERNET_FLAG_DONT_CACHE, 0);
|
||||
if (h_http == NULL) {
|
||||
return std::nullopt;
|
||||
}
|
||||
std::string response;
|
||||
DWORD buff_size = 4096;
|
||||
char *buffer = new char[buff_size];
|
||||
DWORD number = 1;
|
||||
while (number > 0) {
|
||||
memset(buffer, 0, buff_size);
|
||||
InternetReadFile(h_http, buffer, buff_size, &number);
|
||||
if (number != 0) {
|
||||
response += std::string(buffer, number);
|
||||
}
|
||||
}
|
||||
delete[] buffer;
|
||||
buffer = NULL;
|
||||
InternetCloseHandle(h_http);
|
||||
h_http = NULL;
|
||||
InternetCloseHandle(h_session);
|
||||
h_session = NULL;
|
||||
|
||||
return response;
|
||||
}
|
||||
@@ -2,21 +2,22 @@
|
||||
|
||||
#include <vector>
|
||||
#include <utility>
|
||||
#include <ctime>
|
||||
#include <algorithm>
|
||||
#include <chrono>
|
||||
|
||||
#include <stdint.h>
|
||||
#include <WinUser.h>
|
||||
|
||||
#include "Configer.h"
|
||||
#include "AsstDef.h"
|
||||
#include "Logger.hpp"
|
||||
|
||||
using namespace asst;
|
||||
|
||||
WinMacro::WinMacro(const std::string& simulator_name, HandleType type)
|
||||
: m_simulator_name(simulator_name),
|
||||
m_handle_type(type),
|
||||
m_rand_engine(time(NULL))
|
||||
m_rand_engine(std::chrono::system_clock::now().time_since_epoch().count())
|
||||
{
|
||||
findHandle();
|
||||
}
|
||||
@@ -40,12 +41,13 @@ bool WinMacro::findHandle()
|
||||
handle_vec = info.view;
|
||||
break;
|
||||
case HandleType::Control:
|
||||
m_xOffset = info.xOffset;
|
||||
m_yOffset = info.yOffset;
|
||||
m_is_adb = info.is_adb;
|
||||
m_x_offset = info.x_offset;
|
||||
m_y_offset = info.y_offset;
|
||||
handle_vec = info.control;
|
||||
break;
|
||||
default:
|
||||
DebugTraceError("Handle type error!: %d", m_handle_type);
|
||||
DebugTraceError("Handle type error!", m_handle_type);
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -77,8 +79,30 @@ bool WinMacro::findHandle()
|
||||
window_wbuff = NULL;
|
||||
}
|
||||
}
|
||||
if (m_is_adb && m_handle != NULL) {
|
||||
|
||||
DebugTrace("Handle: 0x%x, Name: %s, Type: %d", m_handle, m_simulator_name.c_str(), m_handle_type);
|
||||
DWORD pid = 0;
|
||||
::GetWindowThreadProcessId(m_handle, &pid);
|
||||
HANDLE handle = ::OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, pid);
|
||||
LPSTR path_buff = new CHAR[MAX_PATH];
|
||||
memset(path_buff, 0, MAX_PATH);
|
||||
DWORD buff_size = MAX_PATH;
|
||||
QueryFullProcessImageNameA(handle, 0, path_buff, &buff_size);
|
||||
std::string adb_dir = path_buff;
|
||||
if (path_buff != NULL) {
|
||||
delete[] path_buff;
|
||||
path_buff = NULL;
|
||||
}
|
||||
size_t pos = adb_dir.find_last_of('\\') + 1;
|
||||
adb_dir = adb_dir.substr(0, pos);
|
||||
adb_dir = '"' + StringReplaceAll(info.adb.path, "[EmulatorPath]", adb_dir) + '"';
|
||||
std::string connect_cmd = adb_dir + info.adb.connect;
|
||||
int ret = system(connect_cmd.c_str());
|
||||
DebugTrace("Call", connect_cmd, "—— ret", ret);
|
||||
|
||||
m_click_cmd = adb_dir + info.adb.click;
|
||||
}
|
||||
DebugTrace("Handle:", m_handle, "Name:", m_simulator_name, "Type:", m_handle_type);
|
||||
|
||||
if (m_handle != NULL) {
|
||||
return true;
|
||||
@@ -111,7 +135,7 @@ bool WinMacro::showWindow()
|
||||
return false;
|
||||
}
|
||||
|
||||
return ::ShowWindow(m_handle, SW_SHOW);
|
||||
return ::ShowWindow(m_handle, SW_RESTORE);
|
||||
}
|
||||
|
||||
bool WinMacro::hideWindow()
|
||||
@@ -163,17 +187,29 @@ bool WinMacro::click(const Point& p)
|
||||
return false;
|
||||
}
|
||||
|
||||
int x = (p.x + m_xOffset) / getScreenScale();
|
||||
int y = (p.y + m_yOffset) / getScreenScale();
|
||||
|
||||
DebugTrace("click, raw: %d, %d, cor: %d, %d", p.x, p.y, x, y);
|
||||
|
||||
LPARAM lparam = MAKELPARAM(x, y);
|
||||
if (m_is_adb) {
|
||||
int x = (p.x + m_x_offset);
|
||||
int y = (p.y + m_y_offset);
|
||||
std::string cur_cmd = StringReplaceAll(m_click_cmd, "[x]", std::to_string(x));
|
||||
cur_cmd = StringReplaceAll(cur_cmd, "[y]", std::to_string(y));
|
||||
int ret = system(cur_cmd.c_str());
|
||||
DebugTrace("Call", cur_cmd, "—— ret", ret);
|
||||
return !ret;
|
||||
}
|
||||
else {
|
||||
int x = (p.x + m_x_offset) / getScreenScale();
|
||||
int y = (p.y + m_y_offset) / getScreenScale();
|
||||
DebugTrace("Click, raw:", p.x, p.y, "corr:", x, y);
|
||||
|
||||
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
|
||||
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
|
||||
LPARAM lparam = MAKELPARAM(x, y);
|
||||
|
||||
return true;
|
||||
::SendMessage(m_handle, WM_LBUTTONDOWN, MK_LBUTTON, lparam);
|
||||
::SendMessage(m_handle, WM_LBUTTONUP, 0, lparam);
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
bool WinMacro::clickRange(const Rect& rect)
|
||||
@@ -242,10 +278,12 @@ cv::Mat WinMacro::getImage(const Rect& rect)
|
||||
DeleteDC(memDC);
|
||||
ReleaseDC(m_handle, pDC);
|
||||
|
||||
#ifdef _DEBUG
|
||||
std::string filename = Configer::getCurDir() + "\\test.bmp";
|
||||
cv::imwrite(filename, dst_mat);
|
||||
#endif
|
||||
/*
|
||||
#ifdef _DEBUG
|
||||
std::string filename = GetCurrentDir() + "\\print.bmp";
|
||||
cv::imwrite(filename, dst_mat);
|
||||
#endif
|
||||
*/
|
||||
|
||||
return dst_mat;
|
||||
}
|
||||
@@ -5,15 +5,20 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:MeoAsstGui"
|
||||
mc:Ignorable="d"
|
||||
Title="MeoAssistance-明日方舟辅助" Height="500" Width="400">
|
||||
Title="Meo明日方舟辅助" Height="500" Width="400" Loaded="OnLoaded">
|
||||
<Grid>
|
||||
<CheckBox x:Name="checkBox_useMedicine" Content="吃理智药" HorizontalAlignment="Left" Margin="50,100,0,0" VerticalAlignment="Top" Checked="checkBox_useMedicine_Checked" Unchecked="checkBox_useMedicine_Checked" IsChecked="True"/>
|
||||
<CheckBox x:Name="checkBox_useStone" Content="吃石头" HorizontalAlignment="Left" Margin="50,150,0,0" VerticalAlignment="Top" Checked="checkBox_useStone_Checked" Unchecked="checkBox_useStone_Checked"/>
|
||||
<TextBox x:Name="textBox_useStone" HorizontalAlignment="Left" Height="23" Margin="112,148,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_useStone_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
|
||||
<Label x:Name="label_stoneNumber" Content="颗" HorizontalAlignment="Left" Margin="164,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-5.771,-6.291"/>
|
||||
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
|
||||
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,280,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
|
||||
<Button x:Name="button_startSanity" Content="开始刷理智" HorizontalAlignment="Left" Margin="50,270,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_startSanity"/>
|
||||
<Button x:Name="button_stop" Content="停止" HorizontalAlignment="Left" Margin="50,350,0,0" VerticalAlignment="Top" Width="300" Height="50" Click="button_Click_stop"/>
|
||||
<Label x:Name="catch_status" Content="" HorizontalAlignment="Left" Margin="50,30,0,0" VerticalAlignment="Top"/>
|
||||
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,200,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
|
||||
<Button x:Name="button_visit" Content="访问基建" HorizontalAlignment="Left" Margin="230,270,0,0" VerticalAlignment="Top" Width="120" Height="50" Click="button_Click_visit"/>
|
||||
<Label x:Name="exec_times" Content="" HorizontalAlignment="Left" Margin="230,30,0,0" VerticalAlignment="Top"/>
|
||||
<Label x:Name="stone_times" Content="" HorizontalAlignment="Left" Margin="230,144,0,0" VerticalAlignment="Top" RenderTransformOrigin="-0.702,0.403"/>
|
||||
<CheckBox x:Name="checkBox_maxTimes" Content="指定次数" HorizontalAlignment="Left" Margin="50,200,0,0" VerticalAlignment="Top" Checked="checkBox_maxTimes_Checked" Unchecked="checkBox_maxTimes_Checked"/>
|
||||
<TextBox x:Name="textBox_maxTimes" HorizontalAlignment="Left" Height="23" Margin="124,198,0,0" TextWrapping="Wrap" Text="0" VerticalAlignment="Top" Width="47" TextChanged="textBox_maxTimes_TextChanged" InputMethod.IsInputMethodEnabled="False"/>
|
||||
<Label x:Name="label" Content="次" HorizontalAlignment="Left" Margin="176,193,0,0" VerticalAlignment="Top" RenderTransformOrigin="0.397,-0.745"/>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -13,6 +13,7 @@ using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows.Threading;
|
||||
|
||||
namespace MeoAsstGui
|
||||
{
|
||||
@@ -22,38 +23,56 @@ namespace MeoAsstGui
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
|
||||
[DllImport("MeoAssistance.dll")] static public extern IntPtr CreateAsst();
|
||||
[DllImport("MeoAssistance.dll")] static public extern void DestoryAsst(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static public extern bool AsstCatchSimulator(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static public extern void AsstStart(IntPtr ptr, string task);
|
||||
[DllImport("MeoAssistance.dll")] static public extern void AsstStop(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static public extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
|
||||
[DllImport("MeoAssistance.dll")] static private extern IntPtr CreateAsst();
|
||||
[DllImport("MeoAssistance.dll")] static private extern void DestoryAsst(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static private extern bool AsstCatchSimulator(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static private extern void AsstStart(IntPtr ptr, string task);
|
||||
[DllImport("MeoAssistance.dll")] static private extern void AsstStop(IntPtr ptr);
|
||||
[DllImport("MeoAssistance.dll")] static private extern bool AsstSetParam(IntPtr p_asst, string type, string param, string value);
|
||||
[DllImport("MeoAssistance.dll")]
|
||||
static private extern bool AsstGetParam(
|
||||
IntPtr p_asst, string type, string param,
|
||||
[In, Out] StringBuilder lp_string, int buffer_size);
|
||||
|
||||
|
||||
private IntPtr p_asst;
|
||||
UpdateDialog updateDialog;
|
||||
private DispatcherTimer update_times = new DispatcherTimer();
|
||||
|
||||
public MainWindow()
|
||||
{
|
||||
InitializeComponent();
|
||||
|
||||
p_asst = CreateAsst();
|
||||
}
|
||||
~MainWindow()
|
||||
{
|
||||
DestoryAsst(p_asst);
|
||||
}
|
||||
|
||||
private void OnLoaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
updateDialog = new UpdateDialog();
|
||||
updateDialog.CheckUpdateAndShowDialog();
|
||||
updateDialog.Close();
|
||||
|
||||
p_asst = CreateAsst();
|
||||
update_times.Tick += new EventHandler(updateExecTimes);
|
||||
update_times.Interval = TimeSpan.FromSeconds(1);
|
||||
}
|
||||
private void button_Click_startSanity(object sender, RoutedEventArgs e)
|
||||
{
|
||||
bool catched = AsstCatchSimulator(p_asst);
|
||||
catch_status.Content = "捕获模拟器窗口:" + catched;
|
||||
AsstStart(p_asst, "SanityBegin");
|
||||
update_times.Start();
|
||||
}
|
||||
|
||||
private void button_Click_stop(object sender, RoutedEventArgs e)
|
||||
{
|
||||
AsstStop(p_asst);
|
||||
catch_status.Content = "";
|
||||
update_times.Stop();
|
||||
exec_times.Content = "";
|
||||
stone_times.Content = "";
|
||||
}
|
||||
|
||||
private void checkBox_useMedicine_Checked(object sender, RoutedEventArgs e)
|
||||
@@ -70,18 +89,25 @@ namespace MeoAsstGui
|
||||
|
||||
private void textBox_useStone_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", textBox_useStone.Text);
|
||||
if (checkBox_useStone.IsChecked == true)
|
||||
{
|
||||
String text = textBox_useStone.Text != String.Empty ? textBox_useStone.Text : "0";
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", text);
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBox_useStone_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (checkBox_useMedicine.IsChecked == true)
|
||||
if (checkBox_useStone.IsChecked == true)
|
||||
{
|
||||
AsstSetParam(p_asst, "task.type", "UseStone", "doNothing");
|
||||
String text = textBox_useStone.Text != String.Empty ? textBox_useStone.Text : "0";
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", text);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsstSetParam(p_asst, "task.type", "UseStone", "stop");
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StoneConfirm", "0");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,5 +117,41 @@ namespace MeoAsstGui
|
||||
catch_status.Content = "捕获模拟器窗口:" + catched;
|
||||
AsstStart(p_asst, "VisitBegin");
|
||||
}
|
||||
|
||||
private void updateExecTimes(object sender, EventArgs e)
|
||||
{
|
||||
StringBuilder buff_start = new StringBuilder(16);
|
||||
AsstGetParam(p_asst, "task.execTimes", "StartButton2", buff_start, 16);
|
||||
exec_times.Content = "已开始行动 " + buff_start + " 次";
|
||||
|
||||
if (checkBox_useStone.IsChecked == true)
|
||||
{
|
||||
StringBuilder buff_stone = new StringBuilder(16);
|
||||
AsstGetParam(p_asst, "task.execTimes", "StoneConfirm", buff_stone, 16);
|
||||
stone_times.Content = "已碎石 " + buff_stone + " 个";
|
||||
}
|
||||
}
|
||||
|
||||
private void checkBox_maxTimes_Checked(object sender, RoutedEventArgs e)
|
||||
{
|
||||
if (checkBox_maxTimes.IsChecked == true)
|
||||
{
|
||||
String text = textBox_maxTimes.Text != String.Empty ? textBox_maxTimes.Text : "0";
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", text);
|
||||
}
|
||||
else
|
||||
{
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", int.MaxValue.ToString());
|
||||
}
|
||||
}
|
||||
|
||||
private void textBox_maxTimes_TextChanged(object sender, TextChangedEventArgs e)
|
||||
{
|
||||
if (checkBox_maxTimes.IsChecked == true)
|
||||
{
|
||||
String text = textBox_maxTimes.Text != String.Empty ? textBox_maxTimes.Text : "0";
|
||||
AsstSetParam(p_asst, "task.maxTimes", "StartButton1", text);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,7 @@
|
||||
<UpdateRequired>false</UpdateRequired>
|
||||
<MapFileExtensions>true</MapFileExtensions>
|
||||
<ApplicationRevision>0</ApplicationRevision>
|
||||
<ApplicationVersion>1.0.0.%2a</ApplicationVersion>
|
||||
<ApplicationVersion>0.2.0.0</ApplicationVersion>
|
||||
<UseApplicationTrust>false</UseApplicationTrust>
|
||||
<BootstrapperEnabled>true</BootstrapperEnabled>
|
||||
</PropertyGroup>
|
||||
@@ -54,6 +54,9 @@
|
||||
<PropertyGroup>
|
||||
<RunPostBuildEvent>Always</RunPostBuildEvent>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<ApplicationIcon>favicon.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
<ItemGroup>
|
||||
<Reference Include="System" />
|
||||
<Reference Include="System.Data" />
|
||||
@@ -75,6 +78,9 @@
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
</ApplicationDefinition>
|
||||
<Compile Include="UpdateDialog.xaml.cs">
|
||||
<DependentUpon>UpdateDialog.xaml</DependentUpon>
|
||||
</Compile>
|
||||
<Page Include="MainWindow.xaml">
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
<SubType>Designer</SubType>
|
||||
@@ -87,6 +93,10 @@
|
||||
<DependentUpon>MainWindow.xaml</DependentUpon>
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Page Include="UpdateDialog.xaml">
|
||||
<SubType>Designer</SubType>
|
||||
<Generator>MSBuild:Compile</Generator>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Compile Include="Properties\AssemblyInfo.cs">
|
||||
@@ -126,6 +136,9 @@
|
||||
<Install>false</Install>
|
||||
</BootstrapperPackage>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Resource Include="favicon.ico" />
|
||||
</ItemGroup>
|
||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||
<PropertyGroup>
|
||||
<PostBuildEvent>xcopy /e /y /i $(SolutionDir)resource $(TargetDir)resource</PostBuildEvent>
|
||||
|
||||
16
MeoAsstGui/UpdateDialog.xaml
Normal file
@@ -0,0 +1,16 @@
|
||||
<Window x:Class="MeoAsstGui.UpdateDialog"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:local="clr-namespace:MeoAsstGui"
|
||||
mc:Ignorable="d"
|
||||
Title="有新版本" Height="500" Width="400">
|
||||
<Grid>
|
||||
<Label x:Name="label_tag" Content="" HorizontalAlignment="Center" Margin="10,25,10.333,0" VerticalAlignment="Top" Height="50" Width="373" FontSize="24"/>
|
||||
<Label x:Name="label_body" Content="" HorizontalAlignment="Left" Margin="50,80,0,0" VerticalAlignment="Top" Height="281" Width="290" FontSize="16"/>
|
||||
<Button x:Name="button_confirm" Content="前往下载" HorizontalAlignment="Left" Margin="50,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_confirm_Click"/>
|
||||
<Button x:Name="button_cancer" Content="下次一定" HorizontalAlignment="Left" Margin="220,366,0,0" VerticalAlignment="Top" Width="120" Height="60" Click="button_cancer_Click"/>
|
||||
|
||||
</Grid>
|
||||
</Window>
|
||||
69
MeoAsstGui/UpdateDialog.xaml.cs
Normal file
@@ -0,0 +1,69 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Shapes;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace MeoAsstGui
|
||||
{
|
||||
/// <summary>
|
||||
/// UpdateDialog.xaml 的交互逻辑
|
||||
/// </summary>
|
||||
public partial class UpdateDialog : Window
|
||||
{
|
||||
[DllImport("MeoAssistance.dll")]
|
||||
static private extern bool CheckVersionUpdate(
|
||||
[In, Out] StringBuilder tag, int tag_bufsize,
|
||||
[In, Out] StringBuilder html_url, int html_bufsize,
|
||||
[In, Out] StringBuilder body, int body_bufsize);
|
||||
public UpdateDialog()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
|
||||
private String m_htmlUrl;
|
||||
|
||||
public void CheckUpdateAndShowDialog()
|
||||
{
|
||||
StringBuilder tag = new StringBuilder(64);
|
||||
StringBuilder html_url = new StringBuilder(512);
|
||||
StringBuilder body = new StringBuilder(4096);
|
||||
|
||||
bool ret = CheckVersionUpdate(tag, 64, html_url, 512, body, 4096);
|
||||
if (!ret)
|
||||
{
|
||||
return;
|
||||
}
|
||||
label_tag.Content = "新版本:" + tag;
|
||||
byte[] buffer1 = Encoding.Default.GetBytes(body.ToString());
|
||||
byte[] buffer2 = Encoding.Convert(Encoding.UTF8, Encoding.Default, buffer1, 0, buffer1.Length);
|
||||
string strBuffer = Encoding.Default.GetString(buffer2, 0, buffer2.Length);
|
||||
strBuffer = strBuffer.Replace("\\r\\n", "\r\n");
|
||||
int len = strBuffer.Length > 128 ? 128 : strBuffer.Length;
|
||||
label_body.Content = strBuffer.Substring(0, len) + "\n......";
|
||||
|
||||
m_htmlUrl = html_url.ToString();
|
||||
ShowDialog();
|
||||
}
|
||||
|
||||
private void button_cancer_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
private void button_confirm_Click(object sender, RoutedEventArgs e)
|
||||
{
|
||||
System.Diagnostics.Process.Start(m_htmlUrl);
|
||||
Close();
|
||||
}
|
||||
}
|
||||
}
|
||||
BIN
MeoAsstGui/favicon.ico
Normal file
|
After Width: | Height: | Size: 66 KiB |
43
README.md
@@ -4,20 +4,18 @@ A game assistance for Arknights
|
||||
|
||||
一款明日方舟的游戏辅助,供PC端安卓模拟器使用,龟速开发中……
|
||||
|
||||

|
||||

|
||||
|
||||
## 功能介绍
|
||||
|
||||
- 支持自动刷完理智
|
||||
- 支持自动吃完体力药
|
||||
- 支持根据设置自动吃石头
|
||||
- 刷完后程序会自动停止
|
||||
- 自动刷完理智
|
||||
- 可设置是否吃完理智药
|
||||
- 可设置是否吃石头级数量
|
||||
- 可设置刷的次数
|
||||
- 代理失败会自动放弃本次行动
|
||||
- 支持自动访问好友基建
|
||||
- 所有操作,都是点击按钮内随机位置,且模拟泊松分布,不会像鼠标宏一样一直是同一个点,没有封号风险
|
||||
~~(虽然好像也没听说过谁用鼠标宏被封号的)~~
|
||||
- 模拟器窗口可以被遮挡,即使全屏看视频、玩游戏,也完全不影响辅助运行
|
||||
~~(但是模拟器还是不能最小化)~~
|
||||
- 支持自动访问好友基建,访问完了还会贴心的帮你点进信用商店~
|
||||
- 所有操作,都是点击按钮内随机位置,且支持设置随机延时,没有封号风险
|
||||
- 模拟器窗口可以被遮挡,即使全屏看视频、玩游戏,也不影响辅助运行
|
||||
- 支持多款主流模拟器
|
||||
- 自适应分辨率及屏幕缩放
|
||||
- 未来更多功能见[Todo](#Todo)
|
||||
@@ -44,9 +42,14 @@ A game assistance for Arknights
|
||||
|
||||
兼容,但需要手动设置分辨率:设置中心——引擎设置——分辨率设置——1280x720——保存后重启模拟器
|
||||
|
||||
#### MuMu手游助手 && MuMu模拟器
|
||||
#### MuMu模拟器
|
||||
|
||||
不兼容,MuMu所有的窗口句柄均不响应SendMessage鼠标消息,但官方提供了adb的方式进行控制,有时间再做
|
||||
MuMu是个奇葩,它的所有的窗口句柄均不响应SendMessage鼠标消息
|
||||
|
||||
- MuMu模拟器
|
||||
非常勉强的使用adb控制的方式,兼容了刷理智的功能,需要在模拟器设置里把分辨率设置成1280x720。建议使用"Sanity.exe",而不是图形化界面,因为adb控制台窗口会一直往出弹
|
||||
- MuMu手游助手(星云引擎)
|
||||
不兼容,可见未来内也想不到什么好主意来兼容的
|
||||
|
||||
## 使用说明
|
||||
|
||||
@@ -69,6 +72,12 @@ A game assistance for Arknights
|
||||
2. 点击"访问基建"
|
||||
3. 达到10次上限,或者所有可访问的好友都访问完了,就会自动停的
|
||||
|
||||
### 设置操作延时
|
||||
|
||||
请手动修改`resource\config.json`文件中,`options`.`controlDelayRange`字段的值,格式为`[最小延时, 最大延时]`,单位为毫秒,例如想设置3~5秒的随机延时,即设置为`[ 3000, 5000]` 即可。文件保存后请重新打开程序。
|
||||
|
||||

|
||||
|
||||
## Todo
|
||||
|
||||
~~在做了在做了.jpg~~
|
||||
@@ -78,7 +87,7 @@ A game assistance for Arknights
|
||||
- [x] 基本图形化界面
|
||||
- [ ] 图形化界面进一步完善
|
||||
- [ ] 日志打印,错误提示
|
||||
- [ ] 使模拟器窗口不可见的按钮
|
||||
- [ ] 操作随机延时支持设置
|
||||
- [ ] 刷理智
|
||||
- [x] 支持剿灭
|
||||
- [x] 支持使模拟器窗口不可见
|
||||
@@ -86,8 +95,10 @@ A game assistance for Arknights
|
||||
- [x] 代理失败的情况
|
||||
- [x] 支持等级提升
|
||||
- [x] 支持自动勾选代理指挥
|
||||
- [ ] 支持刷指定次数
|
||||
- [x] 支持刷指定次数
|
||||
- [x] 自动吃石头(根据设置,指定数量)
|
||||
- [x] 操作随机延时
|
||||
- [ ] 指定刷XX个某材料
|
||||
- [ ] 支持凌晨4点更新数据
|
||||
- [ ] 结束界面自动截图,可用于上传企鹅物流
|
||||
- [ ] 持续监视理智,一有就自动刷掉
|
||||
@@ -100,9 +111,13 @@ A game assistance for Arknights
|
||||
- [x] 更换算法为模板匹配找图,而不是当前的区域相似度对比
|
||||
- [x] 优化算法效率,添加缓存功能
|
||||
- [x] 优化任务队列,减少不必要的计算
|
||||
- [ ] 掉落材料计数
|
||||
- [ ] 窗口分辨率自适应
|
||||
- [ ] 进一步优化任务队列效率
|
||||
- [x] 其他
|
||||
- [x] 尝试减小程序体积
|
||||
- [x] 检查程序更新
|
||||
- [ ] 程序自动更新
|
||||
|
||||
|
||||
## 致谢
|
||||
|
||||
BIN
README/1.png
|
Before Width: | Height: | Size: 19 KiB |
@@ -1,9 +1,18 @@
|
||||
#include "Assistance.h"
|
||||
#include "Updater.h"
|
||||
#include "Logger.hpp"
|
||||
|
||||
int main(int argc, char** argv)
|
||||
{
|
||||
using namespace asst;
|
||||
|
||||
bool up = Updater::instance().has_new_version();
|
||||
if (up) {
|
||||
auto && info = Updater::instance().get_version_info();
|
||||
std::cout << "ÓÐа汾£º" << info.tag_name << std::endl;
|
||||
std::cout << "µØÖ·£º" << info.html_url << std::endl;
|
||||
}
|
||||
|
||||
Assistance asst;
|
||||
|
||||
auto ret = asst.setSimulator();
|
||||
@@ -13,7 +22,7 @@ int main(int argc, char** argv)
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
DebugTraceInfo("Find Simulator: %s", ret->c_str());
|
||||
DebugTraceInfo("Find Simulator:", ret.value());
|
||||
}
|
||||
|
||||
DebugTraceInfo("Start");
|
||||
|
||||
2
meojson
BIN
readme/controlDelayRange.png
Normal file
|
After Width: | Height: | Size: 33 KiB |
BIN
readme/gui.png
Normal file
|
After Width: | Height: | Size: 25 KiB |
BIN
resource/CollectCredit.png
Normal file
|
After Width: | Height: | Size: 4.5 KiB |
BIN
resource/CreditStore.png
Normal file
|
After Width: | Height: | Size: 19 KiB |
BIN
resource/Loading.png
Normal file
|
After Width: | Height: | Size: 453 KiB |
BIN
resource/Mall.png
Normal file
|
After Width: | Height: | Size: 23 KiB |
BIN
resource/PopupCancel.png
Normal file
|
After Width: | Height: | Size: 77 KiB |
BIN
resource/PopupConfirm.png
Normal file
|
After Width: | Height: | Size: 57 KiB |
|
Before Width: | Height: | Size: 383 KiB After Width: | Height: | Size: 343 KiB |
|
Before Width: | Height: | Size: 4.2 KiB After Width: | Height: | Size: 3.5 KiB |
@@ -1,11 +1,9 @@
|
||||
{
|
||||
"version": "0.3",
|
||||
"version": "0.4",
|
||||
"options": {
|
||||
"delay": {
|
||||
"type": "fixedTime",
|
||||
"fixedTime": 2000
|
||||
},
|
||||
"cache": true
|
||||
"identifyCache": true,
|
||||
"identifyDelay": 1000,
|
||||
"controlDelayRange": [ 0, 0 ]
|
||||
},
|
||||
"handle": {
|
||||
"BlueStacks": {
|
||||
@@ -147,6 +145,64 @@
|
||||
"height": 769,
|
||||
"xOffset": 0,
|
||||
"yOffset": -42
|
||||
},
|
||||
"MuMuAsst": {
|
||||
"window": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon",
|
||||
"window": "明日方舟 - 星云引擎"
|
||||
}
|
||||
],
|
||||
"view": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon",
|
||||
"window": "明日方舟 - 星云引擎"
|
||||
}
|
||||
],
|
||||
"control": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon_DELETE",
|
||||
"window": "明日方舟 - 星云引擎_DELETE"
|
||||
}
|
||||
],
|
||||
"adbControl": {
|
||||
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
|
||||
"connect": " connect 127.0.0.1:7555",
|
||||
"click": " shell input tap [x] [y]"
|
||||
},
|
||||
"width": 1280,
|
||||
"height": 809,
|
||||
"xOffset": 0,
|
||||
"yOffset": -36
|
||||
},
|
||||
"MuMuEmulator": {
|
||||
"window": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon",
|
||||
"window": "明日方舟 - MuMu模拟器"
|
||||
}
|
||||
],
|
||||
"view": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon",
|
||||
"window": "明日方舟 - MuMu模拟器"
|
||||
}
|
||||
],
|
||||
"control": [
|
||||
{
|
||||
"class": "Qt5QWindowIcon",
|
||||
"window": "明日方舟 - MuMu模拟器"
|
||||
}
|
||||
],
|
||||
"adbControl": {
|
||||
"path": "[EmulatorPath]..\\vmonitor\\bin\\adb_server.exe",
|
||||
"connect": " connect 127.0.0.1:7555",
|
||||
"click": " shell input tap [x] [y]"
|
||||
},
|
||||
"width": 1280,
|
||||
"height": 809,
|
||||
"xOffset": 0,
|
||||
"yOffset": -36
|
||||
}
|
||||
},
|
||||
"tasks": {
|
||||
@@ -167,7 +223,7 @@
|
||||
},
|
||||
"UsePrts": {
|
||||
"filename": "UsePrts.png",
|
||||
"threshold": 0.97,
|
||||
"threshold": 0.8,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"StartButton1"
|
||||
@@ -175,7 +231,7 @@
|
||||
},
|
||||
"StartButton1": {
|
||||
"filename": "StartButton1.png",
|
||||
"threshold": 0.94,
|
||||
"threshold": 0.8,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"StartButton2",
|
||||
@@ -184,18 +240,17 @@
|
||||
]
|
||||
},
|
||||
"StartButton2": {
|
||||
"id": 2,
|
||||
"filename": "StartButton2.png",
|
||||
"threshold": 0.99,
|
||||
"type": "clickSelf",
|
||||
"rearDelay": 20000,
|
||||
"next": [
|
||||
"PRTS"
|
||||
]
|
||||
},
|
||||
"PRTS": {
|
||||
"filename": "PRTS.png",
|
||||
"threshold": 0.98,
|
||||
"type": "doNothing",
|
||||
"rearDelay": 5000,
|
||||
"next": [
|
||||
"PRTS",
|
||||
"PrtsErrorConfirm",
|
||||
@@ -205,15 +260,28 @@
|
||||
"Random": {
|
||||
"filename": "",
|
||||
"threshold": 0,
|
||||
"type": "clickRand",
|
||||
"type": "clickRect",
|
||||
"specificArea": [
|
||||
1100,
|
||||
700,
|
||||
150,
|
||||
30
|
||||
],
|
||||
"next": [
|
||||
"Loading",
|
||||
"StartButton1",
|
||||
"Random"
|
||||
]
|
||||
},
|
||||
"Loading": {
|
||||
"filename": "Loading.png",
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"StartButton1"
|
||||
]
|
||||
},
|
||||
"UseMedicine": {
|
||||
"filename": "UseMedicine.png",
|
||||
"threshold": 0.99,
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"MedicineConfirm"
|
||||
@@ -221,15 +289,14 @@
|
||||
},
|
||||
"MedicineConfirm": {
|
||||
"filename": "MedicineConfirm.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"reduceOtherTimes": [ "StartButton1" ],
|
||||
"next": [
|
||||
"StartButton1"
|
||||
]
|
||||
},
|
||||
"UseStone": {
|
||||
"filename": "UseStone.png",
|
||||
"threshold": 0.99,
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"StoneConfirm"
|
||||
@@ -237,16 +304,15 @@
|
||||
},
|
||||
"StoneConfirm": {
|
||||
"filename": "MedicineConfirm.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"maxTimes": 0,
|
||||
"reduceOtherTimes": [ "StartButton1" ],
|
||||
"next": [
|
||||
"StartButton1"
|
||||
]
|
||||
},
|
||||
"PrtsErrorConfirm": {
|
||||
"filename": "PrtsErrorConfirm.png",
|
||||
"threshold": 0.98,
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"AbandonAction"
|
||||
@@ -254,8 +320,8 @@
|
||||
},
|
||||
"AbandonAction": {
|
||||
"filename": "AbandonAction.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"reduceOtherTimes": [ "StartButton1", "StartButton2", "Loading" ],
|
||||
"next": [
|
||||
"Random"
|
||||
]
|
||||
@@ -270,21 +336,19 @@
|
||||
"StartToVisit",
|
||||
"VisitNext",
|
||||
"VisitNextBlack",
|
||||
"Return"
|
||||
"ReturnToFriends"
|
||||
]
|
||||
},
|
||||
"Return": {
|
||||
"ReturnToFriends": {
|
||||
"filename": "Return.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"Friends",
|
||||
"Return"
|
||||
"ReturnToFriends"
|
||||
]
|
||||
},
|
||||
"Friends": {
|
||||
"filename": "Friends.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"FriendsList"
|
||||
@@ -292,7 +356,6 @@
|
||||
},
|
||||
"FriendsList": {
|
||||
"filename": "FriendsList.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"StartToVisit"
|
||||
@@ -300,7 +363,6 @@
|
||||
},
|
||||
"StartToVisit": {
|
||||
"filename": "StartToVisit.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"VisitNext"
|
||||
@@ -308,23 +370,74 @@
|
||||
},
|
||||
"VisitNext": {
|
||||
"filename": "VisitNext.png",
|
||||
"threshold": 0.98,
|
||||
"type": "clickSelf",
|
||||
"threshold": 0.99,
|
||||
"maxTimes": 21,
|
||||
"exceededNext": [
|
||||
"ReturnToMall"
|
||||
],
|
||||
"next": [
|
||||
"VisitLimited",
|
||||
"VisitNext",
|
||||
"VisitNextBlack"
|
||||
]
|
||||
},
|
||||
"ReturnToMall": {
|
||||
"filename": "Return.png",
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"Mall",
|
||||
"ReturnToMall",
|
||||
"ReturnToMallConfirm"
|
||||
]
|
||||
},
|
||||
"ReturnToMallConfirm": {
|
||||
"filename": "PopupConfirm.png",
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"ReturnToMall"
|
||||
]
|
||||
},
|
||||
"Mall": {
|
||||
"filename": "Mall.png",
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"CreditStore"
|
||||
]
|
||||
},
|
||||
"CreditStore": {
|
||||
"filename": "CreditStore.png",
|
||||
"threshold": 0.89,
|
||||
"rearDelay": 1000,
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"CollectCredit",
|
||||
"Stop"
|
||||
]
|
||||
},
|
||||
"CollectCredit": {
|
||||
"filename": "CollectCredit.png",
|
||||
"type": "clickSelf",
|
||||
"next": [
|
||||
"Stop"
|
||||
]
|
||||
},
|
||||
"VisitLimited": {
|
||||
"filename": "VisitLimited.png",
|
||||
"threshold": 0.65,
|
||||
"type": "stop",
|
||||
"next": []
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"ReturnToMall"
|
||||
]
|
||||
},
|
||||
"VisitNextBlack": {
|
||||
"filename": "VisitNextBlack.png",
|
||||
"threshold": 0.98,
|
||||
"type": "doNothing",
|
||||
"next": [
|
||||
"ReturnToMall"
|
||||
]
|
||||
},
|
||||
"Stop": {
|
||||
"filename": "",
|
||||
"threshold": 0,
|
||||
"type": "stop",
|
||||
"next": []
|
||||
}
|
||||
|
||||
2
update_resource.bat
Normal file
@@ -0,0 +1,2 @@
|
||||
xcopy /e /y /i resource x64\Debug\resource
|
||||
xcopy /e /y /i resource x64\Release\resource
|
||||