fix panic

This commit is contained in:
flswld
2023-03-22 11:41:16 +08:00
parent f99d845d57
commit b5267d57d8
4 changed files with 76 additions and 52 deletions

View File

@@ -4,9 +4,9 @@
#### 『原神』 Game Server But Golang Ver.
#### 代号hk4e中的hk起源于『Honkai Impact 3rd』
#### 本项目的目标为构建一个高性能高可用的ARPG游戏服务端并非以完整还原游戏内原本功能点为目的
#### 项目的客户端协议([360NENZ/teyvat-helper-hk4e-proto](https://github.com/360NENZ/teyvat-helper-hk4e-proto))、配置表([TomyJan/xudong](https://github.com/TomyJan/xudong))主要基于3.2版本修改而来因此请尽量使用3.2版本的客户端,但不是必须的
#### 项目的客户端协议、配置表主要基于3.2版本修改而来因此请尽量使用3.2版本的客户端,但不是必须的
[3.2.0国际服客户端下载链接](https://autopatchhk.yuanshen.com/client_app/download/pc_zip/20221024103618_h2e3o3zijYKEqHnQ/GenshinImpact_3.2.0.zip)
@@ -16,12 +16,11 @@
## 特性
* 原生的高可用集群架构,任意节点宕机不会影响到整个系统,可大量水平扩展支撑千万级DAU不是梦
* 玩家级无状态游戏服务器,无锁单线程模型,开发省时省力,完善的玩家数据交换机制(内存-缓存-数据库)
拒绝同步阻塞的数据库访问掌控每一纳秒的CPU时间不是梦
* 新颖的玩家在线跨服无缝迁移功能,以多人世界之名,反复横跳于多个服务器进程之间不是梦
* 独创的网关服务器侧客户端协议代理转换功能,拒绝因协议号消息号混淆而带来代码改动的烦恼,不同协议版本客户端同时在线联机不是梦
* 完整的密钥交换机制实现,安全性++拒绝一个写死的随机数种子和XOR密钥文件用到天荒地老搭建一个属于自己的别具一格的聊天渠道不是梦
* 原生的高可用集群架构,任意节点宕机不会影响到整个系统,可大量水平扩展
* 玩家级无状态游戏服务器,无锁单线程模型,开发省时省力,完善的玩家数据交换机制(内存-缓存-数据库),拒绝同步阻塞的数据库访问
* 新颖的玩家在线跨服无缝迁移功能
* 独创的网关服务器侧客户端协议代理转换功能,拒绝因协议号消息号混淆而带来代码改动的烦恼
* 完整的密钥交换机制实现,安全性++拒绝一个写死的随机数种子和XOR密钥文件用到天荒地老
## 编译和运行环境

View File

@@ -321,6 +321,9 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector,
}
// 旧有新没有的group即为消失的
group := scene.GetGroupById(groupId)
if group == nil {
continue
}
for _, entity := range group.GetAllEntity() {
delEntityIdList = append(delEntityIdList, entity.GetId())
}

View File

