mirror of
https://github.com/FlourishingWorld/hk4e.git
synced 2026-02-04 15:52:27 +08:00
351 lines
9.6 KiB
Go
351 lines
9.6 KiB
Go
package game
|
|
|
|
import (
|
|
"time"
|
|
|
|
"hk4e/common/mq"
|
|
"hk4e/gs/model"
|
|
"hk4e/pkg/logger"
|
|
"hk4e/protocol/cmd"
|
|
"hk4e/protocol/proto"
|
|
|
|
pb "google.golang.org/protobuf/proto"
|
|
)
|
|
|
|
const (
|
|
MaxMsgListLen = 100 // 与某人的最大聊天记录条数
|
|
)
|
|
|
|
func (g *Game) PullRecentChatReq(player *model.Player, payloadMsg pb.Message) {
|
|
req := payloadMsg.(*proto.PullRecentChatReq)
|
|
// 经研究发现 原神现网环境 客户端仅拉取最新的5条未读聊天消息 所以人太多的话小姐姐不回你消息是有原因的
|
|
// 因此 阿米你这样做真的合适吗 不过现在代码到了我手上我想怎么写就怎么写 我才不会重蹈覆辙
|
|
_ = req.PullNum
|
|
|
|
retMsgList := make([]*proto.ChatInfo, 0)
|
|
for _, msgList := range player.ChatMsgMap {
|
|
for _, chatMsg := range msgList {
|
|
// 反手就是一个遍历
|
|
if chatMsg.IsRead {
|
|
continue
|
|
}
|
|
retMsgList = append(retMsgList, g.ConvChatMsgToChatInfo(chatMsg))
|
|
}
|
|
}
|
|
|
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
if world == nil {
|
|
logger.Error("get world is nil, worldId: %v, uid: %v", player.WorldId, player.PlayerID)
|
|
return
|
|
}
|
|
if world.GetMultiplayer() {
|
|
chatList := world.GetChatList()
|
|
count := len(chatList)
|
|
if count > 10 {
|
|
count = 10
|
|
}
|
|
for i := len(chatList) - count; i < len(chatList); i++ {
|
|
playerChatNotify := &proto.PlayerChatNotify{
|
|
ChannelId: 0,
|
|
ChatInfo: chatList[i],
|
|
}
|
|
g.SendMsg(cmd.PlayerChatNotify, player.PlayerID, player.ClientSeq, playerChatNotify)
|
|
}
|
|
}
|
|
|
|
pullRecentChatRsp := &proto.PullRecentChatRsp{
|
|
ChatInfo: retMsgList,
|
|
}
|
|
g.SendMsg(cmd.PullRecentChatRsp, player.PlayerID, player.ClientSeq, pullRecentChatRsp)
|
|
}
|
|
|
|
func (g *Game) PullPrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
|
req := payloadMsg.(*proto.PullPrivateChatReq)
|
|
targetUid := req.TargetUid
|
|
pullNum := req.PullNum
|
|
fromSequence := req.FromSequence
|
|
|
|
msgList, exist := player.ChatMsgMap[targetUid]
|
|
if !exist {
|
|
return
|
|
}
|
|
if pullNum+fromSequence > uint32(len(msgList)) {
|
|
pullNum = uint32(len(msgList)) - fromSequence
|
|
}
|
|
recentMsgList := msgList[fromSequence : fromSequence+pullNum]
|
|
retMsgList := make([]*proto.ChatInfo, 0)
|
|
for _, chatMsg := range recentMsgList {
|
|
retMsgList = append(retMsgList, g.ConvChatMsgToChatInfo(chatMsg))
|
|
}
|
|
|
|
pullPrivateChatRsp := &proto.PullPrivateChatRsp{
|
|
ChatInfo: retMsgList,
|
|
}
|
|
g.SendMsg(cmd.PullPrivateChatRsp, player.PlayerID, player.ClientSeq, pullPrivateChatRsp)
|
|
}
|
|
|
|
// SendPrivateChat 发送私聊文本消息给玩家
|
|
func (g *Game) SendPrivateChat(player *model.Player, targetUid uint32, content any) {
|
|
chatMsg := &model.ChatMsg{
|
|
Sequence: 0,
|
|
Time: uint32(time.Now().Unix()),
|
|
ToUid: targetUid,
|
|
Uid: player.PlayerID,
|
|
IsRead: false,
|
|
}
|
|
// 根据传入的值判断消息类型
|
|
switch content.(type) {
|
|
case string:
|
|
// 文本消息
|
|
chatMsg.MsgType = model.ChatMsgTypeText
|
|
chatMsg.Text = content.(string)
|
|
case uint32:
|
|
// 图标消息
|
|
chatMsg.MsgType = model.ChatMsgTypeIcon
|
|
chatMsg.Icon = content.(uint32)
|
|
}
|
|
|
|
// 写入db
|
|
go USER_MANAGER.SaveUserChatMsgToDbSync(chatMsg)
|
|
|
|
// 消息加入自己的队列
|
|
msgList, exist := player.ChatMsgMap[targetUid]
|
|
// 处理序号
|
|
if !exist {
|
|
msgList = make([]*model.ChatMsg, 0)
|
|
chatMsg.Sequence = 101
|
|
} else {
|
|
chatMsg.Sequence = uint32(len(msgList)) + 101
|
|
}
|
|
if len(msgList) > MaxMsgListLen {
|
|
msgList = msgList[1:]
|
|
}
|
|
msgList = append(msgList, chatMsg)
|
|
player.ChatMsgMap[targetUid] = msgList
|
|
|
|
chatInfo := g.ConvChatMsgToChatInfo(chatMsg)
|
|
|
|
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,
|
|
},
|
|
},
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
// 消息加入目标玩家的队列
|
|
msgList, exist = targetPlayer.ChatMsgMap[player.PlayerID]
|
|
if !exist {
|
|
msgList = make([]*model.ChatMsg, 0)
|
|
}
|
|
if len(msgList) > MaxMsgListLen {
|
|
msgList = msgList[1:]
|
|
}
|
|
msgList = append(msgList, chatMsg)
|
|
targetPlayer.ChatMsgMap[player.PlayerID] = msgList
|
|
|
|
// 如果目标玩家在线发送消息
|
|
if targetPlayer.Online {
|
|
privateChatNotify := &proto.PrivateChatNotify{
|
|
ChatInfo: chatInfo,
|
|
}
|
|
g.SendMsg(cmd.PrivateChatNotify, targetPlayer.PlayerID, player.ClientSeq, privateChatNotify)
|
|
}
|
|
}
|
|
|
|
func (g *Game) PrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
|
req := payloadMsg.(*proto.PrivateChatReq)
|
|
targetUid := req.TargetUid
|
|
content := req.Content
|
|
|
|
// 根据发送的类型发送消息
|
|
switch content.(type) {
|
|
case *proto.PrivateChatReq_Text:
|
|
text := content.(*proto.PrivateChatReq_Text).Text
|
|
if len(text) == 0 || len(text) > 80 {
|
|
g.SendError(cmd.PrivateChatRsp, player, &proto.PrivateChatRsp{}, proto.Retcode_RET_PRIVATE_CHAT_CONTENT_TOO_LONG)
|
|
return
|
|
}
|
|
// 发送私聊文本消息
|
|
g.SendPrivateChat(player, targetUid, text)
|
|
// 输入命令 会检测是否为命令的
|
|
COMMAND_MANAGER.PlayerInputCommand(player, targetUid, text)
|
|
case *proto.PrivateChatReq_Icon:
|
|
icon := content.(*proto.PrivateChatReq_Icon).Icon
|
|
// 发送私聊图标消息
|
|
g.SendPrivateChat(player, targetUid, icon)
|
|
default:
|
|
return
|
|
}
|
|
|
|
g.SendMsg(cmd.PrivateChatRsp, player.PlayerID, player.ClientSeq, new(proto.PrivateChatRsp))
|
|
}
|
|
|
|
func (g *Game) ReadPrivateChatReq(player *model.Player, payloadMsg pb.Message) {
|
|
req := payloadMsg.(*proto.ReadPrivateChatReq)
|
|
targetUid := req.TargetUid
|
|
|
|
msgList, exist := player.ChatMsgMap[targetUid]
|
|
if !exist {
|
|
return
|
|
}
|
|
for index, chatMsg := range msgList {
|
|
chatMsg.IsRead = true
|
|
msgList[index] = chatMsg
|
|
}
|
|
player.ChatMsgMap[targetUid] = msgList
|
|
|
|
// 更新db
|
|
go USER_MANAGER.ReadAndUpdateUserChatMsgToDbSync(player.PlayerID, targetUid)
|
|
|
|
g.SendMsg(cmd.ReadPrivateChatRsp, player.PlayerID, player.ClientSeq, new(proto.ReadPrivateChatRsp))
|
|
}
|
|
|
|
func (g *Game) PlayerChatReq(player *model.Player, payloadMsg pb.Message) {
|
|
req := payloadMsg.(*proto.PlayerChatReq)
|
|
channelId := req.ChannelId
|
|
chatInfo := req.ChatInfo
|
|
|
|
sendChatInfo := &proto.ChatInfo{
|
|
Time: uint32(time.Now().Unix()),
|
|
Uid: player.PlayerID,
|
|
Content: nil,
|
|
}
|
|
switch chatInfo.Content.(type) {
|
|
case *proto.ChatInfo_Text:
|
|
text := chatInfo.Content.(*proto.ChatInfo_Text).Text
|
|
if len(text) == 0 {
|
|
return
|
|
}
|
|
sendChatInfo.Content = &proto.ChatInfo_Text{
|
|
Text: text,
|
|
}
|
|
case *proto.ChatInfo_Icon:
|
|
icon := chatInfo.Content.(*proto.ChatInfo_Icon).Icon
|
|
sendChatInfo.Content = &proto.ChatInfo_Icon{
|
|
Icon: icon,
|
|
}
|
|
default:
|
|
return
|
|
}
|
|
|
|
world := WORLD_MANAGER.GetWorldByID(player.WorldId)
|
|
if world == nil {
|
|
logger.Error("get world is nil, worldId: %v, uid: %v", player.WorldId, player.PlayerID)
|
|
return
|
|
}
|
|
world.AddChat(sendChatInfo)
|
|
|
|
playerChatNotify := &proto.PlayerChatNotify{
|
|
ChannelId: channelId,
|
|
ChatInfo: sendChatInfo,
|
|
}
|
|
g.SendToWorldA(world, cmd.PlayerChatNotify, player.ClientSeq, playerChatNotify)
|
|
|
|
g.SendMsg(cmd.PlayerChatRsp, player.PlayerID, player.ClientSeq, new(proto.PlayerChatRsp))
|
|
}
|
|
|
|
func (g *Game) ConvChatInfoToChatMsg(chatInfo *proto.ChatInfo) (chatMsg *model.ChatMsg) {
|
|
chatMsg = &model.ChatMsg{
|
|
Sequence: chatInfo.Sequence,
|
|
Time: chatInfo.Time,
|
|
ToUid: chatInfo.ToUid,
|
|
Uid: chatInfo.Uid,
|
|
IsRead: chatInfo.IsRead,
|
|
MsgType: 0,
|
|
Text: "",
|
|
Icon: 0,
|
|
}
|
|
switch chatInfo.Content.(type) {
|
|
case *proto.ChatInfo_Text:
|
|
chatMsg.MsgType = model.ChatMsgTypeText
|
|
chatMsg.Text = chatInfo.Content.(*proto.ChatInfo_Text).Text
|
|
case *proto.ChatInfo_Icon:
|
|
chatMsg.MsgType = model.ChatMsgTypeIcon
|
|
chatMsg.Icon = chatInfo.Content.(*proto.ChatInfo_Icon).Icon
|
|
default:
|
|
}
|
|
return chatMsg
|
|
}
|
|
|
|
func (g *Game) ConvChatMsgToChatInfo(chatMsg *model.ChatMsg) (chatInfo *proto.ChatInfo) {
|
|
chatInfo = &proto.ChatInfo{
|
|
Time: chatMsg.Time,
|
|
Sequence: chatMsg.Sequence,
|
|
ToUid: chatMsg.ToUid,
|
|
Uid: chatMsg.Uid,
|
|
IsRead: chatMsg.IsRead,
|
|
Content: nil,
|
|
}
|
|
switch chatMsg.MsgType {
|
|
case model.ChatMsgTypeText:
|
|
chatInfo.Content = &proto.ChatInfo_Text{
|
|
Text: chatMsg.Text,
|
|
}
|
|
case model.ChatMsgTypeIcon:
|
|
chatInfo.Content = &proto.ChatInfo_Icon{
|
|
Icon: chatMsg.Icon,
|
|
}
|
|
default:
|
|
}
|
|
return chatInfo
|
|
}
|
|
|
|
// 跨服玩家聊天通知
|
|
|
|
func (g *Game) 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)
|
|
}
|
|
if len(msgList) > MaxMsgListLen {
|
|
msgList = msgList[1:]
|
|
}
|
|
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)
|
|
}
|
|
}
|