aozhiwei 2bc17d7a2e 1
2024-08-01 14:06:01 +08:00

733 lines
17 KiB
Go

package team
import (
"q5"
"f5"
"cs"
"mt"
"main/common"
"main/constant"
"fmt"
"sort"
"strings"
"github.com/golang/protobuf/proto"
)
type robot struct {
meta *mt.Robot
specSkill int32
}
type team struct {
cs.MsgHandlerImpl
teamUuid string
nextTeamUuid string
copyIdx int32
zoneId int32
nodeId int32
mapInfo* common.MapInfoRsp
sortIdx int32
owner common.Player
state int32
startTime int64
stateNotifyMsg *cs.SMTeamStateNotify
memberIdHash map[string]common.Player
preTeamRealPlayerHash map[string]int64
robotList []*robot
matchOk *team
matchTick int64
refreshUserStatusTimer *f5.TimerWp
}
func (this* robot) GetAccountId() string {
return "6517_2006_" + q5.ToString(this.meta.GetId())
}
func (this* robot) FillMFTeamMember(member_pb *cs.MFTeamMember) {
member_pb.AccountId = proto.String(this.GetAccountId())
member_pb.Name = proto.String(this.meta.GetName())
//member_pb.Id = proto.Int32(this.sortIdx)
member_pb.IsLeader = proto.Int32(0)
member_pb.SpecSkill = proto.Int32(this.specSkill)
{
member_pb.Hero = &cs.MFHero{}
member_pb.Hero.HeroId = proto.Int32(this.meta.GetHeroId())
member_pb.Hero.Quality = proto.Int32(0)
member_pb.Hero.CurrentTimes = proto.Int32(0)
member_pb.Hero.TotalTimes = proto.Int32(0)
member_pb.Hero.SkinId = proto.Int32(0)
}
member_pb.State = proto.Int32(0)
member_pb.Online = proto.Int32(1)
member_pb.Permission = proto.Int32(0)
member_pb.IsReady = proto.Int32(1)
}
func (this *team) init(copyIdx int32, zoneId int32, nodeId int32,
teamUuid string, owner common.Player, mapInfo* common.MapInfoRsp) {
this.sortIdx++
this.teamUuid = teamUuid
this.copyIdx = copyIdx
this.zoneId = zoneId
this.nodeId = nodeId
this.mapInfo = mapInfo
this.owner = owner
this.owner.SetPermission(1)
this.stateNotifyMsg.JoinMsg.TeamUuid = proto.String(this.teamUuid)
owner.SetTeam(this)
owner.SetSortIdx(this.sortIdx)
this.addMember(owner)
}
func (this *team) postInit() {
if this.IsCopy() {
}
}
func (this *team) GetZoneId() int32 {
return this.zoneId
}
func (this *team) GetNodeId() int32 {
return this.nodeId
}
func (this *team) GetZnKey() int64 {
return q5.MkInt64(this.GetZoneId(), this.GetNodeId())
}
func (this *team) GetTeamUuid() string {
return this.teamUuid
}
func (this *team) CanJoin(accountId string) bool {
if this.IsCopy() {
if !this.isFull() {
return true
} else if this.GetMemberByAccountId(accountId) != nil {
return true
}
} else {
return !this.isFull()
}
return false
}
func (this *team) GetMemberByAccountId(accountId string) common.Player {
hum, ok := this.memberIdHash[accountId]
if ok {
return hum
}
return nil
}
func (this *team) onPlayerOffline(hum common.Player) {
}
func (this *team) onPlayerOnline(hum common.Player) {
}
func (this *team) ReJoin(hum common.Player) {
this.checkMemberState()
}
func (this *team) Join(hum common.Player) bool {
this.sortIdx++
hum.SetTeam(this)
hum.SetSortIdx(this.sortIdx)
this.addMember(hum)
this.rearrangementSortIdx()
this.checkMemberState()
return true
}
func (this *team) IsLeader(hum common.Player) bool {
return hum == this.owner
}
func (this *team) isFull() bool {
return len(this.memberIdHash) >= 4
}
func (this *team) IsCopy() bool {
return this.copyIdx > 0
}
func (this *team) GetCopyIdx() int32 {
return this.copyIdx
}
func (this *team) Started() bool {
return this.state == constant.TEAM_STATE_STARTED
}
func (this *team) Matching() bool {
return this.state == constant.TEAM_STATE_MATCHING
}
func (this *team) IsLock() bool {
return this.Started() || this.Matching()
}
func (this *team) setMatchOk(targetM *team) {
this.matchOk = targetM
this.matchTick = q5.GetTickCount()
}
func (this *team) isMainTeam() bool {
return this.getMainTeam() == this
}
func (this *team) getMainTeam() *team {
if this.matchOk == nil {
return this
}
if this.GetTeamUuid() < this.matchOk.GetTeamUuid() {
return this
} else {
return this.matchOk
}
}
func (this *team) onMatchOk(startTime int64) {
this.doStartGame(startTime)
}
func (this *team) CanStartGame(hum common.Player) bool {
if !this.IsLock() {
if this.GetMemberNum() > 0 {
allReady := true
this.traverseMembers(
func (m common.Player) bool {
if m != this.owner && !m.IsReady() {
allReady = false
return false
}
return true
})
return allReady
}
}
return false
}
func (this *team) StartGame() {
if !this.IsLock() && this.CanStartGame(this.owner) {
if this.IsMobaMode() {
this.state = constant.TEAM_STATE_MATCHING
this.stateNotifyMsg.State = proto.Int32(this.state)
_matchMgr.addMatch(this)
this.SendStateNotify()
} else {
this.doStartGame(f5.GetApp().GetNowSeconds())
}
}
}
func (this *team) doStartGame(startTime int64) {
this.state = constant.TEAM_STATE_STARTED
this.startTime = startTime
this.stateNotifyMsg.State = proto.Int32(this.state)
this.genStartGameInfo()
this.SendStateNotify()
count := 1
f5.GetTimer().SetInterval(1000, func(e int32, args *q5.Args) {
if e == q5.TIMER_EXEC_EVENT {
this.SendStateNotify()
count++
if count > 10 {
f5.GetTimer().DeleteRunningTimer()
_teamMgr.removeTeam(this.GetTeamUuid())
}
}
})
}
func (this *team) GetMemberNum() int32 {
return int32(len(this.memberIdHash))
}
func (this *team) chooseNextLeader() {
var nextLeader common.Player
this.traverseMembers(
func (m common.Player) bool {
if nextLeader == nil {
nextLeader = m
} else if m.GetSortIdx() < nextLeader.GetSortIdx() {
nextLeader = m
}
return true
})
this.owner = nextLeader
this.owner.SetPermission(1)
}
func (this *team) Leave(hum common.Player) {
if !this.IsLock() {
if this.IsLeader(hum) {
delete(this.memberIdHash, hum.GetAccountId())
if this.GetMemberNum() > 0 {
this.chooseNextLeader()
}
} else {
delete(this.memberIdHash, hum.GetAccountId())
}
if this.GetMemberNum() < 0 {
this.Disband()
}
this.checkMemberState()
this.SendUpdateNotify()
}
}
func (this *team) Disband() {
if !this.IsLock() {
if this.GetMemberNum() < 0 {
} else {
notifyMsg := &cs.SMTeamDisbandNotify{}
this.broadcastMsg(notifyMsg)
}
_teamMgr.removeTeam(this.GetTeamUuid())
this.checkMemberState()
}
}
func (this *team) KickOut(hum common.Player, targetId string) {
if !this.IsLock() {
if this.IsLeader(hum) {
target := this.GetMemberByAccountId(targetId)
if target != nil && target != hum {
notifyMsg := &cs.SMTeamKickoutNotify{}
notifyMsg.AccountId = proto.String(target.GetAccountId())
target.SendMsg(notifyMsg)
delete(this.memberIdHash, target.GetAccountId())
}
}
}
}
func (this *team) HandoverLeader(hum common.Player, targetId string) {
if !this.IsLock() {
if this.IsLeader(hum) {
target := this.GetMemberByAccountId(targetId)
if target != nil && target != hum {
this.owner = target
this.owner.SetPermission(1)
}
}
}
}
func (this *team) CancelMatch() {
if this.Matching() {
_matchMgr.cancelMatch(this)
this.state = constant.TEAM_STATE_INIT
this.stateNotifyMsg.State = proto.Int32(this.state)
this.SendStateNotify()
}
}
func (this *team) SetMapInfo(mapInfo *common.MapInfoRsp) {
if !this.IsLock() {
this.mapInfo = mapInfo
}
}
func (this* team) IsMobaMode() bool {
return this.mapInfo.IsMoba != 0
}
func (this *team) rearrangementSortIdx() {
members := []common.Player{}
q5.NewSlice(&members, 0, 4)
this.traverseMembers(
func (m common.Player) bool {
q5.AppendSlice(&members, m)
return true
})
sort.Slice(members, func(i, j int) bool {
return members[i].GetSortIdx() < members[j].GetSortIdx()
})
idx := int32(0)
for _, m := range members {
idx++
m.SetSortIdx(idx)
}
}
func (this *team) genStartGameInfo() {
startInfo := struct {
ZoneId int32 `json:"zone_id"`
NodeId int32 `json:"node_id"`
ModeId int32 `json:"mode_id"`
MapId int32 `json:"map_id"`
RoomUuid string `json:"room_uuid"`
StartTime int32 `json:"start_time"`
TeamList []struct {
TeamUuid string `json:"team_uuid"`
Members []struct {
AccountId string `json:"account_id"`
SpecSkill int32 `json:"spec_skill"`
HeroUniId string `json:"hero_uniid"`
IsAndroid int32 `json:"is_android"`
RobotId int32 `json:"robot_id"`
} `json:"members"`
} `json:"team_list"`
ObList []struct {
AccountId string `json:"account_id"`
} `json:"ob_list"`
} {
ZoneId: this.GetZoneId(),
NodeId: this.GetNodeId(),
ModeId: q5.ToInt32(this.getModeId()),
MapId: this.mapInfo.MapId,
RoomUuid: q5.ToString(this.getMainTeam().GetTeamUuid()),
StartTime: int32(this.startTime),
}
this.stateNotifyMsg.JoinMsg.TeamUuid = proto.String(this.getMainTeam().GetTeamUuid())
q5.NewSlice(&this.stateNotifyMsg.TeamList, 0, 10)
{
q5.NewSlice(&startInfo.TeamList, 0, 10)
teamList := []*team{}
q5.NewSlice(&teamList, 0, 10)
if this.isMainTeam() {
{
ele := q5.NewSliceElement(&teamList)
*ele = this
}
{
if this.matchOk != nil {
ele := q5.NewSliceElement(&teamList)
*ele = this.matchOk
}
}
} else {
{
if this.matchOk != nil {
ele := q5.NewSliceElement(&teamList)
*ele = this.matchOk
}
}
{
ele := q5.NewSliceElement(&teamList)
*ele = this
}
}
for _, t := range teamList {
{
ele := q5.NewSliceElement(&startInfo.TeamList)
ele.TeamUuid = t.GetTeamUuid()
for _, m := range t.memberIdHash {
ele2 := q5.NewSliceElement(&ele.Members)
ele2.AccountId = m.GetAccountId()
ele2.SpecSkill = m.GetSpecSkill()
ele2.HeroUniId = m.GetHeroUniid()
}
if this.IsMobaMode() {
robotIdx := 0
for i := len(ele.Members); i < 4; i++ {
ele2 := q5.NewSliceElement(&ele.Members)
robot := t.robotList[robotIdx]
robotIdx++
ele2.AccountId = robot.GetAccountId()
ele2.SpecSkill = robot.specSkill
ele2.HeroUniId = ""
ele2.IsAndroid = 1
ele2.RobotId = robot.meta.GetId()
}
if len(teamList) < 2 {
ele := q5.NewSliceElement(&startInfo.TeamList)
ele.TeamUuid = t.GetTeamUuid() + "@"
for i := 0; i < 4; i++ {
ele2 := q5.NewSliceElement(&ele.Members)
robot := t.robotList[robotIdx]
robotIdx++
ele2.AccountId = robot.GetAccountId()
ele2.SpecSkill = robot.specSkill
ele2.HeroUniId = ""
ele2.IsAndroid = 1
ele2.RobotId = robot.meta.GetId()
}
}
}
}
{
ele := q5.NewSliceElement(&this.stateNotifyMsg.TeamList)
*ele = &cs.MFTeam{}
(*ele).TeamUuid = proto.String(t.GetTeamUuid())
for _, m := range t.memberIdHash {
m_pb := q5.NewSliceElement(&(*ele).Members)
*m_pb = &cs.MFTeamMember{}
m.FillMFTeamMember(*m_pb)
}
if this.IsMobaMode() {
robotIdx := 0
for i := len((*ele).Members); i < 4; i++ {
robot := t.robotList[robotIdx]
robotIdx++
m_pb := q5.NewSliceElement(&(*ele).Members)
*m_pb = &cs.MFTeamMember{}
robot.FillMFTeamMember(*m_pb)
}
if len(teamList) < 2 {
ele := q5.NewSliceElement(&this.stateNotifyMsg.TeamList)
*ele = &cs.MFTeam{}
(*ele).TeamUuid = proto.String(t.GetTeamUuid())
for i := 0; i < 4; i++ {
robot := t.robotList[robotIdx]
robotIdx++
m_pb := q5.NewSliceElement(&(*ele).Members)
*m_pb = &cs.MFTeamMember{}
robot.FillMFTeamMember(*m_pb)
}
}
}
}
}
}
sign := q5.Md5Str(q5.EncodeJson(&startInfo) + "520d8eAbB(8cf1^#$^&!@d833a42c820432PDAFE^^)")
payload := sign + ":" + "normal_room|" + q5.EncodeJson(&startInfo)
this.stateNotifyMsg.JoinMsg.Payload = proto.String(payload)
this.genNextCopyTeam()
this.stateNotifyMsg.NextTeamUuid = proto.String(this.nextTeamUuid)
}
func (this *team) genNextCopyTeam() {
nextCopyIdx := this.copyIdx + 1
oldId := q5.ToString(this.nodeId) + "_" +
q5.ToString(this.zoneId) + "_" +
q5.ToString(this.copyIdx) + "_";
newId := q5.ToString(this.nodeId) + "_" +
q5.ToString(this.zoneId) + "_" +
q5.ToString(nextCopyIdx) + "_";
this.nextTeamUuid = strings.Replace(this.GetTeamUuid(), oldId, newId, 1)
if this.nextTeamUuid == this.GetTeamUuid() {
panic("genNextCopyTeam error1")
return
}
if _teamMgr.GetTeamByUuid(this.nextTeamUuid) != nil {
panic("genNextCopyTeam error2")
return
}
nextMapInfo := &common.MapInfoRsp{}
*nextMapInfo = *this.mapInfo
nextTeam := newTeam()
nextTeam.init(nextCopyIdx, this.zoneId, this.nodeId,
this.nextTeamUuid, this.owner.GenNextCopy(), nextMapInfo)
this.traverseMembers(
func (m common.Player) bool {
this.preTeamRealPlayerHash[m.GetAccountId()] = q5.GetTickCount()
if m != this.owner {
nextTeam.Join(m.GenNextCopy())
}
return true
})
_teamMgr.addTeam(nextTeam)
nextTeam.postInit()
}
func (this *team) broadcastMsg(msg proto.Message) {
this.traverseMembers(
func (m common.Player) bool {
m.SendMsg(msg)
return true
})
}
func (this *team) SendUpdateNotify() {
notifyMsg := &cs.SMTeamUpdateNotify{}
notifyMsg.TeamInfo = &cs.MFTeam{}
notifyMsg.TeamInfo.TeamUuid = proto.String(this.teamUuid)
notifyMsg.TeamInfo.ModeId = proto.Int32(this.getModeId())
notifyMsg.TeamInfo.MapId = proto.Int32(this.mapInfo.MapId)
q5.NewSlice(&notifyMsg.TeamInfo.Members, 0, 1)
this.traverseMembers(
func (m common.Player) bool {
m_pb := &cs.MFTeamMember{}
q5.AppendSlice(&notifyMsg.TeamInfo.Members, m_pb)
m.FillMFTeamMember(m_pb)
return true
})
this.broadcastMsg(notifyMsg)
}
func (this *team) SendStateNotify() {
this.broadcastMsg(this.stateNotifyMsg)
}
func (this *team) canMatch(targetT *team) bool {
if this == targetT {
return false
}
if this.getModeId() != targetT.getModeId() {
return false
}
if this.mapInfo.MapId != targetT.mapInfo.MapId {
return false
}
if this.GetMemberNum() <= 0 || targetT.GetMemberNum() <= 0 {
return false
}
if !this.HasOnlinePlayer() {
return false
}
if !targetT.HasOnlinePlayer() {
return false
}
hasSameUser := false
this.traverseMembers(
func (m common.Player) bool {
if targetT.GetMemberByAccountId(m.GetAccountId()) != nil {
hasSameUser = true
return false
}
return true
})
if hasSameUser {
return false
}
return true
}
func (this *team) getModeId() int32 {
var modeId int32
q5.DuckToSimple(this.mapInfo.ModeId, &modeId)
return modeId
}
func (this *team) addMember(hum common.Player) {
if this.GetMemberByAccountId(hum.GetAccountId()) != nil {
panic("member already exists")
}
this.memberIdHash[hum.GetAccountId()] = hum
}
func (this *team) traverseMembers(cb func(common.Player) bool) {
for _, m := range this.memberIdHash {
if !cb(m) {
break
}
}
}
func (this *team) checkMemberState() {
if !this.IsCopy() {
return
}
if this.refreshUserStatusTimer != nil && !this.refreshUserStatusTimer.Expired() {
return
}
if this.GetMemberNum() > 1 && this.HasOnlinePlayer() {
sending := false
this.refreshUserStatusTimer = f5.GetTimer().SetIntervalWp(
1000,
func (e int32, args *q5.Args) {
if e == q5.TIMER_EXEC_EVENT {
if this.GetMemberNum() > 1 && this.HasOnlinePlayer() {
if !sending {
sending = true
params := map[string]string{
"c": "User",
"a": "queryStatus",
"accountIds" : this.genAccountIdParam(),
}
url := fmt.Sprintf("%s/webapp/index.php",
mt.Table.Config.GetById(0).GetFriendapiUrl())
rspObj := new(common.UserQueryStatusRsp)
f5.GetHttpCliMgr().SendJsStyleJsonRspRequest(
url,
params,
rspObj,
func(rsp f5.HttpCliResponse) {
sending = false
if rsp.GetErr() == nil && rsp.JsonParseOk() {
dirty := false
for _, u := range rspObj.Users {
m := this.GetMemberByAccountId(u.AccountId)
if m != nil {
if m.IsBattling() != (u.Battling != 0) {
dirty = true
}
m.SetBattling(u.Battling != 0)
}
}
if dirty {
this.SendUpdateNotify()
}
}
})
}
} else {
f5.GetTimer().DeleteRunningTimer()
this.refreshUserStatusTimer = nil
}
}
})
}
}
func (this *team) genAccountIdParam() string {
param := ""
this.traverseMembers(
func (m common.Player) bool {
param = param + m.GetAccountId() + ","
return true
})
return param
}
func (this *team) HasOnlinePlayer() bool {
has := false
this.traverseMembers(
func (m common.Player) bool {
if m.IsOnline() {
has = true
return false
}
return true
})
return has
}
func (this *team) NeedMatchRealPlayer() bool {
if mt.Table.Config.Get().GetMatchRealPlayer() == 0 {
return false
}
return q5.ToInt32(this.getModeId()) == 2
}
func newTeam() *team {
t := new(team)
t.state = constant.TEAM_STATE_INIT
t.stateNotifyMsg = &cs.SMTeamStateNotify{}
t.stateNotifyMsg.JoinMsg = &cs.MFJoinMsg{}
t.memberIdHash = map[string]common.Player{}
t.preTeamRealPlayerHash = make(map[string]int64)
t.robotList = []*robot{}
{
cb := func (meta *mt.Robot) bool {
for _, ele := range(t.robotList) {
if meta == ele.meta {
return false
}
}
return true
}
for i := 0; i < 8; i++ {
robotMeta := mt.Table.Robot.RandElementExclude(cb)
if robotMeta != nil {
robot := new(robot)
robot.meta = robotMeta
robot.specSkill = 0
q5.AppendSlice(&t.robotList, robot)
}
}
}
return t
}