地牢场景传送

This commit is contained in:
flswld
2023-03-24 17:37:20 +08:00
parent 729efa900e
commit e3242cf894
11 changed files with 243 additions and 123 deletions

View File

@@ -160,13 +160,13 @@ func (c *CommandManager) TeleportCommand(cmd *CommandMessage) {
c.SendMessage(cmd.Executor, "已将玩家 UID%v 请求加入目标玩家 UID%v 的世界。", player.PlayerID, targetUid)
} else {
// 传送玩家至目标玩家的位置
c.gmCmd.GMTeleportPlayer(player.PlayerID, target.SceneId, target.Pos.X, target.Pos.Y, target.Pos.Z)
c.gmCmd.GMTeleportPlayer(player.PlayerID, target.SceneId, 0, target.Pos.X, target.Pos.Y, target.Pos.Z)
// 发送消息给执行者
c.SendMessage(cmd.Executor, "已将玩家 UID%v 传送至 目标玩家 UID%v。", player.PlayerID, targetUid)
}
} else {
// 传送玩家至指定的位置
c.gmCmd.GMTeleportPlayer(player.PlayerID, sceneId, pos.X, pos.Y, pos.Z)
c.gmCmd.GMTeleportPlayer(player.PlayerID, sceneId, 0, pos.X, pos.Y, pos.Z)
// 发送消息给执行者
c.SendMessage(cmd.Executor, "已将玩家 UID%v 传送至 场景:%v, X%.2f, Y%.2f, Z%.2f。", player.PlayerID, sceneId, pos.X, pos.Y, pos.Z)
}

View File

@@ -19,7 +19,7 @@ type GMCmd struct {
// 玩家通用GM指令
// GMTeleportPlayer 传送玩家
func (g *GMCmd) GMTeleportPlayer(userId, sceneId uint32, posX, posY, posZ float64) {
func (g *GMCmd) GMTeleportPlayer(userId, sceneId, dungeonId uint32, posX, posY, posZ float64) {
player := USER_MANAGER.GetOnlineUser(userId)
if player == nil {
logger.Error("player is nil, uid: %v", userId)
@@ -29,7 +29,7 @@ func (g *GMCmd) GMTeleportPlayer(userId, sceneId uint32, posX, posY, posZ float6
X: posX,
Y: posY,
Z: posZ,
}, new(model.Vector), 0)
}, new(model.Vector), dungeonId)
}
// GMAddUserItem 给予玩家物品

View File

