多人世界队伍

This commit is contained in:
huangxiaolei
2022-12-09 02:01:25 +08:00
parent 3615ad194a
commit 5e8d457344
7 changed files with 325 additions and 58 deletions

View File

@@ -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)

View File

@@ -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)

View File

@@ -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{

View File

@@ -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
}

View File

@@ -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)

View File

@@ -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 {

View File

@@ -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:"-"` // 玩家客户端往返时延