mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:52:27 +08:00
寻路服务器
This commit is contained in:
@@ -95,42 +95,3 @@ func (g *GameDataConfig) loadAll() {
|
||||
g.excelBinPrefix += "/"
|
||||
g.load()
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) ReadWorldTerrain() []byte {
|
||||
resourcePath := g.getResourcePathPrefix()
|
||||
dirInfo, err := os.Stat(resourcePath)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.Error("open game data config dir error: %v", err)
|
||||
return nil
|
||||
}
|
||||
dirInfo, err = os.Stat(resourcePath + "/WorldStatic")
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.Error("open game data world static dir error: %v", err)
|
||||
return nil
|
||||
}
|
||||
data, err := os.ReadFile(resourcePath + "/WorldStatic/world_terrain.bin")
|
||||
if err != nil {
|
||||
logger.Error("read world terrain file error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return data
|
||||
}
|
||||
|
||||
func (g *GameDataConfig) WriteWorldTerrain(data []byte) {
|
||||
resourcePath := g.getResourcePathPrefix()
|
||||
dirInfo, err := os.Stat(resourcePath)
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.Error("open game data config dir error: %v", err)
|
||||
return
|
||||
}
|
||||
dirInfo, err = os.Stat(resourcePath + "/WorldStatic")
|
||||
if err != nil || !dirInfo.IsDir() {
|
||||
logger.Error("open game data world static dir error: %v", err)
|
||||
return
|
||||
}
|
||||
err = os.WriteFile(resourcePath+"/WorldStatic/world_terrain.bin", data, 0644)
|
||||
if err != nil {
|
||||
logger.Error("write world terrain file error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
@@ -140,7 +140,6 @@ func (g *GameManager) Stop() {
|
||||
EventId: RunUserCopyAndSave,
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
// g.worldManager.worldStatic.SaveTerrain()
|
||||
}
|
||||
|
||||
// SendMsg 发送消息给客户端
|
||||
|
||||
@@ -66,7 +66,6 @@ func (r *RouteManager) InitRoute() {
|
||||
r.registerRouter(cmd.ChooseCurAvatarTeamReq, GAME_MANAGER.ChooseCurAvatarTeamReq)
|
||||
r.registerRouter(cmd.GetGachaInfoReq, GAME_MANAGER.GetGachaInfoReq)
|
||||
r.registerRouter(cmd.DoGachaReq, GAME_MANAGER.DoGachaReq)
|
||||
r.registerRouter(cmd.QueryPathReq, GAME_MANAGER.QueryPathReq)
|
||||
r.registerRouter(cmd.CombatInvocationsNotify, GAME_MANAGER.CombatInvocationsNotify)
|
||||
r.registerRouter(cmd.AbilityInvocationsNotify, GAME_MANAGER.AbilityInvocationsNotify)
|
||||
r.registerRouter(cmd.ClientAbilityInitFinishNotify, GAME_MANAGER.ClientAbilityInitFinishNotify)
|
||||
|
||||
@@ -209,19 +209,19 @@ func (t *TickManager) onTickSecond(now int64) {
|
||||
worldPlayerRTTNotify.PlayerRttList = append(worldPlayerRTTNotify.PlayerRttList, playerRTTInfo)
|
||||
}
|
||||
GAME_MANAGER.SendMsg(cmd.WorldPlayerRTTNotify, player.PlayerID, 0, worldPlayerRTTNotify)
|
||||
}
|
||||
if !world.IsBigWorld() && world.owner.SceneLoadState == model.SceneEnterDone {
|
||||
// 刷怪
|
||||
scene := world.GetSceneById(3)
|
||||
monsterEntityCount := 0
|
||||
for _, entity := range scene.entityMap {
|
||||
if entity.entityType == uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER) {
|
||||
monsterEntityCount++
|
||||
if !world.IsBigWorld() && world.owner.SceneLoadState == model.SceneEnterDone {
|
||||
scene := world.GetSceneById(3)
|
||||
monsterEntityCount := 0
|
||||
for _, entity := range scene.entityMap {
|
||||
if entity.entityType == uint32(proto.ProtEntityType_PROT_ENTITY_TYPE_MONSTER) {
|
||||
monsterEntityCount++
|
||||
}
|
||||
}
|
||||
if monsterEntityCount < 30 {
|
||||
monsterEntityId := t.createMonster(world.owner, scene)
|
||||
GAME_MANAGER.AddSceneEntityNotify(world.owner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true, false)
|
||||
}
|
||||
}
|
||||
if monsterEntityCount < 30 {
|
||||
monsterEntityId := t.createMonster(scene)
|
||||
GAME_MANAGER.AddSceneEntityNotify(world.owner, proto.VisionType_VISION_TYPE_BORN, []uint32{monsterEntityId}, true, false)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +241,7 @@ func (t *TickManager) onTick200MilliSecond(now int64) {
|
||||
func (t *TickManager) onTick100MilliSecond(now int64) {
|
||||
}
|
||||
|
||||
func (t *TickManager) createMonster(scene *Scene) uint32 {
|
||||
func (t *TickManager) createMonster(player *model.Player, scene *Scene) uint32 {
|
||||
pos := &model.Vector{
|
||||
X: 2747,
|
||||
Y: 194,
|
||||
|
||||
@@ -108,6 +108,13 @@ func (g *GameManager) ToTheMoonEnterSceneReq(player *model.Player, payloadMsg pb
|
||||
g.SendMsg(cmd.ToTheMoonEnterSceneRsp, player.PlayerID, player.ClientSeq, new(proto.ToTheMoonEnterSceneRsp))
|
||||
}
|
||||
|
||||
func (g *GameManager) PathfindingEnterSceneReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user pf enter scene, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.PathfindingEnterSceneReq)
|
||||
_ = req
|
||||
g.SendMsg(cmd.PathfindingEnterSceneRsp, player.PlayerID, player.ClientSeq, new(proto.PathfindingEnterSceneRsp))
|
||||
}
|
||||
|
||||
func (g *GameManager) SetEntityClientDataNotify(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user set entity client data, uid: %v", player.PlayerID)
|
||||
ntf := payloadMsg.(*proto.SetEntityClientDataNotify)
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"hk4e/gs/constant"
|
||||
"strconv"
|
||||
|
||||
"hk4e/gs/constant"
|
||||
|
||||
gdc "hk4e/gs/config"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
@@ -108,23 +109,6 @@ func (g *GameManager) TeleportPlayer(player *model.Player, enterReason uint32, s
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) PathfindingEnterSceneReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user pathfinding enter scene, uid: %v", player.PlayerID)
|
||||
g.SendMsg(cmd.PathfindingEnterSceneRsp, player.PlayerID, player.ClientSeq, new(proto.PathfindingEnterSceneRsp))
|
||||
}
|
||||
|
||||
func (g *GameManager) QueryPathReq(player *model.Player, payloadMsg pb.Message) {
|
||||
// logger.Debug("user query path, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.QueryPathReq)
|
||||
|
||||
queryPathRsp := &proto.QueryPathRsp{
|
||||
Corners: []*proto.Vector{req.DestinationPos[0]},
|
||||
QueryId: req.QueryId,
|
||||
QueryStatus: proto.QueryPathRsp_PATH_STATUS_TYPE_SUCC,
|
||||
}
|
||||
g.SendMsg(cmd.QueryPathRsp, player.PlayerID, player.ClientSeq, queryPathRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) GetScenePointReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user get scene point, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.GetScenePointReq)
|
||||
|
||||
@@ -18,20 +18,15 @@ import (
|
||||
// 世界管理器
|
||||
|
||||
type WorldManager struct {
|
||||
worldMap map[uint32]*World
|
||||
snowflake *alg.SnowflakeWorker
|
||||
worldStatic *WorldStatic
|
||||
bigWorld *World
|
||||
worldMap map[uint32]*World
|
||||
snowflake *alg.SnowflakeWorker
|
||||
bigWorld *World
|
||||
}
|
||||
|
||||
func NewWorldManager(snowflake *alg.SnowflakeWorker) (r *WorldManager) {
|
||||
r = new(WorldManager)
|
||||
r.worldMap = make(map[uint32]*World)
|
||||
r.snowflake = snowflake
|
||||
r.worldStatic = NewWorldStatic()
|
||||
r.worldStatic.InitTerrain()
|
||||
// r.worldStatic.Pathfinding()
|
||||
// r.worldStatic.ConvPathVectorListToAiMoveVectorList()
|
||||
return r
|
||||
}
|
||||
|
||||
|
||||
@@ -1,163 +0,0 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"encoding/gob"
|
||||
"unsafe"
|
||||
|
||||
gdc "hk4e/gs/config"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/alg"
|
||||
"hk4e/pkg/logger"
|
||||
)
|
||||
|
||||
// 世界的静态资源坐标点数据
|
||||
|
||||
type MeshMapPos struct {
|
||||
X int16
|
||||
Y int16
|
||||
Z int16
|
||||
}
|
||||
|
||||
type WorldStatic struct {
|
||||
// x y z -> if terrain exist
|
||||
terrain map[MeshMapPos]bool
|
||||
// x y z -> gather id
|
||||
gather map[MeshMapPos]uint32
|
||||
pathfindingStartPos MeshMapPos
|
||||
pathfindingEndPos MeshMapPos
|
||||
pathVectorList []MeshMapPos
|
||||
aiMoveMeshSpeedParam int
|
||||
aiMoveVectorList []*model.Vector
|
||||
aiMoveCurrIndex int
|
||||
}
|
||||
|
||||
func NewWorldStatic() (r *WorldStatic) {
|
||||
r = new(WorldStatic)
|
||||
r.terrain = make(map[MeshMapPos]bool)
|
||||
r.gather = make(map[MeshMapPos]uint32)
|
||||
r.InitGather()
|
||||
r.pathfindingStartPos = MeshMapPos{
|
||||
X: 2747,
|
||||
Y: 194,
|
||||
Z: -1719,
|
||||
}
|
||||
r.pathfindingEndPos = MeshMapPos{
|
||||
X: 2588,
|
||||
Y: 211,
|
||||
Z: -1349,
|
||||
}
|
||||
r.pathVectorList = make([]MeshMapPos, 0)
|
||||
r.aiMoveMeshSpeedParam = 3
|
||||
r.aiMoveVectorList = make([]*model.Vector, 0)
|
||||
r.aiMoveCurrIndex = 0
|
||||
return r
|
||||
}
|
||||
|
||||
func (w *WorldStatic) InitTerrain() bool {
|
||||
data := gdc.CONF.ReadWorldTerrain()
|
||||
decoder := gob.NewDecoder(bytes.NewReader(data))
|
||||
err := decoder.Decode(&w.terrain)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal world terrain data error: %v", err)
|
||||
return false
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SaveTerrain() bool {
|
||||
var buffer bytes.Buffer
|
||||
encoder := gob.NewEncoder(&buffer)
|
||||
err := encoder.Encode(w.terrain)
|
||||
if err != nil {
|
||||
logger.Error("marshal world terrain data error: %v", err)
|
||||
return false
|
||||
}
|
||||
gdc.CONF.WriteWorldTerrain(buffer.Bytes())
|
||||
return true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) GetTerrain(x int16, y int16, z int16) (exist bool) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
exist = w.terrain[pos]
|
||||
return exist
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SetTerrain(x int16, y int16, z int16) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
w.terrain[pos] = true
|
||||
}
|
||||
|
||||
func (w *WorldStatic) InitGather() {
|
||||
}
|
||||
|
||||
func (w *WorldStatic) GetGather(x int16, y int16, z int16) (gatherId uint32, exist bool) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
gatherId, exist = w.gather[pos]
|
||||
return gatherId, exist
|
||||
}
|
||||
|
||||
func (w *WorldStatic) SetGather(x int16, y int16, z int16, gatherId uint32) {
|
||||
pos := MeshMapPos{
|
||||
X: x,
|
||||
Y: y,
|
||||
Z: z,
|
||||
}
|
||||
w.gather[pos] = gatherId
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvWSTMapToPFMap() map[alg.MeshMapPos]bool {
|
||||
return *(*map[alg.MeshMapPos]bool)(unsafe.Pointer(&w.terrain))
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvWSPosToPFPos(v MeshMapPos) alg.MeshMapPos {
|
||||
return alg.MeshMapPos(v)
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvPFPVLToWSPVL(v []alg.MeshMapPos) []MeshMapPos {
|
||||
return *(*[]MeshMapPos)(unsafe.Pointer(&v))
|
||||
}
|
||||
|
||||
func (w *WorldStatic) Pathfinding() {
|
||||
bfs := alg.NewBFS()
|
||||
bfs.InitMap(
|
||||
w.ConvWSTMapToPFMap(),
|
||||
w.ConvWSPosToPFPos(w.pathfindingStartPos),
|
||||
w.ConvWSPosToPFPos(w.pathfindingEndPos),
|
||||
100,
|
||||
)
|
||||
pathVectorList := bfs.Pathfinding()
|
||||
if pathVectorList == nil {
|
||||
logger.Error("could not find path")
|
||||
return
|
||||
}
|
||||
logger.Debug("find path success, path: %v", pathVectorList)
|
||||
w.pathVectorList = w.ConvPFPVLToWSPVL(pathVectorList)
|
||||
}
|
||||
|
||||
func (w *WorldStatic) ConvPathVectorListToAiMoveVectorList() {
|
||||
for index, currPathVector := range w.pathVectorList {
|
||||
if index > 0 {
|
||||
lastPathVector := w.pathVectorList[index-1]
|
||||
for i := 0; i < w.aiMoveMeshSpeedParam; i++ {
|
||||
w.aiMoveVectorList = append(w.aiMoveVectorList, &model.Vector{
|
||||
X: float64(lastPathVector.X) + float64(currPathVector.X-lastPathVector.X)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
Y: float64(lastPathVector.Y) + float64(currPathVector.Y-lastPathVector.Y)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
Z: float64(lastPathVector.Z) + float64(currPathVector.Z-lastPathVector.Z)/float64(w.aiMoveMeshSpeedParam)*float64(i),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user