mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-03-01 00:35:36 +08:00
场景组管理和场景实体玩家视野管理分离
This commit is contained in:
@@ -1,8 +1,6 @@
|
|||||||
package game
|
package game
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"math"
|
|
||||||
|
|
||||||
"hk4e/common/constant"
|
"hk4e/common/constant"
|
||||||
"hk4e/gdconf"
|
"hk4e/gdconf"
|
||||||
"hk4e/gs/model"
|
"hk4e/gs/model"
|
||||||
@@ -132,13 +130,9 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
|
|||||||
}
|
}
|
||||||
fightProp[constant.FIGHT_PROP_CUR_HP] = currHp
|
fightProp[constant.FIGHT_PROP_CUR_HP] = currHp
|
||||||
}
|
}
|
||||||
entityFightPropUpdateNotify := &proto.EntityFightPropUpdateNotify{
|
g.EntityFightPropUpdateNotifyBroadcast(world, target)
|
||||||
FightPropMap: fightProp,
|
if currHp == 0 && target.GetEntityType() == constant.ENTITY_TYPE_MONSTER {
|
||||||
EntityId: target.GetId(),
|
g.KillEntity(scene, target.GetId(), proto.PlayerDieType_PLAYER_DIE_GM)
|
||||||
}
|
|
||||||
g.SendToWorldA(world, cmd.EntityFightPropUpdateNotify, player.ClientSeq, entityFightPropUpdateNotify)
|
|
||||||
if currHp == 0 && target.GetEntityType() != constant.ENTITY_TYPE_AVATAR {
|
|
||||||
scene.SetEntityLifeState(target, constant.LIFE_STATE_DEAD, proto.PlayerDieType_PLAYER_DIE_GM)
|
|
||||||
}
|
}
|
||||||
combatData, err := pb.Marshal(evtBeingHitInfo)
|
combatData, err := pb.Marshal(evtBeingHitInfo)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -258,72 +252,48 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector,
|
|||||||
// 跨越了block格子
|
// 跨越了block格子
|
||||||
logger.Debug("player cross grid, oldGid: %v, newGid: %v, uid: %v", oldGid, newGid, player.PlayerID)
|
logger.Debug("player cross grid, oldGid: %v, newGid: %v, uid: %v", oldGid, newGid, player.PlayerID)
|
||||||
}
|
}
|
||||||
// 旧位置视野范围内的group
|
// 加载和卸载的group
|
||||||
oldVisionGroupMap := make(map[uint32]*gdconf.Group)
|
oldNeighborGroupMap := g.GetNeighborGroup(player.SceneId, oldPos)
|
||||||
oldGroupList := aoiManager.GetObjectListByPos(float32(oldPos.X), 0.0, float32(oldPos.Z))
|
newNeighborGroupMap := g.GetNeighborGroup(player.SceneId, newPos)
|
||||||
for groupId, groupAny := range oldGroupList {
|
for groupId, groupConfig := range oldNeighborGroupMap {
|
||||||
groupConfig := groupAny.(*gdconf.Group)
|
_, exist := newNeighborGroupMap[groupId]
|
||||||
distance2D := math.Sqrt((oldPos.X-float64(groupConfig.Pos.X))*(oldPos.X-float64(groupConfig.Pos.X)) +
|
|
||||||
(oldPos.Z-float64(groupConfig.Pos.Z))*(oldPos.Z-float64(groupConfig.Pos.Z)))
|
|
||||||
if distance2D > ENTITY_LOD {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if groupConfig.DynamicLoad {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
oldVisionGroupMap[uint32(groupId)] = groupConfig
|
|
||||||
}
|
|
||||||
// 新位置视野范围内的group
|
|
||||||
newVisionGroupMap := make(map[uint32]*gdconf.Group)
|
|
||||||
newGroupList := aoiManager.GetObjectListByPos(float32(newPos.X), 0.0, float32(newPos.Z))
|
|
||||||
for groupId, groupAny := range newGroupList {
|
|
||||||
groupConfig := groupAny.(*gdconf.Group)
|
|
||||||
distance2D := math.Sqrt((newPos.X-float64(groupConfig.Pos.X))*(newPos.X-float64(groupConfig.Pos.X)) +
|
|
||||||
(newPos.Z-float64(groupConfig.Pos.Z))*(newPos.Z-float64(groupConfig.Pos.Z)))
|
|
||||||
if distance2D > ENTITY_LOD {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if groupConfig.DynamicLoad {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
newVisionGroupMap[uint32(groupId)] = groupConfig
|
|
||||||
}
|
|
||||||
// 消失的场景实体
|
|
||||||
delEntityIdList := make([]uint32, 0)
|
|
||||||
for groupId, groupConfig := range oldVisionGroupMap {
|
|
||||||
_, exist := newVisionGroupMap[groupId]
|
|
||||||
if exist {
|
if exist {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 旧有新没有的group即为消失的
|
// 旧有新没有的group即为卸载的
|
||||||
group := scene.GetGroupById(groupId)
|
|
||||||
if group == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, entity := range group.GetAllEntity() {
|
|
||||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
|
||||||
}
|
|
||||||
if !world.GetMultiplayer() {
|
if !world.GetMultiplayer() {
|
||||||
// 处理多人世界不同玩家不同位置的group卸载情况
|
// 处理多人世界不同玩家不同位置的group卸载情况
|
||||||
g.RemoveGroup(player, scene, groupConfig)
|
g.RemoveGroup(player, scene, groupConfig)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 出现的场景实体
|
for groupId, groupConfig := range newNeighborGroupMap {
|
||||||
addEntityIdList := make([]uint32, 0)
|
_, exist := oldNeighborGroupMap[groupId]
|
||||||
for groupId, groupConfig := range newVisionGroupMap {
|
|
||||||
_, exist := oldVisionGroupMap[groupId]
|
|
||||||
if exist {
|
if exist {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
// 新有旧没有的group即为出现的
|
// 新有旧没有的group即为加载的
|
||||||
g.AddSceneGroup(player, scene, groupConfig)
|
g.AddSceneGroup(player, scene, groupConfig)
|
||||||
group := scene.GetGroupById(groupId)
|
}
|
||||||
if group == nil {
|
// 消失和出现的场景实体
|
||||||
|
oldVisionEntityMap := g.GetVisionEntity(scene, oldPos)
|
||||||
|
newVisionEntityMap := g.GetVisionEntity(scene, newPos)
|
||||||
|
delEntityIdList := make([]uint32, 0)
|
||||||
|
for entityId := range oldVisionEntityMap {
|
||||||
|
_, exist := newVisionEntityMap[entityId]
|
||||||
|
if exist {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
for _, entity := range group.GetAllEntity() {
|
// 旧有新没有的实体即为消失的
|
||||||
addEntityIdList = append(addEntityIdList, entity.GetId())
|
delEntityIdList = append(delEntityIdList, entityId)
|
||||||
|
}
|
||||||
|
addEntityIdList := make([]uint32, 0)
|
||||||
|
for entityId := range newVisionEntityMap {
|
||||||
|
_, exist := oldVisionEntityMap[entityId]
|
||||||
|
if exist {
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
|
// 新有旧没有的实体即为出现的
|
||||||
|
addEntityIdList = append(addEntityIdList, entityId)
|
||||||
}
|
}
|
||||||
// 同步客户端消失和出现的场景实体
|
// 同步客户端消失和出现的场景实体
|
||||||
if len(delEntityIdList) > 0 {
|
if len(delEntityIdList) > 0 {
|
||||||
@@ -452,11 +422,14 @@ func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
for _, entry := range req.Invokes {
|
for _, entry := range req.Invokes {
|
||||||
// logger.Debug("AbilityInvocationsNotify: %v", entry, player.PlayerID)
|
// logger.Debug("AbilityInvocationsNotify: %v", entry, player.PlayerID)
|
||||||
switch entry.ArgumentType {
|
switch entry.ArgumentType {
|
||||||
case proto.AbilityInvokeArgument_ABILITY_META_MODIFIER_CHANGE:
|
case proto.AbilityInvokeArgument_ABILITY_META_MODIFIER_CHANGE:
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
worldAvatar := world.GetWorldAvatarByEntityId(entry.EntityId)
|
worldAvatar := world.GetWorldAvatarByEntityId(entry.EntityId)
|
||||||
if worldAvatar != nil {
|
if worldAvatar != nil {
|
||||||
for _, ability := range worldAvatar.abilityList {
|
for _, ability := range worldAvatar.abilityList {
|
||||||
@@ -575,7 +548,6 @@ func (g *GameManager) EvtDoSkillSuccNotify(player *model.Player, payloadMsg pb.M
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtDoSkillSuccNotify: %v", req)
|
logger.Debug("EvtDoSkillSuccNotify: %v", req)
|
||||||
|
|
||||||
// 处理技能开始的耐力消耗
|
// 处理技能开始的耐力消耗
|
||||||
g.SkillStartStamina(player, req.CasterId, req.SkillId)
|
g.SkillStartStamina(player, req.CasterId, req.SkillId)
|
||||||
}
|
}
|
||||||
@@ -585,7 +557,7 @@ func (g *GameManager) EvtAvatarEnterFocusNotify(player *model.Player, payloadMsg
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtAvatarEnterFocusNotify: %v", req)
|
// logger.Debug("EvtAvatarEnterFocusNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
g.SendToWorldA(world, cmd.EvtAvatarEnterFocusNotify, player.ClientSeq, req)
|
g.SendToWorldA(world, cmd.EvtAvatarEnterFocusNotify, player.ClientSeq, req)
|
||||||
}
|
}
|
||||||
@@ -595,7 +567,7 @@ func (g *GameManager) EvtAvatarUpdateFocusNotify(player *model.Player, payloadMs
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtAvatarUpdateFocusNotify: %v", req)
|
// logger.Debug("EvtAvatarUpdateFocusNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
g.SendToWorldA(world, cmd.EvtAvatarUpdateFocusNotify, player.ClientSeq, req)
|
g.SendToWorldA(world, cmd.EvtAvatarUpdateFocusNotify, player.ClientSeq, req)
|
||||||
}
|
}
|
||||||
@@ -605,7 +577,7 @@ func (g *GameManager) EvtAvatarExitFocusNotify(player *model.Player, payloadMsg
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtAvatarExitFocusNotify: %v", req)
|
// logger.Debug("EvtAvatarExitFocusNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
g.SendToWorldA(world, cmd.EvtAvatarExitFocusNotify, player.ClientSeq, req)
|
g.SendToWorldA(world, cmd.EvtAvatarExitFocusNotify, player.ClientSeq, req)
|
||||||
}
|
}
|
||||||
@@ -615,7 +587,7 @@ func (g *GameManager) EvtEntityRenderersChangedNotify(player *model.Player, payl
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtEntityRenderersChangedNotify: %v", req)
|
// logger.Debug("EvtEntityRenderersChangedNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
g.SendToWorldA(world, cmd.EvtEntityRenderersChangedNotify, player.ClientSeq, req)
|
g.SendToWorldA(world, cmd.EvtEntityRenderersChangedNotify, player.ClientSeq, req)
|
||||||
}
|
}
|
||||||
@@ -625,7 +597,7 @@ func (g *GameManager) EvtCreateGadgetNotify(player *model.Player, payloadMsg pb.
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtCreateGadgetNotify: %v", req)
|
// logger.Debug("EvtCreateGadgetNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
if world == nil {
|
if world == nil {
|
||||||
logger.Error("world is nil, WorldId: %v", player.WorldId)
|
logger.Error("world is nil, WorldId: %v", player.WorldId)
|
||||||
@@ -652,7 +624,7 @@ func (g *GameManager) EvtDestroyGadgetNotify(player *model.Player, payloadMsg pb
|
|||||||
if player.SceneLoadState != model.SceneEnterDone {
|
if player.SceneLoadState != model.SceneEnterDone {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
logger.Debug("EvtDestroyGadgetNotify: %v", req)
|
// logger.Debug("EvtDestroyGadgetNotify: %v", req)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
scene := world.GetSceneById(player.SceneId)
|
scene := world.GetSceneById(player.SceneId)
|
||||||
if scene == nil {
|
if scene == nil {
|
||||||
|
|||||||
@@ -20,7 +20,8 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ENTITY_MAX_BATCH_SEND_NUM = 1000 // 单次同步的最大实体数量
|
ENTITY_MAX_BATCH_SEND_NUM = 1000 // 单次同步的最大实体数量
|
||||||
ENTITY_LOD = 100 // 实体加载视野距离
|
ENTITY_VISION_DISTANCE = 100 // 实体视野距离
|
||||||
|
GROUP_LOAD_DISTANCE = 250 // 场景组加载距离
|
||||||
)
|
)
|
||||||
|
|
||||||
func (g *GameManager) EnterSceneReadyReq(player *model.Player, payloadMsg pb.Message) {
|
func (g *GameManager) EnterSceneReadyReq(player *model.Player, payloadMsg pb.Message) {
|
||||||
@@ -34,35 +35,10 @@ func (g *GameManager) EnterSceneReadyReq(player *model.Player, payloadMsg pb.Mes
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
if ctx.OldSceneId != 0 {
|
if ctx.OldSceneId != 0 {
|
||||||
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[ctx.OldSceneId]
|
|
||||||
if !exist {
|
|
||||||
logger.Error("player scene not exist in aoi, sceneId: %v, uid: %v", ctx.OldSceneId, player.PlayerID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
objectList := aoiManager.GetObjectListByPos(float32(ctx.OldPos.X), 0.0, float32(ctx.OldPos.Z))
|
|
||||||
delEntityIdList := make([]uint32, 0)
|
|
||||||
oldScene := world.GetSceneById(ctx.OldSceneId)
|
oldScene := world.GetSceneById(ctx.OldSceneId)
|
||||||
for _, groupAny := range objectList {
|
delEntityIdList := make([]uint32, 0)
|
||||||
groupConfig := groupAny.(*gdconf.Group)
|
for entityId := range g.GetVisionEntity(oldScene, ctx.OldPos) {
|
||||||
distance2D := math.Sqrt((ctx.OldPos.X-float64(groupConfig.Pos.X))*(ctx.OldPos.X-float64(groupConfig.Pos.X)) +
|
delEntityIdList = append(delEntityIdList, entityId)
|
||||||
(ctx.OldPos.Z-float64(groupConfig.Pos.Z))*(ctx.OldPos.Z-float64(groupConfig.Pos.Z)))
|
|
||||||
if distance2D > ENTITY_LOD {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if groupConfig.DynamicLoad {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
group := oldScene.GetGroupById(uint32(groupConfig.Id))
|
|
||||||
if group == nil {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
for _, entity := range group.GetAllEntity() {
|
|
||||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
|
||||||
}
|
|
||||||
if !world.GetMultiplayer() {
|
|
||||||
// 处理多人世界不同玩家不同位置的group卸载情况
|
|
||||||
g.RemoveGroup(player, oldScene, groupConfig)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList)
|
g.RemoveSceneEntityNotifyToPlayer(player, proto.VisionType_VISION_MISS, delEntityIdList)
|
||||||
}
|
}
|
||||||
@@ -314,22 +290,7 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
|
|||||||
g.AddSceneEntityNotify(player, visionType, []uint32{activeAvatarEntityId}, true, false)
|
g.AddSceneEntityNotify(player, visionType, []uint32{activeAvatarEntityId}, true, false)
|
||||||
|
|
||||||
// 加载附近的group
|
// 加载附近的group
|
||||||
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[scene.GetId()]
|
for _, groupConfig := range g.GetNeighborGroup(scene.GetId(), player.Pos) {
|
||||||
if !exist {
|
|
||||||
logger.Error("player scene not exist in aoi, sceneId: %v, uid: %v", scene.GetId(), player.PlayerID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
|
|
||||||
for _, groupAny := range objectList {
|
|
||||||
groupConfig := groupAny.(*gdconf.Group)
|
|
||||||
distance2D := math.Sqrt((player.Pos.X-float64(groupConfig.Pos.X))*(player.Pos.X-float64(groupConfig.Pos.X)) +
|
|
||||||
(player.Pos.Z-float64(groupConfig.Pos.Z))*(player.Pos.Z-float64(groupConfig.Pos.Z)))
|
|
||||||
if distance2D > ENTITY_LOD {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if groupConfig.DynamicLoad {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
g.AddSceneGroup(player, scene, groupConfig)
|
g.AddSceneGroup(player, scene, groupConfig)
|
||||||
}
|
}
|
||||||
if player.SceneJump {
|
if player.SceneJump {
|
||||||
@@ -337,9 +298,10 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
|
|||||||
} else {
|
} else {
|
||||||
visionType = proto.VisionType_VISION_TRANSPORT
|
visionType = proto.VisionType_VISION_TRANSPORT
|
||||||
}
|
}
|
||||||
|
// 同步客户端视野内的场景实体
|
||||||
entityIdList := make([]uint32, 0)
|
entityIdList := make([]uint32, 0)
|
||||||
entityMap := scene.GetAllEntity()
|
visionEntityMap := g.GetVisionEntity(scene, player.Pos)
|
||||||
for _, entity := range entityMap {
|
for _, entity := range visionEntityMap {
|
||||||
if entity.GetId() == activeAvatarEntityId {
|
if entity.GetId() == activeAvatarEntityId {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
@@ -391,8 +353,7 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
scene := world.GetSceneById(player.SceneId)
|
scene := world.GetSceneById(player.SceneId)
|
||||||
entity := scene.GetEntity(req.EntityId)
|
g.KillEntity(scene, req.EntityId, proto.PlayerDieType_PLAYER_DIE_DRAWN)
|
||||||
scene.SetEntityLifeState(entity, constant.LIFE_STATE_DEAD, proto.PlayerDieType_PLAYER_DIE_DRAWN)
|
|
||||||
|
|
||||||
sceneEntityDrownRsp := &proto.SceneEntityDrownRsp{
|
sceneEntityDrownRsp := &proto.SceneEntityDrownRsp{
|
||||||
EntityId: req.EntityId,
|
EntityId: req.EntityId,
|
||||||
@@ -400,143 +361,6 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
|
|||||||
g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp)
|
g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp)
|
||||||
}
|
}
|
||||||
|
|
||||||
var SceneTransactionSeq uint32 = 0
|
|
||||||
|
|
||||||
func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify {
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
scene := world.GetSceneById(player.SceneId)
|
|
||||||
if scene == nil {
|
|
||||||
logger.Error("scene is nil, sceneId: %v", player.SceneId)
|
|
||||||
return new(proto.PlayerEnterSceneNotify)
|
|
||||||
}
|
|
||||||
enterSceneToken := world.AddEnterSceneContext(&EnterSceneContext{
|
|
||||||
OldSceneId: 0,
|
|
||||||
Uid: player.PlayerID,
|
|
||||||
})
|
|
||||||
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
|
|
||||||
SceneId: player.SceneId,
|
|
||||||
Pos: &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)},
|
|
||||||
SceneBeginTime: uint64(scene.GetSceneCreateTime()),
|
|
||||||
Type: enterType,
|
|
||||||
TargetUid: player.PlayerID,
|
|
||||||
EnterSceneToken: enterSceneToken,
|
|
||||||
WorldLevel: player.PropertiesMap[constant.PLAYER_PROP_PLAYER_WORLD_LEVEL],
|
|
||||||
EnterReason: uint32(proto.EnterReason_ENTER_REASON_LOGIN),
|
|
||||||
IsFirstLoginEnterScene: true,
|
|
||||||
WorldType: 1,
|
|
||||||
SceneTagIdList: make([]uint32, 0),
|
|
||||||
}
|
|
||||||
SceneTransactionSeq++
|
|
||||||
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
|
||||||
strconv.Itoa(int(player.PlayerID)) + "-" +
|
|
||||||
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
|
||||||
strconv.Itoa(int(SceneTransactionSeq))
|
|
||||||
for _, sceneTagDataConfig := range gdconf.GetSceneTagDataMap() {
|
|
||||||
if uint32(sceneTagDataConfig.SceneId) == player.SceneId {
|
|
||||||
playerEnterSceneNotify.SceneTagIdList = append(playerEnterSceneNotify.SceneTagIdList, uint32(sceneTagDataConfig.SceneTagId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return playerEnterSceneNotify
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GameManager) PacketPlayerEnterSceneNotifyTp(
|
|
||||||
player *model.Player,
|
|
||||||
enterType proto.EnterType,
|
|
||||||
enterReason uint32,
|
|
||||||
prevSceneId uint32,
|
|
||||||
prevPos *model.Vector,
|
|
||||||
dungeonId uint32,
|
|
||||||
) *proto.PlayerEnterSceneNotify {
|
|
||||||
return g.PacketPlayerEnterSceneNotifyMp(player, player, enterType, enterReason, prevSceneId, prevPos, dungeonId)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GameManager) PacketPlayerEnterSceneNotifyMp(
|
|
||||||
player *model.Player,
|
|
||||||
targetPlayer *model.Player,
|
|
||||||
enterType proto.EnterType,
|
|
||||||
enterReason uint32,
|
|
||||||
prevSceneId uint32,
|
|
||||||
prevPos *model.Vector,
|
|
||||||
dungeonId uint32,
|
|
||||||
) *proto.PlayerEnterSceneNotify {
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
scene := world.GetSceneById(player.SceneId)
|
|
||||||
if scene == nil {
|
|
||||||
logger.Error("scene is nil, sceneId: %v", player.SceneId)
|
|
||||||
return new(proto.PlayerEnterSceneNotify)
|
|
||||||
}
|
|
||||||
enterSceneToken := world.AddEnterSceneContext(&EnterSceneContext{
|
|
||||||
OldSceneId: prevSceneId,
|
|
||||||
OldPos: &model.Vector{
|
|
||||||
X: prevPos.X,
|
|
||||||
Y: prevPos.Y,
|
|
||||||
Z: prevPos.Z,
|
|
||||||
},
|
|
||||||
OldRot: &model.Vector{
|
|
||||||
X: 0,
|
|
||||||
Y: 0,
|
|
||||||
Z: 0,
|
|
||||||
},
|
|
||||||
Uid: player.PlayerID,
|
|
||||||
})
|
|
||||||
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
|
|
||||||
PrevSceneId: prevSceneId,
|
|
||||||
PrevPos: &proto.Vector{X: float32(prevPos.X), Y: float32(prevPos.Y), Z: float32(prevPos.Z)},
|
|
||||||
SceneId: player.SceneId,
|
|
||||||
Pos: &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)},
|
|
||||||
SceneBeginTime: uint64(scene.GetSceneCreateTime()),
|
|
||||||
Type: enterType,
|
|
||||||
TargetUid: targetPlayer.PlayerID,
|
|
||||||
EnterSceneToken: enterSceneToken,
|
|
||||||
WorldLevel: targetPlayer.PropertiesMap[constant.PLAYER_PROP_PLAYER_WORLD_LEVEL],
|
|
||||||
EnterReason: enterReason,
|
|
||||||
WorldType: 1,
|
|
||||||
DungeonId: dungeonId,
|
|
||||||
SceneTagIdList: make([]uint32, 0),
|
|
||||||
}
|
|
||||||
SceneTransactionSeq++
|
|
||||||
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
|
||||||
strconv.Itoa(int(targetPlayer.PlayerID)) + "-" +
|
|
||||||
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
|
||||||
strconv.Itoa(int(SceneTransactionSeq))
|
|
||||||
for _, sceneTagDataConfig := range gdconf.GetSceneTagDataMap() {
|
|
||||||
if uint32(sceneTagDataConfig.SceneId) == player.SceneId {
|
|
||||||
playerEnterSceneNotify.SceneTagIdList = append(playerEnterSceneNotify.SceneTagIdList, uint32(sceneTagDataConfig.SceneTagId))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return playerEnterSceneNotify
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GameManager) AddSceneGroup(player *model.Player, scene *Scene, groupConfig *gdconf.Group) {
|
|
||||||
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
|
|
||||||
if initSuiteId < 1 || initSuiteId > len(groupConfig.SuiteList) {
|
|
||||||
logger.Error("invalid init suite id: %v, uid: %v", initSuiteId, player.PlayerID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
|
|
||||||
ntf := &proto.GroupSuiteNotify{
|
|
||||||
GroupMap: make(map[uint32]uint32),
|
|
||||||
}
|
|
||||||
ntf.GroupMap[uint32(groupConfig.Id)] = uint32(initSuiteId)
|
|
||||||
g.SendMsg(cmd.GroupSuiteNotify, player.PlayerID, player.ClientSeq, ntf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GameManager) RemoveGroup(player *model.Player, scene *Scene, groupConfig *gdconf.Group) {
|
|
||||||
group := scene.GetGroupById(uint32(groupConfig.Id))
|
|
||||||
if group == nil {
|
|
||||||
logger.Error("group not exist, groupId: %v, uid: %v", groupConfig.Id, player.PlayerID)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for suiteId := range group.GetAllSuite() {
|
|
||||||
scene.RemoveGroupSuite(uint32(groupConfig.Id), suiteId)
|
|
||||||
}
|
|
||||||
ntf := &proto.GroupUnloadNotify{
|
|
||||||
GroupList: make([]uint32, 0),
|
|
||||||
}
|
|
||||||
ntf.GroupList = append(ntf.GroupList, uint32(groupConfig.Id))
|
|
||||||
g.SendMsg(cmd.GroupUnloadNotify, player.PlayerID, player.ClientSeq, ntf)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (g *GameManager) AddSceneEntityNotifyToPlayer(player *model.Player, visionType proto.VisionType, entityList []*proto.SceneEntityInfo) {
|
func (g *GameManager) AddSceneEntityNotifyToPlayer(player *model.Player, visionType proto.VisionType, entityList []*proto.SceneEntityInfo) {
|
||||||
sceneEntityAppearNotify := &proto.SceneEntityAppearNotify{
|
sceneEntityAppearNotify := &proto.SceneEntityAppearNotify{
|
||||||
AppearType: visionType,
|
AppearType: visionType,
|
||||||
@@ -642,16 +466,266 @@ func (g *GameManager) AddSceneEntityNotify(player *model.Player, visionType prot
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameManager) EntityFightPropUpdateNotifyBroadcast(scene *Scene, entity *Entity, fightPropId uint32) {
|
func (g *GameManager) EntityFightPropUpdateNotifyBroadcast(world *World, entity *Entity) {
|
||||||
for _, player := range scene.GetAllPlayer() {
|
ntf := &proto.EntityFightPropUpdateNotify{
|
||||||
fightProp := entity.GetFightProp()
|
FightPropMap: entity.GetFightProp(),
|
||||||
ntf := &proto.EntityFightPropUpdateNotify{
|
EntityId: entity.GetId(),
|
||||||
FightPropMap: make(map[uint32]float32),
|
|
||||||
EntityId: entity.GetId(),
|
|
||||||
}
|
|
||||||
ntf.FightPropMap[fightPropId] = fightProp[fightPropId]
|
|
||||||
g.SendMsg(cmd.EntityFightPropUpdateNotify, player.PlayerID, player.ClientSeq, ntf)
|
|
||||||
}
|
}
|
||||||
|
g.SendToWorldA(world, cmd.EntityFightPropUpdateNotify, 0, ntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) KillPlayerAvatar(player *model.Player, dieType proto.PlayerDieType) {
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
activeAvatarId := world.GetPlayerActiveAvatarId(player)
|
||||||
|
worldAvatar := world.GetPlayerWorldAvatar(player, activeAvatarId)
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
avatarEntity := scene.GetEntity(worldAvatar.GetAvatarEntityId())
|
||||||
|
|
||||||
|
dbAvatar := player.GetDbAvatar()
|
||||||
|
avatar, exist := dbAvatar.AvatarMap[activeAvatarId]
|
||||||
|
if !exist {
|
||||||
|
logger.Error("get active avatar is nil, avatarId: %v", activeAvatarId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
avatarEntity.lifeState = constant.LIFE_STATE_DEAD
|
||||||
|
|
||||||
|
ntf := &proto.AvatarLifeStateChangeNotify{
|
||||||
|
LifeState: uint32(avatarEntity.lifeState),
|
||||||
|
AttackTag: "",
|
||||||
|
DieType: dieType,
|
||||||
|
ServerBuffList: nil,
|
||||||
|
MoveReliableSeq: avatarEntity.lastMoveReliableSeq,
|
||||||
|
SourceEntityId: 0,
|
||||||
|
AvatarGuid: avatar.Guid,
|
||||||
|
}
|
||||||
|
g.SendToWorldA(world, cmd.AvatarLifeStateChangeNotify, 0, ntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) RevivePlayerAvatar(player *model.Player) {
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
activeAvatarId := world.GetPlayerActiveAvatarId(player)
|
||||||
|
worldAvatar := world.GetPlayerWorldAvatar(player, activeAvatarId)
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
avatarEntity := scene.GetEntity(worldAvatar.GetAvatarEntityId())
|
||||||
|
|
||||||
|
dbAvatar := player.GetDbAvatar()
|
||||||
|
avatar, exist := dbAvatar.AvatarMap[activeAvatarId]
|
||||||
|
if !exist {
|
||||||
|
logger.Error("get active avatar is nil, avatarId: %v", activeAvatarId)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
avatar.LifeState = constant.LIFE_STATE_ALIVE
|
||||||
|
// 设置血量
|
||||||
|
avatar.FightPropMap[constant.FIGHT_PROP_CUR_HP] = 110
|
||||||
|
g.EntityFightPropUpdateNotifyBroadcast(world, avatarEntity)
|
||||||
|
|
||||||
|
avatarEntity.lifeState = constant.LIFE_STATE_REVIVE
|
||||||
|
|
||||||
|
ntf := &proto.AvatarLifeStateChangeNotify{
|
||||||
|
AvatarGuid: avatar.Guid,
|
||||||
|
LifeState: uint32(avatarEntity.lifeState),
|
||||||
|
DieType: proto.PlayerDieType_PLAYER_DIE_NONE,
|
||||||
|
MoveReliableSeq: avatarEntity.lastMoveReliableSeq,
|
||||||
|
}
|
||||||
|
g.SendToWorldA(world, cmd.AvatarLifeStateChangeNotify, 0, ntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) KillEntity(scene *Scene, entityId uint32, dieType proto.PlayerDieType) {
|
||||||
|
entity := scene.GetEntity(entityId)
|
||||||
|
entity.lifeState = constant.LIFE_STATE_DEAD
|
||||||
|
// 设置血量
|
||||||
|
entity.fightProp[constant.FIGHT_PROP_CUR_HP] = 0
|
||||||
|
g.EntityFightPropUpdateNotifyBroadcast(scene.world, entity)
|
||||||
|
ntf := &proto.LifeStateChangeNotify{
|
||||||
|
EntityId: entity.id,
|
||||||
|
LifeState: uint32(entity.lifeState),
|
||||||
|
DieType: dieType,
|
||||||
|
MoveReliableSeq: entity.lastMoveReliableSeq,
|
||||||
|
}
|
||||||
|
g.SendToWorldA(scene.world, cmd.LifeStateChangeNotify, 0, ntf)
|
||||||
|
|
||||||
|
// 删除实体
|
||||||
|
scene.DestroyEntity(entity.id)
|
||||||
|
g.RemoveSceneEntityNotifyBroadcast(scene, proto.VisionType_VISION_DIE, []uint32{entity.id})
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) GetVisionEntity(scene *Scene, pos *model.Vector) map[uint32]*Entity {
|
||||||
|
visionEntity := make(map[uint32]*Entity)
|
||||||
|
for _, entity := range scene.GetAllEntity() {
|
||||||
|
if math.Abs(pos.X-entity.pos.X) > ENTITY_VISION_DISTANCE ||
|
||||||
|
math.Abs(pos.Z-entity.pos.Z) > ENTITY_VISION_DISTANCE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
visionEntity[entity.GetId()] = entity
|
||||||
|
}
|
||||||
|
return visionEntity
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) GetNeighborGroup(sceneId uint32, pos *model.Vector) map[uint32]*gdconf.Group {
|
||||||
|
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[sceneId]
|
||||||
|
if !exist {
|
||||||
|
logger.Error("scene not exist in aoi, sceneId: %v", sceneId)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
objectList := aoiManager.GetObjectListByPos(float32(pos.X), 0.0, float32(pos.Z))
|
||||||
|
neighborGroup := make(map[uint32]*gdconf.Group)
|
||||||
|
for _, groupAny := range objectList {
|
||||||
|
groupConfig := groupAny.(*gdconf.Group)
|
||||||
|
if math.Abs(pos.X-float64(groupConfig.Pos.X)) > GROUP_LOAD_DISTANCE ||
|
||||||
|
math.Abs(pos.Z-float64(groupConfig.Pos.Z)) > GROUP_LOAD_DISTANCE {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if groupConfig.DynamicLoad {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
neighborGroup[uint32(groupConfig.Id)] = groupConfig
|
||||||
|
}
|
||||||
|
return neighborGroup
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) AddSceneGroup(player *model.Player, scene *Scene, groupConfig *gdconf.Group) {
|
||||||
|
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
|
||||||
|
if initSuiteId < 1 || initSuiteId > len(groupConfig.SuiteList) {
|
||||||
|
logger.Error("invalid init suite id: %v, uid: %v", initSuiteId, player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
|
||||||
|
ntf := &proto.GroupSuiteNotify{
|
||||||
|
GroupMap: make(map[uint32]uint32),
|
||||||
|
}
|
||||||
|
ntf.GroupMap[uint32(groupConfig.Id)] = uint32(initSuiteId)
|
||||||
|
g.SendMsg(cmd.GroupSuiteNotify, player.PlayerID, player.ClientSeq, ntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) RemoveGroup(player *model.Player, scene *Scene, groupConfig *gdconf.Group) {
|
||||||
|
group := scene.GetGroupById(uint32(groupConfig.Id))
|
||||||
|
if group == nil {
|
||||||
|
logger.Error("group not exist, groupId: %v, uid: %v", groupConfig.Id, player.PlayerID)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for suiteId := range group.GetAllSuite() {
|
||||||
|
scene.RemoveGroupSuite(uint32(groupConfig.Id), suiteId)
|
||||||
|
}
|
||||||
|
ntf := &proto.GroupUnloadNotify{
|
||||||
|
GroupList: make([]uint32, 0),
|
||||||
|
}
|
||||||
|
ntf.GroupList = append(ntf.GroupList, uint32(groupConfig.Id))
|
||||||
|
g.SendMsg(cmd.GroupUnloadNotify, player.PlayerID, player.ClientSeq, ntf)
|
||||||
|
}
|
||||||
|
|
||||||
|
var SceneTransactionSeq uint32 = 0
|
||||||
|
|
||||||
|
func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify {
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
if scene == nil {
|
||||||
|
logger.Error("scene is nil, sceneId: %v", player.SceneId)
|
||||||
|
return new(proto.PlayerEnterSceneNotify)
|
||||||
|
}
|
||||||
|
enterSceneToken := world.AddEnterSceneContext(&EnterSceneContext{
|
||||||
|
OldSceneId: 0,
|
||||||
|
Uid: player.PlayerID,
|
||||||
|
})
|
||||||
|
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
|
||||||
|
SceneId: player.SceneId,
|
||||||
|
Pos: &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)},
|
||||||
|
SceneBeginTime: uint64(scene.GetSceneCreateTime()),
|
||||||
|
Type: enterType,
|
||||||
|
TargetUid: player.PlayerID,
|
||||||
|
EnterSceneToken: enterSceneToken,
|
||||||
|
WorldLevel: player.PropertiesMap[constant.PLAYER_PROP_PLAYER_WORLD_LEVEL],
|
||||||
|
EnterReason: uint32(proto.EnterReason_ENTER_REASON_LOGIN),
|
||||||
|
IsFirstLoginEnterScene: true,
|
||||||
|
WorldType: 1,
|
||||||
|
SceneTagIdList: make([]uint32, 0),
|
||||||
|
}
|
||||||
|
SceneTransactionSeq++
|
||||||
|
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
||||||
|
strconv.Itoa(int(player.PlayerID)) + "-" +
|
||||||
|
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
||||||
|
strconv.Itoa(int(SceneTransactionSeq))
|
||||||
|
for _, sceneTagDataConfig := range gdconf.GetSceneTagDataMap() {
|
||||||
|
if uint32(sceneTagDataConfig.SceneId) == player.SceneId {
|
||||||
|
playerEnterSceneNotify.SceneTagIdList = append(playerEnterSceneNotify.SceneTagIdList, uint32(sceneTagDataConfig.SceneTagId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return playerEnterSceneNotify
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) PacketPlayerEnterSceneNotifyTp(
|
||||||
|
player *model.Player,
|
||||||
|
enterType proto.EnterType,
|
||||||
|
enterReason uint32,
|
||||||
|
prevSceneId uint32,
|
||||||
|
prevPos *model.Vector,
|
||||||
|
dungeonId uint32,
|
||||||
|
) *proto.PlayerEnterSceneNotify {
|
||||||
|
return g.PacketPlayerEnterSceneNotifyMp(player, player, enterType, enterReason, prevSceneId, prevPos, dungeonId)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (g *GameManager) PacketPlayerEnterSceneNotifyMp(
|
||||||
|
player *model.Player,
|
||||||
|
targetPlayer *model.Player,
|
||||||
|
enterType proto.EnterType,
|
||||||
|
enterReason uint32,
|
||||||
|
prevSceneId uint32,
|
||||||
|
prevPos *model.Vector,
|
||||||
|
dungeonId uint32,
|
||||||
|
) *proto.PlayerEnterSceneNotify {
|
||||||
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
scene := world.GetSceneById(player.SceneId)
|
||||||
|
if scene == nil {
|
||||||
|
logger.Error("scene is nil, sceneId: %v", player.SceneId)
|
||||||
|
return new(proto.PlayerEnterSceneNotify)
|
||||||
|
}
|
||||||
|
enterSceneToken := world.AddEnterSceneContext(&EnterSceneContext{
|
||||||
|
OldSceneId: prevSceneId,
|
||||||
|
OldPos: &model.Vector{
|
||||||
|
X: prevPos.X,
|
||||||
|
Y: prevPos.Y,
|
||||||
|
Z: prevPos.Z,
|
||||||
|
},
|
||||||
|
OldRot: &model.Vector{
|
||||||
|
X: 0,
|
||||||
|
Y: 0,
|
||||||
|
Z: 0,
|
||||||
|
},
|
||||||
|
Uid: player.PlayerID,
|
||||||
|
})
|
||||||
|
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
|
||||||
|
PrevSceneId: prevSceneId,
|
||||||
|
PrevPos: &proto.Vector{X: float32(prevPos.X), Y: float32(prevPos.Y), Z: float32(prevPos.Z)},
|
||||||
|
SceneId: player.SceneId,
|
||||||
|
Pos: &proto.Vector{X: float32(player.Pos.X), Y: float32(player.Pos.Y), Z: float32(player.Pos.Z)},
|
||||||
|
SceneBeginTime: uint64(scene.GetSceneCreateTime()),
|
||||||
|
Type: enterType,
|
||||||
|
TargetUid: targetPlayer.PlayerID,
|
||||||
|
EnterSceneToken: enterSceneToken,
|
||||||
|
WorldLevel: targetPlayer.PropertiesMap[constant.PLAYER_PROP_PLAYER_WORLD_LEVEL],
|
||||||
|
EnterReason: enterReason,
|
||||||
|
WorldType: 1,
|
||||||
|
DungeonId: dungeonId,
|
||||||
|
SceneTagIdList: make([]uint32, 0),
|
||||||
|
}
|
||||||
|
SceneTransactionSeq++
|
||||||
|
playerEnterSceneNotify.SceneTransaction = strconv.Itoa(int(player.SceneId)) + "-" +
|
||||||
|
strconv.Itoa(int(targetPlayer.PlayerID)) + "-" +
|
||||||
|
strconv.Itoa(int(time.Now().Unix())) + "-" +
|
||||||
|
strconv.Itoa(int(SceneTransactionSeq))
|
||||||
|
for _, sceneTagDataConfig := range gdconf.GetSceneTagDataMap() {
|
||||||
|
if uint32(sceneTagDataConfig.SceneId) == player.SceneId {
|
||||||
|
playerEnterSceneNotify.SceneTagIdList = append(playerEnterSceneNotify.SceneTagIdList, uint32(sceneTagDataConfig.SceneTagId))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return playerEnterSceneNotify
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *GameManager) PacketFightPropMapToPbFightPropList(fightPropMap map[uint32]float32) []*proto.FightPropPair {
|
func (g *GameManager) PacketFightPropMapToPbFightPropList(fightPropMap map[uint32]float32) []*proto.FightPropPair {
|
||||||
|
|||||||
@@ -448,18 +448,6 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
if world == nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
scene := world.GetSceneById(player.SceneId)
|
|
||||||
activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player))
|
|
||||||
avatarEntity := scene.GetEntity(activeAvatar.GetAvatarEntityId())
|
|
||||||
if avatarEntity == nil {
|
|
||||||
logger.Error("avatar entity is nil, entityId: %v", activeAvatar.GetAvatarEntityId())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO 耐力未完成的内容:
|
// TODO 耐力未完成的内容:
|
||||||
// 一直溺水回到距离最近的位置 ?
|
// 一直溺水回到距离最近的位置 ?
|
||||||
// 溺水队伍扣血
|
// 溺水队伍扣血
|
||||||
@@ -470,7 +458,7 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
|
|||||||
// 先传送玩家再设置角色存活否则同时设置会传送前显示角色实体
|
// 先传送玩家再设置角色存活否则同时设置会传送前显示角色实体
|
||||||
if player.StaminaInfo.DrownBackDelay > 20 && player.SceneLoadState == model.SceneEnterDone {
|
if player.StaminaInfo.DrownBackDelay > 20 && player.SceneLoadState == model.SceneEnterDone {
|
||||||
// 设置角色存活
|
// 设置角色存活
|
||||||
scene.SetEntityLifeState(avatarEntity, constant.LIFE_STATE_REVIVE, proto.PlayerDieType_PLAYER_DIE_NONE)
|
g.RevivePlayerAvatar(player)
|
||||||
// 重置溺水返回时间
|
// 重置溺水返回时间
|
||||||
player.StaminaInfo.DrownBackDelay = 0
|
player.StaminaInfo.DrownBackDelay = 0
|
||||||
} else if player.StaminaInfo.DrownBackDelay == 20 {
|
} else if player.StaminaInfo.DrownBackDelay == 20 {
|
||||||
@@ -500,24 +488,11 @@ func (g *GameManager) HandleDrown(player *model.Player, stamina uint32) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
||||||
scene := world.GetSceneById(player.SceneId)
|
|
||||||
if scene == nil {
|
|
||||||
logger.Error("scene is nil, sceneId: %v", player.SceneId)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player))
|
|
||||||
avatarEntity := scene.GetEntity(activeAvatar.GetAvatarEntityId())
|
|
||||||
if avatarEntity == nil {
|
|
||||||
logger.Error("avatar entity is nil, entityId: %v", activeAvatar.GetAvatarEntityId())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// 确保玩家正在游泳
|
// 确保玩家正在游泳
|
||||||
if player.StaminaInfo.State == proto.MotionState_MOTION_SWIM_MOVE || player.StaminaInfo.State == proto.MotionState_MOTION_SWIM_DASH {
|
if player.StaminaInfo.State == proto.MotionState_MOTION_SWIM_MOVE || player.StaminaInfo.State == proto.MotionState_MOTION_SWIM_DASH {
|
||||||
logger.Debug("player drown, curStamina: %v, state: %v", stamina, player.StaminaInfo.State)
|
logger.Debug("player drown, curStamina: %v, state: %v", stamina, player.StaminaInfo.State)
|
||||||
// 设置角色为死亡
|
// 设置角色为死亡
|
||||||
scene.SetEntityLifeState(avatarEntity, constant.LIFE_STATE_DEAD, proto.PlayerDieType_PLAYER_DIE_DRAWN)
|
g.KillPlayerAvatar(player, proto.PlayerDieType_PLAYER_DIE_DRAWN)
|
||||||
// 溺水返回安全点 计时开始
|
// 溺水返回安全点 计时开始
|
||||||
player.StaminaInfo.DrownBackDelay = 1
|
player.StaminaInfo.DrownBackDelay = 1
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,6 +78,9 @@ func (g *GameManager) ChangeAvatarReq(player *model.Player, payloadMsg pb.Messag
|
|||||||
func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Message) {
|
func (g *GameManager) SetUpAvatarTeamReq(player *model.Player, payloadMsg pb.Message) {
|
||||||
req := payloadMsg.(*proto.SetUpAvatarTeamReq)
|
req := payloadMsg.(*proto.SetUpAvatarTeamReq)
|
||||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||||
|
if world == nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
if world.GetMultiplayer() {
|
if world.GetMultiplayer() {
|
||||||
g.SendError(cmd.SetUpAvatarTeamRsp, player, &proto.SetUpAvatarTeamRsp{})
|
g.SendError(cmd.SetUpAvatarTeamRsp, player, &proto.SetUpAvatarTeamRsp{})
|
||||||
return
|
return
|
||||||
|
|||||||
@@ -16,7 +16,7 @@ import (
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
ENTITY_NUM_UNLIMIT = true // 是否不限制场景内实体数量
|
ENTITY_NUM_UNLIMIT = true // 是否不限制场景内实体数量
|
||||||
ENTITY_MAX_SEND_NUM = 500 // 场景内最大实体数量
|
ENTITY_MAX_SEND_NUM = 1000 // 场景内最大实体数量
|
||||||
MAX_MULTIPLAYER_WORLD_NUM = 10 // 本服务器最大多人世界数量
|
MAX_MULTIPLAYER_WORLD_NUM = 10 // 本服务器最大多人世界数量
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -117,9 +117,7 @@ func (w *WorldManager) LoadSceneBlockAoiMap() {
|
|||||||
minZ := int16(0)
|
minZ := int16(0)
|
||||||
maxZ := int16(0)
|
maxZ := int16(0)
|
||||||
blockXLen := int16(0)
|
blockXLen := int16(0)
|
||||||
blockYLen := int16(0)
|
|
||||||
blockZLen := int16(0)
|
blockZLen := int16(0)
|
||||||
ok := true
|
|
||||||
for _, blockConfig := range sceneLuaConfig.BlockMap {
|
for _, blockConfig := range sceneLuaConfig.BlockMap {
|
||||||
if int16(blockConfig.BlockRange.Min.X) < minX {
|
if int16(blockConfig.BlockRange.Min.X) < minX {
|
||||||
minX = int16(blockConfig.BlockRange.Min.X)
|
minX = int16(blockConfig.BlockRange.Min.X)
|
||||||
@@ -134,54 +132,37 @@ func (w *WorldManager) LoadSceneBlockAoiMap() {
|
|||||||
maxZ = int16(blockConfig.BlockRange.Max.Z)
|
maxZ = int16(blockConfig.BlockRange.Max.Z)
|
||||||
}
|
}
|
||||||
xLen := int16(blockConfig.BlockRange.Max.X - blockConfig.BlockRange.Min.X)
|
xLen := int16(blockConfig.BlockRange.Max.X - blockConfig.BlockRange.Min.X)
|
||||||
yLen := int16(blockConfig.BlockRange.Max.Y - blockConfig.BlockRange.Min.Y)
|
|
||||||
zLen := int16(blockConfig.BlockRange.Max.Z - blockConfig.BlockRange.Min.Z)
|
zLen := int16(blockConfig.BlockRange.Max.Z - blockConfig.BlockRange.Min.Z)
|
||||||
if blockXLen == 0 {
|
if blockXLen == 0 {
|
||||||
blockXLen = xLen
|
blockXLen = xLen
|
||||||
} else {
|
} else {
|
||||||
if blockXLen != xLen {
|
if blockXLen != xLen {
|
||||||
ok = false
|
logger.Error("config scene block size not same, scene id: %v", sceneLuaConfig.Id)
|
||||||
break
|
return
|
||||||
}
|
|
||||||
}
|
|
||||||
if blockYLen == 0 {
|
|
||||||
blockYLen = yLen
|
|
||||||
} else {
|
|
||||||
if blockYLen != yLen {
|
|
||||||
ok = false
|
|
||||||
break
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if blockZLen == 0 {
|
if blockZLen == 0 {
|
||||||
blockZLen = zLen
|
blockZLen = zLen
|
||||||
} else {
|
} else {
|
||||||
if blockZLen != zLen {
|
if blockZLen != zLen {
|
||||||
ok = false
|
logger.Error("config scene block size not same, scene id: %v", sceneLuaConfig.Id)
|
||||||
break
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if !ok {
|
|
||||||
logger.Error("config scene block size not same, scene id: %v", sceneLuaConfig.Id)
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
numX := int16(0)
|
numX := int16(0)
|
||||||
if blockXLen != 0 {
|
if (maxX-minX) != 0 && blockXLen != 0 {
|
||||||
numX = (maxX - minX) / blockXLen
|
numX = (maxX - minX) / blockXLen
|
||||||
} else {
|
} else {
|
||||||
numX = 1
|
logger.Error("config scene block size is zero, scene id: %v", sceneLuaConfig.Id)
|
||||||
}
|
return
|
||||||
if numX == 0 {
|
|
||||||
numX = 1
|
|
||||||
}
|
}
|
||||||
numZ := int16(0)
|
numZ := int16(0)
|
||||||
if blockZLen != 0 {
|
if (maxZ-minZ) != 0 && blockZLen != 0 {
|
||||||
numZ = (maxZ - minZ) / blockZLen
|
numZ = (maxZ - minZ) / blockZLen
|
||||||
} else {
|
} else {
|
||||||
numZ = 1
|
logger.Error("config scene block size is zero, scene id: %v", sceneLuaConfig.Id)
|
||||||
}
|
return
|
||||||
if numZ == 0 {
|
|
||||||
numZ = 1
|
|
||||||
}
|
}
|
||||||
// 将每个block作为aoi格子 并在格子中放入block拥有的所有group
|
// 将每个block作为aoi格子 并在格子中放入block拥有的所有group
|
||||||
aoiManager := alg.NewAoiManager()
|
aoiManager := alg.NewAoiManager()
|
||||||
|
|||||||
@@ -8,7 +8,6 @@ import (
|
|||||||
"hk4e/gdconf"
|
"hk4e/gdconf"
|
||||||
"hk4e/gs/model"
|
"hk4e/gs/model"
|
||||||
"hk4e/pkg/logger"
|
"hk4e/pkg/logger"
|
||||||
"hk4e/protocol/cmd"
|
|
||||||
"hk4e/protocol/proto"
|
"hk4e/protocol/proto"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -87,65 +86,6 @@ func (s *Scene) RemovePlayer(player *model.Player) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType proto.PlayerDieType) {
|
|
||||||
if entity.GetEntityType() == constant.ENTITY_TYPE_AVATAR {
|
|
||||||
// 获取玩家对象
|
|
||||||
player := USER_MANAGER.GetOnlineUser(entity.avatarEntity.uid)
|
|
||||||
if player == nil {
|
|
||||||
logger.Error("player is nil, uid: %v", entity.avatarEntity.uid)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 获取角色
|
|
||||||
dbAvatar := player.GetDbAvatar()
|
|
||||||
avatar, ok := dbAvatar.AvatarMap[entity.avatarEntity.avatarId]
|
|
||||||
if !ok {
|
|
||||||
logger.Error("avatar is nil, avatarId: %v", avatar)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
// 设置角色存活状态
|
|
||||||
if lifeState == constant.LIFE_STATE_REVIVE {
|
|
||||||
avatar.LifeState = constant.LIFE_STATE_ALIVE
|
|
||||||
// 设置血量
|
|
||||||
entity.fightProp[constant.FIGHT_PROP_CUR_HP] = 110
|
|
||||||
GAME_MANAGER.EntityFightPropUpdateNotifyBroadcast(s, entity, constant.FIGHT_PROP_CUR_HP)
|
|
||||||
}
|
|
||||||
|
|
||||||
avatarLifeStateChangeNotify := &proto.AvatarLifeStateChangeNotify{
|
|
||||||
LifeState: uint32(lifeState),
|
|
||||||
AttackTag: "",
|
|
||||||
DieType: dieType,
|
|
||||||
ServerBuffList: nil,
|
|
||||||
MoveReliableSeq: entity.lastMoveReliableSeq,
|
|
||||||
SourceEntityId: 0,
|
|
||||||
AvatarGuid: avatar.Guid,
|
|
||||||
}
|
|
||||||
GAME_MANAGER.SendToWorldA(s.world, cmd.AvatarLifeStateChangeNotify, 0, avatarLifeStateChangeNotify)
|
|
||||||
} else {
|
|
||||||
// 设置存活状态
|
|
||||||
entity.lifeState = lifeState
|
|
||||||
|
|
||||||
if lifeState == constant.LIFE_STATE_DEAD {
|
|
||||||
// 设置血量
|
|
||||||
entity.fightProp[constant.FIGHT_PROP_CUR_HP] = 0
|
|
||||||
GAME_MANAGER.EntityFightPropUpdateNotifyBroadcast(s, entity, constant.FIGHT_PROP_CUR_HP)
|
|
||||||
}
|
|
||||||
|
|
||||||
lifeStateChangeNotify := &proto.LifeStateChangeNotify{
|
|
||||||
EntityId: entity.id,
|
|
||||||
AttackTag: "",
|
|
||||||
MoveReliableSeq: entity.lastMoveReliableSeq,
|
|
||||||
DieType: dieType,
|
|
||||||
LifeState: uint32(lifeState),
|
|
||||||
SourceEntityId: 0,
|
|
||||||
}
|
|
||||||
GAME_MANAGER.SendToWorldA(s.world, cmd.LifeStateChangeNotify, 0, lifeStateChangeNotify)
|
|
||||||
|
|
||||||
// 删除实体
|
|
||||||
s.DestroyEntity(entity.id)
|
|
||||||
GAME_MANAGER.RemoveSceneEntityNotifyBroadcast(s, proto.VisionType_VISION_DIE, []uint32{entity.id})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 {
|
func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32 {
|
||||||
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_AVATAR)
|
entityId := s.world.GetNextWorldEntityId(constant.ENTITY_TYPE_AVATAR)
|
||||||
dbAvatar := player.GetDbAvatar()
|
dbAvatar := player.GetDbAvatar()
|
||||||
@@ -185,8 +125,12 @@ func (s *Scene) CreateEntityWeapon() uint32 {
|
|||||||
moveState: uint16(proto.MotionState_MOTION_NONE),
|
moveState: uint16(proto.MotionState_MOTION_NONE),
|
||||||
lastMoveSceneTimeMs: 0,
|
lastMoveSceneTimeMs: 0,
|
||||||
lastMoveReliableSeq: 0,
|
lastMoveReliableSeq: 0,
|
||||||
fightProp: nil,
|
fightProp: map[uint32]float32{
|
||||||
entityType: constant.ENTITY_TYPE_WEAPON,
|
constant.FIGHT_PROP_CUR_HP: math.MaxFloat32,
|
||||||
|
constant.FIGHT_PROP_MAX_HP: math.MaxFloat32,
|
||||||
|
constant.FIGHT_PROP_BASE_HP: float32(1),
|
||||||
|
},
|
||||||
|
entityType: constant.ENTITY_TYPE_WEAPON,
|
||||||
}
|
}
|
||||||
s.CreateEntity(entity)
|
s.CreateEntity(entity)
|
||||||
return entity.id
|
return entity.id
|
||||||
|
|||||||
Reference in New Issue
Block a user