package game import ( "hk4e/gs/model" "hk4e/pkg/logger" "hk4e/protocol/cmd" "hk4e/protocol/proto" pb "google.golang.org/protobuf/proto" ) func (g *GameManager) UnionCmdNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user send union cmd, uid: %v", player.PlayerID) req := payloadMsg.(*proto.UnionCmdNotify) _ = req world := g.worldManager.GetWorldByID(player.WorldId) if world == nil { return } scene := world.GetSceneById(player.SceneId) // 只给附近aoi区域的玩家广播消息 surrPlayerList := make([]*model.Player, 0) entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) for _, entityId := range entityIdList { entity := scene.GetEntity(entityId) if entity == nil { continue } if entity.avatarEntity != nil { otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) surrPlayerList = append(surrPlayerList, otherPlayer) } } // CombatInvocationsNotify转发 // PacketCombatInvocationsNotify if player.CombatInvokeHandler.AllLen() > 0 { combatInvocationsNotify := new(proto.CombatInvocationsNotify) combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardAll for _, v := range surrPlayerList { g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, player.ClientSeq, combatInvocationsNotify) } } if player.CombatInvokeHandler.AllExceptCurLen() > 0 { combatInvocationsNotify := new(proto.CombatInvocationsNotify) combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardAllExceptCur for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } g.SendMsg(cmd.CombatInvocationsNotify, v.PlayerID, player.ClientSeq, combatInvocationsNotify) } } if player.CombatInvokeHandler.HostLen() > 0 { combatInvocationsNotify := new(proto.CombatInvocationsNotify) combatInvocationsNotify.InvokeList = player.CombatInvokeHandler.EntryListForwardHost g.SendMsg(cmd.CombatInvocationsNotify, world.owner.PlayerID, player.ClientSeq, combatInvocationsNotify) } // AbilityInvocationsNotify转发 // PacketAbilityInvocationsNotify if player.AbilityInvokeHandler.AllLen() > 0 { abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAll for _, v := range surrPlayerList { g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, player.ClientSeq, abilityInvocationsNotify) } } if player.AbilityInvokeHandler.AllExceptCurLen() > 0 { abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardAllExceptCur for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } g.SendMsg(cmd.AbilityInvocationsNotify, v.PlayerID, player.ClientSeq, abilityInvocationsNotify) } } if player.AbilityInvokeHandler.HostLen() > 0 { abilityInvocationsNotify := new(proto.AbilityInvocationsNotify) abilityInvocationsNotify.Invokes = player.AbilityInvokeHandler.EntryListForwardHost g.SendMsg(cmd.AbilityInvocationsNotify, world.owner.PlayerID, player.ClientSeq, abilityInvocationsNotify) } player.CombatInvokeHandler.Clear() player.AbilityInvokeHandler.Clear() } func (g *GameManager) MassiveEntityElementOpBatchNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user meeo sync, uid: %v", player.PlayerID) req := payloadMsg.(*proto.MassiveEntityElementOpBatchNotify) ntf := req world := g.worldManager.GetWorldByID(player.WorldId) if world == nil { return } scene := world.GetSceneById(player.SceneId) ntf.OpIdx = scene.meeoIndex scene.meeoIndex++ // 只给附近aoi区域的玩家广播消息 surrPlayerList := make([]*model.Player, 0) entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) for _, entityId := range entityIdList { entity := scene.GetEntity(entityId) if entity == nil { continue } if entity.avatarEntity != nil { otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) surrPlayerList = append(surrPlayerList, otherPlayer) } } for _, v := range surrPlayerList { g.SendMsg(cmd.MassiveEntityElementOpBatchNotify, v.PlayerID, player.ClientSeq, ntf) } } func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user combat invocations, uid: %v", player.PlayerID) req := payloadMsg.(*proto.CombatInvocationsNotify) world := g.worldManager.GetWorldByID(player.WorldId) if world == nil { return } scene := world.GetSceneById(player.SceneId) for _, entry := range req.InvokeList { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) switch entry.ArgumentType { //case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: // scene.AddAttack(&Attack{ // combatInvokeEntry: entry, // uid: player.PlayerID, // }) case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE: if player.SceneLoadState != model.SceneEnterDone { continue } entityMoveInfo := new(proto.EntityMoveInfo) err := pb.Unmarshal(entry.CombatData, entityMoveInfo) if err != nil { logger.LOG.Error("parse combat invocations entity move info error: %v", err) continue } motionInfo := entityMoveInfo.MotionInfo if motionInfo.Pos == nil || motionInfo.Rot == nil { continue } activeAvatarId := player.TeamConfig.GetActiveAvatarId() playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) playerActiveAvatarEntityId := playerTeamEntity.avatarEntityMap[activeAvatarId] if entityMoveInfo.EntityId == playerActiveAvatarEntityId { // 玩家在移动 ok := world.aoiManager.IsValidAoiPos(motionInfo.Pos.X, motionInfo.Pos.Y, motionInfo.Pos.Z) if !ok { continue } // aoi oldGid := world.aoiManager.GetGidByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) newGid := world.aoiManager.GetGidByPos(motionInfo.Pos.X, motionInfo.Pos.Y, motionInfo.Pos.Z) if oldGid != newGid { // 跨越了格子 oldGridList := world.aoiManager.GetSurrGridListByGid(oldGid) oldEntityIdMap := make(map[uint32]bool) for _, grid := range oldGridList { tmp := grid.GetEntityIdList() for _, v := range tmp { oldEntityIdMap[v] = true } } newGridList := world.aoiManager.GetSurrGridListByGid(newGid) newEntityIdMap := make(map[uint32]bool) for _, grid := range newGridList { tmp := grid.GetEntityIdList() for _, v := range tmp { newEntityIdMap[v] = true } } delEntityIdList := make([]uint32, 0) delUidList := make([]uint32, 0) for oldEntityId := range oldEntityIdMap { _, exist := newEntityIdMap[oldEntityId] if exist { continue } delEntityIdList = append(delEntityIdList, oldEntityId) entity := scene.GetEntity(oldEntityId) if entity == nil { continue } if entity.avatarEntity != nil { delUidList = append(delUidList, entity.avatarEntity.uid) } } addEntityIdList := make([]uint32, 0) addUidList := make([]uint32, 0) for newEntityId := range newEntityIdMap { _, exist := oldEntityIdMap[newEntityId] if exist { continue } addEntityIdList = append(addEntityIdList, newEntityId) entity := scene.GetEntity(newEntityId) if entity == nil { continue } if entity.avatarEntity != nil { addUidList = append(addUidList, entity.avatarEntity.uid) } } // 发送已消失格子里的实体消失通知 g.RemoveSceneEntityNotifyToPlayer(player, delEntityIdList) // 发送新出现格子里的实体出现通知 g.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, addEntityIdList, false) // 更新玩家的位置信息 player.Pos.X = float64(motionInfo.Pos.X) player.Pos.Y = float64(motionInfo.Pos.Y) player.Pos.Z = float64(motionInfo.Pos.Z) // 更新玩家所在格子 world.aoiManager.RemoveEntityIdFromGrid(playerActiveAvatarEntityId, oldGid) world.aoiManager.AddEntityIdToGrid(playerActiveAvatarEntityId, newGid) // 其他玩家 for _, uid := range delUidList { otherPlayer := g.userManager.GetOnlineUser(uid) g.RemoveSceneEntityNotifyToPlayer(otherPlayer, []uint32{playerActiveAvatarEntityId}) } for _, uid := range addUidList { otherPlayer := g.userManager.GetOnlineUser(uid) g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{playerActiveAvatarEntityId}, false) } } // 把队伍中的其他非活跃角色也同步进行移动 team := player.TeamConfig.GetActiveTeam() for _, avatarId := range team.AvatarIdList { // 跳过当前的活跃角色 if avatarId == activeAvatarId { continue } entityId := playerTeamEntity.avatarEntityMap[avatarId] entity := scene.GetEntity(entityId) if entity == nil { continue } entity.pos.X = float64(motionInfo.Pos.X) entity.pos.Y = float64(motionInfo.Pos.Y) entity.pos.Z = float64(motionInfo.Pos.Z) entity.rot.X = float64(motionInfo.Rot.X) entity.rot.Y = float64(motionInfo.Rot.Y) entity.rot.Z = float64(motionInfo.Rot.Z) } // 更新玩家的位置信息 player.Pos.X = float64(motionInfo.Pos.X) player.Pos.Y = float64(motionInfo.Pos.Y) player.Pos.Z = float64(motionInfo.Pos.Z) player.Rot.X = float64(motionInfo.Rot.X) player.Rot.Y = float64(motionInfo.Rot.Y) player.Rot.Z = float64(motionInfo.Rot.Z) //// TODO 采集大地图地形数据 //if world.IsBigWorld() && scene.id == 3 && player.PlayerID != 1 { // if motionInfo.State == proto.MotionState_MOTION_STATE_WALK || // motionInfo.State == proto.MotionState_MOTION_STATE_RUN || // motionInfo.State == proto.MotionState_MOTION_STATE_DASH || // motionInfo.State == proto.MotionState_MOTION_STATE_CLIMB { // logger.LOG.Debug("set terr motionInfo: %v", motionInfo) // exist := g.worldManager.worldStatic.GetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z)) // g.worldManager.worldStatic.SetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z)) // if !exist { // // TODO 薄荷标记 // // 只给附近aoi区域的玩家广播消息 // surrPlayerList := make([]*model.Player, 0) // entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) // for _, entityId := range entityIdList { // entity := scene.GetEntity(entityId) // if entity == nil { // continue // } // if entity.avatarEntity != nil { // otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) // surrPlayerList = append(surrPlayerList, otherPlayer) // } // } // pos := &model.Vector{ // X: float64(int16(motionInfo.Pos.X)), // Y: float64(int16(motionInfo.Pos.Y)), // Z: float64(int16(motionInfo.Pos.Z)), // } // gadgetEntityId := scene.CreateEntityGadget(pos, 3003009) // for _, otherPlayer := range surrPlayerList { // g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{gadgetEntityId}, false) // } // } // } //} } // 更新场景实体的位置信息 sceneEntity := scene.GetEntity(entityMoveInfo.EntityId) if sceneEntity != nil { sceneEntity.pos = &model.Vector{ X: float64(motionInfo.Pos.X), Y: float64(motionInfo.Pos.Y), Z: float64(motionInfo.Pos.Z), } sceneEntity.rot = &model.Vector{ X: float64(motionInfo.Rot.X), Y: float64(motionInfo.Rot.Y), Z: float64(motionInfo.Rot.Z), } sceneEntity.moveState = uint16(motionInfo.State) sceneEntity.lastMoveSceneTimeMs = entityMoveInfo.SceneTime sceneEntity.lastMoveReliableSeq = entityMoveInfo.ReliableSeq //logger.LOG.Debug("entity move, id: %v, pos: %v, uid: %v", sceneEntity.id, sceneEntity.pos, player.PlayerID) } // 处理耐力消耗 g.HandleStamina(player, motionInfo.State) player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) default: player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) } } } func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user ability invocations, uid: %v", player.PlayerID) req := payloadMsg.(*proto.AbilityInvocationsNotify) for _, entry := range req.Invokes { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) // 处理能力调用 g.HandleAbilityInvoke(player, entry) player.AbilityInvokeHandler.AddEntry(entry.ForwardType, entry) } } func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user client ability init finish, uid: %v", player.PlayerID) req := payloadMsg.(*proto.ClientAbilityInitFinishNotify) invokeHandler := model.NewInvokeHandler[proto.AbilityInvokeEntry]() for _, entry := range req.Invokes { //logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) // 处理能力调用 g.HandleAbilityInvoke(player, entry) invokeHandler.AddEntry(entry.ForwardType, entry) } world := g.worldManager.GetWorldByID(player.WorldId) if world == nil { return } scene := world.GetSceneById(player.SceneId) // 只给附近aoi区域的玩家广播消息 surrPlayerList := make([]*model.Player, 0) entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) for _, entityId := range entityIdList { entity := scene.GetEntity(entityId) if entity == nil { continue } if entity.avatarEntity != nil { otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) surrPlayerList = append(surrPlayerList, otherPlayer) } } // ClientAbilityInitFinishNotify转发 // PacketClientAbilityInitFinishNotify if invokeHandler.AllLen() == 0 && invokeHandler.AllExceptCurLen() == 0 && invokeHandler.HostLen() == 0 { for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) clientAbilityInitFinishNotify.EntityId = req.EntityId g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) } } if invokeHandler.AllLen() > 0 { clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) clientAbilityInitFinishNotify.EntityId = req.EntityId clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardAll for _, v := range surrPlayerList { g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) } } if invokeHandler.AllExceptCurLen() > 0 { clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) clientAbilityInitFinishNotify.EntityId = req.EntityId clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardAllExceptCur for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } g.SendMsg(cmd.ClientAbilityInitFinishNotify, v.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) } } if invokeHandler.HostLen() > 0 { clientAbilityInitFinishNotify := new(proto.ClientAbilityInitFinishNotify) clientAbilityInitFinishNotify.EntityId = req.EntityId clientAbilityInitFinishNotify.Invokes = invokeHandler.EntryListForwardHost g.SendMsg(cmd.ClientAbilityInitFinishNotify, world.owner.PlayerID, player.ClientSeq, clientAbilityInitFinishNotify) } } func (g *GameManager) ClientAbilityChangeNotify(player *model.Player, payloadMsg pb.Message) { //logger.LOG.Debug("user client ability change, uid: %v", player.PlayerID) req := payloadMsg.(*proto.ClientAbilityChangeNotify) invokeHandler := model.NewInvokeHandler[proto.AbilityInvokeEntry]() for _, entry := range req.Invokes { invokeHandler.AddEntry(entry.ForwardType, entry) } world := g.worldManager.GetWorldByID(player.WorldId) if world == nil { return } scene := world.GetSceneById(player.SceneId) // 只给附近aoi区域的玩家广播消息 surrPlayerList := make([]*model.Player, 0) entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) for _, entityId := range entityIdList { entity := scene.GetEntity(entityId) if entity == nil { continue } if entity.avatarEntity != nil { otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) surrPlayerList = append(surrPlayerList, otherPlayer) } } // ClientAbilityChangeNotify转发 // PacketClientAbilityChangeNotify if invokeHandler.AllLen() == 0 && invokeHandler.AllExceptCurLen() == 0 && invokeHandler.HostLen() == 0 { clientAbilityChangeNotify := new(proto.ClientAbilityChangeNotify) clientAbilityChangeNotify.EntityId = req.EntityId clientAbilityChangeNotify.IsInitHash = req.IsInitHash for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } g.SendMsg(cmd.ClientAbilityChangeNotify, v.PlayerID, player.ClientSeq, clientAbilityChangeNotify) } } if invokeHandler.AllLen() > 0 { clientAbilityChangeNotify := new(proto.ClientAbilityChangeNotify) clientAbilityChangeNotify.EntityId = req.EntityId clientAbilityChangeNotify.IsInitHash = req.IsInitHash clientAbilityChangeNotify.Invokes = invokeHandler.EntryListForwardAll for _, v := range surrPlayerList { g.SendMsg(cmd.ClientAbilityChangeNotify, v.PlayerID, player.ClientSeq, clientAbilityChangeNotify) } } if invokeHandler.AllExceptCurLen() > 0 { clientAbilityChangeNotify := new(proto.ClientAbilityChangeNotify) clientAbilityChangeNotify.EntityId = req.EntityId clientAbilityChangeNotify.IsInitHash = req.IsInitHash clientAbilityChangeNotify.Invokes = invokeHandler.EntryListForwardAllExceptCur for _, v := range surrPlayerList { if player.PlayerID == v.PlayerID { continue } g.SendMsg(cmd.ClientAbilityChangeNotify, v.PlayerID, player.ClientSeq, clientAbilityChangeNotify) } } if invokeHandler.HostLen() > 0 { clientAbilityChangeNotify := new(proto.ClientAbilityChangeNotify) clientAbilityChangeNotify.EntityId = req.EntityId clientAbilityChangeNotify.IsInitHash = req.IsInitHash clientAbilityChangeNotify.Invokes = invokeHandler.EntryListForwardHost g.SendMsg(cmd.ClientAbilityChangeNotify, world.owner.PlayerID, player.ClientSeq, clientAbilityChangeNotify) } } func (g *GameManager) EvtDoSkillSuccNotify(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user event do skill success, uid: %v", player.PlayerID) req := payloadMsg.(*proto.EvtDoSkillSuccNotify) logger.LOG.Debug("EvtDoSkillSuccNotify: %v", req) // 处理技能开始时的耐力消耗 g.HandleSkillStartStamina(player, req.SkillId) }