服务器玩家在线信息同步

This commit is contained in:
flswld
2023-03-17 14:30:49 +08:00
parent 658b577c20
commit 7de1d2e765
19 changed files with 286 additions and 77 deletions

View File

@@ -85,7 +85,7 @@ func Run(ctx context.Context, configFile string) error {
messageQueue := mq.NewMessageQueue(api.GS, APPID, client)
defer messageQueue.Close()
gameManager := game.NewGameManager(db, messageQueue, GSID, APPID, mainGsAppid.AppId)
gameManager := game.NewGameManager(db, messageQueue, GSID, APPID, mainGsAppid.AppId, client.Discovery)
defer gameManager.Close()
// natsrpc server

View File

@@ -6,6 +6,7 @@ import (
"time"
"hk4e/common/mq"
"hk4e/common/rpc"
"hk4e/gate/kcp"
"hk4e/gdconf"
"hk4e/gs/dao"
@@ -46,6 +47,7 @@ var ONLINE_PLAYER_NUM int32 = 0 // 当前在线玩家数
var SELF *model.Player
type GameManager struct {
discovery *rpc.DiscoveryClient // node服务器客户端
dao *dao.Dao
snowflake *alg.SnowflakeWorker
gsId uint32
@@ -54,8 +56,9 @@ type GameManager struct {
ai *model.Player // 本服的Ai玩家对象
}
func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue, gsId uint32, gsAppid string, mainGsAppid string) (r *GameManager) {
func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue, gsId uint32, gsAppid string, mainGsAppid string, discovery *rpc.DiscoveryClient) (r *GameManager) {
r = new(GameManager)
r.discovery = discovery
r.dao = dao
MESSAGE_QUEUE = messageQueue
r.snowflake = alg.NewSnowflakeWorker(int64(gsId))

View File

@@ -240,14 +240,16 @@ func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq
g.SendMsg(cmd.QuestListNotify, userId, clientSeq, g.PacketQuestListNotify(player))
// g.GCGLogin(player) // 发送GCG登录相关的通知包
playerLoginRsp := &proto.PlayerLoginRsp{
IsUseAbilityHash: true,
AbilityHashCode: 0,
GameBiz: "hk4e_global",
IsScOpen: false,
RegisterCps: "mihoyo",
CountryCode: "CN",
Birthday: "2000-01-01",
TotalTickTime: 0.0,
IsUseAbilityHash: true,
AbilityHashCode: 0,
IsEnableClientHashDebug: true,
IsScOpen: false,
ScInfo: []byte{},
TotalTickTime: 0.0,
GameBiz: "hk4e_global",
RegisterCps: "mihoyo",
CountryCode: "US",
Birthday: "2000-01-01",
}
g.SendMsg(cmd.PlayerLoginRsp, userId, clientSeq, playerLoginRsp)
}

View File

@@ -1,6 +1,8 @@
package game
import (
"context"
"sync"
"time"
"hk4e/gs/dao"
@@ -19,10 +21,11 @@ import (
// 玩家定时保存 写入db和redis
type UserManager struct {
dao *dao.Dao // db对象
playerMap map[uint32]*model.Player // 内存玩家数据
saveUserChan chan *SaveUserData // 用于主协程发送玩家数据给定时保存协程
remotePlayerMap map[uint32]string // 远程玩家 key:userId value:玩家所在gs的appid
dao *dao.Dao // db对象
playerMap map[uint32]*model.Player // 内存玩家数据
saveUserChan chan *SaveUserData // 用于主协程发送玩家数据给定时保存协程
remotePlayerMap map[uint32]string // 远程玩家 key:userId value:玩家所在gs的appid
remotePlayerMapLock sync.RWMutex
}
func NewUserManager(dao *dao.Dao) (r *UserManager) {
@@ -32,6 +35,8 @@ func NewUserManager(dao *dao.Dao) (r *UserManager) {
r.saveUserChan = make(chan *SaveUserData) // 无缓冲区chan 避免主协程在写入时被迫加锁
r.remotePlayerMap = make(map[uint32]string)
go r.saveUserHandle()
r.syncRemotePlayerMap()
go r.autoSyncRemotePlayerMap()
return r
}
@@ -251,8 +256,39 @@ func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
// 远程玩家相关操作
func (u *UserManager) autoSyncRemotePlayerMap() {
ticker := time.NewTicker(time.Second * 60)
for {
<-ticker.C
u.syncRemotePlayerMap()
}
}
func (u *UserManager) syncRemotePlayerMap() {
rsp, err := GAME_MANAGER.discovery.GetGlobalGsOnlineMap(context.TODO(), nil)
if err != nil {
logger.Error("get global gs online map error: %v", err)
return
}
copyMap := make(map[uint32]string)
for k, v := range rsp.GlobalGsOnlineMap {
player, exist := u.playerMap[k]
if exist && player.Online {
continue
}
copyMap[k] = v
}
copyMapLen := len(copyMap)
u.remotePlayerMapLock.Lock()
u.remotePlayerMap = copyMap
u.remotePlayerMapLock.Unlock()
logger.Info("sync remote player map finish, len: %v", copyMapLen)
}
func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
u.remotePlayerMapLock.RLock()
_, exist := u.remotePlayerMap[userId]
u.remotePlayerMapLock.RUnlock()
if !exist {
return false
} else {
@@ -261,7 +297,9 @@ func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
}
func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
u.remotePlayerMapLock.RLock()
appId, exist := u.remotePlayerMap[userId]
u.remotePlayerMapLock.RUnlock()
if !exist {
return ""
} else {
@@ -270,12 +308,14 @@ func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
}
func (u *UserManager) SetRemoteUserOnlineState(userId uint32, isOnline bool, appId string) {
u.remotePlayerMapLock.Lock()
if isOnline {
u.remotePlayerMap[userId] = appId
} else {
delete(u.remotePlayerMap, userId)
u.DeleteUser(userId)
}
u.remotePlayerMapLock.Unlock()
}
// GetRemoteOnlineUserList 获取指定数量的远程在线玩家 玩家数据只读禁止修改
@@ -285,16 +325,22 @@ func (u *UserManager) GetRemoteOnlineUserList(total int) map[uint32]*model.Playe
}
onlinePlayerMap := make(map[uint32]*model.Player)
count := 0
userIdList := make([]uint32, 0)
u.remotePlayerMapLock.RLock()
for userId := range u.remotePlayerMap {
userIdList = append(userIdList, userId)
count++
if count >= total {
break
}
}
u.remotePlayerMapLock.RUnlock()
for _, userId := range userIdList {
player := u.LoadTempOfflineUser(userId, false)
if player == nil {
continue
}
onlinePlayerMap[player.PlayerID] = player
count++
if count >= total {
break
}
}
return onlinePlayerMap
}