#include "precompile.h" #include #include "matchteam.h" #include "matchmgr.h" #include "GGListener.h" #include "metamgr.h" #include "roommgr.h" void RawTeamMember::FillMFMatchTeamMember(cs::MFMatchTeamMember* p) { p->set_account_id(msg.account_id()); p->set_name(msg.name()); p->set_avatar_url(msg.avatar_url()); if (choose_hero_times <= 0) { p->set_hero_id(0); } else { p->set_hero_id(msg.hero_id()); *p->mutable_weapons() = msg.weapons(); *p->mutable_skins() = msg.skins(); *p->mutable_skill_list() = msg.skill_list(); *p->mutable_baseskin() = msg.baseskin(); } p->set_is_leader(is_leader); p->set_state(state); p->set_head(msg.head()); p->set_hero_skin(msg.hero_skin()); } void RawTeamMember::InitRobot() { static long long robot_idx = 1000; msg.set_account_id(a8::Format("6000_2005_%d", {++robot_idx})); { std::set refreshed_robot_set; robot_meta = MetaMgr::Instance()->RandRobot(refreshed_robot_set); if (robot_meta) { #if 1 msg.set_hero_id(30100 + 100 * (robot_meta->i->id() % 3)); #else msg.set_hero_id(robot_meta->i->hero_id()); #endif msg.set_name(robot_meta->i->name()); auto skin = msg.add_skins(); if (!robot_meta->skin_id.empty()) { skin->set_skin_id(robot_meta->skin_id[0]); skin->set_skin_lv(1); } { MetaData::Player* hero_meta = MetaMgr::Instance()->GetPlayer(msg.hero_id()); if (hero_meta) { MetaData::PlayerSkin* skin_meta = MetaMgr::Instance()->GetPlayerSkin(hero_meta->i->skinlist()); if (skin_meta) { msg.set_hero_skin(skin_meta->i->id()); } } } } else { abort(); } } } MatchTeam::~MatchTeam() { timer_attacher.ClearTimerList(); #ifdef DEBUG a8::XPrintf("~MatchTeam %s\n", {GetTeamUUid()}); #endif } void MatchTeam::Init(f8::MsgHdr& hdr, const cs::CMJoin& msg) { master_team_ = this; create_tick_ = a8::XGetTickCount(); a8::Timer::Instance()->AddRepeatTimerAndAttach (1000, a8::XParams() .SetSender(this), [] (const a8::XParams& param) { MatchTeam* team = (MatchTeam*)param.sender.GetUserData(); team->Update(); }, &timer_attacher.timer_list_ ); phase_= kMatchCombining; phase_start_tick_ = a8::XGetTickCount(); countdown_ = MetaMgr::Instance()->match_team_time; AddRawMember(hdr, msg); } void MatchTeam::_CMMatchCancel(f8::MsgHdr& hdr, const cs::CMMatchCancel& msg) { auto member = GetMemberBySocket(hdr.socket_handle); if (member) { } } void MatchTeam::_CMMatchChoose(f8::MsgHdr& hdr, const cs::CMMatchChoose& msg) { #ifdef DEBUG a8::XPrintf("cmmatchchoose %s phase_:%d %s\n", {hdr.socket_handle, phase_, GetTeamUUid()}); { for (auto& pair : raw_member_hash_) { a8::XPrintf("cmmatchchoose member %d:%d:%s %s:%d\n", { hdr.socket_handle, phase_, GetTeamUUid(), pair.second->msg.account_id(), pair.second->socket_handle }); } } #endif auto member = GetMemberBySocket(hdr.socket_handle); if (member && master_team_->phase_ == kMatchChoose) { member->msg.set_hero_id(msg.hero_id()); *member->msg.mutable_weapons() = msg.weapons(); *member->msg.mutable_skins() = msg.skins(); *member->msg.mutable_skill_list() = msg.skill_list(); *member->msg.mutable_baseskin() = msg.baseskin(); member->msg.set_hero_skin(msg.hero_skin()); ++member->choose_hero_times; #ifdef DEBUG a8::XPrintf("matchchoose %s\n", {member->msg.account_id()}); #endif } } void MatchTeam::_CMMatchStartGame(f8::MsgHdr& hdr, const cs::CMMatchStartGame& msg) { if (master_team_->phase_ == kMatchChoose) { auto member = GetMemberBySocket(hdr.socket_handle); if (member) { member->state = kMatchPrepare; #ifdef DEBUG a8::XPrintf("matchgamestart %s\n", {member->msg.account_id()}); #endif } } } void MatchTeam::_CMMatchCancelStartGame(f8::MsgHdr& hdr, const cs::CMMatchCancelStartGame& msg) { if (master_team_->phase_ == kMatchChoose) { auto member = GetMemberBySocket(hdr.socket_handle); if (member) { member->state = kMatchReadying; #ifdef DEBUG a8::XPrintf("matchcancelgamestart %s\n", {member->msg.account_id()}); #endif } } } void MatchTeam::AddRawMember(f8::MsgHdr& hdr, const cs::CMJoin& msg) { std::shared_ptr member = std::make_shared(); member->team = this; member->add_tick = a8::XGetTickCount(); member->socket_handle = hdr.socket_handle; member->msg = msg; raw_member_hash_[msg.account_id()] = member; curr_member_hash_.push_back(member); if (!first_member_) { first_member_ = member; } if (master_team_ != this) { master_team_->curr_member_hash_.push_back(member); } #ifdef DEBUG a8::XPrintf("AddRawMember %s %s %d %d %d\n", { GetTeamUUid(), msg.account_id(), curr_member_hash_.size(), master_team_->curr_member_hash_.size(), master_team_ == this ? 1 : 0 }); #endif } bool MatchTeam::IsRawMember(const std::string &account_id) { auto itr = raw_member_hash_.find(account_id); return itr != raw_member_hash_.end(); } bool MatchTeam::IsValidMember(const cs::CMJoin& msg) { if (msg.team_members().size() <= 0) { return false; } if (first_member_->msg.team_uuid() != msg.team_uuid()) { return false; } if (first_member_->msg.team_members().size() != msg.team_members().size()) { return false; } for (int i = 0; i < msg.team_members().size(); ++i) { auto& a = msg.team_members(i); auto& b = first_member_->msg.team_members(i); if (a.account_id() != b.account_id()) { return false; } } return true; } void MatchTeam::Update() { if (IsMasterTeam()) { UpdateMaster(); } else { UpdateSlave(); } master_team_->SyncMatchInfo(); if (phase_ == kMatchStartGame && IsMasterTeam()) { StartGame(); } } void MatchTeam::SyncMatchInfo() { cs::SMUpdateMatchInfo notifymsg; for (auto member : curr_member_hash_) { member->FillMFMatchTeamMember(notifymsg.mutable_info()->add_members()); } notifymsg.mutable_info()->set_phase(phase_); notifymsg.mutable_info()->set_countdown(phase_left_time_); notifymsg.mutable_info()->set_predict_time(MetaMgr::Instance()->match_team_time); for (auto& member : curr_member_hash_) { if (member->socket_handle != 0) { GGListener::Instance()->SendToClient(member->socket_handle, 0, notifymsg); } } } void MatchTeam::TryCombineTeam() { if (GetPredictMemberNum() < MAX_TEAM_NUM) { MatchTeam* matched_team = nullptr; MatchMgr::Instance()->TraverseTeam ( [this, &matched_team] (MatchTeam* team, bool& stop) { if (team == this) { return; } if (CanCombine(team)) { matched_team = team; stop = true; } }); if (matched_team) { Combine(matched_team); } } } void MatchTeam::UpdateMaster() { phase_left_time_ = GetPhaseLeftTime(); switch (phase_) { case kMatchCombining: { if (IsShuaRobotTime()) { if (curr_member_hash_.size() < MAX_TEAM_NUM) { ShuaRobot(); } } else { if (GetPredictMemberNum() < MAX_TEAM_NUM) { TryCombineTeam(); } } if (phase_left_time_ <= 0 || GetPredictMemberNum() >= MAX_TEAM_NUM) { ChooseLeader(); phase_ = kMatchChoose; phase_start_tick_ = a8::XGetTickCount(); countdown_ = MetaMgr::Instance()->match_choose_time; } } break; case kMatchChoose: { UpdateTeamState(); CheckChoose(); CheckPrepare(); if ((phase_left_time_ <= MetaMgr::Instance()->match_lock_time) || IsAllPrepare()) { for (int i = 0; i < MAX_TEAM_NUM; ++i) { AutoChoose(true); } for (auto& member : curr_member_hash_) { member->state = kMatchPrepare; } phase_ = kMatchLock; phase_start_tick_ = a8::XGetTickCount(); countdown_ = MetaMgr::Instance()->match_lock_time; } } break; case kMatchLock: { if (phase_left_time_ <= 0) { phase_ = kMatchStartGame; phase_start_tick_ = a8::XGetTickCount(); } } break; case kMatchStartGame: { } break; default: { } break; } } void MatchTeam::UpdateSlave() { switch (phase_) { case kMatchCombining: { } break; case kMatchChoose: { } break; case kMatchLock: { } break; default: { } break; } } int MatchTeam::GetPredictMemberNum() { int num = GetRawMemberNum(); for (auto& pair : combined_team_hash_) { num += pair.second->GetRawMemberNum(); } return num; } bool MatchTeam::HasSameCurrMember(MatchTeam* b) { bool has = false; for (auto& a_member : curr_member_hash_) { for (auto& b_member : b->curr_member_hash_) { if (a_member->msg.account_id() == b_member->msg.account_id()) { has = true; break; } } } return has; } bool MatchTeam::CanCombine(MatchTeam* b) { if (this == b) { #ifdef DEBUG a8::XPrintf("CanCombine 1\n", {}); #endif return false; } //已合并 if (master_team_ != this){ #ifdef DEBUG a8::XPrintf("CanCombine 2\n", {}); #endif return false; } //已合并 if (b->master_team_ != b) { #ifdef DEBUG a8::XPrintf("CanCombine 3\n", {}); #endif return false; } if (phase_ != kMatchCombining) { #ifdef DEBUG a8::XPrintf("CanCombine 4\n", {}); #endif return false; } if (b->phase_ != kMatchCombining) { #ifdef DEBUG a8::XPrintf("CanCombine 5\n", {}); #endif return false; } if (IsShuaRobotTime()) { #ifdef DEBUG a8::XPrintf("CanCombine 6\n", {}); #endif return false; } if (b->IsShuaRobotTime()) { #ifdef DEBUG a8::XPrintf("CanCombine 7\n", {}); #endif return false; } if (!b->combined_team_hash_.empty()) { #ifdef DEBUG a8::XPrintf("CanCombine 8\n", {}); #endif return false; } if (GetPredictMemberNum() + b->GetPredictMemberNum() > MAX_TEAM_NUM) { #ifdef DEBUG a8::XPrintf("CanCombine 9\n", {}); #endif return false; } if (combined_team_hash_.find(b->GetTeamUUid()) != combined_team_hash_.end()) { #ifdef DEBUG a8::XPrintf("CanCombine 10\n", {}); #endif return false; } if (b->combined_team_hash_.find(GetTeamUUid()) != b->combined_team_hash_.end()) { #ifdef DEBUG a8::XPrintf("CanCombine 10\n", {}); #endif return false; } if (HasSameCurrMember(b)) { #ifdef DEBUG a8::XPrintf("CanCombine 11\n", {}); #endif return false; } return true; } void MatchTeam::Combine(MatchTeam* b) { #ifdef DEBUG a8::XPrintf("Combine %s->%s %d:%d", { b->GetTeamUUid(), GetTeamUUid(), b->curr_member_hash_.size(), curr_member_hash_.size() }); #endif combined_team_hash_[b->GetTeamUUid()] = b; b->master_team_ = this; for (auto& member : b->curr_member_hash_) { curr_member_hash_.push_back(member); } } std::string MatchTeam::GetTeamUUid() { return first_member_->msg.team_uuid(); } int MatchTeam::GetMapId() { return first_member_->msg.mapid(); } bool MatchTeam::IsShuaRobotTime() { return phase_ == kMatchCombining && phase_left_time_ <= MetaMgr::Instance()->match_robot_time; } int MatchTeam::GetPhaseLeftTime() { int passtime = (a8::XGetTickCount() - phase_start_tick_) / 1000; return std::max(0, countdown_ - passtime); } std::shared_ptr MatchTeam::GetMemberBySocket(int socket_handle) { for (auto& pair : raw_member_hash_) { if (pair.second->socket_handle == socket_handle) { return pair.second; } } return std::shared_ptr(); } void MatchTeam::ShuaRobot() { for (int i = curr_member_hash_.size(); i < MAX_TEAM_NUM; ++i) { std::shared_ptr member = std::make_shared(); member->team = this; member->add_tick = a8::XGetTickCount(); member->is_robot = true; member->InitRobot(); curr_member_hash_.push_back(member); } } void MatchTeam::StartGame() { RoomMgr::Instance()->JoinTeam(this); for (auto& member : curr_member_hash_) { if (member->socket_handle != 0) { MatchMgr::Instance()->RemoveSocket(member->socket_handle); } } for (auto& pair : combined_team_hash_) { MatchMgr::Instance()->RemoveTeam(pair.first); } MatchMgr::Instance()->RemoveTeam(GetTeamUUid()); } void MatchTeam::ChooseLeader() { std::shared_ptr leader; for (auto& member : curr_member_hash_) { if (!member->is_robot) { if (member->socket_handle) { if (!leader) { leader = member; leader->is_leader = true; continue; } } } member->is_leader = false; } } void MatchTeam::AutoChoose(bool force) { for (auto& member : curr_member_hash_) { if (member->choose_hero_times <= 0) { if (member->is_robot){ ++member->choose_hero_times; } else if (force) { ++member->choose_hero_times; } } } } bool MatchTeam::IsAllPrepare() { int num = 0; for (auto& member : curr_member_hash_) { if (member->state == kMatchPrepare) { ++num; } } return num >= MAX_TEAM_NUM; } void MatchTeam::UpdateTeamState() { } void MatchTeam::CheckChoose() { if (phase_ != kMatchChoose) { return; } if (phase_left_time_ <= 10 || all_player_choose_times_ > 0) { if (last_auto_choose_tick_ <= 0) { AutoChoose(); last_auto_choose_tick_ = a8::XGetTickCount(); } else { if (a8::XGetTickCount() - last_auto_choose_tick_ > (last_auto_choose_tick_ % 3000)) { AutoChoose(); last_auto_choose_tick_ = a8::XGetTickCount(); } } } } void MatchTeam::CheckPrepare() { if (phase_ != kMatchChoose) { return; } }