mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 16:02:26 +08:00
fix panic
This commit is contained in:
15
README.md
15
README.md
@@ -4,9 +4,9 @@
|
|||||||
|
|
||||||
#### 『原神』 Game Server But Golang Ver.
|
#### 『原神』 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)
|
[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密钥文件用到天荒地老,搭建一个属于自己的别具一格的聊天渠道不是梦
|
|
||||||
|
|
||||||
## 编译和运行环境
|
## 编译和运行环境
|
||||||
|
|
||||||
|
|||||||
@@ -321,6 +321,9 @@ func (g *GameManager) AoiPlayerMove(player *model.Player, oldPos *model.Vector,
|
|||||||
}
|
}
|
||||||
// 旧有新没有的group即为消失的
|
// 旧有新没有的group即为消失的
|
||||||
group := scene.GetGroupById(groupId)
|
group := scene.GetGroupById(groupId)
|
||||||
|
if group == nil {
|
||||||
|
continue
|
||||||
|
}
|
||||||
for _, entity := range group.GetAllEntity() {
|
for _, entity := range group.GetAllEntity() {
|
||||||
delEntityIdList = append(delEntityIdList, entity.GetId())
|
delEntityIdList = append(delEntityIdList, entity.GetId())
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -245,6 +245,7 @@ func (g *GameManager) SceneInitFinishReq(player *model.Player, payloadMsg pb.Mes
|
|||||||
func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) {
|
func (g *GameManager) AddSceneGroup(scene *Scene, groupConfig *gdconf.Group) {
|
||||||
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
|
initSuiteId := int(groupConfig.GroupInitConfig.Suite)
|
||||||
if initSuiteId > len(groupConfig.SuiteList) {
|
if initSuiteId > len(groupConfig.SuiteList) {
|
||||||
|
logger.Error("invalid init suite id: %v", initSuiteId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
scene.AddGroupSuite(uint32(groupConfig.Id), uint8(initSuiteId))
|
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)
|
activeAvatarEntityId := world.GetPlayerWorldAvatarEntityId(player, activeAvatarId)
|
||||||
g.AddSceneEntityNotify(player, visionType, []uint32{activeAvatarEntityId}, true, false)
|
g.AddSceneEntityNotify(player, visionType, []uint32{activeAvatarEntityId}, true, false)
|
||||||
|
|
||||||
|
// 加载附近的group
|
||||||
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[scene.GetId()]
|
aoiManager, exist := WORLD_MANAGER.GetSceneBlockAoiMap()[scene.GetId()]
|
||||||
|
addEntityIdList := make([]uint32, 0)
|
||||||
if exist {
|
if exist {
|
||||||
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
|
objectList := aoiManager.GetObjectListByPos(float32(player.Pos.X), 0.0, float32(player.Pos.Z))
|
||||||
for _, groupAny := range objectList {
|
for _, groupAny := range objectList {
|
||||||
group := groupAny.(*gdconf.Group)
|
groupConfig := groupAny.(*gdconf.Group)
|
||||||
distance2D := math.Sqrt((player.Pos.X-float64(group.Pos.X))*(player.Pos.X-float64(group.Pos.X)) +
|
distance2D := math.Sqrt((player.Pos.X-float64(groupConfig.Pos.X))*(player.Pos.X-float64(groupConfig.Pos.X)) +
|
||||||
(player.Pos.Z-float64(group.Pos.Z))*(player.Pos.Z-float64(group.Pos.Z)))
|
(player.Pos.Z-float64(groupConfig.Pos.Z))*(player.Pos.Z-float64(groupConfig.Pos.Z)))
|
||||||
if distance2D > ENTITY_LOD {
|
if distance2D > ENTITY_LOD {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if group.DynamicLoad {
|
if groupConfig.DynamicLoad {
|
||||||
continue
|
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 {
|
if player.SceneJump {
|
||||||
visionType = proto.VisionType_VISION_MEET
|
visionType = proto.VisionType_VISION_MEET
|
||||||
|
entityMap := scene.GetAllEntity()
|
||||||
|
for _, entity := range entityMap {
|
||||||
|
if entity.GetId() == activeAvatarEntityId {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
entityIdList = append(entityIdList, entity.GetId())
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
visionType = proto.VisionType_VISION_TRANSPORT
|
visionType = proto.VisionType_VISION_TRANSPORT
|
||||||
}
|
entityIdList = addEntityIdList
|
||||||
entityMap := scene.GetAllEntity()
|
|
||||||
entityIdList := make([]uint32, 0)
|
|
||||||
for _, entity := range entityMap {
|
|
||||||
if entity.GetId() == activeAvatarEntityId {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
entityIdList = append(entityIdList, entity.GetId())
|
|
||||||
}
|
}
|
||||||
g.AddSceneEntityNotify(player, visionType, entityIdList, false, false)
|
g.AddSceneEntityNotify(player, visionType, entityIdList, false, false)
|
||||||
|
|
||||||
|
|||||||
@@ -17,37 +17,11 @@ type Scene struct {
|
|||||||
id uint32
|
id uint32
|
||||||
world *World
|
world *World
|
||||||
playerMap map[uint32]*model.Player
|
playerMap map[uint32]*model.Player
|
||||||
entityMap map[uint32]*Entity
|
entityMap map[uint32]*Entity // 场景中全部的实体
|
||||||
groupMap map[uint32]*Group
|
groupMap map[uint32]*Group // 场景中按group->suite分类的实体
|
||||||
gameTime uint32 // 游戏内提瓦特大陆的时间
|
gameTime uint32 // 游戏内提瓦特大陆的时间
|
||||||
createTime int64 // 场景创建时间
|
createTime int64 // 场景创建时间
|
||||||
meeoIndex uint32 // 客户端风元素染色同步协议的计数器
|
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
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Scene) GetId() 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) {
|
func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
|
||||||
groupConfig := gdconf.GetSceneGroup(int32(groupId))
|
groupConfig := gdconf.GetSceneGroup(int32(groupId))
|
||||||
if groupConfig == nil {
|
if groupConfig == nil {
|
||||||
|
logger.Error("get scene group config is nil, groupId: %v", groupId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
suiteConfig := groupConfig.SuiteList[suiteId-1]
|
suiteConfig := groupConfig.SuiteList[suiteId-1]
|
||||||
@@ -429,6 +404,7 @@ func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
|
|||||||
for _, monsterConfigId := range suiteConfig.MonsterConfigIdList {
|
for _, monsterConfigId := range suiteConfig.MonsterConfigIdList {
|
||||||
monster, exist := groupConfig.MonsterMap[monsterConfigId]
|
monster, exist := groupConfig.MonsterMap[monsterConfigId]
|
||||||
if !exist {
|
if !exist {
|
||||||
|
logger.Error("monster config not exist, monsterConfigId: %v", monsterConfigId)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
entityId := s.createConfigEntity(uint32(groupConfig.Id), monster)
|
entityId := s.createConfigEntity(uint32(groupConfig.Id), monster)
|
||||||
@@ -438,6 +414,7 @@ func (s *Scene) AddGroupSuite(groupId uint32, suiteId uint8) {
|
|||||||
for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList {
|
for _, gadgetConfigId := range suiteConfig.GadgetConfigIdList {
|
||||||
gadget, exist := groupConfig.GadgetMap[gadgetConfigId]
|
gadget, exist := groupConfig.GadgetMap[gadgetConfigId]
|
||||||
if !exist {
|
if !exist {
|
||||||
|
logger.Error("gadget config not exist, gadgetConfigId: %v", gadgetConfigId)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
entityId := s.createConfigEntity(uint32(groupConfig.Id), gadget)
|
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) {
|
func (s *Scene) RemoveGroupSuite(groupId uint32, suiteId uint8) {
|
||||||
group := s.groupMap[groupId]
|
group := s.groupMap[groupId]
|
||||||
if group == nil {
|
if group == nil {
|
||||||
|
logger.Error("group not exist, groupId: %v", groupId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
suite := group.suiteMap[suiteId]
|
suite := group.suiteMap[suiteId]
|
||||||
if suite == nil {
|
if suite == nil {
|
||||||
|
logger.Error("suite not exist, suiteId: %v", suiteId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
for _, entity := range suite.entityMap {
|
for _, entity := range suite.entityMap {
|
||||||
@@ -531,6 +510,7 @@ func (s *Scene) createConfigEntity(groupId uint32, entityConfig any) uint32 {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// TODO 临时写死
|
||||||
func getTempFightPropMap() map[uint32]float32 {
|
func getTempFightPropMap() map[uint32]float32 {
|
||||||
fpm := map[uint32]float32{
|
fpm := map[uint32]float32{
|
||||||
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
|
constant.FIGHT_PROP_CUR_HP: float32(72.91699),
|
||||||
@@ -552,6 +532,40 @@ func getTempFightPropMap() map[uint32]float32 {
|
|||||||
return fpm
|
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 场景实体数据结构
|
// Entity 场景实体数据结构
|
||||||
type Entity struct {
|
type Entity struct {
|
||||||
id uint32 // 实体id
|
id uint32 // 实体id
|
||||||
|
|||||||
Reference in New Issue
Block a user