302 lines
8.6 KiB
C++
302 lines
8.6 KiB
C++
#include "stdafx.h"
|
|
|
|
#include "GameServer.h"
|
|
#include "AceInterface.h"
|
|
#include "NetbarInterface.h"
|
|
#include "AceReportInterface.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);
|
|
|
|
AceReportInterface::onReceiveReportRequest(client, request);
|
|
}
|
|
|
|
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);
|
|
}
|