#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(message); onClientLoginRequest(conn, loginRequest); } break; case GAME_PROTO_CLIENT_PACKET: { Game::ClientTickPacket* clientTickPacket = dynamic_cast(message); onClientTickPacket(conn, clientTickPacket); } break; case GAME_PROTO_HEART_BEAT: { Game::HeartBeat* heartPacket = dynamic_cast(message); onClientHeartBeat(conn, heartPacket); } break; case GAME_PROTO_UGC_REQUEST: { Game::UGCRequest* ugcRequest = dynamic_cast(message); onUGCRequest(conn, ugcRequest); } break; case GAME_PROTO_REPORT_REQ: { Game::GameReportReq* reportRequest = dynamic_cast(message); onReportRequest(conn, reportRequest); } break; case GAME_PROTO_NETBAR_REQ: { Game::NetbaraStatusReq* netbarRequest = dynamic_cast(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); }