mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-03-01 00:35:36 +08:00
优化登录、离线、服务器重启等会话连接问题
This commit is contained in:
+95
-62
@@ -4,6 +4,7 @@ import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gate/kcp"
|
||||
"hk4e/gs/dao"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/alg"
|
||||
@@ -41,80 +42,104 @@ func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue) (r *GameManager
|
||||
WORLD_MANAGER = NewWorldManager(r.snowflake)
|
||||
TICK_MANAGER = NewTickManager()
|
||||
COMMAND_MANAGER = NewCommandManager()
|
||||
r.run()
|
||||
return r
|
||||
}
|
||||
|
||||
func (g *GameManager) Start() {
|
||||
func (g *GameManager) run() {
|
||||
ROUTE_MANAGER.InitRoute()
|
||||
USER_MANAGER.StartAutoSaveUser()
|
||||
go func() {
|
||||
intervalTime := time.Second.Nanoseconds() * 60
|
||||
lastTime := time.Now().UnixNano()
|
||||
routeCost := int64(0)
|
||||
tickCost := int64(0)
|
||||
localEventCost := int64(0)
|
||||
commandCost := int64(0)
|
||||
for {
|
||||
now := time.Now().UnixNano()
|
||||
if now-lastTime > intervalTime {
|
||||
routeCost /= 1e6
|
||||
tickCost /= 1e6
|
||||
localEventCost /= 1e6
|
||||
commandCost /= 1e6
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost detail, routeCost: %vms, tickCost: %vms, localEventCost: %vms, commandCost: %vms",
|
||||
routeCost, tickCost, localEventCost, commandCost)
|
||||
totalCost := routeCost + tickCost + localEventCost + commandCost
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost percent, routeCost: %v%%, tickCost: %v%%, localEventCost: %v%%, commandCost: %v%%",
|
||||
float32(routeCost)/float32(totalCost)*100.0,
|
||||
float32(tickCost)/float32(totalCost)*100.0,
|
||||
float32(localEventCost)/float32(totalCost)*100.0,
|
||||
float32(commandCost)/float32(totalCost)*100.0)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost detail, totalCost: %vms",
|
||||
totalCost)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost percent, totalCost: %v%%",
|
||||
float32(totalCost)/float32(intervalTime/1e6)*100.0)
|
||||
lastTime = now
|
||||
routeCost = 0
|
||||
tickCost = 0
|
||||
localEventCost = 0
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
end := time.Now().UnixNano()
|
||||
routeCost += end - start
|
||||
case <-TICK_MANAGER.ticker.C:
|
||||
// 游戏服务器定时帧
|
||||
start := time.Now().UnixNano()
|
||||
TICK_MANAGER.OnGameServerTick()
|
||||
end := time.Now().UnixNano()
|
||||
tickCost += end - start
|
||||
case localEvent := <-LOCAL_EVENT_MANAGER.localEventChan:
|
||||
// 处理本地事件
|
||||
start := time.Now().UnixNano()
|
||||
LOCAL_EVENT_MANAGER.LocalEventHandle(localEvent)
|
||||
end := time.Now().UnixNano()
|
||||
localEventCost += end - start
|
||||
case command := <-COMMAND_MANAGER.commandTextInput:
|
||||
// 处理传入的命令 (普通玩家 GM命令)
|
||||
start := time.Now().UnixNano()
|
||||
COMMAND_MANAGER.HandleCommand(command)
|
||||
end := time.Now().UnixNano()
|
||||
commandCost += end - start
|
||||
}
|
||||
go g.gameMainLoopD()
|
||||
}
|
||||
|
||||
func (g *GameManager) gameMainLoopD() {
|
||||
for times := 1; times <= 1000; times++ {
|
||||
logger.Warn("start game main loop, times: %v", times)
|
||||
g.gameMainLoop()
|
||||
logger.Warn("game main loop stop")
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) gameMainLoop() {
|
||||
defer func() {
|
||||
if err := recover(); err != nil {
|
||||
logger.Error("!!! GAME MAIN LOOP PANIC !!!")
|
||||
logger.Error("error: %v", err)
|
||||
logger.Error("stack: %v", logger.Stack())
|
||||
}
|
||||
}()
|
||||
intervalTime := time.Second.Nanoseconds() * 60
|
||||
lastTime := time.Now().UnixNano()
|
||||
routeCost := int64(0)
|
||||
tickCost := int64(0)
|
||||
localEventCost := int64(0)
|
||||
commandCost := int64(0)
|
||||
for {
|
||||
now := time.Now().UnixNano()
|
||||
if now-lastTime > intervalTime {
|
||||
routeCost /= 1e6
|
||||
tickCost /= 1e6
|
||||
localEventCost /= 1e6
|
||||
commandCost /= 1e6
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost detail, routeCost: %vms, tickCost: %vms, localEventCost: %vms, commandCost: %vms",
|
||||
routeCost, tickCost, localEventCost, commandCost)
|
||||
totalCost := routeCost + tickCost + localEventCost + commandCost
|
||||
logger.Info("[GAME MAIN LOOP] cpu time cost percent, routeCost: %v%%, tickCost: %v%%, localEventCost: %v%%, commandCost: %v%%",
|
||||
float32(routeCost)/float32(totalCost)*100.0,
|
||||
float32(tickCost)/float32(totalCost)*100.0,
|
||||
float32(localEventCost)/float32(totalCost)*100.0,
|
||||
float32(commandCost)/float32(totalCost)*100.0)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost detail, totalCost: %vms",
|
||||
totalCost)
|
||||
logger.Info("[GAME MAIN LOOP] total cpu time cost percent, totalCost: %v%%",
|
||||
float32(totalCost)/float32(intervalTime/1e6)*100.0)
|
||||
lastTime = now
|
||||
routeCost = 0
|
||||
tickCost = 0
|
||||
localEventCost = 0
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
end := time.Now().UnixNano()
|
||||
routeCost += end - start
|
||||
case <-TICK_MANAGER.ticker.C:
|
||||
// 游戏服务器定时帧
|
||||
start := time.Now().UnixNano()
|
||||
TICK_MANAGER.OnGameServerTick()
|
||||
end := time.Now().UnixNano()
|
||||
tickCost += end - start
|
||||
case localEvent := <-LOCAL_EVENT_MANAGER.localEventChan:
|
||||
// 处理本地事件
|
||||
start := time.Now().UnixNano()
|
||||
LOCAL_EVENT_MANAGER.LocalEventHandle(localEvent)
|
||||
end := time.Now().UnixNano()
|
||||
localEventCost += end - start
|
||||
case command := <-COMMAND_MANAGER.commandTextInput:
|
||||
// 处理传入的命令 (普通玩家 GM命令)
|
||||
start := time.Now().UnixNano()
|
||||
COMMAND_MANAGER.HandleCommand(command)
|
||||
end := time.Now().UnixNano()
|
||||
commandCost += end - start
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) Stop() {
|
||||
// 下线玩家
|
||||
userList := USER_MANAGER.GetAllOnlineUserList()
|
||||
for _, player := range userList {
|
||||
g.DisconnectPlayer(player.PlayerID, kcp.EnetServerShutdown)
|
||||
}
|
||||
time.Sleep(time.Second * 5)
|
||||
// 保存玩家数据
|
||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||
EventId: RunUserCopyAndSave,
|
||||
}
|
||||
time.Sleep(time.Second * 3)
|
||||
time.Sleep(time.Second * 5)
|
||||
// g.worldManager.worldStatic.SaveTerrain()
|
||||
}
|
||||
|
||||
@@ -197,6 +222,14 @@ func (g *GameManager) ReconnectPlayer(userId uint32) {
|
||||
g.SendMsg(cmd.ClientReconnectNotify, userId, 0, new(proto.ClientReconnectNotify))
|
||||
}
|
||||
|
||||
func (g *GameManager) DisconnectPlayer(userId uint32) {
|
||||
g.SendMsg(cmd.ServerDisconnectClientNotify, userId, 0, new(proto.ServerDisconnectClientNotify))
|
||||
func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) {
|
||||
g.messageQueue.SendToGate("1", &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeConnCtrl,
|
||||
EventId: mq.KickPlayerNotify,
|
||||
ConnCtrlMsg: &mq.ConnCtrlMsg{
|
||||
KickUserId: userId,
|
||||
KickReason: reason,
|
||||
},
|
||||
})
|
||||
// g.SendMsg(cmd.ServerDisconnectClientNotify, userId, 0, new(proto.ServerDisconnectClientNotify))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user