mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-14 07:02:26 +08:00
拆分了聊天数据,减小玩家数据结构大小
This commit is contained in:
@@ -12,6 +12,10 @@ import (
|
||||
pb "google.golang.org/protobuf/proto"
|
||||
)
|
||||
|
||||
const (
|
||||
MaxMsgListLen = 1000 // 与某人的最大聊天记录条数
|
||||
)
|
||||
|
||||
func (g *GameManager) PullRecentChatReq(player *model.Player, payloadMsg pb.Message) {
|
||||
logger.Debug("user pull recent chat, uid: %v", player.PlayerID)
|
||||
req := payloadMsg.(*proto.PullRecentChatReq)
|
||||
@@ -94,7 +98,7 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
||||
chatInfo.Content = &proto.ChatInfo_Text{
|
||||
Text: content.(string),
|
||||
}
|
||||
case int, int32, uint32:
|
||||
case uint32:
|
||||
// 图标消息
|
||||
chatInfo.Content = &proto.ChatInfo_Icon{
|
||||
Icon: content.(uint32),
|
||||
@@ -106,6 +110,9 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
if len(msgList) > MaxMsgListLen {
|
||||
msgList = msgList[1:]
|
||||
}
|
||||
msgList = append(msgList, chatMsg)
|
||||
player.ChatMsgMap[targetUid] = msgList
|
||||
|
||||
@@ -136,7 +143,10 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
||||
})
|
||||
} else {
|
||||
// 目标玩家全服离线
|
||||
// TODO 接入redis直接同步写入数据
|
||||
chatMsgMap := map[uint32][]*model.ChatMsg{
|
||||
player.PlayerID: {chatMsg},
|
||||
}
|
||||
go USER_MANAGER.AppendOfflineUserChatMsgToDbSync(targetUid, chatMsgMap)
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -145,6 +155,9 @@ func (g *GameManager) SendPrivateChat(player *model.Player, targetUid uint32, co
|
||||
if !exist {
|
||||
msgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
if len(msgList) > MaxMsgListLen {
|
||||
msgList = msgList[1:]
|
||||
}
|
||||
msgList = append(msgList, chatMsg)
|
||||
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
||||
|
||||
@@ -167,7 +180,8 @@ func (g *GameManager) PrivateChatReq(player *model.Player, payloadMsg pb.Message
|
||||
switch content.(type) {
|
||||
case *proto.PrivateChatReq_Text:
|
||||
text := content.(*proto.PrivateChatReq_Text).Text
|
||||
if len(text) == 0 {
|
||||
if len(text) == 0 || len(text) > 80 {
|
||||
g.SendError(cmd.PrivateChatRsp, player, &proto.PrivateChatRsp{}, proto.Retcode_RET_PRIVATE_CHAT_CONTENT_TOO_LONG)
|
||||
return
|
||||
}
|
||||
// 发送私聊文本消息
|
||||
|
||||
@@ -149,13 +149,13 @@ func (g *GameManager) LoginNotify(userId uint32, player *model.Player, clientSeq
|
||||
g.GCGLogin(player) // 发送GCG登录相关的通知包
|
||||
playerLoginRsp := &proto.PlayerLoginRsp{
|
||||
IsUseAbilityHash: true,
|
||||
AbilityHashCode: -228935105,
|
||||
AbilityHashCode: 0,
|
||||
GameBiz: "hk4e_cn",
|
||||
IsScOpen: false,
|
||||
RegisterCps: "taptap",
|
||||
CountryCode: "CN",
|
||||
Birthday: "2000-01-01",
|
||||
TotalTickTime: 1185941.871788,
|
||||
TotalTickTime: 0.0,
|
||||
}
|
||||
g.SendMsg(cmd.PlayerLoginRsp, userId, clientSeq, playerLoginRsp)
|
||||
}
|
||||
@@ -165,7 +165,7 @@ func (g *GameManager) PacketPlayerDataNotify(player *model.Player) *proto.Player
|
||||
NickName: player.NickName,
|
||||
ServerTime: uint64(time.Now().UnixMilli()),
|
||||
IsFirstLoginToday: true,
|
||||
RegionId: player.RegionId,
|
||||
RegionId: 1,
|
||||
PropMap: make(map[uint32]*proto.PropValue),
|
||||
}
|
||||
for k, v := range player.PropertiesMap {
|
||||
@@ -344,7 +344,6 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata
|
||||
player.FriendList = make(map[uint32]bool)
|
||||
player.FriendApplyList = make(map[uint32]bool)
|
||||
|
||||
player.RegionId = 1
|
||||
player.SceneId = 3
|
||||
|
||||
player.PropertiesMap = make(map[uint16]uint32)
|
||||
@@ -397,7 +396,6 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata
|
||||
player.AvatarMap = make(map[uint32]*model.Avatar)
|
||||
player.GameObjectGuidMap = make(map[uint64]model.GameObject)
|
||||
player.DropInfo = model.NewDropInfo()
|
||||
player.ChatMsgMap = make(map[uint32][]*model.ChatMsg)
|
||||
player.GCGInfo = model.NewGCGInfo()
|
||||
|
||||
// 添加选定的主角
|
||||
@@ -418,5 +416,7 @@ func (g *GameManager) CreatePlayer(userId uint32, nickName string, mainCharAvata
|
||||
player.TeamConfig = model.NewTeamInfo()
|
||||
player.TeamConfig.GetActiveTeam().SetAvatarIdList([]uint32{mainCharAvatarId})
|
||||
|
||||
player.ChatMsgMap = make(map[uint32][]*model.ChatMsg)
|
||||
|
||||
return player
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"hk4e/gs/dao"
|
||||
"hk4e/gs/model"
|
||||
"hk4e/pkg/logger"
|
||||
"hk4e/pkg/object"
|
||||
"hk4e/protocol/proto"
|
||||
|
||||
"github.com/vmihailenco/msgpack/v5"
|
||||
@@ -141,6 +142,8 @@ func (u *UserManager) OnlineUser(userId uint32, clientSeq uint32, gateAppId stri
|
||||
if player != nil {
|
||||
u.SaveUserToRedisSync(player)
|
||||
u.ChangeUserDbState(player, model.DbNormal)
|
||||
playerDb := u.LoadUserChatMsgFromDbSync(userId)
|
||||
player.ChatMsgMap = playerDb.ChatMsgMap
|
||||
} else {
|
||||
logger.Error("can not find user from db, uid: %v", userId)
|
||||
}
|
||||
@@ -170,11 +173,20 @@ type PlayerOfflineInfo struct {
|
||||
|
||||
// OfflineUser 玩家离线
|
||||
func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsInfo) {
|
||||
startTime := time.Now().UnixNano()
|
||||
playerData, err := msgpack.Marshal(player)
|
||||
if err != nil {
|
||||
logger.Error("marshal player data error: %v", err)
|
||||
return
|
||||
}
|
||||
chatMsgMapData, err := object.DeepMarshal(&player.ChatMsgMap)
|
||||
if err != nil {
|
||||
logger.Error("marshal chat msg map error: %v", err)
|
||||
return
|
||||
}
|
||||
endTime := time.Now().UnixNano()
|
||||
costTime := endTime - startTime
|
||||
logger.Info("offline copy player data and chat msg cost time: %v ns", costTime)
|
||||
go func() {
|
||||
playerCopy := new(model.Player)
|
||||
err := msgpack.Unmarshal(playerData, playerCopy)
|
||||
@@ -185,6 +197,16 @@ func (u *UserManager) OfflineUser(player *model.Player, changeGsInfo *ChangeGsIn
|
||||
playerCopy.DbState = player.DbState
|
||||
u.SaveUserToDbSync(playerCopy)
|
||||
u.SaveUserToRedisSync(playerCopy)
|
||||
chatMsgMap := make(map[uint32][]*model.ChatMsg)
|
||||
err = object.DeepUnmarshal(&chatMsgMap, chatMsgMapData)
|
||||
if err != nil {
|
||||
logger.Error("unmarshal chat msg map error: %v", err)
|
||||
return
|
||||
}
|
||||
playerDb := new(dao.PlayerDb)
|
||||
playerDb.PlayerID = playerCopy.PlayerID
|
||||
playerDb.ChatMsgMap = chatMsgMap
|
||||
u.SaveUserChatMsgToDbSync(playerDb)
|
||||
LOCAL_EVENT_MANAGER.localEventChan <- &LocalEvent{
|
||||
EventId: UserOfflineSaveToDbFinish,
|
||||
Msg: &PlayerOfflineInfo{
|
||||
@@ -457,6 +479,51 @@ func (u *UserManager) SaveUserListToDbSync(insertPlayerList []*model.Player, upd
|
||||
logger.Info("save user finish, insert user count: %v, update user count: %v", len(insertPlayerList), len(updatePlayerList))
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadUserChatMsgFromDbSync(userId uint32) *dao.PlayerDb {
|
||||
playerDb, err := u.dao.QueryPlayerDbByID(userId)
|
||||
if err != nil {
|
||||
logger.Error("query player db error: %v", err)
|
||||
return nil
|
||||
}
|
||||
return playerDb
|
||||
}
|
||||
|
||||
func (u *UserManager) SaveUserChatMsgToDbSync(playerDb *dao.PlayerDb) {
|
||||
_, err := u.dao.QueryPlayerDbByID(playerDb.PlayerID)
|
||||
if err != nil {
|
||||
err := u.dao.InsertPlayerDb(playerDb)
|
||||
if err != nil {
|
||||
logger.Error("insert player db error: %v", err)
|
||||
return
|
||||
}
|
||||
} else {
|
||||
err := u.dao.UpdatePlayerDb(playerDb)
|
||||
if err != nil {
|
||||
logger.Error("update player db error: %v", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (u *UserManager) AppendOfflineUserChatMsgToDbSync(userId uint32, chatMsgMap map[uint32][]*model.ChatMsg) {
|
||||
playerDb := u.LoadUserChatMsgFromDbSync(userId)
|
||||
if playerDb == nil {
|
||||
return
|
||||
}
|
||||
for uid, msgList := range chatMsgMap {
|
||||
allMsgList, exist := playerDb.ChatMsgMap[uid]
|
||||
if !exist {
|
||||
allMsgList = make([]*model.ChatMsg, 0)
|
||||
}
|
||||
allMsgList = append(allMsgList, msgList...)
|
||||
if len(allMsgList) > MaxMsgListLen {
|
||||
allMsgList = allMsgList[len(allMsgList)-MaxMsgListLen:]
|
||||
}
|
||||
playerDb.ChatMsgMap[uid] = allMsgList
|
||||
}
|
||||
u.SaveUserChatMsgToDbSync(playerDb)
|
||||
}
|
||||
|
||||
func (u *UserManager) LoadUserFromRedisSync(userId uint32) *model.Player {
|
||||
player := u.dao.GetRedisPlayer(userId)
|
||||
return player
|
||||
|
||||
@@ -101,7 +101,6 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
|
||||
GAME_MANAGER.EntityFightPropUpdateNotifyBroadcast(s, entity, uint32(constant.FIGHT_PROP_CUR_HP))
|
||||
}
|
||||
|
||||
// PacketAvatarLifeStateChangeNotify
|
||||
avatarLifeStateChangeNotify := &proto.AvatarLifeStateChangeNotify{
|
||||
LifeState: uint32(lifeState),
|
||||
AttackTag: "",
|
||||
@@ -111,9 +110,7 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
|
||||
SourceEntityId: 0,
|
||||
AvatarGuid: avatar.Guid,
|
||||
}
|
||||
for _, p := range s.playerMap {
|
||||
GAME_MANAGER.SendMsg(cmd.AvatarLifeStateChangeNotify, p.PlayerID, p.ClientSeq, avatarLifeStateChangeNotify)
|
||||
}
|
||||
GAME_MANAGER.SendToWorldA(s.world, cmd.AvatarLifeStateChangeNotify, 0, avatarLifeStateChangeNotify)
|
||||
} else {
|
||||
// 设置存活状态
|
||||
entity.lifeState = lifeState
|
||||
@@ -124,7 +121,6 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
|
||||
GAME_MANAGER.EntityFightPropUpdateNotifyBroadcast(s, entity, uint32(constant.FIGHT_PROP_CUR_HP))
|
||||
}
|
||||
|
||||
// PacketLifeStateChangeNotify
|
||||
lifeStateChangeNotify := &proto.LifeStateChangeNotify{
|
||||
EntityId: entity.id,
|
||||
AttackTag: "",
|
||||
@@ -133,9 +129,7 @@ func (s *Scene) SetEntityLifeState(entity *Entity, lifeState uint16, dieType pro
|
||||
LifeState: uint32(lifeState),
|
||||
SourceEntityId: 0,
|
||||
}
|
||||
for _, p := range s.playerMap {
|
||||
GAME_MANAGER.SendMsg(cmd.LifeStateChangeNotify, p.PlayerID, p.ClientSeq, lifeStateChangeNotify)
|
||||
}
|
||||
GAME_MANAGER.SendToWorldA(s.world, cmd.LifeStateChangeNotify, 0, lifeStateChangeNotify)
|
||||
|
||||
// 删除实体
|
||||
s.DestroyEntity(entity.id)
|
||||
@@ -159,9 +153,8 @@ func (s *Scene) CreateEntityAvatar(player *model.Player, avatarId uint32) uint32
|
||||
moveState: uint16(proto.MotionState_MOTION_NONE),
|
||||
lastMoveSceneTimeMs: 0,
|
||||
lastMoveReliableSeq: 0,
|
||||
// fightProp: player.AvatarMap[avatarId].FightPropMap, // 使用角色结构的数据
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_AVATAR),
|
||||
// level: 0, // 使用角色结构的数据
|
||||
fightProp: player.AvatarMap[avatarId].FightPropMap, // 使用角色结构的数据
|
||||
entityType: uint32(proto.ProtEntityType_PROT_ENTITY_AVATAR),
|
||||
avatarEntity: &AvatarEntity{
|
||||
uid: player.PlayerID,
|
||||
avatarId: avatarId,
|
||||
|
||||
Reference in New Issue
Block a user