#include "precompile.h" #include #include #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 "framework/cpp/httpclientpool.h" #include "framework/cpp/utils.h" const int ROOM_NUM_DOWN_LIMIT = 15; const int ROOM_NUM_UP_LIMIT = 40; const int HUM_NUM_DOWN_LIMIT = 1000; static RoomType_e GetHumanRoomType(const cs::CMJoin& msg) { std::vector tmp_strings; a8::Split(msg.pre_settlement_info(), tmp_strings, ','); if (tmp_strings.size() < 3) { return RT_NewBrid; } //游戏次数,吃鸡数,击杀数 int game_times = a8::XValue(tmp_strings[0]); #if 0 int win_times = a8::XValue(tmp_strings[1]); int kill_times = a8::XValue(tmp_strings[2]); #endif if (game_times <= MetaMgr::Instance()->newbie_game_times) { return RT_NewBrid; } else if (game_times == 2) { return RT_MidBrid; } return RT_OldBrid; } void RoomMgr::Init() { InstallReportStateTimer(); } 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) { for (auto& pair : room_hash_) { pair.second->Update(delta_time); } } void RoomMgr::_CMJoin(f8::MsgHdr& hdr, const cs::CMJoin& msg) { if (IsLimitJoin()) { JoinErrorHandle(msg, 2, hdr.socket_handle); return; } RoomType_e self_room_type = GetHumanRoomType(msg); Room* room = GetJoinableRoom(msg, self_room_type); if (!room) { JoinErrorHandle(msg, 3, hdr.socket_handle); return; } Player* hum = PlayerMgr::Instance()-> CreatePlayerByCMJoin(hdr.ip_saddr, hdr.socket_handle, msg); hum->meta = MetaMgr::Instance()->human_meta; hum->ProcPrepareItems(msg.prepare_items()); hum->ProcPrepareItems2(msg.prepare_items2()); room->AddPlayer(hum); } 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) { std::vector> group_rooms; for (int i = 0; i < RT_Max; ++i) { group_rooms.push_back(std::vector()); } 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->room_type].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) { if (RoomNum() < ROOM_NUM_DOWN_LIMIT - 5) { return nullptr; } } if (self_room_type == RT_MidBrid) { if (RoomNum() < ROOM_NUM_DOWN_LIMIT - 5) { return nullptr; } } for (int i = 0; i < RT_Max; ++i) { if (RoomNum() > ROOM_NUM_DOWN_LIMIT - 5) { for (Room* room : group_rooms[i]) { return room; } } else { if (i != self_room_type) { for (Room* room : group_rooms[i]) { return room; } } } } return CreateRoom(self_room_type); } 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) { if ((room->pending_request <= 0) || (a8::XGetTickCount() - room->game_over_tick > 1000 * 8)) { RoomMgr::Instance()->room_hash_.erase(room->room_uuid); RoomMgr::Instance()->over_room_hash_[room->room_uuid] = room; RoomMgr::Instance()->FreeOverRoom(param.sender); } } }; inactive_room_hash_.erase(room_uuid); Room* room = GetRoomByUuid(room_uuid); if (room) { room->game_over_tick = a8::XGetTickCount(); room->game_over_timer = a8::Timer::Instance()->AddRepeatTimer(500, a8::XParams() .SetSender(room_uuid), callback); } } 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", App::Instance()->perf.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()) { itr->second->UnInit(); room_idx_hash_.erase(itr->second->room_idx); 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 || ( RoomNum() >= ROOM_NUM_DOWN_LIMIT && App::Instance()->perf.alive_count >= HUM_NUM_DOWN_LIMIT ); } int RoomMgr::AllocRoomIdx() { do { if (current_room_idx_ <= 0) { current_room_idx_ = 1; } if (current_room_idx_ >= (MAX_ROOM_IDX - 1)) { current_room_idx_ = 1; } } while (GetRoomByIdx(++current_room_idx_)); return current_room_idx_; } Room* RoomMgr::CreateRoom(RoomType_e room_type) { int room_idx = AllocRoomIdx(); if (room_idx < 1) { return nullptr; } Room* room = new Room(); room->room_type = room_type; room->room_uuid = App::Instance()->NewUuid(); room->room_idx = AllocRoomIdx(); MapMgr::Instance()->AttachRoom(room); if (GetRoomByUuid(room->room_uuid)) { abort(); } if (GetRoomByIdx(room->room_idx)) { abort(); } room->Init(); inactive_room_hash_[room->room_uuid] = room; room_hash_[room->room_uuid] = room; room_idx_hash_[room->room_idx] = room; 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(), App::Instance()->perf.max_run_delay_time, RoomMgr::Instance()->RoomNum(), App::Instance()->perf.entity_num[ET_Player], PlayerMgr::Instance()->OnlineNum(), }); }