feat: Add ThriftController

This commit is contained in:
shxyke
2023-10-04 09:53:16 +08:00
parent 2a2c137d82
commit a077e58719
13 changed files with 1171 additions and 1 deletions

View File

@@ -15,8 +15,10 @@ option(INSTALL_RESOURCE "install resource" OFF)
option(INSTALL_DEVEL "install development files" OFF)
option(INSTALL_THIRD_LIBS "install third party libraries" ON)
option(USE_MAADEPS "use third-party libraries built by MaaDeps" ON)
option(WITH_THRIFT "build with thrift" OFF)
include(${PROJECT_SOURCE_DIR}/cmake/utils.cmake)
include(${PROJECT_SOURCE_DIR}/cmake/thrift-gen.cmake)
if(USE_MAADEPS)
include(${PROJECT_SOURCE_DIR}/MaaDeps/maadeps.cmake)
@@ -27,7 +29,7 @@ if (MSVC)
add_compile_options("/MP")
add_compile_options("/W4;/WX")
add_compile_options("/wd4127") # conditional expression is constant
add_compile_options("/Wv:19.35.32217") # disable warning introduced after this version
add_compile_options("/Wv:19.35.32217") # disable warning introduced after this version
set(CMAKE_MSVC_RUNTIME_LIBRARY "MultiThreaded$<$<CONFIG:Debug>:Debug>DLL")
else ()
@@ -79,9 +81,17 @@ find_package(MaaDerpLearning REQUIRED)
find_package(asio REQUIRED)
find_package(ONNXRuntime)
find_package(cpr CONFIG REQUIRED)
if(WITH_THRIFT)
find_package(Thrift CONFIG REQUIRED)
endif(WITH_THRIFT)
target_link_libraries(MaaCore ${OpenCV_LIBS} MaaDerpLearning asio::asio ZLIB::ZLIB ONNXRuntime::ONNXRuntime cpr::cpr header_only_libraries)
if(WITH_THRIFT)
add_subdirectory(src/MaaThriftController)
target_link_libraries(MaaCore MaaThriftController)
endif(WITH_THRIFT)
if(WIN32)
target_link_libraries(MaaCore ws2_32)
endif()

13
MAA.sln
View File

