From 5e8d4573445740df3a3c873543ffa8d1fcfdbb8d Mon Sep 17 00:00:00 2001 From: huangxiaolei <1782360262@qq.com> Date: Fri, 9 Dec 2022 02:01:25 +0800 Subject: [PATCH] =?UTF-8?q?=E5=A4=9A=E4=BA=BA=E4=B8=96=E7=95=8C=E9=98=9F?= =?UTF-8?q?=E4=BC=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- gs/game/user_manager.go | 2 +- gs/game/user_multiplayer.go | 27 +++--- gs/game/user_scene.go | 20 +++-- gs/game/user_team.go | 149 +++++++++++++++++++++++++----- gs/game/world_manager.go | 175 +++++++++++++++++++++++++++++++++--- gs/model/avatar.go | 9 ++ gs/model/player.go | 1 - 7 files changed, 325 insertions(+), 58 deletions(-) diff --git a/gs/game/user_manager.go b/gs/game/user_manager.go index 28fad73e..694e560e 100644 --- a/gs/game/user_manager.go +++ b/gs/game/user_manager.go @@ -256,7 +256,7 @@ func (u *UserManager) SaveUser() { playerMapTemp[k] = v } u.playerMapLock.RUnlock() - logger.LOG.Info("copy user map finish") + logger.LOG.Info("copyLocalTeamToWorld user map finish") insertList := make([]*model.Player, 0) deleteList := make([]uint32, 0) updateList := make([]*model.Player, 0) diff --git a/gs/game/user_multiplayer.go b/gs/game/user_multiplayer.go index 2f5cb235..56c5fba5 100644 --- a/gs/game/user_multiplayer.go +++ b/gs/game/user_multiplayer.go @@ -52,7 +52,6 @@ func (g *GameManager) PlayerApplyEnterMpResultReq(player *model.Player, payloadM func (g *GameManager) PlayerGetForceQuitBanInfoReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user get world exit ban info, uid: %v", player.PlayerID) - result := true world := WORLD_MANAGER.GetWorldByID(player.WorldId) for _, worldPlayer := range world.playerMap { @@ -72,7 +71,6 @@ func (g *GameManager) PlayerGetForceQuitBanInfoReq(player *model.Player, payload func (g *GameManager) BackMyWorldReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user back world, uid: %v", player.PlayerID) - // 其他玩家 ok := g.UserLeaveWorld(player) @@ -87,7 +85,6 @@ func (g *GameManager) BackMyWorldReq(player *model.Player, payloadMsg pb.Message func (g *GameManager) ChangeWorldToSingleModeReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user change world to single, uid: %v", player.PlayerID) - // 房主 ok := g.UserLeaveWorld(player) @@ -103,8 +100,15 @@ func (g *GameManager) ChangeWorldToSingleModeReq(player *model.Player, payloadMs func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user kick player, uid: %v", player.PlayerID) req := payloadMsg.(*proto.SceneKickPlayerReq) + world := WORLD_MANAGER.GetWorldByID(player.WorldId) + if player.PlayerID != world.owner.PlayerID { + sceneKickPlayerRsp := &proto.SceneKickPlayerRsp{ + Retcode: int32(proto.Retcode_RETCODE_RET_SVR_ERROR), + } + g.SendMsg(cmd.SceneKickPlayerRsp, player.PlayerID, player.ClientSeq, sceneKickPlayerRsp) + return + } targetUid := req.TargetUid - targetPlayer := USER_MANAGER.GetOnlineUser(targetUid) ok := g.UserLeaveWorld(targetPlayer) if ok { @@ -112,7 +116,6 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes TargetUid: targetUid, KickerUid: player.PlayerID, } - world := WORLD_MANAGER.GetWorldByID(player.WorldId) for _, worldPlayer := range world.playerMap { g.SendMsg(cmd.SceneKickPlayerNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneKickPlayerNotify) } @@ -130,10 +133,8 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user join player scene, uid: %v", player.PlayerID) req := payloadMsg.(*proto.JoinPlayerSceneReq) - hostPlayer := USER_MANAGER.GetOnlineUser(req.TargetUid) hostWorld := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId) - _, exist := hostWorld.waitEnterPlayerMap[player.PlayerID] if !exist { return @@ -234,8 +235,7 @@ func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint if world.multiplayer { return } - - world.ChangeToMP() + world.ChangeToMultiplayer() worldDataNotify := &proto.WorldDataNotify{ WorldPropMap: make(map[uint32]*proto.PropValue), @@ -312,7 +312,6 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player) } } } - scene := world.GetSceneById(player.SceneId) // 仅仅把当前的场上角色的实体消失掉 @@ -336,11 +335,9 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player) world.RemovePlayer(player) player.WorldId = 0 - if world.multiplayer && len(world.playerMap) > 0 { g.UpdateWorldPlayerInfo(world, player) } - if world.owner.PlayerID == player.PlayerID { // 房主离开销毁世界 WORLD_MANAGER.DestroyWorld(world.id) @@ -402,7 +399,7 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod } scenePlayerInfoNotify.PlayerInfoList = append(scenePlayerInfoNotify.PlayerInfoList, &proto.ScenePlayerInfo{ Uid: worldPlayer.PlayerID, - PeerId: worldPlayer.PeerId, + PeerId: hostWorld.GetPlayerPeerId(worldPlayer), Name: worldPlayer.NickName, SceneId: worldPlayer.SceneId, OnlinePlayerInfo: onlinePlayerInfo, @@ -410,7 +407,7 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod } g.SendMsg(cmd.ScenePlayerInfoNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, scenePlayerInfoNotify) - sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(hostWorld) + sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotifyMp(hostWorld) g.SendMsg(cmd.SceneTeamUpdateNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneTeamUpdateNotify) syncTeamEntityNotify := &proto.SyncTeamEntityNotify{ @@ -426,7 +423,7 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) teamEntityInfo := &proto.TeamEntityInfo{ TeamEntityId: worldPlayerTeamEntity.teamEntityId, - AuthorityPeerId: worldPlayer.PeerId, + AuthorityPeerId: hostWorld.GetPlayerPeerId(worldPlayer), TeamAbilityInfo: new(proto.AbilitySyncStateInfo), } syncTeamEntityNotify.TeamEntityInfoList = append(syncTeamEntityNotify.TeamEntityInfoList, teamEntityInfo) diff --git a/gs/game/user_scene.go b/gs/game/user_scene.go index 92fdca64..295255f1 100644 --- a/gs/game/user_scene.go +++ b/gs/game/user_scene.go @@ -22,8 +22,8 @@ func (g *GameManager) EnterSceneReadyReq(player *model.Player, payloadMsg pb.Mes enterScenePeerNotify := &proto.EnterScenePeerNotify{ DestSceneId: player.SceneId, - PeerId: player.PeerId, - HostPeerId: world.owner.PeerId, + PeerId: world.GetPlayerPeerId(player), + HostPeerId: world.GetPlayerPeerId(world.owner), EnterSceneToken: player.EnterSceneToken, } g.SendMsg(cmd.EnterScenePeerNotify, player.PlayerID, player.ClientSeq, enterScenePeerNotify) @@ -99,7 +99,7 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes hostPlayerNotify := &proto.HostPlayerNotify{ HostUid: world.owner.PlayerID, - HostPeerId: world.owner.PeerId, + HostPeerId: world.GetPlayerPeerId(world.owner), } g.SendMsg(cmd.HostPlayerNotify, player.PlayerID, player.ClientSeq, hostPlayerNotify) @@ -174,7 +174,7 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes } scenePlayerInfoNotify.PlayerInfoList = append(scenePlayerInfoNotify.PlayerInfoList, &proto.ScenePlayerInfo{ Uid: worldPlayer.PlayerID, - PeerId: worldPlayer.PeerId, + PeerId: world.GetPlayerPeerId(worldPlayer), Name: worldPlayer.NickName, SceneId: worldPlayer.SceneId, OnlinePlayerInfo: onlinePlayerInfo, @@ -182,7 +182,12 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes } g.SendMsg(cmd.ScenePlayerInfoNotify, player.PlayerID, player.ClientSeq, scenePlayerInfoNotify) - sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) + var sceneTeamUpdateNotify *proto.SceneTeamUpdateNotify = nil + if world.multiplayer { + sceneTeamUpdateNotify = g.PacketSceneTeamUpdateNotifyMp(world) + } else { + sceneTeamUpdateNotify = g.PacketSceneTeamUpdateNotify(world) + } g.SendMsg(cmd.SceneTeamUpdateNotify, player.PlayerID, player.ClientSeq, sceneTeamUpdateNotify) syncTeamEntityNotify := &proto.SyncTeamEntityNotify{ @@ -198,7 +203,7 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) teamEntityInfo := &proto.TeamEntityInfo{ TeamEntityId: worldPlayerTeamEntity.teamEntityId, - AuthorityPeerId: worldPlayer.PeerId, + AuthorityPeerId: world.GetPlayerPeerId(worldPlayer), TeamAbilityInfo: new(proto.AbilitySyncStateInfo), } syncTeamEntityNotify.TeamEntityInfoList = append(syncTeamEntityNotify.TeamEntityInfoList, teamEntityInfo) @@ -679,11 +684,12 @@ func (g *GameManager) PacketSceneAvatarInfo(scene *Scene, player *model.Player, for _, reliquary := range player.AvatarMap[avatarId].EquipReliquaryList { equipIdList = append(equipIdList, reliquary.ItemId) } + world := WORLD_MANAGER.GetWorldByID(player.WorldId) sceneAvatarInfo := &proto.SceneAvatarInfo{ Uid: player.PlayerID, AvatarId: avatarId, Guid: player.AvatarMap[avatarId].Guid, - PeerId: player.PeerId, + PeerId: world.GetPlayerPeerId(player), EquipIdList: equipIdList, SkillDepotId: player.AvatarMap[avatarId].SkillDepotId, Weapon: &proto.SceneWeaponInfo{ diff --git a/gs/game/user_team.go b/gs/game/user_team.go index 67db9fd8..0f3ed008 100644 --- a/gs/game/user_team.go +++ b/gs/game/user_team.go @@ -87,9 +87,8 @@ func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Mes } avatarGuidList := req.AvatarTeamGuidList world := WORLD_MANAGER.GetWorldByID(player.WorldId) - multiTeam := teamId == 4 selfTeam := teamId == uint32(player.TeamConfig.GetActiveTeamId()) - if (multiTeam && len(avatarGuidList) == 0) || (selfTeam && len(avatarGuidList) == 0) || len(avatarGuidList) > 4 || world.multiplayer { + if (selfTeam && len(avatarGuidList) == 0) || len(avatarGuidList) > 4 || world.multiplayer { setUpAvatarTeamRsp := &proto.SetUpAvatarTeamRsp{ Retcode: int32(proto.Retcode_RETCODE_RET_SVR_ERROR), } @@ -204,6 +203,7 @@ func (g *GameManager) ChooseCurAvatarTeamReq(player *model.Player, payloadMsg pb func (g *GameManager) ChangeMpTeamAvatarReq(player *model.Player, payloadMsg pb.Message) { logger.LOG.Debug("user change mp team, uid: %v", player.PlayerID) req := payloadMsg.(*proto.ChangeMpTeamAvatarReq) + currAvatarGuid := req.CurAvatarGuid avatarGuidList := req.AvatarGuidList world := WORLD_MANAGER.GetWorldByID(player.WorldId) @@ -214,38 +214,42 @@ func (g *GameManager) ChangeMpTeamAvatarReq(player *model.Player, payloadMsg pb. g.SendMsg(cmd.ChangeMpTeamAvatarRsp, player.PlayerID, player.ClientSeq, changeMpTeamAvatarRsp) return } + avatarIdList := make([]uint32, 0) for _, avatarGuid := range avatarGuidList { - for avatarId, avatar := range player.AvatarMap { - if avatarGuid == avatar.Guid { - avatarIdList = append(avatarIdList, avatarId) - } + avatarId := player.GetAvatarIdByGuid(avatarGuid) + avatarIdList = append(avatarIdList, avatarId) + } + world.SetPlayerLocalTeam(player, avatarIdList) + + currAvatarId := player.GetAvatarIdByGuid(currAvatarGuid) + localTeam := world.multiplayerTeam.localTeamMap[player.PlayerID] + avatarIndex := 0 + for index, worldTeamAvatar := range localTeam { + if worldTeamAvatar.avatarId == 0 { + continue + } + if worldTeamAvatar.avatarId == currAvatarId { + avatarIndex = index } } - player.TeamConfig.ClearTeamAvatar(3) - for _, avatarId := range avatarIdList { - player.TeamConfig.AddAvatarToTeam(avatarId, 3) - } - player.TeamConfig.CurrAvatarIndex = 0 - player.TeamConfig.UpdateTeam() + world.SetPlayerLocalAvatarIndex(player, avatarIndex) + + world.UpdateMultiplayerTeam() scene := world.GetSceneById(player.SceneId) scene.UpdatePlayerTeamEntity(player) for _, worldPlayer := range world.playerMap { - sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotify(world) + sceneTeamUpdateNotify := g.PacketSceneTeamUpdateNotifyMp(world) g.SendMsg(cmd.SceneTeamUpdateNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, sceneTeamUpdateNotify) } + avatarId := world.GetPlayerActiveAvatarId(player) + avatar := player.AvatarMap[avatarId] + changeMpTeamAvatarRsp := &proto.ChangeMpTeamAvatarRsp{ - CurAvatarGuid: player.AvatarMap[player.TeamConfig.GetActiveAvatarId()].Guid, - AvatarGuidList: make([]uint64, 0), - } - team := player.TeamConfig.GetTeamByIndex(3) - for _, avatarId := range team.AvatarIdList { - if avatarId == 0 { - break - } - changeMpTeamAvatarRsp.AvatarGuidList = append(changeMpTeamAvatarRsp.AvatarGuidList, player.AvatarMap[avatarId].Guid) + CurAvatarGuid: avatar.Guid, + AvatarGuidList: req.AvatarGuidList, } g.SendMsg(cmd.ChangeMpTeamAvatarRsp, player.PlayerID, player.ClientSeq, changeMpTeamAvatarRsp) } @@ -352,3 +356,104 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam } return sceneTeamUpdateNotify } + +func (g *GameManager) PacketSceneTeamUpdateNotifyMp(world *World) *proto.SceneTeamUpdateNotify { + sceneTeamUpdateNotify := &proto.SceneTeamUpdateNotify{ + IsInMp: world.multiplayer, + } + empty := new(proto.AbilitySyncStateInfo) + for _, worldTeamAvatar := range world.multiplayerTeam.worldTeam { + if worldTeamAvatar.avatarId == 0 { + continue + } + worldPlayer := USER_MANAGER.GetOnlineUser(worldTeamAvatar.uid) + worldPlayerScene := world.GetSceneById(worldPlayer.SceneId) + worldPlayerTeamEntity := worldPlayerScene.GetPlayerTeamEntity(worldPlayer.PlayerID) + worldPlayerAvatar := worldPlayer.AvatarMap[worldTeamAvatar.avatarId] + equipIdList := make([]uint32, 0) + weapon := worldPlayerAvatar.EquipWeapon + equipIdList = append(equipIdList, weapon.ItemId) + for _, reliquary := range worldPlayerAvatar.EquipReliquaryList { + 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, + WeaponAbilityInfo: empty, + AbilityControlBlock: new(proto.AbilityControlBlock), + } + if world.multiplayer { + sceneTeamAvatar.AvatarInfo = g.PacketAvatarInfo(worldPlayerAvatar) + sceneTeamAvatar.SceneAvatarInfo = g.PacketSceneAvatarInfo(worldPlayerScene, worldPlayer, worldTeamAvatar.avatarId) + } + // add AbilityControlBlock + avatarDataConfig := gdc.CONF.AvatarDataMap[int32(worldTeamAvatar.avatarId)] + acb := sceneTeamAvatar.AbilityControlBlock + embryoId := 0 + // add avatar abilities + if avatarDataConfig != nil { + for _, abilityId := range avatarDataConfig.Abilities { + embryoId++ + emb := &proto.AbilityEmbryo{ + AbilityId: uint32(embryoId), + AbilityNameHash: uint32(abilityId), + AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME), + } + acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb) + } + } + // add default abilities + for _, abilityId := range constant.GameConstantConst.DEFAULT_ABILITY_HASHES { + embryoId++ + emb := &proto.AbilityEmbryo{ + AbilityId: uint32(embryoId), + AbilityNameHash: uint32(abilityId), + AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME), + } + acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb) + } + // add team resonances + for id := range worldPlayer.TeamConfig.TeamResonancesConfig { + embryoId++ + emb := &proto.AbilityEmbryo{ + AbilityId: uint32(embryoId), + AbilityNameHash: uint32(id), + AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME), + } + acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb) + } + // add skill depot abilities + skillDepot := gdc.CONF.AvatarSkillDepotDataMap[int32(worldPlayerAvatar.SkillDepotId)] + if skillDepot != nil && len(skillDepot.Abilities) != 0 { + for _, id := range skillDepot.Abilities { + embryoId++ + emb := &proto.AbilityEmbryo{ + AbilityId: uint32(embryoId), + AbilityNameHash: uint32(id), + AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME), + } + acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb) + } + } + // add equip abilities + for skill := range worldPlayerAvatar.ExtraAbilityEmbryos { + embryoId++ + emb := &proto.AbilityEmbryo{ + AbilityId: uint32(embryoId), + AbilityNameHash: uint32(endec.Hk4eAbilityHashCode(skill)), + AbilityOverrideNameHash: uint32(constant.GameConstantConst.DEFAULT_ABILITY_NAME), + } + acb.AbilityEmbryoList = append(acb.AbilityEmbryoList, emb) + } + sceneTeamUpdateNotify.SceneTeamAvatarList = append(sceneTeamUpdateNotify.SceneTeamAvatarList, sceneTeamAvatar) + } + return sceneTeamUpdateNotify +} diff --git a/gs/game/world_manager.go b/gs/game/world_manager.go index 9638f64b..6b085452 100644 --- a/gs/game/world_manager.go +++ b/gs/game/world_manager.go @@ -64,6 +64,8 @@ func (w *WorldManager) CreateWorld(owner *model.Player, multiplayer bool) *World ), playerFirstEnterMap: make(map[uint32]int64), waitEnterPlayerMap: make(map[uint32]int64), + multiplayerTeam: CreateMultiplayerTeam(), + peerMap: make(map[uint32]*model.Player), } if world.IsBigWorld() { world.aoiManager = aoi.NewAoiManager( @@ -90,9 +92,33 @@ func (w *WorldManager) GetBigWorld() *World { return w.bigWorld } +// InitBigWorld 初始化大世界 func (w *WorldManager) InitBigWorld(owner *model.Player) { w.bigWorld = w.GetWorldByID(owner.WorldId) - w.bigWorld.multiplayer = true + w.bigWorld.ChangeToMultiplayer() +} + +// WorldTeamAvatar 通用世界队伍角色项 +type WorldTeamAvatar struct { + uid uint32 + avatarId uint32 +} + +type MultiplayerTeam struct { + // key:uid value:玩家的本地队伍 + localTeamMap map[uint32][]*WorldTeamAvatar + // key:uid value:玩家当前角色索引 + localAvatarIndexMap map[uint32]int + // 最终的世界队伍 + worldTeam []*WorldTeamAvatar +} + +func CreateMultiplayerTeam() (r *MultiplayerTeam) { + r = new(MultiplayerTeam) + r.localTeamMap = make(map[uint32][]*WorldTeamAvatar) + r.localAvatarIndexMap = make(map[uint32]int) + r.worldTeam = make([]*WorldTeamAvatar, 0) + return r } type World struct { @@ -100,14 +126,16 @@ type World struct { owner *model.Player playerMap map[uint32]*model.Player sceneMap map[uint32]*Scene - entityIdCounter uint32 - worldLevel uint8 - multiplayer bool + entityIdCounter uint32 // 世界的实体id生成计数器 + worldLevel uint8 // 世界等级 + multiplayer bool // 是否多人世界 mpLevelEntityId uint32 - chatMsgList []*proto.ChatInfo - aoiManager *aoi.AoiManager // 当前世界地图的aoi管理器 - playerFirstEnterMap map[uint32]int64 - waitEnterPlayerMap map[uint32]int64 + chatMsgList []*proto.ChatInfo // 世界聊天消息列表 + aoiManager *aoi.AoiManager // 当前世界地图的aoi管理器 + playerFirstEnterMap map[uint32]int64 // 玩家第一次进入世界的时间 key:uid value:进入时间 + waitEnterPlayerMap map[uint32]int64 // 等待进入世界的列表 key:uid value:开始时间 + multiplayerTeam *MultiplayerTeam + peerMap map[uint32]*model.Player // key:玩家编号 value:player对象 } func (w *World) GetNextWorldEntityId(entityType uint16) uint32 { @@ -116,18 +144,117 @@ func (w *World) GetNextWorldEntityId(entityType uint16) uint32 { return ret } +func (w *World) GetPlayerPeerId(player *model.Player) uint32 { + for peerId, worldPlayer := range w.peerMap { + if worldPlayer.PlayerID == player.PlayerID { + return peerId + } + } + return 0 +} + +func (w *World) GetNextPeerId() uint32 { + return uint32(len(w.playerMap) + 1) +} + +func (w *World) GetWorldPlayerNum() int { + return len(w.playerMap) +} + func (w *World) AddPlayer(player *model.Player, sceneId uint32) { - player.PeerId = uint32(len(w.playerMap) + 1) + w.peerMap[w.GetNextPeerId()] = player w.playerMap[player.PlayerID] = player + // 将玩家自身当前的队伍角色信息复制到世界的玩家本地队伍 + team := player.TeamConfig.GetActiveTeam() + w.SetPlayerLocalTeam(player, team.AvatarIdList) + w.UpdateMultiplayerTeam() scene := w.GetSceneById(sceneId) scene.AddPlayer(player) } func (w *World) RemovePlayer(player *model.Player) { + delete(w.peerMap, w.GetPlayerPeerId(player)) scene := w.sceneMap[player.SceneId] scene.RemovePlayer(player) delete(w.playerMap, player.PlayerID) delete(w.playerFirstEnterMap, player.PlayerID) + delete(w.multiplayerTeam.localTeamMap, player.PlayerID) + delete(w.multiplayerTeam.localAvatarIndexMap, player.PlayerID) + w.UpdateMultiplayerTeam() +} + +func (w *World) SetPlayerLocalTeam(player *model.Player, avatarIdList []uint32) { + localTeam := make([]*WorldTeamAvatar, 4) + for index := 0; index < 4; index++ { + if index > len(avatarIdList)-1 { + localTeam[index] = &WorldTeamAvatar{ + uid: 0, + avatarId: 0, + } + } else { + avatarId := avatarIdList[index] + localTeam[index] = &WorldTeamAvatar{ + uid: player.PlayerID, + avatarId: avatarId, + } + } + } + w.multiplayerTeam.localTeamMap[player.PlayerID] = localTeam +} + +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.multiplayerTeam.localTeamMap[player.PlayerID])-1 { + return + } + w.multiplayerTeam.localAvatarIndexMap[player.PlayerID] = index +} + +func (w *World) GetPlayerActiveAvatarId(player *model.Player) uint32 { + avatarIndex := w.GetPlayerLocalAvatarIndex(player) + localTeam := w.multiplayerTeam.localTeamMap[player.PlayerID] + worldTeamAvatar := localTeam[avatarIndex] + return worldTeamAvatar.avatarId +} + +func (w *World) copyLocalTeamToWorld(start int, end int, peerId uint32) { + localTeamIndex := 0 + for index := start; index <= end; index++ { + player := w.peerMap[peerId] + localTeam := w.multiplayerTeam.localTeamMap[player.PlayerID] + w.multiplayerTeam.worldTeam[index] = localTeam[localTeamIndex] + localTeamIndex++ + } +} + +// UpdateMultiplayerTeam 整合所有玩家的本地队伍计算出世界队伍 +func (w *World) UpdateMultiplayerTeam() { + w.multiplayerTeam.worldTeam = make([]*WorldTeamAvatar, 4) + switch w.GetWorldPlayerNum() { + case 1: + // 1P*4 + w.copyLocalTeamToWorld(0, 3, 1) + case 2: + // 1P*2 + 2P*2 + w.copyLocalTeamToWorld(0, 1, 1) + w.copyLocalTeamToWorld(2, 3, 2) + case 3: + // 1P*2 + 2P*1 + 3P*1 + w.copyLocalTeamToWorld(0, 1, 1) + w.copyLocalTeamToWorld(2, 2, 2) + w.copyLocalTeamToWorld(3, 3, 3) + case 4: + // 1P*1 + 2P*1 + 3P*1 + 4P*1 + w.copyLocalTeamToWorld(0, 0, 1) + w.copyLocalTeamToWorld(1, 1, 2) + w.copyLocalTeamToWorld(2, 2, 3) + w.copyLocalTeamToWorld(3, 3, 4) + default: + break + } } func (w *World) CreateScene(sceneId uint32) *Scene { @@ -166,7 +293,7 @@ func (w *World) IsBigWorld() bool { return w.owner.PlayerID == 1 } -func (w *World) ChangeToMP() { +func (w *World) ChangeToMultiplayer() { w.multiplayer = true } @@ -189,10 +316,10 @@ type Scene struct { playerMap map[uint32]*model.Player entityMap map[uint32]*Entity playerTeamEntityMap map[uint32]*PlayerTeamEntity - gameTime uint32 + gameTime uint32 // 游戏内提瓦特大陆的时间 attackQueue *alg.RAQueue[*Attack] createTime int64 - meeoIndex uint32 + meeoIndex uint32 // 客户端风元素染色同步协议的计数器 } type AvatarEntity struct { @@ -261,6 +388,10 @@ func (s *Scene) CreatePlayerTeamEntity(player *model.Player) { } func (s *Scene) UpdatePlayerTeamEntity(player *model.Player) { + if s.world.multiplayer { + s.UpdatePlayerTeamEntityMp(player) + return + } team := player.TeamConfig.GetActiveTeam() playerTeamEntity := s.playerTeamEntityMap[player.PlayerID] for _, avatarId := range team.AvatarIdList { @@ -281,6 +412,26 @@ func (s *Scene) UpdatePlayerTeamEntity(player *model.Player) { } } +func (s *Scene) UpdatePlayerTeamEntityMp(player *model.Player) { + playerTeamEntity := s.playerTeamEntityMap[player.PlayerID] + for _, worldTeamAvatar := range s.world.multiplayerTeam.worldTeam { + if worldTeamAvatar.uid != player.PlayerID || worldTeamAvatar.avatarId == 0 { + 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) diff --git a/gs/model/avatar.go b/gs/model/avatar.go index a4522d01..3fdb9c95 100644 --- a/gs/model/avatar.go +++ b/gs/model/avatar.go @@ -75,6 +75,15 @@ func (p *Player) InitAvatar(avatar *Avatar) { return } +func (p *Player) GetAvatarIdByGuid(guid uint64) uint32 { + for avatarId, avatar := range p.AvatarMap { + if guid == avatar.Guid { + return avatarId + } + } + return 0 +} + func (p *Player) AddAvatar(avatarId uint32) { avatarDataConfig, ok := gdc.CONF.AvatarDataMap[int32(avatarId)] if !ok { diff --git a/gs/model/player.go b/gs/model/player.go index 264aa3d7..7b13b877 100644 --- a/gs/model/player.go +++ b/gs/model/player.go @@ -56,7 +56,6 @@ type Player struct { EnterSceneToken uint32 `bson:"-"` // 玩家的世界进入令牌 DbState int `bson:"-"` // 数据库存档状态 WorldId uint32 `bson:"-"` // 所在的世界id - PeerId uint32 `bson:"-"` // 多人世界的玩家编号 GameObjectGuidCounter uint64 `bson:"-"` // 游戏对象guid计数器 ClientTime uint32 `bson:"-"` // 玩家客户端的本地时钟 ClientRTT uint32 `bson:"-"` // 玩家客户端往返时延