mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-23 14:32:27 +08:00
优化登录、离线、服务器重启等会话连接问题
This commit is contained in:
@@ -49,7 +49,6 @@ func Run(ctx context.Context, configFile string) error {
|
||||
defer messageQueue.Close()
|
||||
|
||||
gameManager := game.NewGameManager(db, messageQueue)
|
||||
gameManager.Start()
|
||||
defer gameManager.Stop()
|
||||
|
||||
c := make(chan os.Signal, 1)
|
||||
|
||||
@@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gate/kcp"
|
||||
"hk4e/gs/dao"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/alg"
|
||||
@@ -41,80 +42,104 @@ func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue) (r *GameManager
|
||||
WORLD_MANAGER = NewWorldManager(r.snowflake)
|
||||
TICK_MANAGER = NewTickManager()
|
||||
COMMAND_MANAGER = NewCommandManager()
|
||||
r.run()
|
||||
return r
|
||||
}
|
||||
|
||||
func (g *GameManager) Start() {
|
||||
func (g *GameManager) run() {
|
||||
ROUTE_MANAGER.InitRoute()
|
||||
USER_MANAGER.StartAutoSaveUser()
|
||||
go func() {
|
||||
intervalTime := time.Second.Nanoseconds() * 60
|
||||
lastTime := time.Now().UnixNano()
|
||||
routeCost := int64(0)
|
||||
tickCost := int64(0)
|
||||
localEventCost := int64(0)
|
||||
commandCost := int64(0)
|
||||
for {
|
||||
now := time.Now().UnixNano()
|
||||
if now-lastTime > intervalTime {
|
||||
routeCost /= 1e6
|
||||
tickCost /= 1e6
|
||||
localEventCost /= 1e6
|
||||
commandCost /= 1e6
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost detail, routeCost: %vms, tickCost: %vms, localEventCost: %vms, commandCost: %vms",
|
||||
routeCost, tickCost, localEventCost, commandCost)
|
||||
totalCost := routeCost + tickCost + localEventCost + commandCost
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost percent, routeCost: %v%%, tickCost: %v%%, localEventCost: %v%%, commandCost: %v%%",
|
||||
float32(routeCost)/float32(totalCost)*100.0,
|
||||
float32(tickCost)/float32(totalCost)*100.0,
|
||||
float32(localEventCost)/float32(totalCost)*100.0,
|
||||
float32(commandCost)/float32(totalCost)*100.0)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost detail, totalCost: %vms",
|
||||
totalCost)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost percent, totalCost: %v%%",
|
||||
float32(totalCost)/float32(intervalTime/1e6)*100.0)
|
||||
lastTime = now
|
||||
routeCost = 0
|
||||
tickCost = 0
|
||||
localEventCost = 0
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
end := time.Now().UnixNano()
|
||||
routeCost += end - start
|
||||
case <-TICK_MANAGER.ticker.C:
|
||||
// 游戏服务器定时帧
|
||||
start := time.Now().UnixNano()
|
||||
TICK_MANAGER.OnGameServerTick()
|
||||
end := time.Now().UnixNano()
|
||||
tickCost += end - start
|
||||
case localEvent := <-LOCAL_EVENT_MANAGER.localEventChan:
|
||||
// 处理本地事件
|
||||
start := time.Now().UnixNano()
|
||||
LOCAL_EVENT_MANAGER.LocalEventHandle(localEvent)
|
||||
end := time.Now().UnixNano()
|
||||
localEventCost += end - start
|
||||
case command := <-COMMAND_MANAGER.commandTextInput:
|
||||
// 处理传入的命令 (普通玩家 GM命令)
|
||||
start := time.Now().UnixNano()
|
||||
COMMAND_MANAGER.HandleCommand(command)
|
||||
end := time.Now().UnixNano()
|
||||
commandCost += end - start
|
||||
}
|
||||
go g.gameMainLoopD()
|
||||
}
|
||||
|
||||
func (g *GameManager) gameMainLoopD() {
|
||||
for times := 1; times <= 1000; times++ {
|
||||
logger.Warn("start game main loop, times: %v", times)
|
||||
g.gameMainLoop()
|
||||
logger.Warn("game main loop stop")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) gameMainLoop() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.Error("!!! GAME MAIN LOOP PANIC !!!")
|
||||
logger.Error("error: %v", err)
|
||||
logger.Error("stack: %v", logger.Stack())
|
||||
}
|
||||
}()
|
||||
intervalTime := time.Second.Nanoseconds() * 60
|
||||
lastTime := time.Now().UnixNano()
|
||||
routeCost := int64(0)
|
||||
tickCost := int64(0)
|
||||
localEventCost := int64(0)
|
||||
commandCost := int64(0)
|
||||
for {
|
||||
now := time.Now().UnixNano()
|
||||
if now-lastTime > intervalTime {
|
||||
routeCost /= 1e6
|
||||
tickCost /= 1e6
|
||||
localEventCost /= 1e6
|
||||
commandCost /= 1e6
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost detail, routeCost: %vms, tickCost: %vms, localEventCost: %vms, commandCost: %vms",
|
||||
routeCost, tickCost, localEventCost, commandCost)
|
||||
totalCost := routeCost + tickCost + localEventCost + commandCost
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost percent, routeCost: %v%%, tickCost: %v%%, localEventCost: %v%%, commandCost: %v%%",
|
||||
float32(routeCost)/float32(totalCost)*100.0,
|
||||
float32(tickCost)/float32(totalCost)*100.0,
|
||||
float32(localEventCost)/float32(totalCost)*100.0,
|
||||
float32(commandCost)/float32(totalCost)*100.0)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost detail, totalCost: %vms",
|
||||
totalCost)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost percent, totalCost: %v%%",
|
||||
float32(totalCost)/float32(intervalTime/1e6)*100.0)
|
||||
lastTime = now
|
||||
routeCost = 0
|
||||
tickCost = 0
|
||||
localEventCost = 0
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
end := time.Now().UnixNano()
|
||||
routeCost += end - start
|
||||
case <-TICK_MANAGER.ticker.C:
|
||||
// 游戏服务器定时帧
|
||||
start := time.Now().UnixNano()
|
||||
TICK_MANAGER.OnGameServerTick()
|
||||
end := time.Now().UnixNano()
|
||||
tickCost += end - start
|
||||
case localEvent := <-LOCAL_EVENT_MANAGER.localEventChan:
|
||||
// 处理本地事件
|
||||
start := time.Now().UnixNano()
|
||||
LOCAL_EVENT_MANAGER.LocalEventHandle(localEvent)
|
||||
end := time.Now().UnixNano()
|
||||
localEventCost += end - start
|
||||
case command := <-COMMAND_MANAGER.commandTextInput:
|
||||
// 处理传入的命令 (普通玩家 GM命令)
|
||||
start := time.Now().UnixNano()
|
||||
COMMAND_MANAGER.HandleCommand(command)
|
||||
end := time.Now().UnixNano()
|
||||
commandCost += end - start
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) Stop() {
|
||||
// 下线玩家
|
||||
userList := USER_MANAGER.GetAllOnlineUserList()
|
||||
for _, player := range userList {
|
||||
g.DisconnectPlayer(player.PlayerID, kcp.EnetServerShutdown)
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
// 保存玩家数据
|
||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||
EventId: RunUserCopyAndSave,
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
time.Sleep(time.Second * 5)
|
||||
// g.worldManager.worldStatic.SaveTerrain()
|
||||
}
|
||||
|
||||
@@ -197,6 +222,14 @@ func (g *GameManager) ReconnectPlayer(userId uint32) {
|
||||
g.SendMsg(cmd.ClientReconnectNotify, userId, 0, new(proto.ClientReconnectNotify))
|
||||
}
|
||||
|
||||
func (g *GameManager) DisconnectPlayer(userId uint32) {
|
||||
g.SendMsg(cmd.ServerDisconnectClientNotify, userId, 0, new(proto.ServerDisconnectClientNotify))
|
||||
func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) {
|
||||
g.messageQueue.SendToGate("1", &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeConnCtrl,
|
||||
EventId: mq.KickPlayerNotify,
|
||||
ConnCtrlMsg: &mq.ConnCtrlMsg{
|
||||
KickUserId: userId,
|
||||
KickReason: reason,
|
||||
},
|
||||
})
|
||||
// g.SendMsg(cmd.ServerDisconnectClientNotify, userId, 0, new(proto.ServerDisconnectClientNotify))
|
||||
}
|
||||
|
||||
@@ -2,6 +2,7 @@ package game
|
||||
|
||||
import (
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gate/kcp"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/protocol/cmd"
|
||||
@@ -37,8 +38,7 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userId)
|
||||
// 临时为了调试便捷搞的重连 生产环境请务必去除 不然新用户会一直重连不能进入
|
||||
// GAME_MANAGER.ReconnectPlayer(userId)
|
||||
GAME_MANAGER.DisconnectPlayer(userId, kcp.EnetNotFoundSession)
|
||||
return
|
||||
}
|
||||
player.ClientSeq = clientSeq
|
||||
@@ -119,22 +119,30 @@ func (r *RouteManager) InitRoute() {
|
||||
}
|
||||
|
||||
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
if netMsg.MsgType != mq.MsgTypeGame {
|
||||
return
|
||||
}
|
||||
gameMsg := netMsg.GameMsg
|
||||
switch netMsg.EventId {
|
||||
case mq.NormalMsg:
|
||||
r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
case mq.UserRegNotify:
|
||||
GAME_MANAGER.OnReg(gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
case mq.UserLoginNotify:
|
||||
GAME_MANAGER.OnLogin(gameMsg.UserId, gameMsg.ClientSeq)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(gameMsg.UserId)
|
||||
case mq.ClientRttNotify:
|
||||
GAME_MANAGER.ClientRttNotify(gameMsg.UserId, gameMsg.ClientRtt)
|
||||
case mq.ClientTimeNotify:
|
||||
GAME_MANAGER.ClientTimeNotify(gameMsg.UserId, gameMsg.ClientTime)
|
||||
switch netMsg.MsgType {
|
||||
case mq.MsgTypeGame:
|
||||
gameMsg := netMsg.GameMsg
|
||||
switch netMsg.EventId {
|
||||
case mq.NormalMsg:
|
||||
if gameMsg.CmdId == cmd.PlayerLoginReq {
|
||||
GAME_MANAGER.PlayerLoginReq(gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
return
|
||||
}
|
||||
if gameMsg.CmdId == cmd.SetPlayerBornDataReq {
|
||||
GAME_MANAGER.SetPlayerBornDataReq(gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
return
|
||||
}
|
||||
r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(gameMsg.UserId)
|
||||
}
|
||||
case mq.MsgTypeConnCtrl:
|
||||
connCtrlMsg := netMsg.ConnCtrlMsg
|
||||
switch netMsg.EventId {
|
||||
case mq.ClientRttNotify:
|
||||
GAME_MANAGER.ClientRttNotify(connCtrlMsg.UserId, connCtrlMsg.ClientRtt)
|
||||
case mq.ClientTimeNotify:
|
||||
GAME_MANAGER.ClientTimeNotify(connCtrlMsg.UserId, connCtrlMsg.ClientTime)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,6 +18,9 @@ func DoForward[IET model.InvokeEntryType](player *model.Player, req pb.Message,
|
||||
}
|
||||
cmdId := cmdProtoMap.GetCmdIdByProtoObj(req)
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
return
|
||||
}
|
||||
if invokeHandler.AllLen() == 0 && invokeHandler.AllExceptCurLen() == 0 && invokeHandler.HostLen() == 0 {
|
||||
ntf := cmdProtoMap.GetProtoObjByCmdId(cmdId)
|
||||
for _, fieldName := range copyFieldList {
|
||||
@@ -90,6 +93,9 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
|
||||
return
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world == nil {
|
||||
return
|
||||
}
|
||||
scene := world.GetSceneById(player.SceneId)
|
||||
for _, entry := range req.InvokeList {
|
||||
switch entry.ArgumentType {
|
||||
|
||||
@@ -14,6 +14,20 @@ import (
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
func (g *GameManager) PlayerLoginReq(userId uint32, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.Info("user login req, uid: %v", userId)
|
||||
req := payloadMsg.(*proto.PlayerLoginReq)
|
||||
logger.Debug("login data: %v", req)
|
||||
g.OnLogin(userId, clientSeq)
|
||||
}
|
||||
|
||||
func (g *GameManager) SetPlayerBornDataReq(userId uint32, clientSeq uint32, payloadMsg pb.Message) {
|
||||
logger.Info("user reg req, uid: %v", userId)
|
||||
req := payloadMsg.(*proto.SetPlayerBornDataReq)
|
||||
logger.Debug("reg data: %v", req)
|
||||
g.OnReg(userId, clientSeq, req)
|
||||
}
|
||||
|
||||
func (g *GameManager) OnLogin(userId uint32, clientSeq uint32) {
|
||||
logger.Info("user login, uid: %v", userId)
|
||||
player, asyncWait := USER_MANAGER.OnlineUser(userId, clientSeq)
|
||||
@@ -117,6 +131,17 @@ func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq
|
||||
g.SendMsg(cmd.PlayerStoreNotify, userId, clientSeq, g.PacketPlayerStoreNotify(player))
|
||||
g.SendMsg(cmd.AvatarDataNotify, userId, clientSeq, g.PacketAvatarDataNotify(player))
|
||||
g.SendMsg(cmd.OpenStateUpdateNotify, userId, clientSeq, g.PacketOpenStateUpdateNotify())
|
||||
playerLoginRsp := &proto.PlayerLoginRsp{
|
||||
IsUseAbilityHash: true,
|
||||
AbilityHashCode: -228935105,
|
||||
GameBiz: "hk4e_cn",
|
||||
IsScOpen: false,
|
||||
RegisterCps: "taptap",
|
||||
CountryCode: "CN",
|
||||
Birthday: "2000-01-01",
|
||||
TotalTickTime: 1185941.871788,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerLoginRsp, userId, clientSeq, playerLoginRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) PacketPlayerDataNotify(player *model.Player) *proto.PlayerDataNotify {
|
||||
|
||||
@@ -140,7 +140,7 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes
|
||||
|
||||
g.SendMsg(cmd.LeaveWorldNotify, player.PlayerID, player.ClientSeq, new(proto.LeaveWorldNotify))
|
||||
|
||||
// g.LoginNotify(player.PlayerID, player, 0)
|
||||
g.LoginNotify(player.PlayerID, player, 0)
|
||||
|
||||
if hostPlayer.SceneLoadState == model.SceneEnterDone {
|
||||
delete(hostWorld.waitEnterPlayerMap, player.PlayerID)
|
||||
@@ -268,7 +268,6 @@ func (g *GameManager) UserLeaveWorld(player *model.Player) bool {
|
||||
return false
|
||||
}
|
||||
}
|
||||
g.UserWorldRemovePlayer(oldWorld, player)
|
||||
g.ReconnectPlayer(player.PlayerID)
|
||||
return true
|
||||
}
|
||||
@@ -318,12 +317,13 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player)
|
||||
|
||||
world.RemovePlayer(player)
|
||||
player.WorldId = 0
|
||||
if world.multiplayer && world.GetWorldPlayerNum() > 0 {
|
||||
g.UpdateWorldPlayerInfo(world, player)
|
||||
}
|
||||
if world.owner.PlayerID == player.PlayerID {
|
||||
// 房主离开销毁世界
|
||||
WORLD_MANAGER.DestroyWorld(world.id)
|
||||
return
|
||||
}
|
||||
if world.multiplayer && world.GetWorldPlayerNum() > 0 {
|
||||
g.UpdateWorldPlayerInfo(world, player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
gdc "hk4e/gs/config"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
gdc "hk4e/gs/config"
|
||||
|
||||
"hk4e/gdconf"
|
||||
"hk4e/gs/constant"
|
||||
"hk4e/gs/model"
|
||||
@@ -529,7 +530,7 @@ func (g *GameManager) SetPlayerStamina(player *model.Player, stamina uint32) {
|
||||
// 设置玩家的耐力
|
||||
prop := constant.PlayerPropertyConst.PROP_CUR_PERSIST_STAMINA
|
||||
player.PropertiesMap[prop] = stamina
|
||||
//logger.Debug("player stamina set, stamina: %v", stamina)
|
||||
// logger.Debug("player stamina set, stamina: %v", stamina)
|
||||
|
||||
// PacketPlayerPropNotify
|
||||
g.PlayerPropNotify(player, prop)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"hk4e/protocol/cmd"
|
||||
"math"
|
||||
"time"
|
||||
|
||||
"hk4e/protocol/cmd"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/constant"
|
||||
"hk4e/gs/game/aoi"
|
||||
@@ -64,7 +65,7 @@ func (w *WorldManager) CreateWorld(owner *model.Player) *World {
|
||||
playerFirstEnterMap: make(map[uint32]int64),
|
||||
waitEnterPlayerMap: make(map[uint32]int64),
|
||||
multiplayerTeam: CreateMultiplayerTeam(),
|
||||
peerMap: make(map[uint32]*model.Player),
|
||||
peerList: make([]*model.Player, 0),
|
||||
}
|
||||
if world.IsBigWorld() {
|
||||
world.aoiManager = aoi.NewAoiManager(
|
||||
@@ -132,7 +133,7 @@ type World struct {
|
||||
playerFirstEnterMap map[uint32]int64 // 玩家第一次进入世界的时间 key:uid value:进入时间
|
||||
waitEnterPlayerMap map[uint32]int64 // 等待进入世界的列表 key:uid value:开始时间
|
||||
multiplayerTeam *MultiplayerTeam
|
||||
peerMap map[uint32]*model.Player // key:玩家编号 value:player对象
|
||||
peerList []*model.Player // 玩家编号列表
|
||||
}
|
||||
|
||||
func (w *World) GetNextWorldEntityId(entityType uint16) uint32 {
|
||||
@@ -157,17 +158,23 @@ func (w *World) GetNextWorldEntityId(entityType uint16) uint32 {
|
||||
|
||||
// GetPlayerPeerId 获取当前玩家世界内编号
|
||||
func (w *World) GetPlayerPeerId(player *model.Player) uint32 {
|
||||
for peerId, worldPlayer := range w.peerMap {
|
||||
peerId := uint32(0)
|
||||
for peerIdIndex, worldPlayer := range w.peerList {
|
||||
if worldPlayer.PlayerID == player.PlayerID {
|
||||
return peerId
|
||||
peerId = uint32(peerIdIndex) + 1
|
||||
}
|
||||
}
|
||||
return 0
|
||||
logger.Debug("get player peer id is: %v, uid: %v", peerId, player.PlayerID)
|
||||
return peerId
|
||||
}
|
||||
|
||||
// GetNextPeerId 获取下一个世界内玩家编号
|
||||
func (w *World) GetNextPeerId() uint32 {
|
||||
return uint32(len(w.playerMap) + 1)
|
||||
// GetPlayerByPeerId 通过世界内编号获取玩家
|
||||
func (w *World) GetPlayerByPeerId(peerId uint32) *model.Player {
|
||||
peerIdIndex := int(peerId) - 1
|
||||
if peerIdIndex >= len(w.peerList) {
|
||||
return nil
|
||||
}
|
||||
return w.peerList[peerIdIndex]
|
||||
}
|
||||
|
||||
// GetWorldPlayerNum 获取世界中玩家的数量
|
||||
@@ -176,7 +183,7 @@ func (w *World) GetWorldPlayerNum() int {
|
||||
}
|
||||
|
||||
func (w *World) AddPlayer(player *model.Player, sceneId uint32) {
|
||||
w.peerMap[w.GetNextPeerId()] = player
|
||||
w.peerList = append(w.peerList, player)
|
||||
w.playerMap[player.PlayerID] = player
|
||||
// 将玩家自身当前的队伍角色信息复制到世界的玩家本地队伍
|
||||
team := player.TeamConfig.GetActiveTeam()
|
||||
@@ -203,7 +210,8 @@ func (w *World) AddPlayer(player *model.Player, sceneId uint32) {
|
||||
}
|
||||
|
||||
func (w *World) RemovePlayer(player *model.Player) {
|
||||
delete(w.peerMap, w.GetPlayerPeerId(player))
|
||||
peerId := w.GetPlayerPeerId(player)
|
||||
w.peerList = append(w.peerList[:peerId-1], w.peerList[peerId:]...)
|
||||
scene := w.sceneMap[player.SceneId]
|
||||
scene.RemovePlayer(player)
|
||||
delete(w.playerMap, player.PlayerID)
|
||||
@@ -416,7 +424,7 @@ func (w *World) SetPlayerLocalTeam(player *model.Player, avatarIdList []uint32)
|
||||
}
|
||||
|
||||
func (w *World) copyLocalTeamToWorld(start int, end int, peerId uint32) {
|
||||
player := w.peerMap[peerId]
|
||||
player := w.GetPlayerByPeerId(peerId)
|
||||
localTeam := w.GetPlayerLocalTeam(player)
|
||||
localTeamIndex := 0
|
||||
for index := start; index <= end; index++ {
|
||||
@@ -438,6 +446,10 @@ func (w *World) copyLocalTeamToWorld(start int, end int, peerId uint32) {
|
||||
|
||||
// UpdateMultiplayerTeam 整合所有玩家的本地队伍计算出世界队伍
|
||||
func (w *World) UpdateMultiplayerTeam() {
|
||||
_, exist := w.playerMap[w.owner.PlayerID]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
w.multiplayerTeam.worldTeam = make([]*WorldAvatar, 4)
|
||||
switch w.GetWorldPlayerNum() {
|
||||
case 1:
|
||||
|
||||
Reference in New Issue
Block a user