@@ -10,6 +10,7 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MaaWpfGui", "src\MaaWpfGui\
EndProjectSection
EndProject
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MaaCore", "src\MaaCore\MaaCore.vcxproj", "{362D1E30-F5AE-4279-9985-65C27B3BA300}"
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MaaThriftController", "src\MaaThriftController\MaaThriftController.vcxproj", "{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution Items", "{11F02235-5785-408B-9651-8A4B41FF36F4}"
ProjectSection(SolutionItems) = preProject
@@ -58,6 +59,18 @@ Global
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{362D1E30-F5AE-4279-9985-65C27B3BA300}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|ARM64.ActiveCfg = Debug|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|ARM64.Build.0 = Debug|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|x64.ActiveCfg = Debug|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Debug|x64.Build.0 = Debug|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|ARM64.ActiveCfg = Release|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|ARM64.Build.0 = Release|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|x64.ActiveCfg = Release|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.Release|x64.Build.0 = Release|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|ARM64.ActiveCfg = RelWithDebInfo|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|ARM64.Build.0 = RelWithDebInfo|ARM64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|x64.ActiveCfg = RelWithDebInfo|x64
{8238EDB1-19BF-4E3B-AF5B-016120D59D7B}.RelWithDebInfo|x64.Build.0 = RelWithDebInfo|x64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|ARM64.ActiveCfg = Debug|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|ARM64.Build.0 = Debug|ARM64
{F860C043-4D86-41B6-A97E-4A75C9A6C4EC}.Debug|x64.ActiveCfg = Debug|x64

35
cmake/thrift-gen.cmake Normal file
View File

@@ -0,0 +1,35 @@
macro(GENERATE_THRIFT_LIB LIB_NAME FILENAME OUTPUTDIR SOURCES)
file(MAKE_DIRECTORY ${OUTPUTDIR})
detect_host_triplet(HOST_TRIPLET)
if(EXISTS ${PROJECT_SOURCE_DIR}/MaaDeps/vcpkg/installed/maa-${HOST_TRIPLET}/tools/thrift/thrift${CMAKE_EXECUTABLE_SUFFIX})
set(THRIFT_COMPILER ${PROJECT_SOURCE_DIR}/MaaDeps/vcpkg/installed/maa-${HOST_TRIPLET}/tools/thrift/thrift${CMAKE_EXECUTABLE_SUFFIX})
else()
find_program(THRIFT_COMPILER thrift)
endif()
if(NOT THRIFT_COMPILER)
message(FATAL_ERROR "Thrift compiler not found")
endif()
get_filename_component(THRIFT_IDL_NAME ${FILENAME} NAME_WE)
set(THRIFT_IDL_TARGET "${LIB_NAME}_${THRIFT_IDL_NAME}_idl")
set("${THRIFT_IDL_NAME}-gen-cpp"
${OUTPUTDIR}/${THRIFT_IDL_NAME}.cpp
${OUTPUTDIR}/${THRIFT_IDL_NAME}.h
${OUTPUTDIR}/${THRIFT_IDL_NAME}_types.cpp
${OUTPUTDIR}/${THRIFT_IDL_NAME}_types.h)
add_custom_command(OUTPUT ${${THRIFT_IDL_NAME}-gen-cpp}
DEPENDS ${FILENAME}
COMMAND ${THRIFT_COMPILER} --gen cpp:no_skeleton -out ${OUTPUTDIR} ${FILENAME}
VERBATIM)
add_custom_target(${THRIFT_IDL_TARGET} DEPENDS ${${THRIFT_IDL_NAME}-gen-cpp})
add_library(${LIB_NAME} STATIC ${${THRIFT_IDL_NAME}-gen-cpp})
add_dependencies(${LIB_NAME} ${THRIFT_IDL_TARGET})
set_target_properties(${LIB_NAME} PROPERTIES POSITION_INDEPENDENT_CODE ON)
target_link_libraries(${LIB_NAME} PUBLIC thrift::thrift)
target_include_directories(${LIB_NAME} PUBLIC ${OUTPUTDIR})
set(${SOURCES} ${${SOURCES}} ${GENERATED_SOURCES} PARENT_SCOPE)
endmacro(GENERATE_THRIFT_LIB)
if (WITH_THRIFT)
add_compile_definitions(WITH_THRIFT)
endif (WITH_THRIFT)

View File

@@ -24,6 +24,26 @@ function(get_osx_architecture)
endif()
endfunction()
function(detect_host_triplet outvar)
string(TOLOWER "${CMAKE_HOST_SYSTEM_NAME}" host_triplet_system)
string(TOLOWER "${CMAKE_HOST_SYSTEM_PROCESSOR}" host_triplet_arch)
if(host_triplet_system STREQUAL "darwin")
set(host_triplet_system "osx")
endif()
message("host_triplet_system: ${host_triplet_system}")
message("host_triplet_arch: ${host_triplet_arch}")
if(host_triplet_arch MATCHES "(amd64|x86_64)")
set(host_triplet_arch "x64")
elseif(host_triplet_arch MATCHES "i[3456]86")
set(host_triplet_arch "x86")
elseif(host_triplet_arch MATCHES "(aarch64|armv8l|arm64)")
set(host_triplet_arch "arm64")
else()
message(FATAL_ERROR "Unrecognized CMAKE_HOST_SYSTEM_PROCESSOR: ${CMAKE_HOST_SYSTEM_PROCESSOR}")
endif()
set(${outvar} "${host_triplet_arch}-${host_triplet_system}" PARENT_SCOPE)
endfunction()
if (APPLE)
set(CMAKE_OSX_DEPLOYMENT_TARGET 12.0)
get_osx_architecture()

View File

@@ -0,0 +1,71 @@
namespace cpp ThriftController
struct Point {
1: i32 x,
2: i32 y,
}
struct ClickParam {
1: Point point,
}
struct SwipeParam {
1: Point point1,
2: Point point2,
3: i32 duration,
}
struct TouchParam {
1: i32 contact,
2: Point point,
}
enum InputEventType {
TOUCH_DOWN = 0,
TOUCH_UP = 1,
TOUCH_MOVE = 2,
TOUCH_RESET = 3,
KEY_DOWN = 4,
KEY_UP = 5,
WAIT_MS = 6,
}
struct InputEvent {
1: InputEventType type,
2: TouchParam touch,
3: i32 key,
4: i32 wait_ms,
}
struct Size {
1: i32 width,
2: i32 height,
}
struct CustomImage {
1: Size size,
2: i32 type,
3: binary data,
}
service ThriftController {
bool connect(),
bool set_option(1: string key, 2: string value),
string get_uuid(),
CustomImage screencap(),
bool start_game(1: string activity),
bool stop_game(1: string activity),
bool click(1: ClickParam param),
bool swipe(1: SwipeParam param),
bool inject_input_events(1: list<InputEvent> events),
bool press_key(1: i32 param),
i64 get_support_features(),
Size get_screen_res(),
}

View File

@@ -0,0 +1,580 @@
#ifdef WITH_THRIFT
#include "MaaThriftController.h"
#ifdef _MSC_VER
#pragma warning(push)
#pragma warning(disable : 4245 4706)
#endif
#include <thrift/protocol/TBinaryProtocol.h>
#include <thrift/transport/TBufferTransports.h>
#include <thrift/transport/TSocket.h>
#ifdef _MSC_VER
#pragma warning(pop)
#endif
#include "Config/GeneralConfig.h"
#include "Utils/NoWarningCV.h"
asst::MaaThriftController::~MaaThriftController()
{
LogTraceFunction;
close();
}
bool asst::MaaThriftController::connect([[maybe_unused]] const std::string& adb_path,
[[maybe_unused]] const std::string& address, const std::string& config)
{
LogTraceFunction;
clear_info();
#ifdef ASST_DEBUG
if (config == "DEBUG") {
m_inited = true;
return true;
}
#endif
auto get_info_json = [&]() -> json::value {
return json::object {
{ "uuid", m_uuid },
{ "details",
json::object {
{ "config", config },
} },
};
};
auto config_error = [&]() {
json::value info = get_info_json() | json::object {
{ "what", "ConnectFailed" },
{ "why", "ConfigError" },
{ "config", config },
};
callback(AsstMsg::ConnectionInfo, info);
};
static const std::unordered_map<std::string, ThriftControllerTypeEnum> type_map = {
{ "Socket", ThriftControllerTypeEnum::MaaThriftControllerType_Socket },
{ "UnixDomainSocket", ThriftControllerTypeEnum::MaaThriftControllerType_UnixDomainSocket },
};
using namespace apache::thrift;
std::shared_ptr<transport::TSocket> socket;
auto param_json = json::parse(config);
if (!param_json.has_value()) {
json::value info = get_info_json() | json::object {
{ "what", "ConnectFailed" },
{ "why", "ConfigError" },
{ "config", config },
};
callback(AsstMsg::ConnectionInfo, info);
return false;
}
auto type = param_json->at("type").as_string();
switch (type_map.at(type)) {
case ThriftControllerTypeEnum::MaaThriftControllerType_Socket:
if (param_json->at("param").is_object()) {
auto host = param_json->at("param").at("host").as_string();
auto port = param_json->at("param").at("port").as_integer();
socket = std::make_shared<transport::TSocket>(host, port);
}
else {
config_error();
return false;
}
break;
case ThriftControllerTypeEnum::MaaThriftControllerType_UnixDomainSocket:
if (param_json->at("param").is_string()) {
auto path = param_json->at("param").as_string();
socket = std::make_shared<transport::TSocket>(path);
}
else {
config_error();
return false;
}
break;
default:
config_error();
return false;
}
transport_ = std::make_shared<transport::TBufferedTransport>(socket);
auto protocol = std::make_shared<protocol::TBinaryProtocol>(transport_);
client_ = std::make_shared<ThriftController::ThriftControllerClient>(protocol);
try {
transport_->open();
}
catch (const std::exception& e) {
Log.error("Cannot open transport: {}", e.what());
json::value info = get_info_json() | json::object {
{ "what", "ConnectFailed" },
{ "why", "TransportError" },
{ "config", config },
};
callback(AsstMsg::ConnectionInfo, info);
return false;
}
auto connect_ret = false;
try {
connect_ret = client_->connect();
}
catch (const std::exception& e) {
Log.error("Cannot connect to MaaThriftController:", e.what());
return false;
}
if (!connect_ret) {
Log.error("Cannot connect to MaaThriftController");
json::value info = get_info_json() | json::object {
{ "what", "ConnectFailed" },
{ "why", "ConnectError" },
{ "config", config },
};
callback(AsstMsg::ConnectionInfo, info);
return false;
}
m_config = config;
if (need_exit()) {
return false;
}
/* uuid */
{
try {
client_->get_uuid(m_uuid);
}
catch (const std::exception& e) {
Log.error("Cannot get uuid:", e.what());
return false;
}
if (!m_uuid.empty()) {
json::value info = get_info_json() | json::object {
{ "what", "UuidGot" },
{ "why", "" },
};
info["details"]["uuid"] = m_uuid;
callback(AsstMsg::ConnectionInfo, info);
}
else {
json::value info = get_info_json() | json::object {
{ "what", "ConnectFailed" },
{ "why", "Uuid Empty" },
};
callback(AsstMsg::ConnectionInfo, info);
}
}
if (need_exit()) {
return false;
}
/* display */
{
ThriftController::Size screen_res;
try {
client_->get_screen_res(screen_res);
}
catch (const std::exception& e) {
Log.error("Cannot get screen resolution:", e.what());
return false;
}
auto width = screen_res.width;
auto height = screen_res.height;
json::value info = get_info_json() | json::object {
{ "what", "ResolutionGot" },
{ "why", "" },
};
info["details"] |= json::object {
{ "width", width },
{ "height", height },
};
callback(AsstMsg::ConnectionInfo, info);
if (width == 0 || height == 0) {
info["what"] = "ResolutionError";
info["why"] = "Get resolution failed";
callback(AsstMsg::ConnectionInfo, info);
return false;
}
m_screen_size = { width, height };
}
if (need_exit()) {
return false;
}
{
try {
m_support_features = static_cast<ControlFeat::Feat>(client_->get_support_features());
}
catch (const std::exception& e) {
Log.error("Cannot get support features:", e.what());
return false;
}
}
{
json::value info = get_info_json() | json::object {
{ "what", "Connected" },
{ "why", "" },
};
callback(AsstMsg::ConnectionInfo, info);
}
return true;
}
bool asst::MaaThriftController::inited() const noexcept
{
return m_inited;
}
void asst::MaaThriftController::set_swipe_with_pause(bool enable) noexcept
{
m_swipe_with_pause_enabled = enable;
}
const std::string& asst::MaaThriftController::get_uuid() const
{
return m_uuid;
}
bool asst::MaaThriftController::screencap(cv::Mat& image_payload, [[maybe_unused]] bool allow_reconnect)
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
ThriftController::CustomImage img;
try {
client_->screencap(img);
}
catch (const std::exception& e) {
Log.error("Cannot get screencap:", e.what());
return false;
}
if (img.data.empty()) {
Log.error("client_->screencap() return empty buffer");
return false;
}
cv::Mat orig_mat(img.size.height, img.size.width, img.type, img.data.data());
orig_mat.copyTo(image_payload);
return true;
}
bool asst::MaaThriftController::start_game(const std::string& client_type)
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
if (client_type.empty()) {
return false;
}
auto intent_name = Config.get_intent_name(client_type);
if (!intent_name) {
return false;
}
try {
return client_->start_game(*intent_name);
}
catch (const std::exception& e) {
Log.error("Cannot start game:", e.what());
return false;
}
}
bool asst::MaaThriftController::stop_game()
{
return false;
}
bool asst::MaaThriftController::click(const Point& p)
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
ThriftController::ClickParam click_param;
click_param.point.x = p.x;
click_param.point.y = p.y;
return client_->click(click_param);
}
bool asst::MaaThriftController::swipe(const Point& p1, const Point& p2, int duration, bool extra_swipe, double slope_in,
double slope_out, bool with_pause)
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
if (!support_precise_swipe()) {
ThriftController::SwipeParam swipe_param;
swipe_param.point1.x = p1.x;
swipe_param.point1.y = p1.y;
swipe_param.point2.x = p2.x;
swipe_param.point2.y = p2.y;
swipe_param.duration = duration;
try {
return client_->swipe(swipe_param);
}
catch (const std::exception& e) {
Log.error("Cannot swipe:", e.what());
return false;
}
}
int x1 = p1.x, y1 = p1.y;
int x2 = p2.x, y2 = p2.y;
const auto width = m_screen_size.first;
const auto height = m_screen_size.second;
// 起点不能在屏幕外,但是终点可以
if (x1 < 0 || x1 >= width || y1 < 0 || y1 >= height) {
Log.warn("swipe point1 is out of range", x1, y1);
x1 = std::clamp(x1, 0, width - 1);
y1 = std::clamp(y1, 0, height - 1);
}
toucher_down(p1);
constexpr int TimeInterval = DefaultSwipeDelay;
auto cubic_spline = [](double slope_0, double slope_1, double t) {
const double a = slope_0;
const double b = -(2 * slope_0 + slope_1 - 3);
const double c = -(-slope_0 - slope_1 + 2);
return a * t + b * std::pow(t, 2) + c * std::pow(t, 3);
}; // TODO: move this to math.hpp
bool need_pause = with_pause && use_swipe_with_pause();
const auto& opt = Config.get_options();
std::future<void> pause_future;
auto progressive_move = [&](int _x1, int _y1, int _x2, int _y2, int _duration) {
for (int cur_time = TimeInterval; cur_time < _duration; cur_time += TimeInterval) {
double progress = cubic_spline(slope_in, slope_out, static_cast<double>(cur_time) / duration);
int cur_x = static_cast<int>(std::lerp(_x1, _x2, progress));
int cur_y = static_cast<int>(std::lerp(_y1, _y2, progress));
if (need_pause && std::sqrt(std::pow(cur_x - _x1, 2) + std::pow(cur_y - _y1, 2)) >
opt.swipe_with_pause_required_distance) {
need_pause = false;
pause_future = std::async(std::launch::async, [&]() { press_esc(); });
}
if (cur_x < 0 || cur_x > width || cur_y < 0 || cur_y > height) {
continue;
}
toucher_move({ cur_x, cur_y });
}
if (_x2 >= 0 && _x2 <= width && _y2 >= 0 && _y2 <= height) {
toucher_move({ _x2, _y2 });
}
};
progressive_move(x1, y1, x2, y2, duration ? duration : opt.minitouch_swipe_default_duration);
if (extra_swipe && opt.minitouch_extra_swipe_duration > 0) {
std::this_thread::sleep_for(std::chrono::milliseconds(opt.minitouch_swipe_extra_end_delay)); // 停留终点
progressive_move(x2, y2, x2, y2 - opt.minitouch_extra_swipe_dist, opt.minitouch_extra_swipe_duration);
}
bool ret = toucher_up(p2);
return ret;
}
bool asst::MaaThriftController::inject_input_event(const InputEvent& event)
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
bool ret = false;
ThriftController::InputEvent input_event;
switch (event.type) {
case InputEvent::Type::TOUCH_DOWN:
input_event.type = ThriftController::InputEventType::TOUCH_DOWN;
break;
case InputEvent::Type::TOUCH_UP:
input_event.type = ThriftController::InputEventType::TOUCH_UP;
break;
case InputEvent::Type::TOUCH_MOVE:
input_event.type = ThriftController::InputEventType::TOUCH_MOVE;
break;
case InputEvent::Type::TOUCH_RESET:
input_event.type = ThriftController::InputEventType::TOUCH_RESET;
break;
case InputEvent::Type::KEY_DOWN:
input_event.type = ThriftController::InputEventType::KEY_DOWN;
break;
case InputEvent::Type::KEY_UP:
input_event.type = ThriftController::InputEventType::KEY_UP;
break;
case InputEvent::Type::WAIT_MS:
input_event.type = ThriftController::InputEventType::WAIT_MS;
break;
case InputEvent::Type::COMMIT:
try {
ret = client_->inject_input_events(m_input_events);
}
catch (const std::exception& e) {
Log.error("Cannot inject input events:", e.what());
}
m_input_events.clear();
return ret;
case InputEvent::Type::UNKNOWN:
default:
Log.error("unknown input event type");
return false;
}
input_event.touch.point.x = event.point.x;
input_event.touch.point.y = event.point.y;
input_event.touch.contact = event.pointerId;
input_event.key = event.keycode;
input_event.wait_ms = event.milisec;
m_input_events.push_back(input_event);
return true;
}
bool asst::MaaThriftController::press_esc()
{
if (!client_ || !transport_ || !transport_->isOpen()) {
Log.error("client_ is not created or transport_ is not open");
return false;
}
try {
return client_->press_key(111);
}
catch (const std::exception& e) {
Log.error("Cannot press esc:", e.what());
return false;
}
}
asst::ControlFeat::Feat asst::MaaThriftController::support_features() const noexcept
{
return m_support_features;
}
std::pair<int, int> asst::MaaThriftController::get_screen_res() const noexcept
{
return m_screen_size;
}
void asst::MaaThriftController::clear_info() noexcept
{
m_inited = false;
m_screen_size = { 0, 0 };
m_uuid.clear();
m_config.clear();
m_support_features = ControlFeat::NONE;
m_swipe_with_pause_enabled = false;
m_input_events.clear();
close();
client_.reset();
transport_.reset();
}
void asst::MaaThriftController::callback(AsstMsg msg, const json::value& details)
{
if (m_callback) {
m_callback(msg, details, m_inst);
}
}
bool asst::MaaThriftController::support_precise_swipe() const noexcept
{
return m_support_features & ControlFeat::PRECISE_SWIPE;
}
bool asst::MaaThriftController::support_swipe_with_pause() const noexcept
{
return m_support_features & ControlFeat::SWIPE_WITH_PAUSE;
}
bool asst::MaaThriftController::use_swipe_with_pause() const noexcept
{
return m_swipe_with_pause_enabled && support_swipe_with_pause();
}
bool asst::MaaThriftController::toucher_down(const Point& p, const int delay, int contact)
{
InputEvent event;
event.type = InputEvent::Type::TOUCH_DOWN;
event.point = p;
event.pointerId = contact;
inject_input_event(event);
event.type = InputEvent::Type::COMMIT;
auto ret = inject_input_event(event);
if (ret) {
toucher_wait(delay);
}
return ret;
}
bool asst::MaaThriftController::toucher_move(const Point& p, const int delay, int contact)
{
InputEvent event;
event.type = InputEvent::Type::TOUCH_MOVE;
event.point = p;
event.pointerId = contact;
inject_input_event(event);
event.type = InputEvent::Type::COMMIT;
auto ret = inject_input_event(event);
if (ret) {
toucher_wait(delay);
}
return ret;
}
bool asst::MaaThriftController::toucher_up(const Point& p, const int delay, int contact)
{
InputEvent event;
event.type = InputEvent::Type::TOUCH_UP;
event.point = p;
event.pointerId = contact;
inject_input_event(event);
event.type = InputEvent::Type::COMMIT;
auto ret = inject_input_event(event);
if (ret) {
toucher_wait(delay);
}
return ret;
}
void asst::MaaThriftController::toucher_wait(const int delay)
{
std::this_thread::sleep_for(std::chrono::milliseconds(delay));
}
void asst::MaaThriftController::close()
{
if (transport_) {
transport_->close();
}
}
#endif // WITH_THRIFT

