352 lines
8.5 KiB
C++
352 lines
8.5 KiB
C++
#include "precompile.h"
|
|
|
|
#include <a8/timer.h>
|
|
|
|
#include "matchteam.h"
|
|
#include "matchmgr.h"
|
|
#include "GGListener.h"
|
|
#include "metamgr.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());
|
|
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->set_is_leader(is_leader);
|
|
p->set_state(state);
|
|
}
|
|
|
|
void RawTeamMember::InitRobot()
|
|
{
|
|
static long long robot_idx = 1000;
|
|
|
|
msg.set_account_id(a8::Format("6000_2005_%d", {++robot_idx}));
|
|
{
|
|
std::set<int> refreshed_robot_set;
|
|
MetaData::Robot* robot_meta = MetaMgr::Instance()->RandRobot(refreshed_robot_set);
|
|
if (robot_meta) {
|
|
msg.set_hero_id(robot_meta->i->hero_id());
|
|
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);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
auto member = GetMemberBySocket(hdr.socket_handle);
|
|
if (member) {
|
|
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();
|
|
}
|
|
}
|
|
|
|
void MatchTeam::_CMMatchStartGame(f8::MsgHdr& hdr, const cs::CMMatchStartGame& msg)
|
|
{
|
|
if (phase_ == kMatchChoose) {
|
|
auto member = GetMemberBySocket(hdr.socket_handle);
|
|
if (member) {
|
|
|
|
}
|
|
}
|
|
}
|
|
|
|
void MatchTeam::AddRawMember(f8::MsgHdr& hdr, const cs::CMJoin& msg)
|
|
{
|
|
std::shared_ptr<RawTeamMember> member = std::make_shared<RawTeamMember>();
|
|
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;
|
|
}
|
|
}
|
|
|
|
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)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
void MatchTeam::Update()
|
|
{
|
|
if (IsMasterTeam()) {
|
|
UpdateMaster();
|
|
} else {
|
|
UpdateSlave();
|
|
}
|
|
master_team_->SyncMatchInfo();
|
|
}
|
|
|
|
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_);
|
|
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) {
|
|
phase_ = kMatchChoose;
|
|
phase_start_tick_ = a8::XGetTickCount();
|
|
}
|
|
}
|
|
break;
|
|
case kMatchChoose:
|
|
{
|
|
if (phase_left_time_ <= 0) {
|
|
phase_ = kMatchLock;
|
|
phase_start_tick_ = a8::XGetTickCount();
|
|
}
|
|
}
|
|
break;
|
|
case kMatchLock:
|
|
{
|
|
|
|
}
|
|
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) {
|
|
return false;
|
|
}
|
|
//已合并
|
|
if (master_team_ != this){
|
|
return false;
|
|
}
|
|
//已合并
|
|
if (b->master_team_ != b) {
|
|
return false;
|
|
}
|
|
if (phase_ != kMatchCombining) {
|
|
return false;
|
|
}
|
|
if (b->phase_ != kMatchCombining) {
|
|
return false;
|
|
}
|
|
if (IsShuaRobotTime()) {
|
|
return false;
|
|
}
|
|
if (b->IsShuaRobotTime()) {
|
|
return false;
|
|
}
|
|
if (!b->combined_team_hash_.empty()) {
|
|
return false;
|
|
}
|
|
if (GetPredictMemberNum() + b->GetPredictMemberNum() > MAX_TEAM_NUM) {
|
|
return false;
|
|
}
|
|
if (combined_team_hash_.find(b->GetTeamUUid()) != combined_team_hash_.end()) {
|
|
return false;
|
|
}
|
|
if (HasSameCurrMember(b)) {
|
|
return false;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
void MatchTeam::Combine(MatchTeam* b)
|
|
{
|
|
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();
|
|
}
|
|
|
|
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<RawTeamMember> 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<RawTeamMember>();
|
|
}
|
|
|
|
void MatchTeam::ShuaRobot()
|
|
{
|
|
for (int i = curr_member_hash_.size(); i < MAX_TEAM_NUM; ++i) {
|
|
std::shared_ptr<RawTeamMember> member = std::make_shared<RawTeamMember>();
|
|
member->team = this;
|
|
member->add_tick = a8::XGetTickCount();
|
|
member->is_robot = true;
|
|
member->InitRobot();
|
|
curr_member_hash_.push_back(member);
|
|
}
|
|
}
|
|
|
|
void MatchTeam::StartGame()
|
|
{
|
|
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());
|
|
}
|