@@ -245,6 +245,7 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes
func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) {
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
if initSuiteId > len(groupConfig.SuiteList) {
logger.Error("invalid init suite id: %v", initSuiteId)
return
}
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
@@ -285,34 +286,41 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
activeAvatarEntityId := world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)
g.AddSceneEntityNotify(player, visionType, []uint32{activeAvatarEntityId}, true, false)
// 加载附近的group
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[scene.GetId()]
addEntityIdList := make([]uint32, 0)
if exist {
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
for _, groupAny := range objectList {
group := groupAny.(*gdconf.Group)
distance2D := math.Sqrt((player.Pos.X-float64(group.Pos.X))*(player.Pos.X-float64(group.Pos.X)) +
(player.Pos.Z-float64(group.Pos.Z))*(player.Pos.Z-float64(group.Pos.Z)))
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 group.DynamicLoad {
if groupConfig.DynamicLoad {
continue
}
g.AddSceneGroup(scene, group)
g.AddSceneGroup(scene, groupConfig)
group := scene.GetGroupById(uint32(groupConfig.Id))
for _, entity := range group.GetAllEntity() {
addEntityIdList = append(addEntityIdList, entity.GetId())
}
}
}
entityIdList := make([]uint32, 0)
if player.SceneJump {
visionType = proto.VisionType_VISION_MEET
entityMap := scene.GetAllEntity()
for _, entity := range entityMap {
if entity.GetId() == activeAvatarEntityId {
continue
}
entityIdList = append(entityIdList, entity.GetId())
}
} else {
visionType = proto.VisionType_VISION_TRANSPORT
}
entityMap := scene.GetAllEntity()
entityIdList := make([]uint32, 0)
for _, entity := range entityMap {
if entity.GetId() == activeAvatarEntityId {
continue
}
entityIdList = append(entityIdList, entity.GetId())
entityIdList = addEntityIdList
}
g.AddSceneEntityNotify(player, visionType, entityIdList, false, false)

View File

@@ -17,37 +17,11 @@ type Scene struct {
id uint32
world *World
playerMap map[uint32]*model.Player
entityMap map[uint32]*Entity
groupMap map[uint32]*Group
gameTime uint32 // 游戏内提瓦特大陆的时间
createTime int64 // 场景创建时间
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
}
type Group struct {
suiteMap map[uint8]*Suite
}
func (g *Group) GetAllSuite() map[uint8]*Suite {
return g.suiteMap
}
func (g *Group) GetAllEntity() map[uint32]*Entity {
entityMap := make(map[uint32]*Entity)
for _, suite := range g.suiteMap {
for _, entity := range suite.entityMap {
entityMap[entity.id] = entity
}
}
return entityMap
}
type Suite struct {
entityMap map[uint32]*Entity
}
func (s *Suite) GetAllEntity() map[uint32]*Entity {
return s.entityMap
entityMap map[uint32]*Entity // 场景中全部的实体
groupMap map[uint32]*Group // 场景中按group->suite分类的实体
gameTime uint32 // 游戏内提瓦特大陆的时间
createTime int64 // 场景创建时间
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
}
func (s *Scene) GetId() uint32 {
@@ -420,6 +394,7 @@ func (s *Scene) GetEntity(entityId uint32) *Entity {
func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
groupConfig := gdconf.GetSceneGroup(int32(groupId))
if groupConfig == nil {
logger.Error("get scene group config is nil, groupId: %v", groupId)
return
}
suiteConfig := groupConfig.SuiteList[suiteId-1]
@@ -429,6 +404,7 @@ func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
for _, monsterConfigId := range suiteConfig.MonsterConfigIdList {
monster, exist := groupConfig.MonsterMap[monsterConfigId]
if !exist {
logger.Error("monster config not exist, monsterConfigId: %v", monsterConfigId)
continue
}
entityId := s.createConfigEntity(uint32(groupConfig.Id), monster)
@@ -438,6 +414,7 @@ func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList {
gadget, exist := groupConfig.GadgetMap[gadgetConfigId]
if !exist {
logger.Error("gadget config not exist, gadgetConfigId: %v", gadgetConfigId)
continue
}
entityId := s.createConfigEntity(uint32(groupConfig.Id), gadget)
@@ -461,10 +438,12 @@ func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
func (s *Scene) RemoveGroupSuite(groupId uint32, suiteId uint8) {
group := s.groupMap[groupId]
if group == nil {
logger.Error("group not exist, groupId: %v", groupId)
return
}
suite := group.suiteMap[suiteId]
if suite == nil {
logger.Error("suite not exist, suiteId: %v", suiteId)
return
}
for _, entity := range suite.entityMap {
@@ -531,6 +510,7 @@ func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 {
}
}
// TODO 临时写死
func getTempFightPropMap() map[uint32]float32 {
fpm := map[uint32]float32{
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
@@ -552,6 +532,40 @@ func getTempFightPropMap() map[uint32]float32 {
return fpm
}
type Group struct {
suiteMap map[uint8]*Suite
}
type Suite struct {
entityMap map[uint32]*Entity
}
func (g *Group) GetSuiteById(suiteId uint8) *Suite {
return g.suiteMap[suiteId]
}
func (g *Group) GetAllSuite() map[uint8]*Suite {
return g.suiteMap
}
func (g *Group) GetAllEntity() map[uint32]*Entity {
entityMap := make(map[uint32]*Entity)
for _, suite := range g.suiteMap {
for _, entity := range suite.entityMap {
entityMap[entity.id] = entity
}
}
return entityMap
}
func (s *Suite) GetEntityById(entityId uint32) *Entity {
return s.entityMap[entityId]
}
func (s *Suite) GetAllEntity() map[uint32]*Entity {
return s.entityMap
}
// Entity 场景实体数据结构
type Entity struct {
id uint32 // 实体id