View File

@@ -0,0 +1,103 @@
#pragma once
#ifdef WITH_THRIFT
#include "ControllerAPI.h"
#include "Platform/PlatformFactory.h"
#include "Common/AsstMsg.h"
#include "InstHelper.h"
#include "ThriftController.h"
#include "ThriftController_types.h"
namespace asst
{
class MaaThriftController : public ControllerAPI, protected InstHelper
{
public:
MaaThriftController(const AsstCallback& callback, Assistant* inst, [[maybe_unused]] PlatformType type)
: InstHelper(inst), m_callback(callback)
{
LogTraceFunction;
}
MaaThriftController(const MaaThriftController&) = delete;
MaaThriftController(MaaThriftController&&) = delete;
virtual ~MaaThriftController();
virtual bool connect([[maybe_unused]] const std::string& adb_path, [[maybe_unused]] const std::string& address,
const std::string& config) override;
virtual bool inited() const noexcept override;
virtual void set_swipe_with_pause(bool enable) noexcept override;
virtual const std::string& get_uuid() const override;
virtual bool screencap(cv::Mat& image_payload, bool allow_reconnect = false) override;
virtual bool start_game(const std::string& client_type) override;
virtual bool stop_game() override;
virtual bool click(const Point& p) override;
virtual bool swipe(const Point& p1, const Point& p2, int duration = 0, bool extra_swipe = false,
double slope_in = 1, double slope_out = 1, bool with_pause = false) override;
virtual bool inject_input_event(const InputEvent& event) override;
virtual bool press_esc() override;
virtual ControlFeat::Feat support_features() const noexcept override;
virtual std::pair<int, int> get_screen_res() const noexcept override;
MaaThriftController& operator=(const MaaThriftController&) = delete;
MaaThriftController& operator=(MaaThriftController&&) = delete;
protected:
virtual void clear_info() noexcept;
void callback(AsstMsg msg, const json::value& details);
bool support_precise_swipe() const noexcept;
bool support_swipe_with_pause() const noexcept;
bool use_swipe_with_pause() const noexcept;
AsstCallback m_callback;
std::string m_config;
std::string m_uuid;
ControlFeat::Feat m_support_features = ControlFeat::NONE;
bool m_inited = false;
bool m_swipe_with_pause_enabled = false;
std::pair<int, int> m_screen_size = { 0, 0 };
std::vector<ThriftController::InputEvent> m_input_events;
static constexpr int DefaultClickDelay = 50;
static constexpr int DefaultSwipeDelay = 5;
bool toucher_down(const Point& p, const int delay = DefaultClickDelay, int contact = 0);
bool toucher_move(const Point& p, const int delay = DefaultSwipeDelay, int contact = 0);
bool toucher_up(const Point& p, const int delay = DefaultClickDelay, int contact = 0);
void toucher_wait(const int delay);
std::shared_ptr<ThriftController::ThriftControllerClient> client_ = nullptr;
std::shared_ptr<apache::thrift::transport::TTransport> transport_ = nullptr;
enum ThriftControllerTypeEnum
{
// param format should be "host:port"
MaaThriftControllerType_Socket = 1,
// param should be unix domain socket path
MaaThriftControllerType_UnixDomainSocket = 2,
};
private:
static constexpr int MinimalVersion = 2;
void close();
bool open();
};
} // namespace asst
#endif // WITH_THRIFT

