diff --git a/common/mq/nats.go b/common/mq/nats.go index c59e5561..d785938e 100644 --- a/common/mq/nats.go +++ b/common/mq/nats.go @@ -33,7 +33,6 @@ type MessageQueue struct { cmdProtoMap *cmd.CmdProtoMap serverType string appId string - gateTcpMqChan chan []byte gateTcpMqEventChan chan *GateTcpMqEvent gateTcpMqDeadEventChan chan string rpcClient *rpc.Client @@ -63,7 +62,6 @@ func NewMessageQueue(serverType string, appId string, rpcClient *rpc.Client) (r r.cmdProtoMap = cmd.NewCmdProtoMap() r.serverType = serverType r.appId = appId - r.gateTcpMqChan = make(chan []byte, 1000) r.gateTcpMqEventChan = make(chan *GateTcpMqEvent, 1000) r.gateTcpMqDeadEventChan = make(chan string, 1000) r.rpcClient = rpcClient @@ -72,7 +70,7 @@ func NewMessageQueue(serverType string, appId string, rpcClient *rpc.Client) (r } else if serverType == api.GS || serverType == api.ANTICHEAT || serverType == api.PATHFINDING { go r.runGateTcpMqClient() } - go r.recvHandler() + go r.natsMsgRecvHandler() go r.sendHandler() return r } @@ -92,52 +90,82 @@ func (m *MessageQueue) GetNetMsg() chan *NetMsg { return m.netMsgOutput } -func (m *MessageQueue) recvHandler() { +func (m *MessageQueue) natsMsgRecvHandler() { for { - var rawData []byte = nil - select { - case natsMsg := <-m.natsMsgChan: - rawData = natsMsg.Data - case gateTcpMqMsg := <-m.gateTcpMqChan: - rawData = gateTcpMqMsg - } - // msgpack NetMsg - netMsg := new(NetMsg) - err := msgpack.Unmarshal(rawData, netMsg) - if err != nil { - logger.Error("parse bin to net msg error: %v", err) + natsMsg := <-m.natsMsgChan + rawData := natsMsg.Data + netMsg := m.parseNetMsg(rawData) + if netMsg == nil { continue } // 忽略自己发出的广播消息 if netMsg.OriginServerType == m.serverType && netMsg.OriginServerAppId == m.appId { continue } - switch netMsg.MsgType { - case MsgTypeGame: - gameMsg := netMsg.GameMsg - if gameMsg == nil { - logger.Error("recv game msg is nil") - continue - } - if netMsg.EventId == NormalMsg { - // protobuf PayloadMessage - payloadMessage := m.cmdProtoMap.GetProtoObjCacheByCmdId(gameMsg.CmdId) - if payloadMessage == nil { - logger.Error("get protobuf obj by cmd id error: %v", err) - continue - } - err = pb.Unmarshal(gameMsg.PayloadMessageData, payloadMessage) - if err != nil { - logger.Error("parse bin to payload msg error: %v", err) - continue - } - gameMsg.PayloadMessage = payloadMessage - } - } m.netMsgOutput <- netMsg } } +func (m *MessageQueue) buildNetMsg(netMsg *NetMsg) []byte { + switch netMsg.MsgType { + case MsgTypeGame: + gameMsg := netMsg.GameMsg + if gameMsg == nil { + logger.Error("send game msg is nil") + return nil + } + if gameMsg.PayloadMessageData == nil { + // protobuf PayloadMessage + payloadMessageData, err := pb.Marshal(gameMsg.PayloadMessage) + if err != nil { + logger.Error("parse payload msg to bin error: %v", err) + return nil + } + gameMsg.PayloadMessageData = payloadMessageData + } + } + // msgpack NetMsg + rawData, err := msgpack.Marshal(netMsg) + if err != nil { + logger.Error("parse net msg to bin error: %v", err) + return nil + } + return rawData +} + +func (m *MessageQueue) parseNetMsg(rawData []byte) *NetMsg { + // msgpack NetMsg + netMsg := new(NetMsg) + err := msgpack.Unmarshal(rawData, netMsg) + if err != nil { + logger.Error("parse bin to net msg error: %v", err) + return nil + } + switch netMsg.MsgType { + case MsgTypeGame: + gameMsg := netMsg.GameMsg + if gameMsg == nil { + logger.Error("recv game msg is nil") + return nil + } + if netMsg.EventId == NormalMsg { + // protobuf PayloadMessage + payloadMessage := m.cmdProtoMap.GetProtoObjCacheByCmdId(gameMsg.CmdId) + if payloadMessage == nil { + logger.Error("get protobuf obj by cmd id error: %v", err) + return nil + } + err = pb.Unmarshal(gameMsg.PayloadMessageData, payloadMessage) + if err != nil { + logger.Error("parse bin to payload msg error: %v", err) + return nil + } + gameMsg.PayloadMessage = payloadMessage + } + } + return netMsg +} + func (m *MessageQueue) sendHandler() { // 网关tcp连接消息收发快速通道 key1:服务器类型 key2:服务器appid value:连接实例 gateTcpMqInstMap := map[string]map[string]*GateTcpMqInst{ @@ -149,34 +177,15 @@ func (m *MessageQueue) sendHandler() { for { select { case netMsg := <-m.netMsgInput: - switch netMsg.MsgType { - case MsgTypeGame: - gameMsg := netMsg.GameMsg - if gameMsg == nil { - logger.Error("send game msg is nil") - continue - } - if gameMsg.PayloadMessageData == nil { - // protobuf PayloadMessage - payloadMessageData, err := pb.Marshal(gameMsg.PayloadMessage) - if err != nil { - logger.Error("parse payload msg to bin error: %v", err) - continue - } - gameMsg.PayloadMessageData = payloadMessageData - } - } - // msgpack NetMsg - netMsgData, err := msgpack.Marshal(netMsg) - if err != nil { - logger.Error("parse net msg to bin error: %v", err) + rawData := m.buildNetMsg(netMsg) + if rawData == nil { continue } fallbackNatsMqSend := func() { // 找不到tcp快速通道就fallback回nats natsMsg := nats.NewMsg(netMsg.Topic) - natsMsg.Data = netMsgData - err = m.natsConn.PublishMsg(natsMsg) + natsMsg.Data = rawData + err := m.natsConn.PublishMsg(natsMsg) if err != nil { logger.Error("nats publish msg error: %v", err) return @@ -199,25 +208,35 @@ func (m *MessageQueue) sendHandler() { fallbackNatsMqSend() continue } + gateTcpMqSend := func(data []byte) bool { + err := inst.conn.SetWriteDeadline(time.Now().Add(time.Second)) + if err != nil { + fallbackNatsMqSend() + return false + } + _, err = inst.conn.Write(data) + if err != nil { + // 发送失败关闭连接fallback回nats + logger.Error("gate tcp mq send error: %v", err) + _ = inst.conn.Close() + m.gateTcpMqEventChan <- &GateTcpMqEvent{ + event: EventDisconnect, + inst: inst, + } + fallbackNatsMqSend() + return false + } + return true + } // 前4个字节为消息的载荷部分长度 - netMsgDataTcp := make([]byte, 4+len(netMsgData)) - binary.BigEndian.PutUint32(netMsgDataTcp, uint32(len(netMsgData))) - copy(netMsgDataTcp[4:], netMsgData) - err = inst.conn.SetWriteDeadline(time.Now().Add(time.Second)) - if err != nil { - fallbackNatsMqSend() + headLenData := make([]byte, 4) + binary.BigEndian.PutUint32(headLenData, uint32(len(rawData))) + ok := gateTcpMqSend(headLenData) + if !ok { continue } - _, err = inst.conn.Write(netMsgDataTcp) - if err != nil { - // 发送失败关闭连接fallback回nats - logger.Error("gate tcp mq send error: %v", err) - _ = inst.conn.Close() - m.gateTcpMqEventChan <- &GateTcpMqEvent{ - event: EventDisconnect, - inst: inst, - } - fallbackNatsMqSend() + ok = gateTcpMqSend(rawData) + if !ok { continue } case gateTcpMqEvent := <-m.gateTcpMqEventChan: @@ -381,8 +400,8 @@ func (m *MessageQueue) gateTcpMqConn(gateServerConnAddrMap map[string]bool) { func (m *MessageQueue) gateTcpMqRecvHandle(inst *GateTcpMqInst) { dataBuf := make([]byte, 0, 1500) + recvBuf := make([]byte, 1024*1024) for { - recvBuf := make([]byte, 1500) recvLen, err := inst.conn.Read(recvBuf) if err != nil { logger.Error("gate tcp mq recv error: %v", err) @@ -423,7 +442,11 @@ func (m *MessageQueue) gateTcpMqRecvHandleLoop(data []byte, dataBuf *[]byte) { *dataBuf = append(*dataBuf, data...) return } - m.gateTcpMqChan <- data[4 : 4+msgPayloadLen] + rawData := data[4 : 4+msgPayloadLen] + netMsg := m.parseNetMsg(rawData) + if netMsg != nil { + m.netMsgOutput <- netMsg + } if haveMorePacket { m.gateTcpMqRecvHandleLoop(data[packetLen:], dataBuf) } diff --git a/gate/kcp/session.go b/gate/kcp/session.go index 3c56cf17..a567393f 100644 --- a/gate/kcp/session.go +++ b/gate/kcp/session.go @@ -343,8 +343,6 @@ func (s *UDPSession) Close() error { }) if once { - atomic.AddUint64(&DefaultSnmp.CurrEstab, ^uint64(0)) - // try best to send all queued messages s.mu.Lock() s.kcp.flush(false) diff --git a/gate/net/session.go b/gate/net/session.go index cd738fe2..8f52cc31 100644 --- a/gate/net/session.go +++ b/gate/net/session.go @@ -41,10 +41,10 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session) if protoMsg.HeadMessage == nil { logger.Error("recv null head msg: %v", protoMsg) } - // gate本地处理的请求 + // 网关服务器本地处理的请求 switch protoMsg.CmdId { case cmd.GetPlayerTokenReq: - // 获取玩家token请求 + // GATE登录包 if connState != ConnEst { return } @@ -55,14 +55,15 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session) return } // 返回数据到客户端 - rsp := new(ProtoMsg) - rsp.ConvId = protoMsg.ConvId - rsp.CmdId = cmd.GetPlayerTokenRsp - rsp.HeadMessage = k.getHeadMsg(protoMsg.HeadMessage.ClientSequenceId) - rsp.PayloadMessage = getPlayerTokenRsp + rsp := &ProtoMsg{ + ConvId: protoMsg.ConvId, + CmdId: cmd.GetPlayerTokenRsp, + HeadMessage: k.getHeadMsg(protoMsg.HeadMessage.ClientSequenceId), + PayloadMessage: getPlayerTokenRsp, + } session.kcpRawSendChan <- rsp case cmd.PlayerForceExitReq: - // 玩家退出游戏请求 + // 退出游戏 if connState != ConnActive { return } @@ -72,17 +73,18 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session) EventMessage: uint32(kcp.EnetClientClose), } case cmd.PingReq: - // ping请求 + // ping pingReq := protoMsg.PayloadMessage.(*proto.PingReq) logger.Debug("user ping req, data: %v", pingReq.String()) // 返回数据到客户端 pingRsp := new(proto.PingRsp) pingRsp.ClientTime = pingReq.ClientTime - rsp := new(ProtoMsg) - rsp.ConvId = protoMsg.ConvId - rsp.CmdId = cmd.PingRsp - rsp.HeadMessage = k.getHeadMsg(protoMsg.HeadMessage.ClientSequenceId) - rsp.PayloadMessage = pingRsp + rsp := &ProtoMsg{ + ConvId: protoMsg.ConvId, + CmdId: cmd.PingRsp, + HeadMessage: k.getHeadMsg(protoMsg.HeadMessage.ClientSequenceId), + PayloadMessage: pingRsp, + } session.kcpRawSendChan <- rsp logger.Debug("convId: %v, RTO: %v, SRTT: %v, RTTVar: %v", protoMsg.ConvId, session.conn.GetRTO(), session.conn.GetSRTT(), session.conn.GetSRTTVar()) @@ -91,35 +93,40 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session) } // 通知GS玩家客户端往返时延 rtt := session.conn.GetSRTT() - connCtrlMsg := new(mq.ConnCtrlMsg) - connCtrlMsg.UserId = userId - connCtrlMsg.ClientRtt = uint32(rtt) + connCtrlMsg := &mq.ConnCtrlMsg{ + UserId: userId, + ClientRtt: uint32(rtt), + ClientTime: 0, + } k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{ MsgType: mq.MsgTypeConnCtrl, EventId: mq.ClientRttNotify, ConnCtrlMsg: connCtrlMsg, }) // 通知GS玩家客户端的本地时钟 - connCtrlMsg = new(mq.ConnCtrlMsg) - connCtrlMsg.UserId = userId - connCtrlMsg.ClientTime = pingReq.ClientTime + connCtrlMsg = &mq.ConnCtrlMsg{ + UserId: userId, + ClientTime: pingReq.ClientTime, + } k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{ MsgType: mq.MsgTypeConnCtrl, EventId: mq.ClientTimeNotify, ConnCtrlMsg: connCtrlMsg, }) case cmd.PlayerLoginReq: + // GS登录包 if connState != ConnWaitLogin { return } playerLoginReq := protoMsg.PayloadMessage.(*proto.PlayerLoginReq) playerLoginReq.TargetUid = 0 playerLoginReq.TargetHomeOwnerUid = 0 - gameMsg := new(mq.GameMsg) - gameMsg.UserId = userId - gameMsg.CmdId = protoMsg.CmdId - gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId - gameMsg.PayloadMessage = playerLoginReq + gameMsg := &mq.GameMsg{ + UserId: userId, + CmdId: protoMsg.CmdId, + ClientSeq: protoMsg.HeadMessage.ClientSequenceId, + PayloadMessage: playerLoginReq, + } // 转发到GS k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{ MsgType: mq.MsgTypeGame, @@ -131,10 +138,12 @@ func (k *KcpConnectManager) recvMsgHandle(protoMsg *ProtoMsg, session *Session) logger.Error("conn not active so drop packet, cmdId: %v, userId: %v, convId: %v", protoMsg.CmdId, userId, protoMsg.ConvId) return } - gameMsg := new(mq.GameMsg) - gameMsg.UserId = userId - gameMsg.CmdId = protoMsg.CmdId - gameMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId + gameMsg := &mq.GameMsg{ + UserId: userId, + CmdId: protoMsg.CmdId, + ClientSeq: protoMsg.HeadMessage.ClientSequenceId, + PayloadMessageData: nil, + } // 在这里直接序列化成二进制数据 终结PayloadMessage的生命周期并回收进缓存池 payloadMessageData, err := pb.Marshal(protoMsg.PayloadMessage) if err != nil { @@ -207,32 +216,34 @@ func (k *KcpConnectManager) sendMsgHandle() { logger.Error("can not find convId by userId") continue } - protoMsg := new(ProtoMsg) - protoMsg.ConvId = convId - protoMsg.CmdId = gameMsg.CmdId - protoMsg.HeadMessage = k.getHeadMsg(gameMsg.ClientSeq) - protoMsg.PayloadMessage = gameMsg.PayloadMessage + protoMsg := &ProtoMsg{ + ConvId: convId, + CmdId: gameMsg.CmdId, + HeadMessage: k.getHeadMsg(gameMsg.ClientSeq), + PayloadMessage: gameMsg.PayloadMessage, + } session := convSessionMap[protoMsg.ConvId] if session == nil { logger.Error("session is nil, convId: %v", protoMsg.ConvId) - return + continue } kcpRawSendChan := session.kcpRawSendChan if kcpRawSendChan == nil { logger.Error("kcpRawSendChan is nil, convId: %v", protoMsg.ConvId) - return + continue } if len(kcpRawSendChan) == 1000 { logger.Error("kcpRawSendChan is full, convId: %v", protoMsg.ConvId) - return + continue } if protoMsg.CmdId == cmd.PlayerLoginRsp { logger.Debug("session active, convId: %v", protoMsg.ConvId) session.connState = ConnActive // 通知GS玩家各个服务器的appid - serverMsg := new(mq.ServerMsg) - serverMsg.UserId = session.userId - serverMsg.AnticheatServerAppId = session.anticheatServerAppId + serverMsg := &mq.ServerMsg{ + UserId: session.userId, + AnticheatServerAppId: session.anticheatServerAppId, + } k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{ MsgType: mq.MsgTypeServer, EventId: mq.ServerAppidBindNotify, @@ -273,13 +284,14 @@ func (k *KcpConnectManager) sendMsgHandle() { session.gsServerAppId = serverMsg.GameServerAppId session.anticheatServerAppId = "" // 网关代发登录请求到新的GS - gameMsg := new(mq.GameMsg) - gameMsg.UserId = serverMsg.UserId - gameMsg.CmdId = cmd.PlayerLoginReq - gameMsg.ClientSeq = 0 - gameMsg.PayloadMessage = &proto.PlayerLoginReq{ - TargetUid: serverMsg.JoinHostUserId, - TargetHomeOwnerUid: 0, + gameMsg := &mq.GameMsg{ + UserId: serverMsg.UserId, + CmdId: cmd.PlayerLoginReq, + ClientSeq: 0, + PayloadMessage: &proto.PlayerLoginReq{ + TargetUid: serverMsg.JoinHostUserId, + TargetHomeOwnerUid: 0, + }, } k.messageQueue.SendToGs(session.gsServerAppId, &mq.NetMsg{ MsgType: mq.MsgTypeGame, diff --git a/gs/game/game.go b/gs/game/game.go index a1f2aafc..4201df0b 100644 --- a/gs/game/game.go +++ b/gs/game/game.go @@ -369,6 +369,9 @@ func (g *Game) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, payloadMsg logger.Error("player not exist, uid: %v, stack: %v", userId, logger.Stack()) return } + if player.NetFreeze { + return + } gameMsg := new(mq.GameMsg) gameMsg.UserId = userId gameMsg.CmdId = cmdId diff --git a/gs/game/game_command_controller.go b/gs/game/game_command_controller.go index abd6e78a..d2dc45a7 100644 --- a/gs/game/game_command_controller.go +++ b/gs/game/game_command_controller.go @@ -160,13 +160,13 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) { c.SendMessage(cmd.Executor, "已将玩家 UID:%v 请求加入目标玩家 UID:%v 的世界。", player.PlayerID, targetUid) } else { // 传送玩家至目标玩家的位置 - c.gmCmd.GMTeleportPlayer(player.PlayerID, target.SceneId, 0, target.Pos.X, target.Pos.Y, target.Pos.Z) + c.gmCmd.GMTeleportPlayer(player.PlayerID, target.SceneId, target.Pos.X, target.Pos.Y, target.Pos.Z) // 发送消息给执行者 c.SendMessage(cmd.Executor, "已将玩家 UID:%v 传送至 目标玩家 UID:%v。", player.PlayerID, targetUid) } } else { // 传送玩家至指定的位置 - c.gmCmd.GMTeleportPlayer(player.PlayerID, sceneId, 0, pos.X, pos.Y, pos.Z) + c.gmCmd.GMTeleportPlayer(player.PlayerID, sceneId, pos.X, pos.Y, pos.Z) // 发送消息给执行者 c.SendMessage(cmd.Executor, "已将玩家 UID:%v 传送至 场景:%v, X:%.2f, Y:%.2f, Z:%.2f。", player.PlayerID, sceneId, pos.X, pos.Y, pos.Z) } diff --git a/gs/game/game_command_gm.go b/gs/game/game_command_gm.go index 9a8a512e..17e92db1 100644 --- a/gs/game/game_command_gm.go +++ b/gs/game/game_command_gm.go @@ -19,40 +19,20 @@ type GMCmd struct { // 玩家通用GM指令 // GMTeleportPlayer 传送玩家 -func (g *GMCmd) GMTeleportPlayer(userId, sceneId, dungeonId uint32, posX, posY, posZ float64) { +func (g *GMCmd) GMTeleportPlayer(userId, sceneId uint32, posX, posY, posZ float64) { player := USER_MANAGER.GetOnlineUser(userId) if player == nil { logger.Error("player is nil, uid: %v", userId) return } - dungeonPointId := uint32(0) - if dungeonId != 0 { - end := false - for _, pointData := range gdconf.GetScenePointMapBySceneId(int32(sceneId)) { - if end { - break - } - for _, v := range pointData.DungeonIds { - if uint32(v) == dungeonId { - dungeonPointId = uint32(pointData.Id) - end = true - break - } - } - } - if dungeonPointId == 0 { - logger.Error("dungeon pointid not found, dungeonId: %v, uid: %v", dungeonId, userId) - return - } - } GAME.TeleportPlayer( player, proto.EnterReason_ENTER_REASON_GM, sceneId, &model.Vector{X: posX, Y: posY, Z: posZ}, new(model.Vector), - dungeonId, - dungeonPointId, + 0, + 0, ) } @@ -106,6 +86,7 @@ func (g *GMCmd) GMAddUserFlycloak(userId, flycloakId uint32) { // GMAddUserAllItem 给予玩家所有物品 func (g *GMCmd) GMAddUserAllItem(userId, itemCount uint32) { + g.GMHWOptLogoutPlayer(userId) itemList := make([]*ChangeItem, 0) for itemId := range GAME.GetAllItemDataConfig() { itemList = append(itemList, &ChangeItem{ @@ -125,6 +106,7 @@ func (g *GMCmd) GMAddUserAllWeapon(userId, itemCount uint32) { // GMAddUserAllReliquary 给予玩家所有圣遗物 func (g *GMCmd) GMAddUserAllReliquary(userId, itemCount uint32) { + g.GMHWOptLogoutPlayer(userId) for itemId := range GAME.GetAllReliquaryDataConfig() { g.GMAddUserReliquary(userId, uint32(itemId), itemCount) } @@ -153,6 +135,7 @@ func (g *GMCmd) GMAddUserAllFlycloak(userId uint32) { // GMAddUserAllEvery 给予玩家所有内容 func (g *GMCmd) GMAddUserAllEvery(userId, itemCount uint32) { + g.GMHWOptLogoutPlayer(userId) // 给予玩家所有物品 g.GMAddUserAllItem(userId, itemCount) // 给予玩家所有武器 @@ -165,8 +148,18 @@ func (g *GMCmd) GMAddUserAllEvery(userId, itemCount uint32) { g.GMAddUserAllCostume(userId) // 给予玩家所有风之翼 g.GMAddUserAllFlycloak(userId) +} +// GMHWOptLogoutPlayer GM重量级操作主动下线玩家 +func (g *GMCmd) GMHWOptLogoutPlayer(userId uint32) { GAME.LogoutPlayer(userId) + player := USER_MANAGER.GetOnlineUser(userId) + if player == nil { + logger.Error("player is nil, uid: %v", userId) + return + } + // 冻结掉服务器对该玩家的下行 避免大量发包对整个系统造成压力 + player.NetFreeze = true } // GMAddQuest 添加任务 diff --git a/gs/game/game_route_manager.go b/gs/game/game_route_manager.go index 76284d95..44cbf6c2 100644 --- a/gs/game/game_route_manager.go +++ b/gs/game/game_route_manager.go @@ -47,6 +47,9 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa logger.Error("player not online, uid: %v", userId) return } + if player.NetFreeze { + return + } player.ClientSeq = clientSeq SELF = player handlerFunc(player, payloadMsg) diff --git a/gs/game/game_world_manager.go b/gs/game/game_world_manager.go index 279772e3..09ee890f 100644 --- a/gs/game/game_world_manager.go +++ b/gs/game/game_world_manager.go @@ -399,8 +399,8 @@ type WorldAvatar struct { avatarId uint32 avatarEntityId uint32 weaponEntityId uint32 - abilityList []*proto.AbilityAppliedAbility - modifierList []*proto.AbilityAppliedModifier + abilityMap map[uint32]*proto.AbilityAppliedAbility + modifierMap map[uint32]*proto.AbilityAppliedModifier } func (w *WorldAvatar) GetUid() uint32 { @@ -424,28 +424,31 @@ func (w *WorldAvatar) SetWeaponEntityId(weaponEntityId uint32) { } func (w *WorldAvatar) GetAbilityList() []*proto.AbilityAppliedAbility { - return w.abilityList + abilityList := make([]*proto.AbilityAppliedAbility, 0) + for _, ability := range w.abilityMap { + abilityList = append(abilityList, ability) + } + return abilityList } func (w *WorldAvatar) GetAbilityByInstanceId(instanceId uint32) *proto.AbilityAppliedAbility { - for _, ability := range w.abilityList { - if ability.InstancedAbilityId == instanceId { - return ability - } - } - return nil + return w.abilityMap[instanceId] } -func (w *WorldAvatar) SetAbilityList(abilityList []*proto.AbilityAppliedAbility) { - w.abilityList = abilityList +func (w *WorldAvatar) AddAbility(ability *proto.AbilityAppliedAbility) { + w.abilityMap[ability.InstancedAbilityId] = ability } func (w *WorldAvatar) GetModifierList() []*proto.AbilityAppliedModifier { - return w.modifierList + modifierList := make([]*proto.AbilityAppliedModifier, 0) + for _, modifier := range w.modifierMap { + modifierList = append(modifierList, modifier) + } + return modifierList } -func (w *WorldAvatar) SetModifierList(modifierList []*proto.AbilityAppliedModifier) { - w.modifierList = modifierList +func (w *WorldAvatar) AddModifier(modifier *proto.AbilityAppliedModifier) { + w.modifierMap[modifier.InstancedModifierId] = modifier } // GetWorldAvatarList 获取世界队伍的全部角色列表 @@ -632,8 +635,8 @@ func (w *World) SetPlayerLocalTeam(player *model.Player, avatarIdList []uint32) avatarId: avatarId, avatarEntityId: 0, weaponEntityId: 0, - abilityList: make([]*proto.AbilityAppliedAbility, 0), - modifierList: make([]*proto.AbilityAppliedModifier, 0), + abilityMap: make(map[uint32]*proto.AbilityAppliedAbility), + modifierMap: make(map[uint32]*proto.AbilityAppliedModifier), } } w.multiplayerTeam.localTeamMap[player.PlayerID] = newLocalTeam @@ -650,8 +653,8 @@ func (w *World) copyLocalTeamToWorld(start int, end int, peerId uint32) { avatarId: 0, avatarEntityId: 0, weaponEntityId: 0, - abilityList: nil, - modifierList: nil, + abilityMap: nil, + modifierMap: nil, } continue } diff --git a/gs/game/player_fight_sync.go b/gs/game/player_fight_sync.go index 72ed83ac..6d342f7d 100644 --- a/gs/game/player_fight_sync.go +++ b/gs/game/player_fight_sync.go @@ -487,9 +487,7 @@ func (g *Game) ClientAbilityChangeNotify(player *model.Player, payloadMsg pb.Mes if abilityMetaAddAbility.Ability == nil { continue } - abilityList := worldAvatar.GetAbilityList() - abilityList = append(abilityList, abilityMetaAddAbility.Ability) - worldAvatar.SetAbilityList(abilityList) + worldAvatar.AddAbility(abilityMetaAddAbility.Ability) case proto.AbilityInvokeArgument_ABILITY_META_MODIFIER_CHANGE: abilityMetaModifierChange := new(proto.AbilityMetaModifierChange) err := pb.Unmarshal(abilityInvokeEntry.AbilityData, abilityMetaModifierChange) @@ -516,9 +514,7 @@ func (g *Game) ClientAbilityChangeNotify(player *model.Player, payloadMsg pb.Mes if worldAvatar == nil { continue } - modifierList := worldAvatar.GetModifierList() - modifierList = append(modifierList, abilityAppliedModifier) - worldAvatar.SetModifierList(modifierList) + worldAvatar.AddModifier(abilityAppliedModifier) } } } @@ -738,6 +734,7 @@ func (g *Game) handleGadgetEntityBeHitLow(player *model.Player, entity *Entity, } g.ChangeGadgetState(player, entity.GetId(), constant.GADGET_STATE_GEAR_START) } else if strings.Contains(gadgetDataConfig.ServerLuaScript, "SubfieldDrop_WoodenObject_Broken") { + // 木箱破碎 g.KillEntity(player, scene, entity.GetId(), proto.PlayerDieType_PLAYER_DIE_GM) } } diff --git a/gs/model/player.go b/gs/model/player.go index c55e9d88..7e16c454 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -56,21 +56,21 @@ type Player struct { DbQuest *DbQuest // 任务 DbWorld *DbWorld // 大世界 // 在线数据 请随意 记得加忽略字段的tag - LastSaveTime uint32 `bson:"-" msgpack:"-"` // 上一次保存时间 + LastSaveTime uint32 `bson:"-" msgpack:"-"` // 上一次存档保存时间 DbState int `bson:"-" msgpack:"-"` // 数据库存档状态 WorldId uint32 `bson:"-" msgpack:"-"` // 所在的世界id GameObjectGuidCounter uint64 `bson:"-" msgpack:"-"` // 游戏对象guid计数器 LastKeepaliveTime uint32 `bson:"-" msgpack:"-"` // 上一次保持活跃时间 - ClientTime uint32 `bson:"-" msgpack:"-"` // 客户端的本地时钟 - ClientRTT uint32 `bson:"-" msgpack:"-"` // 客户端往返时延 + ClientTime uint32 `bson:"-" msgpack:"-"` // 客户端本地时钟 + ClientRTT uint32 `bson:"-" msgpack:"-"` // 客户端网络往返时延 GameObjectGuidMap map[uint64]GameObject `bson:"-" msgpack:"-"` // 游戏对象guid映射表 Online bool `bson:"-" msgpack:"-"` // 在线状态 Pause bool `bson:"-" msgpack:"-"` // 暂停状态 SceneJump bool `bson:"-" msgpack:"-"` // 是否场景切换 SceneLoadState int `bson:"-" msgpack:"-"` // 场景加载状态 CoopApplyMap map[uint32]int64 `bson:"-" msgpack:"-"` // 敲门申请的玩家uid及时间 - StaminaInfo *StaminaInfo `bson:"-" msgpack:"-"` // 耐力临时数据 - VehicleInfo *VehicleInfo `bson:"-" msgpack:"-"` // 载具临时数据 + StaminaInfo *StaminaInfo `bson:"-" msgpack:"-"` // 耐力在线数据 + VehicleInfo *VehicleInfo `bson:"-" msgpack:"-"` // 载具在线数据 ClientSeq uint32 `bson:"-" msgpack:"-"` // 客户端发包请求的序号 CombatInvokeHandler *InvokeHandler[proto.CombatInvokeEntry] `bson:"-" msgpack:"-"` // combat转发器 AbilityInvokeHandler *InvokeHandler[proto.AbilityInvokeEntry] `bson:"-" msgpack:"-"` // ability转发器 @@ -79,6 +79,7 @@ type Player struct { GCGCurGameGuid uint32 `bson:"-" msgpack:"-"` // GCG玩家所在的游戏guid GCGInfo *GCGInfo `bson:"-" msgpack:"-"` // 七圣召唤信息 XLuaDebug bool `bson:"-" msgpack:"-"` // 是否开启客户端XLUA调试 + NetFreeze bool `bson:"-" msgpack:"-"` // 客户端网络上下行冻结状态 // 特殊数据 ChatMsgMap map[uint32][]*ChatMsg `bson:"-" msgpack:"-"` // 聊天信息 数据量偏大 只从db读写 不保存到redis }