优化代码

This commit is contained in:
huangxiaolei
2022-11-24 14:17:21 +08:00
parent 21d549c507
commit 2b3a152af6
13 changed files with 242 additions and 222 deletions

View File

@@ -1,7 +1,7 @@
http_port = 8080 http_port = 8080
[hk4e] [hk4e]
kcp_addr = "hk4e.flswld.com" kcp_addr = "127.0.0.1"
kcp_port = 22103 kcp_port = 22103
login_sdk_url = "https://api.flswld.com/api/v1/auth/login" login_sdk_url = "https://api.flswld.com/api/v1/auth/login"

View File

@@ -1,5 +1,5 @@
[hk4e] [hk4e]
kcp_addr = "hk4e.flswld.com" kcp_addr = "127.0.0.1"
kcp_port = 22103 kcp_port = 22103
[logger] [logger]

View File

@@ -25,7 +25,7 @@ type GameManager struct {
userManager *UserManager userManager *UserManager
// 世界管理器 // 世界管理器
worldManager *WorldManager worldManager *WorldManager
// 游戏服务器tick // 游戏服务器定时帧管理器
tickManager *TickManager tickManager *TickManager
} }
@@ -41,11 +41,7 @@ func NewGameManager(dao *dao.Dao, netMsgInput chan *cmd.NetMsg, netMsgOutput cha
r.worldManager = NewWorldManager(r.snowflake) r.worldManager = NewWorldManager(r.snowflake)
r.tickManager = NewTickManager(r) r.tickManager = NewTickManager(r)
//r.worldManager.worldStatic.InitTerrain() // 创建一个公共的开放世界的AI
//r.worldManager.worldStatic.Pathfinding()
//r.worldManager.worldStatic.ConvPathVectorListToAiMoveVectorList()
// 大世界的主人
r.OnRegOk(false, &proto.SetPlayerBornDataReq{AvatarId: 10000007, NickName: "大世界的主人"}, 1, 0) r.OnRegOk(false, &proto.SetPlayerBornDataReq{AvatarId: 10000007, NickName: "大世界的主人"}, 1, 0)
bigWorldOwner := r.userManager.GetOnlineUser(1) bigWorldOwner := r.userManager.GetOnlineUser(1)
bigWorldOwner.SceneLoadState = model.SceneEnterDone bigWorldOwner.SceneLoadState = model.SceneEnterDone

View File

@@ -1,5 +1,7 @@
package game package game
// 本地事件队列管理器
const ( const (
LoadLoginUserFromDbFinish = iota LoadLoginUserFromDbFinish = iota
CheckUserExistOnRegFromDbFinish CheckUserExistOnRegFromDbFinish

View File

@@ -7,6 +7,8 @@ import (
"hk4e/protocol/cmd" "hk4e/protocol/cmd"
) )
// 接口路由管理器
type HandlerFunc func(player *model.Player, payloadMsg pb.Message) type HandlerFunc func(player *model.Player, payloadMsg pb.Message)
type RouteManager struct { type RouteManager struct {

View File

@@ -10,6 +10,8 @@ import (
"time" "time"
) )
// 游戏服务器定时帧管理器
type TickManager struct { type TickManager struct {
ticker *time.Ticker ticker *time.Ticker
tickCount uint64 tickCount uint64
@@ -77,7 +79,7 @@ func (t *TickManager) onTick10Minute(now int64) {
} }
func (t *TickManager) onTickMinute(now int64) { func (t *TickManager) onTickMinute(now int64) {
t.gameManager.ServerAnnounceNotify(100, "test123") //t.gameManager.ServerAnnounceNotify(100, "test123")
for _, world := range t.gameManager.worldManager.worldMap { for _, world := range t.gameManager.worldManager.worldMap {
for _, player := range world.playerMap { for _, player := range world.playerMap {
// 随机物品 // 随机物品
@@ -149,6 +151,7 @@ func (t *TickManager) onTick5Second(now int64) {
} }
for _, player := range world.playerMap { for _, player := range world.playerMap {
if world.multiplayer { if world.multiplayer {
// 多人世界其他玩家的坐标位置广播
// PacketWorldPlayerLocationNotify // PacketWorldPlayerLocationNotify
worldPlayerLocationNotify := new(proto.WorldPlayerLocationNotify) worldPlayerLocationNotify := new(proto.WorldPlayerLocationNotify)
for _, worldPlayer := range world.playerMap { for _, worldPlayer := range world.playerMap {
@@ -201,6 +204,7 @@ func (t *TickManager) onTick5Second(now int64) {
func (t *TickManager) onTickSecond(now int64) { func (t *TickManager) onTickSecond(now int64) {
for _, world := range t.gameManager.worldManager.worldMap { for _, world := range t.gameManager.worldManager.worldMap {
for _, player := range world.playerMap { for _, player := range world.playerMap {
// 世界里所有玩家的网络延迟广播
// PacketWorldPlayerRTTNotify // PacketWorldPlayerRTTNotify
worldPlayerRTTNotify := new(proto.WorldPlayerRTTNotify) worldPlayerRTTNotify := new(proto.WorldPlayerRTTNotify)
worldPlayerRTTNotify.PlayerRttList = make([]*proto.PlayerRTTInfo, 0) worldPlayerRTTNotify.PlayerRttList = make([]*proto.PlayerRTTInfo, 0)
@@ -214,13 +218,15 @@ func (t *TickManager) onTickSecond(now int64) {
} }
func (t *TickManager) onTick100MilliSecond(now int64) { func (t *TickManager) onTick100MilliSecond(now int64) {
// AttackHandler // 伤害处理和转发
for _, world := range t.gameManager.worldManager.worldMap { for _, world := range t.gameManager.worldManager.worldMap {
for _, scene := range world.sceneMap { for _, scene := range world.sceneMap {
scene.AttackHandler(t.gameManager) scene.AttackHandler(t.gameManager)
} }
} }
// 服务器控制的模拟AI移动
//bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1) //bigWorldOwner := t.gameManager.userManager.GetOnlineUser(1)
//bigWorld := t.gameManager.worldManager.GetBigWorld() //bigWorld := t.gameManager.worldManager.GetBigWorld()
//bigWorldScene := bigWorld.GetSceneById(3) //bigWorldScene := bigWorld.GetSceneById(3)

View File

@@ -9,7 +9,7 @@ import (
) )
func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg pb.Message) { func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg pb.Message) {
//logger.LOG.Debug("user combat invocations, uid: %v", player.PlayerID) logger.LOG.Debug("user combat invocations, uid: %v", player.PlayerID)
req := payloadMsg.(*proto.CombatInvocationsNotify) req := payloadMsg.(*proto.CombatInvocationsNotify)
world := g.worldManager.GetWorldByID(player.WorldId) world := g.worldManager.GetWorldByID(player.WorldId)
if world == nil { if world == nil {
@@ -18,7 +18,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
scene := world.GetSceneById(player.SceneId) scene := world.GetSceneById(player.SceneId)
invokeHandler := NewInvokeHandler[proto.CombatInvokeEntry]() invokeHandler := NewInvokeHandler[proto.CombatInvokeEntry]()
for _, entry := range req.InvokeList { for _, entry := range req.InvokeList {
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
switch entry.ArgumentType { switch entry.ArgumentType {
case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT: case proto.CombatTypeArgument_COMBAT_TYPE_ARGUMENT_EVT_BEING_HIT:
scene.AddAttack(&Attack{ scene.AddAttack(&Attack{
@@ -145,42 +145,42 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
player.Rot.X = float64(motionInfo.Rot.X) player.Rot.X = float64(motionInfo.Rot.X)
player.Rot.Y = float64(motionInfo.Rot.Y) player.Rot.Y = float64(motionInfo.Rot.Y)
player.Rot.Z = float64(motionInfo.Rot.Z) player.Rot.Z = float64(motionInfo.Rot.Z)
// TODO 采集大地图地形数据 //// TODO 采集大地图地形数据
if world.IsBigWorld() && scene.id == 3 && player.PlayerID != 1 { //if world.IsBigWorld() && scene.id == 3 && player.PlayerID != 1 {
if motionInfo.State == proto.MotionState_MOTION_STATE_WALK || // if motionInfo.State == proto.MotionState_MOTION_STATE_WALK ||
motionInfo.State == proto.MotionState_MOTION_STATE_RUN || // motionInfo.State == proto.MotionState_MOTION_STATE_RUN ||
motionInfo.State == proto.MotionState_MOTION_STATE_DASH || // motionInfo.State == proto.MotionState_MOTION_STATE_DASH ||
motionInfo.State == proto.MotionState_MOTION_STATE_CLIMB { // motionInfo.State == proto.MotionState_MOTION_STATE_CLIMB {
logger.LOG.Debug("set terr motionInfo: %v", motionInfo) // logger.LOG.Debug("set terr motionInfo: %v", motionInfo)
exist := g.worldManager.worldStatic.GetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z)) // exist := g.worldManager.worldStatic.GetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z))
g.worldManager.worldStatic.SetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z)) // g.worldManager.worldStatic.SetTerrain(int16(motionInfo.Pos.X), int16(motionInfo.Pos.Y), int16(motionInfo.Pos.Z))
if !exist { // if !exist {
// TODO 薄荷标记 // // TODO 薄荷标记
// 只给附近aoi区域的玩家广播消息 // // 只给附近aoi区域的玩家广播消息
surrPlayerList := make([]*model.Player, 0) // surrPlayerList := make([]*model.Player, 0)
entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z)) // entityIdList := world.aoiManager.GetEntityIdListByPos(float32(player.Pos.X), float32(player.Pos.Y), float32(player.Pos.Z))
for _, entityId := range entityIdList { // for _, entityId := range entityIdList {
entity := scene.GetEntity(entityId) // entity := scene.GetEntity(entityId)
if entity == nil { // if entity == nil {
continue // continue
} // }
if entity.avatarEntity != nil { // if entity.avatarEntity != nil {
otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid) // otherPlayer := g.userManager.GetOnlineUser(entity.avatarEntity.uid)
surrPlayerList = append(surrPlayerList, otherPlayer) // surrPlayerList = append(surrPlayerList, otherPlayer)
} // }
} // }
pos := &model.Vector{ // pos := &model.Vector{
X: float64(int16(motionInfo.Pos.X)), // X: float64(int16(motionInfo.Pos.X)),
Y: float64(int16(motionInfo.Pos.Y)), // Y: float64(int16(motionInfo.Pos.Y)),
Z: float64(int16(motionInfo.Pos.Z)), // Z: float64(int16(motionInfo.Pos.Z)),
} // }
gadgetEntityId := scene.CreateEntityGadget(pos, 3003009) // gadgetEntityId := scene.CreateEntityGadget(pos, 3003009)
for _, otherPlayer := range surrPlayerList { // for _, otherPlayer := range surrPlayerList {
g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{gadgetEntityId}, false) // g.AddSceneEntityNotify(otherPlayer, proto.VisionType_VISION_TYPE_BORN, []uint32{gadgetEntityId}, false)
} // }
} // }
} // }
} //}
} }
// 更新场景实体的位置信息 // 更新场景实体的位置信息
sceneEntity := scene.GetEntity(entityMoveInfo.EntityId) sceneEntity := scene.GetEntity(entityMoveInfo.EntityId)
@@ -198,7 +198,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
sceneEntity.moveState = uint16(motionInfo.State) sceneEntity.moveState = uint16(motionInfo.State)
sceneEntity.lastMoveSceneTimeMs = entityMoveInfo.SceneTime sceneEntity.lastMoveSceneTimeMs = entityMoveInfo.SceneTime
sceneEntity.lastMoveReliableSeq = entityMoveInfo.ReliableSeq sceneEntity.lastMoveReliableSeq = entityMoveInfo.ReliableSeq
//logger.LOG.Debug("entity move, id: %v, pos: %v, uid: %v", sceneEntity.id, sceneEntity.pos, player.PlayerID) logger.LOG.Debug("entity move, id: %v, pos: %v, uid: %v", sceneEntity.id, sceneEntity.pos, player.PlayerID)
} }
invokeHandler.addEntry(entry.ForwardType, entry) invokeHandler.addEntry(entry.ForwardType, entry)
default: default:
@@ -246,7 +246,7 @@ func (g *GameManager) CombatInvocationsNotify(player *model.Player, payloadMsg p
} }
func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Message) { func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg pb.Message) {
//logger.LOG.Debug("user ability invocations, uid: %v", player.PlayerID) logger.LOG.Debug("user ability invocations, uid: %v", player.PlayerID)
req := payloadMsg.(*proto.AbilityInvocationsNotify) req := payloadMsg.(*proto.AbilityInvocationsNotify)
world := g.worldManager.GetWorldByID(player.WorldId) world := g.worldManager.GetWorldByID(player.WorldId)
if world == nil { if world == nil {
@@ -255,7 +255,7 @@ func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg
scene := world.GetSceneById(player.SceneId) scene := world.GetSceneById(player.SceneId)
invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]() invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]()
for _, entry := range req.Invokes { for _, entry := range req.Invokes {
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
invokeHandler.addEntry(entry.ForwardType, entry) invokeHandler.addEntry(entry.ForwardType, entry)
} }
@@ -299,7 +299,7 @@ func (g *GameManager) AbilityInvocationsNotify(player *model.Player, payloadMsg
} }
func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloadMsg pb.Message) { func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloadMsg pb.Message) {
//logger.LOG.Debug("user client ability ok, uid: %v", player.PlayerID) logger.LOG.Debug("user client ability ok, uid: %v", player.PlayerID)
req := payloadMsg.(*proto.ClientAbilityInitFinishNotify) req := payloadMsg.(*proto.ClientAbilityInitFinishNotify)
world := g.worldManager.GetWorldByID(player.WorldId) world := g.worldManager.GetWorldByID(player.WorldId)
if world == nil { if world == nil {
@@ -308,7 +308,7 @@ func (g *GameManager) ClientAbilityInitFinishNotify(player *model.Player, payloa
scene := world.GetSceneById(player.SceneId) scene := world.GetSceneById(player.SceneId)
invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]() invokeHandler := NewInvokeHandler[proto.AbilityInvokeEntry]()
for _, entry := range req.Invokes { for _, entry := range req.Invokes {
//logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID) logger.LOG.Debug("AT: %v, FT: %v, UID: %v", entry.ArgumentType, entry.ForwardType, player.PlayerID)
invokeHandler.addEntry(entry.ForwardType, entry) invokeHandler.addEntry(entry.ForwardType, entry)
} }

View File

@@ -286,10 +286,10 @@ func (g *GameManager) DoGachaReq(player *model.Player, payloadMsg pb.Message) {
xh := uint32(random.GetRandomInt32(0, 10)) xh := uint32(random.GetRandomInt32(0, 10))
gachaItem := new(proto.GachaItem) gachaItem := new(proto.GachaItem)
gachaItem.TokenItemList = []*proto.ItemParam{{ gachaItem.GachaItem = &proto.ItemParam{
ItemId: itemId, ItemId: itemId,
Count: 1, Count: 1,
}} }
// 星尘 // 星尘
if xc != 0 { if xc != 0 {
g.AddUserItem(player.PlayerID, []*UserItem{{ g.AddUserItem(player.PlayerID, []*UserItem{{
@@ -317,7 +317,7 @@ func (g *GameManager) DoGachaReq(player *model.Player, payloadMsg pb.Message) {
doGachaRsp.GachaItemList = append(doGachaRsp.GachaItemList, gachaItem) doGachaRsp.GachaItemList = append(doGachaRsp.GachaItemList, gachaItem)
} }
//logger.LOG.Debug("doGachaRsp: %v", doGachaRsp.String()) logger.LOG.Debug("doGachaRsp: %v", doGachaRsp.String())
g.SendMsg(cmd.DoGachaRsp, player.PlayerID, player.ClientSeq, doGachaRsp) g.SendMsg(cmd.DoGachaRsp, player.PlayerID, player.ClientSeq, doGachaRsp)
} }

View File

@@ -42,17 +42,17 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u
world.AddPlayer(player, player.SceneId) world.AddPlayer(player, player.SceneId)
player.WorldId = world.id player.WorldId = world.id
// TODO 薄荷标记 //// TODO 薄荷标记
if world.IsBigWorld() { //if world.IsBigWorld() {
bigWorld := world.GetSceneById(3) // bigWorld := world.GetSceneById(3)
for pos := range g.worldManager.worldStatic.terrain { // for pos := range g.worldManager.worldStatic.terrain {
bigWorld.CreateEntityGadget(&model.Vector{ // bigWorld.CreateEntityGadget(&model.Vector{
X: float64(pos.X), // X: float64(pos.X),
Y: float64(pos.Y), // Y: float64(pos.Y),
Z: float64(pos.Z), // Z: float64(pos.Z),
}, 3003009) // }, 3003009)
} // }
} //}
// PacketPlayerDataNotify // PacketPlayerDataNotify
playerDataNotify := new(proto.PlayerDataNotify) playerDataNotify := new(proto.PlayerDataNotify)

View File

@@ -147,7 +147,7 @@ func (g *GameManager) PathfindingEnterSceneReq(player *model.Player, payloadMsg
} }
func (g *GameManager) QueryPathReq(player *model.Player, payloadMsg pb.Message) { func (g *GameManager) QueryPathReq(player *model.Player, payloadMsg pb.Message) {
//logger.LOG.Debug("user query path, uid: %v", player.PlayerID) logger.LOG.Debug("user query path, uid: %v", player.PlayerID)
req := payloadMsg.(*proto.QueryPathReq) req := payloadMsg.(*proto.QueryPathReq)
// PacketQueryPathRsp // PacketQueryPathRsp

View File

@@ -1,11 +1,8 @@
package game package game
import ( import (
"bytes"
"encoding/gob"
pb "google.golang.org/protobuf/proto" pb "google.golang.org/protobuf/proto"
"hk4e/common/utils/alg" "hk4e/common/utils/alg"
gdc "hk4e/gs/config"
"hk4e/gs/constant" "hk4e/gs/constant"
"hk4e/gs/game/aoi" "hk4e/gs/game/aoi"
"hk4e/gs/model" "hk4e/gs/model"
@@ -14,160 +11,10 @@ import (
"hk4e/protocol/proto" "hk4e/protocol/proto"
"math" "math"
"time" "time"
"unsafe"
) )
// 世界管理器 // 世界管理器
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) 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.LOG.Error("could not find path")
return
}
logger.LOG.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),
})
}
}
}
}
func (w *WorldStatic) InitTerrain() bool {
data := gdc.CONF.ReadWorldTerrain()
decoder := gob.NewDecoder(bytes.NewReader(data))
err := decoder.Decode(&w.terrain)
if err != nil {
logger.LOG.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.LOG.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
}
type WorldManager struct { type WorldManager struct {
worldMap map[uint32]*World worldMap map[uint32]*World
snowflake *alg.SnowflakeWorker snowflake *alg.SnowflakeWorker
@@ -180,6 +27,9 @@ func NewWorldManager(snowflake *alg.SnowflakeWorker) (r *WorldManager) {
r.worldMap = make(map[uint32]*World) r.worldMap = make(map[uint32]*World)
r.snowflake = snowflake r.snowflake = snowflake
r.worldStatic = NewWorldStatic() r.worldStatic = NewWorldStatic()
r.worldStatic.InitTerrain()
//r.worldStatic.Pathfinding()
//r.worldStatic.ConvPathVectorListToAiMoveVectorList()
return r return r
} }
@@ -520,6 +370,8 @@ func (s *Scene) GetEntity(entityId uint32) *Entity {
return s.entityMap[entityId] return s.entityMap[entityId]
} }
// 伤害处理和转发
func (s *Scene) AddAttack(attack *Attack) { func (s *Scene) AddAttack(attack *Attack) {
s.attackQueue.EnQueue(attack) s.attackQueue.EnQueue(attack)
} }
@@ -544,7 +396,7 @@ func (s *Scene) AttackHandler(gameManager *GameManager) {
} }
attackResult := hitInfo.AttackResult attackResult := hitInfo.AttackResult
//logger.LOG.Debug("run attack handler, attackResult: %v", attackResult) logger.LOG.Debug("run attack handler, attackResult: %v", attackResult)
target := s.entityMap[attackResult.DefenseId] target := s.entityMap[attackResult.DefenseId]
if target == nil { if target == nil {
logger.LOG.Error("could not found target, defense id: %v", attackResult.DefenseId) logger.LOG.Error("could not found target, defense id: %v", attackResult.DefenseId)

162
gs/game/world_static.go Normal file
View File

@@ -0,0 +1,162 @@
package game
import (
"bytes"
"encoding/gob"
"hk4e/common/utils/alg"
gdc "hk4e/gs/config"
"hk4e/gs/model"
"hk4e/logger"
"unsafe"
)
// 世界的静态资源坐标点数据
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.LOG.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.LOG.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.LOG.Error("could not find path")
return
}
logger.LOG.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),
})
}
}
}
}