View File

@@ -54,6 +54,7 @@
<ClInclude Include="Controller\ControllerAPI.h" />
<ClInclude Include="Controller\ControllerFactory.h" />
<ClInclude Include="Controller\ControlScaleProxy.h" />
<ClCompile Include="Controller\MaaThriftController.h" />
<ClInclude Include="Controller\MaatouchController.h" />
<ClInclude Include="Controller\MinitouchController.h" />
<ClInclude Include="Controller\PlayToolsController.h" />
@@ -223,6 +224,7 @@
<ClCompile Include="Controller\adb-lite\protocol.cpp" />
<ClCompile Include="Controller\Controller.cpp" />
<ClCompile Include="Controller\ControlScaleProxy.cpp" />
<ClCompile Include="Controller\MaaThriftController.cpp" />
<ClCompile Include="Controller\MinitouchController.cpp" />
<ClCompile Include="Controller\PlayToolsController.cpp" />
<ClCompile Include="Controller\AdbController.cpp" />

View File

@@ -534,6 +534,9 @@
<ClInclude Include="Controller\ControlScaleProxy.h">
<Filter>Source\Controller</Filter>
</ClInclude>
<ClInclude Include="Controller\MaaThriftController.h">
<Filter>Source\Controller</Filter>
</ClInclude>
<ClInclude Include="Controller\MaatouchController.h">
<Filter>Source\Controller</Filter>
</ClInclude>
@@ -971,6 +974,9 @@
<ClCompile Include="Controller\adb-lite\protocol.cpp">
<Filter>Source\Controller\adb-lite</Filter>
</ClCompile>
<ClCompile Include="Controller\MaaThriftController.cpp">
<Filter>Source\Controller</Filter>
</ClCompile>
<ClCompile Include="Controller\MinitouchController.cpp">
<Filter>Source\Controller</Filter>
</ClCompile>

