增加ACE安全测试工程

This commit is contained in:
2025-12-06 16:42:21 +08:00
parent b78ee53326
commit b38ad590a9
68 changed files with 5385 additions and 0 deletions
+25
View File
@@ -0,0 +1,25 @@
set(WTL_DIR $ENV{LIBRARIES_SDK_ROOT}/wtl)
set(CYCLONE_DIR $ENV{CYCLONE_SDK_ROOT})
set(RapidJSON_DIR $ENV{LIBRARIES_SDK_ROOT}/rapidjson/cmake)
find_package(RapidJSON REQUIRED)
set(OPENSSL_ROOT_DIR $ENV{LIBRARIES_SDK_ROOT}/openssl)
set(ZLIB_USE_STATIC_LIBS True)
set(ZLIB_ROOT $ENV{LIBRARIES_SDK_ROOT}/zlib)
set(CURL_DIR $ENV{LIBRARIES_SDK_ROOT}/libcurl/lib/cmake/CURL)
find_package(CURL CONFIG REQUIRED)
set(GAME_PROTO_DIR ${CMAKE_CURRENT_SOURCE_DIR}/aCommon/proto)
set(ACE_CLIENT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/aCommon/ace_sdk/client)
set(ACE_SERVER_DIR ${CMAKE_CURRENT_SOURCE_DIR}/aCommon/ace_sdk/server)
set(Protobuf_DIR $ENV{LIBRARIES_SDK_ROOT}/protobuf/cmake)
find_package(Protobuf CONFIG REQUIRED)
add_subdirectory(aClient)
add_subdirectory(aCommon)
add_subdirectory(aServer)
+123
View File
@@ -0,0 +1,123 @@
#include "stdafx.h"
#include "AceClientInterface.h"
#include <ace_sdk_client.h>
#include <ace_sdk_client_anti_cheat_core.h>
#include <ace_sdk_protocol_binding.h>
bool AceClientInterface::init()
{
//init ace sdk client protocol binding
m_protoBindingInitRetCode = AceProtocolBindingSDK::__ace_sdk_protocol_binding_init();
if (m_protoBindingInitRetCode != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk client proto binding, ret : %d\n", m_protoBindingInitRetCode);
//continue even failed...
}
printf(">>ACE SDK client proto binding init success.\n");
//init ace sdk
AceSdkResult ret = ace_sdk_client_init();
if(ret!= ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk client, ret : %d\n", ret);
return false;
}
return true;
}
void AceClientInterface::deinit()
{
AceSdkResult ret = ace_sdk_client_deinit();
}
bool AceClientInterface::onServerLoginReply(const char* accountID, uint32_t worldID,
const char* loginToken,
const char* lightFeatureName, uint32_t lightFeatureDataCRC,
const uint8_t* lightFeatureData, uint32_t lightFeatureDataLengh)
{
//call ace client login
AceSdkResult ret = ace_sdk_client_log_in(
accountID, ACE_SDK_ACCOUNT_TYPE_QQ,
worldID, loginToken
);
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_log_in, ret : %d\n", ret);
return false;
}
//call ace client light feature data
AceProtocolBindingSDK::g__ace_sdk_on_receive_signature(
lightFeatureName,
lightFeatureData,
lightFeatureDataLengh,
lightFeatureDataCRC
);
return true;
}
void AceClientInterface::onServerLogout()
{
AceSdkResult ret = ace_sdk_client_log_out();
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_log_out, ret : %d\n", ret);
}
}
void AceClientInterface::getClientTickPacket(uint8_t* out_buffer, uint32_t& out_len)
{
int64_t timeNow = cyclone::sys_api::utc_time_now();
if(timeNow - m_lastTickTime < 100ll*1000ll)
{
out_len = 0;
return;
}
m_lastTickTime = timeNow;
AceSdkClientPacket packet;
AceSdkResult ret = ace_sdk_client_get_packet(&packet);
if (ret == ACE_SDK_RESULT_OK)
{
printf(">>ACE ace_sdk_client_get_packet, len : %d\n", packet.len);
out_len = packet.len;
memcpy(out_buffer, packet.buffer, packet.len);
}
else
{
out_len = 0;
return;
}
}
void AceClientInterface::onServerTickPacket(const uint8_t* input_buffer, uint32_t input_len)
{
AceSdkResult ret = ace_sdk_client_on_packet_received(input_buffer, input_len);
if(ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_client_on_packet_received, ret : %d\n", ret);
}
}
uint32_t AceClientInterface::getProtoBindingData(uint8_t* bindDataBuf, uint32_t buffSize)
{
AceProtocolBindingSDK::AceSdkAntiDataInfo bindingData;
memset(&bindingData, 0, sizeof(bindingData));
AceProtocolBindingSDK::g__ace_sdk_get_report_data3(&bindingData);
uint32_t dataLength = bindingData.anti_data_len_;
if (bindingData.anti_data_len_ <= buffSize)
{
memcpy(bindDataBuf, bindingData.anti_data_, bindingData.anti_data_len_);
}
else
{
printf(">>ACE fail to get proto binding data, buffer size too small!\n");
}
AceProtocolBindingSDK::g__ace_sdk_del_report_data(&bindingData);
return dataLength;
}
+26
View File
@@ -0,0 +1,26 @@
#pragma once
class AceClientInterface
{
public:
bool init();
void deinit();
uint32_t getPbRetCode() const {
return m_protoBindingInitRetCode;
}
bool onServerLoginReply(const char* accountID, uint32_t worldID,
const char* loginToken,
const char* lightFeatureName, uint32_t lightFeatureDataCRC,
const uint8_t* lightFeatureData, uint32_t lightFeatureDataLengh);
void onServerLogout();
void getClientTickPacket(uint8_t* out_buffer, uint32_t& out_len);
void onServerTickPacket(const uint8_t* input_buffer, uint32_t input_len);
uint32_t getProtoBindingData(uint8_t* bindDataBuf, uint32_t buffSize);
protected:
uint32_t m_protoBindingInitRetCode = 0;
int64_t m_lastTickTime = 0;
};
+85
View File
@@ -0,0 +1,85 @@
#include "stdafx.h"
#include "AceReportInterface.h"
#include "GameProto.h"
#include "GameProto.pb.h"
#include "GameClient.h"
struct ACEReportStruct
{
int32_t id;
Game::GameReportReq reportRequest;
ACEReport::CallbackFunction callback;
};
ACEReport::ACEReport()
{
m_nextID = 1;
}
ACEReport::~ACEReport()
{
}
void ACEReport::init(GameClient* client)
{
m_client = client;
}
ACEReportContext ACEReport::createReportContext(
const char* account,
int32_t worldID,
const char* reported_name,
const char* reported_roldid,
ACEReportScene scene,
ACEReportCategory category,
const ACEReportReasonArray& reasons,
DNFReportEntranceID entranceID
)
{
ACEReportStruct* ctx = new ACEReportStruct();
ctx->id = m_nextID++;
ctx->callback = nullptr;
ctx->reportRequest.set_ctx_id(ctx->id);
ctx->reportRequest.set_reported_account_id(account);
ctx->reportRequest.set_reported_world_id(worldID);
ctx->reportRequest.set_reported_name(reported_name);
ctx->reportRequest.set_reported_roleid(reported_roldid);
ctx->reportRequest.set_report_scene(static_cast<int32_t>(scene));
ctx->reportRequest.set_report_category(static_cast<int32_t>(category));
ctx->reportRequest.set_report_entrance(static_cast<int32_t>(entranceID));
for(ACEReportReason reason: reasons)
{
ctx->reportRequest.add_report_reason(static_cast<int32_t>(reason));
}
m_reportStructMap.insert(std::make_pair(ctx->id, ctx));
return ctx;
}
ACEReportStruct* ACEReport::getReport(ACEReportContext ctx)
{
if (ctx == nullptr) return nullptr;
ReportStructMap::iterator it = m_reportStructMap.find(ctx->id);
if (it == m_reportStructMap.end()) return nullptr;
return it->second;
}
bool ACEReport::uploadReport(ACEReportContext ctx, CallbackFunction callback)
{
ACEReportStruct* report = getReport(ctx);
if (report == nullptr) return false;
Game::GameReportReq& reportReq = report->reportRequest;
if(reportReq.report_reason_size() == 0)
{
return false;
}
report->callback = callback;
m_client->sendProtobufMessage(GAME_PROTO_REPORT_REQ, &reportReq);
return true;
}
+161
View File
@@ -0,0 +1,161 @@
#pragma once
#include <stdint.h>
#include <vector>
#include <functional>
enum ACEReportScene
{
REPORT_SCENE_UGC = 1,
REPORT_SCENE_INFORMATION=2,
REPORT_SCENE_BATTLE=3,
REPORT_SCENE_ARTICLE=4,
REPORT_SCENE_COMMENT=5,
REPORT_SCENE_IMAGE=6,
REPORT_SCENE_ORGANIZE=7,
REPORT_SCENE_OTHER=8,
};
enum ACEReportCategory
{
REPORT_CATEGORY_ILLEGAL = 1,
REPORT_CATEGORY_BEHAVIOR = 2,
REPORT_CATEGORY_CHEAT = 3,
REPORT_CATEGORY_STUDIO = 4,
REPORT_CATEGORY_UGC = 7,
REPORT_CATEGORY_ORGANIZE = 8,
REPORT_CATEGORY_PERSONAL = 9,
};
enum ACEReportReason
{
//发布违规信息 REPORT_CATEGORY_ILLEGAL
REPORT_REASON_ILLEGAL_ABUSE = 101,
REPORT_REASON_ILLEGAL_ADVERTISEMENT = 102,
REPORT_REASON_ILLEGAL_PORN = 103,
REPORT_REASON_ILLEGAL_POLITICS = 104,
REPORT_REASON_ILLEGAL_HARASS = 105,
REPORT_REASON_ILLEGAL_VIOLENT = 106,
REPORT_REASON_ILLEGAL_GAMBLE = 107,
REPORT_REASON_ILLEGAL_CHEAT = 108,
REPORT_REASON_ILLEGAL_PRIVACY_LEAKS = 109,
REPORT_REASON_IULEGAL_INFRINGEMENT = 110,
REPORT_REASON_ILLEGAL_OTHER = 199,
//恶意游戏行为 REPORT_CATEGORY BEHAVIOR
REPORT_REASON_BEHAVIOR_FRIENDLYFIRE = 201,
REPORT_REASON_BEHAVIOR_FORM_CHEATER_TEAM = 202,
REPORT_REASON_BEHAVIOR_JOIN_CHEATER_TEAM = 203,
REPORT_REASON_BEHAVIOR_GUARDED_BY_CHEATER = 204,
REPORT_REASON_BEHAVIOR_EXPLOITING = 205,
REPORT_REASON_BEHAVIOR_AUTO_ROBOT = 206,
REPORT_REASON_BEHAVIOR_PASSIVE_PLAY = 207,
REPORT_REASON_BEHAVIOR_MALICIOUS_REPEAT = 208,
REPORT_REASON_BEHAVIOR_REFUSE_COOPERATE = 210,
REPORT_REASON_BEHAVIOR_OTHER=299,
//使用作弊工具REPORT_CATEGORY_CHEAT
REPORT_REASON_CHEAT_SEE_THROUTH = 301,
REPORT_REASON_CHEAT_AUTO_AIM = 302,
REPORT_REASON_CHEAT_NO_RECOIL = 303,
REPORT_REASON_CHEAT_SPEED_UP = 304,
REPORT_REASON_CHEAT_DAMAGE_RANGE = 305,
REPORT_REASON_CHEAT_WALL_THROUGH = 306,
REPORT_REASON_CHEAT_FLYING = 307,
REPORT_REASON_CHEAT_TELEPORT = 308,
REPORT_REASON_CHEAT_INSTANT_KILLING = 309,
REPORT_REASON_CHEAT_AUTO_FIRING = 310,
REPORT_REASON_CHEAT_MACRO = 311,
REPORT_REASON_CHEAT_INF_PROJECTILES = 312,
REPORT_REASON_CHEAT_SHOOTING_SPEED = 313,
REPORT_REASON_CHEAT_INF_BULLETS = 314,
REPORT_REASON_CHEAT_EXTERNAL_DEVICE = 315,
REPORT_REASON_CHEAT_REMOTE_PICKING = 316,
REPORT_REASON_CHEAT_REMOTE_KILLING = 317,
REPORT_REASON_CHEAT_OTHER=399,
//工作室行为REPORT_CATEGORY_STUDIO
REPORT_REASON_STUDIO_COMPETE_RESOURCE = 401,
REPORT_REASON_STUDIO_OFFLINE_DEAL = 402,
REPORT_REASON_STUDIO_ILLEGAL_BENEFITS = 403,
REPORT_REASON_STUDIO_TEAM = 404,
REPORT_REASON_STUDIO_MULTI_PLAVING = 405,
REPORT_REASON_STUDIO_OTHER=499,
//自定义内容违规REPORT_CATEGORY_UGC
REPORT_REASON_UGC_ILLEGAL_NAME = 701,
REPORT_REASON_UGC_ILLEGAL_BRIEF = 702,
REPORT_REASON_UGC_PORN_CONTENT = 703,
REPORT_REASON_UGC_POLITICAL_CONTENT = 704,
REPORT_REASON_UGC_ABUSIVE_CONTENT = 705,
REPORT_REASON_UGC_FRAUDULENT_CONTENT = 706,
REPORT_REASON_UGC_OTHER=799,
};
enum DNFReportEntranceID
{
DNF_REPORT_ENTRANCE_TEST = 0,
};
typedef std::vector<ACEReportReason> ACEReportReasonArray;
struct ACEReportStruct;
typedef ACEReportStruct* ACEReportContext;
class GameClient;
class ACEReport
{
public:
ACEReport();
~ACEReport();
void init(GameClient* client);
public:
ACEReportContext createReportContext(
const char* account,
int32_t worldID,
const char* reported_name,
const char* reported_roldid,
ACEReportScene scene,
ACEReportCategory category,
const ACEReportReasonArray& reasons,
DNFReportEntranceID entranceID = DNF_REPORT_ENTRANCE_TEST
);
//设置对局ID和时间,如果要举报和战局有关的信息,这两条必须同时设置
void setReportBattleID(ACEReportContext ctx, const char* battle_id, int32_t battle_time);
//设置举报的描述信息,这里举报者自己描述的文本信息
void setReportDesc(ACEReportContext ctx, const char* desc);
//设置举报内容,这里是指要举报的目标内容
void setContent(ACEReportContext ctx, const char* content);
//设置举报的公会、战队、房间等组织的ID和名称
void setGroupID(ACEReportContext ctx, const char* groupID, const char* groupName);
//设置举报者的头像URL,最大长度4096字寸,要求外网或者IDC个的多访问下载
void setReportedProfileUrl(ACEReportContext ctx, const char* profileURL);
//添加举报的图片URL,可以添加多个(最多12个),单条最人长度4096字节,要求外网或者IDC能够访问下载
void addReportedPictureURL(ACEReportContext ctx, const char* profileURL);
//添加举报的视频URL,可以添加多个(最务1个),单条最人长度4096字节,要求外网或者IDC能够访问下载
void addReportedVideoURL(ACEReportContext ctx, const char* profileuRL);
//添加举报的语音URL,可以添加多个(最多12个),单条最大长度409
void addReportedVoiceURL(ACEReportContext tx, const char* profileURL);
//添加其他需要添加的ID,例如文章T,房间T0等,每种类型都可以添加多个, addReportcontent(ctx, "room id",“123456");
void addReportIDContent(ACEReportContext ctx, const char* idTyne, const char* idContent);
//上报结果回调
typedef std::function<void(ACEReportContext ctx, int32_t result, const char* error_message)> CallbackFunction;
bool uploadReport(ACEReportContext ctx, CallbackFunction callback);
private:
void onReportResult(int32_t reportID, uint32_t result, const char* errorMessage);
ACEReportStruct* getReport(ACEReportContext ctx);
private:
GameClient* m_client = nullptr;
typedef std::map<int32_t, ACEReportContext> ReportStructMap;
ReportStructMap m_reportStructMap;
int32_t m_nextID = 0;
};
+71
View File
@@ -0,0 +1,71 @@
set(ACLIENT_SOURCE_FILES
stdafx.h
main.cpp
MainDialog.h
MainDialog.cpp
GameClient.h
GameClient.cpp
AceClientInterface.h
AceClientInterface.cpp
AceReportInterface.h
AceReportInterface.cpp
NetbarInterface.h
NetbarInterface.cpp
)
set(ACLIENT_RC_FILES
aClient.rc
)
source_group("Resource Files" FILES ${ACLIENT_RC_FILES})
set(ACLIENT_PRECOMPILE_FILE
stdafx.cpp
)
foreach(filename ${ACLIENT_SOURCE_FILES})
get_filename_component(ext ${filename} LAST_EXT ABSOLUTE)
string(TOLOWER ${ext} ext_lower)
if(${ext_lower} STREQUAL ".cpp" )
set_source_files_properties(
${filename}
PROPERTIES
COMPILE_FLAGS "/Yustdafx.h"
)
endif()
endforeach()
set_source_files_properties(${ACLIENT_PRECOMPILE_FILE}
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
add_executable(aClient WIN32
${ACLIENT_SOURCE_FILES}
${ACLIENT_RC_FILES}
${ACLIENT_PRECOMPILE_FILE}
)
target_include_directories(aClient
PRIVATE
${ACE_CLIENT_DIR}/include
${WTL_DIR}/include
${CYCLONE_DIR}/include
${GAME_PROTO_DIR}
)
target_link_directories(aClient
PRIVATE
${CYCLONE_DIR}/lib
)
target_link_libraries(aClient
PRIVATE
aGameProto
cyclone.lib
ws2_32.lib
shlwapi.lib
winmm.lib
)
+285
View File
@@ -0,0 +1,285 @@
#include "stdafx.h"
#include "GameClient.h"
#include <strsafe.h>
const char* GameClient::s_default_account_id = "979591";
const uint32_t GameClient::s_default_world_id = 160;
GameClient::GameClient()
: m_status(STATUS_DISCONNECTED)
, m_client(nullptr)
, m_looper(nullptr)
{
m_clientTickBuffer = new uint8_t[2048];
}
GameClient::~GameClient()
{
m_client = nullptr;
cyclone::Looper::destroy_looper(m_looper);
m_looper = nullptr;
delete[] m_clientTickBuffer;
m_clientTickBuffer = nullptr;
}
bool GameClient::init()
{
assert(m_status == STATUS_DISCONNECTED);
m_reportInterface.init(this);
m_clientNetbarInterface.init(this);
return m_aceClientInterface.init();
}
void GameClient::deinit()
{
m_aceClientInterface.deinit();
}
void GameClient::connectToGameServer(const std::string& server_ip, uint16_t server_port)
{
assert(m_status == STATUS_DISCONNECTED);
m_server_ip = server_ip;
m_server_port = server_port;
CY_LOG(cyclone::L_DEBUG, "connect to %s:%d...", server_ip.c_str(), server_port);
m_looper = cyclone::Looper::create_looper();
m_client = std::make_shared<cyclone::TcpClient>(m_looper, nullptr);
m_client->m_listener.on_connected = std::bind(&GameClient::onConnected, this, std::placeholders::_1, std::placeholders::_3);
m_client->m_listener.on_message = std::bind(&GameClient::onMessage, this, std::placeholders::_2);
m_client->m_listener.on_close = std::bind(&GameClient::onClose, this);
m_client->connect(cyclone::Address(m_server_ip.c_str(), m_server_port));
m_status = STATUS_CONNECTING;
}
void GameClient::disconnectFromGameServer()
{
if (m_client)
{
m_client->disconnect();
m_status = STATUS_LOGGING_OUT;
}
}
void GameClient::tick()
{
if (m_looper)
{
m_looper->step();
}
if (m_status == STATUS_LOGGED_IN)
{
uint32_t packetLen = 0;
m_aceClientInterface.getClientTickPacket(m_clientTickBuffer, packetLen);
if (packetLen > 0)
{
Game::ClientTickPacket clientTickPacket;
clientTickPacket.mutable_client_packet()->assign((const char*)m_clientTickBuffer, packetLen);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_CLIENT_PACKET, &clientTickPacket, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
sendHeartBeat();
}
m_clientNetbarInterface.tick();
}
uint32_t GameClient::onConnected(cyclone::TcpClientPtr client, bool success)
{
assert(m_status == STATUS_CONNECTING);
CY_LOG(cyclone::L_DEBUG, "connect to %s:%d %s.",
client->get_server_address().get_ip(), client->get_server_address().get_port(),
success ? "OK" : "FAILED");
if (success)
{
m_status = STATUS_CONNECTED;
sendLoginRequest(s_default_account_id, s_default_world_id);
return 0;
}
else
{
return 1000 * 5;
}
}
void GameClient::sendLoginRequest(const char* accountID, int32_t worldID)
{
assert(m_status == STATUS_CONNECTED);
Game::LoginRequest loginRequest;
loginRequest.set_accound_id(accountID);
loginRequest.set_world_id(worldID);
loginRequest.set_pb_retcode(m_aceClientInterface.getPbRetCode());
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_LOGIN_REQUEST, &loginRequest, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
m_status = STATUS_LOGGING_IN;
}
void GameClient::onMessage(cyclone::TcpConnectionPtr conn)
{
cyclone::RingBuf& buf = conn->get_input_buf();
for (;;)
{
cyclone::Packet packet;
if (!packet.build_from_ringbuf(GAME_PACKET_HEAD_SIZE, buf)) return;
::google::protobuf::Message* message = parserProtoMessage(packet);
switch (packet.get_packet_id())
{
case GAME_PROTO_LOGIN_REPLY:
{
Game::LoginReply* loginReply = dynamic_cast<Game::LoginReply*>(message);
onServerLoginReply(conn, loginReply);
}
break;
case GAME_PROTO_SERVER_PACKET:
{
Game::ServerTickPacket* serverTickPacket = dynamic_cast<Game::ServerTickPacket*>(message);
onServerTickPacket(conn, serverTickPacket);
}
break;
case GAME_PROTO_UGC_REPLY:
{
Game::UGCReply* ugcReply = dynamic_cast<Game::UGCReply*>(message);
onServerUGCReply(conn, ugcReply);
}
break;
case GAME_PROTO_NETBAR_RES:
{
Game::NetbarStatusRes* netbarResponse = dynamic_cast<Game::NetbarStatusRes*>(message);
onServerNetbarResponse(conn, netbarResponse);
}
break;
}
}
}
void GameClient::onServerLoginReply(cyclone::TcpConnectionPtr conn, Game::LoginReply* reply)
{
assert(m_status == STATUS_LOGGING_IN);
m_aceClientInterface.onServerLoginReply(s_default_account_id, s_default_world_id,
reply->ace_token().c_str(),
reply->light_feature().name().c_str(),
reply->light_feature().data_crc(),
(const uint8_t*)reply->light_feature().data().data(),
(uint32_t)reply->light_feature().data().size()
);
m_status = STATUS_LOGGED_IN;
}
void GameClient::onServerTickPacket(cyclone::TcpConnectionPtr conn, Game::ServerTickPacket* reply)
{
assert(m_status == STATUS_LOGGED_IN || m_status==STATUS_LOGGING_IN);
m_aceClientInterface.onServerTickPacket(
(const uint8_t*)(reply->server_packet().data()),
(uint32_t)(reply->server_packet().size())
);
}
void GameClient::sendHeartBeat()
{
assert(m_status == STATUS_LOGGED_IN);
uint64_t timeNow = cyclone::sys_api::utc_time_now();
if(timeNow-m_lastHeartBeatTime < 60 * 1000ll*1000ll)
{
return;
}
m_lastHeartBeatTime = timeNow;
uint8_t bindBuffer[1024];
uint32_t bindDataLength = m_aceClientInterface.getProtoBindingData(bindBuffer, sizeof(bindBuffer));
Game::HeartBeat heartBeat;
heartBeat.set_timestamp((int32_t)timeGetTime());
heartBeat.mutable_pb_data()->assign((const char*)bindBuffer, bindDataLength);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_HEART_BEAT, &heartBeat, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onServerUGCReply(cyclone::TcpConnectionPtr conn, Game::UGCReply* reply)
{
assert(m_status == STATUS_LOGGED_IN);
wchar_t wszTemp[2048];
UINT btn = MB_OK;
if (reply->result() == 0)
{
StringCchPrintfW(wszTemp, sizeof(wszTemp)/sizeof(wszTemp[0]),
L"UGC Reply: ContextID=%d, ErrorCode=%d, Result=%d",
reply->ugc_ctx_id(),
reply->error_code(),
reply->result()
);
}
else
{
btn = MB_OK | MB_ICONERROR;
wchar_t wszFiltedContent[1024];
::MultiByteToWideChar(CP_UTF8, 0, reply->filted_content().c_str(), -1,
wszFiltedContent, sizeof(wszFiltedContent) / sizeof(wszFiltedContent[0]));
StringCchPrintfW(wszTemp, sizeof(wszTemp)/sizeof(wszTemp[0]),
L"UGC Reply: ContextID=%d, ErrorCode=%d, Result=%d, FiltedText='%s'",
reply->ugc_ctx_id(),
reply->error_code(),
reply->result(),
wszFiltedContent
);
}
MessageBoxW(NULL, wszTemp, L"UGC Reply", btn);
}
void GameClient::sendUGCContent(int32_t ugcSceneID, const char* content)
{
assert(m_status == STATUS_LOGGED_IN);
Game::UGCRequest ugcRequest;
ugcRequest.set_ugc_ctx_id(m_nextUGCContextID++);
ugcRequest.set_ugc_scene_id(ugcSceneID);
ugcRequest.set_ugc_content(content);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_UGC_REQUEST, &ugcRequest, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onClose(void)
{
m_aceClientInterface.onServerLogout();
m_status = STATUS_LOGGED_OUT;
}
void GameClient::sendProtobufMessage(uint16_t id, ::google::protobuf::Message* message)
{
cyclone::Packet packet;
serializeProtoMessage(id, message, packet);
m_client->send(packet.get_memory_buf(), packet.get_memory_size());
}
void GameClient::onServerNetbarResponse(cyclone::TcpConnectionPtr conn, Game::NetbarStatusRes* reply)
{
m_clientNetbarInterface.onReceiveNetbarReportRequest(reply);
}
+81
View File
@@ -0,0 +1,81 @@
#pragma once
#include "GameProto.h"
#include "GameProto.pb.h"
#include "AceClientInterface.h"
#include "AceReportInterface.h"
#include "NetbarInterface.h"
class GameClient
{
public:
enum Status
{
STATUS_DISCONNECTED = 0,
//call connectToGameServer...
STATUS_CONNECTING,
//onConnected
STATUS_CONNECTED,
//call sendLoginRequest...
STATUS_LOGGING_IN,
//onServerLoginReply
STATUS_LOGGED_IN,
//call sendLogoutRequest...
STATUS_LOGGING_OUT,
//socket closed
STATUS_LOGGED_OUT,
STATUS_FAILED,
};
const static char* s_default_account_id;
const static uint32_t s_default_world_id;
public:
bool init();
void deinit();
void connectToGameServer(const std::string& server_ip, uint16_t server_port);
void disconnectFromGameServer();
void sendProtobufMessage(uint16_t id, ::google::protobuf::Message* message);
void sendUGCContent(int32_t ugcSceneID, const char* content);
ACEReport* getAceReportInterface(void) { return &m_reportInterface; }
TencentNetbarInterface* getNetbarInterface(void) { return &m_clientNetbarInterface; }
void tick();
cyclone::TcpClientPtr get_client(void) { return m_client; }
protected:
uint32_t onConnected(cyclone::TcpClientPtr client, bool success);
void onMessage(cyclone::TcpConnectionPtr conn);
void onClose(void);
protected:
void sendLoginRequest(const char* accountID, int32_t worldID);
void onServerLoginReply(cyclone::TcpConnectionPtr conn, Game::LoginReply* reply);
void onServerTickPacket(cyclone::TcpConnectionPtr conn, Game::ServerTickPacket* reply);
void onServerUGCReply(cyclone::TcpConnectionPtr conn, Game::UGCReply* reply);
void onServerNetbarResponse(cyclone::TcpConnectionPtr conn, Game::NetbarStatusRes* reply);
void sendHeartBeat();
private:
Status m_status = STATUS_DISCONNECTED;
cyclone::TcpClientPtr m_client;
cyclone::Looper* m_looper;
std::string m_server_ip;
uint16_t m_server_port;
uint64_t m_lastHeartBeatTime = 0;
AceClientInterface m_aceClientInterface;
uint8_t* m_clientTickBuffer = nullptr;
ACEReport m_reportInterface;
int32_t m_nextUGCContextID = 1;
TencentNetbarInterface m_clientNetbarInterface;
public:
GameClient();
~GameClient();
};
+170
View File
@@ -0,0 +1,170 @@
#include "stdafx.h"
#include "MainDialog.h"
#include "AceReportInterface.h"
#include <tlhelp32.h>
#include <psapi.h>
LRESULT CMainDialog::OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
CenterWindow(GetParent());
if(m_gameClient.init()==false)
{
MessageBoxA("Failed to init Ace SDK client interface!", "Error", MB_OK|MB_ICONERROR);
CloseDialog(IDCANCEL);
return FALSE;
}
return TRUE;
}
LRESULT CMainDialog::OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CloseDialog(wID);
return 0;
}
LRESULT CMainDialog::OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
CloseDialog(wID);
return 0;
}
void CMainDialog::CloseDialog(int nVal)
{
m_gameClient.deinit();
DestroyWindow();
::PostQuitMessage(nVal);
}
LRESULT CMainDialog::OnTimer(UINT /*uMsg*/, WPARAM wParam, LPARAM /*lParam*/, BOOL& /*bHandled*/)
{
if(wParam==101)
{
m_gameClient.tick();
}
return 0;
}
LRESULT CMainDialog::OnConnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
m_gameClient.connectToGameServer("127.0.0.1", 2025);
this->SetTimer(101, 100, NULL);
return 0;
}
LRESULT CMainDialog::OnDisconnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
this->KillTimer(101);
m_gameClient.disconnectFromGameServer();
return 0;
}
LRESULT CMainDialog::OnSendUGCContent(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
// To be implemented
wchar_t wszUgcContent[2048];
::GetDlgItemTextW(m_hWnd, IDC_EDIT_UGC_CONTENT, wszUgcContent, sizeof(wszUgcContent)/sizeof(wchar_t));
char szUtf8UgcContent[2048] = { 0 };
::WideCharToMultiByte(CP_UTF8, 0, wszUgcContent, -1, szUtf8UgcContent, sizeof(szUtf8UgcContent), NULL, NULL);
m_gameClient.sendUGCContent(101, szUtf8UgcContent);
return 0;
}
LRESULT CMainDialog::OnSendReport(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
ACEReport* reportInterface = m_gameClient.getAceReportInterface();
auto ctx = reportInterface->createReportContext(
"reporter_account",
1,
"reported_name",
"reported_roleid",
ACEReportScene::REPORT_SCENE_UGC,
ACEReportCategory::REPORT_CATEGORY_BEHAVIOR,
ACEReportReasonArray{ ACEReportReason::REPORT_REASON_ILLEGAL_ABUSE, ACEReportReason::REPORT_REASON_ILLEGAL_ADVERTISEMENT },
DNF_REPORT_ENTRANCE_TEST
);
reportInterface->uploadReport(ctx, [this](ACEReportContext ctx, int32_t result, const char* error_message) {
if (result == 0) {
::MessageBoxA(m_hWnd, "Report uploaded successfully!", "Info", MB_OK | MB_ICONINFORMATION);
}
else {
::MessageBoxA(m_hWnd, error_message, "Error", MB_OK | MB_ICONERROR);
}
}
);
return 0;
}
LRESULT CMainDialog::OnNetbarClientLoad(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
TencentNetbarInterface* netbarInterface = m_gameClient.getNetbarInterface();
netbarInterface->beginRequestNetbarStatus(
[this](TencentNetbarInterface::RequestStatus status)
{
// Handle the request status update here
switch (status) {
case TencentNetbarInterface::RS_RequestDone:
::MessageBoxA(m_hWnd, "Netbar status request completed successfully!", "Info", MB_OK | MB_ICONINFORMATION);
break;
case TencentNetbarInterface::RS_ReqestFailed:
::MessageBoxA(m_hWnd, "Netbar status request failed!", "Error", MB_OK | MB_ICONERROR);
break;
default:
// Other statuses can be handled as needed
break;
}
});
return 0;
}
bool IsProcessRunning(DWORD pid)
{
HANDLE hSnapshot = CreateToolhelp32Snapshot(TH32CS_SNAPPROCESS, 0);
if (hSnapshot == INVALID_HANDLE_VALUE) {
return false;
}
PROCESSENTRY32 pe;
pe.dwSize = sizeof(PROCESSENTRY32);
bool isRunning = false;
if (Process32First(hSnapshot, &pe)) {
do {
if (pe.th32ProcessID == pid) {
isRunning = true;
break;
}
} while (Process32Next(hSnapshot, &pe));
}
CloseHandle(hSnapshot);
return isRunning;
}
LRESULT CMainDialog::OnCheckMainPlayProcess(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/)
{
wchar_t wszPid[64];
::GetDlgItemTextW(m_hWnd, IDC_EDIT_MAINPLAY_PID, wszPid, sizeof(wszPid)/sizeof(wchar_t));
DWORD pid = _wtoi(wszPid);
if (pid == 0)
{
::MessageBoxA(m_hWnd, "Invalid PID!", "Error", MB_OK | MB_ICONERROR);
return 0;
}
bool isRunning = IsProcessRunning(pid);
if (isRunning)
{
::MessageBoxA(m_hWnd, "MainPlay process is running.", "Info", MB_OK | MB_ICONINFORMATION);
}
else
{
::MessageBoxA(m_hWnd, "MainPlay process is not running.", "Info", MB_OK | MB_ICONSTOP);
}
return 0;
}
+47
View File
@@ -0,0 +1,47 @@
#pragma once
#include "resource.h"
#include "GameClient.h"
class CMainDialog : public CDialogImpl<CMainDialog>
{
public:
enum { IDD = IDD_DIALOG_MAIN };
BEGIN_MSG_MAP(CMainDialog)
MESSAGE_HANDLER(WM_INITDIALOG, OnInitDialog)
COMMAND_ID_HANDLER(IDOK, OnOK)
COMMAND_ID_HANDLER(IDCANCEL, OnCancel)
MESSAGE_HANDLER(WM_TIMER, OnTimer)
COMMAND_ID_HANDLER(IDC_BUTTON_CONNECT_GAME_SERVER, OnConnectToGameServer)
COMMAND_ID_HANDLER(IDC_BUTTON_DISCONNECT_GAME_SERVER, OnDisconnectToGameServer)
COMMAND_ID_HANDLER(IDC_BUTTON_UGC_SEND, OnSendUGCContent)
COMMAND_ID_HANDLER(IDC_BUTTON_REPORT_SEND, OnSendReport)
COMMAND_ID_HANDLER(IDC_BUTTON_NETBAR_CLIENTLOAD, OnNetbarClientLoad)
COMMAND_ID_HANDLER(IDC_BUTTON_CHECK_MAINPLAY_PROCESS, OnCheckMainPlayProcess)
END_MSG_MAP()
virtual BOOL PreTranslateMessage(MSG* pMsg)
{
return ::IsDialogMessage(m_hWnd, pMsg);
}
private:
LRESULT OnInitDialog(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnOK(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCancel(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnTimer(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/);
LRESULT OnConnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnDisconnectToGameServer(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSendUGCContent(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnSendReport(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnNetbarClientLoad(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
LRESULT OnCheckMainPlayProcess(WORD /*wNotifyCode*/, WORD wID, HWND /*hWndCtl*/, BOOL& /*bHandled*/);
void CloseDialog(int nVal);
protected:
GameClient m_gameClient;
};
+177
View File
@@ -0,0 +1,177 @@
#include "stdafx.h"
#include "NetbarInterface.h"
#include "iigw_api_client.h"
#include "GameProto.h"
#include "GameProto.pb.h"
#include "GameClient.h"
TencentNetbarInterface::TencentNetbarInterface()
{
m_requestStatus.store(RS_NotRequest);
m_workThread = NULL;
m_netbarStatus = NS_Unknown;
m_clientErrorCode = 0;
m_serverErrorCode = 0;
m_serverErrorMessage.clear();
m_netbarLevel = -1;
m_clientNetbarReq = new Game::NetbaraStatusReq();
}
TencentNetbarInterface::~TencentNetbarInterface()
{
delete m_clientNetbarReq;
m_clientNetbarReq = nullptr;
}
void TencentNetbarInterface::init(GameClient* client)
{
m_client = client;
}
void TencentNetbarInterface::tick()
{
switch (m_requestStatus)
{
case RequestStatus::RS_ClientRequest_Done:
{
m_client->sendProtobufMessage(GameProto::GAME_PROTO_NETBAR_REQ, m_clientNetbarReq);
m_requestStatus = RequestStatus::RS_ServerRequesting;
}
break;
case RequestStatus::RS_ClientRequest_Failed:
{
m_requestStatus = RequestStatus::RS_ReqestFailed;
}
break;
}
}
bool TencentNetbarInterface::beginRequestNetbarStatus(RequestCallback callback)
{
if(m_requestStatus==RequestStatus::RS_RequestDone || m_requestStatus==RequestStatus::RS_ReqestFailed)
{
//already done
if(callback)
{
callback(m_requestStatus.load());
}
return true;
}
if(m_requestStatus != RequestStatus::RS_NotRequest)
{
//already requesting
return false;
}
m_requestStatus = RequestStatus::RS_ClientRequesting;
unsigned int threadID = 0;
m_workThread = (HANDLE)_beginthreadex(NULL, 0, TencentNetbarInterface::_workingThreadEntry, this, 0,&threadID);
if(m_workThread == NULL)
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
return false;
}
m_requestCallback = callback;
return true;
}
unsigned int TencentNetbarInterface::_workingThreadEntry(void* param)
{
TencentNetbarInterface* pThis = (TencentNetbarInterface*)param;
if(pThis)
{
pThis->workThreadEntry();
}
::CloseHandle(pThis->m_workThread);
pThis->m_workThread = NULL;
return 0;
}
bool TencentNetbarInterface::workThreadEntry()
{
HMODULE hNetbarDllHandle = NULL;
bool isSuccess = false;
do {
hNetbarDllHandle = ::LoadLibraryW(L"iigw_client_api.dll");
if (hNetbarDllHandle == NULL)
{
m_clientErrorCode = GetLastError();
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
//create interface
iepm_qqwb::IQQNetbarIIGWPlugin *pProxy = iepm_qqwb::CreateQQNetbarIIGWPlugin(hNetbarDllHandle);
if(pProxy == nullptr)
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
//call client interfae
int ret = pProxy->IsNetbarMachine(TENCENT_NETBAR_DNF_CLIENT_GAME_ID, GameClient::s_default_account_id, iepm_qqwb::at_qq);
bool isNetbar = (ret == IIGW_MSG_STATUS_NETBAR_PC);
iepm_qqwb::NetbarLv netbarlv = {0};
memset(&netbarlv, 0, sizeof(netbarlv));
m_clientErrorCode = pProxy->ReqNetbarLv2(
TENCENT_NETBAR_DNF_CLIENT_GAME_ID,
GameClient::s_default_world_id,
GameClient::s_default_account_id,
iepm_qqwb::at_qq,
nullptr,
0,
&netbarlv,
5000
);
if (m_clientErrorCode != 0 || netbarlv.tokenLen<=0 )
{
m_requestStatus = RequestStatus::RS_ClientRequest_Failed;
break;
}
m_clientNetbarReq->Clear();
m_clientNetbarReq->set_is_netbar_machine(isNetbar);
m_clientNetbarReq->set_token((const char*)netbarlv.tokenBuff, (size_t)netbarlv.tokenLen);
m_clientNetbarReq->set_macs(netbarlv.macs);
m_requestStatus = RequestStatus::RS_ClientRequest_Done;
isSuccess = true;
} while (false);
if(hNetbarDllHandle)
{
::FreeLibrary(hNetbarDllHandle);
hNetbarDllHandle = NULL;
}
return isSuccess;
}
void TencentNetbarInterface::onReceiveNetbarReportRequest(Game::NetbarStatusRes* response)
{
m_netbarLevel = response->netbar_level();
m_serverErrorCode = response->error_code();
m_serverErrorMessage = response->error_message();
if (m_serverErrorCode == 0)
{
m_serverErrorCode = NetbarStatus::NS_Netbar;
}
else
{
m_serverErrorCode = NetbarStatus::NS_ServerFailed;
}
m_requestStatus = RequestStatus::RS_RequestDone;
if (m_requestCallback)
{
m_requestCallback(m_requestStatus);
}
}
+69
View File
@@ -0,0 +1,69 @@
#pragma once
#include <functional>
namespace Game
{
class NetbaraStatusReq;
class NetbarStatusRes;
};
class GameClient;
class TencentNetbarInterface
{
public:
TencentNetbarInterface();
~TencentNetbarInterface();
public:
enum RequestStatus
{
RS_NotRequest=0,
RS_ClientRequesting,
RS_ClientRequest_Done,
RS_ClientRequest_Failed,
RS_ServerRequesting,
RS_ReqestFailed,
RS_RequestDone,
};
enum NetbarStatus
{
NS_Unknown = 0,
NS_Netbar,
NS_ClientFailed,
NS_ServerFailed,
};
typedef std::function<void(RequestStatus)> RequestCallback;
bool beginRequestNetbarStatus(RequestCallback callback);
void onReceiveNetbarReportRequest(Game::NetbarStatusRes* response);
void init(GameClient* client);
void tick();
private:
static unsigned int _workingThreadEntry(void* param);
bool workThreadEntry();
private:
enum { TENCENT_NETBAR_DNF_CLIENT_GAME_ID = 20 };
private:
GameClient* m_client = nullptr;
std::atomic<RequestStatus> m_requestStatus;
HANDLE m_workThread;
NetbarStatus m_netbarStatus;
int32_t m_clientErrorCode;
int32_t m_serverErrorCode;
std::string m_serverErrorMessage;
int32_t m_netbarLevel;
RequestCallback m_requestCallback;
Game::NetbaraStatusReq* m_clientNetbarReq = nullptr;
};
Binary file not shown.
Binary file not shown.
+580
View File
@@ -0,0 +1,580 @@
/************************************************************
Copyright (C), 2008-2018, Tencent Tech. Co., Ltd.
FileName: iigw_api_client.h
Author: cooperli Version : 1.0 Date: 2008-03-25
Description: 信息网关API头文件
History:
<author> <time> <version > <desc>
cooperli 2008-03-27 1.0 build
***********************************************************/
#ifndef _ITC_CLIENT_H_
#define _ITC_CLIENT_H_
// VC动态库
#ifdef iigw_client_api_EXPORTS
#define IIGW_DLL_EXPORT __declspec(dllexport)
#else
#define IIGW_DLL_EXPORT
#endif
#ifdef __cplusplus
extern "C"
{
#endif
#define SVR_PROT 5692 // IIGW SERVER 的端口
#define INFOGW_MAX_MSG_LEN 2048 // 最大消息长度为512 BYTE
#define INFOGW_MAX_TO_GAME_SVR_STR_LEN 256 // 最大送到GAME SERVER的串长度为256 BYTE
#define INFOGW_MIN_ERR_BUF_LEN 256 // 最小消息长度为256 BYTE
#define INFOGW_OPEN_ID_LEN 64
// 消息类型定义INFOGW_MSG_TYPE
enum
{
INFOGW_MSG_TYPE_REQ = 1, // 请求消息
INFOGW_MSG_TYPE_ACK = 2, // 回应消息
INFOGW_MSG_TYPE_BOTTOM // 底部,无效值
};
// 消息错误类型定义
enum IIGW_MSG_STATUS
{
IIGW_MSG_STATUS_OK = 0, // 正确消息
IIGW_MSG_STATUS_UNKNOWN_VER_ERR = 1, // MAGIC KEY出错
IIGW_MSG_STATUS_MSG_TYPE_ERR = 2, // 消息类型错误
IIGW_MSG_STATUS_OPT_ERR = 3, // 业务类型出错
IIGW_MSG_STATUS_NO_RETURN = 4, // 没有收到对端的回应
IIGW_MSG_STATUS_CRYPT_LEN_ERR = 5, // TO GAME SVR的消息长度出错
IIGW_MSG_STATUS_MSG_LEN_ERR = 6, // 消息长度出错
IIGW_MSG_STATUS_BUF_LEN_ERR = 7, // 输入BUFFFER长度太少
IIGW_MSG_STATUS_RD_CFG_ERR = 8, // 读配置出错
IIGW_MSG_STATUS_CONNECT_ERR = 9, // 连接出错
IIGW_MSG_STATUS_SENT_MSG_ERR = 10, // 发送消息出错
IIGW_MSG_STATUS_DNS_RESOLVE_ERR = 30, // DNS解释出错,不能把域名解释成IP
IIGW_MSG_STATUS_PARSE_RSP_ERR = 11, // 解析返回包出错
IIGW_MSG_STATUS_PARA_ERR = -1, // 参数出错
// 服务端发现的错误lix
IIGW_MSG_STATUS_UNKNOWN_VER_ERR_R = 101, // MAGIC KEY出错
IIGW_MSG_STATUS_MSG_TYPE_ERR_R = 102, // 消息类型错误
IIGW_MSG_STATUS_OPT_ERR_R = 103, // 业务类型出错
IIGW_MSG_STATUS_HEARD_LEN_ERR_R = 104, // 消息协议头长度出错
IIGW_MSG_STATUS_OPT_LEN_ERR = 105, // 业务信息长度出错
IIGW_MSG_STATUS_OPT_COUNT_ERR = 106, // 业务信息长度出错
IIGW_MSG_STATUS_NET_ERR_R = 107, // 网络通讯出错
IIGW_MSG_STATUS_RES_LIMIT_R = 110, // 资源受限
IIGW_MSG_STATUS_BJ_NEW_USER = 200, // CF !!! 北京新用户,禁止登陆
IIGW_MSG_STATUS_NETBAR_PC = 256, // 是网吧机器
IIGW_MSG_STATUS_NOT_IN_NETBAR = 300, // 非网吧环境
IIGW_MSG_STATUS_NOT_A_CHINESE_OS = 301, // 非中文操作系统
IIGW_MSG_STATUS_VMP_CRC_ERROR = 400,
IIGW_MSG_STATUS_VMP_DEBUG_ERROR = 401,
IIGW_MSG_STATUS_OS_SEH_ERROR = 402,
IIGW_MSG_STATUS_CPP_SEH_ERROR = 403,
IIGW_MSG_STATUS_UNKNOW_ERROR = 404,
IIGW_MSG_STATUS_BOTTOM // 底部,无效值
};
// 业务ID定义 INFOGW_OPERATION_ID
enum
{
INFOGW_OPERATION_CF = 10, // CF查询网吧等级业务ID
INFOGW_OPERATION_DNF = 20, // DNF查询网吧等级业务ID
INFOGW_OPERATION_ID_BOTTOM // 底部,无效值
};
typedef unsigned int UINT;
typedef struct infoGWReqMsgHeader_st
{
UINT uiVersion; // 版本号,认证头
UINT uiMsgType; // 消息类型,可以表示客户端消息,服务后台消息等
UINT uiSeqNo; //
UINT uiTime; // 本地时间戳
UINT uiOperationId; // 查询的业务类型 .参看 enum INFOGW_OPERATION_ID
UINT uiStatus; // 当为接收的信息时有效
UINT uiMsgBodyLen; // 业务消息长度
} INFOGW_INTF_CLIENT_MSG_HEADER;
typedef struct infoGWReqMsg_st
{
INFOGW_INTF_CLIENT_MSG_HEADER stMsgHd;
char szMsgBody[INFOGW_MAX_MSG_LEN]; // 业务相关消息体
} INFOGW_INTF_CLIENT_MSG;
typedef struct infoGWReqNetbarLv_st
{
unsigned int uiUni;
unsigned int ulNetbarIP;
} INFOGW_REQ_NETBAR_LV;
typedef struct infoGWReqNetbarLvOpenid_st
{
unsigned int uiType;
char open_id[INFOGW_OPEN_ID_LEN];
unsigned int ulNetbarIP;
} INFOGW_REQ_NETBAR_LV_OPENID;
// TO GAME SERVER 的的加密串的明文结构
typedef struct IIGWNetbar_st
{
unsigned int ulInfoGWTimeStamp; // 时间截
unsigned int uiUni; // QQ号码
unsigned int ulNetbarIP; // 网吧ip
unsigned char ucNetbarLv; // 网吧等级
//unsigned int ulNetbarLv; // 网吧等级v2
unsigned char ucCreditRank; // 荣誉等级
unsigned char ucTeamRank; // 战队等级
unsigned char ucVIP; // 会员VIP
unsigned char ucCampaign; // 活动
unsigned char ucReserve[15]; // 备用
} INFOGW_NETBAR;
//==============================================================
#define IIGE_MAX_OP_COUNT 15 // 批量查询每次查询的最大业务数量
#define IIGW_CRYPT_BUF_LEN 128 // 批量查询返回加密串缓存区长度
typedef struct IIGW_OPERATIONS
{
int count;
unsigned int uiOperationId[IIGE_MAX_OP_COUNT];
} INFOGW_OPIDS;
typedef struct IIGW_NETBAR_INFO_
{
unsigned int uiOperationId;
int iStatus; // 返回状态:1-正常,0-非正常
unsigned int ucCryptBufLen;
unsigned char szCryptBuf[IIGW_CRYPT_BUF_LEN];
} IIGW_NETBAR_INFO;
typedef struct IIGW_NETBAR_INFO_BATCH_ {
int count;
IIGW_NETBAR_INFO stNetbarInfo[IIGE_MAX_OP_COUNT];
} IIGW_NETBAR_INFO_BATCH;
//==============================================================
/*************************************************
Function: INFOGW_api_req_netbar_lv
Description: 请求查询网吧等级,并等待回应的加密包
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
anselyang 2008-03-25 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen // error buffer size
);
/*************************************************
Function: INFOGW_api_req_netbar_lv_ext
Description: 请求查询网吧等级,并等待回应的加密包 CF活动是否弹出
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
char *op_buf, -- 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len -- 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
anselyang 2009-07-14 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv_ext
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen, // error buffer size
char *op_buf, // 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len // 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
);
/*************************************************
Function: INFOGW_api_req_platinum_netbar_lv
Description: 请求查询铂金网吧等级
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码,没有可填0
Output:
int &level, -- 铂金网吧等级
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2016-11-29 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_platinum_netbar_lv
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
int &level // 铂金网吧等级
);
/*************************************************
Function: INFOGW_api_req_platinum_netbar_lv_ext
Description: 请求查询铂金网吧等级
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码,没有可填0
unsigned int zone_id, -- 游戏大区,没有可填0
Output:
int &level, -- 铂金网吧等级
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2016-11-29 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_platinum_netbar_lv_ext
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
unsigned int zone_id, //游戏大区
int &level // 铂金网吧等级
);
/*************************************************
Function: INFOGW_api_req_netbar_lv_ext_with_zone_id
Description: 请求查询网吧等级,并等待回应的加密包 CF活动是否弹出
Calls: INFOGW_api_set_server
INFOGW_send_recv
Called By: API 外部调用
Table Accessed: NONE
Table Updated: NONE
Input:
const int uiOperationId, -- 业务代码(不同的游戏有不同的业务代码)
unsigned long uiUni, -- QQ号码
unsigned long zone_id, -- 大区ID
const char *cIP, -- 网吧IP
const unsigned char *ticketBuf, -- TGP票据,若不需要填空
const int ticketLen, -- TGP票据长度,若不需要填0
unsigned long errBufLen -- error 的BUFFER大小:不应少于256
INOUT
int *bufLen, -- 输入是ack_buf的最大长度,不应少于256,输出是响应数据长度
Output:
void *cryptInfoBuf, -- 响应数据的BUFFER地址
void *error -- 错误描述的BUFFER地址,输入时BUFFER必需清空,不应少于256
char *op_buf, -- 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len -- 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
Return: 返回0成功,其它为错误码,在iigw_api_client.h enum IIGW_MSG_STATUS中定义
History:
<author> <time> <version > <desc>
cooperli 2017-01-19 1.0 build
*************************************************/
int IIGW_DLL_EXPORT INFOGW_api_req_netbar_lv_ext_with_zone_id
(
const int uiOperationId, // 业务代码
unsigned long uiUni, // QQ No.
unsigned int zone_id, // 游戏大区.
const char *cIP, // netbar ip addr. eg: 192.168.1.1
const unsigned char *ticketBuf, // TGP票据,若不需要填空
const int ticketLen, // TGP票据长度,若不需要填0
unsigned char *cryptInfoBuf, // output crypt info. . include: netbar level, netbar ip , infoGW's timestamp
int *bufLen, // crypt info. len
char *error, // error print char
unsigned long errBufLen, // error buffer size
char *op_buf, // 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
int *op_buf_len, // 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
const int time_out=5000 // 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
);
//////////////////////////////////////////////////////////////////////////
/** QQ网吧插件接口*/
namespace iepm_qqwb{
enum account_type{
at_qq, //0
at_wechart, // 1
at_facebook, //2
at_email, // 3
at_steam, //4
at_gopenid,//5
at_topenid, // 6 手机号对应的openid
};
/**
* @brief NetbarLv QQ网吧签名结构体
* @param tokenBuf 用来存放QQ网吧签名的buff
* @param tokenLen QQ网吧签名的长度
* @param ip PC的ip地址
* @param macs PC的mac地址列表
* @param macSize PC的mac地址个数
*/
struct NetbarLv {
unsigned char tokenBuff[1024];
int tokenLen;
char ip[32];
char macs[128];
int macSize;
};
/**
* @brief notify_req_netbarlv_result 回调函数,返回获取签名的结果和内容
* @param game_id 游戏ID
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id
* @param ret_code 获取签名的结果,返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
* @param netbarlv NetbarLv信息,当ret_code=0时返回
*/
typedef void(*notify_req_netbarlv_result)(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
int ret_code,
NetbarLv *netbarlv
);
struct IQQNetbarIIGWPlugin{
/**
* @brief 获取网吧机器信息
* @param game_id 游戏ID,由网吧项目组这边分配
* @param uin 用户登录游戏的QQ号
* @param zone_id 登录游戏的大区号
* @param cryptInfoBuf 用来存放网吧机器信息的加密串
* @param bufLen 加密串长度
* @param time_out 阻塞时间,单位->毫秒,范围1~10000 ,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int GetNetbarMachineContent(
unsigned int game_id,
unsigned int uin,
unsigned int zone_id,
unsigned char *cryptInfoBuf,
int *bufLen,
const int time_out=5000
) = 0;
/**
* @brief 获取机器是否在网吧
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @return int 返回IIGW_MSG_STATUS_NETBAR_PC表示是网吧机器, IIGW_MSG_STATUS_NOT_IN_NETBAR表示非网吧机器,其他为错误码
*/
virtual int IsNetbarMachine(unsigned int game_id,
const char open_id[INFOGW_OPEN_ID_LEN],
account_type type) = 0;
/**
* @brief 获取机器是否在网吧,该接口仅为pubg使用
* @return bool 返回true表示在网吧
*/
virtual int IsNetbarMachine() = 0;
/**
* @brief ReqNetbarLv 获取网吧等级
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param ticketBuf, TGP票据,若不需要填空
* @param ticketLen, TGP票据长度,若不需要填0
* @param cryptInfoBuf 用来存放网吧机器信息的加密串
* @param bufLen 加密串长度
* @param error, 错误的msg
* @param errBufLen, error buffer size
* @param op_buf, 其他可选BUF 只给CF 活动用 stMsgHd.uiSeqNo
* @param op_buf_len, 其他可选BUF 长度 只给CF 活动用 stMsgHd.uiSeqNo
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @param type 保留字段,open_id帐号类型,0是QQ号,1是微信,【2是facebook,3是邮箱账号,这2个都是wegame自己的opend_id】
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
const unsigned char *ticketBuf,
const int ticketLen,
unsigned char *cryptInfoBuf,
int *bufLen,
char *error,
unsigned long errBufLen,
char *op_buf,
int *op_buf_len,
const int time_out=5000,
unsigned int type = 1
) = 0;
/**
* @brief ReqNetbarLv2 获取网吧等级
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是msdk的gopen_id
* @param ticketBuff, 用户登录游戏时的token,用于登录校验
* @param ticketLen, 用户登录游戏时的token长度
* @param netbarlv 输出参数,参考NetbarLv的声明
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv2(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
unsigned int type,
const char *ticketBuff,
const int ticketLen,
NetbarLv *netbarlv,
const int time_out = 5000
) = 0;
/**
* @brief 获取机器是否在网吧,给PUBG用的接口,其他业务请调用IsNetbarMachine
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @return bool 返回true表示在网吧
*/
virtual int IsNetbar_ForPubg(const char open_id[INFOGW_OPEN_ID_LEN], account_type type) = 0;
/**
* @brief 获取网吧签名token,给PUBG用的接口
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,参考account_type,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是steam账号
* @param opt_token 存储token用的buff,建议长度512
* @param opt_token_len 返回的token 长度
* @return int 返回0成功,返回IIGW_MSG_STATUS_NOT_IN_NETBAR(300)表示非网吧环境,并且opt_token会为空,
其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarToken_ForPubg(const char open_id[INFOGW_OPEN_ID_LEN], account_type type,
char *opt_token, int *opt_token_len) = 0;
/*************************************************
Function: SetProxy
Description: 设置代理,在所有获取等级接口之前调用
History:
<author> <time> <version > <desc>
cooperli 2019-6-11 1.0 build
*************************************************/
virtual void SetProxy(
const char url[INFOGW_OPEN_ID_LEN], // 代理URL
const char user[INFOGW_OPEN_ID_LEN], // 代理账号
const char pwd[INFOGW_OPEN_ID_LEN] // 代理密码
) = 0;
/**
* @brief RegNetbarLvCallback 注册异步获取网吧等级的回调函数,只需调用一次
* @param handle_result 回调函数
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int RegNetbarLvCallback(notify_req_netbarlv_result handle_result) = 0;
/**
* @brief ReqNetbarLv2_Asyn 异步获取网吧等级,调用该函数之前需调用RegNetbarLvCallback注册回调
* @param game_id 游戏ID,由网吧项目组这边分配(对应老接口的uiOperationId)
* @param zone_id 登录游戏的大区号
* @param open_id 用户登录游戏的open_id,最大长度64
* @param type open_id帐号类型,0是QQ号,1是微信,2是facebook,3是邮箱账号,4是msdk的gopen_id
* @param ticketBuff, 用户登录游戏时的token,用于登录校验
* @param ticketLen, 用户登录游戏时的token长度
* @param time_out 阻塞时间,单位->毫秒,范围1~10000,默认值为5000
* @return int 返回0成功,其他为错误码,参考enum IIGW_MSG_STATUS中定义
*/
virtual int ReqNetbarLv2_Asyn(
unsigned int game_id,
unsigned int zone_id,
const char open_id[INFOGW_OPEN_ID_LEN],
unsigned int type,
const char *ticketBuff,
const int ticketLen,
const int time_out = 5000
) = 0;
};
/**
* @brief 创建QQ网吧插件接口
* @param hDll LoadLibrary返回的HMODULE
* @return IQQNetbarIIGWPlugin 失败返回nullptr。该接口内存由插件管理,无需外部释放
*/
inline IQQNetbarIIGWPlugin *CreateQQNetbarIIGWPlugin(HMODULE hDll){
if (!hDll) {
return nullptr;
}
typedef HRESULT (WINAPI *QUERYPLUGININTERFACE)(const char*, void**);
#ifdef _WIN64
QUERYPLUGININTERFACE qpi = (QUERYPLUGININTERFACE)GetProcAddress(hDll,
"QueryPluginInterface");
#else
QUERYPLUGININTERFACE qpi = (QUERYPLUGININTERFACE)GetProcAddress(hDll,
"_QueryPluginInterface@8");
#endif
if (qpi) {
IQQNetbarIIGWPlugin* plugin = nullptr;
HRESULT hresult = qpi("IQQNetbarIIGWPlugin", reinterpret_cast<void**>(&plugin));
if (SUCCEEDED(hresult)) {
return plugin;
}
}
return nullptr;
}
}
#ifdef __cplusplus
}
#endif
#endif // _ITC_CLIENT_H_
+46
View File
@@ -0,0 +1,46 @@
#include "stdafx.h"
#include "MainDialog.h"
CAppModule _Module;
int Run(LPTSTR /*lpCmdLine*/ = NULL, int nCmdShow = SW_SHOWDEFAULT)
{
CMessageLoop theLoop;
_Module.AddMessageLoop(&theLoop);
CMainDialog dlgMain;
if (dlgMain.Create(NULL) == NULL)
{
ATLTRACE(_T("Main dialog creation failed!\n"));
return 0;
}
dlgMain.ShowWindow(nCmdShow);
int nRet = theLoop.Run();
_Module.RemoveMessageLoop();
return nRet;
}
int WINAPI _tWinMain(HINSTANCE hInstance, HINSTANCE /*hPrevInstance*/, LPTSTR lpstrCmdLine, int nCmdShow)
{
HRESULT hRes = ::CoInitialize(NULL);
ATLASSERT(SUCCEEDED(hRes));
// this resolves ATL window thunking problem when Microsoft Layer for Unicode (MSLU) is used
::DefWindowProc(NULL, 0, 0, 0L);
AtlInitCommonControls(ICC_COOL_CLASSES | ICC_BAR_CLASSES); // add flags to support other controls
hRes = _Module.Init(NULL, hInstance);
ATLASSERT(SUCCEEDED(hRes));
int nRet = Run(lpstrCmdLine, nCmdShow);
_Module.Term();
::CoUninitialize();
return nRet;
}
+26
View File
@@ -0,0 +1,26 @@
//{{NO_DEPENDENCIES}}
// Microsoft Visual C++ generated include file.
// Used by aClient.rc
//
#define IDD_DIALOG_MAIN 101
#define IDC_BUTTON_CONNECT_GAME_SERVER 1001
#define IDC_BUTTON_DISCONNECT_GAME_SERVER 1002
#define IDC_BUTTON_UGC_SEND 1003
#define IDC_EDIT1 1004
#define IDC_EDIT_UGC_CONTENT 1004
#define IDC_BUTTON_REPORT_SEND 1005
#define IDC_BUTTON_NETBAR_CLIENTLOAD 1006
#define IDC_EDIT_MAINPLAY_PID 1007
#define IDC_BUTTON1 1008
#define IDC_BUTTON_CHECK_MAINPLAY_PROCESS 1008
// Next default values for new objects
//
#ifdef APSTUDIO_INVOKED
#ifndef APSTUDIO_READONLY_SYMBOLS
#define _APS_NEXT_RESOURCE_VALUE 103
#define _APS_NEXT_COMMAND_VALUE 40001
#define _APS_NEXT_CONTROL_VALUE 1009
#define _APS_NEXT_SYMED_VALUE 101
#endif
#endif
+2
View File
@@ -0,0 +1,2 @@
#include "stdafx.h"
+9
View File
@@ -0,0 +1,9 @@
#pragma once
#include <cy_core.h>
#include <cy_event.h>
#include <cy_network.h>
#include <atlbase.h>
#include <atlapp.h>
#include <atldlgs.h>
+1
View File
@@ -0,0 +1 @@
add_subdirectory(proto)
Binary file not shown.
Binary file not shown.
@@ -0,0 +1,92 @@
#ifndef __ACE_SDK_ACCOUNT_H__
#define __ACE_SDK_ACCOUNT_H__
#include "ace_sdk_common.h"
#pragma pack(push, 1)
#ifndef ACE_SDK_ACCOUNT_TYPE_ENUM
#define ACE_SDK_ACCOUNT_TYPE_ENUM
typedef enum
{
ACE_SDK_ACCOUNT_TYPE_QQ = 1, // QQ Number
ACE_SDK_ACCOUNT_TYPE_WECHAT = 2, // WeChat Openid
ACE_SDK_ACCOUNT_TYPE_BAIDU = 3, // Baidu Account
ACE_SDK_ACCOUNT_TYPE_QQ_OPENID = 4, // QQ Openid
ACE_SDK_ACCOUNT_TYPE_VISITOR = 7, // Visitor
ACE_SDK_ACCOUNT_TYPE_GOPENID = 8, // Gopenid
ACE_SDK_ACCOUNT_TYPE_GOOGLE = 101, // Google Mail
ACE_SDK_ACCOUNT_TYPE_WEGAME_MAIL = 102, // Wegame Mail
ACE_SDK_ACCOUNT_TYPE_4399 = 201, // 4399
ACE_SDK_ACCOUNT_TYPE_GARENA = 202, // Garena
ACE_SDK_ACCOUNT_TYPE_GIANT_NETWORK = 203, // Giant Network
ACE_SDK_ACCOUNT_TYPE_WEGAME = 301, // WeGame Rail ID
ACE_SDK_ACCOUNT_TYPE_STEAM = 302, // Steam
ACE_SDK_ACCOUNT_TYPE_WEGAME_COMMON_ID = 308, // WeGame Common ID
ACE_SDK_ACCOUNT_TYPE_WOODUAN = 312, // WOODUAN
ACE_SDK_ACCOUNT_TYPE_VK = 314, // VK
ACE_SDK_ACCOUNT_TYPE_COMMON_ID = 601, // Common Account
ACE_SDK_ACCOUNT_TYPE_FACEBOOK = 1001, // Facebook
ACE_SDK_ACCOUNT_TYPE_SUPERCELL = 1002, // Supercell
ACE_SDK_ACCOUNT_TYPE_TCOMMIC = 1005, // Tcommic
ACE_SDK_ACCOUNT_TYPE_UPLAY = 1006, // Uplay
ACE_SDK_ACCOUNT_TYPE_PHONE_OPENID = 1014, // Telephone Openid
ACE_SDK_ACCOUNT_TYPE_LINE = 1019, // Line
ACE_SDK_ACCOUNT_TYPE_APPLE = 1020, // Apple
} AceSdkAccountType;
#endif
#ifndef ACE_SDK_ACCOUNT_PLAT_ENUM
#define ACE_SDK_ACCOUNT_PLAT_ENUM
typedef enum
{
ACE_SDK_PLAT_ID_IOS = 0, // IOS
ACE_SDK_PLAT_ID_ANDROID = 1, // Android
ACE_SDK_PLAT_ID_PC_CLIENT = 3, // PC
ACE_SDK_PLAT_ID_LINUX = 4, // Linux
ACE_SDK_PLAT_ID_SWITCH = 6, // Switch client
ACE_SDK_PLAT_ID_MAC = 7, // Mac
ACE_SDK_PLAT_ID_PS_CLIENT = 8, // PS client
ACE_SDK_PLAT_ID_XBOX_CLIENT = 9, // XBOX client
ACE_SDK_PLAT_ID_PC_EMULATOR_CLIENT = 11, // PC Emulator
ACE_SDK_PLAT_ID_HARMONY_MOBILE = 12, // Harmony Mobile
ACE_SDK_PLAT_ID_HARMONY_PC = 13, // Harmony PC
ACE_SDK_PLAT_ID_UNKNOWN = 99,
} AceSdkAccountPlatID;
#endif
#ifndef ACE_SDK_MAX_ACCOUNT_LEN
#define ACE_SDK_MAX_ACCOUNT_LEN 65
#endif
/**
* 1. Some fields below also require filling in on the client side, their consistency between client and server needs to be ensured.
*/
typedef struct
{
/**
* Player's account is a C-style string composed only of printable ascii characters(except spaces) and '\0' terminator.
* Player's account must be unique for the same 'game_id_'.
*/
char account_[ACE_SDK_MAX_ACCOUNT_LEN];
/**
* If it is not defined in 'AceSdkAccountType', fill it with 'AceSdkAccountType::ACE_SDK_ACCOUNT_TYPE_COMMON_ID'.
*/
AceSdkAccountType account_type_;
// Plat ID of player's client.
AceSdkAccountPlatID plat_id_;
// Contact ACE to obtain your game ID.
uint32_t game_id_;
/**
* For games with separate zones, please fill in the zone ID to uniquely identify a zone; for games without separate zones, please fill in 0.
*/
uint32_t world_id_;
} AceSdkAccount;
#pragma pack(pop)
#endif // __ACE_SDK_ACCOUNT_H__
@@ -0,0 +1,21 @@
#ifndef __ACE_SDK_CLIENT_H__
#define __ACE_SDK_CLIENT_H__
#include <stdint.h>
#include "ace_sdk_common.h"
#include "ace_sdk_account.h"
#include "ace_sdk_client_impl.h"
/**
* Initializes the ACE Client SDK.
* This function should be called before any other functions in the ACE Client SDK.
*/
AceSdkResult ace_sdk_client_init();
/**
* Should be called when the game process is exiting.
*/
AceSdkResult ace_sdk_client_deinit();
#endif
@@ -0,0 +1,52 @@
#ifndef __ACE_SDK_CLIENT_ANTI_CHEAT_CORE_H__
#define __ACE_SDK_CLIENT_ANTI_CHEAT_CORE_H__
#include <stdint.h>
#include "ace_sdk_common.h"
#include "ace_sdk_account.h"
#include "ace_sdk_client_impl.h"
/**
* This function should be called when the user logs in succesfully.
* @param account_id The GLOBALLY UNIQUE account ID. Its length must be less than or equal to 64 characters, and each must be printable ASCII characters except space.
* @param account_type Find the account type in AceSdkAccountType, or set to ACE_SDK_ACCOUNT_TYPE_COMMON_ID.
* @param world_id For games with multiple zones, set to the unique zone id, or set to 0.
* @param login_ticket The login ticket. A C-style string which is transfered from the game server by ace_sdk_server_get_ticket() of the ACE server sdk.
* @note For each player, the first 3 parameters must be the same as the fields with same name in the server sdk.
*/
AceSdkResult ace_sdk_client_log_in(const char* account_id, AceSdkAccountType account_type, uint32_t world_id, const char* login_ticket);
/**
* Should be called when the user succesfully logs out from the server.
*/
AceSdkResult ace_sdk_client_log_out();
/** The packet buffer */
typedef struct __AceSdkClientPacket {
/** packer buffer */
uint8_t buffer[2048];
/** packet len */
uint32_t len;
} AceSdkClientPacket;
/**
* Should be called every 100ms once the game connects to the game server, and the packet should be sent through the relay channel.
* @param packet The packet buffer.
* @return ACE_SDK_RESULT_OK if there is a packet that need to be sent, and ACE_SDK_RESULT_NO_PACKET_NEED_SENDING if no packets need to be sent.
* @note This function is thread-safe.
*/
AceSdkResult ace_sdk_client_get_packet(AceSdkClientPacket* out_packet);
/**
* Should be called when game received a packet from the relay channel.
* @param packet Pointer to the packet buffer.
* @param len The length of the packet.
* @note This function is NOT thread-safe. Please call this function from a single thread, or ensure that the calls to this function are sequential and do not overlap.
*/
AceSdkResult ace_sdk_client_on_packet_received(const uint8_t* packet_buffer, uint32_t packet_len);
#endif
@@ -0,0 +1,166 @@
#ifndef __ACE_SDK_CLIENT_IMPL_H__
#define __ACE_SDK_CLIENT_IMPL_H__
#ifndef _WIN32
#error ACE Client SDK is only compatible with Windows programs now.
#endif
#include <stdint.h>
#include <string.h>
#include <windows.h>
#define STRSAFE_NO_DEPRECATE
#include <strsafe.h>
#include "ace_sdk_common.h"
#include "ace_sdk_account.h"
struct __AceSdkClientPacket;
struct __AceSdkClientLightFeaturePacket;
struct __AceSdkClientLightFeature;
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientLogInRoutine)(void*, const char*, uint32_t, uint32_t, const char*);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientLogOutRoutine)(void*);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientDeinitRoutine)(void*);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientGetPacketRoutine)(void*, struct __AceSdkClientPacket* out_packet);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientOnPacketReceivedRoutine)(void*, const uint8_t*, uint32_t);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientGetLightFeaturePacketRoutine)(void*, struct __AceSdkClientLightFeaturePacket*);
typedef AceSdkResult(ACE_SDK_CALL* __AceSdkClientOnLightFeatureReceivedRoutine)(void*, const struct __AceSdkClientLightFeature*);
typedef struct {
void* handle_;
void* deprecated1_;
__AceSdkClientLogOutRoutine log_out_;
__AceSdkClientDeinitRoutine deinit_;
__AceSdkClientGetPacketRoutine get_packet_;
__AceSdkClientOnPacketReceivedRoutine on_packet_received_;
__AceSdkClientLogInRoutine log_in_;
__AceSdkClientGetLightFeaturePacketRoutine get_light_feature_packet_;
__AceSdkClientOnLightFeatureReceivedRoutine on_light_feature_received_;
}__AceSdkClientObject;
typedef struct {
const ACE_CHAR* config_path_;
}__AceSdkClientInitParams;
#ifdef _MSC_VER
__declspec(selectany) __AceSdkClientObject* __ace_sdk_client_object = NULL;
#else
__attribute__((weak)) __AceSdkClientObject* __ace_sdk_client_object = NULL;
#endif
#define __ACE_SDK_CLIENT_VERSION 9
inline int32_t __ace_sdk_get_exe_mod_path(ACE_CHAR* path, uint32_t len)
{
uint32_t ret = GetModuleFileNameW(NULL, path, len);
if (ret == 0 || ret == len)
{
return -1;
}
ACE_CHAR* pos = wcsrchr(path, L'\\');
if (pos == NULL)
{
return -1;
}
*pos = L'\0';
return 0;
}
inline AceSdkResult ace_sdk_client_init()
{
ACE_CHAR full_path[1024];
if (__ace_sdk_get_exe_mod_path(full_path, ARRAYSIZE(full_path)) != 0)
{
return ACE_SDK_RESULT_CALC_PATH_FAILED;
}
#ifdef _WIN64
const ACE_CHAR* dll_path = L"\\AntiCheatExpert\\ACE-Base64.dll";
#else
const ACE_CHAR* dll_path = L"\\AntiCheatExpert\\x86\\ACE-Base32.dll";
#endif
if (FAILED(StringCchCatW(full_path, ARRAYSIZE(full_path), dll_path)))
{
return ACE_SDK_RESULT_CALC_PATH_FAILED;
}
int32_t ret = __ace_sdk_load_library(full_path);
if (ret != 0)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
typedef AceSdkResult(*InitRoutine)(uint32_t, const __AceSdkClientInitParams*, __AceSdkClientObject**);
InitRoutine init = (InitRoutine)__ace_sdk_get_symbol("InitAceClient5");
if (init == NULL)
{
__ace_sdk_unload_library();
return ACE_SDK_RESULT_SYMBOL_NOT_FOUND;
}
return init(__ACE_SDK_CLIENT_VERSION, NULL, &__ace_sdk_client_object);
}
inline AceSdkResult ace_sdk_client_log_in(const char* account_id, AceSdkAccountType account_type, uint32_t world_id, const char* login_token)
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->log_in_(__ace_sdk_client_object->handle_, account_id, (uint32_t)account_type, world_id, login_token);
}
inline AceSdkResult ace_sdk_client_log_out()
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->log_out_(__ace_sdk_client_object->handle_);
}
inline AceSdkResult ace_sdk_client_deinit()
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
AceSdkResult ret = __ace_sdk_client_object->deinit_(__ace_sdk_client_object->handle_);
__ace_sdk_client_object = NULL;
return ret;
}
inline AceSdkResult ace_sdk_client_get_packet(struct __AceSdkClientPacket* out_packet)
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->get_packet_(__ace_sdk_client_object->handle_, out_packet);
}
inline AceSdkResult ace_sdk_client_on_packet_received(const uint8_t* packet, uint32_t len)
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->on_packet_received_(__ace_sdk_client_object->handle_, packet, len);
}
inline AceSdkResult ace_sdk_client_get_light_feature_packet(struct __AceSdkClientLightFeaturePacket* out_packet)
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->get_light_feature_packet_(__ace_sdk_client_object->handle_, out_packet);
}
inline AceSdkResult ace_sdk_client_on_light_feature_received(const struct __AceSdkClientLightFeature* light_feature)
{
if (__ace_sdk_client_object == NULL)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
return __ace_sdk_client_object->on_light_feature_received_(__ace_sdk_client_object->handle_, light_feature);
}
#endif
@@ -0,0 +1,41 @@
#ifndef __ACE_SDK_CLIENT_LIGHT_FEATURE_H__
#define __ACE_SDK_CLIENT_LIGHT_FEATURE_H__
#include <stdint.h>
#include "ace_sdk_common.h"
#include "ace_sdk_account.h"
#include "ace_sdk_client_impl.h"
/** The light feature packet buffer */
typedef struct __AceSdkClientLightFeaturePacket {
/** packer buffer */
uint8_t buffer[1024];
/** packet len */
uint32_t len;
} AceSdkClientLightFeaturePacket;
/* The light feature info. All fields are transfered from the game server.
* See AceSdkLightFeatureResponse in ace_sdk_server_light_feature.h */
typedef struct __AceSdkClientLightFeature {
const char* name;
const uint8_t* data;
uint32_t data_len;
uint32_t crc;
} AceSdkClientLightFeature;
/**
* Should be called every time the client tries to send a packet to the game server.
* @param out_packet packet that should be bind to a game protocol to send to the game server.
*/
AceSdkResult ace_sdk_client_get_light_feature_packet(AceSdkClientLightFeaturePacket* out_packet);
/**
* Should be called when game received the light feature from the game server.
* @param data date received from the game server
*/
AceSdkResult ace_sdk_client_on_light_feature_received(const AceSdkClientLightFeature* data);
#endif
@@ -0,0 +1,234 @@
#ifndef __ACE_SDK_COMMON_H__
#define __ACE_SDK_COMMON_H__
#include <stdint.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <dlfcn.h>
#endif
#ifdef __cplusplus
#define ACE_EXTERN_C extern "C"
#else
#define ACE_EXTERN_C
#endif
#if defined(_WIN32) && !defined(_WIN64)
#define ACE_SDK_CALL __cdecl
#else
#define ACE_SDK_CALL
#endif
#ifdef _WIN32
typedef wchar_t ACE_CHAR;
#else
typedef char ACE_CHAR;
#endif
typedef enum
{
ACE_SDK_RESULT_OK = 0,
ACE_SDK_RESULT_NOT_SUPPORTED = 1,
ACE_SDK_RESULT_INVALID_PARAMETER = 2,
ACE_SDK_RESULT_CALC_PATH_FAILED = 3,
ACE_SDK_RESULT_LOAD_LIBRARY_FAILED = 4,
ACE_SDK_RESULT_UNLOAD_LIBRARY_FAILED = 5,
ACE_SDK_RESULT_SYMBOL_NOT_FOUND = 6,
ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED = 7,
ACE_SDK_RESULT_INTERNAL_ERROR = 8,
ACE_SDK_RESULT_ACCOUNT_TOO_LONG = 9,
ACE_SDK_RESULT_ACCOUNT_ILLEGAL_CHARACTER = 10,
ACE_SDK_RESULT_NO_PACKET_NEED_SENDING = 100,
ACE_SDK_RESULT_ILLEGAL_LOG_IN = 101,
ACE_SDK_RESULT_COMMON_END = 1000,
ACE_SDK_RESULT_DEVELOP_LANGUAGE_BEGIN = 10000,
ACE_SDK_RESULT_PACK_STRUCT_1BYTE_ERROR = 10001,
ACE_SDK_RESULT_UNPACK_STRUCT_1BYTE_ERROR = 10002,
ACE_SDK_RESULT_PACK_STRUCT_1BYTE_LEN_ERROR = 10003,
ACE_SDK_RESLUT_JAVA_JNI_BEGIN = 20001,
ACE_SDK_RESLUT_JAVA_JNI_ENV_NULL = 20002,
ACE_SDK_RESLUT_JAVA_JNI_JVM_NULL = 20003,
ACE_SDK_RESLUT_JAVA_JNI_JOBJECT_NULL = 20004,
ACE_SDK_RESLUT_JAVA_JNI_CLASS_NULL = 20005,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_DATA_FAILED = 20006,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_OFFSET_FAILED = 20007,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_CAPACITY_FAILED = 20008,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_LENGTH_ERROR = 20009,
// Array field must use the pre-defined length
ACE_SDK_RESLUT_JAVA_ARRAY_LENTGH_ERROR = 20010,
ACE_SDK_RESLUT_JAVA_JNI_END = 20100,
ACE_SDK_RESULT_DEVELOP_LANGUAGE_END = 99999,
ACE_SDK_RESULT_BUSI_INTERFACE_BEGIN = 100000,
ACE_SDK_RESLUT_LIGHT_FEATURE_BEGIN = 100001,
ACE_SDK_RESLUT_LIGHT_FEATURE_NOT_OPENED = 100002,
ACE_SDK_RESLUT_LIGHT_FEATURE_END = 100100,
ACE_SDK_RESLUT_UIC_BEGIN = 100101,
ACE_SDK_RESULT_UIC_TEXT_INTERF_CALL_FAILED = 100102,
ACE_SDK_RESULT_UIC_TEXT_CALLBACK_HAS_NOT_SET = 100103,
ACE_SDK_RESULT_UIC_PIC_INTERF_CALL_FAILED = 100104,
ACE_SDK_RESULT_UIC_PIC_CALLBACK_HAS_NOT_SET = 100105,
ACE_SDK_RESLUT_UIC_END = 100200,
ACE_SDK_RESULT_SAFEMODE_BEGIN = 100201,
ACE_SDK_RESULT_SAFEMODE_CALLBACK_HAS_NOT_SET = 100202,
ACE_SDK_RESULT_SAFEMODE_INTERF_CALL_FAILED = 100203,
ACE_SDK_RESULT_SAFEMODE_END = 100300,
ACE_SDK_RESULT_GAME_SESSION_BEGIN = 100301,
ACE_SDK_RESULT_GAME_SESSION_INTERF_CALL_FAILED = 100302,
ACE_SDK_RESULT_GAME_SESSION_END = 100400,
ACE_SDK_RESULT_BUSI_INTERFACE_END = 999999,
ACE_SDK_RESULT_MAX_INT32 = 0x7fffffff,
} AceSdkResult;
// ----------------------------------------------------
// Internal definitions and functions
// ----------------------------------------------------
#ifdef _WIN32
typedef HMODULE __ACE_SDK_MODULE;
#else
typedef void* __ACE_SDK_MODULE;
#endif
#if defined(ACE_CGO)
extern __ACE_SDK_MODULE __ace_sdk_global_module;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) __ACE_SDK_MODULE __ace_sdk_global_module;
#else
__attribute__((weak)) __ACE_SDK_MODULE __ace_sdk_global_module;
#endif
#ifdef _WIN32
inline int32_t __ace_sdk_load_library_win(const ACE_CHAR* path)
{
if (__ace_sdk_global_module != NULL)
{
return ACE_SDK_RESULT_OK;
}
__ace_sdk_global_module = LoadLibraryW(path);
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
inline void* __ace_sdk_get_symbol_win(const char* symbol_name)
{
if (__ace_sdk_global_module == NULL)
{
return NULL;
}
void* func = (void*)GetProcAddress(__ace_sdk_global_module, symbol_name);
return func;
}
inline int32_t __ace_sdk_unload_library_win()
{
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_OK;
}
BOOL ret = FreeLibrary(__ace_sdk_global_module);
__ace_sdk_global_module = NULL;
return ret == TRUE ? ACE_SDK_RESULT_OK : ACE_SDK_RESULT_UNLOAD_LIBRARY_FAILED;
}
#else
inline int32_t __ace_sdk_load_library_linux(const ACE_CHAR* path)
{
char* error = NULL;
if (__ace_sdk_global_module != NULL)
{
return ACE_SDK_RESULT_OK;
}
__ace_sdk_global_module = dlopen(path, RTLD_NOW);
error = dlerror();
if (error)
{
fprintf(stderr, "Open shared library %s failed, %s.\n", path, error);
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
inline void* __ace_sdk_get_symbol_linux(const char* symbol_name)
{
void *func = NULL;
char *error = NULL;
if (__ace_sdk_global_module == NULL)
{
return NULL;
}
func = dlsym(__ace_sdk_global_module, symbol_name);
error = dlerror();
if (error)
{
fprintf(stderr, "dlsym failed, %s.\n", error);
return NULL;
}
return func;
}
inline int32_t __ace_sdk_unload_library_linux()
{
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_OK;
}
int32_t ret = dlclose(__ace_sdk_global_module);
__ace_sdk_global_module = NULL;
if (ret != 0)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
#endif
inline int32_t __ace_sdk_load_library(const ACE_CHAR* path)
{
#ifdef _WIN32
return __ace_sdk_load_library_win(path);
#else
return __ace_sdk_load_library_linux(path);
#endif
}
inline void* __ace_sdk_get_symbol(const char* symbol_name)
{
#ifdef _WIN32
return __ace_sdk_get_symbol_win(symbol_name);
#else
return __ace_sdk_get_symbol_linux(symbol_name);
#endif
}
inline int32_t __ace_sdk_unload_library()
{
#if defined(_WIN32)
return __ace_sdk_unload_library_win();
#else
return __ace_sdk_unload_library_linux();
#endif
}
#endif
@@ -0,0 +1,47 @@
#ifndef __ACE_SDK_PROTOCOL_BINDING_H__
#define __ACE_SDK_PROTOCOL_BINDING_H__
#include <stdint.h>
#include <stdio.h>
#define INIT_FUNC_KEY (0xaa55abca)
namespace AceProtocolBindingSDK
{
#pragma pack(push, 1)
struct AceSdkAntiDataInfo
{
unsigned int anti_data_len_; /* [in] length of anti data */
const unsigned char *anti_data_; /* [in] anti data buffer */
};
#pragma pack(pop)
typedef struct
{
uint64_t xor_key;
uint64_t get_report_data3_ptr;
uint64_t del_report_data_ptr;
uint64_t on_receive_signature;
}SharedMemInfo,*PSharedMemInfo;
typedef struct
{
uint64_t xor_key;
uint64_t report_data_encrypt_ptr;
uint64_t get_encrypt_key_ptr;
}EncryptSharedMemInfo, *PEncryptSharedMemInfo;
//游戏启动时调用该函数初始化共享内存数据
uint32_t __ace_sdk_protocol_binding_init();
//在发送协议时通过该指针调获取安全需要上报的数据
extern void (*g__ace_sdk_get_report_data3)(AceSdkAntiDataInfo*);
//上报完成后调用该函数删除数据
extern void(*g__ace_sdk_del_report_data)(AceSdkAntiDataInfo*);
//下行收到服务端下发的夹带数据调用该函数
extern void(*g__ace_sdk_on_receive_signature)(const char* name, const unsigned char *buf, uint32_t buf_len, uint32_t crc);
}
#endif
#include "ace_sdk_protocol_binding_impl.h"
@@ -0,0 +1,125 @@
#undef BUILD_WITH_UE
#ifdef BUILD_WITH_UE
#include "Windows/AllowWindowsPlatformTypes.h"
#include "Windows/PreWindowsApi.h"
#include <windows.h>
#include "Windows/PostWindowsApi.h"
#include "Windows/HideWindowsPlatformTypes.h"
#else
#include <windows.h>
#endif
#include <strsafe.h>
//#include "ace_sdk_protocol_binding.h"
#define XOR_CHAR(x) (x^(0x2A))
#define SHARED_MEM_SIZE (255)
#define XOR_KEY_SALT (0x255)
namespace AceProtocolBindingSDK
{
enum
{
PROTOCOL_BINDING_ERROR_SUCCESS = 0,
PROTOCOL_BINDING_ERROR_EXE_PATH = 1,
PROTOCOL_BINDING_ERROR_FULL_PATH = 2,
PROTOCOL_BINDING_ERROR_HANDLE_NULL = 3,
PROTOCOL_BINDING_ERROR_CALL_FUNC = 4,
PROTOCOL_BINDING_ERROR_GET_FUNC = 5,
};
void __ace_sdk_get_report_data3(AceSdkAntiDataInfo* report_data);
void __ace_sdk_del_report_data(AceSdkAntiDataInfo* del_data);
void __ace_sdk_on_receive_signature(const char* name, const unsigned char *buf, uint32_t buf_len, uint32_t crc);
void(*g__ace_sdk_get_report_data3)(AceSdkAntiDataInfo*) = __ace_sdk_get_report_data3;
void(*g__ace_sdk_del_report_data)(AceSdkAntiDataInfo*) = __ace_sdk_del_report_data;
void(*g__ace_sdk_on_receive_signature)(const char* name, const unsigned char *buf, uint32_t buf_len, uint32_t crc) = __ace_sdk_on_receive_signature;
inline int32_t __ace_sdk_get_exe_mod_path(wchar_t* path, uint32_t len)
{
uint32_t ret = GetModuleFileNameW(NULL, path, len);
if (ret == 0 || ret == len)
{
return -1;
}
wchar_t* pos = wcsrchr(path, L'\\');
if (pos == NULL)
{
return -1;
}
*pos = L'\0';
return 0;
}
uint32_t __ace_sdk_protocol_binding_init()
{
static bool init_successful = false;
if (init_successful == true)
{
return PROTOCOL_BINDING_ERROR_SUCCESS;
}
auto now_time = GetTickCount64();
uint64_t mem_xor_key = (now_time << 32) | now_time;
SharedMemInfo info;
info.xor_key = mem_xor_key;
info.get_report_data3_ptr = reinterpret_cast<uint64_t>(&g__ace_sdk_get_report_data3) ^ (info.xor_key + XOR_KEY_SALT);
info.del_report_data_ptr = reinterpret_cast<uint64_t>(&g__ace_sdk_del_report_data) ^ (info.xor_key + XOR_KEY_SALT);
info.on_receive_signature = reinterpret_cast<uint64_t>(&g__ace_sdk_on_receive_signature) ^ (info.xor_key + XOR_KEY_SALT);
wchar_t full_path[1024] = { 0 };
if (__ace_sdk_get_exe_mod_path(full_path, ARRAYSIZE(full_path)) != 0)
{
return PROTOCOL_BINDING_ERROR_EXE_PATH;
}
const wchar_t dll_path[] = { L'\\', L'A', L'n', L't', L'i', L'C', L'h', L'e', L'a', L't', L'E', L'x', L'p', L'e', L'r', L't', L'\\', L'A', L'C', L'E', L'-', L'P', L'B', L'C', L'-', L'G', L'a', L'm', L'e', L'6', L'4', L'.', L'd', L'l', L'l', L'\0' };;
if (FAILED(StringCchCatW(full_path, ARRAYSIZE(full_path), dll_path)))
{
return PROTOCOL_BINDING_ERROR_FULL_PATH;
}
auto handle = GetModuleHandleW(full_path);
if (handle == NULL)
{
handle = LoadLibraryW(full_path);
}
if (handle == NULL)
{
return PROTOCOL_BINDING_ERROR_HANDLE_NULL;
}
typedef bool(*InitRoutine)(SharedMemInfo*, uint32_t key);
InitRoutine func = (InitRoutine)GetProcAddress(handle, MAKEINTRESOURCEA(7));
if (func == NULL)
{
return PROTOCOL_BINDING_ERROR_GET_FUNC;
}
bool init_result = func(&info, INIT_FUNC_KEY);
if (init_result == true)
{
init_successful = true;
return PROTOCOL_BINDING_ERROR_SUCCESS;
}
return PROTOCOL_BINDING_ERROR_CALL_FUNC;
}
void __ace_sdk_get_report_data3(AceSdkAntiDataInfo* report_data)
{
}
void __ace_sdk_del_report_data(AceSdkAntiDataInfo* del_data)
{
}
void __ace_sdk_on_receive_signature(const char* name, const unsigned char *buf, uint32_t buf_len, uint32_t crc)
{
}
}
@@ -0,0 +1,92 @@
#ifndef __ACE_SDK_ACCOUNT_H__
#define __ACE_SDK_ACCOUNT_H__
#include "ace_sdk_common.h"
#pragma pack(push, 1)
#ifndef ACE_SDK_ACCOUNT_TYPE_ENUM
#define ACE_SDK_ACCOUNT_TYPE_ENUM
typedef enum
{
ACE_SDK_ACCOUNT_TYPE_QQ = 1, // QQ Number
ACE_SDK_ACCOUNT_TYPE_WECHAT = 2, // WeChat Openid
ACE_SDK_ACCOUNT_TYPE_BAIDU = 3, // Baidu Account
ACE_SDK_ACCOUNT_TYPE_QQ_OPENID = 4, // QQ Openid
ACE_SDK_ACCOUNT_TYPE_VISITOR = 7, // Visitor
ACE_SDK_ACCOUNT_TYPE_GOPENID = 8, // Gopenid
ACE_SDK_ACCOUNT_TYPE_GOOGLE = 101, // Google Mail
ACE_SDK_ACCOUNT_TYPE_WEGAME_MAIL = 102, // Wegame Mail
ACE_SDK_ACCOUNT_TYPE_4399 = 201, // 4399
ACE_SDK_ACCOUNT_TYPE_GARENA = 202, // Garena
ACE_SDK_ACCOUNT_TYPE_GIANT_NETWORK = 203, // Giant Network
ACE_SDK_ACCOUNT_TYPE_WEGAME = 301, // WeGame Rail ID
ACE_SDK_ACCOUNT_TYPE_STEAM = 302, // Steam
ACE_SDK_ACCOUNT_TYPE_WEGAME_COMMON_ID = 308, // WeGame Common ID
ACE_SDK_ACCOUNT_TYPE_WOODUAN = 312, // WOODUAN
ACE_SDK_ACCOUNT_TYPE_VK = 314, // VK
ACE_SDK_ACCOUNT_TYPE_COMMON_ID = 601, // Common Account
ACE_SDK_ACCOUNT_TYPE_FACEBOOK = 1001, // Facebook
ACE_SDK_ACCOUNT_TYPE_SUPERCELL = 1002, // Supercell
ACE_SDK_ACCOUNT_TYPE_TCOMMIC = 1005, // Tcommic
ACE_SDK_ACCOUNT_TYPE_UPLAY = 1006, // Uplay
ACE_SDK_ACCOUNT_TYPE_PHONE_OPENID = 1014, // Telephone Openid
ACE_SDK_ACCOUNT_TYPE_LINE = 1019, // Line
ACE_SDK_ACCOUNT_TYPE_APPLE = 1020, // Apple
} AceSdkAccountType;
#endif
#ifndef ACE_SDK_ACCOUNT_PLAT_ENUM
#define ACE_SDK_ACCOUNT_PLAT_ENUM
typedef enum
{
ACE_SDK_PLAT_ID_IOS = 0, // IOS
ACE_SDK_PLAT_ID_ANDROID = 1, // Android
ACE_SDK_PLAT_ID_PC_CLIENT = 3, // PC
ACE_SDK_PLAT_ID_LINUX = 4, // Linux
ACE_SDK_PLAT_ID_SWITCH = 6, // Switch client
ACE_SDK_PLAT_ID_MAC = 7, // Mac
ACE_SDK_PLAT_ID_PS_CLIENT = 8, // PS client
ACE_SDK_PLAT_ID_XBOX_CLIENT = 9, // XBOX client
ACE_SDK_PLAT_ID_PC_EMULATOR_CLIENT = 11, // PC Emulator
ACE_SDK_PLAT_ID_HARMONY_MOBILE = 12, // Harmony Mobile
ACE_SDK_PLAT_ID_HARMONY_PC = 13, // Harmony PC
ACE_SDK_PLAT_ID_UNKNOWN = 99,
} AceSdkAccountPlatID;
#endif
#ifndef ACE_SDK_MAX_ACCOUNT_LEN
#define ACE_SDK_MAX_ACCOUNT_LEN 65
#endif
/**
* 1. Some fields below also require filling in on the client side, their consistency between client and server needs to be ensured.
*/
typedef struct
{
/**
* Player's account is a C-style string composed only of printable ascii characters(except spaces) and '\0' terminator.
* Player's account must be unique for the same 'game_id_'.
*/
char account_[ACE_SDK_MAX_ACCOUNT_LEN];
/**
* If it is not defined in 'AceSdkAccountType', fill it with 'AceSdkAccountType::ACE_SDK_ACCOUNT_TYPE_COMMON_ID'.
*/
AceSdkAccountType account_type_;
// Plat ID of player's client.
AceSdkAccountPlatID plat_id_;
// Contact ACE to obtain your game ID.
uint32_t game_id_;
/**
* For games with separate zones, please fill in the zone ID to uniquely identify a zone; for games without separate zones, please fill in 0.
*/
uint32_t world_id_;
} AceSdkAccount;
#pragma pack(pop)
#endif // __ACE_SDK_ACCOUNT_H__
@@ -0,0 +1,234 @@
#ifndef __ACE_SDK_COMMON_H__
#define __ACE_SDK_COMMON_H__
#include <stdint.h>
#include <stdio.h>
#ifdef _WIN32
#include <windows.h>
#else
#include <unistd.h>
#include <dlfcn.h>
#endif
#ifdef __cplusplus
#define ACE_EXTERN_C extern "C"
#else
#define ACE_EXTERN_C
#endif
#if defined(_WIN32) && !defined(_WIN64)
#define ACE_SDK_CALL __cdecl
#else
#define ACE_SDK_CALL
#endif
#ifdef _WIN32
typedef wchar_t ACE_CHAR;
#else
typedef char ACE_CHAR;
#endif
typedef enum
{
ACE_SDK_RESULT_OK = 0,
ACE_SDK_RESULT_NOT_SUPPORTED = 1,
ACE_SDK_RESULT_INVALID_PARAMETER = 2,
ACE_SDK_RESULT_CALC_PATH_FAILED = 3,
ACE_SDK_RESULT_LOAD_LIBRARY_FAILED = 4,
ACE_SDK_RESULT_UNLOAD_LIBRARY_FAILED = 5,
ACE_SDK_RESULT_SYMBOL_NOT_FOUND = 6,
ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED = 7,
ACE_SDK_RESULT_INTERNAL_ERROR = 8,
ACE_SDK_RESULT_ACCOUNT_TOO_LONG = 9,
ACE_SDK_RESULT_ACCOUNT_ILLEGAL_CHARACTER = 10,
ACE_SDK_RESULT_NO_PACKET_NEED_SENDING = 100,
ACE_SDK_RESULT_ILLEGAL_LOG_IN = 101,
ACE_SDK_RESULT_COMMON_END = 1000,
ACE_SDK_RESULT_DEVELOP_LANGUAGE_BEGIN = 10000,
ACE_SDK_RESULT_PACK_STRUCT_1BYTE_ERROR = 10001,
ACE_SDK_RESULT_UNPACK_STRUCT_1BYTE_ERROR = 10002,
ACE_SDK_RESULT_PACK_STRUCT_1BYTE_LEN_ERROR = 10003,
ACE_SDK_RESLUT_JAVA_JNI_BEGIN = 20001,
ACE_SDK_RESLUT_JAVA_JNI_ENV_NULL = 20002,
ACE_SDK_RESLUT_JAVA_JNI_JVM_NULL = 20003,
ACE_SDK_RESLUT_JAVA_JNI_JOBJECT_NULL = 20004,
ACE_SDK_RESLUT_JAVA_JNI_CLASS_NULL = 20005,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_DATA_FAILED = 20006,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_OFFSET_FAILED = 20007,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_CAPACITY_FAILED = 20008,
ACE_SDK_RESLUT_JAVA_JNI_REFLECT_BS_LENGTH_ERROR = 20009,
// Array field must use the pre-defined length
ACE_SDK_RESLUT_JAVA_ARRAY_LENTGH_ERROR = 20010,
ACE_SDK_RESLUT_JAVA_JNI_END = 20100,
ACE_SDK_RESULT_DEVELOP_LANGUAGE_END = 99999,
ACE_SDK_RESULT_BUSI_INTERFACE_BEGIN = 100000,
ACE_SDK_RESLUT_LIGHT_FEATURE_BEGIN = 100001,
ACE_SDK_RESLUT_LIGHT_FEATURE_NOT_OPENED = 100002,
ACE_SDK_RESLUT_LIGHT_FEATURE_END = 100100,
ACE_SDK_RESLUT_UIC_BEGIN = 100101,
ACE_SDK_RESULT_UIC_TEXT_INTERF_CALL_FAILED = 100102,
ACE_SDK_RESULT_UIC_TEXT_CALLBACK_HAS_NOT_SET = 100103,
ACE_SDK_RESULT_UIC_PIC_INTERF_CALL_FAILED = 100104,
ACE_SDK_RESULT_UIC_PIC_CALLBACK_HAS_NOT_SET = 100105,
ACE_SDK_RESLUT_UIC_END = 100200,
ACE_SDK_RESULT_SAFEMODE_BEGIN = 100201,
ACE_SDK_RESULT_SAFEMODE_CALLBACK_HAS_NOT_SET = 100202,
ACE_SDK_RESULT_SAFEMODE_INTERF_CALL_FAILED = 100203,
ACE_SDK_RESULT_SAFEMODE_END = 100300,
ACE_SDK_RESULT_GAME_SESSION_BEGIN = 100301,
ACE_SDK_RESULT_GAME_SESSION_INTERF_CALL_FAILED = 100302,
ACE_SDK_RESULT_GAME_SESSION_END = 100400,
ACE_SDK_RESULT_BUSI_INTERFACE_END = 999999,
ACE_SDK_RESULT_MAX_INT32 = 0x7fffffff,
} AceSdkResult;
// ----------------------------------------------------
// Internal definitions and functions
// ----------------------------------------------------
#ifdef _WIN32
typedef HMODULE __ACE_SDK_MODULE;
#else
typedef void* __ACE_SDK_MODULE;
#endif
#if defined(ACE_CGO)
extern __ACE_SDK_MODULE __ace_sdk_global_module;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) __ACE_SDK_MODULE __ace_sdk_global_module;
#else
__attribute__((weak)) __ACE_SDK_MODULE __ace_sdk_global_module;
#endif
#ifdef _WIN32
inline int32_t __ace_sdk_load_library_win(const ACE_CHAR* path)
{
if (__ace_sdk_global_module != NULL)
{
return ACE_SDK_RESULT_OK;
}
__ace_sdk_global_module = LoadLibraryW(path);
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
inline void* __ace_sdk_get_symbol_win(const char* symbol_name)
{
if (__ace_sdk_global_module == NULL)
{
return NULL;
}
void* func = (void*)GetProcAddress(__ace_sdk_global_module, symbol_name);
return func;
}
inline int32_t __ace_sdk_unload_library_win()
{
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_OK;
}
BOOL ret = FreeLibrary(__ace_sdk_global_module);
__ace_sdk_global_module = NULL;
return ret == TRUE ? ACE_SDK_RESULT_OK : ACE_SDK_RESULT_UNLOAD_LIBRARY_FAILED;
}
#else
inline int32_t __ace_sdk_load_library_linux(const ACE_CHAR* path)
{
char* error = NULL;
if (__ace_sdk_global_module != NULL)
{
return ACE_SDK_RESULT_OK;
}
__ace_sdk_global_module = dlopen(path, RTLD_NOW);
error = dlerror();
if (error)
{
fprintf(stderr, "Open shared library %s failed, %s.\n", path, error);
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
inline void* __ace_sdk_get_symbol_linux(const char* symbol_name)
{
void *func = NULL;
char *error = NULL;
if (__ace_sdk_global_module == NULL)
{
return NULL;
}
func = dlsym(__ace_sdk_global_module, symbol_name);
error = dlerror();
if (error)
{
fprintf(stderr, "dlsym failed, %s.\n", error);
return NULL;
}
return func;
}
inline int32_t __ace_sdk_unload_library_linux()
{
if (__ace_sdk_global_module == NULL)
{
return ACE_SDK_RESULT_OK;
}
int32_t ret = dlclose(__ace_sdk_global_module);
__ace_sdk_global_module = NULL;
if (ret != 0)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
#endif
inline int32_t __ace_sdk_load_library(const ACE_CHAR* path)
{
#ifdef _WIN32
return __ace_sdk_load_library_win(path);
#else
return __ace_sdk_load_library_linux(path);
#endif
}
inline void* __ace_sdk_get_symbol(const char* symbol_name)
{
#ifdef _WIN32
return __ace_sdk_get_symbol_win(symbol_name);
#else
return __ace_sdk_get_symbol_linux(symbol_name);
#endif
}
inline int32_t __ace_sdk_unload_library()
{
#if defined(_WIN32)
return __ace_sdk_unload_library_win();
#else
return __ace_sdk_unload_library_linux();
#endif
}
#endif
@@ -0,0 +1,124 @@
#ifndef __ACE_SDK_SERVER_H__
#define __ACE_SDK_SERVER_H__
#include "ace_sdk_common.h"
#pragma pack(push, 1)
#define ACE_SDK_MAX_LIBRARY_DIR_LENGTH 1024
#define ACE_SDK_MAX_TOKEN_LENGTH 128
/**
AceSdkServerLibraryInfo
*/
typedef struct __AceSdkServerLibraryInfo
{
/**
* Need to end with 0
* Directory of libace_sdk.so(linux) or ace_sdk.dll(windows)
*/
ACE_CHAR library_dir_[ACE_SDK_MAX_LIBRARY_DIR_LENGTH];
} AceSdkServerLibraryInfo;
/**
AceSdkServerAuthInfo
*/
typedef struct __AceSdkServerAuthInfo
{
uint32_t game_id_;
/**
* Need to end with 0
* Contact ACE to obtain your token
*/
char auth_token_[ACE_SDK_MAX_TOKEN_LENGTH];
} AceSdkServerAuthInfo;
/**
AceSdkServerRegion
*/
typedef enum __AceSdkServerRegion
{
/**
* Mainland, China, excluding Hong Kong, Macao and Taiwan..
*/
ACE_SDK_REGION_CHINA_MAINLAND = 101,
/**
* Hong Kong, China
*/
ACE_SDK_REGION_CHINA_HONGKONG = 102,
/**
* Macao, China
*/
ACE_SDK_REGION_CHINA_MACAO = 103,
/**
* Taiwan, China
*/
ACE_SDK_REGION_CHINA_TAIWAN = 104,
/**
* All regions of the Asia except for those defined accurately in this enumeration.
*/
ACE_SDK_REGION_ASIA = 200,
/**
* All regions of the Europe except for those defined accurately in this enumeration.
*/
ACE_SDK_REGION_EUROPE = 300,
/**
* All regions of the America except for those defined accurately in this enumeration.
*/
ACE_SDK_REGION_AMERICA = 400,
} AceSdkServerRegion;
/**
AceSdkGameDistributor
*/
typedef enum __AceSdkGameDistributor
{
/**
* This option usually means:
* 1. the game servers are deployed on Tencent’s intranet (mainland China), or
* 2. the game servers are deployed on Tencent Cloud (Oversea). In this case, you need remember to enable the server to access the public network through the TCP protocol.
*/
ACE_SDK_GAME_DISTRIBUTOR_TENCENT = 1,
/**
* If use this option, you need remember to enable the server to access the public network through the TCP protocol.
*/
ACE_SDK_GAME_DISTRIBUTOR_COMMON = 1000,
} AceSdkGameDistributor;
/**
AceSdkServerDeploymentInfo
*/
typedef struct __AceSdkServerDeploymentInfo
{
/**
It indicates where the game server reports data. So it is necessary to fill it with the most suitable value in the enumeration.
If the game server is deployed in mutiple regions,
case 1: Game servers in different regions are assigned different game ids(they generally are), it is necessary to fill it according to gameid.
case 2: Game servers in different regions are assigned same game id, it is necessary to fill it as ACE_SDK_REGION_ASIA and contact ACE to confirm it.
*/
AceSdkServerRegion region_;
/**
Game distributor
*/
AceSdkGameDistributor distributor_;
} AceSdkServerDeploymentInfo;
#pragma pack(pop)
/**
@brief Init ACE SDK of server side. It must be called before using any other interfaces.
@param library It indicates where the libace_sdk.so/ace_sdk.dll is located.
@param auth_info Authentication info which is provided by ACE.
@param deployment_info Deployment info of the game server.
*/
AceSdkResult ace_sdk_server_init(const AceSdkServerLibraryInfo* library_info, const AceSdkServerAuthInfo* auth_info, const AceSdkServerDeploymentInfo* deployment_info);
/**
@brief Deinit ACE SDK of server side. It could be called before process is ready to exist.
*/
AceSdkResult ace_sdk_server_deinit();
#include "ace_sdk_server_impl.h"
#endif // __ACE_SDK_SERVER_H__
@@ -0,0 +1,81 @@
#ifndef __ACE_SDK_SERVER_ANTI_CHEAT_CORE_H__
#define __ACE_SDK_SERVER_ANTI_CHEAT_CORE_H__
#include "ace_sdk_account.h"
#include "ace_sdk_server_anti_cheat_core_impl.h"
#pragma pack(push, 1)
#ifndef ACE_SDK_MAX_PLAYER_ROLE_NAME
#define ACE_SDK_MAX_PLAYER_ROLE_NAME 1024
#endif
#ifndef ACE_SDK_MAX_PACKET_SIZE
#define ACE_SDK_MAX_PACKET_SIZE (2 * 1024)
#endif
#ifndef ACE_SDK_MAX_PACKET_NUM
#define ACE_SDK_MAX_PACKET_NUM 100
#endif
typedef struct __AceSdkPlayerAddInfo
{
char role_name_[ACE_SDK_MAX_PLAYER_ROLE_NAME];
} AceSdkPlayerAddInfo;
typedef struct __AceSdkServerPacket
{
/**
* It indicates the account to which the packet belongs.
*/
AceSdkAccount account_;
/**
* It represents the actual length of 'packet_buffer_'.
*/
uint32_t packet_len_;
uint8_t packet_buffer_[ACE_SDK_MAX_PACKET_SIZE];
} AceSdkServerPacket;
typedef struct __AceSdkServerPacketList
{
/**
* if 'packet_num_' is 0, it means that there is no data to send to the ACE client currently.
*/
uint32_t packet_num_;
AceSdkServerPacket packets_[ACE_SDK_MAX_PACKET_NUM];
} AceSdkServerPacketList;
#pragma pack(pop)
/**
* @brief It must be called after player logins the game immediately.
* @brief If player's client reconnects to game server successfully after calling 'del_player_', it also should be called.
* @param account Account for player.
* @param info Additional Information for Player.
*/
AceSdkResult ace_sdk_server_add_player(const AceSdkAccount* account, const AceSdkPlayerAddInfo* info);
/**
* @brief It must be called every 60 seconds between calling 'add_player_' and 'del_player_'.
* @brief It should not be called before calling 'add_player_' or after calling 'del_player_'.
* @param account Account for player.
*/
AceSdkResult ace_sdk_server_keep_alive_player(const AceSdkAccount* account);
/**
* @brief It must be called after player logouts the game immediately.
* @brief If game server losts the connection of player's client, it also should be called.
* @param account Account for player.
*/
AceSdkResult ace_sdk_server_delete_player(const AceSdkAccount* account);
/**
* @brief It must be called when receive anti cheat packet from client
* @param packet Packet that received from ACE client and need to be sent to ACE backend.
*/
AceSdkResult ace_sdk_server_on_packet_received(const AceSdkServerPacket* packet);
/**
* @brief must be called more than 1000 times per second.The faster and more uniform the frequency, the better.
*/
AceSdkResult ace_sdk_server_get_packet(AceSdkServerPacketList* packets);
#endif // __ACE_SDK_SERVER_ANTI_CHEAT_CORE_H__
@@ -0,0 +1,115 @@
#ifndef __ACE_SDK_SERVER_ANTI_CHEAT_CORE_IMPL_H__
#define __ACE_SDK_SERVER_ANTI_CHEAT_CORE_IMPL_H__
#include "ace_sdk_server.h"
struct __AceSdkPlayerAddInfo;
struct __AceSdkServerPacket;
struct __AceSdkServerPacketList;
/***
* Internal functions' implementation
*/
#pragma pack(push, 1)
typedef int32_t(ACE_SDK_CALL* __AceSdkServerAddPlayer)(const AceSdkAccount*, const struct __AceSdkPlayerAddInfo*);
typedef int32_t(ACE_SDK_CALL* __AceSdkServerKeepAlivePlayer)(const AceSdkAccount*);
typedef int32_t(ACE_SDK_CALL* __AceSdkServerDeletePlayer)(const AceSdkAccount*);
typedef int32_t(ACE_SDK_CALL* __AceSdkServerOnPacketReceived)(const struct __AceSdkServerPacket*);
typedef int32_t(ACE_SDK_CALL* __AceSdkServerGetPacket)(struct __AceSdkServerPacketList*);
typedef struct
{
__AceSdkServerAddPlayer add_player_;
__AceSdkServerKeepAlivePlayer keep_alive_player_;
__AceSdkServerDeletePlayer del_player_;
__AceSdkServerOnPacketReceived on_packet_received_;
__AceSdkServerGetPacket get_packet_;
} __AceSdkServerAntiCheatCoreObject;
#pragma pack(pop)
#if defined(ACE_CGO)
extern __AceSdkServerAntiCheatCoreObject* __ace_sdk_server_anti_cheat_core_object;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) __AceSdkServerAntiCheatCoreObject* __ace_sdk_server_anti_cheat_core_object = NULL;
#else
__attribute__((weak)) __AceSdkServerAntiCheatCoreObject* __ace_sdk_server_anti_cheat_core_object = NULL;
#endif
inline int32_t __ace_sdk_server_anti_cheat_core_init()
{
if (__ace_sdk_init_succ == 0)
{
return -1;
}
if (__ace_sdk_server_anti_cheat_core_object != NULL)
{
return 0;
}
typedef __AceSdkServerAntiCheatCoreObject* (ACE_SDK_CALL*__AceSdkServerGetAntiCheatCoreObject)();
__AceSdkServerGetAntiCheatCoreObject func = (__AceSdkServerGetAntiCheatCoreObject)__ace_sdk_get_symbol("__ace_sdk_server_get_anti_cheat_core_object");
if (func == NULL)
{
return -1;
}
__ace_sdk_server_anti_cheat_core_object = func();
if (__ace_sdk_server_anti_cheat_core_object == NULL)
{
return -1;
}
return 0;
}
inline AceSdkResult ace_sdk_server_add_player(const AceSdkAccount* account, const struct __AceSdkPlayerAddInfo* info)
{
if (__ace_sdk_server_anti_cheat_core_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_anti_cheat_core_object->add_player_(account, info);
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_keep_alive_player(const AceSdkAccount* account)
{
if (__ace_sdk_server_anti_cheat_core_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_anti_cheat_core_object->keep_alive_player_(account);
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_delete_player(const AceSdkAccount* account)
{
if (__ace_sdk_server_anti_cheat_core_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_anti_cheat_core_object->del_player_(account);
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_on_packet_received(const struct __AceSdkServerPacket* packet)
{
if (__ace_sdk_server_anti_cheat_core_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_anti_cheat_core_object->on_packet_received_(packet);
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_get_packet(struct __AceSdkServerPacketList* packets)
{
if (__ace_sdk_server_anti_cheat_core_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_anti_cheat_core_object->get_packet_(packets);
return ACE_SDK_RESULT_OK;
}
#endif // __ACE_SDK_SERVER_ANTI_CHEAT_CORE_IMPL_H__
@@ -0,0 +1,211 @@
#ifndef __ACE_SDK_SERVER_IMPL_H__
#define __ACE_SDK_SERVER_IMPL_H__
#include "ace_sdk_common.h"
struct __AceSdkServerLibraryInfo;
struct __AceSdkServerAuthInfo;
struct __AceSdkServerDeploymentInfo;
#define ACE_SDK_SERVER_MAX_GAME_DEV_LANGUAGE_LEN 64
#pragma pack(push, 1)
typedef struct
{
char library_path_[ACE_SDK_MAX_LIBRARY_DIR_LENGTH * 2];
char game_dev_language_[ACE_SDK_SERVER_MAX_GAME_DEV_LANGUAGE_LEN];
} AceSdkServerExtendInfo;
#pragma pack(pop)
#if defined(ACE_CGO)
extern int __ace_sdk_init_succ;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) int __ace_sdk_init_succ = 0;
#else
__attribute__((weak)) int __ace_sdk_init_succ = 0;
#endif
/***
* Internal functions' implementation
*/
inline AceSdkResult ace_sdk_server_report_extend_info(const AceSdkServerExtendInfo* extend_info)
{
if (extend_info == NULL)
{
return ACE_SDK_RESULT_OK;
}
typedef int(ACE_SDK_CALL* AceSdkServerExtendInfoReport)(const AceSdkServerExtendInfo* info);
AceSdkServerExtendInfoReport func_extend_info = (AceSdkServerExtendInfoReport)__ace_sdk_get_symbol("__ace_sdk_server_extend_info");
if (func_extend_info != NULL)
{
func_extend_info(extend_info);
}
return ACE_SDK_RESULT_OK;
}
/**
* Initialize the SDK using the specified interface.
*/
inline AceSdkResult ace_sdk_server_init_specified(const struct __AceSdkServerLibraryInfo* library_info, const struct __AceSdkServerAuthInfo* auth_info, const struct __AceSdkServerDeploymentInfo* deployment_info, const char* name)
{
int32_t ret = ACE_SDK_RESULT_OK;
if (library_info == NULL || auth_info == NULL || deployment_info == NULL || name == NULL)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
ACE_CHAR library_path[ACE_SDK_MAX_LIBRARY_DIR_LENGTH * 2] = {0};
#ifdef _WIN32
_snwprintf_s(library_path, sizeof(library_path)/sizeof(library_path[0]), _TRUNCATE, L"%s/%s", library_info->library_dir_, L"ace_sdk.dll");
#else
snprintf(library_path, sizeof(library_path), "%s/%s", library_info->library_dir_, "libace_sdk.so");
#endif
ret = __ace_sdk_load_library(library_path);
if (ret != 0)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
typedef int(ACE_SDK_CALL* AceSdkServerInit)(const struct __AceSdkServerAuthInfo*, const struct __AceSdkServerDeploymentInfo*);
AceSdkServerInit func = (AceSdkServerInit)__ace_sdk_get_symbol(name);
if (func == NULL)
{
return ACE_SDK_RESULT_SYMBOL_NOT_FOUND;
}
ret = func(auth_info, deployment_info);
if (ret != 0)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
__ace_sdk_init_succ = 1;
// report extend info
AceSdkServerExtendInfo extend_info;
#ifdef _WIN32
char library_path_utf8[ACE_SDK_MAX_LIBRARY_DIR_LENGTH] = {0};
int library_path_utf8_len = WideCharToMultiByte(CP_UTF8, 0, library_info->library_dir_, -1, library_path_utf8, sizeof(library_path_utf8)-1, NULL, NULL);
if (library_path_utf8_len <= 0)
{
return ACE_SDK_RESULT_OK;
}
library_path_utf8[library_path_utf8_len] = 0;
snprintf(extend_info.library_path_, sizeof(extend_info.library_path_), "%s/%s", library_path_utf8, "ace_sdk.dll");
#else
snprintf(extend_info.library_path_, sizeof(extend_info.library_path_), "%s/%s", library_info->library_dir_, "libace_sdk.so");
#endif
snprintf(extend_info.game_dev_language_, sizeof(extend_info.game_dev_language_), "C/C++");
ace_sdk_server_report_extend_info(&extend_info);
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_init(const struct __AceSdkServerLibraryInfo* library_info, const struct __AceSdkServerAuthInfo* auth_info, const struct __AceSdkServerDeploymentInfo* deployment_info)
{
return ace_sdk_server_init_specified(library_info, auth_info, deployment_info, "__ace_sdk_server_init");
}
inline AceSdkResult ace_sdk_server_init_without_proc(const struct __AceSdkServerLibraryInfo* library_info, const struct __AceSdkServerAuthInfo* auth_info, const struct __AceSdkServerDeploymentInfo* deployment_info)
{
return ace_sdk_server_init_specified(library_info, auth_info, deployment_info, "__ace_sdk_server_init_without_proc");
}
inline AceSdkResult ace_sdk_server_proc()
{
if (!__ace_sdk_init_succ)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
typedef int(ACE_SDK_CALL* ace_sdk_server_proc)();
ace_sdk_server_proc func = (ace_sdk_server_proc)__ace_sdk_get_symbol("__ace_sdk_server_proc");
if (func != NULL)
{
func();
}
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_deinit()
{
int32_t ret = ACE_SDK_RESULT_OK;
__ace_sdk_init_succ = 0;
typedef int(ACE_SDK_CALL* AceSdkServerDeinit)();
AceSdkServerDeinit func = (AceSdkServerDeinit)__ace_sdk_get_symbol("__ace_sdk_server_deinit");
if (func != NULL)
{
func();
}
ret = __ace_sdk_unload_library();
if (ret != 0)
{
return ACE_SDK_RESULT_UNLOAD_LIBRARY_FAILED;
}
return ACE_SDK_RESULT_OK;
}
/***
* Internal functions' implementation for special usage
*/
#pragma pack(push, 1)
/**
AceSdkServerEnvType
*/
typedef enum
{
ACE_SDK_SERVER_TEST = 101,
ACE_SDK_SERVER_PRODUCT = 1001
} AceSdkServerEnvType;
/**
AceSdkServerNetworkType
*/
typedef enum
{
ACE_SDK_SERVER_INTRA_NET = 0,
ACE_SDK_SERVER_PUBLIC_NET = 1,
} AceSdkServerNetType;
/**
AceSdkServerAccessInfo
*/
#define ACE_SDK_SERVER_MAX_DOMAIN_LEN 1024
typedef struct
{
char product_data_proxy_[ACE_SDK_SERVER_MAX_DOMAIN_LEN];
char product_busi_proxy_[ACE_SDK_SERVER_MAX_DOMAIN_LEN];
char test_data_proxy_[ACE_SDK_SERVER_MAX_DOMAIN_LEN];
char test_busi_proxy_[ACE_SDK_SERVER_MAX_DOMAIN_LEN];
AceSdkServerEnvType env_type_;
AceSdkServerNetType net_type_;
} AceSdkServerAccessInfo;
#pragma pack(pop)
inline AceSdkResult ace_sdk_server_customized_init(const struct __AceSdkServerLibraryInfo* library_info, const struct __AceSdkServerAuthInfo* auth_info, const AceSdkServerAccessInfo* access_info)
{
int32_t ret = ACE_SDK_RESULT_OK;
ACE_CHAR library_path[ACE_SDK_MAX_LIBRARY_DIR_LENGTH * 2] = {0};
#ifdef _WIN32
_snwprintf_s(library_path, sizeof(library_path)/sizeof(library_path[0]), _TRUNCATE, L"%s/%s", library_info->library_dir_, L"ace_sdk.dll");
#else
snprintf(library_path, sizeof(library_path), "%s/%s", library_info->library_dir_, "libace_sdk.so");
#endif
ret = __ace_sdk_load_library(library_path);
if (ret != 0)
{
return ACE_SDK_RESULT_LOAD_LIBRARY_FAILED;
}
typedef int(ACE_SDK_CALL* AceSdkServerInit)(const struct __AceSdkServerAuthInfo*, const AceSdkServerAccessInfo*);
AceSdkServerInit func = (AceSdkServerInit)__ace_sdk_get_symbol("__ace_sdk_server_customized_init");
if (func == NULL)
{
return ACE_SDK_RESULT_SYMBOL_NOT_FOUND;
}
ret = func(auth_info, access_info);
if (ret != 0)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
__ace_sdk_init_succ = 1;
return ACE_SDK_RESULT_OK;
}
#endif // __ACE_SDK_SERVER_IMPL_H__
@@ -0,0 +1,62 @@
#ifndef __ACE_SDK_SERVER_LIGHT_FEATURE_H__
#define __ACE_SDK_SERVER_LIGHT_FEATURE_H__
#include "ace_sdk_account.h"
#include "ace_sdk_server_light_feature_impl.h"
#pragma pack(push, 1)
#define ACE_SDK_MAX_CLIENT_VERSION_LEN 256
#define ACE_SDK_MAX_LIGHT_FEATURE_NAME_LEN 256
#define ACE_SDK_MAX_LIGHT_FEATURE_DATA_LEN (128 * 1024)
/**
* TssSdkGetFeatureUserInfo
*/
typedef struct __AceSdkLightFeatureRequest
{
/**
* Version of the client: string separated by '.'
*/
char client_version_[ACE_SDK_MAX_CLIENT_VERSION_LEN];
} AceSdkLightFeatureRequest;
/**
* AceSdkLightFeatureResponse
*/
typedef struct __AceSdkLightFeatureResponse
{
/**
* Actual length of the light feature. 0 means that no light features are matched.
*/
int32_t data_len_;
/**
* Binary content of the light feature.
*/
char data_[ACE_SDK_MAX_LIGHT_FEATURE_DATA_LEN];
/**
* Name of the light feature(C-style string). It is recommended to log it along with the account for trouble shooting.
*/
char name_[ACE_SDK_MAX_LIGHT_FEATURE_NAME_LEN];
/**
* CRC32 of the light feature data. It is recommended to log it along with the account for trouble shooting.
*/
uint32_t data_crc_;
} AceSdkLightFeatureResponse;
#pragma pack(pop)
/**
* @brief It must be called after player logins the game as soon as possible.
* @param account Account of player.
* @param request Information for matching light feature.
* @param response Information of light feature.
* @returns Non-0 : Contact ACE to handle it.
* 0 : If 'data_len_' is not 0, send light feature data('data_') to ACE client with the actual length('data_len_') and guarante success.
* If 'data_len_' is 0, do nothing.
* @note If light feature is matched but not sent to ACE client successfully and immediately, players may be punished wrongly by ACE.
*/
AceSdkResult ace_sdk_server_get_light_feature(const AceSdkAccount* account, const AceSdkLightFeatureRequest* request, AceSdkLightFeatureResponse* response);
#endif // __ACE_SDK_SERVER_LIGHT_FEATURE_H__
@@ -0,0 +1,63 @@
#ifndef __ACE_SDK_SERVER_LIGHT_FEATURE_IMPL_H__
#define __ACE_SDK_SERVER_LIGHT_FEATURE_IMPL_H__
#include "ace_sdk_server.h"
struct __AceSdkLightFeatureRequest;
struct __AceSdkLightFeatureResponse;
#if defined(ACE_CGO)
extern int __ace_sdk_light_feature_init_succ;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) int __ace_sdk_light_feature_init_succ = 0;
#else
__attribute__((weak)) int __ace_sdk_light_feature_init_succ = 0;
#endif
inline int ace_sdk_server_init_light_feature() {
int ret = 0;
if (!__ace_sdk_init_succ)
{
return -1;
}
if (__ace_sdk_light_feature_init_succ)
{
return ret;
}
typedef int32_t(ACE_SDK_CALL* __AceSdkServerInitLightFeature)();
__AceSdkServerInitLightFeature func = (__AceSdkServerInitLightFeature)__ace_sdk_get_symbol("__ace_sdk_server_init_light_feature");
if (func == NULL)
{
return -1;
}
ret = func();
if (ret == 0)
{
__ace_sdk_light_feature_init_succ = 1;
}
return ret;
}
inline AceSdkResult ace_sdk_server_get_light_feature(const AceSdkAccount* account, const struct __AceSdkLightFeatureRequest* request, struct __AceSdkLightFeatureResponse* response)
{
if (ace_sdk_server_init_light_feature() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
if (account == NULL || request == NULL || response == NULL)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
typedef int32_t(ACE_SDK_CALL* __AceSdkServerGetLightFeature)(const AceSdkAccount*, const struct __AceSdkLightFeatureRequest*, struct __AceSdkLightFeatureResponse*);
__AceSdkServerGetLightFeature func = (__AceSdkServerGetLightFeature)__ace_sdk_get_symbol("__ace_sdk_server_get_light_feature");
if (func == NULL)
{
return ACE_SDK_RESULT_SYMBOL_NOT_FOUND;
}
func(account, request, response);
return ACE_SDK_RESULT_OK;
}
#endif // ACE_SDK_SERVER_LIGHT_FEATURE_IMPL_H
@@ -0,0 +1,238 @@
#ifndef __ACE_SDK_SERVER_TEXT_CHECK_H__
#define __ACE_SDK_SERVER_TEXT_CHECK_H__
#include "ace_sdk_account.h"
#include "ace_sdk_server_uic.h"
#include "ace_sdk_server_text_check_impl.h"
#pragma pack(push, 1)
#define ACE_SDK_UIC_MAX_MESSAGE_LEN 15000
#define ACE_SDK_UIC_MAX_TITLE_LEN 300
#define ACE_SDK_UIC_MAX_INTRODUCTION_LEN 1000
#define ACE_SDK_UIC_MAX_BATCH_MULTI_TEXT_LEN 10
#define ACE_SDK_UIC_MAX_EXTRA_DATA_LEN 4095
typedef enum
{
ACE_LANGUAGE_NON = 0, // No language distinction
ACE_LANGUAGE_EN = 1, // English
ACE_LANGUAGE_CHT = 2, // Traditional Chinese
ACE_LANGUAGE_VN = 3, // Vietnamese
ACE_LANGUAGE_CHS = 4, // Simplified Chinese
ACE_LANGUAGE_TH = 5, // Thai
ACE_LANGUAGE_KO = 6, // Korean
ACE_LANGUAGE_FR = 7, // French
ACE_LANGUAGE_DE = 8, // German
ACE_LANGUAGE_RU = 9, // Russian
ACE_LANGUAGE_TR = 10, // Turkish
ACE_LANGUAGE_PTEU = 11, // Portugal (Europe)
ACE_LANGUAGE_PTLT = 12, // Portugal (Latin America)
ACE_LANGUAGE_ESEU = 13, // Spain (Europe)
ACE_LANGUAGE_ESLT = 14, // Spain (Latin America)
ACE_LANGUAGE_IT = 15, // Italy
ACE_LANGUAGE_NL = 16, // Dutch
ACE_LANGUAGE_MY = 17, // Malay
ACE_LANGUAGE_ID = 18, // Indonesian
ACE_LANGUAGE_AR = 19, // Arabic
ACE_LANGUAGE_INDIA = 20, // Hindi
ACE_LANGUAGE_JP = 21, // Japanese
ACE_LANGUAGE_MAX_DEFINE = 100
} AceSdkTextMsglanguage;
typedef struct
{
/**
* It represents the text usage scene id, segmentation principle refer to AceSdkUicMsgCategory
* For specific values, refer to the registration scenario on the ACE official website
* Required
*/
uint32_t scene_id_;
/**
* It represents message content, maximum length is ACE_SDK_UIC_MAX_MESSAGE_LEN
* Required
*/
char text_[ACE_SDK_UIC_MAX_MESSAGE_LEN];
/**
* It represents title of message content, maximum length is ACE_SDK_UIC_MAX_TITLE_LEN
* Optional, if no need, recommend clear it
*/
char title_[ACE_SDK_UIC_MAX_TITLE_LEN];
/**
* It represents introduction of message content, maximum length is ACE_SDK_UIC_MAX_INTRODUCTION_LEN
* Optional, if no need, recommend clear it
*/
char introduction_[ACE_SDK_UIC_MAX_INTRODUCTION_LEN];
/**
* It represents language of message content, refer to AceSdkTextMsglanguage
* By default, fill in ACE_LANGUAGE_NON(0) to indicate no language distinction
* Required
*/
int32_t local_language_;
/**
* Reserved for extended content, generally in json format, maximum length is ACE_SDK_UIC_MAX_EXTRA_DATA_LEN
* Optional, if no need, recommend clear it
*/
char extra_data_[ACE_SDK_UIC_MAX_EXTRA_DATA_LEN];
} AceSdkMultiTextInputInfo;
typedef struct __AceSdkBatchMultiTextInputInfo
{
/**
* It indicates the account to which the input belongs
* Required
*/
AceSdkAccount account_info_;
/**
* It represents the area id of the account, refer to AceSdkUicAreaID
* Required
*/
uint32_t area_id_;
/**
* It represents the role id of the account
* Required
*/
uint32_t role_id_;
/**
* It represents the role level of the account
* Required
*/
uint32_t role_level_;
/**
* It represents the role name of the account
* Required
*/
char role_name_[ACE_SDK_UIC_MAX_ROLE_NAME_LEN];
/**
* It represents the url of user avatar, maximum length is ACE_SDK_UIC_MAX_HEAD_PIC_URL_LEN
* Optional, if no need, recommend clear it
*/
char head_pic_url_[ACE_SDK_UIC_MAX_HEAD_PIC_URL_LEN];
/**
* It represents the length of 'multi_text_array_', maximum length is ACE_SDK_UIC_MAX_BATCH_MULTI_TEXT_LEN
* Required
*/
int32_t multi_text_cnt_;
/**
* It contains several sets of input text
* Required
*/
AceSdkMultiTextInputInfo multi_text_array_[ACE_SDK_UIC_MAX_BATCH_MULTI_TEXT_LEN];
/**
* callback_len_ is the length of 'callback_data_', maximum length is ACE_SDK_UIC_MAX_CALLBACK_DATA_LEN
* When the asynchronous interface is called back, the 'callback_data_' is returned as it is
* Optional, if none fill in Zero and NULL
*/
int32_t callback_len_;
uint8_t callback_data_[ACE_SDK_UIC_MAX_CALLBACK_DATA_LEN];
} AceSdkBatchMultiTextInputInfo;
typedef enum
{
/**
* Legal text
*/
ACE_SDK_MSG_NORMAL_FLAG = 0,
/**
* Illegal text contains malicious words
* 1. user profile scenarios such as naming: failed to name
* 2. instant messaging scenarios: only the sender self can see it, and the visible content is the filtered text
*/
ACE_SDK_MSG_EVIL_FLAG = 1,
/**
* Illegal text contains sensitive words
* 1. user profile scenarios such as naming: failed to name
* 2. instant messaging scenarios: both the receiver and sender can see it, and the visible content is the filtered text
*/
ACE_SDK_MSG_DIRTY_FLAG = 2,
} AceSdkUicMsgResultFlag;
typedef struct
{
/**
* Return the scene id entered before
*/
uint32_t scene_id_;
/**
* The judgment result of the user input text from ACE Backend
* Please display the user input text as required in AceSdkUicMsgResultFlag
*/
uint32_t check_result_;
/**
* Label of the user input text from ACE Backend
*/
uint32_t lable_;
/**
* Judgement Description of the user input text from ACE Backend
*/
char check_desc_[ACE_SDK_UIC_MAX_CHECK_DESC_LEN];
/**
* Filtered text of the user input replaced by ACE Backend
*/
char filtered_text_[ACE_SDK_UIC_MAX_MESSAGE_LEN];
} AceSdkUicJudegeResultInfoMultiText;
typedef struct __AceSdkUicJudgeResultInfoBatchMultiText
{
/**
* Return the account entered before
*/
AceSdkAccount account_info_;
/**
* Zero represents judgement of ACE Backend success
* Not Zero represents judgement of ACE Backend fail
*/
uint32_t err_code_;
/**
* Error Description of ACE Backend judgement
*/
char err_msg_[ACE_SDK_UIC_MAX_ERR_MSG_LEN];
/**
* It represents the length of 'multi_text_array_', maximum length is ACE_SDK_UIC_MAX_BATCH_MULTI_TEXT_LEN
* If err_code_ == 0, it is the same as entered before
*/
int32_t multext_result_cnt_;
/**
* It contains several sets of judgement result from ACE Backend
*/
AceSdkUicJudegeResultInfoMultiText multext_result_array_[ACE_SDK_UIC_MAX_BATCH_MULTI_TEXT_LEN];
/**
* callback_len_ is the length of 'callback_data_', maximum length is ACE_SDK_UIC_MAX_CALLBACK_DATA_LEN
* It is the same as entered before
*/
int32_t callback_len_;
uint8_t callback_data_[ACE_SDK_UIC_MAX_CALLBACK_DATA_LEN];
} AceSdkUicJudgeResultInfoBatchMultiText;
/**
* @brief Callback function of gamesvr to receive the judgement result of user input texts
* @param result_info The judgement result from ACE SDK
* @return 0 Processing Successfully
* @return other value Processing Failed
*/
typedef int(*OnRecvAceSdkUicJudgeResultInfoBatchMultiText)(const AceSdkUicJudgeResultInfoBatchMultiText* result_info);
#pragma pack(pop)
/**
* @brief Set the callback function to receive the judgement result of user input texts
* @brief The callback function must be set firstly before call 'ace_sdk_server_judge_batch_multi_text' in order to get judgement result
* @brief A single autonomous thread propelling the callback interface within the SDK is distinct from the game server thread invoking 'ace_sdk_server_judge_batch_multi_text'. Please pay attention to potential thread safety concerns.
* The callback function should be designed to be lightweight. It is recommended to transfer time-consuming operations to the business layer working thread for processing to avoid blocking the callback thread inside the SDK.
* @brief After the SDK executes the callback function, it will immediately reclaim the data returned to the callback function.
* It is recommended that the game copy the returned data to the business layer memory space within the callback function to avoid memory security issues such as out-of-bounds access.
* @param on_result_func The callback function pointer
*/
AceSdkResult ace_sdk_server_set_recv_batch_multi_text_result_callback(OnRecvAceSdkUicJudgeResultInfoBatchMultiText on_result_func);
/**
* @brief Asynchronous interface to review batch multi-text of an account
* @brief Before calling this function, you must first set 'OnRecvAceSdkUicJudgeResultInfoBatchMultiText'
* @brief All texts will be sent to ACE Backend for review, and even if the backend review times out(500 ms), ACE SDK has local policies to cover it
* @param input_info A group of texts to review
*/
AceSdkResult ace_sdk_server_judge_batch_multi_text(const AceSdkBatchMultiTextInputInfo* input_info);
#endif // __ACE_SDK_SERVER_TEXT_CHECK_H__
@@ -0,0 +1,103 @@
#ifndef __ACE_SDK_SERVER_TEXT_CHECK_IMPL_H__
#define __ACE_SDK_SERVER_TEXT_CHECK_IMPL_H__
#include "ace_sdk_server.h"
struct __AceSdkUicJudgeResultInfoBatchMultiText;
struct __AceSdkBatchMultiTextInputInfo;
typedef int(*__OnRecvAceSdkUicJudgeResultInfoBatchMultiText)(const struct __AceSdkUicJudgeResultInfoBatchMultiText* result_info);
/***
* Internal functions' implementation
*/
#pragma pack(push, 1)
typedef int32_t (ACE_SDK_CALL*__AceSdkServerSetOnRecvResultBatchMultiText)(__OnRecvAceSdkUicJudgeResultInfoBatchMultiText);
typedef int32_t (ACE_SDK_CALL*__AceSdkServerJudgeBatchMultiText)(const struct __AceSdkBatchMultiTextInputInfo*);
typedef struct
{
__AceSdkServerSetOnRecvResultBatchMultiText set_on_recv_judge_result_;
__AceSdkServerJudgeBatchMultiText judge_batch_multi_text_;
} __AceSdkServerUicBatchMultiTextObject;
#pragma pack(pop)
#if defined(ACE_CGO)
extern __AceSdkServerUicBatchMultiTextObject* __ace_sdk_server_uic_batch_multi_text_object;
extern int __is_set_ace_sdk_server_recv_batch_multi_text_callback;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) __AceSdkServerUicBatchMultiTextObject* __ace_sdk_server_uic_batch_multi_text_object = NULL;
__declspec(selectany) int __is_set_ace_sdk_server_recv_batch_multi_text_callback = 0;
#else
__attribute__((weak)) __AceSdkServerUicBatchMultiTextObject* __ace_sdk_server_uic_batch_multi_text_object = NULL;
__attribute__((weak)) int __is_set_ace_sdk_server_recv_batch_multi_text_callback = 0;
#endif
inline int32_t __ace_sdk_server_uic_batch_multi_text_init()
{
if (__ace_sdk_init_succ == 0)
{
return -1;
}
if (__ace_sdk_server_uic_batch_multi_text_object != NULL)
{
return 0;
}
typedef __AceSdkServerUicBatchMultiTextObject* (ACE_SDK_CALL*__AceSdkServerGetUicBatchMultiTextObject)();
__AceSdkServerGetUicBatchMultiTextObject func = (__AceSdkServerGetUicBatchMultiTextObject)__ace_sdk_get_symbol("__ace_sdk_server_get_uic_batch_multi_text_object");
if (func == NULL)
{
return -1;
}
__ace_sdk_server_uic_batch_multi_text_object = func();
if (__ace_sdk_server_uic_batch_multi_text_object == NULL)
{
return -1;
}
return 0;
}
inline AceSdkResult ace_sdk_server_set_recv_batch_multi_text_result_callback(__OnRecvAceSdkUicJudgeResultInfoBatchMultiText on_result_func)
{
if (on_result_func == NULL)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
if (__ace_sdk_server_uic_batch_multi_text_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
__ace_sdk_server_uic_batch_multi_text_object->set_on_recv_judge_result_(on_result_func);
__is_set_ace_sdk_server_recv_batch_multi_text_callback = 1;
return ACE_SDK_RESULT_OK;
}
inline AceSdkResult ace_sdk_server_judge_batch_multi_text(const struct __AceSdkBatchMultiTextInputInfo* input_info)
{
if (input_info == NULL)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
if (__ace_sdk_server_uic_batch_multi_text_init() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
if (!__is_set_ace_sdk_server_recv_batch_multi_text_callback)
{
return ACE_SDK_RESULT_UIC_TEXT_CALLBACK_HAS_NOT_SET;
}
// not allow input_info->multi_text_cnt_ <= 0 || input_info->multi_text_cnt_ > 10
if (__ace_sdk_server_uic_batch_multi_text_object->judge_batch_multi_text_(input_info) != 0)
{
return ACE_SDK_RESULT_UIC_TEXT_INTERF_CALL_FAILED;
}
return ACE_SDK_RESULT_OK;
}
#endif // __ACE_SDK_SERVER_TEXT_CHECK_IMPL_H__
@@ -0,0 +1,33 @@
#ifndef __ACE_SDK_SERVER_TICKET_H__
#define __ACE_SDK_SERVER_TICKET_H__
#include "ace_sdk_account.h"
#include "ace_sdk_server_ticket_impl.h"
#pragma pack(push, 1)
#define ACE_SDK_MAX_TICKET_LENGTH 1024
typedef struct __AceSdkTicket
{
/**
* It represents the actual length of 'ticket_'.
*/
uint32_t ticket_len_;
/**
* Is a C-style string generaged locally by ACE SDK.
*/
char ticket_[ACE_SDK_MAX_TICKET_LENGTH];
} AceSdkTicket;
#pragma pack(pop)
/**
* @brief It must be called when a player tries to enter the game.
* @brief If the obtained ticket is not sent to the client ACE SDK, the player must be prohibited from entering the game.
* @param account Account for player.
* @param ticket Ticket used to verify players for ACE.
*/
AceSdkResult ace_sdk_server_get_ticket(const AceSdkAccount* account, AceSdkTicket* ticket);
#endif // __ACE_SDK_SERVER_TICKET_H__
@@ -0,0 +1,62 @@
#ifndef __ACE_SDK_SERVER_TICKET_IMPL_H__
#define __ACE_SDK_SERVER_TICKET_IMPL_H__
#include "ace_sdk_server.h"
struct __AceSdkTicket;
#if defined(ACE_CGO)
extern int __ace_sdk_ticket_init_succ;
#elif defined(_WIN32) && defined(_MSC_VER)
__declspec(selectany) int __ace_sdk_ticket_init_succ = 0;
#else
__attribute__((weak)) int __ace_sdk_ticket_init_succ = 0;
#endif
inline int ace_sdk_server_init_ticket() {
int ret = 0;
if (!__ace_sdk_init_succ)
{
return -1;
}
if (__ace_sdk_ticket_init_succ)
{
return ret;
}
typedef int32_t(ACE_SDK_CALL* __AceSdkServerInitTicket)();
__AceSdkServerInitTicket func = (__AceSdkServerInitTicket)__ace_sdk_get_symbol("__ace_sdk_server_init_ticket");
if (func == NULL)
{
return -1;
}
ret = func();
if (ret == 0)
{
__ace_sdk_ticket_init_succ = 1;
}
return ret;
}
inline AceSdkResult ace_sdk_server_get_ticket(const AceSdkAccount* account, struct __AceSdkTicket* ticket)
{
if (ace_sdk_server_init_ticket() != 0)
{
return ACE_SDK_RESULT_INIT_NOT_CALLED_OR_FAILED;
}
if (account == NULL || ticket == NULL)
{
return ACE_SDK_RESULT_INVALID_PARAMETER;
}
typedef int32_t(ACE_SDK_CALL* __AceSdkServerGetTicket)(const AceSdkAccount*, struct __AceSdkTicket*);
__AceSdkServerGetTicket func = (__AceSdkServerGetTicket)__ace_sdk_get_symbol("__ace_sdk_server_get_ticket");
if (func == NULL)
{
return ACE_SDK_RESULT_SYMBOL_NOT_FOUND;
}
func(account, ticket);
return ACE_SDK_RESULT_OK;
}
#endif // __ACE_SDK_SERVER_TICKET_IMPL_H__
@@ -0,0 +1,33 @@
#ifndef __ACE_SDK_SERVER_UIC_H__
#define __ACE_SDK_SERVER_UIC_H__
#pragma pack(push, 1)
#define ACE_SDK_UIC_MAX_CALLBACK_DATA_LEN 1024
#define ACE_SDK_UIC_MAX_ROLE_NAME_LEN 1024
#define ACE_SDK_UIC_MAX_HEAD_PIC_URL_LEN 1024
#define ACE_SDK_UIC_MAX_CHECK_DESC_LEN 512
#define ACE_SDK_UIC_MAX_ERR_MSG_LEN 128
typedef enum
{
ACE_SDK_CONTENT_CATEGORY_METERIRAL = 100, // user profile [100-999]
ACE_SDK_CONTENT_CATEGORY_MESSAGE = 1000, // instant message [1000-1899]
ACE_SDK_CONTENT_CATEGORY_PRIVATE_CHAT = 1900, // private chat [1900-1999]
ACE_SDK_CONTENT_CATEGORY_SOCIAL = 2000, // social operation [2000-2999]
ACE_SDK_CONTENT_CATEGORY_FORUM = 3000, // user space or forum [3000-3999]
ACE_SDK_CONTENT_CATEGORY_SEARCH = 4000, // user search [4000-4999]
} AceSdkUicMsgCategory;
typedef enum
{
ACE_SDK_AREA_ID_WECHAT = 1, // WeChat
ACE_SDK_AREA_ID_QQ = 2, // QQ
ACE_SDK_AREA_ID_GUEST = 3, // GUEST
ACE_SDK_AREA_ID_COMMON = 999, // Temporarily used when WeChat and QQ do not exist
} AceSdkUicAreaID;
#pragma pack(pop)
#endif // __ACE_SDK_SERVER_UIC_H__
+25
View File
@@ -0,0 +1,25 @@
add_library(aGameProto
GameProto.proto
GameProto.h
GameProto.cpp
)
protobuf_generate(
LANGUAGE cpp
TARGET aGameProto
PROTOS GameProto.proto
)
target_include_directories(aGameProto
PUBLIC
${CMAKE_CURRENT_BINARY_DIR}
PRIVATE
${CYCLONE_DIR}/include
)
target_link_libraries(aGameProto
PUBLIC
protobuf::libprotobuf
)
+69
View File
@@ -0,0 +1,69 @@
#include "GameProto.h"
#include "GameProto.pb.h"
void serializeProtoMessage(uint16_t id, ::google::protobuf::Message* message, cyclone::Packet& outputPacket)
{
uint16_t messageSize = static_cast<uint16_t>(message->ByteSizeLong());
outputPacket.build_from_memory(GAME_PACKET_HEAD_SIZE, id, messageSize, nullptr);
message->SerializeToArray(outputPacket.get_packet_content(), messageSize);
}
::google::protobuf::Message* parserProtoMessage(const cyclone::Packet& inputPacket)
{
uint16_t packetID = inputPacket.get_packet_id();
::google::protobuf::Message* newMessage = nullptr;
switch (packetID)
{
case GAME_PROTO_LOGIN_REQUEST:
newMessage = new Game::LoginRequest();
break;
case GAME_PROTO_LOGIN_REPLY:
newMessage = new Game::LoginReply();
break;
case GAME_PROTO_CLIENT_PACKET:
newMessage = new Game::ClientTickPacket();
break;
case GAME_PROTO_SERVER_PACKET:
newMessage = new Game::ServerTickPacket();
break;
case GAME_PROTO_HEART_BEAT:
newMessage = new Game::HeartBeat();
break;
case GAME_PROTO_UGC_REQUEST:
newMessage = new Game::UGCRequest();
break;
case GAME_PROTO_UGC_REPLY:
newMessage = new Game::UGCReply();
break;
case GAME_PROTO_REPORT_REQ:
newMessage = new Game::GameReportReq();
break;
case GAME_PROTO_REPORT_RES:
newMessage = new Game::GameReportRes();
break;
case GAME_PROTO_NETBAR_REQ:
newMessage = new Game::NetbaraStatusReq();
break;
case GAME_PROTO_NETBAR_RES:
newMessage = new Game::NetbarStatusRes();
break;
default:
break;
}
if (newMessage)
{
newMessage->ParseFromArray(inputPacket.get_packet_content(), inputPacket.get_packet_size());
}
return newMessage;
}
+34
View File
@@ -0,0 +1,34 @@
#pragma once
#include <vector>
#include <cy_network.h>
namespace google {
namespace protobuf {
class Message;
}
};
enum
{
GAME_PACKET_HEAD_SIZE = 4
};
enum GameProto
{
GAME_PROTO_LOGIN_REQUEST = 1,
GAME_PROTO_LOGIN_REPLY = 2,
GAME_PROTO_CLIENT_PACKET = 3,
GAME_PROTO_SERVER_PACKET = 4,
GAME_PROTO_HEART_BEAT = 5,
GAME_PROTO_UGC_REQUEST = 6,
GAME_PROTO_UGC_REPLY = 7,
GAME_PROTO_REPORT_REQ = 8,
GAME_PROTO_REPORT_RES = 9,
GAME_PROTO_NETBAR_REQ = 10,
GAME_PROTO_NETBAR_RES = 11,
};
void serializeProtoMessage(uint16_t id, ::google::protobuf::Message* message, cyclone::Packet& outputPacket);
::google::protobuf::Message* parserProtoMessage(const cyclone::Packet& inputPacket);
+110
View File
@@ -0,0 +1,110 @@
syntax = "proto3";
package Game;
message LoginRequest
{
string accound_id = 1;
int32 world_id = 2;
int32 pb_retcode = 3;
};
message LightFeature
{
int32 data_len = 1;
int32 data_crc = 2;
bytes data = 3;
string name = 4;
}
message LoginReply
{
int32 result = 1;
int32 runtime_id = 2;
bytes ace_token = 3;
LightFeature light_feature = 4;
}
message HeartBeat
{
int32 timestamp = 1;
bytes pb_data = 2;
}
message ClientTickPacket
{
bytes client_packet = 1;
}
message ServerTickPacket
{
bytes server_packet = 1;
}
message UGCRequest
{
int32 ugc_ctx_id = 1;
int32 ugc_scene_id = 2;
string ugc_content = 3;
}
message UGCReply
{
int32 ugc_ctx_id = 1;
int32 error_code = 2;
int32 result = 3;
string filted_content = 4;
}
message GameReportReq
{
//.被举报者信息
string reported_account_id =1; //被举报者账号ID
int32 reported_world_id=2; //被举报者小区号
string reported_name = 3; //被举报者小区号
string reported_roleid = 4; //被举报者角色号1
int32 ctx_id =5; //用子标识消息的唯ID
//举报数据
int32 report_category = 10; //举报的大类
repeated int32 report_reason = 11; //举报原因类型
int32 report_scene=12; //举报场景
string reported_profile_url=13;//被举报者的头像URL
string report_battle_id =14; //对局ID
int32 report_battle_time=15; //对局时间点
string report_desc =16; //举报详细描述
string report_content = 17; //举报的文本内容
repeated string pic_url_array=18; //举报的图片URL列表
repeated string video_url_array =19; //举报的视频URL列表
repeated string voice_url_array=20; //举报的语音URL列表
string report_group_id=21; //被举报的公会、战队、房间等组织ID
string report_group_name=22; //被举报的公会、战队、房间等组织名称
repeated GameReportContentID content_id_array = 23;
int32 report_entrance=24; //举报入口标识
}
message GameReportContentID
{
string id_type=1;
repeated string id_list=2;
}
message GameReportRes
{
int32 ctx_id =1; //用子标识消息的唯ID
int32 result =2; //服务器返回的代码,0表示成功,非0表示失败
string err_msg=3; //错误描述信息
}
message NetbaraStatusReq
{
bool is_netbar_machine=1;
string token=2;
string macs=3;
}
message NetbarStatusRes
{
int32 error_code=1;
string error_message=2;
int32 netbar_level=3;
}
+181
View File
@@ -0,0 +1,181 @@
#include "stdafx.h"
#include "AceInterface.h"
#include "GameServer.h"
const wchar_t* AceInterface::kLibraryDir = L"./";
const uint32_t AceInterface::kGameID = 719;
const char* AceInterface::kAuthToken = "79205A21";
const uint32_t AceInterface::kWorldID = 160;
bool AceInterface::initAceInterface()
{
AceSdkServerLibraryInfo library_info;
memset(&library_info, 0, sizeof(AceSdkServerLibraryInfo));
memcpy(library_info.library_dir_, kLibraryDir, wcslen(kLibraryDir)*sizeof(wchar_t));
AceSdkServerAuthInfo auth_info;
memset(&auth_info, 0, sizeof(AceSdkServerAuthInfo));
auth_info.game_id_ = kGameID;
snprintf(auth_info.auth_token_, sizeof(auth_info.auth_token_), "%s", kAuthToken);
AceSdkServerDeploymentInfo deployment_info;
memset(&deployment_info, 0, sizeof(AceSdkServerDeploymentInfo));
deployment_info.region_ = ACE_SDK_REGION_CHINA_MAINLAND;
deployment_info.distributor_ = ACE_SDK_GAME_DISTRIBUTOR_COMMON;
AceSdkResult ret = ace_sdk_server_init(&library_info, &auth_info, &deployment_info);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to init ace sdk server, ret : %d\n", ret);
//return false;
}
//set text judge callback
ret = ace_sdk_server_set_recv_batch_multi_text_result_callback(onAceTextJudgeCallback);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to set text judge callback, ret : %d\n", ret);
//return false;
}
printf(">>ACE SDK server init success.\n");
return true;
}
bool AceInterface::onPlayerLogin(const AceSdkAccount& account, AceSdkTicket& aceTicket, AceSdkLightFeatureResponse& lightFeature)
{
// add player when login
AceSdkPlayerAddInfo add_player_info;
memset(&add_player_info, 0, sizeof(AceSdkPlayerAddInfo));
snprintf(add_player_info.role_name_, sizeof(add_player_info.role_name_) - 1, "qq_%s", account.account_);
AceSdkResult ret = ace_sdk_server_add_player(&account, &add_player_info);
if (ret != 0)
{
printf(">>ACE fail to add player, ret: %d\n", ret);
return false;
}
printf(">>ACE add player success.\n");
// get ticket
memset(&aceTicket, 0, sizeof(AceSdkTicket));
ret = ace_sdk_server_get_ticket(&account, &aceTicket);
if (ret != 0)
{
printf(">>ACE fail to get ace ticket, ret: %d\n", ret);
return false;
}
printf(">>ACE Succ to get ace ticket, len=%u, content=%s\n", aceTicket.ticket_len_, aceTicket.ticket_);
//get light feature
AceSdkLightFeatureRequest lightFeatureReq;
memset(&lightFeatureReq, 0, sizeof(AceSdkLightFeatureRequest));
snprintf(lightFeatureReq.client_version_, sizeof(lightFeatureReq.client_version_) - 1, "%s", "1.0.0");
memset(&lightFeature, 0, sizeof(AceSdkLightFeatureResponse));
ret = ace_sdk_server_get_light_feature(&account, &lightFeatureReq, &lightFeature);
if (ret != 0)
{
printf(">>ACE fail to get ace ticket, ret: %d\n", ret);
return false;
}
printf(">>ACE Succ to get light feature\n");
return true;
}
void AceInterface::onPlayerLogout(const AceSdkAccount& account)
{
AceSdkResult ret = ace_sdk_server_delete_player(&account);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_delete_player, ret : %d\n", ret);
}
}
void AceInterface::onReceiveClientTickPacket(const AceSdkAccount& account, const uint8_t* packet_buffer, uint32_t packet_len)
{
AceSdkServerPacket serverPacket;
memset(&serverPacket, 0, sizeof(AceSdkServerPacket));
memcpy(&(serverPacket.account_), &account, sizeof(AceSdkAccount));
serverPacket.packet_len_ = packet_len;
memcpy(serverPacket.packet_buffer_, packet_buffer, packet_len);
AceSdkResult ret = ace_sdk_server_on_packet_received(&serverPacket);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_on_packet_received, ret : %d\n", ret);
}
}
void AceInterface::getServerTickPacket(AceSdkServerPacketList& serverTickPackets)
{
memset(&serverTickPackets, 0, sizeof(AceSdkServerPacketList));
AceSdkResult ret = ace_sdk_server_get_packet(&serverTickPackets);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_get_packets, ret : %d\n", ret);
}
if (serverTickPackets.packet_num_ > 0)
{
printf(">>ACE call ace_sdk_server_on_packet_received, packet_num : %d\n", serverTickPackets.packet_num_);
}
}
void AceInterface::keepClientAlive(const AceSdkAccount& account)
{
AceSdkResult ret = ace_sdk_server_keep_alive_player(&account);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_keep_alive, ret : %d\n", ret);
}
}
bool AceInterface::onUGCRequest(const AceSdkAccount& account, int32_t ugcSceneID, const char* content,
int32_t ugcCtxID, int32_t clientID)
{
AceSdkBatchMultiTextInputInfo textInputInfo;
memset(&textInputInfo, 0, sizeof(AceSdkBatchMultiTextInputInfo));
textInputInfo.account_info_ = account;
snprintf(textInputInfo.role_name_, ACE_SDK_UIC_MAX_ROLE_NAME_LEN - 1, "qq_%s", account.account_);
textInputInfo.multi_text_cnt_ = 1;
textInputInfo.multi_text_array_[0].scene_id_ = ugcSceneID;
snprintf(textInputInfo.multi_text_array_[0].text_, ACE_SDK_UIC_MAX_MESSAGE_LEN, "%s", content);
AceTextJudgeCallbackData callbackData;
memset(&callbackData, 0, sizeof(AceTextJudgeCallbackData));
callbackData.clientID = clientID;
callbackData.ugcClientCtxID = ugcCtxID;
textInputInfo.callback_len_ = sizeof(AceTextJudgeCallbackData);
memcpy(textInputInfo.callback_data_, &callbackData, sizeof(AceTextJudgeCallbackData));
AceSdkResult ret = ace_sdk_server_judge_batch_multi_text(&textInputInfo);
if (ret != ACE_SDK_RESULT_OK)
{
printf(">>ACE fail to call ace_sdk_server_judge_batch_multi_text, ret : %d\n", ret);
return false;
}
printf(">>ACE call ace_sdk_server_judge_batch_multi_text\n");
return true;
}
int AceInterface::onAceTextJudgeCallback(const AceSdkUicJudgeResultInfoBatchMultiText* result_info)
{
if (result_info == nullptr) return 0;
if (result_info->callback_len_ != sizeof(AceTextJudgeCallbackData))
{
printf(">>ACE text judge callback data length mismatch, len : %d\n", result_info->callback_len_);
return 0;
}
printf(">>ACE text judge callback received, err_code : %d, multext_result_cnt : %d\n",
result_info->err_code_, result_info->multext_result_cnt_);
AceTextJudgeCallbackData callbackData;
memcpy(&callbackData, result_info->callback_data_, sizeof(AceTextJudgeCallbackData));
GameServer::getSingleton()->onUGCCallback(callbackData.clientID, callbackData.ugcClientCtxID, result_info);
return 0;
}
+32
View File
@@ -0,0 +1,32 @@
#pragma once
class AceInterface
{
public:
const static wchar_t* kLibraryDir;
const static uint32_t kGameID;
const static char* kAuthToken;
const static uint32_t kWorldID;
public:
static bool initAceInterface();
static bool onPlayerLogin(const AceSdkAccount& account, AceSdkTicket& ace_ticket, AceSdkLightFeatureResponse& lightFeature);
static void onPlayerLogout(const AceSdkAccount& account);
static void onReceiveClientTickPacket(const AceSdkAccount& account, const uint8_t* packet_buffer, uint32_t packet_len);
static void getServerTickPacket(AceSdkServerPacketList& serverTickPackets);
static void keepClientAlive(const AceSdkAccount& account);
static bool onUGCRequest(const AceSdkAccount& account, int32_t ugcSceneID, const char* content,
int32_t ugcCtxID, int32_t clientID);
private:
static int onAceTextJudgeCallback(const AceSdkUicJudgeResultInfoBatchMultiText* result_info);
struct AceTextJudgeCallbackData
{
int32_t clientID;
int32_t ugcClientCtxID;
};
};
+8
View File
@@ -0,0 +1,8 @@
#include "stdafx.h"
#include "AceReportInterface.h"
std::string buildReportRequestUrl(const std::string& baseUrl, const std::string& user,
const std::string& token, uint32_t timeStamp, const std::string& body)
{
return "";
}
+4
View File
@@ -0,0 +1,4 @@
#pragma once
std::string buildReportRequestUrl();
+62
View File
@@ -0,0 +1,62 @@
set(ASERVER_SOURCE_FILES
stdafx.h
main.cpp
GameServer.h
GameServer.cpp
AceInterface.h
AceInterface.cpp
AceReportInterface.h
AceReportInterface.cpp
NetbarInterface.h
NetbarInterface.cpp
CurlHelper.h
CurlHelper.cpp
)
set(ASERVER_PRECOMPILE_FILE
stdafx.cpp
)
foreach(filename ${ASERVER_SOURCE_FILES})
get_filename_component(ext ${filename} LAST_EXT ABSOLUTE)
string(TOLOWER ${ext} ext_lower)
if(${ext_lower} STREQUAL ".cpp" )
set_source_files_properties(
${filename}
PROPERTIES
COMPILE_FLAGS "/Yustdafx.h"
)
endif()
endforeach()
set_source_files_properties(${ASERVER_PRECOMPILE_FILE}
PROPERTIES
COMPILE_FLAGS "/Ycstdafx.h"
)
add_executable(aServer
${ASERVER_SOURCE_FILES}
${ASERVER_PRECOMPILE_FILE}
)
target_include_directories(aServer
PRIVATE
${CYCLONE_DIR}/include
${ACE_SERVER_DIR}/include
${RAPIDJSON_INCLUDE_DIRS}
${GAME_PROTO_DIR}
)
target_link_directories(aServer
PRIVATE
${CYCLONE_DIR}/lib
)
target_link_libraries(aServer
PRIVATE
aGameProto
cyclone.lib
ws2_32.lib
shlwapi.lib
CURL::libcurl_static
)
+116
View File
@@ -0,0 +1,116 @@
#include "stdafx.h"
#include "CurlHelper.h"
#include <curl/curl.h>
struct CurlBodyData
{
const char* bodyPtr;
size_t sizeLeft;
};
static size_t curlReadCallback(void* ptr, size_t size, size_t nmemb, void* userdata)
{
CurlBodyData* bodyData = static_cast<CurlBodyData*>(userdata);
size_t bufferSize = size * nmemb;
if(bufferSize < 1) return 0;
if (bodyData->sizeLeft == 0)
return 0;
//we only send one byte at a time
size_t copySize = 1;
memcpy(ptr, bodyData->bodyPtr, copySize);
bodyData->bodyPtr += copySize;
bodyData->sizeLeft -= copySize;
return copySize;
}
static size_t curlWriteCallback(void* ptr, size_t size, size_t nmemb, void* userdata)
{
std::string* output = static_cast<std::string*>(userdata);
size_t newLength = size * nmemb;
size_t oldLength = output->size();
output->resize(oldLength + newLength);
std::copy((char*)ptr, (char*)ptr + newLength, output->begin() + oldLength);
return newLength;
}
int32_t curlRequest(const std::string& url, const std::string& body, std::string& output, bool jsonBody)
{
CURL* curlCtx = curl_easy_init();
if (curlCtx == nullptr) return -1;
curl_easy_reset(curlCtx);
CurlBodyData bodyData;
bodyData.bodyPtr = body.c_str();
bodyData.sizeLeft = body.size();
curl_easy_setopt(curlCtx, CURLOPT_URL, url.c_str());
curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYPEER, 0L);
curl_easy_setopt(curlCtx, CURLOPT_SSL_VERIFYHOST, 0L);
curl_easy_setopt(curlCtx, CURLOPT_NOPROXY, "*");
curl_easy_setopt(curlCtx, CURLOPT_TIMEOUT, 3L);
curl_easy_setopt(curlCtx, CURLOPT_NOSIGNAL, 1L);
curl_easy_setopt(curlCtx, CURLOPT_POST, 1L);
curl_easy_setopt(curlCtx, CURLOPT_READFUNCTION, curlReadCallback);
curl_easy_setopt(curlCtx, CURLOPT_READDATA, &bodyData);
curl_easy_setopt(curlCtx, CURLOPT_WRITEFUNCTION, curlWriteCallback);
curl_easy_setopt(curlCtx, CURLOPT_WRITEDATA, &output);
struct curl_slist* headers = nullptr;
if (jsonBody)
{
headers = curl_slist_append(headers, "Content-Type: application/json");
}
if(headers != nullptr)
{
curl_easy_setopt(curlCtx, CURLOPT_HTTPHEADER, headers);
}
curl_easy_setopt(curlCtx, CURLOPT_POSTFIELDSIZE, static_cast<long>(bodyData.sizeLeft));
CURLcode returnCode = curl_easy_perform(curlCtx);
if(returnCode != CURLE_OK)
{
curl_easy_cleanup(curlCtx);
if (headers != nullptr)
{
curl_slist_free_all(headers);
headers = nullptr;
}
return -1;
}
long stateCode = 0;
curl_easy_getinfo(curlCtx, CURLINFO_RESPONSE_CODE, &stateCode);
if (headers != nullptr)
{
curl_slist_free_all(headers);
headers = nullptr;
}
curl_easy_cleanup(curlCtx);
if(stateCode != 200)
{
return static_cast<int32_t>(stateCode);
}
if(output.empty())
{
return -1;
}
return returnCode;
}
+3
View File
@@ -0,0 +1,3 @@
#pragma once
int32_t curlRequest(const std::string& url, const std::string& body, std::string& output, bool jsonBody);
+299
View File
@@ -0,0 +1,299 @@
#include "stdafx.h"
#include "GameServer.h"
#include "AceInterface.h"
#include "NetbarInterface.h"
#include "GameProto.pb.h"
GameServer* GameServer::getSingleton()
{
static GameServer instance;
return &instance;
}
GameServer::GameServer()
{
}
GameServer::~GameServer()
{
}
void GameServer::startAndJoin(uint16_t server_port)
{
m_clients_lock = cyclone::sys_api::mutex_create();
cyclone::TcpServer server;
server.m_listener.on_connected = std::bind(&GameServer::onClientConnected, this, std::placeholders::_3);
server.m_listener.on_message = std::bind(&GameServer::onClientMessage, this, std::placeholders::_3);
server.m_listener.on_close = std::bind(&GameServer::onClientClose, this, std::placeholders::_3);
if (!server.bind(cyclone::Address(server_port, false), false)) return;
int32_t workerThreads = 1; // cyclone::sys_api::get_cpu_counts();
if (!(server.start(workerThreads))) return;
//server.join();
while (true)
{
tick();
if (m_tickSleepSwitch == 0)
{
cyclone::sys_api::thread_sleep(1);
}
m_tickSleepSwitch = (m_tickSleepSwitch + 1) % 15;
}
cyclone::sys_api::mutex_destroy(m_clients_lock);
}
GameClient* GameServer::getClient(int32_t client_id)
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
std::map< int32_t, GameClient >::iterator it = m_clients.find(client_id);
if(it==m_clients.end())
{
return nullptr;
}
return &(it->second);
}
void GameServer::tick()
{
AceSdkServerPacketList serverTickPackets;
AceInterface::getServerTickPacket(serverTickPackets);
if (serverTickPackets.packet_num_ == 0) return;
for (uint32_t i = 0; i < serverTickPackets.packet_num_; ++i)
{
const AceSdkServerPacket& serverPacket = serverTickPackets.packets_[i];
std::map< std::string, int32_t >::iterator it = m_accountToConnectionID.find(std::string(serverPacket.account_.account_));
if (it == m_accountToConnectionID.end()) continue;
GameClient* client = getClient(it->second);
if (client == nullptr) continue;
Game::ServerTickPacket serverTickPacket;
serverTickPacket.mutable_server_packet()->assign((const char*)serverPacket.packet_buffer_, serverPacket.packet_len_);
cyclone::Packet packet;
serializeProtoMessage(GAME_PROTO_SERVER_PACKET, &serverTickPacket, packet);
client->connection->send(packet.get_memory_buf(), packet.get_memory_size());
}
}
void GameServer::onClientConnected(cyclone::TcpConnectionPtr conn)
{
//new connection
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
m_clients.insert({ conn->get_id(),{ conn->get_id(), conn } });
}
CY_LOG(cyclone::L_DEBUG, "new connection accept, from %s:%d to %s:%d",
conn->get_peer_addr().get_ip(),
conn->get_peer_addr().get_port(),
conn->get_local_addr().get_ip(),
conn->get_local_addr().get_port());
}
void GameServer::onClientMessage(cyclone::TcpConnectionPtr conn)
{
cyclone::RingBuf& buf = conn->get_input_buf();
for (;;)
{
cyclone::Packet packet;
if (!packet.build_from_ringbuf(GAME_PACKET_HEAD_SIZE, buf)) return;
::google::protobuf::Message* message = parserProtoMessage(packet);
switch (packet.get_packet_id())
{
case GAME_PROTO_LOGIN_REQUEST:
{
Game::LoginRequest* loginRequest = dynamic_cast<Game::LoginRequest*>(message);
onClientLoginRequest(conn, loginRequest);
}
break;
case GAME_PROTO_CLIENT_PACKET:
{
Game::ClientTickPacket* clientTickPacket = dynamic_cast<Game::ClientTickPacket*>(message);
onClientTickPacket(conn, clientTickPacket);
}
break;
case GAME_PROTO_HEART_BEAT:
{
Game::HeartBeat* heartPacket = dynamic_cast<Game::HeartBeat*>(message);
onClientHeartBeat(conn, heartPacket);
}
break;
case GAME_PROTO_UGC_REQUEST:
{
Game::UGCRequest* ugcRequest = dynamic_cast<Game::UGCRequest*>(message);
onUGCRequest(conn, ugcRequest);
}
break;
case GAME_PROTO_REPORT_REQ:
{
Game::GameReportReq* reportRequest = dynamic_cast<Game::GameReportReq*>(message);
onReportRequest(conn, reportRequest);
}
break;
case GAME_PROTO_NETBAR_REQ:
{
Game::NetbaraStatusReq* netbarRequest = dynamic_cast<Game::NetbaraStatusReq*>(message);
onNetbarRequest(conn, netbarRequest);
}
}
}
}
void GameServer::onClientClose(cyclone::TcpConnectionPtr conn)
{
cyclone::sys_api::auto_mutex lock(m_clients_lock);
GameClient* client = getClient(conn->get_id());
AceInterface::onPlayerLogout(client->aceAccount);
m_accountToConnectionID.erase(std::string(client->aceAccount.account_));
m_clients.erase(conn->get_id());
CY_LOG(cyclone::L_DEBUG, "connection %s:%d closed",
conn->get_peer_addr().get_ip(),
conn->get_peer_addr().get_port());
}
void GameServer::onClientLoginRequest(cyclone::TcpConnectionPtr conn, Game::LoginRequest* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
client->gameAccoundID = request->accound_id();
client->gameWorldID = request->world_id();
m_accountToConnectionID.insert({ request->accound_id(), conn->get_id() });
//create ace account info
AceSdkAccount& account = client->aceAccount;
memset(&account, 0, sizeof(AceSdkAccount));
snprintf(account.account_, sizeof(account.account_) - 1, "%s", request->accound_id().c_str());
account.account_type_ = ACE_SDK_ACCOUNT_TYPE_QQ;
account.plat_id_ = ACE_SDK_PLAT_ID_PC_CLIENT;
account.game_id_ = AceInterface::kGameID;
account.world_id_ = AceInterface::kWorldID;
int32_t pbRetCode = request->pb_retcode();
printf(">>ACE client pb ret code: %d\n", pbRetCode);
AceSdkTicket aceTicket;
AceSdkLightFeatureResponse lightFeature;
if (!AceInterface::onPlayerLogin(account, aceTicket, lightFeature))
{
printf(">>ACE player login failed.\n");
return;
}
Game::LightFeature lightFeatureProto;
lightFeatureProto.set_data_len(lightFeature.data_len_);
lightFeatureProto.set_data_crc(lightFeature.data_crc_);
lightFeatureProto.set_data(std::string((const char*)lightFeature.data_, lightFeature.data_len_));
lightFeatureProto.set_name(std::string(lightFeature.name_));
//send login reply
Game::LoginReply loginReply;
loginReply.set_result(0);
loginReply.set_runtime_id(conn->get_id());
loginReply.set_ace_token(aceTicket.ticket_);
loginReply.mutable_light_feature()->CopyFrom(lightFeatureProto);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_LOGIN_REPLY, &loginReply, outputPacket);
conn->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
}
void GameServer::onClientTickPacket(cyclone::TcpConnectionPtr conn, Game::ClientTickPacket* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::onReceiveClientTickPacket(client->aceAccount,
(const uint8_t*)(request->client_packet().data()), (uint32_t)(request->client_packet().size()));
}
void GameServer::onClientHeartBeat(cyclone::TcpConnectionPtr conn, Game::HeartBeat* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::keepClientAlive(client->aceAccount);
if(request->pb_data().length()>0)
{
//log
printf(">>ACE receive heart beat pb data, len=%zu\n", request->pb_data().length());
}
}
void GameServer::onUGCRequest(cyclone::TcpConnectionPtr conn, Game::UGCRequest* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
AceInterface::onUGCRequest(client->aceAccount,
request->ugc_scene_id(), request->ugc_content().c_str(),
request->ugc_ctx_id(), conn->get_id());
}
void GameServer::onUGCCallback(int32_t connID, int32_t ctxID, const AceSdkUicJudgeResultInfoBatchMultiText* result_info)
{
GameClient* client = getClient(connID);
assert(client);
if (result_info->multext_result_cnt_ < 1)
{
return;
}
Game::UGCReply ugcReply;
ugcReply.set_ugc_ctx_id(ctxID);
ugcReply.set_error_code(result_info->err_code_);
ugcReply.set_result(result_info->multext_result_array_[0].check_result_);
ugcReply.set_filted_content(result_info->multext_result_array_[0].filtered_text_);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_UGC_REPLY, &ugcReply, outputPacket);
client->connection->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
}
void GameServer::onReportRequest(cyclone::TcpConnectionPtr conn, Game::GameReportReq* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
}
void GameServer::onNetbarRequest(cyclone::TcpConnectionPtr conn, Game::NetbaraStatusReq* request)
{
if (request == nullptr) return;
GameClient* client = getClient(conn->get_id());
assert(client);
NetbarInterface::onReceiveNetbarReportRequest(client, request);
}
+61
View File
@@ -0,0 +1,61 @@
#pragma once
#include "GameProto.h"
namespace Game
{
class LoginRequest;
class ClientTickPacket;
class HeartBeat;
class UGCRequest;
class GameReportReq;
class NetbaraStatusReq;
}
struct GameClient
{
int32_t agent_id;
cyclone::TcpConnectionPtr connection;
std::string gameAccoundID;
int32_t gameWorldID;
AceSdkAccount aceAccount;
};
class GameServer
{
public:
static GameServer* getSingleton();
public:
void startAndJoin(uint16_t server_port);
GameClient* getClient(int32_t client_id);
void onUGCCallback(int32_t connID, int32_t ctxID, const AceSdkUicJudgeResultInfoBatchMultiText* result_info);
protected:
void onClientConnected(cyclone::TcpConnectionPtr conn);
void onClientMessage(cyclone::TcpConnectionPtr conn);
void onClientClose(cyclone::TcpConnectionPtr conn);
protected:
void tick();
void onClientLoginRequest(cyclone::TcpConnectionPtr conn, Game::LoginRequest* request);
void onClientTickPacket(cyclone::TcpConnectionPtr conn, Game::ClientTickPacket* request);
void onClientHeartBeat(cyclone::TcpConnectionPtr conn, Game::HeartBeat* request);
void onUGCRequest(cyclone::TcpConnectionPtr conn, Game::UGCRequest* request);
void onReportRequest(cyclone::TcpConnectionPtr conn, Game::GameReportReq* request);
void onNetbarRequest(cyclone::TcpConnectionPtr conn, Game::NetbaraStatusReq* request);
private:
std::map< int32_t, GameClient > m_clients;
std::map< std::string, int32_t > m_accountToConnectionID;
cyclone::sys_api::mutex_t m_clients_lock;
int32_t m_tickSleepSwitch = 0;
public:
GameServer();
~GameServer();
};
+119
View File
@@ -0,0 +1,119 @@
#include "stdafx.h"
#include "NetbarInterface.h"
#include "GameServer.h"
#include "GameProto.pb.h"
#include "CurlHelper.h"
#include "rapidjson/document.h"
#include "rapidjson/stringbuffer.h"
#include "rapidjson/writer.h"
std::string buildRequestJson(GameClient* client, Game::NetbaraStatusReq* request)
{
rapidjson::Document root;
root.SetObject();
rapidjson::Document::AllocatorType& allocator = root.GetAllocator();
//openid
rapidjson::Value openIDValue(client->gameAccoundID.c_str(), static_cast<rapidjson::SizeType>(client->gameAccoundID.length()), allocator);
root.AddMember("openid", openIDValue, allocator);
//ip
std::string ipStr = client->connection->get_peer_addr().get_ip();
rapidjson::Value ipValue(ipStr.c_str(), static_cast<rapidjson::SizeType>(ipStr.length()), allocator);
root.AddMember("ip", ipValue, allocator);
//mac
rapidjson::Value macArray(rapidjson::kArrayType);
std::stringstream ss(request->macs().c_str());
std::string mac;
while (std::getline(ss, mac, ';'))
{
rapidjson::Value macValue(mac.c_str(), static_cast<rapidjson::SizeType>(mac.length()), allocator);
macArray.PushBack(macValue, allocator);
};
root.AddMember("macs", macArray, allocator);
//netbar token
rapidjson::Value tokenValue(request->token().c_str(), static_cast<rapidjson::SizeType>(request->token().length()), allocator);
root.AddMember("netbar_token", tokenValue, allocator);
//game id
root.AddMember("game_id", 1, allocator);
//game zone
std::string strZoneID = std::to_string(client->gameWorldID);
rapidjson::Value zoneIDValue(strZoneID.c_str(), static_cast<rapidjson::SizeType>(strZoneID.length()), allocator);
root.AddMember("zone", zoneIDValue, allocator);
//request no
std::string strRequestTime = std::to_string(static_cast<uint32_t>(time(nullptr)));
rapidjson::Value requestNumber(strRequestTime.c_str(), static_cast<rapidjson::SizeType>(strRequestTime.length()), allocator);
root.AddMember("reqno", requestNumber, allocator);
rapidjson::StringBuffer sb;
rapidjson::Writer<rapidjson::StringBuffer> writer(sb);
root.Accept(writer);
std::string outputJson = sb.GetString();
return outputJson;
}
std::string buildRequestUrl()
{
return "http://api-test.netbar.itrpc.woa.com/netbar.cafe.rewards.rewards/Rewards";
}
bool NetbarInterface::onReceiveNetbarReportRequest(GameClient* client, Game::NetbaraStatusReq* request)
{
std::string requestBody = buildRequestJson(client, request);
std::string requestUrl = buildRequestUrl();
std::string result;
int32_t retCode = curlRequest(requestUrl, requestBody, result, true);
int32_t errorCode = 0;
std::string errorInfo;
int32_t netbarLevel = 0;
if(retCode != 0)
{
CY_LOG(cyclone::L_ERROR, "NetbarInterface::onReceiveNetbarReportRequest curlRequest failed, retCode=%d", retCode);
char szTemp[256] = { 0 };
snprintf(szTemp, 256, "Curl request failed, retCode=%d", retCode);
errorInfo = szTemp;
}
else
{
rapidjson::Document document;
rapidjson::ParseResult prserResult = document.Parse(result.c_str());
if(document.HasMember("errcode") && document["errcode"].IsInt())
{
errorCode = document["errcode"].GetInt();
}
if(document.HasMember("errinfo") && document["errinfo"].IsString())
{
errorInfo = document["errinfo"].GetString();
}
if(document.HasMember("rids") && document["rids"].IsInt())
{
netbarLevel = document["rids"].GetInt();
}
}
////send netbar status reply
Game::NetbarStatusRes netbarResponse;
netbarResponse.set_error_code(errorCode);
netbarResponse.set_error_message(errorInfo);
netbarResponse.set_netbar_level(netbarLevel);
cyclone::Packet outputPacket;
serializeProtoMessage(GAME_PROTO_NETBAR_RES, &netbarResponse, outputPacket);
client->connection->send(outputPacket.get_memory_buf(), outputPacket.get_memory_size());
return true;
}
+13
View File
@@ -0,0 +1,13 @@
#pragma once
struct GameClient;
namespace Game
{
class NetbaraStatusReq;
};
class NetbarInterface
{
public:
static bool onReceiveNetbarReportRequest(GameClient* client, Game::NetbaraStatusReq* request);
};
+15
View File
@@ -0,0 +1,15 @@
#include "stdafx.h"
#include "GameServer.h"
#include "AceInterface.h"
int main(int argc, char* argv[])
{
//init ace interface
if (!AceInterface::initAceInterface())
{
return -1;
}
GameServer::getSingleton()->startAndJoin(2025);
return 0;
}
+2
View File
@@ -0,0 +1,2 @@
#include "stdafx.h"
+16
View File
@@ -0,0 +1,16 @@
#pragma once
#include <cy_core.h>
#include <cy_event.h>
#include <cy_network.h>
#include <ace_sdk_server_ticket.h>
#include <ace_sdk_server_light_feature.h>
#include <ace_sdk_server_anti_cheat_core.h>
#include <ace_sdk_server_text_check.h>
#include <ace_sdk_server.h>
#include <ace_sdk_account.h>
#include <sstream>
#include <string>
#include <iostream>