Files
dnf-utils/ace_test/aServer/GameServer.cpp
T

300 lines
8.5 KiB
C++

#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::onReceiveNetbarStatusRequest(client, request);
}