View File

@@ -0,0 +1,5 @@
GENERATE_THRIFT_LIB(MaaThriftController
${PROJECT_SOURCE_DIR}/include/interfaces/ThriftController.thrift
${CMAKE_CURRENT_BINARY_DIR}/MaaThriftController maa_thrift_controller_src)
source_group(TREE ${CMAKE_CURRENT_BINARY_DIR} FILES ${maa_thrift_controller_src})

View File

@@ -0,0 +1,6 @@
<Project>
<PropertyGroup>
<MaaDepsPropsFile>$(MSBuildThisFileDirectory)..\..\MaaDeps\msbuild\maadeps.props</MaaDepsPropsFile>
</PropertyGroup>
<Import Condition="Exists('$(MaaDepsPropsFile)')" Project="$(MaaDepsPropsFile)" />
</Project>

View File

@@ -0,0 +1,14 @@
<Project>
<PropertyGroup>
<MaaDepsTargetsFile>$(MSBuildThisFileDirectory)..\..\MaaDeps\msbuild\maadeps.targets</MaaDepsTargetsFile>
<MaaDepsDisableFlagFile>$(MSBuildThisFileDirectory)..\..\MSBUILD_DISABLE_MAADEPS</MaaDepsDisableFlagFile>
<MaaDepsExists Condition="Exists('$(MaaDepsTargetsFile)')">true</MaaDepsExists>
<MaaDepsDisableFlagExists Condition="Exists('$(MaaDepsDisableFlagFile)')">true</MaaDepsDisableFlagExists>
<MaaDepsMissingMessage>Missing third-party dependencies, run `python maadeps-download.py`. / 缺少第三方依赖,请运行 `python maadeps-download.py`。
Alternatively, run `python maadeps-build.py` to build third-party dependencies from source, or create a file named `MSBUILD_DISABLE_MAADEPS` next to MAA.sln file and bring your own libraries to MSBuild.</MaaDepsMissingMessage>
</PropertyGroup>
<Target Name="MessageMaaDepsNotExists" BeforeTargets="ClCompile" Condition="$(MaaDepsExists) != 'true' and '$(MaaDepsDisableFlagExists)' != true">
<Error Text="$(MaaDepsMissingMessage)" />
</Target>
<Import Condition="$(MaaDepsExists) == 'true'" Project="$(MaaDepsTargetsFile)" />
</Project>