@@ -187,7 +187,7 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata
sceneLuaConfig := gdconf.GetSceneLuaConfigById(int32(player.SceneId))
if sceneLuaConfig == nil {
logger.Error("get scene lua config is nil, sceneId: %v", player.SceneId)
logger.Error("get scene lua config is nil, sceneId: %v, uid: %v", player.SceneId, player.PlayerID)
return nil
}
player.SafePos = &model.Vector{

View File

@@ -16,6 +16,8 @@ import (
pb "google.golang.org/protobuf/proto"
)
// 场景模块 场景组 小组 实体 管理相关
const (
ENTITY_MAX_BATCH_SEND_NUM = 1000 // 单次同步的最大实体数量
ENTITY_LOD = 100 // 实体加载视野距离
@@ -381,31 +383,6 @@ func (g *GameManager) PostEnterSceneReq(player *model.Player, payloadMsg pb.Mess
g.SendMsg(cmd.PostEnterSceneRsp, player.PlayerID, player.ClientSeq, postEnterSceneRsp)
}
func (g *GameManager) ChangeGameTimeReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.ChangeGameTimeReq)
gameTime := req.GameTime
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
if scene == nil {
logger.Error("scene is nil, sceneId: %v", player.SceneId)
return
}
scene.ChangeGameTime(gameTime)
for _, scenePlayer := range scene.GetAllPlayer() {
playerGameTimeNotify := &proto.PlayerGameTimeNotify{
GameTime: scene.GetGameTime(),
Uid: scenePlayer.PlayerID,
}
g.SendMsg(cmd.PlayerGameTimeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, playerGameTimeNotify)
}
changeGameTimeRsp := &proto.ChangeGameTimeRsp{
CurGameTime: scene.GetGameTime(),
}
g.SendMsg(cmd.ChangeGameTimeRsp, player.PlayerID, player.ClientSeq, changeGameTimeRsp)
}
func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.SceneEntityDrownReq)
@@ -414,7 +391,8 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
return
}
scene := world.GetSceneById(player.SceneId)
scene.DestroyEntity(req.EntityId)
entity := scene.GetEntity(req.EntityId)
scene.SetEntityLifeState(entity, constant.LIFE_STATE_DEAD, proto.PlayerDieType_PLAYER_DIE_DRAWN)
sceneEntityDrownRsp := &proto.SceneEntityDrownRsp{
EntityId: req.EntityId,
@@ -422,16 +400,6 @@ func (g *GameManager) SceneEntityDrownReq(player *model.Player, payloadMsg pb.Me
g.SendMsg(cmd.SceneEntityDrownRsp, player.PlayerID, player.ClientSeq, sceneEntityDrownRsp)
}
func (g *GameManager) NpcTalkReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.NpcTalkReq)
rsp := &proto.NpcTalkRsp{
CurTalkId: req.TalkId,
NpcEntityId: req.NpcEntityId,
EntityId: req.EntityId,
}
g.SendMsg(cmd.NpcTalkRsp, player.PlayerID, player.ClientSeq, rsp)
}
var SceneTransactionSeq uint32 = 0
func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, enterType proto.EnterType) *proto.PlayerEnterSceneNotify {
@@ -443,6 +411,7 @@ func (g *GameManager) PacketPlayerEnterSceneNotifyLogin(player *model.Player, en
}
enterSceneToken := world.AddEnterSceneContext(&EnterSceneContext{
OldSceneId: 0,
Uid: player.PlayerID,
})
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
SceneId: player.SceneId,
@@ -503,6 +472,12 @@ func (g *GameManager) PacketPlayerEnterSceneNotifyMp(
Y: prevPos.Y,
Z: prevPos.Z,
},
OldRot: &model.Vector{
X: 0,
Y: 0,
Z: 0,
},
Uid: player.PlayerID,
})
playerEnterSceneNotify := &proto.PlayerEnterSceneNotify{
PrevSceneId: prevSceneId,

View File

@@ -277,18 +277,15 @@ func (g *GameManager) SkillStartStamina(player *model.Player, casterId uint32, s
// VehicleRestoreStaminaHandler 处理载具持续回复耐力
func (g *GameManager) VehicleRestoreStaminaHandler(player *model.Player) {
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
if scene == nil {
logger.Error("scene is nil, sceneId: %v", player.SceneId)
return
}
// 玩家暂停状态不更新耐力
if player.Pause {
return
}
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil {
return
}
scene := world.GetSceneById(player.SceneId)
// 获取玩家创建的载具实体
entity := scene.GetEntity(player.VehicleInfo.InVehicleEntityId)
if entity == nil {
@@ -311,16 +308,15 @@ func (g *GameManager) VehicleRestoreStaminaHandler(player *model.Player) {
// SustainStaminaHandler 处理持续耐力消耗
func (g *GameManager) SustainStaminaHandler(player *model.Player) {
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
if scene == nil {
logger.Error("scene is nil, sceneId: %v", player.SceneId)
return
}
// 玩家暂停状态不更新耐力
if player.Pause {
return
}
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil {
return
}
scene := world.GetSceneById(player.SceneId)
// 获取玩家处于的载具实体
entity := scene.GetEntity(player.VehicleInfo.InVehicleEntityId)
if entity == nil {
@@ -453,11 +449,10 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
}
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
if scene == nil {
logger.Error("scene is nil, sceneId: %v", player.SceneId)
if world == nil {
return
}
scene := world.GetSceneById(player.SceneId)
activeAvatar := world.GetPlayerWorldAvatar(player, world.GetPlayerActiveAvatarId(player))
avatarEntity := scene.GetEntity(activeAvatar.GetAvatarEntityId())
if avatarEntity == nil {
@@ -489,22 +484,6 @@ func (g *GameManager) DrownBackHandler(player *model.Player) {
Y: player.SafePos.Y,
Z: player.SafePos.Z,
}
// 获取最近角色实体的锚点
// TODO 阻塞优化 16ms我感觉有点慢
// for _, entry := range gdc.CONF.ScenePointEntries {
// if entry.PointData == nil || entry.PointData.TranPos == nil {
// continue
// }
// pointPos := &model.Vector{
// X: entry.PointData.TranPos.X,
// Y: entry.PointData.TranPos.Y,
// Z: entry.PointData.TranPos.Z,
// }
// // 该坐标距离小于之前的则赋值
// if player.SafePos.Distance(pointPos) < player.SafePos.Distance(pos) {
// pos = pointPos
// }
// }
// 传送玩家至安全位置
g.TeleportPlayer(player, uint16(proto.EnterReason_ENTER_REASON_REVIVAL), player.SceneId, pos, new(model.Vector), 0)
}

View File

@@ -13,9 +13,10 @@ import (
pb "google.golang.org/protobuf/proto"
)
// 大地图模块 大世界相关的所有逻辑
func (g *GameManager) SceneTransToPointReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.SceneTransToPointReq)
dbWorld := player.GetDbWorld()
dbScene := dbWorld.GetSceneById(req.SceneId)
if dbScene == nil {
@@ -32,9 +33,9 @@ func (g *GameManager) SceneTransToPointReq(player *model.Player, payloadMsg pb.M
g.SendError(cmd.SceneTransToPointRsp, player, &proto.SceneTransToPointRsp{}, proto.Retcode_RET_POINT_NOT_UNLOCKED)
return
}
// 传送玩家
sceneId := req.SceneId
g.TeleportPlayer(player, uint16(proto.EnterReason_ENTER_REASON_TRANS_POINT), sceneId, &model.Vector{
g.TeleportPlayer(player, uint16(proto.EnterReason_ENTER_REASON_TRANS_POINT), req.SceneId, &model.Vector{
X: pointDataConfig.TranPos.X,
Y: pointDataConfig.TranPos.Y,
Z: pointDataConfig.TranPos.Z,
@@ -112,9 +113,9 @@ func (g *GameManager) GetScenePointReq(player *model.Player, payloadMsg pb.Messa
func (g *GameManager) MarkMapReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.MarkMapReq)
operation := req.Op
if operation == proto.MarkMapReq_ADD {
if req.Op == proto.MarkMapReq_ADD {
logger.Debug("user mark type: %v", req.Mark.PointType)
// 地图标点传送
if req.Mark.PointType == proto.MapMarkPointType_NPC {
posYInt, err := strconv.ParseInt(req.Mark.Name, 10, 64)
if err != nil {
@@ -129,6 +130,7 @@ func (g *GameManager) MarkMapReq(player *model.Player, payloadMsg pb.Message) {
}, new(model.Vector), 0)
}
}
g.SendMsg(cmd.MarkMapRsp, player.PlayerID, player.ClientSeq, &proto.MarkMapRsp{})
}
func (g *GameManager) GetSceneAreaReq(player *model.Player, payloadMsg pb.Message) {
@@ -176,6 +178,112 @@ func (g *GameManager) EnterWorldAreaReq(player *model.Player, payloadMsg pb.Mess
g.SendMsg(cmd.EnterWorldAreaRsp, player.PlayerID, player.ClientSeq, enterWorldAreaRsp)
}
func (g *GameManager) ChangeGameTimeReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.ChangeGameTimeReq)
gameTime := req.GameTime
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
scene := world.GetSceneById(player.SceneId)
if scene == nil {
logger.Error("scene is nil, sceneId: %v", player.SceneId)
return
}
scene.ChangeGameTime(gameTime)
for _, scenePlayer := range scene.GetAllPlayer() {
playerGameTimeNotify := &proto.PlayerGameTimeNotify{
GameTime: scene.GetGameTime(),
Uid: scenePlayer.PlayerID,
}
g.SendMsg(cmd.PlayerGameTimeNotify, scenePlayer.PlayerID, scenePlayer.ClientSeq, playerGameTimeNotify)
}
changeGameTimeRsp := &proto.ChangeGameTimeRsp{
CurGameTime: scene.GetGameTime(),
}
g.SendMsg(cmd.ChangeGameTimeRsp, player.PlayerID, player.ClientSeq, changeGameTimeRsp)
}
func (g *GameManager) NpcTalkReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.NpcTalkReq)
rsp := &proto.NpcTalkRsp{
CurTalkId: req.TalkId,
NpcEntityId: req.NpcEntityId,
EntityId: req.EntityId,
}
g.SendMsg(cmd.NpcTalkRsp, player.PlayerID, player.ClientSeq, rsp)
}
func (g *GameManager) DungeonEntryInfoReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.DungeonEntryInfoReq)
pointDataConfig := gdconf.GetScenePointBySceneIdAndPointId(int32(req.SceneId), int32(req.PointId))
if pointDataConfig == nil {
g.SendError(cmd.DungeonEntryInfoRsp, player, &proto.DungeonEntryInfoRsp{})
return
}
rsp := &proto.DungeonEntryInfoRsp{
DungeonEntryList: make([]*proto.DungeonEntryInfo, 0),
PointId: req.PointId,
}
for _, dungeonId := range pointDataConfig.DungeonIds {
rsp.DungeonEntryList = append(rsp.DungeonEntryList, &proto.DungeonEntryInfo{
DungeonId: uint32(dungeonId),
})
}
g.SendMsg(cmd.DungeonEntryInfoRsp, player.PlayerID, player.ClientSeq, rsp)
}
func (g *GameManager) PlayerEnterDungeonReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.PlayerEnterDungeonReq)
dungeonDataConfig := gdconf.GetDungeonDataById(int32(req.DungeonId))
if dungeonDataConfig == nil {
logger.Error("get dungeon data config is nil, dungeonId: %v, uid: %v", req.DungeonId, player.PlayerID)
return
}
sceneLuaConfig := gdconf.GetSceneLuaConfigById(dungeonDataConfig.SceneId)
if sceneLuaConfig == nil {
logger.Error("get scene lua config is nil, sceneId: %v, uid: %v", dungeonDataConfig.SceneId, player.PlayerID)
return
}
g.TeleportPlayer(player, uint16(proto.EnterReason_ENTER_REASON_DUNGEON_ENTER), uint32(dungeonDataConfig.SceneId), &model.Vector{
X: float64(sceneLuaConfig.SceneConfig.BornPos.X),
Y: float64(sceneLuaConfig.SceneConfig.BornPos.Y),
Z: float64(sceneLuaConfig.SceneConfig.BornPos.Z),
}, &model.Vector{
X: float64(sceneLuaConfig.SceneConfig.BornRot.X),
Y: float64(sceneLuaConfig.SceneConfig.BornRot.Y),
Z: float64(sceneLuaConfig.SceneConfig.BornRot.Z),
}, req.DungeonId)
rsp := &proto.PlayerEnterDungeonRsp{
DungeonId: req.DungeonId,
PointId: req.PointId,
}
g.SendMsg(cmd.PlayerEnterDungeonRsp, player.PlayerID, player.ClientSeq, rsp)
}
func (g *GameManager) PlayerQuitDungeonReq(player *model.Player, payloadMsg pb.Message) {
req := payloadMsg.(*proto.PlayerQuitDungeonReq)
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
if world == nil {
return
}
ctx := world.GetLastEnterSceneContextBySceneIdAndUid(3, player.PlayerID)
if ctx == nil {
return
}
g.TeleportPlayer(player, uint16(proto.EnterReason_ENTER_REASON_DUNGEON_QUIT), 3, &model.Vector{
X: ctx.OldPos.X,
Y: ctx.OldPos.Y,
Z: ctx.OldPos.Z,
}, new(model.Vector), 0)
rsp := &proto.PlayerQuitDungeonRsp{
PointId: req.PointId,
}
g.SendMsg(cmd.PlayerQuitDungeonRsp, player.PlayerID, player.ClientSeq, rsp)
}
// TeleportPlayer 传送玩家至地图上的某个位置
func (g *GameManager) TeleportPlayer(player *model.Player, enterReason uint16, sceneId uint32, pos, rot *model.Vector, dungeonId uint32) {
// 传送玩家
@@ -221,18 +329,16 @@ func (g *GameManager) TeleportPlayer(player *model.Player, enterReason uint16, s
player.Rot.Z = rot.Z
var enterType proto.EnterType
switch enterReason {
case uint16(proto.EnterReason_ENTER_REASON_DUNGEON_ENTER):
logger.Debug("player tp to dungeon scene, sceneId: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_DUNGEON
default:
if jumpScene {
logger.Debug("player jump scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_JUMP
} else {
logger.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_GOTO
if jumpScene {
logger.Debug("player jump scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_JUMP
if enterReason == uint16(proto.EnterReason_ENTER_REASON_DUNGEON_ENTER) {
logger.Debug("player tp to dungeon scene, sceneId: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_DUNGEON
}
} else {
logger.Debug("player goto scene, scene: %v, pos: %v", player.SceneId, player.Pos)
enterType = proto.EnterType_ENTER_GOTO
}
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyTp(player, enterType, uint32(enterReason), oldSceneId, oldPos, dungeonId)
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)

View File

@@ -145,6 +145,9 @@ func (r *RouteManager) initRoute() {
r.registerRouter(cmd.EvtAiSyncCombatThreatInfoNotify, GAME_MANAGER.EvtAiSyncCombatThreatInfoNotify)
r.registerRouter(cmd.EntityConfigHashNotify, GAME_MANAGER.EntityConfigHashNotify)
r.registerRouter(cmd.MonsterAIConfigHashNotify, GAME_MANAGER.MonsterAIConfigHashNotify)
r.registerRouter(cmd.DungeonEntryInfoReq, GAME_MANAGER.DungeonEntryInfoReq)
r.registerRouter(cmd.PlayerEnterDungeonReq, GAME_MANAGER.PlayerEnterDungeonReq)
r.registerRouter(cmd.PlayerQuitDungeonReq, GAME_MANAGER.PlayerQuitDungeonReq)
}
func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {

View File

@@ -207,6 +207,8 @@ func (w *WorldManager) GetMultiplayerWorldNum() uint32 {
type EnterSceneContext struct {
OldSceneId uint32
OldPos *model.Vector
OldRot *model.Vector
Uid uint32
}
// World 世界数据结构
@@ -258,6 +260,23 @@ func (w *World) AddEnterSceneContext(ctx *EnterSceneContext) uint32 {
return w.enterSceneToken
}
func (w *World) GetLastEnterSceneContextBySceneIdAndUid(sceneId uint32, uid uint32) *EnterSceneContext {
for token := w.enterSceneToken; token >= 5000; token -= 100 {
ctx, exist := w.enterSceneContextMap[token]
if !exist {
continue
}
if ctx.OldSceneId != sceneId {
continue
}
if ctx.Uid != uid {
continue
}
return ctx
}
return nil
}
func (w *World) GetWorldLevel() uint8 {
return w.worldLevel
}