1117 lines
39 KiB
C++
1117 lines
39 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/mutable_xobject.h>
|
|
#include <a8/openssl.h>
|
|
|
|
#include "roommgr.h"
|
|
#include "room.h"
|
|
#include "cs_proto.pb.h"
|
|
#include "GGListener.h"
|
|
#include "player.h"
|
|
#include "playermgr.h"
|
|
#include "app.h"
|
|
#include "jsondatamgr.h"
|
|
#include "playermgr.h"
|
|
#include "mapmgr.h"
|
|
#include "perfmonitor.h"
|
|
#include "matchmgr.h"
|
|
#include "matchteam.h"
|
|
#include "httpproxy.h"
|
|
#include "mapmgr.h"
|
|
#include "debugcmd.h"
|
|
#include "custom_battle.h"
|
|
#include "custom_team.h"
|
|
#include "custom_member.h"
|
|
|
|
#include "mt/Param.h"
|
|
#include "mt/Text.h"
|
|
#include "mt/Hero.h"
|
|
#include "mt/Equip.h"
|
|
#include "mt/Map.h"
|
|
#include "mt/PveGemini.h"
|
|
#include "mt/PveGeminiMode.h"
|
|
#include "mt/PveGeminiContent.h"
|
|
|
|
#include <f8/httpclientpool.h>
|
|
#include <f8/utils.h>
|
|
#include <f8/udplog.h>
|
|
#include <f8/timer.h>
|
|
|
|
static const int ROOM_NUM_UP_LIMIT = 1000;
|
|
static const int HUM_NUM_DOWN_LIMIT = 2500;
|
|
|
|
static RoomType_e GetHumanRoomType(const std::shared_ptr<BattleDataContext> netdata)
|
|
{
|
|
long long hero_uniid = 0;
|
|
int hero_lv = 0;
|
|
int quality = 0;
|
|
netdata->GetHeroLvQuality(hero_uniid, hero_lv, quality);
|
|
if (netdata->join_msg->room_mode() == kPvpRankMode) {
|
|
#if 1
|
|
auto rank_mode_conf = mt::Param::GetRankModeConfByHeroLv(hero_lv);
|
|
if (!rank_mode_conf) {
|
|
abort();
|
|
}
|
|
#else
|
|
auto rank_mode_conf = mt::Param::GetRankModeConfByElo(netdata->GetElo());
|
|
if (!rank_mode_conf) {
|
|
abort();
|
|
}
|
|
#endif
|
|
return rank_mode_conf->room_type;
|
|
} else {
|
|
if (hero_lv < mt::Param::s().new_room_max_level) {
|
|
return RoomType_OldBrid1;
|
|
}
|
|
#if 1
|
|
if (hero_lv < mt::Param::s().mid_room_max_level) {
|
|
return RoomType_OldBrid2;
|
|
}
|
|
#else
|
|
if (netdata->GetRank() < mt::Param::s().mid_room_max_rank) {
|
|
return RoomType_OldBrid2;
|
|
}
|
|
#endif
|
|
return RoomType_OldBrid3;
|
|
}
|
|
}
|
|
|
|
void RoomMgr::Init()
|
|
{
|
|
InstallReportStateTimer();
|
|
}
|
|
|
|
void RoomMgr::UnInit()
|
|
{
|
|
for (auto& pair : room_hash_) {
|
|
pair.second->UnInit();
|
|
}
|
|
for (auto& pair : over_room_hash_) {
|
|
pair.second->UnInit();
|
|
}
|
|
room_hash_.clear();
|
|
over_room_hash_.clear();
|
|
}
|
|
|
|
void RoomMgr::Update(int delta_time)
|
|
{
|
|
long long real_alive_count = 0;
|
|
for (auto& pair : room_hash_) {
|
|
auto& room = pair.second;
|
|
room->Update(delta_time);
|
|
real_alive_count += room->RealAliveCount();
|
|
}
|
|
PerfMonitor::Instance()->real_alive_count = real_alive_count;
|
|
}
|
|
|
|
void RoomMgr::_CMJoin(f8::MsgHdr& hdr, const cs::CMJoin& msg)
|
|
{
|
|
if (IsLimitJoin()) {
|
|
JoinErrorHandle(msg, 2, hdr.socket_handle);
|
|
return;
|
|
}
|
|
{
|
|
cs::CMJoin* mutable_msg = (cs::CMJoin*)&msg;
|
|
AdjustCMJoin(mutable_msg);
|
|
#ifdef DEBUG
|
|
a8::XPrintf("AdjustCMJoinAfter room_mode:%d pve_instance_id:%d\n",
|
|
{
|
|
msg.room_mode(),
|
|
msg.pve_instance_id()
|
|
});
|
|
#endif
|
|
}
|
|
if (msg.force_enter_newbie_room()) {
|
|
//EnterNewBie(hdr, msg);
|
|
return;
|
|
}
|
|
if (MatchMgr::Instance()->NeedMatch(msg)) {
|
|
MatchMgr::Instance()->_CMJoin(hdr, msg);
|
|
return;
|
|
}
|
|
const mt::Map* map_meta = mt::Map::GetById(msg.mapid());
|
|
if (!map_meta || !map_meta->IsOpen()) {
|
|
JoinErrorHandle(msg, 3, hdr.socket_handle);
|
|
return;
|
|
}
|
|
if (!msg.custom_room_payload().empty()) {
|
|
_CMJoinCustomBattle(hdr, msg);
|
|
return;
|
|
}
|
|
std::shared_ptr<cs::CMJoin> join_msg = std::make_shared<cs::CMJoin>();
|
|
*join_msg = msg;
|
|
std::vector<std::shared_ptr<cs::CMJoin>> join_msgs{join_msg};
|
|
auto ip_saddr = hdr.ip_saddr;
|
|
auto socket_handle = hdr.socket_handle;
|
|
auto cb =
|
|
[ip_saddr, socket_handle, join_msg]
|
|
(std::vector<std::shared_ptr<BattleDataContext>>& results)
|
|
{
|
|
cs::CMJoin& msg = *join_msg;
|
|
if (RoomMgr::Instance()->IsLimitJoin()) {
|
|
RoomMgr::Instance()->JoinErrorHandle(msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
if (!results.at(0)->parse_ok) {
|
|
return;
|
|
}
|
|
int game_times = 0;
|
|
RoomType_e self_room_type = GetHumanRoomType(results.at(0));
|
|
time_t register_time = f8::ExtractRegisterTimeFromSessionId(msg.session_id());
|
|
int proto_version = msg.proto_version();
|
|
int channel = f8::ExtractChannelIdFromAccountId(msg.account_id());
|
|
std::shared_ptr<Room> room = RoomMgr::Instance()->GetJoinableRoom
|
|
(
|
|
msg,
|
|
self_room_type,
|
|
game_times,
|
|
register_time,
|
|
proto_version,
|
|
channel
|
|
);
|
|
if (!room) {
|
|
#ifdef DEBUG
|
|
a8::XPrintf("GetJoinableRoom error %s\n", {msg.account_id()});
|
|
#endif
|
|
RoomMgr::Instance()->JoinErrorHandle(msg, 3, socket_handle);
|
|
return;
|
|
}
|
|
Player* hum = room->NewPlayer();
|
|
hum->proto_version = msg.proto_version();
|
|
#if 0
|
|
hum->hero_uniid = a8::XValue(msg.hero_uniid());
|
|
#endif
|
|
hum->battle_uuid = results.at(0)->battle_uuid;
|
|
hum->is_valid_battle = results.at(0)->is_valid_battle;
|
|
hum->payload = results.at(0)->payload;
|
|
PlayerMgr::Instance()->
|
|
CreatePlayerByCMJoin(hum,
|
|
ip_saddr,
|
|
socket_handle,
|
|
msg
|
|
);
|
|
hum->meta = mt::Hero::GetById(msg.hero_id());
|
|
if (!hum->meta) {
|
|
hum->meta = mt::Param::s().human_meta;
|
|
}
|
|
hum->room = room.get();
|
|
hum->SetBattleContext(results.at(0));
|
|
hum->GetBattleContext()->Init(hum);
|
|
{
|
|
long long hero_uniid = 0;
|
|
int hero_lv = 1;
|
|
int quality = 1;
|
|
hum->GetBattleContext()->GetHeroLvQuality(hero_uniid, hero_lv, quality);
|
|
hum->hero_uniid = hero_uniid;
|
|
}
|
|
room->AddPlayer(hum);
|
|
hum->ProcSkillList();
|
|
hum->SetHP(hum->GetBattleContext()->GetMaxHP());
|
|
hum->SetMaxHP(hum->GetHP());
|
|
PlayerMgr::Instance()->IncAccountNum(msg.account_id());
|
|
RoomMgr::Instance()->OnJoinRoomOk(msg, hum);
|
|
};
|
|
SendGetBattleData(0, join_msgs, cb);
|
|
}
|
|
|
|
void RoomMgr::_CMReconnect(f8::MsgHdr& hdr, const cs::CMReconnect& msg)
|
|
{
|
|
auto send_reconnect_failed =
|
|
[] (int socket_handle, int errcode, const std::string& errmsg)
|
|
{
|
|
cs::SMReconnect respmsg;
|
|
respmsg.set_errcode(errcode);
|
|
respmsg.set_errmsg(errmsg);
|
|
GGListener::Instance()->SendToClient(socket_handle, 0, respmsg);
|
|
f8::Timer::Instance()->SetTimeout
|
|
(
|
|
1000 * 3,
|
|
[socket_handle] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
GGListener::Instance()->ForceCloseChildSocket(socket_handle);
|
|
}
|
|
}
|
|
);
|
|
};
|
|
|
|
auto room = GetRoomByUuid(a8::XValue(msg.room_uuid()));
|
|
if (!room) {
|
|
send_reconnect_failed(hdr.socket_handle, 1,
|
|
TEXT("battle_server_reconnect_failreason_room_destoryed", "房间已销毁"));
|
|
f8::UdpLog::Instance()->Debug
|
|
("房间已销毁 %s",
|
|
{
|
|
msg.room_uuid()
|
|
});
|
|
return;
|
|
}
|
|
#if 0
|
|
if (room->GetRoomMode() != kPvpMode) {
|
|
send_reconnect_failed(hdr.socket_handle, 1,
|
|
TEXT("battle_server_reconnect_failreason_only_chiji", "只有吃鸡模式支持重连"));
|
|
return;
|
|
}
|
|
#endif
|
|
Player* hum = room->GetPlayerByAccountId(msg.account_id());
|
|
if (!hum) {
|
|
send_reconnect_failed(hdr.socket_handle, 1,
|
|
TEXT("battle_server_reconnect_failreason_notfound_accountid", "accountid未在房间列表"));
|
|
return;
|
|
}
|
|
hum->_CMReconnect(hdr, msg);
|
|
}
|
|
|
|
void RoomMgr::_CMPing(f8::MsgHdr& hdr, const cs::CMPing& msg)
|
|
{
|
|
cs::SMPing respmsg;
|
|
GGListener::Instance()->SendToClient(hdr.socket_handle, 0, respmsg);
|
|
}
|
|
|
|
int RoomMgr::RoomNum()
|
|
{
|
|
return room_hash_.size();
|
|
}
|
|
|
|
int RoomMgr::OverRoomNum()
|
|
{
|
|
return over_room_hash_.size();
|
|
}
|
|
|
|
std::shared_ptr<Room> RoomMgr::GetJoinableRoom(const cs::CMJoin& msg,
|
|
const RoomType_e self_room_type,
|
|
int game_times,
|
|
int creator_register_time,
|
|
int proto_version,
|
|
int channel
|
|
)
|
|
{
|
|
std::vector<std::vector<std::shared_ptr<Room>>> group_rooms;
|
|
for (int i = 0; i < RoomType_Max; ++i) {
|
|
group_rooms.push_back(std::vector<std::shared_ptr<Room>>());
|
|
}
|
|
for (auto& pair : inactive_room_hash_) {
|
|
auto& room = pair.second;
|
|
if (!room->GetCustomBattle() &&
|
|
room->CanJoin(msg.account_id(),
|
|
self_room_type,
|
|
(RoomMode_e)msg.room_mode(),
|
|
proto_version,
|
|
channel,
|
|
msg.mapid(),
|
|
msg)) {
|
|
if (!msg.team_uuid().empty() && room->HaveMyTeam(msg.team_uuid())) {
|
|
return room;
|
|
}
|
|
group_rooms[room->GetRoomType()].push_back(room);
|
|
}
|
|
}
|
|
|
|
if (!group_rooms[self_room_type].empty()) {
|
|
return group_rooms[self_room_type][rand() % group_rooms[self_room_type].size()];
|
|
}
|
|
if (msg.room_mode() == kPvpRankMode) {
|
|
} else {
|
|
if (self_room_type == RoomType_OldBrid2) {
|
|
for (auto& room : group_rooms[RoomType_OldBrid3]) {
|
|
if (room->GetGasInactiveReaminTime() > 8 &&
|
|
room->GetPlayerNum() + 8 < room->GetRoomMaxPlayerNum()) {
|
|
return room;
|
|
}
|
|
}
|
|
} else if (self_room_type == RoomType_OldBrid3) {
|
|
for (auto& room : group_rooms[RoomType_OldBrid2]) {
|
|
if (room->GetGasInactiveReaminTime() > 8 &&
|
|
room->GetPlayerNum() + 8 < room->GetRoomMaxPlayerNum()) {
|
|
return room;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
return CreateRoom(msg,
|
|
self_room_type,
|
|
game_times,
|
|
creator_register_time,
|
|
proto_version,
|
|
channel,
|
|
msg.mapid(),
|
|
nullptr);
|
|
}
|
|
|
|
std::shared_ptr<Room> RoomMgr::GetJoinableRoom(MatchTeam* team)
|
|
{
|
|
for (auto& pair : inactive_room_hash_) {
|
|
auto room = pair.second;
|
|
if (room->CanJoin(team)) {
|
|
return room;
|
|
}
|
|
}
|
|
int game_times = 0;
|
|
RoomType_e self_room_type = RoomType_OldBrid1;
|
|
time_t register_time = f8::ExtractRegisterTimeFromSessionId(team->GetOwner()->msg->session_id());
|
|
int proto_version = team->GetOwner()->msg->proto_version();
|
|
int channel = f8::ExtractChannelIdFromAccountId(team->GetOwner()->msg->account_id());
|
|
|
|
return CreateRoom(*team->GetOwner()->msg,
|
|
self_room_type,
|
|
game_times,
|
|
register_time,
|
|
proto_version,
|
|
channel,
|
|
team->GetOwner()->msg->mapid(),
|
|
nullptr);
|
|
}
|
|
|
|
std::shared_ptr<Room> RoomMgr::GetRoomByUuid(const std::string& room_uuid)
|
|
{
|
|
auto itr = room_hash_.find(room_uuid);
|
|
return itr != room_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
std::shared_ptr<Room> RoomMgr::GetRoomByIdx(int room_idx)
|
|
{
|
|
auto itr = room_idx_hash_.find(room_idx);
|
|
return itr != room_idx_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
void RoomMgr::AddOverRoom(const std::string& room_uuid)
|
|
{
|
|
auto callback =
|
|
[room_uuid] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
auto room = RoomMgr::Instance()->GetRoomByUuid(room_uuid);
|
|
if (room) {
|
|
RoomMgr::Instance()->room_hash_.erase(room->GetRoomUuid());
|
|
RoomMgr::Instance()->over_room_hash_[room->GetRoomUuid()] = room;
|
|
RoomMgr::Instance()->FreeOverRoom(room_uuid);
|
|
}
|
|
}
|
|
};
|
|
|
|
inactive_room_hash_.erase(room_uuid);
|
|
auto room = GetRoomByUuid(room_uuid);
|
|
if (room) {
|
|
room->added_to_over_room = true;
|
|
f8::Timer::Instance()->SetIntervalEx
|
|
(1000 * 5,
|
|
callback,
|
|
&room->timer_attacher);
|
|
}
|
|
}
|
|
|
|
void RoomMgr::ActiveRoom(const std::string& room_uuid)
|
|
{
|
|
inactive_room_hash_.erase(room_uuid);
|
|
}
|
|
|
|
void RoomMgr::ReportServerState(int instance_id, const std::string& host, int port)
|
|
{
|
|
auto cb =
|
|
[instance_id, host, port]
|
|
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
|
|
{
|
|
if (ok) {
|
|
f8::Timer::Instance()->SetTimeoutEx
|
|
(1000,
|
|
[instance_id, host, port] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
RoomMgr::Instance()->ReportServerState(
|
|
instance_id,
|
|
host,
|
|
port
|
|
);
|
|
}
|
|
},
|
|
&RoomMgr::Instance()->reportstate_timer_attacher_);
|
|
} else {
|
|
f8::Timer::Instance()->SetTimeoutEx
|
|
(1000,
|
|
[instance_id, host, port]
|
|
(int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
RoomMgr::Instance()->ReportServerState
|
|
(
|
|
instance_id,
|
|
host,
|
|
port
|
|
);
|
|
}
|
|
},
|
|
&RoomMgr::Instance()->reportstate_timer_attacher_);
|
|
}
|
|
};
|
|
std::string url = a8::Format("http://%s:%d/webapp/index.php?c=GS&a=report&",
|
|
{
|
|
host,
|
|
port
|
|
});
|
|
auto url_params = a8::MutableXObject::CreateObject();
|
|
url_params->SetVal("node_id", App::Instance()->GetNodeId());
|
|
url_params->SetVal("instance_id", App::Instance()->GetInstanceId());
|
|
url_params->SetVal("ip", JsonDataMgr::Instance()->ip);
|
|
url_params->SetVal("port", JsonDataMgr::Instance()->listen_port);
|
|
url_params->SetVal("online_num", PlayerMgr::Instance()->OnlineNum());
|
|
url_params->SetVal("room_num", RoomNum());
|
|
url_params->SetVal("channel", JsonDataMgr::Instance()->channel);
|
|
url_params->SetVal("alive_count", PerfMonitor::Instance()->real_alive_count);
|
|
url_params->SetVal("servicing", App::Instance()->IsServicing() ? 1 : 0);
|
|
f8::HttpClientPool::Instance()->HttpGet
|
|
(
|
|
cb,
|
|
url.c_str(),
|
|
*url_params,
|
|
rand() % MAX_SYS_HTTP_NUM
|
|
);
|
|
}
|
|
|
|
void RoomMgr::FreeOverRoom(const std::string& room_uuid)
|
|
{
|
|
auto itr = over_room_hash_.find(room_uuid);
|
|
if (itr != over_room_hash_.end()) {
|
|
--PerfMonitor::Instance()->room_num[itr->second->GetRoomType()];
|
|
itr->second->UnInit();
|
|
room_idx_hash_.erase(itr->second->GetRoomIdx());
|
|
over_room_hash_.erase(itr);
|
|
}
|
|
}
|
|
|
|
void RoomMgr::InstallReportStateTimer()
|
|
{
|
|
reportstate_timer_attacher_.ClearTimerList();
|
|
auto master_svr_cluster_conf = JsonDataMgr::Instance()->GetMasterServerClusterConf();
|
|
for (int i = 0; i < master_svr_cluster_conf->Size(); ++i) {
|
|
auto master_svr_conf = master_svr_cluster_conf->At(i);
|
|
int instance_id = master_svr_conf->At("instance_id")->AsXValue();
|
|
std::string remote_ip = master_svr_conf->At("ip")->AsXValue();
|
|
int remote_port = master_svr_conf->At("listen_port")->AsXValue();
|
|
|
|
f8::Timer::Instance()->SetTimeoutEx
|
|
(1000 + (i + 1),
|
|
[instance_id, remote_ip, remote_port]
|
|
(int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
RoomMgr::Instance()->ReportServerState
|
|
(
|
|
instance_id,
|
|
remote_ip,
|
|
remote_port
|
|
);
|
|
}
|
|
},
|
|
&reportstate_timer_attacher_);
|
|
}
|
|
}
|
|
|
|
bool RoomMgr::IsLimitJoin()
|
|
{
|
|
return RoomNum() >= ROOM_NUM_UP_LIMIT ||
|
|
(
|
|
PerfMonitor::Instance()->real_alive_count >= HUM_NUM_DOWN_LIMIT
|
|
);
|
|
}
|
|
|
|
int RoomMgr::AllocRoomIdx()
|
|
{
|
|
do {
|
|
if (current_room_idx_ < 0) {
|
|
current_room_idx_ = 0;
|
|
}
|
|
if (current_room_idx_ >= (MAX_ROOM_IDX - 3)) {
|
|
current_room_idx_ = 0;
|
|
}
|
|
} while (GetRoomByIdx(++current_room_idx_));
|
|
return current_room_idx_;
|
|
}
|
|
|
|
std::shared_ptr<Room> RoomMgr::CreateRoom(const cs::CMJoin& msg,
|
|
RoomType_e room_type,
|
|
int game_times,
|
|
int creator_register_time,
|
|
int creator_proto_version,
|
|
int creator_channel,
|
|
int map_id,
|
|
std::shared_ptr<CustomBattle> custom_battle)
|
|
{
|
|
int room_idx = AllocRoomIdx();
|
|
if (room_idx < 1) {
|
|
return nullptr;
|
|
}
|
|
RoomInitInfo init_info;
|
|
{
|
|
init_info.room_idx = room_idx;
|
|
init_info.room_uuid = App::Instance()->NewUuid();
|
|
init_info.room_type = room_type;
|
|
init_info.room_mode = (RoomMode_e)msg.room_mode();
|
|
init_info.init_map_id = map_id;
|
|
init_info.creator_game_times = game_times;
|
|
init_info.creator_register_time = creator_register_time;
|
|
init_info.creator_proto_version = creator_proto_version;
|
|
init_info.creator_channel = creator_channel;
|
|
init_info.pve_instance_id = msg.pve_instance_id();
|
|
init_info.pve_human_num = std::max(1, msg.team_members_size());
|
|
init_info.is_newbie_room = msg.force_enter_newbie_room() ? true : false;
|
|
init_info.custom_battle = custom_battle;
|
|
if (GetRoomByUuid(init_info.room_uuid)) {
|
|
A8_ABORT();
|
|
}
|
|
if (GetRoomByIdx(init_info.room_idx)) {
|
|
A8_ABORT();
|
|
}
|
|
}
|
|
auto room = std::make_shared<Room>();
|
|
MapMgr::Instance()->AttachRoom(room.get(), init_info);
|
|
room->InitData(init_info);
|
|
room->Init();
|
|
inactive_room_hash_[room->GetRoomUuid()] = room;
|
|
room_hash_[room->GetRoomUuid()] = room;
|
|
room_idx_hash_[room->GetRoomIdx()] = room;
|
|
++PerfMonitor::Instance()->room_num[room->GetRoomType()];
|
|
#ifdef DEBUG
|
|
f8::UdpLog::Instance()->Debug("createroom room_idx:%d room_uuid:%d room_type:%d",
|
|
{
|
|
room->GetRoomIdx(),
|
|
room->GetRoomUuid(),
|
|
room->GetRoomType()
|
|
});
|
|
#endif
|
|
return room;
|
|
}
|
|
|
|
void RoomMgr::JoinErrorHandle(const cs::CMJoin& msg, int error_code, int socket_handle)
|
|
{
|
|
{
|
|
cs::SMJoinedNotify notifymsg;
|
|
notifymsg.set_error_code(error_code);
|
|
GGListener::Instance()->SendToClient(socket_handle, 0, notifymsg);
|
|
}
|
|
{
|
|
f8::Timer::Instance()->SetTimeout
|
|
(1000 * 2,
|
|
[socket_handle] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
GGListener::Instance()->ForceCloseChildSocket(socket_handle);
|
|
}
|
|
});
|
|
}
|
|
f8::UdpLog::Instance()->Warning
|
|
("join error errcode:%d accountid:%s max_mainloop_rundelay:%d "
|
|
"room_num:%d player_num:%d online_num:%d",
|
|
{
|
|
error_code,
|
|
msg.account_id(),
|
|
PerfMonitor::Instance()->max_run_delay_time,
|
|
RoomMgr::Instance()->RoomNum(),
|
|
PerfMonitor::Instance()->entity_num[ET_Player],
|
|
PlayerMgr::Instance()->OnlineNum(),
|
|
});
|
|
}
|
|
|
|
bool RoomMgr::IsGM(const std::string& account_id)
|
|
{
|
|
return gm_hash_.find(account_id) != gm_hash_.end();
|
|
}
|
|
|
|
void RoomMgr::JoinTeam(MatchTeam* team)
|
|
{
|
|
auto room = GetJoinableRoom(team);
|
|
if (!room) {
|
|
return;
|
|
}
|
|
room->AddTeam(team);
|
|
}
|
|
|
|
std::string RoomMgr::GenTeamHashData(const std::string& team_uuid, std::map<std::string, std::string>* team_hash)
|
|
{
|
|
std::string data;
|
|
data += a8::Format("team_uuid:%s ", {team_uuid});
|
|
for (auto pair : *team_hash) {
|
|
data += a8::Format("%s->%d ", {pair.first, pair.second});
|
|
}
|
|
return data;
|
|
}
|
|
|
|
void RoomMgr::OnJoinRoomOk(const cs::CMJoin& msg, Player* hum)
|
|
{
|
|
if (msg.team_uuid().empty()) {
|
|
return;
|
|
}
|
|
std::map<std::string, std::string>* team_hash = nullptr;
|
|
{
|
|
auto itr = team_room_hash_.find(msg.team_uuid());
|
|
if (itr == team_room_hash_.end()) {
|
|
team_room_hash_[msg.team_uuid()] = std::map<std::string, std::string>();
|
|
itr = team_room_hash_.find(msg.team_uuid());
|
|
team_hash = &itr->second;
|
|
for (auto& team_member : msg.team_members()) {
|
|
team_hash->insert(std::make_pair(team_member.account_id(), ""));
|
|
}
|
|
std::string team_uuid = msg.team_uuid();
|
|
f8::Timer::Instance()->SetTimeout
|
|
(1000 * 60,
|
|
[team_uuid] (int event, const a8::Args* args)
|
|
{
|
|
if (a8::TIMER_EXEC_EVENT == event) {
|
|
RoomMgr::Instance()->TeamRoomTimeOut(team_uuid);
|
|
}
|
|
}
|
|
);
|
|
} else {
|
|
team_hash = &itr->second;
|
|
}
|
|
}
|
|
if (!team_hash) {
|
|
A8_ABORT();
|
|
}
|
|
hum->init_team_member_num = team_hash->size();
|
|
{
|
|
auto itr = team_hash->find(hum->account_id);
|
|
if (itr != team_hash->end()) {
|
|
itr->second = hum->room->GetRoomUuid();
|
|
} else {
|
|
f8::UdpLog::Instance()->Warning
|
|
("team_data:%s account_id:%s not exists",
|
|
{
|
|
GenTeamHashData(msg.team_uuid(), team_hash),
|
|
hum->account_id
|
|
});
|
|
}
|
|
}
|
|
}
|
|
|
|
void RoomMgr::TeamRoomTimeOut(const std::string& team_uuid)
|
|
{
|
|
std::map<std::string, std::string>* team_hash = nullptr;
|
|
{
|
|
auto itr = team_room_hash_.find(team_uuid);
|
|
if (itr != team_room_hash_.end()) {
|
|
team_hash = &itr->second;
|
|
}
|
|
}
|
|
if (team_hash) {
|
|
bool ok = true;
|
|
for (auto pair : *team_hash) {
|
|
if (pair.second.empty()) {
|
|
ok = false;
|
|
break;
|
|
}
|
|
}
|
|
if (!ok) {
|
|
f8::UdpLog::Instance()->Warning
|
|
("team match failed team_data:%s ",
|
|
{
|
|
GenTeamHashData(team_uuid, team_hash),
|
|
});
|
|
}
|
|
team_room_hash_.erase(team_uuid);
|
|
} else {
|
|
f8::UdpLog::Instance()->Warning
|
|
("team not found team_uuid:s",
|
|
{
|
|
team_uuid
|
|
});
|
|
}
|
|
}
|
|
|
|
void RoomMgr::SendGetBattleData(int mode,
|
|
std::vector<std::shared_ptr<cs::CMJoin>>& join_msgs,
|
|
std::function<
|
|
void(std::vector<std::shared_ptr<BattleDataContext>>&)> cb)
|
|
{
|
|
if (join_msgs.empty()) {
|
|
abort();
|
|
}
|
|
std::shared_ptr<std::vector<std::shared_ptr<BattleDataContext>>> result =
|
|
std::make_shared<std::vector<std::shared_ptr<BattleDataContext>>>();
|
|
bool is_old_version = false;
|
|
for (auto& msg : join_msgs) {
|
|
std::shared_ptr<BattleDataContext> context = std::make_shared<BattleDataContext>();
|
|
context->join_msg = msg;
|
|
context->battle_uuid = App::Instance()->NewUuid();
|
|
context->errcode = 100;
|
|
context->errmsg = "";
|
|
result->push_back(context);
|
|
if (msg->proto_version() < 2022032201) {
|
|
is_old_version = true;
|
|
}
|
|
}
|
|
{
|
|
std::string url;
|
|
JsonDataMgr::Instance()->GetApiUrl(url);
|
|
if (url.find('?') != std::string::npos) {
|
|
url += "&c=Battle&a=getBattleData";
|
|
} else {
|
|
url += "?&c=Battle&a=getBattleData";
|
|
}
|
|
auto url_params = a8::MutableXObject::CreateObject();
|
|
{
|
|
auto members = a8::MutableXObject::CreateArray();
|
|
int i = 0;
|
|
for (auto msg : join_msgs) {
|
|
auto member = a8::MutableXObject::CreateObject();
|
|
member->SetVal("account_id", msg->account_id());
|
|
member->SetVal("session_id", msg->session_id());
|
|
member->SetVal("hero_uniid", msg->hero_uniid());
|
|
member->SetVal("battle_uuid", result->at(i)->battle_uuid);
|
|
member->SetVal("weapon_uuid1",
|
|
msg->weapons().size() > 0 ? msg->weapons(0).weapon_uniid() : "");
|
|
member->SetVal("weapon_uuid2",
|
|
msg->weapons().size() > 1 ? msg->weapons(1).weapon_uniid() : "");
|
|
#if 0
|
|
member->SetVal("cmjoin", f8::PbToJson(msg.get()));
|
|
#endif
|
|
++i;
|
|
members->Push(*member.get());
|
|
}
|
|
url_params->SetVal("account_id", join_msgs[0]->account_id());
|
|
url_params->SetVal("session_id", join_msgs[0]->session_id());
|
|
url_params->SetVal("team_uuid", join_msgs[0]->team_uuid());
|
|
url_params->SetVal("mode", mode);
|
|
url_params->SetVal("members", members->ToJsonStr());
|
|
}
|
|
HttpProxy::Instance()->HttpGet
|
|
(
|
|
[result, cb]
|
|
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
|
|
{
|
|
if (ok) {
|
|
f8::UdpLog::Instance()->Info
|
|
("GetBattleData ok %s",
|
|
{
|
|
rsp_obj->ToJsonStr()
|
|
});
|
|
|
|
if (rsp_obj->GetType() == a8::XOT_OBJECT) {
|
|
int match_mode = rsp_obj->Get("match_mode");
|
|
RoomMgr::Instance()->SetMatchMode(match_mode ? 1 : 0);
|
|
if (rsp_obj->HasKey("members")) {
|
|
auto members = rsp_obj->At("members");
|
|
if (members->GetType() == a8::XOT_ARRAY && members->Size() == result->size()) {
|
|
for (int i = 0; i < members->Size(); ++i) {
|
|
auto& ctx = result->at(i);
|
|
auto member = members->At(i);
|
|
if (member->GetType() == a8::XOT_OBJECT) {
|
|
ctx->ParseResult(*member);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
cb(*result);
|
|
} else {
|
|
f8::UdpLog::Instance()->Warning
|
|
("GetBattleData error %s",
|
|
{
|
|
""
|
|
});
|
|
cb(*result);
|
|
}
|
|
},
|
|
url.c_str(),
|
|
*url_params
|
|
);
|
|
}
|
|
}
|
|
|
|
void RoomMgr::SetMatchMode(int mode)
|
|
{
|
|
match_mode_ = mode;
|
|
}
|
|
|
|
void RoomMgr::AdjustCMJoin(cs::CMJoin* msg)
|
|
{
|
|
msg->set_force_enter_newbie_room(false);
|
|
msg->set_pve_instance_id(0);
|
|
#ifdef DEBUG
|
|
const mt::Map* map_meta = mt::Map::GetById(msg->mapid());
|
|
if (map_meta && map_meta->is_moba()) {
|
|
msg->set_room_mode(kMobaMode);
|
|
return;
|
|
}
|
|
#endif
|
|
#ifdef DEBUG1
|
|
{
|
|
auto data = a8::MutableXObject::CreateObject();
|
|
data->SetVal("zone_id", 1);
|
|
data->SetVal("node_id", 1);
|
|
data->SetVal("room_uuid", App::Instance()->NewUuid());
|
|
data->SetVal("start_time", Global::g_nowtime);
|
|
auto team_list = a8::MutableXObject::CreateArray();
|
|
{
|
|
std::map<std::string, std::string> test_members;
|
|
test_members[msg->account_id()] = msg->session_id();
|
|
auto team = a8::MutableXObject::CreateObject();
|
|
auto members = a8::MutableXObject::CreateArray();
|
|
team->SetVal("team_uuid", App::Instance()->NewUuid());
|
|
for (auto& pair : test_members) {
|
|
auto member = a8::MutableXObject::CreateObject();
|
|
member->SetVal("account_id", pair.first);
|
|
//member->SetVal("session_id", pair.second);
|
|
members->Push(*member.get());
|
|
}
|
|
team->SetVal("members", *members.get());
|
|
team_list->Push(*team.get());
|
|
}
|
|
{
|
|
std::map<std::string, std::string> test_members;
|
|
test_members[msg->account_id()] = "6513_2006_2";
|
|
auto team = a8::MutableXObject::CreateObject();
|
|
auto members = a8::MutableXObject::CreateArray();
|
|
team->SetVal("team_uuid", App::Instance()->NewUuid());
|
|
for (auto& pair : test_members) {
|
|
auto member = a8::MutableXObject::CreateObject();
|
|
member->SetVal("account_id", pair.first);
|
|
//member->SetVal("session_id", pair.second);
|
|
members->Push(*member.get());
|
|
}
|
|
team->SetVal("members", *members.get());
|
|
team_list->Push(*team.get());
|
|
}
|
|
data->SetVal("team_list", *team_list.get());
|
|
{
|
|
std::string custom_data = a8::openssl::md5
|
|
(data->ToJsonStr() + "520d8eAbB(8cf1^#$^&!@d833a42c820432PDAFE^^)") + "|" +
|
|
data->ToJsonStr();
|
|
msg->set_custom_room_payload(custom_data);
|
|
}
|
|
}
|
|
#endif
|
|
if (msg->proto_version() < cs::ProtoVersion) {
|
|
msg->set_mapid(2001);
|
|
}
|
|
#ifdef DEBUG1
|
|
if (DebugCmd::Enable()) {
|
|
msg->set_room_mode(kPvpRankMode);
|
|
}
|
|
#endif
|
|
if (msg->room_mode() < kPvpMode ||
|
|
msg->room_mode() >= kRoomModeEnd) {
|
|
#ifdef DEBUG
|
|
a8::XPrintf("AdjustCMJoin room_mode:%d pve_instance_id:%d\n",
|
|
{
|
|
msg->room_mode(),
|
|
msg->pve_instance_id()
|
|
});
|
|
#endif
|
|
msg->set_room_mode(kPvpMode);
|
|
msg->set_pve_instance_id(0);
|
|
return;
|
|
}
|
|
}
|
|
|
|
std::shared_ptr<CustomBattle> RoomMgr::GetCustomRoom(const std::string& room_uuid)
|
|
{
|
|
auto itr = custom_room_hash_.find(room_uuid);
|
|
return itr != custom_room_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
std::shared_ptr<CustomBattle> RoomMgr::GetHisCustomRoom(const std::string& room_uuid)
|
|
{
|
|
auto itr = his_custom_room_hash_.find(room_uuid);
|
|
return itr != his_custom_room_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
void RoomMgr::_CMJoinCustomBattle(f8::MsgHdr& hdr, const cs::CMJoin& msg)
|
|
{
|
|
if (msg.custom_room_payload().empty()) {
|
|
return;
|
|
}
|
|
std::shared_ptr<cs::CMJoin> join_msg = std::make_shared<cs::CMJoin>();
|
|
*join_msg = msg;
|
|
auto ip_saddr = hdr.ip_saddr;
|
|
auto socket_handle = hdr.socket_handle;
|
|
auto cb =
|
|
[join_msg, ip_saddr, socket_handle]
|
|
(int errcode, const std::string errmsg, std::shared_ptr<CustomBattle> p)
|
|
{
|
|
auto& msg = *join_msg;
|
|
if (errcode) {
|
|
RoomMgr::Instance()->JoinErrorHandle(*join_msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
if (Global::g_nowtime - p->GetStartTime() > 30) {
|
|
RoomMgr::Instance()->JoinErrorHandle(*join_msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
auto team = p->GetTeamByAccountId(msg.account_id());
|
|
if (!team) {
|
|
RoomMgr::Instance()->JoinErrorHandle(*join_msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
auto member = team->GetMember(msg.account_id());
|
|
if (!member) {
|
|
RoomMgr::Instance()->JoinErrorHandle(*join_msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
if (!p->CanAdd(join_msg->account_id(), join_msg->session_id())) {
|
|
RoomMgr::Instance()->JoinErrorHandle(*join_msg, 2, socket_handle);
|
|
return;
|
|
}
|
|
member->GetNetData()->join_msg = join_msg;
|
|
if (!p->GetRoom()) {
|
|
int game_times = 0;
|
|
RoomType_e self_room_type = GetHumanRoomType(member->GetNetData());
|
|
time_t register_time = f8::ExtractRegisterTimeFromSessionId(msg.session_id());
|
|
int proto_version = msg.proto_version();
|
|
int channel = f8::ExtractChannelIdFromAccountId(msg.account_id());
|
|
auto room = RoomMgr::Instance()->CreateRoom
|
|
(*join_msg,
|
|
self_room_type,
|
|
game_times,
|
|
register_time,
|
|
join_msg->proto_version(),
|
|
channel,
|
|
msg.mapid(),
|
|
p);
|
|
p->SetRoom(room.get());
|
|
}
|
|
Player* hum = p->GetRoom()->NewPlayer();
|
|
hum->room = p->GetRoom();
|
|
hum->proto_version = msg.proto_version();
|
|
#if 0
|
|
hum->hero_uniid = a8::XValue(msg.hero_uniid());
|
|
#endif
|
|
hum->battle_uuid = member->GetNetData()->battle_uuid;
|
|
hum->is_valid_battle = member->GetNetData()->is_valid_battle;
|
|
hum->payload = member->GetNetData()->payload;
|
|
msg.set_session_id(member->GetSessionId());
|
|
msg.set_team_uuid(team->GetTeamUuid());
|
|
PlayerMgr::Instance()->
|
|
CreatePlayerByCMJoin(hum,
|
|
ip_saddr,
|
|
socket_handle,
|
|
msg
|
|
);
|
|
hum->meta = mt::Hero::GetById(msg.hero_id());
|
|
if (!hum->meta) {
|
|
hum->meta = mt::Param::s().human_meta;
|
|
}
|
|
hum->SetBattleContext(member->GetNetData());
|
|
hum->GetBattleContext()->Init(hum);
|
|
{
|
|
long long hero_uniid = 0;
|
|
int hero_lv = 1;
|
|
int quality = 1;
|
|
hum->GetBattleContext()->GetHeroLvQuality(hero_uniid, hero_lv, quality);
|
|
hum->hero_uniid = hero_uniid;
|
|
}
|
|
p->GetRoom()->AddPlayer(hum);
|
|
hum->ProcSkillList();
|
|
hum->SetHP(hum->GetBattleContext()->GetMaxHP());
|
|
hum->SetMaxHP(hum->GetHP());
|
|
member->Join(hum);
|
|
PlayerMgr::Instance()->IncAccountNum(msg.account_id());
|
|
RoomMgr::Instance()->OnJoinRoomOk(msg, hum);
|
|
};
|
|
SendGetCustomBattleData(join_msg, cb);
|
|
}
|
|
|
|
void RoomMgr::SendGetCustomBattleData(std::shared_ptr<cs::CMJoin> join_msg,
|
|
std::function<void(int, const std::string, std::shared_ptr<CustomBattle>)> cb)
|
|
{
|
|
auto pos = join_msg->custom_room_payload().find('|');
|
|
std::string head;
|
|
std::string body;
|
|
if (pos == std::string::npos) {
|
|
cb(1, "custom battle data error", nullptr);
|
|
return;
|
|
}
|
|
head = join_msg->custom_room_payload().substr(0, pos);
|
|
body = join_msg->custom_room_payload().substr(pos + 1);
|
|
auto data = std::make_shared<a8::XObject>();
|
|
if (!data->ReadFromJsonString(body) ||
|
|
!data->IsObject()) {
|
|
cb(1, "custom battle data error", nullptr);
|
|
return;
|
|
}
|
|
int start_time = data->Get("start_time", "").GetInt();
|
|
if (Global::g_nowtime - start_time > 40) {
|
|
cb(2, "custom battle is started", nullptr);
|
|
return;
|
|
}
|
|
std::string room_uuid = data->Get("room_uuid", "").GetString();
|
|
if (room_uuid.empty()) {
|
|
cb(1, "custom battle data error", nullptr);
|
|
return;
|
|
}
|
|
auto his_room = GetHisCustomRoom(room_uuid);
|
|
if (his_room) {
|
|
cb(2, "custom battle is dissolution", nullptr);
|
|
return;
|
|
}
|
|
auto cur_room = GetCustomRoom(room_uuid);
|
|
if (cur_room) {
|
|
cb(0, "", cur_room);
|
|
return;
|
|
}
|
|
{
|
|
std::string url;
|
|
JsonDataMgr::Instance()->GetApiUrl(url);
|
|
if (url.find('?') != std::string::npos) {
|
|
url += "&c=Battle&a=getCustomBattleData";
|
|
} else {
|
|
url += "?&c=Battle&a=getCustomBattleData";
|
|
}
|
|
auto url_params = a8::MutableXObject::CreateObject();
|
|
url_params->SetVal("account_id", join_msg->account_id());
|
|
url_params->SetVal("session_id", join_msg->session_id());
|
|
url_params->SetVal("__POST", join_msg->custom_room_payload());
|
|
HttpProxy::Instance()->HttpGet
|
|
(
|
|
[cb]
|
|
(bool ok, a8::XObject* rsp_obj, f8::HttpContext* ctx)
|
|
{
|
|
if (ok) {
|
|
f8::UdpLog::Instance()->Info
|
|
("GetBattleData ok %s",
|
|
{
|
|
rsp_obj->ToJsonStr()
|
|
});
|
|
if (rsp_obj->GetType() != a8::XOT_OBJECT ||
|
|
!rsp_obj->HasKey("errcode")) {
|
|
cb(1, "", nullptr);
|
|
return;
|
|
}
|
|
int errcode = rsp_obj->Get("errcode", "").GetInt();
|
|
std::string errmsg = rsp_obj->Get("errmsg", "").GetString();
|
|
if (errcode) {
|
|
cb(1, "", nullptr);
|
|
return;
|
|
}
|
|
std::string room_uuid = rsp_obj->Get("room_uuid", "").GetString();
|
|
if (room_uuid.empty()) {
|
|
cb(1, "custom battle data error", nullptr);
|
|
return;
|
|
}
|
|
auto cur_room = RoomMgr::Instance()->GetCustomRoom(room_uuid);
|
|
if (cur_room) {
|
|
cb(0, "", cur_room);
|
|
return;
|
|
}
|
|
|
|
auto custom_battle = std::make_shared<CustomBattle>();
|
|
custom_battle->ParseResult(*rsp_obj);
|
|
if (custom_battle->GetParseOk()) {
|
|
cb(0, "", custom_battle);
|
|
} else {
|
|
cb(1, "", custom_battle);
|
|
}
|
|
} else {
|
|
f8::UdpLog::Instance()->Warning
|
|
("GetCustomBattleData error %s",
|
|
{
|
|
""
|
|
});
|
|
cb(1, "custom battle data error", nullptr);
|
|
}
|
|
},
|
|
url.c_str(),
|
|
*url_params
|
|
);
|
|
}
|
|
}
|