View File

@@ -0,0 +1,305 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|ARM64">
<Configuration>Debug</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Debug|x64">
<Configuration>Debug</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|ARM64">
<Configuration>Release</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|x64">
<Configuration>Release</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|ARM64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>ARM64</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="RelWithDebInfo|x64">
<Configuration>RelWithDebInfo</Configuration>
<Platform>x64</Platform>
</ProjectConfiguration>
</ItemGroup>
<ItemGroup>
<CustomBuild Include="..\..\include\interfaces\ThriftController.thrift">
<FileType>Document</FileType>
<Command>mkdir "$(OutDirFullPath)$(ProjectName)"
..\..\MaaDeps\vcpkg\installed\maa-$(PreferredToolArchitecture)-windows\tools\thrift\thrift.exe --gen cpp:no_skeleton --out "$(OutDirFullPath)$(ProjectName)" "%(FullPath)"</Command>
<Message>Generate ThriftController</Message>
<Outputs>$(OutDirFullPath)$(ProjectName)\%(Filename).cpp;$(OutDirFullPath)$(ProjectName)\%(Filename).h;$(OutDirFullPath)$(ProjectName)\%(Filename)_types.cpp;$(OutDirFullPath)$(ProjectName)\%(Filename)_types.h</Outputs>
<TreatOutputAsContent>true</TreatOutputAsContent>
</CustomBuild>
</ItemGroup>
<ItemGroup>
<ClCompile Include="$(OutDirFullPath)$(ProjectName)\ThriftController.cpp" />
<ClCompile Include="$(OutDirFullPath)$(ProjectName)\ThriftController_types.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="$(OutDirFullPath)$(ProjectName)\ThriftController.h" />
<ClInclude Include="$(OutDirFullPath)$(ProjectName)\ThriftController_types.h" />
</ItemGroup>
<PropertyGroup Label="Globals">
<VCProjectVersion>16.0</VCProjectVersion>
<Keyword>Win32Proj</Keyword>
<ProjectGuid>{8238edb1-19bf-4e3b-af5b-016120d59d7b}</ProjectGuid>
<WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
<PreferredToolArchitecture>x64</PreferredToolArchitecture>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>true</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="Configuration">
<ConfigurationType>DynamicLibrary</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<PlatformToolset>v143</PlatformToolset>
<WholeProgramOptimization>false</WholeProgramOptimization>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="Shared">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<ImportGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'" Label="PropertySheets">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'">
<LinkIncremental>false</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<LinkIncremental>true</LinkIncremental>
<LibraryPath>$(SolutionDir)\$(Platform)\$(Configuration)\;$(LibraryPath)</LibraryPath>
<OutDir>$(SolutionDir)\$(Platform)\$(Configuration)\</OutDir>
</PropertyGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningVersion>19.35.32217</WarningVersion>
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/ignore:4286 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|ARM64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<FunctionLevelLinking>true</FunctionLevelLinking>
<IntrinsicFunctions>true</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<Optimization>MaxSpeed</Optimization>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningVersion>19.35.32217</WarningVersion>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
<AdditionalOptions>/ignore:4286 %(AdditionalOptions)</AdditionalOptions>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<Optimization>Disabled</Optimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningVersion>19.35.32217</WarningVersion>
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='RelWithDebInfo|ARM64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>NDEBUG;_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<Optimization>Disabled</Optimization>
<WholeProgramOptimization>true</WholeProgramOptimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<WarningVersion>19.35.32217</WarningVersion>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
<OptimizeReferences>true</OptimizeReferences>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmd.lib;%(AdditionalDependencies)</AdditionalDependencies>
<Profile>true</Profile>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CONSOLE;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<Optimization>Disabled</Optimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|ARM64'">
<ClCompile>
<WarningLevel>Level4</WarningLevel>
<IntrinsicFunctions>false</IntrinsicFunctions>
<SDLCheck>true</SDLCheck>
<PreprocessorDefinitions>_CONSOLE;_DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<ConformanceMode>true</ConformanceMode>
<LanguageStandard>stdcpp20</LanguageStandard>
<LanguageStandard_C>stdc11</LanguageStandard_C>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<Optimization>Disabled</Optimization>
<BasicRuntimeChecks>EnableFastChecks</BasicRuntimeChecks>
<AdditionalOptions>/utf-8 /MP $(ExternalCompilerOptions) %(AdditionalOptions)</AdditionalOptions>
<TreatWarningAsError>true</TreatWarningAsError>
<DebugInformationFormat>EditAndContinue</DebugInformationFormat>
<AdditionalIncludeDirectories>$(ProjectDir);%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
<GenerateDebugInformation>true</GenerateDebugInformation>
<AdditionalDependencies>ws2_32.lib;thriftmdd.lib;%(AdditionalDependencies)</AdditionalDependencies>
</Link>
</ItemDefinitionGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>