473 lines
16 KiB
C++
473 lines
16 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/timer.h>
|
|
#include <a8/mutable_xobject.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 "metamgr.h"
|
|
#include "jsondatamgr.h"
|
|
#include "playermgr.h"
|
|
#include "mapmgr.h"
|
|
#include "perfmonitor.h"
|
|
|
|
#include "framework/cpp/httpclientpool.h"
|
|
#include "framework/cpp/utils.h"
|
|
|
|
const int ROOM_NUM_UP_LIMIT = 1000;
|
|
const int HUM_NUM_DOWN_LIMIT = 2500;
|
|
|
|
static RoomType_e GetHumanRoomType(const cs::CMJoin& msg, int& game_times)
|
|
{
|
|
game_times = 0;
|
|
std::vector<std::string> tmp_strings;
|
|
a8::Split(msg.pre_settlement_info(), tmp_strings, ',');
|
|
if (tmp_strings.size() < 3) {
|
|
return RT_NewBrid;
|
|
}
|
|
//游戏次数,吃鸡数,击杀数,段位
|
|
game_times = a8::XValue(tmp_strings[0]);
|
|
int room_rank = tmp_strings.size() > 3 ? a8::XValue(tmp_strings[3]).GetInt() : 0;
|
|
time_t register_time = f8::ExtractRegisterTimeFromSessionId(msg.session_id());
|
|
#if 1
|
|
#else
|
|
if (!f8::IsOnlineEnv() || RoomMgr::Instance()->IsGM(msg)) {
|
|
game_times = 0;
|
|
if (!msg.team_uuid().empty()) {
|
|
game_times = 1;
|
|
}
|
|
}
|
|
#endif
|
|
|
|
if (!msg.team_uuid().empty() && msg.team_members().size() > 1) {
|
|
for (auto& team_member : msg.team_members()) {
|
|
if (team_member.rank() > 0) {
|
|
if (team_member.rank() > room_rank) {
|
|
room_rank = team_member.rank();
|
|
register_time = team_member.create_time();
|
|
} else if(team_member.rank() == room_rank &&
|
|
team_member.create_time() > register_time) {
|
|
register_time = team_member.create_time();
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
if (msg.force_entry_newbie_room()) {
|
|
return RT_NewBrid;
|
|
}
|
|
if (game_times <= 0) {
|
|
return RT_NewBrid;
|
|
} else if (game_times == 1) {
|
|
return RT_MidBrid;
|
|
}
|
|
}
|
|
|
|
if (!msg.team_uuid().empty() && msg.team_members().size() > 1) {
|
|
if (room_rank >= 0 && room_rank <= 6) {
|
|
return RT_OldBrid1;
|
|
} else if (a8::BetweenDays(Global::g_nowtime, register_time) <= 0) {
|
|
return RT_OldBrid2;
|
|
} else {
|
|
return RT_OldBrid3;
|
|
}
|
|
} else {
|
|
if (room_rank >= 0 && room_rank <= 6) {
|
|
//黄金段位以下
|
|
return RT_OldBrid1;
|
|
} else if (a8::BetweenDays(Global::g_nowtime, register_time) <= 0) {
|
|
//第一天,黄金段位以上
|
|
return RT_OldBrid2;
|
|
} else {
|
|
//其他
|
|
return RT_OldBrid3;
|
|
}
|
|
}
|
|
}
|
|
|
|
void RoomMgr::Init()
|
|
{
|
|
InstallReportStateTimer();
|
|
gm_hash_["6001_2004_oTR6b5d0UzpqJ1w-QbdUawWimgz0"] = 1;
|
|
}
|
|
|
|
void RoomMgr::UnInit()
|
|
{
|
|
for (auto& pair : room_hash_) {
|
|
pair.second->UnInit();
|
|
delete pair.second;
|
|
}
|
|
for (auto& pair : over_room_hash_) {
|
|
pair.second->UnInit();
|
|
delete pair.second;
|
|
}
|
|
}
|
|
|
|
void RoomMgr::Update(int delta_time)
|
|
{
|
|
long long real_alive_count = 0;
|
|
for (auto& pair : room_hash_) {
|
|
Room* 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;
|
|
}
|
|
int game_times = 0;
|
|
RoomType_e self_room_type = GetHumanRoomType(msg, game_times);
|
|
time_t register_time = f8::ExtractRegisterTimeFromSessionId(msg.session_id());
|
|
Room* room = GetJoinableRoom(msg,
|
|
self_room_type,
|
|
game_times,
|
|
register_time,
|
|
msg.force_entry_newbie_room()
|
|
);
|
|
if (!room) {
|
|
JoinErrorHandle(msg, 3, hdr.socket_handle);
|
|
return;
|
|
}
|
|
Player* hum = room->NewPlayer();
|
|
hum->ProcPreSettlementInfo(msg.pre_settlement_info());
|
|
PlayerMgr::Instance()->
|
|
CreatePlayerByCMJoin(hum,
|
|
hdr.ip_saddr,
|
|
hdr.socket_handle,
|
|
msg
|
|
);
|
|
hum->meta = MetaMgr::Instance()->human_meta;
|
|
hum->room = room;
|
|
hum->ProcPrepareItems(msg.prepare_items());
|
|
hum->ProcPrepareItems2(msg.prepare_items2());
|
|
room->AddPlayer(hum);
|
|
PlayerMgr::Instance()->IncAccountNum(msg.account_id());
|
|
}
|
|
|
|
int RoomMgr::RoomNum()
|
|
{
|
|
return room_hash_.size();
|
|
}
|
|
|
|
int RoomMgr::OverRoomNum()
|
|
{
|
|
return over_room_hash_.size();
|
|
}
|
|
|
|
Room* RoomMgr::GetJoinableRoom(const cs::CMJoin& msg,
|
|
const RoomType_e self_room_type,
|
|
int game_times,
|
|
int creator_register_time,
|
|
bool force_entry_newbie_room
|
|
)
|
|
{
|
|
std::vector<std::vector<Room*>> group_rooms;
|
|
for (int i = 0; i < RT_Max; ++i) {
|
|
group_rooms.push_back(std::vector<Room*>());
|
|
}
|
|
for (auto& pair : inactive_room_hash_) {
|
|
Room* room = pair.second;
|
|
if (room->CanJoin(msg.account_id(), self_room_type)) {
|
|
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 (self_room_type == RT_NewBrid) {
|
|
return CreateRoom(self_room_type,
|
|
game_times,
|
|
creator_register_time,
|
|
force_entry_newbie_room);
|
|
}
|
|
if (self_room_type == RT_MidBrid) {
|
|
return CreateRoom(self_room_type,
|
|
game_times,
|
|
creator_register_time,
|
|
force_entry_newbie_room);
|
|
}
|
|
for (int i = 0; i < RT_Max; ++i) {
|
|
for (Room* room : group_rooms[i]) {
|
|
if (room->GetRoomType() == self_room_type) {
|
|
return room;
|
|
}
|
|
}
|
|
}
|
|
return CreateRoom(self_room_type,
|
|
game_times,
|
|
creator_register_time,
|
|
force_entry_newbie_room);
|
|
}
|
|
|
|
Room* RoomMgr::GetRoomByUuid(long long room_uuid)
|
|
{
|
|
auto itr = room_hash_.find(room_uuid);
|
|
return itr != room_hash_.end() ? itr->second : nullptr;
|
|
}
|
|
|
|
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(long long room_uuid)
|
|
{
|
|
auto callback =
|
|
[] (const a8::XParams& param)
|
|
{
|
|
Room* room = RoomMgr::Instance()->GetRoomByUuid(param.sender);
|
|
if (room) {
|
|
RoomMgr::Instance()->room_hash_.erase(room->GetRoomUuid());
|
|
RoomMgr::Instance()->over_room_hash_[room->GetRoomUuid()] = room;
|
|
RoomMgr::Instance()->FreeOverRoom(param.sender);
|
|
}
|
|
};
|
|
|
|
inactive_room_hash_.erase(room_uuid);
|
|
Room* room = GetRoomByUuid(room_uuid);
|
|
if (room) {
|
|
a8::Timer::Instance()->AddRepeatTimerAndAttach
|
|
(1000 * 5,
|
|
a8::XParams()
|
|
.SetSender(room_uuid),
|
|
callback,
|
|
&room->timer_attacher.timer_list_);
|
|
}
|
|
}
|
|
|
|
void RoomMgr::ActiveRoom(long long room_uuid)
|
|
{
|
|
inactive_room_hash_.erase(room_uuid);
|
|
}
|
|
|
|
void RoomMgr::ReportServerState(int instance_id, const std::string& host, int port)
|
|
{
|
|
auto on_ok =
|
|
[] (a8::XParams& param, a8::XObject& data)
|
|
{
|
|
a8::Timer::Instance()->AddDeadLineTimerAndAttach
|
|
(1000,
|
|
a8::XParams()
|
|
.SetSender(param.sender)
|
|
.SetParam1(param.param1)
|
|
.SetParam2(param.param2),
|
|
[] (const a8::XParams& param)
|
|
{
|
|
RoomMgr::Instance()->ReportServerState(
|
|
param.sender,
|
|
param.param1,
|
|
param.param2
|
|
);
|
|
},
|
|
&RoomMgr::Instance()->reportstate_timer_attacher_.timer_list_);
|
|
};
|
|
auto on_error =
|
|
[] (a8::XParams& param, const std::string& response)
|
|
{
|
|
a8::Timer::Instance()->AddDeadLineTimerAndAttach
|
|
(1000,
|
|
a8::XParams()
|
|
.SetSender(param.sender)
|
|
.SetParam1(param.param1)
|
|
.SetParam2(param.param2),
|
|
[] (const a8::XParams& param)
|
|
{
|
|
RoomMgr::Instance()->ReportServerState(
|
|
param.sender,
|
|
param.param1,
|
|
param.param2
|
|
);
|
|
},
|
|
&RoomMgr::Instance()->reportstate_timer_attacher_.timer_list_);
|
|
};
|
|
std::string url = a8::Format("http://%s:%d/webapp/index.php?c=GS&a=report&",
|
|
{
|
|
host,
|
|
port
|
|
});
|
|
a8::MutableXObject* url_params = a8::MutableXObject::NewObject();
|
|
url_params->SetVal("node_id", App::Instance()->node_id);
|
|
url_params->SetVal("instance_id", App::Instance()->instance_id);
|
|
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("alive_count", PerfMonitor::Instance()->real_alive_count);
|
|
url_params->SetVal("servicing", App::Instance()->servicing ? 1 : 0);
|
|
f8::HttpClientPool::Instance()->HttpGet(a8::XParams()
|
|
.SetSender(instance_id)
|
|
.SetParam1(host)
|
|
.SetParam2(port),
|
|
on_ok,
|
|
on_error,
|
|
url.c_str(),
|
|
*url_params,
|
|
rand() % MAX_SYS_HTTP_NUM
|
|
);
|
|
delete url_params;
|
|
}
|
|
|
|
void RoomMgr::FreeOverRoom(long long 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());
|
|
delete itr->second;
|
|
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();
|
|
|
|
a8::Timer::Instance()->AddDeadLineTimerAndAttach
|
|
(1000 + (i + 1),
|
|
a8::XParams()
|
|
.SetSender(instance_id)
|
|
.SetParam1(remote_ip)
|
|
.SetParam2(remote_port),
|
|
[] (const a8::XParams& param)
|
|
{
|
|
RoomMgr::Instance()->ReportServerState(
|
|
param.sender,
|
|
param.param1,
|
|
param.param2
|
|
);
|
|
},
|
|
&reportstate_timer_attacher_.timer_list_);
|
|
}
|
|
}
|
|
|
|
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_;
|
|
}
|
|
|
|
Room* RoomMgr::CreateRoom(RoomType_e room_type,
|
|
int game_times,
|
|
int creator_register_time,
|
|
bool force_entry_newbie_room)
|
|
{
|
|
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.creator_game_times = game_times;
|
|
init_info.creator_register_time = creator_register_time;
|
|
init_info.force_entry_newbie_room = force_entry_newbie_room;
|
|
if (GetRoomByUuid(init_info.room_uuid)) {
|
|
abort();
|
|
}
|
|
if (GetRoomByIdx(init_info.room_idx)) {
|
|
abort();
|
|
}
|
|
}
|
|
Room* room = new Room();
|
|
MapMgr::Instance()->AttachRoom(room, 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
|
|
a8::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);
|
|
}
|
|
{
|
|
a8::Timer::Instance()->AddDeadLineTimer
|
|
(1000 * 2,
|
|
a8::XParams()
|
|
.SetSender(socket_handle),
|
|
[] (const a8::XParams& param)
|
|
{
|
|
GGListener::Instance()->ForceCloseChildSocket(param.sender);
|
|
});
|
|
}
|
|
a8::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 cs::CMJoin& msg)
|
|
{
|
|
if (gm_hash_.find(msg.account_id()) == gm_hash_.end()) {
|
|
return false;
|
|
}
|
|
for (int equip_id : msg.prepare_items()) {
|
|
MetaData::Equip* item_meta = MetaMgr::Instance()->GetEquip(equip_id);
|
|
if (item_meta) {
|
|
if (item_meta->i->equip_type() == EQUIP_TYPE_CAR) {
|
|
return true;
|
|
}
|
|
}
|
|
}
|
|
return false;
|
|
}
|