mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:52:27 +08:00
玩家管理模块接入redis,已完整实现好友、多人世界的跨服交互功能
This commit is contained in:
@@ -6,31 +6,55 @@ import (
|
||||
"hk4e/common/config"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/go-redis/redis/v8"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"go.mongodb.org/mongo-driver/mongo/readpref"
|
||||
)
|
||||
|
||||
type Dao struct {
|
||||
client *mongo.Client
|
||||
db *mongo.Database
|
||||
mongo *mongo.Client
|
||||
db *mongo.Database
|
||||
redis *redis.Client
|
||||
}
|
||||
|
||||
func NewDao() (r *Dao, err error) {
|
||||
r = new(Dao)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url)
|
||||
clientOptions := options.Client().ApplyURI(config.CONF.Database.Url).SetMinPoolSize(1).SetMaxPoolSize(10)
|
||||
client, err := mongo.Connect(context.TODO(), clientOptions)
|
||||
if err != nil {
|
||||
logger.Error("mongo connect error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
r.client = client
|
||||
err = client.Ping(context.TODO(), readpref.Primary())
|
||||
if err != nil {
|
||||
logger.Error("mongo ping error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
r.mongo = client
|
||||
r.db = client.Database("gs_hk4e")
|
||||
r.redis = redis.NewClient(&redis.Options{
|
||||
Addr: config.CONF.Redis.Addr,
|
||||
Password: config.CONF.Redis.Password,
|
||||
DB: 0,
|
||||
PoolSize: 10,
|
||||
MinIdleConns: 1,
|
||||
})
|
||||
err = r.redis.Ping(context.TODO()).Err()
|
||||
if err != nil {
|
||||
logger.Error("redis ping error: %v", err)
|
||||
return nil, err
|
||||
}
|
||||
return r, nil
|
||||
}
|
||||
|
||||
func (d *Dao) CloseDao() {
|
||||
err := d.client.Disconnect(context.TODO())
|
||||
err := d.mongo.Disconnect(context.TODO())
|
||||
if err != nil {
|
||||
logger.Error("mongo close error: %v", err)
|
||||
}
|
||||
err = d.redis.Close()
|
||||
if err != nil {
|
||||
logger.Error("redis close error: %v", err)
|
||||
}
|
||||
}
|
||||
|
||||
53
gs/dao/player_redis.go
Normal file
53
gs/dao/player_redis.go
Normal file
@@ -0,0 +1,53 @@
|
||||
package dao
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strconv"
|
||||
"time"
|
||||
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
)
|
||||
|
||||
const RedisPlayerKeyPrefix = "HK4E"
|
||||
|
||||
func (d *Dao) GetRedisPlayerKey(userId uint32) string {
|
||||
return RedisPlayerKeyPrefix + ":USER:" + strconv.Itoa(int(userId))
|
||||
}
|
||||
|
||||
func (d *Dao) GetRedisPlayer(userId uint32) *model.Player {
|
||||
playerData, err := d.redis.Get(context.TODO(), d.GetRedisPlayerKey(userId)).Result()
|
||||
if err != nil {
|
||||
logger.Error("get player from redis error: %v", err)
|
||||
return nil
|
||||
}
|
||||
player := new(model.Player)
|
||||
err = msgpack.Unmarshal([]byte(playerData), player)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (d *Dao) SetRedisPlayer(player *model.Player) {
|
||||
playerData, err := msgpack.Marshal(player)
|
||||
if err != nil {
|
||||
logger.Error("marshal player error: %v", err)
|
||||
return
|
||||
}
|
||||
err = d.redis.Set(context.TODO(), d.GetRedisPlayerKey(player.PlayerID), playerData, time.Hour*24*30).Err()
|
||||
if err != nil {
|
||||
logger.Error("set player from redis error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (d *Dao) SetRedisPlayerList(playerList []*model.Player) {
|
||||
// TODO 换成redis批量命令执行
|
||||
for _, player := range playerList {
|
||||
d.SetRedisPlayer(player)
|
||||
}
|
||||
}
|
||||
@@ -225,7 +225,7 @@ func (c *CommandManager) SendMessage(executor any, msg string, param ...any) {
|
||||
case *model.Player:
|
||||
// 玩家类型
|
||||
player := executor.(*model.Player)
|
||||
GAME_MANAGER.SendPrivateChat(c.system, player, fmt.Sprintf(msg, param...))
|
||||
GAME_MANAGER.SendPrivateChat(c.system, player.PlayerID, fmt.Sprintf(msg, param...))
|
||||
case string:
|
||||
// GM接口等
|
||||
// str := executor.(string)
|
||||
|
||||
@@ -26,12 +26,12 @@ var USER_MANAGER *UserManager = nil
|
||||
var WORLD_MANAGER *WorldManager = nil
|
||||
var TICK_MANAGER *TickManager = nil
|
||||
var COMMAND_MANAGER *CommandManager = nil
|
||||
var MESSAGE_QUEUE *mq.MessageQueue
|
||||
|
||||
var SELF *model.Player
|
||||
|
||||
type GameManager struct {
|
||||
dao *dao.Dao
|
||||
messageQueue *mq.MessageQueue
|
||||
snowflake *alg.SnowflakeWorker
|
||||
clientCmdProtoMap *client_proto.ClientCmdProtoMap
|
||||
clientCmdProtoMapRefValue reflect.Value
|
||||
@@ -40,7 +40,7 @@ type GameManager struct {
|
||||
func NewGameManager(dao *dao.Dao, messageQueue *mq.MessageQueue, gsId uint32) (r *GameManager) {
|
||||
r = new(GameManager)
|
||||
r.dao = dao
|
||||
r.messageQueue = messageQueue
|
||||
MESSAGE_QUEUE = messageQueue
|
||||
r.snowflake = alg.NewSnowflakeWorker(int64(gsId))
|
||||
if appConfig.CONF.Hk4e.ClientProtoProxyEnable {
|
||||
r.clientCmdProtoMap = client_proto.NewClientCmdProtoMap()
|
||||
@@ -115,7 +115,7 @@ func (g *GameManager) gameMainLoop() {
|
||||
commandCost = 0
|
||||
}
|
||||
select {
|
||||
case netMsg := <-g.messageQueue.GetNetMsg():
|
||||
case netMsg := <-MESSAGE_QUEUE.GetNetMsg():
|
||||
// 接收客户端消息
|
||||
start := time.Now().UnixNano()
|
||||
ROUTE_MANAGER.RouteHandle(netMsg)
|
||||
@@ -171,7 +171,7 @@ func (g *GameManager) SendMsgEx(cmdId uint16, userId uint32, clientSeq uint32, g
|
||||
ClientSeq: clientSeq,
|
||||
PayloadMessage: payloadMsg,
|
||||
}
|
||||
g.messageQueue.SendToGate(gateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(gateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeGame,
|
||||
EventId: mq.NormalMsg,
|
||||
GameMsg: gameMsg,
|
||||
@@ -203,7 +203,7 @@ func (g *GameManager) SendMsg(cmdId uint16, userId uint32, clientSeq uint32, pay
|
||||
return
|
||||
}
|
||||
gameMsg.PayloadMessageData = payloadMessageData
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeGame,
|
||||
EventId: mq.NormalMsg,
|
||||
GameMsg: gameMsg,
|
||||
@@ -271,7 +271,7 @@ func (g *GameManager) DisconnectPlayer(userId uint32, reason uint32) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeConnCtrl,
|
||||
EventId: mq.KickPlayerNotify,
|
||||
ConnCtrlMsg: &mq.ConnCtrlMsg{
|
||||
|
||||
@@ -3,6 +3,7 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
@@ -11,9 +12,10 @@ import (
|
||||
// 本地事件队列管理器
|
||||
|
||||
const (
|
||||
LoadLoginUserFromDbFinish = iota
|
||||
CheckUserExistOnRegFromDbFinish
|
||||
RunUserCopyAndSave
|
||||
LoadLoginUserFromDbFinish = iota // 玩家登录从数据库加载完成回调
|
||||
CheckUserExistOnRegFromDbFinish // 玩家注册从数据库查询是否已存在完成回调
|
||||
RunUserCopyAndSave // 执行一次在线玩家内存数据复制到数据库写入协程
|
||||
UserOfflineSaveToDbFinish
|
||||
)
|
||||
|
||||
type LocalEvent struct {
|
||||
@@ -89,5 +91,30 @@ func (l *LocalEventManager) LocalEventHandle(localEvent *LocalEvent) {
|
||||
endTime := time.Now().UnixNano()
|
||||
costTime := endTime - startTime
|
||||
logger.Info("run save user copy cost time: %v ns", costTime)
|
||||
case UserOfflineSaveToDbFinish:
|
||||
playerOfflineInfo := localEvent.Msg.(*PlayerOfflineInfo)
|
||||
USER_MANAGER.DeleteUser(playerOfflineInfo.Player.PlayerID)
|
||||
MESSAGE_QUEUE.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: playerOfflineInfo.Player.PlayerID,
|
||||
IsOnline: false,
|
||||
},
|
||||
})
|
||||
if playerOfflineInfo.ChangeGsInfo.IsChangeGs {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(playerOfflineInfo.ChangeGsInfo.JoinHostUserId)
|
||||
MESSAGE_QUEUE.SendToGate(playerOfflineInfo.Player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserGsChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: playerOfflineInfo.Player.PlayerID,
|
||||
GameServerAppId: gsAppId,
|
||||
JoinHostUserId: playerOfflineInfo.ChangeGsInfo.JoinHostUserId,
|
||||
},
|
||||
})
|
||||
logger.Info("user change gs notify to gate, uid: %v, gate appid: %v, gs appid: %v, host uid: %v",
|
||||
playerOfflineInfo.Player.PlayerID, playerOfflineInfo.Player.GateAppId, gsAppId, playerOfflineInfo.ChangeGsInfo.JoinHostUserId)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -42,6 +42,10 @@ func (r *RouteManager) doRoute(cmdId uint16, userId uint32, clientSeq uint32, pa
|
||||
GAME_MANAGER.DisconnectPlayer(userId, kcp.EnetNotFoundSession)
|
||||
return
|
||||
}
|
||||
if !player.Online {
|
||||
logger.Error("player not online, uid: %v", userId)
|
||||
return
|
||||
}
|
||||
player.ClientSeq = clientSeq
|
||||
SELF = player
|
||||
handlerFunc(player, payloadMsg)
|
||||
@@ -139,8 +143,6 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
return
|
||||
}
|
||||
r.doRoute(gameMsg.CmdId, gameMsg.UserId, gameMsg.ClientSeq, gameMsg.PayloadMessage)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(gameMsg.UserId)
|
||||
}
|
||||
case mq.MsgTypeConnCtrl:
|
||||
if netMsg.OriginServerType != api.GATE {
|
||||
@@ -152,6 +154,10 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
GAME_MANAGER.ClientRttNotify(connCtrlMsg.UserId, connCtrlMsg.ClientRtt)
|
||||
case mq.ClientTimeNotify:
|
||||
GAME_MANAGER.ClientTimeNotify(connCtrlMsg.UserId, connCtrlMsg.ClientTime)
|
||||
case mq.UserOfflineNotify:
|
||||
GAME_MANAGER.OnUserOffline(connCtrlMsg.UserId, &ChangeGsInfo{
|
||||
IsChangeGs: false,
|
||||
})
|
||||
}
|
||||
case mq.MsgTypeServer:
|
||||
serverMsg := netMsg.ServerMsg
|
||||
@@ -161,10 +167,18 @@ func (r *RouteManager) RouteHandle(netMsg *mq.NetMsg) {
|
||||
USER_MANAGER.SetRemoteUserOnlineState(serverMsg.UserId, serverMsg.IsOnline, netMsg.OriginServerAppId)
|
||||
case mq.ServerAppidBindNotify:
|
||||
GAME_MANAGER.ServerAppidBindNotify(serverMsg.UserId, serverMsg.FightServerAppId, serverMsg.JoinHostUserId)
|
||||
case mq.ServerGetUserBaseInfoReq:
|
||||
GAME_MANAGER.ServerGetUserBaseInfoReq(serverMsg.UserBaseInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerGetUserBaseInfoRsp:
|
||||
GAME_MANAGER.ServerGetUserBaseInfoRsp(serverMsg.UserBaseInfo)
|
||||
case mq.ServerUserBaseInfoReq:
|
||||
GAME_MANAGER.ServerUserBaseInfoReq(serverMsg.UserBaseInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerUserBaseInfoRsp:
|
||||
GAME_MANAGER.ServerUserBaseInfoRsp(serverMsg.UserBaseInfo)
|
||||
case mq.ServerUserMpReq:
|
||||
GAME_MANAGER.ServerUserMpReq(serverMsg.UserMpInfo, netMsg.OriginServerAppId)
|
||||
case mq.ServerUserMpRsp:
|
||||
GAME_MANAGER.ServerUserMpRsp(serverMsg.UserMpInfo)
|
||||
case mq.ServerChatMsgNotify:
|
||||
GAME_MANAGER.ServerChatMsgNotify(serverMsg.ChatMsgInfo)
|
||||
case mq.ServerAddFriendNotify:
|
||||
GAME_MANAGER.ServerAddFriendNotify(serverMsg.AddFriendInfo)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/protocol/cmd"
|
||||
@@ -78,15 +79,14 @@ func (g *GameManager) PullPrivateChatReq(player *model.Player, payloadMsg pb.Mes
|
||||
}
|
||||
|
||||
// SendPrivateChat 发送私聊文本消息给玩家
|
||||
func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, content any) {
|
||||
func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, content any) {
|
||||
chatInfo := &proto.ChatInfo{
|
||||
Time: uint32(time.Now().Unix()),
|
||||
Sequence: 101,
|
||||
ToUid: targetPlayer.PlayerID,
|
||||
ToUid: targetUid,
|
||||
Uid: player.PlayerID,
|
||||
IsRead: false,
|
||||
}
|
||||
|
||||
// 根据传入的值判断消息类型
|
||||
switch content.(type) {
|
||||
case string:
|
||||
@@ -100,21 +100,52 @@ func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, conten
|
||||
Icon: content.(uint32),
|
||||
}
|
||||
}
|
||||
|
||||
chatMsg := g.ConvChatInfoToChatMsg(chatInfo)
|
||||
// 消息加入自己的队列
|
||||
msgList, exist := player.ChatMsgMap[targetPlayer.PlayerID]
|
||||
msgList, exist := player.ChatMsgMap[targetUid]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
player.ChatMsgMap[targetPlayer.PlayerID] = msgList
|
||||
msgList = append(msgList, chatMsg)
|
||||
player.ChatMsgMap[targetUid] = msgList
|
||||
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: chatInfo,
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, player.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 目标玩家在别的服在线
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerChatMsgNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
ChatMsgInfo: &mq.ChatMsgInfo{
|
||||
Time: chatMsg.Time,
|
||||
ToUid: chatMsg.ToUid,
|
||||
Uid: chatMsg.Uid,
|
||||
IsRead: chatMsg.IsRead,
|
||||
MsgType: chatMsg.MsgType,
|
||||
Text: chatMsg.Text,
|
||||
Icon: chatMsg.Icon,
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 目标玩家全服离线
|
||||
// TODO 接入redis直接同步写入数据
|
||||
}
|
||||
return
|
||||
}
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, g.ConvChatInfoToChatMsg(chatInfo))
|
||||
msgList = append(msgList, chatMsg)
|
||||
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
||||
|
||||
// 如果目标玩家在线发送消息
|
||||
@@ -124,11 +155,6 @@ func (g *GameManager) SendPrivateChat(player, targetPlayer *model.Player, conten
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, targetPlayer.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
}
|
||||
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: chatInfo,
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, player.PlayerID, player.ClientSeq, privateChatNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -137,12 +163,6 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
targetUid := req.TargetUid
|
||||
content := req.Content
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return
|
||||
}
|
||||
|
||||
// 根据发送的类型发送消息
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
@@ -150,25 +170,14 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
if len(text) == 0 {
|
||||
return
|
||||
}
|
||||
|
||||
// 发送私聊文本消息
|
||||
g.SendPrivateChat(player, targetPlayer, text)
|
||||
|
||||
g.SendPrivateChat(player, targetUid, text)
|
||||
// 输入命令 会检测是否为命令的
|
||||
COMMAND_MANAGER.InputCommand(player, text)
|
||||
|
||||
if text == "VPU" {
|
||||
g.VideoPlayerUpdate(false)
|
||||
} else if text == "VPUR" {
|
||||
g.VideoPlayerUpdate(true)
|
||||
}
|
||||
|
||||
case *proto.PrivateChatReq_Icon:
|
||||
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
||||
|
||||
// 发送私聊图标消息
|
||||
g.SendPrivateChat(player, targetPlayer, icon)
|
||||
|
||||
g.SendPrivateChat(player, targetUid, icon)
|
||||
default:
|
||||
return
|
||||
}
|
||||
@@ -281,3 +290,37 @@ func (g *GameManager) ConvChatMsgToChatInfo(chatMsg *model.ChatMsg) (chatInfo *p
|
||||
}
|
||||
return chatInfo
|
||||
}
|
||||
|
||||
// 跨服玩家聊天通知
|
||||
|
||||
func (g *GameManager) ServerChatMsgNotify(chatMsgInfo *mq.ChatMsgInfo) {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(chatMsgInfo.ToUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", chatMsgInfo.ToUid)
|
||||
return
|
||||
}
|
||||
chatMsg := &model.ChatMsg{
|
||||
Time: chatMsgInfo.Time,
|
||||
ToUid: chatMsgInfo.ToUid,
|
||||
Uid: chatMsgInfo.Uid,
|
||||
IsRead: chatMsgInfo.IsRead,
|
||||
MsgType: chatMsgInfo.MsgType,
|
||||
Text: chatMsgInfo.Text,
|
||||
Icon: chatMsgInfo.Icon,
|
||||
}
|
||||
// 消息加入目标玩家的队列
|
||||
msgList, exist := targetPlayer.ChatMsgMap[chatMsgInfo.Uid]
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
msgList = append(msgList, chatMsg)
|
||||
targetPlayer.ChatMsgMap[chatMsgInfo.Uid] = msgList
|
||||
|
||||
// 如果目标玩家在线发送消息
|
||||
if targetPlayer.Online {
|
||||
privateChatNotify := &proto.PrivateChatNotify{
|
||||
ChatInfo: g.ConvChatMsgToChatInfo(chatMsg),
|
||||
}
|
||||
g.SendMsg(cmd.PrivateChatNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, privateChatNotify)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@ package game
|
||||
import (
|
||||
"time"
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
@@ -131,7 +130,10 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
}
|
||||
if joinHostUserId != 0 {
|
||||
hostPlayer := USER_MANAGER.GetOnlineUser(joinHostUserId)
|
||||
g.HostEnterMpWorld(hostPlayer, player.PlayerID)
|
||||
if hostPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", joinHostUserId)
|
||||
return
|
||||
}
|
||||
g.JoinOtherWorld(player, hostPlayer)
|
||||
return
|
||||
}
|
||||
@@ -139,7 +141,7 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
player.FightAppId = fightAppId
|
||||
// 创建世界
|
||||
world := WORLD_MANAGER.CreateWorld(player)
|
||||
GAME_MANAGER.messageQueue.SendToFight(fightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(fightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.AddFightRoutine,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -153,53 +155,3 @@ func (g *GameManager) ServerAppidBindNotify(userId uint32, fightAppId string, jo
|
||||
player.SceneLoadState = model.SceneNone
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, userId, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_SELF))
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerGetUserBaseInfoReq(userBaseInfo *mq.UserBaseInfo, gsAppId string) {
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.UserId)
|
||||
return
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
g.messageQueue.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerGetUserBaseInfoRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: userBaseInfo.OriginInfo,
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerGetUserBaseInfoRsp(userBaseInfo *mq.UserBaseInfo) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: userBaseInfo.UserId,
|
||||
TargetPlayerInfo: &proto.OnlinePlayerInfo{
|
||||
Uid: userBaseInfo.UserId,
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
PlayerLevel: userBaseInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userBaseInfo.MpSettingType),
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
Signature: userBaseInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userBaseInfo.WorldPlayerNum,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,14 +61,16 @@ func (g *GameManager) OnLoginOk(userId uint32, player *model.Player, clientSeq u
|
||||
|
||||
g.LoginNotify(userId, player, clientSeq)
|
||||
|
||||
g.messageQueue.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: true,
|
||||
},
|
||||
})
|
||||
if userId >= 100000000 {
|
||||
MESSAGE_QUEUE.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: true,
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) OnReg(userId uint32, clientSeq uint32, gateAppId string, payloadMsg pb.Message) {
|
||||
@@ -106,7 +108,7 @@ func (g *GameManager) OnRegOk(exist bool, req *proto.SetPlayerBornDataReq, userI
|
||||
g.OnLogin(userId, clientSeq, gateAppId)
|
||||
}
|
||||
|
||||
func (g *GameManager) OnUserOffline(userId uint32) {
|
||||
func (g *GameManager) OnUserOffline(userId uint32, changeGsInfo *ChangeGsInfo) {
|
||||
logger.Info("user offline, uid: %v", userId)
|
||||
player := USER_MANAGER.GetOnlineUser(userId)
|
||||
if player == nil {
|
||||
@@ -120,16 +122,7 @@ func (g *GameManager) OnUserOffline(userId uint32) {
|
||||
player.OfflineTime = uint32(time.Now().Unix())
|
||||
player.Online = false
|
||||
player.TotalOnlineTime += uint32(time.Now().UnixMilli()) - player.OnlineTime
|
||||
USER_MANAGER.DeleteUser(player)
|
||||
|
||||
g.messageQueue.SendToAll(&mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserOnlineStateChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: userId,
|
||||
IsOnline: false,
|
||||
},
|
||||
})
|
||||
USER_MANAGER.OfflineUser(player, changeGsInfo)
|
||||
}
|
||||
|
||||
func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq uint32) {
|
||||
|
||||
@@ -6,56 +6,36 @@ import (
|
||||
"hk4e/gs/dao"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
"hk4e/protocol/proto"
|
||||
)
|
||||
|
||||
type SaveUserData struct {
|
||||
insertPlayerList []*model.Player
|
||||
updatePlayerList []*model.Player
|
||||
}
|
||||
// 玩家管理器
|
||||
|
||||
// 玩家注册 从db查询对应uid是否存在并异步回调返回结果
|
||||
// 玩家登录 从db查询出来然后写入redis并异步回调返回玩家对象
|
||||
// 玩家离线 写入db和redis
|
||||
// 玩家定时保存 写入db和redis
|
||||
|
||||
type UserManager struct {
|
||||
dao *dao.Dao
|
||||
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
|
||||
}
|
||||
|
||||
func NewUserManager(dao *dao.Dao) (r *UserManager) {
|
||||
r = new(UserManager)
|
||||
r.dao = dao
|
||||
r.playerMap = make(map[uint32]*model.Player)
|
||||
r.saveUserChan = make(chan *SaveUserData)
|
||||
r.saveUserChan = make(chan *SaveUserData) // 无缓冲区chan 避免主协程在写入时被迫加锁
|
||||
r.remotePlayerMap = make(map[uint32]string)
|
||||
return r
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
|
||||
_, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
|
||||
appId, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return ""
|
||||
} else {
|
||||
return appId
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SetRemoteUserOnlineState(userId uint32, isOnline bool, appId string) {
|
||||
if isOnline {
|
||||
u.remotePlayerMap[userId] = appId
|
||||
} else {
|
||||
delete(u.remotePlayerMap, userId)
|
||||
}
|
||||
}
|
||||
// 在线玩家相关操作
|
||||
|
||||
// GetUserOnlineState 获取玩家在线状态
|
||||
func (u *UserManager) GetUserOnlineState(userId uint32) bool {
|
||||
player, exist := u.playerMap[userId]
|
||||
if !exist {
|
||||
@@ -65,6 +45,7 @@ func (u *UserManager) GetUserOnlineState(userId uint32) bool {
|
||||
}
|
||||
}
|
||||
|
||||
// GetOnlineUser 获取在线玩家对象
|
||||
func (u *UserManager) GetOnlineUser(userId uint32) *model.Player {
|
||||
player, exist := u.playerMap[userId]
|
||||
if !exist {
|
||||
@@ -78,6 +59,7 @@ func (u *UserManager) GetOnlineUser(userId uint32) *model.Player {
|
||||
}
|
||||
}
|
||||
|
||||
// GetAllOnlineUserList 获取全部在线玩家
|
||||
func (u *UserManager) GetAllOnlineUserList() map[uint32]*model.Player {
|
||||
onlinePlayerMap := make(map[uint32]*model.Player)
|
||||
for userId, player := range u.playerMap {
|
||||
@@ -97,13 +79,14 @@ type PlayerRegInfo struct {
|
||||
GateAppId string
|
||||
}
|
||||
|
||||
// CheckUserExistOnReg 玩家注册检查是否已存在
|
||||
func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBornDataReq, clientSeq uint32, gateAppId string) (exist bool, asyncWait bool) {
|
||||
_, exist = u.playerMap[userId]
|
||||
if exist {
|
||||
return true, false
|
||||
} else {
|
||||
go func() {
|
||||
player := u.loadUserFromDb(userId)
|
||||
player := u.LoadUserFromDbSync(userId)
|
||||
exist = false
|
||||
if player != nil {
|
||||
exist = true
|
||||
@@ -123,38 +106,7 @@ func (u *UserManager) CheckUserExistOnReg(userId uint32, req *proto.SetPlayerBor
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadTempOfflineUserSync(userId uint32) *model.Player {
|
||||
player, exist := u.playerMap[userId]
|
||||
if exist {
|
||||
return player
|
||||
} else {
|
||||
player = u.loadUserFromDb(userId)
|
||||
if player == nil {
|
||||
return nil
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
return player
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) loadUserFromDb(userId uint32) *model.Player {
|
||||
player, err := u.dao.QueryPlayerByID(userId)
|
||||
if err != nil {
|
||||
logger.Error("query player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) saveUserToDb(player *model.Player) {
|
||||
err := u.dao.UpdatePlayer(player)
|
||||
if err != nil {
|
||||
logger.Error("update player error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// AddUser 向内存玩家数据里添加一个玩家
|
||||
func (u *UserManager) AddUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
@@ -163,12 +115,9 @@ func (u *UserManager) AddUser(player *model.Player) {
|
||||
u.playerMap[player.PlayerID] = player
|
||||
}
|
||||
|
||||
func (u *UserManager) DeleteUser(player *model.Player) {
|
||||
if player == nil {
|
||||
return
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
// DeleteUser 从内存玩家数据里删除一个玩家
|
||||
func (u *UserManager) DeleteUser(userId uint32) {
|
||||
delete(u.playerMap, userId)
|
||||
}
|
||||
|
||||
type PlayerLoginInfo struct {
|
||||
@@ -178,6 +127,7 @@ type PlayerLoginInfo struct {
|
||||
GateAppId string
|
||||
}
|
||||
|
||||
// OnlineUser 玩家上线
|
||||
func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId string) (*model.Player, bool) {
|
||||
player, exist := u.playerMap[userId]
|
||||
if exist {
|
||||
@@ -185,8 +135,9 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
||||
return player, false
|
||||
} else {
|
||||
go func() {
|
||||
player = u.loadUserFromDb(userId)
|
||||
player = u.LoadUserFromDbSync(userId)
|
||||
if player != nil {
|
||||
u.SaveUserToRedisSync(player)
|
||||
u.ChangeUserDbState(player, model.DbNormal)
|
||||
} else {
|
||||
logger.Error("can not find user from db, uid: %v", userId)
|
||||
@@ -205,6 +156,38 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
||||
}
|
||||
}
|
||||
|
||||
type ChangeGsInfo struct {
|
||||
IsChangeGs bool
|
||||
JoinHostUserId uint32
|
||||
}
|
||||
|
||||
type PlayerOfflineInfo struct {
|
||||
Player *model.Player
|
||||
ChangeGsInfo *ChangeGsInfo
|
||||
}
|
||||
|
||||
// OfflineUser 玩家离线
|
||||
func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsInfo) {
|
||||
playerCopy := new(model.Player)
|
||||
err := object.FastDeepCopy(playerCopy, player)
|
||||
if err != nil {
|
||||
logger.Error("deep copy player error: %v", err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
u.SaveUserToDbSync(playerCopy)
|
||||
u.SaveUserToRedisSync(playerCopy)
|
||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||
EventId: UserOfflineSaveToDbFinish,
|
||||
Msg: &PlayerOfflineInfo{
|
||||
Player: player,
|
||||
ChangeGsInfo: changeGsInfo,
|
||||
},
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
// ChangeUserDbState 玩家存档状态机 主要用于玩家定时保存时进行分类处理
|
||||
func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
|
||||
if player == nil {
|
||||
return
|
||||
@@ -238,8 +221,140 @@ func (u *UserManager) ChangeUserDbState(player *model.Player, state int) {
|
||||
}
|
||||
}
|
||||
|
||||
// 用户数据库定时同步
|
||||
// 远程玩家相关操作
|
||||
|
||||
func (u *UserManager) GetRemoteUserOnlineState(userId uint32) bool {
|
||||
_, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) GetRemoteUserGsAppId(userId uint32) string {
|
||||
appId, exist := u.remotePlayerMap[userId]
|
||||
if !exist {
|
||||
return ""
|
||||
} else {
|
||||
return appId
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SetRemoteUserOnlineState(userId uint32, isOnline bool, appId string) {
|
||||
if isOnline {
|
||||
u.remotePlayerMap[userId] = appId
|
||||
} else {
|
||||
delete(u.remotePlayerMap, userId)
|
||||
u.DeleteUser(userId)
|
||||
}
|
||||
}
|
||||
|
||||
// GetRemoteOnlineUserList 获取指定数量的远程在线玩家
|
||||
func (u *UserManager) GetRemoteOnlineUserList(total int) map[uint32]*model.Player {
|
||||
if total > 50 {
|
||||
return nil
|
||||
}
|
||||
onlinePlayerMap := make(map[uint32]*model.Player)
|
||||
count := 0
|
||||
for userId := range u.remotePlayerMap {
|
||||
player := u.LoadTempOfflineUser(userId)
|
||||
if player == nil {
|
||||
continue
|
||||
}
|
||||
onlinePlayerMap[player.PlayerID] = player
|
||||
count++
|
||||
if count >= total {
|
||||
break
|
||||
}
|
||||
}
|
||||
return onlinePlayerMap
|
||||
}
|
||||
|
||||
// LoadGlobalPlayer 加载并返回一个全服玩家及其在线状态
|
||||
// 参见LoadTempOfflineUser说明
|
||||
func (u *UserManager) LoadGlobalPlayer(userId uint32) (player *model.Player, online bool, remote bool) {
|
||||
online = u.GetUserOnlineState(userId)
|
||||
remote = false
|
||||
if !online {
|
||||
// 本地不在线就看看远程在不在线
|
||||
online = u.GetRemoteUserOnlineState(userId)
|
||||
if online {
|
||||
remote = true
|
||||
}
|
||||
}
|
||||
if online {
|
||||
if remote {
|
||||
// 远程在线玩家 为了简化实现流程 直接加载数据库临时档
|
||||
player = u.LoadTempOfflineUser(userId)
|
||||
} else {
|
||||
// 本地在线玩家
|
||||
player = u.GetOnlineUser(userId)
|
||||
}
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
player = u.LoadTempOfflineUser(userId)
|
||||
}
|
||||
return player, online, remote
|
||||
}
|
||||
|
||||
// 离线玩家相关操作
|
||||
|
||||
// LoadTempOfflineUser 加载临时离线玩家
|
||||
// 正常情况速度较快可以同步阻塞调用
|
||||
func (u *UserManager) LoadTempOfflineUser(userId uint32) *model.Player {
|
||||
player := u.GetOnlineUser(userId)
|
||||
if player != nil && player.Online {
|
||||
logger.Error("not allow get a online player as offline player, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
player = u.LoadUserFromRedisSync(userId)
|
||||
if player == nil {
|
||||
// 玩家可能不存在于redis 尝试从db查询出来然后写入redis
|
||||
// 大多数情况下活跃玩家都在redis 所以不会走到下面
|
||||
// TODO 布隆过滤器防止恶意攻击造成redis缓存穿透
|
||||
if userId < 100000000 || userId > 200000000 {
|
||||
logger.Error("try to load a not exist uid, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
player = u.LoadUserFromDbSync(userId)
|
||||
if player == nil {
|
||||
// 玩家根本就不存在
|
||||
logger.Error("try to load a not exist player from db, uid: %v", userId)
|
||||
return nil
|
||||
}
|
||||
u.SaveUserToRedisSync(player)
|
||||
}
|
||||
u.ChangeUserDbState(player, model.DbDelete)
|
||||
u.playerMap[player.PlayerID] = player
|
||||
return player
|
||||
}
|
||||
|
||||
// SaveTempOfflineUser 保存临时离线玩家
|
||||
// 如果在调用LoadTempOfflineUser后修改了离线玩家数据 则必须立即调用此函数回写
|
||||
func (u *UserManager) SaveTempOfflineUser(player *model.Player) {
|
||||
// 主协程同步写入redis
|
||||
u.SaveUserToRedisSync(player)
|
||||
// 另一个协程异步的写回db
|
||||
playerCopy := new(model.Player)
|
||||
err := object.FastDeepCopy(playerCopy, player)
|
||||
if err != nil {
|
||||
logger.Error("deep copy player error: %v", err)
|
||||
return
|
||||
}
|
||||
go func() {
|
||||
u.SaveUserToDbSync(playerCopy)
|
||||
}()
|
||||
}
|
||||
|
||||
// db和redis相关操作
|
||||
|
||||
type SaveUserData struct {
|
||||
insertPlayerList []*model.Player
|
||||
updatePlayerList []*model.Player
|
||||
}
|
||||
|
||||
// StartAutoSaveUser 玩家定时保存
|
||||
func (u *UserManager) StartAutoSaveUser() {
|
||||
go func() {
|
||||
ticker := time.NewTicker(time.Minute * 5)
|
||||
@@ -253,12 +368,30 @@ func (u *UserManager) StartAutoSaveUser() {
|
||||
go func() {
|
||||
for {
|
||||
saveUserData := <-u.saveUserChan
|
||||
u.SaveUser(saveUserData)
|
||||
u.SaveUserListToDbSync(saveUserData)
|
||||
u.SaveUserListToRedisSync(saveUserData)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUser(saveUserData *SaveUserData) {
|
||||
func (u *UserManager) LoadUserFromDbSync(userId uint32) *model.Player {
|
||||
player, err := u.dao.QueryPlayerByID(userId)
|
||||
if err != nil {
|
||||
logger.Error("query player error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserToDbSync(player *model.Player) {
|
||||
err := u.dao.UpdatePlayer(player)
|
||||
if err != nil {
|
||||
logger.Error("update player error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserListToDbSync(saveUserData *SaveUserData) {
|
||||
err := u.dao.InsertPlayerList(saveUserData.insertPlayerList)
|
||||
if err != nil {
|
||||
logger.Error("insert player list error: %v", err)
|
||||
@@ -271,3 +404,23 @@ func (u *UserManager) SaveUser(saveUserData *SaveUserData) {
|
||||
}
|
||||
logger.Info("save user finish, insert user count: %v, update user count: %v", len(saveUserData.insertPlayerList), len(saveUserData.updatePlayerList))
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadUserFromRedisSync(userId uint32) *model.Player {
|
||||
player := u.dao.GetRedisPlayer(userId)
|
||||
return player
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserToRedisSync(player *model.Player) {
|
||||
u.dao.SetRedisPlayer(player)
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserListToRedisSync(saveUserData *SaveUserData) {
|
||||
setPlayerList := make([]*model.Player, 0, len(saveUserData.insertPlayerList)+len(saveUserData.updatePlayerList))
|
||||
for _, player := range saveUserData.insertPlayerList {
|
||||
setPlayerList = append(setPlayerList, player)
|
||||
}
|
||||
for _, player := range saveUserData.updatePlayerList {
|
||||
setPlayerList = append(setPlayerList, player)
|
||||
}
|
||||
u.dao.SetRedisPlayerList(setPlayerList)
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ import (
|
||||
|
||||
"hk4e/common/constant"
|
||||
"hk4e/common/mq"
|
||||
"hk4e/gate/kcp"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
@@ -27,16 +26,7 @@ func (g *GameManager) PlayerApplyEnterMpReq(player *model.Player, payloadMsg pb.
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpRsp, player.PlayerID, player.ClientSeq, playerApplyEnterMpRsp)
|
||||
|
||||
ok := g.UserApplyEnterWorld(player, targetUid)
|
||||
if !ok {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: targetUid,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
g.UserApplyEnterWorld(player, targetUid)
|
||||
}
|
||||
|
||||
func (g *GameManager) PlayerApplyEnterMpResultReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -73,22 +63,12 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(req.TargetUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", req.TargetUid)
|
||||
g.DisconnectPlayer(player.PlayerID, kcp.EnetServerKick)
|
||||
return
|
||||
}
|
||||
// 走玩家在线跨服迁移流程
|
||||
g.OnUserOffline(player.PlayerID)
|
||||
// TODO 改成异步写入数据库
|
||||
USER_MANAGER.saveUserToDb(player)
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(req.TargetUid)
|
||||
g.messageQueue.SendToGate(player.GateAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserGsChangeNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserId: player.PlayerID,
|
||||
GameServerAppId: gsAppId,
|
||||
JoinHostUserId: req.TargetUid,
|
||||
},
|
||||
g.OnUserOffline(player.PlayerID, &ChangeGsInfo{
|
||||
IsChangeGs: true,
|
||||
JoinHostUserId: req.TargetUid,
|
||||
})
|
||||
return
|
||||
}
|
||||
@@ -98,13 +78,7 @@ func (g *GameManager) JoinPlayerSceneReq(player *model.Player, payloadMsg pb.Mes
|
||||
|
||||
func (g *GameManager) JoinOtherWorld(player *model.Player, hostPlayer *model.Player) {
|
||||
hostWorld := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
_, exist := hostWorld.waitEnterPlayerMap[player.PlayerID]
|
||||
if !exist {
|
||||
return
|
||||
}
|
||||
|
||||
if hostPlayer.SceneLoadState == model.SceneEnterDone {
|
||||
delete(hostWorld.waitEnterPlayerMap, player.PlayerID)
|
||||
player.Pos.X = hostPlayer.Pos.X
|
||||
player.Pos.Y = hostPlayer.Pos.Y
|
||||
player.Pos.Z = hostPlayer.Pos.Z
|
||||
@@ -112,11 +86,13 @@ func (g *GameManager) JoinOtherWorld(player *model.Player, hostPlayer *model.Pla
|
||||
player.Rot.Y = hostPlayer.Rot.Y
|
||||
player.Rot.Z = hostPlayer.Rot.Z
|
||||
player.SceneId = hostPlayer.SceneId
|
||||
|
||||
g.UserWorldAddPlayer(hostWorld, player)
|
||||
|
||||
player.SceneLoadState = model.SceneNone
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_OTHER))
|
||||
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyLogin(player, proto.EnterType_ENTER_TYPE_OTHER)
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, player.PlayerID, player.ClientSeq, playerEnterSceneNotify)
|
||||
} else {
|
||||
hostWorld.waitEnterPlayerMap[player.PlayerID] = time.Now().UnixMilli()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -173,6 +149,10 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes
|
||||
}
|
||||
targetUid := req.TargetUid
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
ok := g.UserLeaveWorld(targetPlayer)
|
||||
if !ok {
|
||||
g.CommonRetError(cmd.SceneKickPlayerRsp, player, &proto.SceneKickPlayerRsp{}, proto.Retcode_RET_MP_TARGET_PLAYER_IN_TRANSFER)
|
||||
@@ -193,41 +173,112 @@ func (g *GameManager) SceneKickPlayerReq(player *model.Player, payloadMsg pb.Mes
|
||||
g.SendMsg(cmd.SceneKickPlayerRsp, player.PlayerID, player.ClientSeq, sceneKickPlayerRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) UserApplyEnterWorld(player *model.Player, targetUid uint32) bool {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
return false
|
||||
func (g *GameManager) UserApplyEnterWorld(player *model.Player, targetUid uint32) {
|
||||
applyFailNotify := func() {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: targetUid,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
if world.multiplayer {
|
||||
return false
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", targetUid)
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "PlayerApplyEnterMpReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
HostUserId: targetUid,
|
||||
ApplyUserId: player.PlayerID,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
applyTime, exist := targetPlayer.CoopApplyMap[player.PlayerID]
|
||||
if exist && time.Now().UnixNano() < applyTime+int64(10*time.Second) {
|
||||
return false
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
targetPlayer.CoopApplyMap[player.PlayerID] = time.Now().UnixNano()
|
||||
targetWorld := WORLD_MANAGER.GetWorldByID(targetPlayer.WorldId)
|
||||
if targetWorld.multiplayer && targetWorld.owner.PlayerID != targetPlayer.PlayerID {
|
||||
return false
|
||||
// 向同一世界内的非房主玩家申请时直接拒绝
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpNotify := new(proto.PlayerApplyEnterMpNotify)
|
||||
playerApplyEnterMpNotify.SrcPlayerInfo = g.PacketOnlinePlayerInfo(player)
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, playerApplyEnterMpNotify)
|
||||
return true
|
||||
}
|
||||
|
||||
func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint32, agree bool) {
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherUid)
|
||||
if otherPlayer == nil {
|
||||
return
|
||||
}
|
||||
applyTime, exist := hostPlayer.CoopApplyMap[otherUid]
|
||||
if !exist || time.Now().UnixNano() > applyTime+int64(10*time.Second) {
|
||||
return
|
||||
}
|
||||
delete(hostPlayer.CoopApplyMap, otherUid)
|
||||
if !agree {
|
||||
return
|
||||
}
|
||||
g.HostEnterMpWorld(hostPlayer, otherUid)
|
||||
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherUid)
|
||||
if otherPlayer == nil {
|
||||
if !USER_MANAGER.GetRemoteUserOnlineState(otherUid) {
|
||||
// 全服不存在该在线玩家
|
||||
logger.Error("target user not online in any game server, uid: %v", otherUid)
|
||||
return
|
||||
}
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(otherUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "PlayerApplyEnterMpResultReq",
|
||||
UserId: hostPlayer.PlayerID,
|
||||
},
|
||||
HostUserId: hostPlayer.PlayerID,
|
||||
ApplyUserId: otherUid,
|
||||
Agreed: agree,
|
||||
HostNickname: hostPlayer.NickName,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
|
||||
otherPlayerWorld := WORLD_MANAGER.GetWorldByID(otherPlayer.WorldId)
|
||||
if otherPlayerWorld.multiplayer {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
@@ -247,15 +298,10 @@ func (g *GameManager) UserDealEnterWorld(hostPlayer *model.Player, otherUid uint
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_JUDGE,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
|
||||
if agree {
|
||||
g.HostEnterMpWorld(hostPlayer, otherPlayer.PlayerID)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherPlayerId uint32) {
|
||||
func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherUid uint32) {
|
||||
world := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
world.waitEnterPlayerMap[otherPlayerId] = time.Now().UnixMilli()
|
||||
if world.multiplayer {
|
||||
return
|
||||
}
|
||||
@@ -286,7 +332,7 @@ func (g *GameManager) HostEnterMpWorld(hostPlayer *model.Player, otherPlayerId u
|
||||
|
||||
guestBeginEnterSceneNotify := &proto.GuestBeginEnterSceneNotify{
|
||||
SceneId: hostPlayer.SceneId,
|
||||
Uid: otherPlayerId,
|
||||
Uid: otherUid,
|
||||
}
|
||||
g.SendMsg(cmd.GuestBeginEnterSceneNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, guestBeginEnterSceneNotify)
|
||||
|
||||
@@ -357,7 +403,7 @@ func (g *GameManager) UserWorldRemovePlayer(world *World, player *model.Player)
|
||||
if world.owner.PlayerID == player.PlayerID {
|
||||
// 房主离开销毁世界
|
||||
WORLD_MANAGER.DestroyWorld(world.id)
|
||||
GAME_MANAGER.messageQueue.SendToFight(world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.DelFightRoutine,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -462,3 +508,112 @@ func (g *GameManager) UpdateWorldPlayerInfo(hostWorld *World, excludePlayer *mod
|
||||
g.SendMsg(cmd.SyncScenePlayTeamEntityNotify, worldPlayer.PlayerID, worldPlayer.ClientSeq, syncScenePlayTeamEntityNotify)
|
||||
}
|
||||
}
|
||||
|
||||
// 跨服玩家多人世界相关请求
|
||||
|
||||
func (g *GameManager) ServerUserMpReq(userMpInfo *mq.UserMpInfo, gsAppId string) {
|
||||
switch userMpInfo.OriginInfo.CmdName {
|
||||
case "PlayerApplyEnterMpReq":
|
||||
applyFailNotify := func() {
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: userMpInfo.OriginInfo,
|
||||
HostUserId: userMpInfo.HostUserId,
|
||||
ApplyOk: false,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
hostPlayer := USER_MANAGER.GetOnlineUser(userMpInfo.HostUserId)
|
||||
if hostPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.HostUserId)
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
applyTime, exist := hostPlayer.CoopApplyMap[userMpInfo.ApplyUserId]
|
||||
if exist && time.Now().UnixNano() < applyTime+int64(10*time.Second) {
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
hostPlayer.CoopApplyMap[userMpInfo.ApplyUserId] = time.Now().UnixNano()
|
||||
hostWorld := WORLD_MANAGER.GetWorldByID(hostPlayer.WorldId)
|
||||
if hostWorld.multiplayer && hostWorld.owner.PlayerID != hostPlayer.PlayerID {
|
||||
// 向同一世界内的非房主玩家申请时直接拒绝
|
||||
applyFailNotify()
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpNotify := new(proto.PlayerApplyEnterMpNotify)
|
||||
playerApplyEnterMpNotify.SrcPlayerInfo = &proto.OnlinePlayerInfo{
|
||||
Uid: userMpInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
Nickname: userMpInfo.ApplyPlayerOnlineInfo.Nickname,
|
||||
PlayerLevel: userMpInfo.ApplyPlayerOnlineInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userMpInfo.ApplyPlayerOnlineInfo.MpSettingType),
|
||||
NameCardId: userMpInfo.ApplyPlayerOnlineInfo.NameCardId,
|
||||
Signature: userMpInfo.ApplyPlayerOnlineInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userMpInfo.ApplyPlayerOnlineInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userMpInfo.ApplyPlayerOnlineInfo.WorldPlayerNum,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpNotify, hostPlayer.PlayerID, hostPlayer.ClientSeq, playerApplyEnterMpNotify)
|
||||
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserMpRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserMpInfo: &mq.UserMpInfo{
|
||||
OriginInfo: userMpInfo.OriginInfo,
|
||||
HostUserId: userMpInfo.HostUserId,
|
||||
ApplyOk: true,
|
||||
},
|
||||
},
|
||||
})
|
||||
case "PlayerApplyEnterMpResultReq":
|
||||
applyPlayer := USER_MANAGER.GetOnlineUser(userMpInfo.ApplyUserId)
|
||||
if applyPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.ApplyUserId)
|
||||
return
|
||||
}
|
||||
applyPlayerWorld := WORLD_MANAGER.GetWorldByID(applyPlayer.WorldId)
|
||||
if applyPlayerWorld.multiplayer {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: userMpInfo.HostNickname,
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, applyPlayer.PlayerID, applyPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
return
|
||||
}
|
||||
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: userMpInfo.HostNickname,
|
||||
IsAgreed: userMpInfo.Agreed,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_JUDGE,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, applyPlayer.PlayerID, applyPlayer.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerUserMpRsp(userMpInfo *mq.UserMpInfo) {
|
||||
switch userMpInfo.OriginInfo.CmdName {
|
||||
case "PlayerApplyEnterMpReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userMpInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userMpInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
if !userMpInfo.ApplyOk {
|
||||
playerApplyEnterMpResultNotify := &proto.PlayerApplyEnterMpResultNotify{
|
||||
TargetUid: userMpInfo.HostUserId,
|
||||
TargetNickname: "",
|
||||
IsAgreed: false,
|
||||
Reason: proto.PlayerApplyEnterMpResultNotify_REASON_PLAYER_CANNOT_ENTER_MP,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerApplyEnterMpResultNotify, player.PlayerID, player.ClientSeq, playerApplyEnterMpResultNotify)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -263,21 +263,14 @@ func (g *GameManager) EnterSceneDoneReq(player *model.Player, payloadMsg pb.Mess
|
||||
world.PlayerEnter(player)
|
||||
|
||||
for otherPlayerId := range world.waitEnterPlayerMap {
|
||||
// 房主第一次进入多人世界场景完成 开始通知等待列表中的玩家进入场景
|
||||
delete(world.waitEnterPlayerMap, otherPlayerId)
|
||||
otherPlayer := USER_MANAGER.GetOnlineUser(otherPlayerId)
|
||||
otherPlayer.Pos.X = player.Pos.X
|
||||
otherPlayer.Pos.Y = player.Pos.Y
|
||||
otherPlayer.Pos.Z = player.Pos.Z
|
||||
otherPlayer.Rot.X = player.Rot.X
|
||||
otherPlayer.Rot.Y = player.Rot.Y
|
||||
otherPlayer.Rot.Z = player.Rot.Z
|
||||
otherPlayer.SceneId = player.SceneId
|
||||
|
||||
g.UserWorldAddPlayer(world, otherPlayer)
|
||||
|
||||
otherPlayer.SceneLoadState = model.SceneNone
|
||||
playerEnterSceneNotify := g.PacketPlayerEnterSceneNotifyLogin(otherPlayer, proto.EnterType_ENTER_TYPE_OTHER)
|
||||
g.SendMsg(cmd.PlayerEnterSceneNotify, otherPlayer.PlayerID, otherPlayer.ClientSeq, playerEnterSceneNotify)
|
||||
if otherPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", otherPlayerId)
|
||||
continue
|
||||
}
|
||||
g.JoinOtherWorld(otherPlayer, player)
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -21,12 +21,28 @@ func (g *GameManager) GetPlayerSocialDetailReq(player *model.Player, payloadMsg
|
||||
req := payloadMsg.(*proto.GetPlayerSocialDetailReq)
|
||||
targetUid := req.Uid
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
targetPlayer, _, remote := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
g.CommonRetError(cmd.GetPlayerSocialDetailRsp, player, &proto.GetPlayerSocialDetailRsp{}, proto.Retcode_RET_PLAYER_NOT_EXIST)
|
||||
return
|
||||
}
|
||||
if remote {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserBaseInfoReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "GetPlayerSocialDetailReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
UserId: targetUid,
|
||||
},
|
||||
},
|
||||
})
|
||||
return
|
||||
}
|
||||
_, exist := player.FriendList[targetPlayer.PlayerID]
|
||||
socialDetail := &proto.SocialDetail{
|
||||
Uid: targetPlayer.PlayerID,
|
||||
@@ -160,19 +176,18 @@ func (g *GameManager) GetPlayerFriendListReq(player *model.Player, payloadMsg pb
|
||||
// 用于实现好友列表内的系统且不更改原先的内容
|
||||
tempFriendList := COMMAND_MANAGER.GetFriendList(player.FriendList)
|
||||
for uid := range tempFriendList {
|
||||
// TODO 同步阻塞待优化
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := USER_MANAGER.GetUserOnlineState(uid)
|
||||
|
||||
friendPlayer, online, _ := USER_MANAGER.LoadGlobalPlayer(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
var onlineState proto.FriendOnlineState = 0
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_DISCONNECT
|
||||
}
|
||||
friendPlayer := USER_MANAGER.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
@@ -200,19 +215,17 @@ func (g *GameManager) GetPlayerAskFriendListReq(player *model.Player, payloadMsg
|
||||
AskFriendList: make([]*proto.FriendBrief, 0),
|
||||
}
|
||||
for uid := range player.FriendApplyList {
|
||||
// TODO 同步阻塞待优化
|
||||
friendPlayer, online, _ := USER_MANAGER.LoadGlobalPlayer(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
var onlineState proto.FriendOnlineState
|
||||
online := USER_MANAGER.GetUserOnlineState(uid)
|
||||
if online {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE
|
||||
} else {
|
||||
onlineState = proto.FriendOnlineState_FRIEND_ONLINE_STATE_DISCONNECT
|
||||
}
|
||||
friendPlayer := USER_MANAGER.LoadTempOfflineUserSync(uid)
|
||||
if friendPlayer == nil {
|
||||
logger.Error("target player is nil, uid: %v", player.PlayerID)
|
||||
continue
|
||||
}
|
||||
friendBrief := &proto.FriendBrief{
|
||||
Uid: friendPlayer.PlayerID,
|
||||
Nickname: friendPlayer.NickName,
|
||||
@@ -238,13 +251,58 @@ func (g *GameManager) AskAddFriendReq(player *model.Player, payloadMsg pb.Messag
|
||||
req := payloadMsg.(*proto.AskAddFriendReq)
|
||||
targetUid := req.TargetUid
|
||||
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayerOnline := USER_MANAGER.GetUserOnlineState(targetUid)
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
askAddFriendRsp := &proto.AskAddFriendRsp{
|
||||
TargetUid: targetUid,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendRsp, player.PlayerID, player.ClientSeq, askAddFriendRsp)
|
||||
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", player.PlayerID)
|
||||
// 非本地玩家
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 远程在线玩家
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerAddFriendNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
AddFriendInfo: &mq.AddFriendInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "AskAddFriendReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
TargetUserId: targetUid,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
targetPlayer, _, _ := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
_, applyExist := targetPlayer.FriendApplyList[player.PlayerID]
|
||||
_, friendExist := targetPlayer.FriendList[player.PlayerID]
|
||||
if applyExist || friendExist {
|
||||
logger.Error("friend or apply already exist, uid: %v", player.PlayerID)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendApplyList[player.PlayerID] = true
|
||||
USER_MANAGER.SaveTempOfflineUser(targetPlayer)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
_, applyExist := targetPlayer.FriendApplyList[player.PlayerID]
|
||||
_, friendExist := targetPlayer.FriendList[player.PlayerID]
|
||||
if applyExist || friendExist {
|
||||
@@ -253,43 +311,26 @@ func (g *GameManager) AskAddFriendReq(player *model.Player, payloadMsg pb.Messag
|
||||
}
|
||||
targetPlayer.FriendApplyList[player.PlayerID] = true
|
||||
|
||||
if targetPlayerOnline {
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: player.PlayerID,
|
||||
}
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
Level: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: player.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: player.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
// 目标玩家在线则通知
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: player.PlayerID,
|
||||
}
|
||||
|
||||
askAddFriendRsp := &proto.AskAddFriendRsp{
|
||||
TargetUid: targetUid,
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
Level: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Signature: player.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: player.OfflineTime,
|
||||
NameCardId: player.NameCard,
|
||||
Param: (uint32(time.Now().Unix()) - player.OfflineTime) / 3600 / 24,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendRsp, player.PlayerID, player.ClientSeq, askAddFriendRsp)
|
||||
}
|
||||
|
||||
func (g *GameManager) AddFriend(player *model.Player, targetUid uint32) {
|
||||
player.FriendList[targetUid] = true
|
||||
// TODO 同步阻塞待优化
|
||||
targetPlayer := USER_MANAGER.LoadTempOfflineUserSync(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("agree friend apply target player is nil, uid: %v", player.PlayerID)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
}
|
||||
|
||||
func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -298,8 +339,12 @@ func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Messa
|
||||
targetUid := req.TargetUid
|
||||
result := req.DealAddFriendResult
|
||||
|
||||
agree := false
|
||||
if result == proto.DealAddFriendResultType_DEAL_ADD_FRIEND_RESULT_TYPE_ACCEPT {
|
||||
g.AddFriend(player, targetUid)
|
||||
agree = true
|
||||
}
|
||||
if agree {
|
||||
player.FriendList[targetUid] = true
|
||||
}
|
||||
delete(player.FriendApplyList, targetUid)
|
||||
|
||||
@@ -308,6 +353,44 @@ func (g *GameManager) DealAddFriendReq(player *model.Player, payloadMsg pb.Messa
|
||||
DealAddFriendResult: result,
|
||||
}
|
||||
g.SendMsg(cmd.DealAddFriendRsp, player.PlayerID, player.ClientSeq, dealAddFriendRsp)
|
||||
|
||||
if agree {
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(targetUid)
|
||||
if targetPlayer == nil {
|
||||
// 非本地玩家
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid) {
|
||||
// 远程在线玩家
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerAddFriendNotify,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
AddFriendInfo: &mq.AddFriendInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
CmdName: "DealAddFriendReq",
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
TargetUserId: targetUid,
|
||||
ApplyPlayerOnlineInfo: &mq.UserBaseInfo{
|
||||
UserId: player.PlayerID,
|
||||
},
|
||||
},
|
||||
},
|
||||
})
|
||||
} else {
|
||||
// 全服离线玩家
|
||||
targetPlayer, _, _ := USER_MANAGER.LoadGlobalPlayer(targetUid)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("apply add friend target player is nil, uid: %v", targetUid)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
USER_MANAGER.SaveTempOfflineUser(targetPlayer)
|
||||
}
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[player.PlayerID] = true
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb.Message) {
|
||||
@@ -315,6 +398,7 @@ func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb
|
||||
|
||||
count := 0
|
||||
onlinePlayerList := make([]*model.Player, 0)
|
||||
// 优先获取本地的在线玩家
|
||||
for _, onlinePlayer := range USER_MANAGER.GetAllOnlineUserList() {
|
||||
if onlinePlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
@@ -325,6 +409,19 @@ func (g *GameManager) GetOnlinePlayerListReq(player *model.Player, payloadMsg pb
|
||||
break
|
||||
}
|
||||
}
|
||||
if count < 50 {
|
||||
// 本地不够时获取远程的在线玩家
|
||||
for _, onlinePlayer := range USER_MANAGER.GetRemoteOnlineUserList(50 - count) {
|
||||
if onlinePlayer.PlayerID == player.PlayerID {
|
||||
continue
|
||||
}
|
||||
onlinePlayerList = append(onlinePlayerList, onlinePlayer)
|
||||
count++
|
||||
if count >= 50 {
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
getOnlinePlayerListRsp := &proto.GetOnlinePlayerListRsp{
|
||||
PlayerInfoList: make([]*proto.OnlinePlayerInfo, 0),
|
||||
@@ -344,11 +441,6 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
return
|
||||
}
|
||||
|
||||
// TODO 删除我
|
||||
g.JoinPlayerSceneReq(player, &proto.JoinPlayerSceneReq{
|
||||
TargetUid: targetUid.TargetUid,
|
||||
})
|
||||
|
||||
if USER_MANAGER.GetUserOnlineState(targetUid.TargetUid) {
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: targetUid.TargetUid,
|
||||
@@ -358,9 +450,9 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
}
|
||||
if USER_MANAGER.GetRemoteUserOnlineState(targetUid.TargetUid) {
|
||||
gsAppId := USER_MANAGER.GetRemoteUserGsAppId(targetUid.TargetUid)
|
||||
g.messageQueue.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerGetUserBaseInfoReq,
|
||||
EventId: mq.ServerUserBaseInfoReq,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: &mq.OriginInfo{
|
||||
@@ -378,6 +470,11 @@ func (g *GameManager) GetOnlinePlayerInfoReq(player *model.Player, payloadMsg pb
|
||||
|
||||
func (g *GameManager) PacketOnlinePlayerInfo(player *model.Player) *proto.OnlinePlayerInfo {
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
worldPlayerNum := uint32(1)
|
||||
// TODO 远程玩家的世界内人数
|
||||
if world != nil {
|
||||
worldPlayerNum = uint32(world.GetWorldPlayerNum())
|
||||
}
|
||||
onlinePlayerInfo := &proto.OnlinePlayerInfo{
|
||||
Uid: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
@@ -386,7 +483,138 @@ func (g *GameManager) PacketOnlinePlayerInfo(player *model.Player) *proto.Online
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: player.HeadImage},
|
||||
CurPlayerNumInWorld: uint32(world.GetWorldPlayerNum()),
|
||||
CurPlayerNumInWorld: worldPlayerNum,
|
||||
}
|
||||
return onlinePlayerInfo
|
||||
}
|
||||
|
||||
// 跨服玩家基础数据请求
|
||||
|
||||
func (g *GameManager) ServerUserBaseInfoReq(userBaseInfo *mq.UserBaseInfo, gsAppId string) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
fallthrough
|
||||
case "GetPlayerSocialDetailReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.UserId)
|
||||
return
|
||||
}
|
||||
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
||||
MESSAGE_QUEUE.SendToGs(gsAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeServer,
|
||||
EventId: mq.ServerUserBaseInfoRsp,
|
||||
ServerMsg: &mq.ServerMsg{
|
||||
UserBaseInfo: &mq.UserBaseInfo{
|
||||
OriginInfo: userBaseInfo.OriginInfo,
|
||||
UserId: player.PlayerID,
|
||||
Nickname: player.NickName,
|
||||
PlayerLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_LEVEL],
|
||||
MpSettingType: uint8(player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_MP_SETTING_TYPE]),
|
||||
NameCardId: player.NameCard,
|
||||
Signature: player.Signature,
|
||||
HeadImageId: player.HeadImage,
|
||||
WorldPlayerNum: uint32(world.GetWorldPlayerNum()),
|
||||
WorldLevel: player.PropertiesMap[constant.PlayerPropertyConst.PROP_PLAYER_WORLD_LEVEL],
|
||||
Birthday: player.Birthday,
|
||||
},
|
||||
},
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func (g *GameManager) ServerUserBaseInfoRsp(userBaseInfo *mq.UserBaseInfo) {
|
||||
switch userBaseInfo.OriginInfo.CmdName {
|
||||
case "GetOnlinePlayerInfoReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
g.SendMsg(cmd.GetOnlinePlayerInfoRsp, player.PlayerID, player.ClientSeq, &proto.GetOnlinePlayerInfoRsp{
|
||||
TargetUid: userBaseInfo.UserId,
|
||||
TargetPlayerInfo: &proto.OnlinePlayerInfo{
|
||||
Uid: userBaseInfo.UserId,
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
PlayerLevel: userBaseInfo.PlayerLevel,
|
||||
MpSettingType: proto.MpSettingType(userBaseInfo.MpSettingType),
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
Signature: userBaseInfo.Signature,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
CurPlayerNumInWorld: userBaseInfo.WorldPlayerNum,
|
||||
},
|
||||
})
|
||||
case "GetPlayerSocialDetailReq":
|
||||
player := USER_MANAGER.GetOnlineUser(userBaseInfo.OriginInfo.UserId)
|
||||
if player == nil {
|
||||
logger.Error("player is nil, uid: %v", userBaseInfo.OriginInfo.UserId)
|
||||
return
|
||||
}
|
||||
_, exist := player.FriendList[userBaseInfo.UserId]
|
||||
socialDetail := &proto.SocialDetail{
|
||||
Uid: userBaseInfo.UserId,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: userBaseInfo.HeadImageId},
|
||||
Nickname: userBaseInfo.Nickname,
|
||||
Signature: userBaseInfo.Signature,
|
||||
Level: userBaseInfo.PlayerLevel,
|
||||
Birthday: &proto.Birthday{Month: uint32(userBaseInfo.Birthday[0]), Day: uint32(userBaseInfo.Birthday[1])},
|
||||
WorldLevel: userBaseInfo.WorldLevel,
|
||||
NameCardId: userBaseInfo.NameCardId,
|
||||
IsShowAvatar: false,
|
||||
FinishAchievementNum: 0,
|
||||
IsFriend: exist,
|
||||
}
|
||||
getPlayerSocialDetailRsp := &proto.GetPlayerSocialDetailRsp{
|
||||
DetailData: socialDetail,
|
||||
}
|
||||
g.SendMsg(cmd.GetPlayerSocialDetailRsp, player.PlayerID, player.ClientSeq, getPlayerSocialDetailRsp)
|
||||
}
|
||||
}
|
||||
|
||||
// 跨服添加好友通知
|
||||
|
||||
func (g *GameManager) ServerAddFriendNotify(addFriendInfo *mq.AddFriendInfo) {
|
||||
switch addFriendInfo.OriginInfo.CmdName {
|
||||
case "AskAddFriendReq":
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(addFriendInfo.TargetUserId)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", addFriendInfo.TargetUserId)
|
||||
return
|
||||
}
|
||||
_, applyExist := targetPlayer.FriendApplyList[addFriendInfo.ApplyPlayerOnlineInfo.UserId]
|
||||
_, friendExist := targetPlayer.FriendList[addFriendInfo.ApplyPlayerOnlineInfo.UserId]
|
||||
if applyExist || friendExist {
|
||||
logger.Error("friend or apply already exist, uid: %v", addFriendInfo.ApplyPlayerOnlineInfo.UserId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendApplyList[addFriendInfo.ApplyPlayerOnlineInfo.UserId] = true
|
||||
|
||||
// 目标玩家在线则通知
|
||||
askAddFriendNotify := &proto.AskAddFriendNotify{
|
||||
TargetUid: addFriendInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
}
|
||||
askAddFriendNotify.TargetFriendBrief = &proto.FriendBrief{
|
||||
Uid: addFriendInfo.ApplyPlayerOnlineInfo.UserId,
|
||||
Nickname: addFriendInfo.ApplyPlayerOnlineInfo.Nickname,
|
||||
Level: addFriendInfo.ApplyPlayerOnlineInfo.PlayerLevel,
|
||||
ProfilePicture: &proto.ProfilePicture{AvatarId: addFriendInfo.ApplyPlayerOnlineInfo.HeadImageId},
|
||||
WorldLevel: addFriendInfo.ApplyPlayerOnlineInfo.WorldLevel,
|
||||
Signature: addFriendInfo.ApplyPlayerOnlineInfo.Signature,
|
||||
OnlineState: proto.FriendOnlineState_FRIEND_ONLINE_STATE_ONLINE,
|
||||
IsMpModeAvailable: true,
|
||||
LastActiveTime: 0,
|
||||
NameCardId: addFriendInfo.ApplyPlayerOnlineInfo.NameCardId,
|
||||
Param: 0,
|
||||
IsGameSource: true,
|
||||
PlatformType: proto.PlatformType_PLATFORM_TYPE_PC,
|
||||
}
|
||||
g.SendMsg(cmd.AskAddFriendNotify, targetPlayer.PlayerID, targetPlayer.ClientSeq, askAddFriendNotify)
|
||||
case "DealAddFriendReq":
|
||||
targetPlayer := USER_MANAGER.GetOnlineUser(addFriendInfo.TargetUserId)
|
||||
if targetPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", addFriendInfo.TargetUserId)
|
||||
return
|
||||
}
|
||||
targetPlayer.FriendList[addFriendInfo.ApplyPlayerOnlineInfo.UserId] = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -206,6 +206,10 @@ func (g *GameManager) PacketSceneTeamUpdateNotify(world *World) *proto.SceneTeam
|
||||
empty := new(proto.AbilitySyncStateInfo)
|
||||
for _, worldAvatar := range world.GetWorldAvatarList() {
|
||||
worldPlayer := USER_MANAGER.GetOnlineUser(worldAvatar.uid)
|
||||
if worldPlayer == nil {
|
||||
logger.Error("player is nil, uid: %v", worldAvatar.uid)
|
||||
continue
|
||||
}
|
||||
worldPlayerScene := world.GetSceneById(worldPlayer.SceneId)
|
||||
worldPlayerAvatar := worldPlayer.AvatarMap[worldAvatar.avatarId]
|
||||
equipIdList := make([]uint32, 0)
|
||||
|
||||
@@ -112,7 +112,7 @@ type World struct {
|
||||
chatMsgList []*proto.ChatInfo // 世界聊天消息列表
|
||||
aoiManager *aoi.AoiManager // 当前世界地图的aoi管理器
|
||||
playerFirstEnterMap map[uint32]int64 // 玩家第一次进入世界的时间 key:uid value:进入时间
|
||||
waitEnterPlayerMap map[uint32]int64 // 等待进入世界的列表 key:uid value:开始时间
|
||||
waitEnterPlayerMap map[uint32]int64 // 进入世界的玩家等待列表 key:uid value:开始时间
|
||||
multiplayerTeam *MultiplayerTeam
|
||||
peerList []*model.Player // 玩家编号列表
|
||||
}
|
||||
@@ -701,7 +701,7 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
|
||||
if avatarId == s.world.GetPlayerActiveAvatarId(player) {
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
}
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineAddEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -751,7 +751,7 @@ func (s *Scene) CreateEntityMonster(pos *model.Vector, level uint8, fightProp ma
|
||||
}
|
||||
s.entityMap[entity.id] = entity
|
||||
s.world.aoiManager.AddEntityIdToGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineAddEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
@@ -901,7 +901,7 @@ func (s *Scene) DestroyEntity(entityId uint32) {
|
||||
}
|
||||
s.world.aoiManager.RemoveEntityIdFromGridByPos(entity.id, float32(entity.pos.X), float32(entity.pos.Y), float32(entity.pos.Z))
|
||||
delete(s.entityMap, entityId)
|
||||
GAME_MANAGER.messageQueue.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MESSAGE_QUEUE.SendToFight(s.world.owner.FightAppId, &mq.NetMsg{
|
||||
MsgType: mq.MsgTypeFight,
|
||||
EventId: mq.FightRoutineDelEntity,
|
||||
FightMsg: &mq.FightMsg{
|
||||
|
||||
Reference in New Issue
Block a user