From 62b08c2ac7e0ba3eed1f88c77ee1ffa0f658a53d Mon Sep 17 00:00:00 2001 From: huangxiaolei <1782360262@qq.com> Date: Mon, 12 Dec 2022 10:24:59 +0800 Subject: [PATCH] =?UTF-8?q?=E6=95=B4=E7=90=86=E5=9C=BA=E6=99=AF=E5=AE=9E?= =?UTF-8?q?=E4=BD=93=E7=9B=B8=E5=85=B3=EF=BC=8C=E4=BC=98=E5=8C=96=E5=90=8C?= =?UTF-8?q?=E6=AD=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gate/forward/forward.go | 18 +- gs/game/game_manager.go | 19 + gs/game/route_manager.go | 6 + gs/game/tick_manager.go | 77 +--- gs/game/user_ability.go | 27 -- gs/game/user_avatar.go | 25 +- gs/game/user_combat.go | 487 -------------------------- gs/game/user_fight_sync.go | 307 ++++++++++++++++ gs/game/user_login.go | 6 +- gs/game/user_map.go | 5 +- gs/game/user_multiplayer.go | 30 +- gs/game/user_scene.go | 121 ++++--- gs/game/user_stamina.go | 21 ++ gs/game/user_team.go | 120 ++++--- gs/game/world_manager.go | 502 ++++++++++++++------------- gs/model/invoke_handler.go | 6 +- gs/model/player.go | 2 +- gs/model/team.go | 38 +- pkg/reflection/struct.go | 30 ++ protocol/cmd/cmd_id_proto_obj_map.go | 12 +- 20 files changed, 847 insertions(+), 1012 deletions(-) delete mode 100644 gs/game/user_ability.go delete mode 100644 gs/game/user_combat.go create mode 100644 gs/game/user_fight_sync.go diff --git a/gate/forward/forward.go b/gate/forward/forward.go index 966a92e0..eed927fb 100644 --- a/gate/forward/forward.go +++ b/gate/forward/forward.go @@ -122,14 +122,12 @@ func (f *ForwardManager) kcpEventHandle() { logger.LOG.Error("can not find userId by convId") continue } - if f.getConnState(event.ConvId) == ConnAlive { - // 通知GS玩家下线 - netMsg := new(cmd.NetMsg) - netMsg.UserId = userId - netMsg.EventId = cmd.UserOfflineNotify - f.netMsgInput <- netMsg - logger.LOG.Info("send to gs user offline, ConvId: %v, UserId: %v", event.ConvId, netMsg.UserId) - } + // 通知GS玩家下线 + netMsg := new(cmd.NetMsg) + netMsg.UserId = userId + netMsg.EventId = cmd.UserOfflineNotify + f.netMsgInput <- netMsg + logger.LOG.Info("send to gs user offline, ConvId: %v, UserId: %v", event.ConvId, netMsg.UserId) // 删除各种map数据 f.deleteConnState(event.ConvId) f.deleteUserIdByConvId(event.ConvId) @@ -281,7 +279,7 @@ func (f *ForwardManager) sendNetMsgToGameServer() { netMsg.ClientSeq = protoMsg.HeadMessage.ClientSequenceId netMsg.PayloadMessage = protoMsg.PayloadMessage f.netMsgInput <- netMsg - case cmd.PlayerForceExitRsp: + case cmd.PlayerForceExitReq: // 玩家退出游戏请求 if connState != ConnAlive { continue @@ -294,7 +292,7 @@ func (f *ForwardManager) sendNetMsgToGameServer() { f.setConnState(protoMsg.ConvId, ConnClose) info := new(gm.KickPlayerInfo) info.UserId = userId - info.Reason = uint32(kcp.EnetServerKick) + info.Reason = uint32(kcp.EnetClientClose) f.KickPlayer(info) case cmd.PingReq: // ping请求 diff --git a/gs/game/game_manager.go b/gs/game/game_manager.go index 2e1c8135..5bb12956 100644 --- a/gs/game/game_manager.go +++ b/gs/game/game_manager.go @@ -130,6 +130,25 @@ func (g *GameManager) CommonRetSucc(cmdId uint16, player *model.Player, rsp pb.M g.SendMsg(cmdId, player.PlayerID, player.ClientSeq, rsp) } +func (g *GameManager) SendToWorldA(world *World, cmdId uint16, seq uint32, msg pb.Message) { + for _, v := range world.playerMap { + GAME_MANAGER.SendMsg(cmdId, v.PlayerID, seq, msg) + } +} + +func (g *GameManager) SendToWorldAEC(world *World, cmdId uint16, seq uint32, msg pb.Message, uid uint32) { + for _, v := range world.playerMap { + if uid == v.PlayerID { + continue + } + GAME_MANAGER.SendMsg(cmdId, v.PlayerID, seq, msg) + } +} + +func (g *GameManager) SendToWorldH(world *World, cmdId uint16, seq uint32, msg pb.Message) { + GAME_MANAGER.SendMsg(cmdId, world.owner.PlayerID, seq, msg) +} + func (g *GameManager) ReconnectPlayer(userId uint32) { g.SendMsg(cmd.ClientReconnectNotify, userId, 0, new(proto.ClientReconnectNotify)) } diff --git a/gs/game/route_manager.go b/gs/game/route_manager.go index 7594c78f..1b84cc29 100644 --- a/gs/game/route_manager.go +++ b/gs/game/route_manager.go @@ -106,6 +106,12 @@ func (r *RouteManager) InitRoute() { r.registerRouter(cmd.ChangeMpTeamAvatarReq, GAME_MANAGER.ChangeMpTeamAvatarReq) r.registerRouter(cmd.SceneAvatarStaminaStepReq, GAME_MANAGER.SceneAvatarStaminaStepReq) r.registerRouter(cmd.JoinPlayerSceneReq, GAME_MANAGER.JoinPlayerSceneReq) + r.registerRouter(cmd.EvtAvatarEnterFocusNotify, GAME_MANAGER.EvtAvatarEnterFocusNotify) + r.registerRouter(cmd.EvtAvatarUpdateFocusNotify, GAME_MANAGER.EvtAvatarUpdateFocusNotify) + r.registerRouter(cmd.EvtAvatarExitFocusNotify, GAME_MANAGER.EvtAvatarExitFocusNotify) + r.registerRouter(cmd.EvtEntityRenderersChangedNotify, GAME_MANAGER.EvtEntityRenderersChangedNotify) + r.registerRouter(cmd.EvtCreateGadgetNotify, GAME_MANAGER.EvtCreateGadgetNotify) + r.registerRouter(cmd.EvtDestroyGadgetNotify, GAME_MANAGER.EvtDestroyGadgetNotify) } func (r *RouteManager) RouteHandle(netMsg *cmd.NetMsg) { diff --git a/gs/game/tick_manager.go b/gs/game/tick_manager.go index f58afb70..13cc39a5 100644 --- a/gs/game/tick_manager.go +++ b/gs/game/tick_manager.go @@ -144,17 +144,17 @@ func (t *TickManager) onTick10Second(now int64) { if monsterEntityCount < 30 { monsterEntityId := t.createMonster(scene) bigWorldOwner := USER_MANAGER.GetOnlineUser(1) - GAME_MANAGER.AddSceneEntityNotify(bigWorldOwner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true) + GAME_MANAGER.AddSceneEntityNotify(bigWorldOwner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true, false) } } for _, player := range world.playerMap { if world.multiplayer || !world.owner.Pause { // 改面板 - for _, avatarId := range world.GetPlayerAvatarIdList(player) { - avatar := player.AvatarMap[avatarId] + for _, worldAvatar := range world.GetPlayerWorldAvatarList(player) { + avatar := player.AvatarMap[worldAvatar.avatarId] avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_ATTACK)] = 1000000 avatar.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CRITICAL)] = 1.0 - GAME_MANAGER.UpdateUserAvatarFightProp(player.PlayerID, avatarId) + GAME_MANAGER.UpdateUserAvatarFightProp(player.PlayerID, worldAvatar.avatarId) } } } @@ -249,75 +249,6 @@ func (t *TickManager) onTick200MilliSecond(now int64) { } func (t *TickManager) onTick100MilliSecond(now int64) { - //// 伤害处理和转发 - //for _, world := range t.gameManager.worldManager.worldMap { - // for _, scene := range world.sceneMap { - // scene.AttackHandler(t.gameManager) - // } - //} - - // 服务器控制的模拟AI移动 - - //bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1) - //bigWorld := t.gameManager.worldManager.GetBigWorld() - //bigWorldScene := bigWorld.GetSceneById(3) - // - //if len(bigWorldScene.playerMap) < 2 { - // return - //} - //if t.gameManager.worldManager.worldStatic.aiMoveCurrIndex >= len(t.gameManager.worldManager.worldStatic.aiMoveVectorList)-1 { - // return - //} - //t.gameManager.worldManager.worldStatic.aiMoveCurrIndex++ - // - //entityMoveInfo := new(proto.EntityMoveInfo) - //activeAvatarId := bigWorldOwner.TeamConfig.GetActiveAvatarId() - //playerTeamEntity := bigWorldScene.GetPlayerTeamEntity(bigWorldOwner.PlayerID) - //entityMoveInfo.EntityId = playerTeamEntity.avatarEntityMap[activeAvatarId] - //entityMoveInfo.SceneTime = uint32(bigWorldScene.GetSceneTime()) - //entityMoveInfo.ReliableSeq = uint32(bigWorldScene.GetSceneTime() / 100 * 100) - //entityMoveInfo.IsReliable = true - //oldPos := model.Vector{ - // X: bigWorldOwner.Pos.X, - // Y: bigWorldOwner.Pos.Y, - // Z: bigWorldOwner.Pos.Z, - //} - //newPos := t.gameManager.worldManager.worldStatic.aiMoveVectorList[t.gameManager.worldManager.worldStatic.aiMoveCurrIndex] - //rotY := math.Atan2(newPos.X-oldPos.X, newPos.Z-oldPos.Z) / math.Pi * 180.0 - //if rotY < 0.0 { - // rotY += 360.0 - //} - //entityMoveInfo.MotionInfo = &proto.MotionInfo{ - // Pos: &proto.Vector{ - // X: float32(newPos.X), - // Y: float32(newPos.Y), - // Z: float32(newPos.Z), - // }, - // Rot: &proto.Vector{ - // X: 0.0, - // Y: float32(rotY), - // Z: 0.0, - // }, - // Speed: &proto.Vector{ - // X: float32((newPos.X - oldPos.X) * 10.0), - // Y: float32((newPos.Y - oldPos.Y) * 10.0), - // Z: float32((newPos.Z - oldPos.Z) * 10.0), - // }, - // State: proto.MotionState_MOTION_STATE_RUN, - // RefPos: new(proto.Vector), - //} - //data, err := pb.Marshal(entityMoveInfo) - //if err != nil { - // logger.LOG.Error("build combat invocations entity move info error: %v", err) - // return - //} - //combatInvocationsNotify := new(proto.CombatInvocationsNotify) - //combatInvocationsNotify.InvokeList = []*proto.CombatInvokeEntry{{ - // CombatData: data, - // ForwardType: proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR, - // ArgumentType: proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE, - //}} - //t.gameManager.CombatInvocationsNotify(bigWorldOwner.PlayerID, bigWorldOwner, 0, combatInvocationsNotify) } func (t *TickManager) createMonster(scene *Scene) uint32 { diff --git a/gs/game/user_ability.go b/gs/game/user_ability.go deleted file mode 100644 index a9640b07..00000000 --- a/gs/game/user_ability.go +++ /dev/null @@ -1,27 +0,0 @@ -package game - -import ( - "hk4e/gs/model" - "hk4e/protocol/proto" -) - -// HandleAbilityInvoke 处理能力调用 -func (g *GameManager) HandleAbilityInvoke(player *model.Player, entry *proto.AbilityInvokeEntry) { - //logger.LOG.Debug("ability invoke handle, entry: %v", entry.ArgumentType) - - switch entry.ArgumentType { - case proto.AbilityInvokeArgument_ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA: - // 消耗耐力 - - //costStamina := new(proto.AbilityMixinCostStamina) - //err := pb.Unmarshal(entry.AbilityData, costStamina) - //if err != nil { - // logger.LOG.Error("unmarshal ability data err: %v", err) - // return - //} - - // 处理技能持续时的耐力消耗 - g.HandleSkillSustainStamina(player) - - } -} diff --git a/gs/game/user_avatar.go b/gs/game/user_avatar.go index 5434a377..599fd171 100644 --- a/gs/game/user_avatar.go +++ b/gs/game/user_avatar.go @@ -88,7 +88,6 @@ func (g *GameManager) WearUserAvatarEquip(userId uint32, avatarId uint32, weapon world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId) - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) if weapon.AvatarId != 0 { // 武器在别的角色身上 @@ -104,14 +103,12 @@ func (g *GameManager) WearUserAvatarEquip(userId uint32, avatarId uint32, weapon weakAvatar := player.AvatarMap[weakAvatarId] weakWeapon := player.WeaponMap[weakAvatar.EquipWeapon.WeaponId] - for _, aid := range world.GetPlayerAvatarIdList(player) { - if aid == weakAvatar.AvatarId { - playerTeamEntity.weaponEntityMap[weakWeapon.WeaponId] = scene.CreateEntityWeapon() - } + weakWorldAvatar := world.GetPlayerWorldAvatar(player, weakAvatarId) + if weakWorldAvatar != nil { + weakWorldAvatar.weaponEntityId = scene.CreateEntityWeapon() + avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(weakAvatar, weakWeapon, weakWorldAvatar.weaponEntityId) + g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) } - - avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(weakAvatar, weakWeapon, playerTeamEntity.weaponEntityMap[weakWeapon.WeaponId]) - g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) } else if avatar.EquipWeapon != nil { // 角色当前有武器 player.TakeOffWeapon(avatarId, avatar.EquipWeapon.WeaponId) @@ -121,14 +118,12 @@ func (g *GameManager) WearUserAvatarEquip(userId uint32, avatarId uint32, weapon player.WearWeapon(avatarId, weaponId) } - for _, aid := range world.GetPlayerAvatarIdList(player) { - if aid == avatarId { - playerTeamEntity.weaponEntityMap[weaponId] = scene.CreateEntityWeapon() - } + worldAvatar := world.GetPlayerWorldAvatar(player, avatarId) + if worldAvatar != nil { + worldAvatar.weaponEntityId = scene.CreateEntityWeapon() + avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(avatar, weapon, worldAvatar.weaponEntityId) + g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) } - - avatarEquipChangeNotify := g.PacketAvatarEquipChangeNotify(avatar, weapon, playerTeamEntity.weaponEntityMap[weaponId]) - g.SendMsg(cmd.AvatarEquipChangeNotify, userId, player.ClientSeq, avatarEquipChangeNotify) } func (g *GameManager) AvatarChangeCostumeReq(player *model.Player, payloadMsg pb.Message) { diff --git a/gs/game/user_combat.go b/gs/game/user_combat.go deleted file mode 100644 index 09527687..00000000 --- a/gs/game/user_combat.go +++ /dev/null @@ -1,487 +0,0 @@ -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 := WORLD_MANAGER.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)) - entityIdList := world.GetSceneById(player.SceneId).GetEntityIdList() - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := USER_MANAGER.GetOnlineUser(entity.avatarEntity.uid) - surrPlayerList = append(surrPlayerList, otherPlayer) - } - } - - // CombatInvocationsNotify转发 - 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转发 - 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 := WORLD_MANAGER.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)) - entityIdList := world.GetSceneById(player.SceneId).GetEntityIdList() - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := USER_MANAGER.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 := WORLD_MANAGER.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 := world.GetPlayerActiveAvatarId(player) - 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 false && 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, proto.VisionType_VISION_TYPE_REMOVE, 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 := USER_MANAGER.GetOnlineUser(uid) - g.RemoveSceneEntityNotifyToPlayer(otherPlayer, proto.VisionType_VISION_TYPE_REMOVE, []uint32{playerActiveAvatarEntityId}) - } - for _, uid := range addUidList { - otherPlayer := USER_MANAGER.GetOnlineUser(uid) - g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{playerActiveAvatarEntityId}, false) - } - } - // 把队伍中的其他非活跃角色也同步进行移动 - for _, avatarId := range world.GetPlayerAvatarIdList(player) { - // 跳过当前的活跃角色 - 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 := WORLD_MANAGER.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)) - entityIdList := world.GetSceneById(player.SceneId).GetEntityIdList() - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := USER_MANAGER.GetOnlineUser(entity.avatarEntity.uid) - surrPlayerList = append(surrPlayerList, otherPlayer) - } - } - - // ClientAbilityInitFinishNotify转发 - 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 := WORLD_MANAGER.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)) - entityIdList := world.GetSceneById(player.SceneId).GetEntityIdList() - for _, entityId := range entityIdList { - entity := scene.GetEntity(entityId) - if entity == nil { - continue - } - if entity.avatarEntity != nil { - otherPlayer := USER_MANAGER.GetOnlineUser(entity.avatarEntity.uid) - surrPlayerList = append(surrPlayerList, otherPlayer) - } - } - - // ClientAbilityChangeNotify转发 - 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) -} diff --git a/gs/game/user_fight_sync.go b/gs/game/user_fight_sync.go new file mode 100644 index 00000000..2db7c3a6 --- /dev/null +++ b/gs/game/user_fight_sync.go @@ -0,0 +1,307 @@ +package game + +import ( + "hk4e/gs/model" + "hk4e/pkg/logger" + "hk4e/pkg/reflection" + "hk4e/protocol/cmd" + "hk4e/protocol/proto" + + pb "google.golang.org/protobuf/proto" +) + +func DoForward[IET model.InvokeEntryType](player *model.Player, req pb.Message, copyFieldList []string, forwardField string, invokeHandler *model.InvokeHandler[IET]) { + cmdProtoMap := cmd.NewCmdProtoMap() + cmdId := cmdProtoMap.GetCmdIdByProtoObj(req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + if invokeHandler.AllLen() == 0 && invokeHandler.AllExceptCurLen() == 0 && invokeHandler.HostLen() == 0 { + ntf := cmdProtoMap.GetProtoObjByCmdId(cmdId) + for _, fieldName := range copyFieldList { + reflection.CopyStructField(ntf, req, fieldName) + } + for _, v := range world.playerMap { + GAME_MANAGER.SendMsg(cmdId, v.PlayerID, player.ClientSeq, ntf) + } + } + if invokeHandler.AllLen() > 0 { + ntf := cmdProtoMap.GetProtoObjByCmdId(cmdId) + for _, fieldName := range copyFieldList { + reflection.CopyStructField(ntf, req, fieldName) + } + reflection.SetStructFieldValue(ntf, forwardField, invokeHandler.EntryListForwardAll) + GAME_MANAGER.SendToWorldA(world, cmdId, player.ClientSeq, ntf) + } + if invokeHandler.AllExceptCurLen() > 0 { + ntf := cmdProtoMap.GetProtoObjByCmdId(cmdId) + for _, fieldName := range copyFieldList { + reflection.CopyStructField(ntf, req, fieldName) + } + reflection.SetStructFieldValue(ntf, forwardField, invokeHandler.EntryListForwardAllExceptCur) + GAME_MANAGER.SendToWorldAEC(world, cmdId, player.ClientSeq, ntf, player.PlayerID) + } + if invokeHandler.HostLen() > 0 { + ntf := cmdProtoMap.GetProtoObjByCmdId(cmdId) + for _, fieldName := range copyFieldList { + reflection.CopyStructField(ntf, req, fieldName) + } + reflection.SetStructFieldValue(ntf, forwardField, invokeHandler.EntryListForwardHost) + GAME_MANAGER.SendToWorldH(world, cmdId, player.ClientSeq, ntf) + } +} + +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 + DoForward[proto.CombatInvokeEntry](player, &proto.CombatInvocationsNotify{}, []string{}, "InvokeList", player.CombatInvokeHandler) + DoForward[proto.AbilityInvokeEntry](player, &proto.AbilityInvocationsNotify{}, []string{}, "Invokes", player.AbilityInvokeHandler) + 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 := WORLD_MANAGER.GetWorldByID(player.WorldId) + if world == nil { + return + } + scene := world.GetSceneById(player.SceneId) + ntf.OpIdx = scene.meeoIndex + scene.meeoIndex++ + g.SendToWorldA(world, cmd.MassiveEntityElementOpBatchNotify, 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) + if player.SceneLoadState != model.SceneEnterDone { + return + } + world := WORLD_MANAGER.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: + player.CombatInvokeHandler.AddEntry(entry.ForwardType, entry) + case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ENTITY_MOVE: + 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 + } + sceneEntity := scene.GetEntity(entityMoveInfo.EntityId) + if sceneEntity == nil { + continue + } + if sceneEntity.avatarEntity != nil { + // 玩家实体在移动 + // 更新玩家的位置信息 + 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) + } else { + // 非玩家实体在移动 更新场景实体的位置信息 + 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) + case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_ANIMATOR_STATE_CHANGED: + evtAnimatorStateChangedInfo := new(proto.EvtAnimatorStateChangedInfo) + err := pb.Unmarshal(entry.CombatData, evtAnimatorStateChangedInfo) + if err != nil { + logger.LOG.Error("parse EvtAnimatorStateChangedInfo error: %v", err) + } + logger.LOG.Debug("%v", evtAnimatorStateChangedInfo) + 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) + } + DoForward[proto.AbilityInvokeEntry](player, &proto.ClientAbilityInitFinishNotify{}, []string{"EntityId"}, "Invokes", invokeHandler) +} + +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) + } + DoForward[proto.AbilityInvokeEntry](player, req, []string{"EntityId", "IsInitHash"}, "Invokes", invokeHandler) + + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + if world == nil { + return + } + for _, abilityInvokeEntry := range req.Invokes { + switch abilityInvokeEntry.ArgumentType { + case proto.AbilityInvokeArgument_ABILITY_INVOKE_ARGUMENT_META_ADD_NEW_ABILITY: + abilityMetaAddAbility := new(proto.AbilityMetaAddAbility) + err := pb.Unmarshal(abilityInvokeEntry.AbilityData, abilityMetaAddAbility) + if err != nil { + logger.LOG.Error("%v", err) + continue + } + worldAvatar := world.GetWorldAvatarByEntityId(abilityInvokeEntry.EntityId) + if worldAvatar == nil { + continue + } + worldAvatar.abilityList = append(worldAvatar.abilityList, abilityMetaAddAbility.Ability) + case proto.AbilityInvokeArgument_ABILITY_INVOKE_ARGUMENT_META_MODIFIER_CHANGE: + abilityMetaModifierChange := new(proto.AbilityMetaModifierChange) + err := pb.Unmarshal(abilityInvokeEntry.AbilityData, abilityMetaModifierChange) + if err != nil { + logger.LOG.Error("%v", err) + continue + } + abilityAppliedModifier := &proto.AbilityAppliedModifier{ + ModifierLocalId: abilityMetaModifierChange.ModifierLocalId, + ParentAbilityEntityId: 0, + ParentAbilityName: abilityMetaModifierChange.ParentAbilityName, + ParentAbilityOverride: abilityMetaModifierChange.ParentAbilityOverride, + InstancedAbilityId: abilityInvokeEntry.Head.InstancedAbilityId, + InstancedModifierId: abilityInvokeEntry.Head.InstancedModifierId, + ExistDuration: 0, + AttachedInstancedModifier: abilityMetaModifierChange.AttachedInstancedModifier, + ApplyEntityId: abilityMetaModifierChange.ApplyEntityId, + IsAttachedParentAbility: abilityMetaModifierChange.IsAttachedParentAbility, + ModifierDurability: nil, + SbuffUid: 0, + IsServerbuffModifier: abilityInvokeEntry.Head.IsServerbuffModifier, + } + worldAvatar := world.GetWorldAvatarByEntityId(abilityInvokeEntry.EntityId) + if worldAvatar == nil { + continue + } + worldAvatar.modifierList = append(worldAvatar.modifierList, abilityAppliedModifier) + default: + } + } +} + +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) +} + +func (g *GameManager) EvtAvatarEnterFocusNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user avatar enter focus, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtAvatarEnterFocusNotify) + logger.LOG.Debug("EvtAvatarEnterFocusNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + g.SendToWorldA(world, cmd.EvtAvatarEnterFocusNotify, player.ClientSeq, req) +} + +func (g *GameManager) EvtAvatarUpdateFocusNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user avatar update focus, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtAvatarUpdateFocusNotify) + logger.LOG.Debug("EvtAvatarUpdateFocusNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + g.SendToWorldA(world, cmd.EvtAvatarUpdateFocusNotify, player.ClientSeq, req) +} + +func (g *GameManager) EvtAvatarExitFocusNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user avatar exit focus, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtAvatarExitFocusNotify) + logger.LOG.Debug("EvtAvatarExitFocusNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + g.SendToWorldA(world, cmd.EvtAvatarExitFocusNotify, player.ClientSeq, req) +} + +func (g *GameManager) EvtEntityRenderersChangedNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user entity render change, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtEntityRenderersChangedNotify) + logger.LOG.Debug("EvtEntityRenderersChangedNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + g.SendToWorldA(world, cmd.EvtEntityRenderersChangedNotify, player.ClientSeq, req) +} + +func (g *GameManager) EvtCreateGadgetNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user create gadget, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtCreateGadgetNotify) + logger.LOG.Debug("EvtCreateGadgetNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + scene := world.GetSceneById(player.SceneId) + scene.ClientCreateEntityGadget(&model.Vector{ + X: float64(req.InitPos.X), + Y: float64(req.InitPos.Y), + Z: float64(req.InitPos.Z), + }, &model.Vector{ + X: float64(req.InitEulerAngles.X), + Y: float64(req.InitEulerAngles.Y), + Z: float64(req.InitEulerAngles.Z), + }, req.EntityId, req.ConfigId, req.CampId, req.CampType, req.OwnerEntityId, req.TargetEntityId, req.PropOwnerEntityId) + g.AddSceneEntityNotify(player, proto.VisionType_VISION_TYPE_BORN, []uint32{req.EntityId}, true, true) +} + +func (g *GameManager) EvtDestroyGadgetNotify(player *model.Player, payloadMsg pb.Message) { + logger.LOG.Debug("user destroy gadget, uid: %v", player.PlayerID) + req := payloadMsg.(*proto.EvtDestroyGadgetNotify) + logger.LOG.Debug("EvtDestroyGadgetNotify: %v", req) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + scene := world.GetSceneById(player.SceneId) + scene.DestroyEntity(req.EntityId) + g.RemoveSceneEntityNotifyBroadcast(scene, proto.VisionType_VISION_TYPE_MISS, []uint32{req.EntityId}) +} diff --git a/gs/game/user_login.go b/gs/game/user_login.go index 0dd82c26..d70bd9a2 100644 --- a/gs/game/user_login.go +++ b/gs/game/user_login.go @@ -31,7 +31,7 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u // 初始化 player.InitAll() - player.TeamConfig.UpdateTeam() + //player.TeamConfig.UpdateTeam() // 创建世界 world := WORLD_MANAGER.CreateWorld(player) world.AddPlayer(player, player.SceneId) @@ -287,7 +287,7 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata player.Signature = "" player.MainCharAvatarId = mainCharAvatarId player.HeadImage = mainCharAvatarId - player.Birthday = [2]uint8{0, 0} + player.Birthday = []uint8{0, 0} player.NameCard = 210001 player.NameCardList = make([]uint32, 0) player.NameCardList = append(player.NameCardList, 210001, 210042) @@ -373,7 +373,7 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata player.WearWeapon(mainCharAvatarId, weaponId) player.TeamConfig = model.NewTeamInfo() - player.TeamConfig.SetTeamAvatar(0, []uint32{mainCharAvatarId}) + player.TeamConfig.GetActiveTeam().SetAvatarIdList([]uint32{mainCharAvatarId}) return player } diff --git a/gs/game/user_map.go b/gs/game/user_map.go index b605be37..cf182612 100644 --- a/gs/game/user_map.go +++ b/gs/game/user_map.go @@ -82,8 +82,7 @@ func (g *GameManager) TeleportPlayer(player *model.Player, sceneId uint32, pos * world := WORLD_MANAGER.GetWorldByID(player.WorldId) oldScene := world.GetSceneById(oldSceneId) activeAvatarId := world.GetPlayerActiveAvatarId(player) - playerTeamEntity := oldScene.GetPlayerTeamEntity(player.PlayerID) - g.RemoveSceneEntityNotifyBroadcast(oldScene, proto.VisionType_VISION_TYPE_REMOVE, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}) + g.RemoveSceneEntityNotifyBroadcast(oldScene, proto.VisionType_VISION_TYPE_REMOVE, []uint32{world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)}) if jumpScene { delTeamEntityNotify := g.PacketDelTeamEntityNotify(oldScene, player) g.SendMsg(cmd.DelTeamEntityNotify, player.PlayerID, player.ClientSeq, delTeamEntityNotify) @@ -91,8 +90,6 @@ func (g *GameManager) TeleportPlayer(player *model.Player, sceneId uint32, pos * oldScene.RemovePlayer(player) newScene := world.GetSceneById(newSceneId) newScene.AddPlayer(player) - } else { - oldScene.UpdatePlayerTeamEntity(player) } player.Pos.X = pos.X player.Pos.Y = pos.Y diff --git a/gs/game/user_multiplayer.go b/gs/game/user_multiplayer.go index cfbec168..3ae22845 100644 --- a/gs/game/user_multiplayer.go +++ b/gs/game/user_multiplayer.go @@ -144,16 +144,12 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes if hostPlayer.SceneLoadState == model.SceneEnterDone { delete(hostWorld.waitEnterPlayerMap, player.PlayerID) - player.Pos = &model.Vector{ - X: hostPlayer.Pos.X, - Y: hostPlayer.Pos.Y, - Z: hostPlayer.Pos.Z, - } - player.Rot = &model.Vector{ - X: hostPlayer.Rot.X, - Y: hostPlayer.Rot.Y, - Z: hostPlayer.Rot.Z, - } + player.Pos.X = hostPlayer.Pos.X + player.Pos.Y = hostPlayer.Pos.Y + player.Pos.Z = hostPlayer.Pos.Z + player.Rot.X = hostPlayer.Rot.X + player.Rot.Y = hostPlayer.Rot.Y + player.Rot.Z = hostPlayer.Rot.Z player.SceneId = hostPlayer.SceneId g.UserWorldAddPlayer(hostWorld, player) @@ -258,10 +254,8 @@ func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint g.SendMsg(cmd.GuestBeginEnterSceneNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, guestBeginEnterSceneNotify) // 仅仅把当前的场上角色的实体消失掉 - scene := world.GetSceneById(hostPlayer.SceneId) - playerTeamEntity := scene.GetPlayerTeamEntity(hostPlayer.PlayerID) activeAvatarId := world.GetPlayerActiveAvatarId(hostPlayer) - g.RemoveSceneEntityNotifyToPlayer(hostPlayer, proto.VisionType_VISION_TYPE_MISS, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}) + g.RemoveSceneEntityNotifyToPlayer(hostPlayer, proto.VisionType_VISION_TYPE_MISS, []uint32{world.GetPlayerWorldAvatarEntityId(hostPlayer, activeAvatarId)}) } func (g *GameManager) UserLeaveWorld(player *model.Player) bool { @@ -306,9 +300,8 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player) scene := world.GetSceneById(player.SceneId) // 仅仅把当前的场上角色的实体消失掉 - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) activeAvatarId := world.GetPlayerActiveAvatarId(player) - g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_TYPE_MISS, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}) + g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_TYPE_MISS, []uint32{world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)}) delTeamEntityNotify := g.PacketDelTeamEntityNotify(scene, player) g.SendMsg(cmd.DelTeamEntityNotify, player.PlayerID, player.ClientSeq, delTeamEntityNotify) @@ -320,8 +313,7 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player) g.SendMsg(cmd.PlayerQuitFromMpNotify, player.PlayerID, player.ClientSeq, playerQuitFromMpNotify) activeAvatarId := world.GetPlayerActiveAvatarId(player) - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) - g.RemoveSceneEntityNotifyBroadcast(scene, proto.VisionType_VISION_TYPE_REMOVE, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}) + g.RemoveSceneEntityNotifyBroadcast(scene, proto.VisionType_VISION_TYPE_REMOVE, []uint32{world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)}) } world.RemovePlayer(player) @@ -410,10 +402,8 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod if worldPlayer.PlayerID == worldPlayer.PlayerID { continue } - worldPlayerScene := hostWorld.GetSceneById(worldPlayer.SceneId) - worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) teamEntityInfo := &proto.TeamEntityInfo{ - TeamEntityId: worldPlayerTeamEntity.teamEntityId, + TeamEntityId: hostWorld.GetPlayerTeamEntityId(worldPlayer), AuthorityPeerId: hostWorld.GetPlayerPeerId(worldPlayer), TeamAbilityInfo: new(proto.AbilitySyncStateInfo), } diff --git a/gs/game/user_scene.go b/gs/game/user_scene.go index eebdbc73..10d32740 100644 --- a/gs/game/user_scene.go +++ b/gs/game/user_scene.go @@ -117,30 +117,36 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes empty := new(proto.AbilitySyncStateInfo) activeAvatarId := world.GetPlayerActiveAvatarId(player) - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) playerEnterSceneInfoNotify := &proto.PlayerEnterSceneInfoNotify{ - CurAvatarEntityId: playerTeamEntity.avatarEntityMap[activeAvatarId], + CurAvatarEntityId: world.GetPlayerWorldAvatarEntityId(player, activeAvatarId), EnterSceneToken: player.EnterSceneToken, TeamEnterInfo: &proto.TeamEnterSceneInfo{ - TeamEntityId: playerTeamEntity.teamEntityId, + TeamEntityId: world.GetPlayerTeamEntityId(player), TeamAbilityInfo: empty, AbilityControlBlock: new(proto.AbilityControlBlock), }, MpLevelEntityInfo: &proto.MPLevelEntityInfo{ EntityId: WORLD_MANAGER.GetWorldByID(player.WorldId).mpLevelEntityId, - AuthorityPeerId: 1, + AuthorityPeerId: world.GetPlayerPeerId(player), AbilityInfo: empty, }, AvatarEnterInfo: make([]*proto.AvatarEnterSceneInfo, 0), } - for _, avatarId := range world.GetPlayerAvatarIdList(player) { - avatar := player.AvatarMap[avatarId] + for _, worldAvatar := range world.GetPlayerWorldAvatarList(player) { + avatar := player.AvatarMap[worldAvatar.avatarId] avatarEnterSceneInfo := &proto.AvatarEnterSceneInfo{ - AvatarGuid: avatar.Guid, - AvatarEntityId: playerTeamEntity.avatarEntityMap[avatarId], - WeaponGuid: avatar.EquipWeapon.Guid, - WeaponEntityId: playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId], - AvatarAbilityInfo: empty, + AvatarGuid: avatar.Guid, + AvatarEntityId: world.GetPlayerWorldAvatarEntityId(player, worldAvatar.avatarId), + WeaponGuid: avatar.EquipWeapon.Guid, + WeaponEntityId: world.GetPlayerWorldAvatarWeaponEntityId(player, worldAvatar.avatarId), + AvatarAbilityInfo: &proto.AbilitySyncStateInfo{ + IsInited: len(worldAvatar.abilityList) != 0, + DynamicValueMap: nil, + AppliedAbilities: worldAvatar.abilityList, + AppliedModifiers: worldAvatar.modifierList, + MixinRecoverInfos: nil, + SgvDynamicValueMap: nil, + }, WeaponAbilityInfo: empty, } playerEnterSceneInfoNotify.AvatarEnterInfo = append(playerEnterSceneInfoNotify.AvatarEnterInfo, avatarEnterSceneInfo) @@ -190,10 +196,8 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes if worldPlayer.PlayerID == player.PlayerID { continue } - worldPlayerScene := world.GetSceneById(worldPlayer.SceneId) - worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) teamEntityInfo := &proto.TeamEntityInfo{ - TeamEntityId: worldPlayerTeamEntity.teamEntityId, + TeamEntityId: world.GetPlayerTeamEntityId(worldPlayer), AuthorityPeerId: world.GetPlayerPeerId(worldPlayer), TeamAbilityInfo: new(proto.AbilitySyncStateInfo), } @@ -218,7 +222,6 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user enter scene done, uid: %v", player.PlayerID) world := WORLD_MANAGER.GetWorldByID(player.WorldId) - scene := world.GetSceneById(player.SceneId) if world.multiplayer && world.IsPlayerFirstEnter(player) { guestPostEnterSceneNotify := &proto.GuestPostEnterSceneNotify{ @@ -230,12 +233,11 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess var visionType = proto.VisionType_VISION_TYPE_TRANSPORT - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) activeAvatarId := world.GetPlayerActiveAvatarId(player) if world.IsPlayerFirstEnter(player) { visionType = proto.VisionType_VISION_TYPE_BORN } - g.AddSceneEntityNotify(player, visionType, []uint32{playerTeamEntity.avatarEntityMap[activeAvatarId]}, true) + g.AddSceneEntityNotify(player, visionType, []uint32{world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)}, true, false) // 通过aoi获取场景中在自己周围格子里的全部实体id //entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) @@ -243,7 +245,7 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess if world.IsPlayerFirstEnter(player) { visionType = proto.VisionType_VISION_TYPE_MEET } - g.AddSceneEntityNotify(player, visionType, entityIdList, false) + g.AddSceneEntityNotify(player, visionType, entityIdList, false, false) sceneAreaWeatherNotify := &proto.SceneAreaWeatherNotify{ WeatherAreaId: 0, @@ -262,16 +264,12 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess for otherPlayerId := range world.waitEnterPlayerMap { delete(world.waitEnterPlayerMap, otherPlayerId) otherPlayer := USER_MANAGER.GetOnlineUser(otherPlayerId) - otherPlayer.Pos = &model.Vector{ - X: player.Pos.X, - Y: player.Pos.Y, - Z: player.Pos.Z, - } - otherPlayer.Rot = &model.Vector{ - X: player.Rot.X, - Y: player.Rot.Y, - Z: player.Rot.Z, - } + otherPlayer.Pos.X = player.Pos.X + otherPlayer.Pos.Y = player.Pos.Y + otherPlayer.Pos.Z = player.Pos.Z + otherPlayer.Rot.X = player.Rot.X + otherPlayer.Rot.Y = player.Rot.Y + otherPlayer.Rot.Z = player.Rot.Z otherPlayer.SceneId = player.SceneId g.UserWorldAddPlayer(world, otherPlayer) @@ -400,12 +398,15 @@ func (g *GameManager) AddSceneEntityNotifyToPlayer(player *model.Player, visionT player.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList)) } -func (g *GameManager) AddSceneEntityNotifyBroadcast(scene *Scene, visionType proto.VisionType, entityList []*proto.SceneEntityInfo) { +func (g *GameManager) AddSceneEntityNotifyBroadcast(player *model.Player, scene *Scene, visionType proto.VisionType, entityList []*proto.SceneEntityInfo, aec bool) { sceneEntityAppearNotify := &proto.SceneEntityAppearNotify{ AppearType: visionType, EntityList: entityList, } for _, scenePlayer := range scene.playerMap { + if aec && scenePlayer.PlayerID == player.PlayerID { + continue + } g.SendMsg(cmd.SceneEntityAppearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityAppearNotify) logger.LOG.Debug("SceneEntityAppearNotify, uid: %v, type: %v, len: %v", scenePlayer.PlayerID, sceneEntityAppearNotify.AppearType, len(sceneEntityAppearNotify.EntityList)) @@ -434,7 +435,7 @@ func (g *GameManager) RemoveSceneEntityNotifyBroadcast(scene *Scene, visionType } } -func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType proto.VisionType, entityIdList []uint32, broadcast bool) { +func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType proto.VisionType, entityIdList []uint32, broadcast bool, aec bool) { world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId) entityList := make([]*proto.SceneEntityInfo, 0) @@ -469,7 +470,7 @@ func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType prot } } if broadcast { - g.AddSceneEntityNotifyBroadcast(scene, visionType, entityList) + g.AddSceneEntityNotifyBroadcast(player, scene, visionType, entityList, aec) } else { g.AddSceneEntityNotifyToPlayer(player, visionType, entityList) } @@ -522,11 +523,11 @@ func (g *GameManager) PacketFightPropMapToPbFightPropList(fightPropMap map[uint3 } func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Player, avatarId uint32) *proto.SceneEntityInfo { - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) - entity := scene.GetEntity(playerTeamEntity.avatarEntityMap[avatarId]) + entity := scene.GetEntity(scene.world.GetPlayerWorldAvatarEntityId(player, avatarId)) if entity == nil { return new(proto.SceneEntityInfo) } + worldAvatar := scene.world.GetWorldAvatarByEntityId(entity.id) sceneEntityInfo := &proto.SceneEntityInfo{ EntityType: proto.ProtEntityType_PROT_ENTITY_TYPE_AVATAR, EntityId: entity.id, @@ -557,7 +558,14 @@ func (g *GameManager) PacketSceneEntityInfoAvatar(scene *Scene, player *model.Pl }, EntityClientData: new(proto.EntityClientData), EntityAuthorityInfo: &proto.EntityAuthorityInfo{ - AbilityInfo: new(proto.AbilitySyncStateInfo), + AbilityInfo: &proto.AbilitySyncStateInfo{ + IsInited: len(worldAvatar.abilityList) != 0, + DynamicValueMap: nil, + AppliedAbilities: worldAvatar.abilityList, + AppliedModifiers: worldAvatar.modifierList, + MixinRecoverInfos: nil, + SgvDynamicValueMap: nil, + }, RendererChangedInfo: new(proto.EntityRendererChangedInfo), AiInfo: &proto.SceneEntityAiInfo{ IsAiOpen: true, @@ -649,9 +657,6 @@ func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32) FightPropList: g.PacketFightPropMapToPbFightPropList(entity.fightProp), LifeState: 1, AnimatorParaList: make([]*proto.AnimatorParameterValueInfoPair, 0), - Entity: &proto.SceneEntityInfo_Gadget{ - Gadget: g.PacketSceneGadgetInfo(entity.gadgetEntity.gatherId), - }, EntityClientData: new(proto.EntityClientData), EntityAuthorityInfo: &proto.EntityAuthorityInfo{ AbilityInfo: new(proto.AbilitySyncStateInfo), @@ -663,12 +668,22 @@ func (g *GameManager) PacketSceneEntityInfoGadget(scene *Scene, entityId uint32) BornPos: new(proto.Vector), }, } + switch entity.gadgetEntity.gadgetType { + case GADGET_TYPE_CLIENT: + sceneEntityInfo.Entity = &proto.SceneEntityInfo_Gadget{ + Gadget: g.PacketSceneGadgetInfoAbility(entity.gadgetEntity), + } + case GADGET_TYPE_GATHER: + sceneEntityInfo.Entity = &proto.SceneEntityInfo_Gadget{ + Gadget: g.PacketSceneGadgetInfoGather(entity.gadgetEntity), + } + default: + break + } return sceneEntityInfo } func (g *GameManager) PacketSceneAvatarInfo(scene *Scene, player *model.Player, avatarId uint32) *proto.SceneAvatarInfo { - avatar := player.AvatarMap[avatarId] - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) equipIdList := make([]uint32, 0) weapon := player.AvatarMap[avatarId].EquipWeapon equipIdList = append(equipIdList, weapon.ItemId) @@ -684,7 +699,7 @@ func (g *GameManager) PacketSceneAvatarInfo(scene *Scene, player *model.Player, EquipIdList: equipIdList, SkillDepotId: player.AvatarMap[avatarId].SkillDepotId, Weapon: &proto.SceneWeaponInfo{ - EntityId: playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId], + EntityId: scene.world.GetPlayerWorldAvatarWeaponEntityId(player, avatarId), GadgetId: uint32(gdc.CONF.ItemDataMap[int32(weapon.ItemId)].GadgetId), ItemId: weapon.ItemId, Guid: weapon.Guid, @@ -716,8 +731,8 @@ func (g *GameManager) PacketSceneMonsterInfo() *proto.SceneMonsterInfo { return sceneMonsterInfo } -func (g *GameManager) PacketSceneGadgetInfo(gatherId uint32) *proto.SceneGadgetInfo { - gather := gdc.CONF.GatherDataMap[int32(gatherId)] +func (g *GameManager) PacketSceneGadgetInfoGather(gadgetEntity *GadgetEntity) *proto.SceneGadgetInfo { + gather := gdc.CONF.GatherDataMap[int32(gadgetEntity.gatherId)] sceneGadgetInfo := &proto.SceneGadgetInfo{ GadgetId: uint32(gather.GadgetId), //GroupId: 133003011, @@ -735,11 +750,29 @@ func (g *GameManager) PacketSceneGadgetInfo(gatherId uint32) *proto.SceneGadgetI return sceneGadgetInfo } +func (g *GameManager) PacketSceneGadgetInfoAbility(gadgetEntity *GadgetEntity) *proto.SceneGadgetInfo { + sceneGadgetInfo := &proto.SceneGadgetInfo{ + GadgetId: gadgetEntity.configId, + OwnerEntityId: gadgetEntity.ownerEntityId, + AuthorityPeerId: 1, + IsEnableInteract: true, + Content: &proto.SceneGadgetInfo_ClientGadget{ + ClientGadget: &proto.ClientGadgetInfo{ + CampId: gadgetEntity.campId, + CampType: gadgetEntity.campType, + OwnerEntityId: gadgetEntity.ownerEntityId, + TargetEntityId: gadgetEntity.targetEntityId, + }, + }, + PropOwnerEntityId: gadgetEntity.propOwnerEntityId, + } + return sceneGadgetInfo +} + func (g *GameManager) PacketDelTeamEntityNotify(scene *Scene, player *model.Player) *proto.DelTeamEntityNotify { - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) delTeamEntityNotify := &proto.DelTeamEntityNotify{ SceneId: player.SceneId, - DelEntityIdList: []uint32{playerTeamEntity.teamEntityId}, + DelEntityIdList: []uint32{scene.world.GetPlayerTeamEntityId(player)}, } return delTeamEntityNotify } diff --git a/gs/game/user_stamina.go b/gs/game/user_stamina.go index c5883828..ef4950a2 100644 --- a/gs/game/user_stamina.go +++ b/gs/game/user_stamina.go @@ -11,6 +11,27 @@ import ( "time" ) +// HandleAbilityInvoke 处理能力调用 +func (g *GameManager) HandleAbilityInvoke(player *model.Player, entry *proto.AbilityInvokeEntry) { + //logger.LOG.Debug("ability invoke handle, entry: %v", entry.ArgumentType) + + switch entry.ArgumentType { + case proto.AbilityInvokeArgument_ABILITY_INVOKE_ARGUMENT_MIXIN_COST_STAMINA: + // 消耗耐力 + + //costStamina := new(proto.AbilityMixinCostStamina) + //err := pb.Unmarshal(entry.AbilityData, costStamina) + //if err != nil { + // logger.LOG.Error("unmarshal ability data err: %v", err) + // return + //} + + // 处理技能持续时的耐力消耗 + g.HandleSkillSustainStamina(player) + + } +} + // SceneAvatarStaminaStepReq 缓慢游泳或缓慢攀爬时消耗耐力 func (g *GameManager) SceneAvatarStaminaStepReq(player *model.Player, payloadMsg pb.Message) { req := payloadMsg.(*proto.SceneAvatarStaminaStepReq) diff --git a/gs/game/user_team.go b/gs/game/user_team.go index f9e4015b..7631f645 100644 --- a/gs/game/user_team.go +++ b/gs/game/user_team.go @@ -18,36 +18,32 @@ func (g *GameManager) ChangeAvatarReq(player *model.Player, payloadMsg pb.Messag targetAvatarGuid := req.Guid world := WORLD_MANAGER.GetWorldByID(player.WorldId) scene := world.GetSceneById(player.SceneId) - playerTeamEntity := scene.GetPlayerTeamEntity(player.PlayerID) + targetAvatarId := player.GetAvatarIdByGuid(targetAvatarGuid) oldAvatarId := world.GetPlayerActiveAvatarId(player) - oldAvatar := player.AvatarMap[oldAvatarId] - if oldAvatar.Guid == targetAvatarGuid { - logger.LOG.Error("can not change to the same avatar, uid: %v, oldAvatarId: %v, oldAvatarGuid: %v", player.PlayerID, oldAvatarId, oldAvatar.Guid) + if targetAvatarId == oldAvatarId { + logger.LOG.Error("can not change to the same avatar, uid: %v, oldAvatarId: %v, targetAvatarId: %v", player.PlayerID, oldAvatarId, targetAvatarId) return } - index := -1 - for avatarIndex, avatarId := range world.GetPlayerAvatarIdList(player) { - if targetAvatarGuid == player.AvatarMap[avatarId].Guid { - index = avatarIndex - } - } - if index == -1 { - logger.LOG.Error("can not find the target avatar in team, uid: %v, target avatar guid: %v", player.PlayerID, targetAvatarGuid) + newAvatarIndex := world.GetPlayerAvatarIndexByAvatarId(player, targetAvatarId) + if newAvatarIndex == -1 { + logger.LOG.Error("can not find the target avatar in team, uid: %v, targetAvatarId: %v", player.PlayerID, targetAvatarId) return } if !world.multiplayer { - player.TeamConfig.CurrAvatarIndex = uint8(index) + player.TeamConfig.CurrAvatarIndex = uint8(newAvatarIndex) } - world.SetPlayerLocalAvatarIndex(player, index) - entity := scene.GetEntity(playerTeamEntity.avatarEntityMap[oldAvatarId]) - if entity == nil { + world.SetPlayerAvatarIndex(player, newAvatarIndex) + oldAvatarEntityId := world.GetPlayerWorldAvatarEntityId(player, oldAvatarId) + oldAvatarEntity := scene.GetEntity(oldAvatarEntityId) + if oldAvatarEntity == nil { + logger.LOG.Error("can not find old avatar entity, entity id: %v", oldAvatarEntityId) return } - entity.moveState = uint16(proto.MotionState_MOTION_STATE_STANDBY) + oldAvatarEntity.moveState = uint16(proto.MotionState_MOTION_STATE_STANDBY) sceneEntityDisappearNotify := &proto.SceneEntityDisappearNotify{ DisappearType: proto.VisionType_VISION_TYPE_REPLACE, - EntityList: []uint32{playerTeamEntity.avatarEntityMap[oldAvatarId]}, + EntityList: []uint32{oldAvatarEntity.id}, } for _, scenePlayer := range scene.playerMap { g.SendMsg(cmd.SceneEntityDisappearNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, sceneEntityDisappearNotify) @@ -57,7 +53,7 @@ func (g *GameManager) ChangeAvatarReq(player *model.Player, payloadMsg pb.Messag newAvatarEntity := g.PacketSceneEntityInfoAvatar(scene, player, newAvatarId) sceneEntityAppearNotify := &proto.SceneEntityAppearNotify{ AppearType: proto.VisionType_VISION_TYPE_REPLACE, - Param: playerTeamEntity.avatarEntityMap[oldAvatarId], + Param: oldAvatarEntity.id, EntityList: []*proto.SceneEntityInfo{newAvatarEntity}, } for _, scenePlayer := range scene.playerMap { @@ -65,7 +61,6 @@ func (g *GameManager) ChangeAvatarReq(player *model.Player, payloadMsg pb.Messag } changeAvatarRsp := &proto.ChangeAvatarRsp{ - Retcode: int32(proto.Retcode_RET_SUCC), CurGuid: targetAvatarGuid, } g.SendMsg(cmd.ChangeAvatarRsp, player.PlayerID, player.ClientSeq, changeAvatarRsp) @@ -98,8 +93,7 @@ func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Mes } } } - player.TeamConfig.ClearTeamAvatar(uint8(teamId - 1)) - player.TeamConfig.SetTeamAvatar(uint8(teamId-1), avatarIdList) + player.TeamConfig.GetTeamByIndex(uint8(teamId - 1)).SetAvatarIdList(avatarIdList) avatarTeamUpdateNotify := &proto.AvatarTeamUpdateNotify{ AvatarTeamMap: make(map[uint32]*proto.AvatarTeam), @@ -117,27 +111,25 @@ func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Mes g.SendMsg(cmd.AvatarTeamUpdateNotify, player.PlayerID, player.ClientSeq, avatarTeamUpdateNotify) if selfTeam { - player.TeamConfig.CurrAvatarIndex = 0 - player.TeamConfig.UpdateTeam() - world.SetPlayerLocalAvatarIndex(player, 0) + //player.TeamConfig.UpdateTeam() world.SetPlayerLocalTeam(player, avatarIdList) world.UpdateMultiplayerTeam() - scene := world.GetSceneById(player.SceneId) - scene.UpdatePlayerTeamEntity(player) + world.InitPlayerWorldAvatar(player) + + currAvatarGuid := req.CurAvatarGuid + currAvatarId := player.GetAvatarIdByGuid(currAvatarGuid) + currAvatarIndex := world.GetPlayerAvatarIndexByAvatarId(player, currAvatarId) + player.TeamConfig.CurrAvatarIndex = uint8(currAvatarIndex) + world.SetPlayerAvatarIndex(player, currAvatarIndex) sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) g.SendMsg(cmd.SceneTeamUpdateNotify, player.PlayerID, player.ClientSeq, sceneTeamUpdateNotify) } - activeAvatarId := world.GetPlayerActiveAvatarId(player) setUpAvatarTeamRsp := &proto.SetUpAvatarTeamRsp{ - TeamId: teamId, - CurAvatarGuid: player.AvatarMap[activeAvatarId].Guid, - AvatarTeamGuidList: make([]uint64, 0), - } - team := player.TeamConfig.GetTeamByIndex(uint8(teamId - 1)) - for _, avatarId := range team.GetAvatarIdList() { - setUpAvatarTeamRsp.AvatarTeamGuidList = append(setUpAvatarTeamRsp.AvatarTeamGuidList, player.AvatarMap[avatarId].Guid) + TeamId: req.TeamId, + CurAvatarGuid: req.CurAvatarGuid, + AvatarTeamGuidList: req.AvatarTeamGuidList, } g.SendMsg(cmd.SetUpAvatarTeamRsp, player.PlayerID, player.ClientSeq, setUpAvatarTeamRsp) } @@ -157,12 +149,11 @@ func (g *GameManager) ChooseCurAvatarTeamReq(player *model.Player, payloadMsg pb } player.TeamConfig.CurrTeamIndex = uint8(teamId) - 1 player.TeamConfig.CurrAvatarIndex = 0 - player.TeamConfig.UpdateTeam() - world.SetPlayerLocalAvatarIndex(player, 0) + //player.TeamConfig.UpdateTeam() + world.SetPlayerAvatarIndex(player, 0) world.SetPlayerLocalTeam(player, team.GetAvatarIdList()) world.UpdateMultiplayerTeam() - scene := world.GetSceneById(player.SceneId) - scene.UpdatePlayerTeamEntity(player) + world.InitPlayerWorldAvatar(player) sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) g.SendMsg(cmd.SceneTeamUpdateNotify, player.PlayerID, player.ClientSeq, sceneTeamUpdateNotify) @@ -188,20 +179,21 @@ func (g *GameManager) ChangeMpTeamAvatarReq(player *model.Player, payloadMsg pb. avatarIdList = append(avatarIdList, avatarId) } world.SetPlayerLocalTeam(player, avatarIdList) - world.SetPlayerLocalAvatarIndex(player, 0) world.UpdateMultiplayerTeam() - scene := world.GetSceneById(player.SceneId) - scene.UpdatePlayerTeamEntity(player) + world.InitPlayerWorldAvatar(player) + + currAvatarGuid := req.CurAvatarGuid + currAvatarId := player.GetAvatarIdByGuid(currAvatarGuid) + newAvatarIndex := world.GetPlayerAvatarIndexByAvatarId(player, currAvatarId) + world.SetPlayerAvatarIndex(player, newAvatarIndex) for _, worldPlayer := range world.playerMap { sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) g.SendMsg(cmd.SceneTeamUpdateNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneTeamUpdateNotify) } - avatarId := world.GetPlayerActiveAvatarId(player) - avatar := player.AvatarMap[avatarId] changeMpTeamAvatarRsp := &proto.ChangeMpTeamAvatarRsp{ - CurAvatarGuid: avatar.Guid, + CurAvatarGuid: req.CurAvatarGuid, AvatarGuidList: req.AvatarGuidList, } g.SendMsg(cmd.ChangeMpTeamAvatarRsp, player.PlayerID, player.ClientSeq, changeMpTeamAvatarRsp) @@ -212,11 +204,10 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam IsInMp: world.multiplayer, } empty := new(proto.AbilitySyncStateInfo) - for _, worldTeamAvatar := range world.GetWorldTeamAvatarList() { - worldPlayer := USER_MANAGER.GetOnlineUser(worldTeamAvatar.uid) + for _, worldAvatar := range world.GetWorldAvatarList() { + worldPlayer := USER_MANAGER.GetOnlineUser(worldAvatar.uid) worldPlayerScene := world.GetSceneById(worldPlayer.SceneId) - worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) - worldPlayerAvatar := worldPlayer.AvatarMap[worldTeamAvatar.avatarId] + worldPlayerAvatar := worldPlayer.AvatarMap[worldAvatar.avatarId] equipIdList := make([]uint32, 0) weapon := worldPlayerAvatar.EquipWeapon equipIdList = append(equipIdList, weapon.ItemId) @@ -224,25 +215,32 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam equipIdList = append(equipIdList, reliquary.ItemId) } sceneTeamAvatar := &proto.SceneTeamAvatar{ - PlayerUid: worldPlayer.PlayerID, - AvatarGuid: worldPlayerAvatar.Guid, - SceneId: worldPlayer.SceneId, - EntityId: worldPlayerTeamEntity.avatarEntityMap[worldTeamAvatar.avatarId], - SceneEntityInfo: g.PacketSceneEntityInfoAvatar(worldPlayerScene, worldPlayer, worldTeamAvatar.avatarId), - WeaponGuid: worldPlayerAvatar.EquipWeapon.Guid, - WeaponEntityId: worldPlayerTeamEntity.weaponEntityMap[worldPlayerAvatar.EquipWeapon.WeaponId], - IsPlayerCurAvatar: world.GetPlayerActiveAvatarId(worldPlayer) == worldTeamAvatar.avatarId, - IsOnScene: world.GetPlayerActiveAvatarId(worldPlayer) == worldTeamAvatar.avatarId, - AvatarAbilityInfo: empty, + PlayerUid: worldPlayer.PlayerID, + AvatarGuid: worldPlayerAvatar.Guid, + SceneId: worldPlayer.SceneId, + EntityId: world.GetPlayerWorldAvatarEntityId(worldPlayer, worldAvatar.avatarId), + SceneEntityInfo: g.PacketSceneEntityInfoAvatar(worldPlayerScene, worldPlayer, worldAvatar.avatarId), + WeaponGuid: worldPlayerAvatar.EquipWeapon.Guid, + WeaponEntityId: world.GetPlayerWorldAvatarWeaponEntityId(worldPlayer, worldAvatar.avatarId), + IsPlayerCurAvatar: world.GetPlayerActiveAvatarId(worldPlayer) == worldAvatar.avatarId, + IsOnScene: world.GetPlayerActiveAvatarId(worldPlayer) == worldAvatar.avatarId, + AvatarAbilityInfo: &proto.AbilitySyncStateInfo{ + IsInited: len(worldAvatar.abilityList) != 0, + DynamicValueMap: nil, + AppliedAbilities: worldAvatar.abilityList, + AppliedModifiers: worldAvatar.modifierList, + MixinRecoverInfos: nil, + SgvDynamicValueMap: nil, + }, WeaponAbilityInfo: empty, AbilityControlBlock: new(proto.AbilityControlBlock), } if world.multiplayer { sceneTeamAvatar.AvatarInfo = g.PacketAvatarInfo(worldPlayerAvatar) - sceneTeamAvatar.SceneAvatarInfo = g.PacketSceneAvatarInfo(worldPlayerScene, worldPlayer, worldTeamAvatar.avatarId) + sceneTeamAvatar.SceneAvatarInfo = g.PacketSceneAvatarInfo(worldPlayerScene, worldPlayer, worldAvatar.avatarId) } // add AbilityControlBlock - avatarDataConfig := gdc.CONF.AvatarDataMap[int32(worldTeamAvatar.avatarId)] + avatarDataConfig := gdc.CONF.AvatarDataMap[int32(worldAvatar.avatarId)] acb := sceneTeamAvatar.AbilityControlBlock embryoId := 0 // add avatar abilities diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index 4634edca..6e45995b 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -8,11 +8,7 @@ import ( "hk4e/gs/game/aoi" "hk4e/gs/model" "hk4e/pkg/alg" - "hk4e/pkg/logger" - "hk4e/protocol/cmd" "hk4e/protocol/proto" - - pb "google.golang.org/protobuf/proto" ) // 世界管理器 @@ -123,9 +119,23 @@ type World struct { } func (w *World) GetNextWorldEntityId(entityType uint16) uint32 { - w.entityIdCounter++ - ret := (uint32(entityType) << 24) + w.entityIdCounter - return ret + for { + w.entityIdCounter++ + ret := (uint32(entityType) << 24) + w.entityIdCounter + reTry := false + for _, scene := range w.sceneMap { + _, exist := scene.entityMap[ret] + if exist { + reTry = true + break + } + } + if reTry { + continue + } else { + return ret + } + } } // GetPlayerPeerId 获取当前玩家世界内编号 @@ -160,11 +170,12 @@ func (w *World) AddPlayer(player *model.Player, sceneId uint32) { w.SetPlayerLocalTeam(player, []uint32{activeAvatarId}) } for _, worldPlayer := range w.playerMap { - w.SetPlayerLocalAvatarIndex(worldPlayer, 0) + w.SetPlayerAvatarIndex(worldPlayer, 0) } w.UpdateMultiplayerTeam() scene := w.GetSceneById(sceneId) scene.AddPlayer(player) + w.InitPlayerTeamEntityId(player) } func (w *World) RemovePlayer(player *model.Player) { @@ -175,13 +186,136 @@ func (w *World) RemovePlayer(player *model.Player) { delete(w.playerFirstEnterMap, player.PlayerID) delete(w.multiplayerTeam.localTeamMap, player.PlayerID) delete(w.multiplayerTeam.localAvatarIndexMap, player.PlayerID) + delete(w.multiplayerTeam.localTeamEntityMap, player.PlayerID) w.UpdateMultiplayerTeam() } -// WorldAvatar 通用世界角色 +// WorldAvatar 世界角色 type WorldAvatar struct { - uid uint32 - avatarId uint32 + uid uint32 + avatarId uint32 + avatarEntityId uint32 + weaponEntityId uint32 + abilityList []*proto.AbilityAppliedAbility + modifierList []*proto.AbilityAppliedModifier +} + +// GetWorldAvatarList 获取世界队伍的全部角色列表 +func (w *World) GetWorldAvatarList() []*WorldAvatar { + worldAvatarList := make([]*WorldAvatar, 0) + for _, worldAvatar := range w.multiplayerTeam.worldTeam { + if worldAvatar.uid == 0 { + continue + } + worldAvatarList = append(worldAvatarList, worldAvatar) + } + return worldAvatarList +} + +// GetPlayerWorldAvatar 获取某玩家在世界队伍中的某角色 +func (w *World) GetPlayerWorldAvatar(player *model.Player, avatarId uint32) *WorldAvatar { + for _, worldAvatar := range w.GetWorldAvatarList() { + if worldAvatar.uid == player.PlayerID && worldAvatar.avatarId == avatarId { + return worldAvatar + } + } + return nil +} + +// GetPlayerWorldAvatarList 获取某玩家在世界队伍中的所有角色列表 +func (w *World) GetPlayerWorldAvatarList(player *model.Player) []*WorldAvatar { + worldAvatarList := make([]*WorldAvatar, 0) + for _, worldAvatar := range w.GetWorldAvatarList() { + if worldAvatar.uid == player.PlayerID { + worldAvatarList = append(worldAvatarList, worldAvatar) + } + } + return worldAvatarList +} + +// GetWorldAvatarByEntityId 通过场景实体id获取世界队伍中的角色 +func (w *World) GetWorldAvatarByEntityId(avatarEntityId uint32) *WorldAvatar { + for _, worldAvatar := range w.GetWorldAvatarList() { + if worldAvatar.avatarEntityId == avatarEntityId { + return worldAvatar + } + } + return nil +} + +// InitPlayerWorldAvatar 初始化某玩家在世界队伍中的所有角色 +func (w *World) InitPlayerWorldAvatar(player *model.Player) { + scene := w.GetSceneById(player.SceneId) + for _, worldAvatar := range w.GetWorldAvatarList() { + if worldAvatar.uid != player.PlayerID { + continue + } + if worldAvatar.avatarEntityId != 0 || worldAvatar.weaponEntityId != 0 { + continue + } + worldAvatar.avatarEntityId = scene.CreateEntityAvatar(player, worldAvatar.avatarId) + worldAvatar.weaponEntityId = scene.CreateEntityWeapon() + } +} + +// GetPlayerTeamEntityId 获取某玩家的本地队伍实体id +func (w *World) GetPlayerTeamEntityId(player *model.Player) uint32 { + return w.multiplayerTeam.localTeamEntityMap[player.PlayerID] +} + +// InitPlayerTeamEntityId 初始化某玩家的本地队伍实体id +func (w *World) InitPlayerTeamEntityId(player *model.Player) { + w.multiplayerTeam.localTeamEntityMap[player.PlayerID] = w.GetNextWorldEntityId(constant.EntityIdTypeConst.TEAM) +} + +// GetPlayerWorldAvatarEntityId 获取某玩家在世界队伍中的某角色的实体id +func (w *World) GetPlayerWorldAvatarEntityId(player *model.Player, avatarId uint32) uint32 { + worldAvatar := w.GetPlayerWorldAvatar(player, avatarId) + if worldAvatar == nil { + return 0 + } + return worldAvatar.avatarEntityId +} + +// GetPlayerWorldAvatarWeaponEntityId 获取某玩家在世界队伍中的某角色的武器的实体id +func (w *World) GetPlayerWorldAvatarWeaponEntityId(player *model.Player, avatarId uint32) uint32 { + worldAvatar := w.GetPlayerWorldAvatar(player, avatarId) + if worldAvatar == nil { + return 0 + } + return worldAvatar.weaponEntityId +} + +// GetPlayerAvatarIndex 获取某玩家当前角色索引 +func (w *World) GetPlayerAvatarIndex(player *model.Player) int { + return w.multiplayerTeam.localAvatarIndexMap[player.PlayerID] +} + +// SetPlayerAvatarIndex 设置某玩家当前角色索引 +func (w *World) SetPlayerAvatarIndex(player *model.Player, index int) { + if index > len(w.GetPlayerLocalTeam(player))-1 { + return + } + w.multiplayerTeam.localAvatarIndexMap[player.PlayerID] = index +} + +// GetPlayerActiveAvatarId 获取玩家当前活跃角色id +func (w *World) GetPlayerActiveAvatarId(player *model.Player) uint32 { + avatarIndex := w.GetPlayerAvatarIndex(player) + localTeam := w.GetPlayerLocalTeam(player) + worldTeamAvatar := localTeam[avatarIndex] + return worldTeamAvatar.avatarId +} + +// GetPlayerAvatarIndexByAvatarId 获取玩家某角色的索引 +func (w *World) GetPlayerAvatarIndexByAvatarId(player *model.Player, avatarId uint32) int { + localTeam := w.GetPlayerLocalTeam(player) + for index, worldAvatar := range localTeam { + if worldAvatar.avatarId == avatarId { + return index + } + } + return -1 } type MultiplayerTeam struct { @@ -189,6 +323,7 @@ type MultiplayerTeam struct { localTeamMap map[uint32][]*WorldAvatar // key:uid value:玩家当前角色索引 localAvatarIndexMap map[uint32]int + localTeamEntityMap map[uint32]uint32 // 最终的世界队伍 worldTeam []*WorldAvatar } @@ -197,6 +332,7 @@ func CreateMultiplayerTeam() (r *MultiplayerTeam) { r = new(MultiplayerTeam) r.localTeamMap = make(map[uint32][]*WorldAvatar) r.localAvatarIndexMap = make(map[uint32]int) + r.localTeamEntityMap = make(map[uint32]uint32) r.worldTeam = make([]*WorldAvatar, 0) return r } @@ -206,74 +342,71 @@ func (w *World) GetPlayerLocalTeam(player *model.Player) []*WorldAvatar { } func (w *World) SetPlayerLocalTeam(player *model.Player, avatarIdList []uint32) { - localTeam := make([]*WorldAvatar, 4) - for index := 0; index < 4; index++ { - if index > len(avatarIdList)-1 { - localTeam[index] = &WorldAvatar{ - uid: 0, - avatarId: 0, + oldLocalTeam := w.multiplayerTeam.localTeamMap[player.PlayerID] + sameAvatarIdList := make([]uint32, 0) + diffAvatarIdList := make([]uint32, 0) + for _, avatarId := range avatarIdList { + exist := false + for _, worldAvatar := range oldLocalTeam { + if worldAvatar.avatarId == avatarId { + exist = true } + } + if exist { + sameAvatarIdList = append(sameAvatarIdList, avatarId) } else { - avatarId := avatarIdList[index] - localTeam[index] = &WorldAvatar{ - uid: player.PlayerID, - avatarId: avatarId, + diffAvatarIdList = append(diffAvatarIdList, avatarId) + } + } + newLocalTeam := make([]*WorldAvatar, len(avatarIdList)) + for _, avatarId := range sameAvatarIdList { + for _, worldAvatar := range oldLocalTeam { + if worldAvatar.avatarId == avatarId { + index := 0 + for i, v := range avatarIdList { + if avatarId == v { + index = i + } + } + newLocalTeam[index] = worldAvatar } } } - w.multiplayerTeam.localTeamMap[player.PlayerID] = localTeam -} - -func (w *World) ClearPlayerLocalTeam(player *model.Player) { - w.multiplayerTeam.localTeamMap[player.PlayerID] = make([]*WorldAvatar, 4) -} - -func (w *World) GetPlayerLocalAvatarIndex(player *model.Player) int { - return w.multiplayerTeam.localAvatarIndexMap[player.PlayerID] -} - -func (w *World) SetPlayerLocalAvatarIndex(player *model.Player, index int) { - if index > len(w.GetPlayerLocalTeam(player))-1 { - return - } - w.multiplayerTeam.localAvatarIndexMap[player.PlayerID] = index -} - -func (w *World) GetPlayerActiveAvatarId(player *model.Player) uint32 { - avatarIndex := w.GetPlayerLocalAvatarIndex(player) - localTeam := w.GetPlayerLocalTeam(player) - worldTeamAvatar := localTeam[avatarIndex] - return worldTeamAvatar.avatarId -} - -func (w *World) GetPlayerAvatarIdList(player *model.Player) []uint32 { - localTeam := w.GetPlayerLocalTeam(player) - avatarIdList := make([]uint32, 0) - for _, worldAvatar := range localTeam { - if worldAvatar.avatarId == 0 { - continue + for _, avatarId := range diffAvatarIdList { + index := 0 + for i, v := range avatarIdList { + if avatarId == v { + index = i + } } - avatarIdList = append(avatarIdList, worldAvatar.avatarId) - } - return avatarIdList -} - -func (w *World) GetWorldTeamAvatarList() []*WorldAvatar { - worldAvatarList := make([]*WorldAvatar, 0) - for _, worldAvatar := range w.multiplayerTeam.worldTeam { - if worldAvatar.avatarId == 0 { - continue + newLocalTeam[index] = &WorldAvatar{ + uid: player.PlayerID, + avatarId: avatarId, + avatarEntityId: 0, + weaponEntityId: 0, + abilityList: make([]*proto.AbilityAppliedAbility, 0), + modifierList: make([]*proto.AbilityAppliedModifier, 0), } - worldAvatarList = append(worldAvatarList, worldAvatar) } - return worldAvatarList + w.multiplayerTeam.localTeamMap[player.PlayerID] = newLocalTeam } func (w *World) copyLocalTeamToWorld(start int, end int, peerId uint32) { + player := w.peerMap[peerId] + localTeam := w.GetPlayerLocalTeam(player) localTeamIndex := 0 for index := start; index <= end; index++ { - player := w.peerMap[peerId] - localTeam := w.GetPlayerLocalTeam(player) + if localTeamIndex >= len(localTeam) { + w.multiplayerTeam.worldTeam[index] = &WorldAvatar{ + uid: 0, + avatarId: 0, + avatarEntityId: 0, + weaponEntityId: 0, + abilityList: nil, + modifierList: nil, + } + continue + } w.multiplayerTeam.worldTeam[index] = localTeam[localTeamIndex] localTeamIndex++ } @@ -337,15 +470,13 @@ func (w *World) PlayerEnter(player *model.Player) { func (w *World) CreateScene(sceneId uint32) *Scene { scene := &Scene{ - id: sceneId, - world: w, - playerMap: make(map[uint32]*model.Player), - entityMap: make(map[uint32]*Entity), - playerTeamEntityMap: make(map[uint32]*PlayerTeamEntity), - gameTime: 18 * 60, - attackQueue: alg.NewRAQueue[*Attack](1000), - createTime: time.Now().UnixMilli(), - meeoIndex: 0, + id: sceneId, + world: w, + playerMap: make(map[uint32]*model.Player), + entityMap: make(map[uint32]*Entity), + gameTime: 18 * 60, + createTime: time.Now().UnixMilli(), + meeoIndex: 0, } w.sceneMap[sceneId] = scene return scene @@ -362,15 +493,13 @@ func (w *World) GetSceneById(sceneId uint32) *Scene { // 场景数据结构 type Scene struct { - id uint32 - world *World - playerMap map[uint32]*model.Player - entityMap map[uint32]*Entity - playerTeamEntityMap map[uint32]*PlayerTeamEntity - gameTime uint32 // 游戏内提瓦特大陆的时间 - attackQueue *alg.RAQueue[*Attack] - createTime int64 - meeoIndex uint32 // 客户端风元素染色同步协议的计数器 + id uint32 + world *World + playerMap map[uint32]*model.Player + entityMap map[uint32]*Entity + gameTime uint32 // 游戏内提瓦特大陆的时间 + createTime int64 + meeoIndex uint32 // 客户端风元素染色同步协议的计数器 } type AvatarEntity struct { @@ -381,8 +510,20 @@ type AvatarEntity struct { type MonsterEntity struct { } +const ( + GADGET_TYPE_CLIENT = iota + GADGET_TYPE_GATHER +) + type GadgetEntity struct { - gatherId uint32 + gadgetType int + gatherId uint32 + configId uint32 + campId uint32 + campType uint32 + ownerEntityId uint32 + targetEntityId uint32 + propOwnerEntityId uint32 } // 场景实体数据结构 @@ -403,12 +544,6 @@ type Entity struct { gadgetEntity *GadgetEntity } -type PlayerTeamEntity struct { - teamEntityId uint32 - avatarEntityMap map[uint32]uint32 - weaponEntityMap map[uint64]uint32 -} - type Attack struct { combatInvokeEntry *proto.CombatInvokeEntry uid uint32 @@ -427,55 +562,18 @@ func (s *Scene) GetSceneTime() int64 { return now - s.createTime } -func (s *Scene) GetPlayerTeamEntity(userId uint32) *PlayerTeamEntity { - return s.playerTeamEntityMap[userId] -} - -func (s *Scene) CreatePlayerTeamEntity(player *model.Player) { - playerTeamEntity := &PlayerTeamEntity{ - teamEntityId: s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.TEAM), - avatarEntityMap: make(map[uint32]uint32), - weaponEntityMap: make(map[uint64]uint32), - } - s.playerTeamEntityMap[player.PlayerID] = playerTeamEntity -} - -func (s *Scene) UpdatePlayerTeamEntity(player *model.Player) { - playerTeamEntity := s.playerTeamEntityMap[player.PlayerID] - for _, worldTeamAvatar := range s.world.GetWorldTeamAvatarList() { - if worldTeamAvatar.uid != player.PlayerID { - continue - } - avatar := player.AvatarMap[worldTeamAvatar.avatarId] - avatarEntityId, exist := playerTeamEntity.avatarEntityMap[worldTeamAvatar.avatarId] - if exist { - s.DestroyEntity(avatarEntityId) - } - playerTeamEntity.avatarEntityMap[worldTeamAvatar.avatarId] = s.CreateEntityAvatar(player, worldTeamAvatar.avatarId) - weaponEntityId, exist := playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId] - if exist { - s.DestroyEntity(weaponEntityId) - } - playerTeamEntity.weaponEntityMap[avatar.EquipWeapon.WeaponId] = s.CreateEntityWeapon() - } -} - func (s *Scene) AddPlayer(player *model.Player) { s.playerMap[player.PlayerID] = player - s.CreatePlayerTeamEntity(player) - s.UpdatePlayerTeamEntity(player) + s.world.InitPlayerWorldAvatar(player) } func (s *Scene) RemovePlayer(player *model.Player) { - playerTeamEntity := s.GetPlayerTeamEntity(player.PlayerID) - for _, avatarEntityId := range playerTeamEntity.avatarEntityMap { - s.DestroyEntity(avatarEntityId) - } - for _, weaponEntityId := range playerTeamEntity.weaponEntityMap { - s.DestroyEntity(weaponEntityId) - } - delete(s.playerTeamEntityMap, player.PlayerID) delete(s.playerMap, player.PlayerID) + worldAvatarList := s.world.GetPlayerWorldAvatarList(player) + for _, worldAvatar := range worldAvatarList { + s.DestroyEntity(worldAvatar.avatarEntityId) + s.DestroyEntity(worldAvatar.weaponEntityId) + } } func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 { @@ -540,6 +638,36 @@ func (s *Scene) CreateEntityMonster(pos *model.Vector, level uint8, fightProp ma return entity.id } +func (s *Scene) ClientCreateEntityGadget(pos, rot *model.Vector, entityId uint32, configId, campId, campType, ownerEntityId, targetEntityId, propOwnerEntityId uint32) { + entity := &Entity{ + id: entityId, + scene: s, + pos: pos, + rot: rot, + moveState: uint16(proto.MotionState_MOTION_STATE_NONE), + lastMoveSceneTimeMs: 0, + lastMoveReliableSeq: 0, + fightProp: map[uint32]float32{ + uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP): math.MaxFloat32, + uint32(constant.FightPropertyConst.FIGHT_PROP_MAX_HP): math.MaxFloat32, + uint32(constant.FightPropertyConst.FIGHT_PROP_BASE_HP): float32(1), + }, + entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET), + level: 0, + gadgetEntity: &GadgetEntity{ + gadgetType: GADGET_TYPE_CLIENT, + configId: configId, + campId: campId, + campType: campType, + ownerEntityId: ownerEntityId, + targetEntityId: targetEntityId, + propOwnerEntityId: propOwnerEntityId, + }, + } + s.entityMap[entity.id] = entity + s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z)) +} + func (s *Scene) CreateEntityGadget(pos *model.Vector, gatherId uint32) uint32 { entityId := s.world.GetNextWorldEntityId(constant.EntityIdTypeConst.GADGET) entity := &Entity{ @@ -558,7 +686,8 @@ func (s *Scene) CreateEntityGadget(pos *model.Vector, gatherId uint32) uint32 { entityType: uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_GADGET), level: 0, gadgetEntity: &GadgetEntity{ - gatherId: gatherId, + gadgetType: GADGET_TYPE_GATHER, + gatherId: gatherId, }, } s.entityMap[entity.id] = entity @@ -586,106 +715,3 @@ func (s *Scene) GetEntityIdList() []uint32 { } return entityIdList } - -// 伤害处理和转发 - -func (s *Scene) AddAttack(attack *Attack) { - s.attackQueue.EnQueue(attack) -} - -func (s *Scene) AttackHandler(gameManager *GameManager) { - combatInvokeEntryListAll := make([]*proto.CombatInvokeEntry, 0) - combatInvokeEntryListOther := make(map[uint32][]*proto.CombatInvokeEntry) - combatInvokeEntryListHost := make([]*proto.CombatInvokeEntry, 0) - - for s.attackQueue.Len() != 0 { - attack := s.attackQueue.DeQueue() - if attack.combatInvokeEntry == nil { - logger.LOG.Error("error attack data, attack value: %v", attack) - continue - } - - hitInfo := new(proto.EvtBeingHitInfo) - err := pb.Unmarshal(attack.combatInvokeEntry.CombatData, hitInfo) - if err != nil { - logger.LOG.Error("parse combat invocations entity hit info error: %v", err) - continue - } - - attackResult := hitInfo.AttackResult - logger.LOG.Debug("run attack handler, attackResult: %v", attackResult) - target := s.entityMap[attackResult.DefenseId] - if target == nil { - logger.LOG.Error("could not found target, defense id: %v", attackResult.DefenseId) - continue - } - attackResult.Damage *= 100 - damage := attackResult.Damage - attackerId := attackResult.AttackerId - _ = attackerId - currHp := float32(0) - if target.fightProp != nil { - currHp = target.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] - currHp -= damage - if currHp < 0 { - currHp = 0 - } - target.fightProp[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp - } - - // PacketEntityFightPropUpdateNotify - entityFightPropUpdateNotify := new(proto.EntityFightPropUpdateNotify) - entityFightPropUpdateNotify.EntityId = target.id - entityFightPropUpdateNotify.FightPropMap = make(map[uint32]float32) - entityFightPropUpdateNotify.FightPropMap[uint32(constant.FightPropertyConst.FIGHT_PROP_CUR_HP)] = currHp - for _, player := range s.playerMap { - gameManager.SendMsg(cmd.EntityFightPropUpdateNotify, player.PlayerID, player.ClientSeq, entityFightPropUpdateNotify) - } - - combatData, err := pb.Marshal(hitInfo) - if err != nil { - logger.LOG.Error("create combat invocations entity hit info error: %v", err) - } - attack.combatInvokeEntry.CombatData = combatData - switch attack.combatInvokeEntry.ForwardType { - case proto.ForwardType_FORWARD_TYPE_TO_ALL: - combatInvokeEntryListAll = append(combatInvokeEntryListAll, attack.combatInvokeEntry) - case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXCEPT_CUR: - fallthrough - case proto.ForwardType_FORWARD_TYPE_TO_ALL_EXIST_EXCEPT_CUR: - if combatInvokeEntryListOther[attack.uid] == nil { - combatInvokeEntryListOther[attack.uid] = make([]*proto.CombatInvokeEntry, 0) - } - combatInvokeEntryListOther[attack.uid] = append(combatInvokeEntryListOther[attack.uid], attack.combatInvokeEntry) - case proto.ForwardType_FORWARD_TYPE_TO_HOST: - combatInvokeEntryListHost = append(combatInvokeEntryListHost, attack.combatInvokeEntry) - default: - } - } - - // PacketCombatInvocationsNotify - if len(combatInvokeEntryListAll) > 0 { - combatInvocationsNotifyAll := new(proto.CombatInvocationsNotify) - combatInvocationsNotifyAll.InvokeList = combatInvokeEntryListAll - for _, player := range s.playerMap { - gameManager.SendMsg(cmd.CombatInvocationsNotify, player.PlayerID, player.ClientSeq, combatInvocationsNotifyAll) - } - } - if len(combatInvokeEntryListOther) > 0 { - for uid, list := range combatInvokeEntryListOther { - combatInvocationsNotifyOther := new(proto.CombatInvocationsNotify) - combatInvocationsNotifyOther.InvokeList = list - for _, player := range s.playerMap { - if player.PlayerID == uid { - continue - } - gameManager.SendMsg(cmd.CombatInvocationsNotify, player.PlayerID, player.ClientSeq, combatInvocationsNotifyOther) - } - } - } - if len(combatInvokeEntryListHost) > 0 { - combatInvocationsNotifyHost := new(proto.CombatInvocationsNotify) - combatInvocationsNotifyHost.InvokeList = combatInvokeEntryListHost - gameManager.SendMsg(cmd.CombatInvocationsNotify, s.world.owner.PlayerID, s.world.owner.ClientSeq, combatInvocationsNotifyHost) - } -} diff --git a/gs/model/invoke_handler.go b/gs/model/invoke_handler.go index 1585f3fc..035d2318 100644 --- a/gs/model/invoke_handler.go +++ b/gs/model/invoke_handler.go @@ -7,18 +7,18 @@ import ( // 泛型通用转发器 -type InvokeType interface { +type InvokeEntryType interface { proto.CombatInvokeEntry | proto.AbilityInvokeEntry } -type InvokeHandler[T InvokeType] struct { +type InvokeHandler[T InvokeEntryType] struct { EntryListForwardAll []*T EntryListForwardAllExceptCur []*T EntryListForwardHost []*T EntryListForwardServer []*T } -func NewInvokeHandler[T InvokeType]() (r *InvokeHandler[T]) { +func NewInvokeHandler[T InvokeEntryType]() (r *InvokeHandler[T]) { r = new(InvokeHandler[T]) r.InitInvokeHandler() return r diff --git a/gs/model/player.go b/gs/model/player.go index e45be3bf..80f900dd 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -28,7 +28,7 @@ type Player struct { NickName string `bson:"nickname"` // 玩家昵称 Signature string `bson:"signature"` // 玩家签名 HeadImage uint32 `bson:"headImage"` // 玩家头像 - Birthday [2]uint8 `bson:"birthday"` // 生日 + Birthday []uint8 `bson:"birthday"` // 生日 NameCard uint32 `bson:"nameCard"` // 当前名片 NameCardList []uint32 `bson:"nameCardList"` // 已解锁名片列表 FriendList map[uint32]bool `bson:"friendList"` // 好友uid列表 diff --git a/gs/model/team.go b/gs/model/team.go index 15b68d02..c8e43d0d 100644 --- a/gs/model/team.go +++ b/gs/model/team.go @@ -6,8 +6,8 @@ import ( ) type Team struct { - Name string `bson:"name"` - AvatarIdList []uint32 `bson:"avatarIdList"` + Name string `bson:"name"` + AvatarIdList [4]uint32 `bson:"avatarIdList"` } func (t *Team) GetAvatarIdList() []uint32 { @@ -21,6 +21,16 @@ func (t *Team) GetAvatarIdList() []uint32 { return avatarIdList } +func (t *Team) SetAvatarIdList(avatarIdList []uint32) { + t.AvatarIdList = [4]uint32{0, 0, 0, 0} + for index := range t.AvatarIdList { + if index >= len(avatarIdList) { + break + } + t.AvatarIdList[index] = avatarIdList[index] + } +} + type TeamInfo struct { TeamList []*Team `bson:"teamList"` CurrTeamIndex uint8 `bson:"currTeamIndex"` @@ -32,10 +42,10 @@ type TeamInfo struct { func NewTeamInfo() (r *TeamInfo) { r = &TeamInfo{ TeamList: []*Team{ - {Name: "冒险", AvatarIdList: make([]uint32, 4)}, - {Name: "委托", AvatarIdList: make([]uint32, 4)}, - {Name: "秘境", AvatarIdList: make([]uint32, 4)}, - {Name: "联机", AvatarIdList: make([]uint32, 4)}, + {Name: "冒险", AvatarIdList: [4]uint32{0, 0, 0, 0}}, + {Name: "委托", AvatarIdList: [4]uint32{0, 0, 0, 0}}, + {Name: "秘境", AvatarIdList: [4]uint32{0, 0, 0, 0}}, + {Name: "联机", AvatarIdList: [4]uint32{0, 0, 0, 0}}, }, CurrTeamIndex: 0, CurrAvatarIndex: 0, @@ -90,22 +100,6 @@ func (t *TeamInfo) GetActiveTeam() *Team { return t.GetTeamByIndex(t.CurrTeamIndex) } -func (t *TeamInfo) ClearTeamAvatar(teamIndex uint8) { - team := t.GetTeamByIndex(teamIndex) - if team == nil { - return - } - team.AvatarIdList = make([]uint32, 4) -} - -func (t *TeamInfo) SetTeamAvatar(teamIndex uint8, avatarIdList []uint32) { - team := t.GetTeamByIndex(teamIndex) - if team == nil { - return - } - team.AvatarIdList = avatarIdList -} - func (t *TeamInfo) GetActiveAvatarId() uint32 { team := t.GetActiveTeam() if team == nil { diff --git a/pkg/reflection/struct.go b/pkg/reflection/struct.go index 13c0c770..1ee6f909 100644 --- a/pkg/reflection/struct.go +++ b/pkg/reflection/struct.go @@ -26,6 +26,24 @@ func ConvStructToMap(value any) map[string]any { return result } +func GetStructFieldValue(structPointer any, fieldName string) (bool, any) { + refType := reflect.TypeOf(structPointer) + if refType.Kind() != reflect.Ptr { + return false, nil + } + refType = refType.Elem() + if refType.Kind() != reflect.Struct { + return false, nil + } + refValue := reflect.ValueOf(structPointer) + if refValue.Kind() != reflect.Ptr { + return false, nil + } + refValue = refValue.Elem() + field := refValue.FieldByName(fieldName) + return true, field.Interface() +} + func SetStructFieldValue(structPointer any, fieldName string, value any) bool { refType := reflect.TypeOf(structPointer) if refType.Kind() != reflect.Ptr { @@ -47,3 +65,15 @@ func SetStructFieldValue(structPointer any, fieldName string, value any) bool { field.Set(reflect.ValueOf(value)) return true } + +func CopyStructField(dst any, src any, fieldName string) bool { + ok, value := GetStructFieldValue(src, fieldName) + if !ok { + return false + } + ok = SetStructFieldValue(dst, fieldName, value) + if !ok { + return false + } + return true +} diff --git a/protocol/cmd/cmd_id_proto_obj_map.go b/protocol/cmd/cmd_id_proto_obj_map.go index 2c446989..a7776132 100644 --- a/protocol/cmd/cmd_id_proto_obj_map.go +++ b/protocol/cmd/cmd_id_proto_obj_map.go @@ -98,7 +98,7 @@ func (c *CmdProtoMap) registerAllMessage() { c.registerMessage(SceneAvatarStaminaStepReq, &proto.SceneAvatarStaminaStepReq{}) // 缓慢游泳或缓慢攀爬时消耗耐力请求 c.registerMessage(SceneAvatarStaminaStepRsp, &proto.SceneAvatarStaminaStepRsp{}) // 缓慢游泳或缓慢攀爬时消耗耐力响应 - // 战斗与技能 + // 战斗与同步 c.registerMessage(AvatarFightPropNotify, &proto.AvatarFightPropNotify{}) // 角色战斗属性通知 c.registerMessage(EntityFightPropUpdateNotify, &proto.EntityFightPropUpdateNotify{}) // 实体战斗属性更新通知 c.registerMessage(CombatInvocationsNotify, &proto.CombatInvocationsNotify{}) // 战斗通知 包含场景中实体的移动数据和伤害数据,多人游戏服务器转发 @@ -106,7 +106,13 @@ func (c *CmdProtoMap) registerAllMessage() { c.registerMessage(ClientAbilityInitFinishNotify, &proto.ClientAbilityInitFinishNotify{}) // 客户端技能初始化完成通知 多人游戏服务器转发 c.registerMessage(EvtDoSkillSuccNotify, &proto.EvtDoSkillSuccNotify{}) // 释放技能成功事件通知 c.registerMessage(ClientAbilityChangeNotify, &proto.ClientAbilityChangeNotify{}) // 客户端技能改变通知 - c.registerMessage(MassiveEntityElementOpBatchNotify, &proto.MassiveEntityElementOpBatchNotify{}) // MEEO通知 风元素染色 + c.registerMessage(MassiveEntityElementOpBatchNotify, &proto.MassiveEntityElementOpBatchNotify{}) // 风元素染色相关通知 + c.registerMessage(EvtAvatarEnterFocusNotify, &proto.EvtAvatarEnterFocusNotify{}) // 进入弓箭蓄力瞄准状态通知 + c.registerMessage(EvtAvatarUpdateFocusNotify, &proto.EvtAvatarUpdateFocusNotify{}) // 弓箭蓄力瞄准状态移动通知 + c.registerMessage(EvtAvatarExitFocusNotify, &proto.EvtAvatarExitFocusNotify{}) // 退出弓箭蓄力瞄准状态通知 + c.registerMessage(EvtEntityRenderersChangedNotify, &proto.EvtEntityRenderersChangedNotify{}) // 实体可视状态改变通知 + c.registerMessage(EvtCreateGadgetNotify, &proto.EvtCreateGadgetNotify{}) // 创建实体通知 + c.registerMessage(EvtDestroyGadgetNotify, &proto.EvtDestroyGadgetNotify{}) // 销毁实体通知 // 队伍 c.registerMessage(ChangeAvatarReq, &proto.ChangeAvatarReq{}) // 更换角色请求 切人 @@ -238,8 +244,6 @@ func (c *CmdProtoMap) registerAllMessage() { //c.registerMessage(MonsterAIConfigHashNotify, &proto.MonsterAIConfigHashNotify{}) //c.registerMessage(GetRegionSearchReq, &proto.GetRegionSearchReq{}) //c.registerMessage(ObstacleModifyNotify, &proto.ObstacleModifyNotify{}) - //c.registerMessage(EvtCreateGadgetNotify, &proto.EvtCreateGadgetNotify{}) - //c.registerMessage(EvtDestroyGadgetNotify, &proto.EvtDestroyGadgetNotify{}) // 空消息 c.registerMessage(65535, &proto.NullMsg{})