PGRData/Script/matrix/xmanager/XChatManager.lua

1456 lines
53 KiB
Lua
Raw Normal View History

local tableInsert = table.insert
local ipairs = ipairs
local ChatChannelType = ChatChannelType
local CSTime = CS.UnityEngine.Time
XChatManagerCreator = function()
local XChatManager = {}
local CLIENT_WORLD_CHAT_MAX_SIZE = 0
local CLIENT_ROOM_CHAT_MAX_SIZE = 0
local REMOVE_CHAT_RECORD_OF_DAY = 0
local CHAT_INTERVAL_TIME = 0
local TodayResetTime = 0
local WORLD_CHAT_MAX_COUNT = 0
local MENTOR_CHAT_MAX_COUNT = 0
-- 一天的秒数
local ONE_DAY_SECONDS = 60 * 60 * 24
local WorldChatList = {} --保存世界聊天记录
local PrivateChatMap = {} --保存私聊的聊天纪录
local GuildChatList = {} --保存公会聊天纪录
local RoomChatList = {} --保存房间聊天记录
local MentorChatList = {} --师徒聊天记录
local ChatList = {} --各类聊天记录
local EmojiDatasDic = {}
local EffectInfo = {} -- 关键字屏幕特效
local EffectTriggerType = {
Me = 1,
Other = 2,
All = 3,
}
local LastChatCoolTime = 0
local LastEffectCoolTime = 0
local MessageId = -1 --离线消息
local OfflineMessageTag = "OfflineRecordMessage_"
local LastRequestChannelTime = 0
local CurrentChatChannelId = 0
local LastReadChatTime = {}
local ChatChannelInfos
local GuildChatContent = ""
local GuildSaveCount = 0
local MentorChatContent = ""
local MentorSaveCount = 0
local SubManager = {}
--协议处理
local MethodName = {
SendChat = "SendChatRequest",
GetGift = "GetGiftsRequest",
GetAllGiftsRequest = "GetAllGiftsRequest",
GetOfflineMessageRequest = "OfflineMessageRequest",
SelectChatChannelRequest = "SelectChatChannelRequest",
EnterWorldChatRequest = "EnterWorldChatRequest",
GetWorldChannelInfoRequest = "GetWorldChannelInfoRequest",
CatchRepeatChat = "ReportBanChatRequest", --重复发言检测
}
function XChatManager.Init()
REMOVE_CHAT_RECORD_OF_DAY = CS.XGame.ClientConfig:GetInt("RemoveChatRecordOfDay")
CLIENT_WORLD_CHAT_MAX_SIZE = CS.XGame.ClientConfig:GetInt("WorldChatMaxSize")
CLIENT_ROOM_CHAT_MAX_SIZE = CS.XGame.ClientConfig:GetInt("RoomChatMaxSize")
CHAT_INTERVAL_TIME = CS.XGame.Config:GetInt("ChatIntervalTime")
WORLD_CHAT_MAX_COUNT = CS.XGame.Config:GetInt("WorldChatMaxCount")
MENTOR_CHAT_MAX_COUNT = XMentorSystemConfigs.GetMentorSystemData("MentorChatMaxCount")
ChatList[ChatChannelType.World] = WorldChatList
ChatList[ChatChannelType.Guild] = GuildChatList
ChatList[ChatChannelType.Room] = RoomChatList
ChatList[ChatChannelType.Mentor] = MentorChatList
for _, type in pairs(ChatChannelType) do
local key = string.format("%s%d" ,XChatConfigs.KEY_LAST_READ_CHAT_TIME, type)
LastReadChatTime[type] = XSaveTool.GetData(key) or XMath.IntMax()
end
XEventManager.AddEventListener(XEventId.EVENT_ROOM_LEAVE_ROOM, function()
RoomChatList = {}
ChatList[ChatChannelType.Room] = RoomChatList
end)
XEventManager.AddEventListener(XEventId.EVENT_LOGIN_DATA_LOAD_COMPLETE, function()
XChatManager.InitChatChannel()
-- 登录完成后直接获取所有频道信息
XChatManager.GetWorldChannelInfos()
end)
-- 聊天播放特效功能
local effectTemplates = XChatConfigs.GetEffectTemplates()
local nowTime = XTime.GetServerNowTimestamp()
for _, template in pairs(effectTemplates) do
local endTime = XTime.ParseToTimestamp(template.EndTimeStr)
if nowTime < endTime then
local data = XTool.Clone(template)
data.BeginTime = XTime.ParseToTimestamp(data.BeginTimeStr)
data.EndTime = endTime
tableInsert(EffectInfo, data)
end
end
XChatManager.SetMetaTable()
XChatManager.InitSubManager()
end
function XChatManager.SetMetaTable()
local _mTable = {__index = function(baseTable, key)
for _, manager in pairs(SubManager) do
if manager and manager[key] then
local v = manager[key]
baseTable[key] = v
return v
end
end
return nil
end}
setmetatable(XChatManager, _mTable)
end
function XChatManager.InitSubManager()
local InitManager = function(managerName)
local manager = require("XEntity/XChat/XChat" .. managerName .. "Manager")
if manager then
manager.Init(XChatManager)
table.insert(SubManager, manager)
end
end
InitManager("EmojiPack")
end
function XChatManager.GetLastRequestChannelTime()
return LastRequestChannelTime
end
function XChatManager.SetLastRequestChannelTime(time)
LastRequestChannelTime = time
end
function XChatManager.GetWorldChatMaxCount()
return WORLD_CHAT_MAX_COUNT
end
function XChatManager.GetMentorChatMaxCount()
return MENTOR_CHAT_MAX_COUNT
end
-- 初始化世界聊天数据
function XChatManager.InitWorldChatData(worldChatDataList)
WorldChatList = {}
ChatList[ChatChannelType.World] = WorldChatList
local WorldChatLoop = function(item)
if item ~= nil then
XChatManager.ProcessExtraContent(item)
tableInsert(WorldChatList, 1, item)
end
end
XTool.LoopCollection(worldChatDataList, WorldChatLoop)
end
--加载私聊信息
function XChatManager.InitFriendPrivateChatData()
PrivateChatMap = {}
local cb = function()
for _, friendId in pairs(XDataCenter.SocialManager.GetFriendIds()) do
XChatManager.ReadSpecifyFriendsChatContent(friendId)
end
XChatManager.GetOfflineMessageRequest(XChatManager.GetLocalOfflineRecord())
end
XDataCenter.SocialManager.GetFriendsInfo(cb)
end
--处理系统消息
local function HandleSystemChat()
--TODO Handle System Chat
end
--处理世界消息
local function HandleWorldChat(chatData, isNotify)
--黑名单的聊天数据不加入
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
if #WorldChatList >= CLIENT_WORLD_CHAT_MAX_SIZE then
table.remove(WorldChatList, #WorldChatList)
end
tableInsert(WorldChatList, 1, chatData)
if isNotify then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_WORLD_MSG, chatData)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_WORLD_MSG, chatData)
end
end
--处理公会消息
local function HandleGuildChat(chatData, isNotify)
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
tableInsert(GuildChatList, 1, chatData)
if isNotify then
XEventManager.DispatchEvent(XEventId.EVENT_GUILD_RECEIVE_CHAT, chatData)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_GUILD_RECEIVE_CHAT, chatData)
end
end
--处理师徒消息
local function HandleMentorChat(chatData, isNotify)
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
if #MentorChatList >= MENTOR_CHAT_MAX_COUNT then
table.remove(MentorChatList, #MentorChatList)
end
tableInsert(MentorChatList, 1, chatData)
if isNotify then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_MENTOR_MSG, chatData)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_MENTOR_MSG, chatData)
end
end
--处理私聊消息
local function HandlePrivateChat(chatData, ignoreNotify)
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
if (not chatData) then
return
end
if chatData.SenderId == XPlayer.Id or
chatData.MsgType == ChatMsgType.Gift or
chatData.MsgType == ChatMsgType.Tips then
chatData.IsRead = true
end
if chatData.SenderId ~= XPlayer.Id then
XChatManager.UpdateLocalOfflineRecord(chatData.MessageId or 0)
end
local targetId = chatData:GetChatTargetId()
XChatManager.AddPrivateChatData(targetId, chatData, false, ignoreNotify)
--保存消息
XChatManager.SaveSpecifyFriendsChatContent(targetId)
end
--处理房间消息
local function HandleRoomChat(chatData)
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
if #RoomChatList >= CLIENT_ROOM_CHAT_MAX_SIZE then
table.remove(RoomChatList, #RoomChatList)
end
tableInsert(RoomChatList, 1, chatData)
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_ROOM_MSG, chatData)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_ROOM_MSG, chatData)
end
-- 清除房间聊天
function XChatManager.ResetRoomChat()
RoomChatList = {}
ChatList[ChatChannelType.Room] = RoomChatList
end
function XChatManager.OnSynChat(chatMsg, ignoreNotify)
local chatData = XChatData.New(chatMsg)
if chatMsg.ChannelType == ChatChannelType.System then
HandleSystemChat(chatData)
elseif chatMsg.ChannelType == ChatChannelType.World then
HandleWorldChat(chatData, true)
elseif chatMsg.ChannelType == ChatChannelType.Private then
HandlePrivateChat(chatData, ignoreNotify)
elseif chatMsg.ChannelType == ChatChannelType.Room then
HandleRoomChat(chatData)
elseif chatMsg.ChannelType == ChatChannelType.Guild then
HandleGuildChat(chatData, true)
XChatManager.SaveGuildChatContent()
elseif chatMsg.ChannelType == ChatChannelType.Mentor then
HandleMentorChat(chatData, true)
end
--接收到礼物时增加一条tip提示
if chatMsg.MsgType == ChatMsgType.Gift then
chatMsg.MsgType = ChatMsgType.Tips
chatMsg.CreateTime = chatMsg.CreateTime
chatMsg.GiftId = chatMsg.GiftId
XChatManager.OnSynChat(chatMsg, true)
end
end
---------------------------------public function-----------------------------------
function XChatManager.GetRemoveChatRecordOfDays()
return REMOVE_CHAT_RECORD_OF_DAY
end
function XChatManager.GetWorldChatMaxSize()
return CLIENT_WORLD_CHAT_MAX_SIZE
end
--=== Emoji ===
function XChatManager.GetEmojiIcon(emojiId)
return XChatConfigs.GetEmojiIcon(emojiId)
end
function XChatManager.GetEmojiQuality()
return XChatConfigs.GetEmojiQuality()
end
function XChatManager.GetEmojiName(emojiId)
return XChatConfigs.GetEmojiName(emojiId)
end
function XChatManager.GetEmojiDescription(emojiId)
return XChatConfigs.GetEmojiDescription(emojiId)
end
function XChatManager.GetEmojiWorldDesc(emojiId)
return XChatConfigs.GetEmojiWorldDesc(emojiId)
end
function XChatManager.GetEmojiBigIcon(emojiId)
return XChatConfigs.GetEmojiBigIcon(emojiId)
end
function XChatManager.GetEmojiTemplates()
local templates = {}
for _, emojiData in pairs(EmojiDatasDic) do
tableInsert(templates, emojiData)
end
table.sort(templates, function(l, r) return l:GetEmojiOrder() < r:GetEmojiOrder() end)
return templates
end
function XChatManager.GetEmojiDatasDic()
return EmojiDatasDic
end
function XChatManager.IsEmojiValid(emojiId)
for _, v in pairs(EmojiDatasDic) do
if v:IsEmojiValid(emojiId) then
return true
end
end
return false
end
--=== Any Chat ===
function XChatManager.GetChatList(type)
return ChatList[type]
end
--=== World Chat ===
function XChatManager.GetWorldChatList()
return WorldChatList
end
--=== Guild Chat ===
function XChatManager.GetGuildChatList()
return GuildChatList
end
--=== Mentor Chat ===
function XChatManager.GetMentorChatList()
return MentorChatList
end
--=== Room Chat ===
function XChatManager.GetRoomChatList()
table.sort(RoomChatList, function(a, b)
if a.CreateTime ~= b.CreateTime then
return a.CreateTime > b.CreateTime
end
end)
return RoomChatList
end
--=== Private Chat ===
-- 获取私聊聊天数据
function XChatManager.GetPrivateDynamicList(friendId)
local msgData = XChatManager.GetPrivateChatsByFriendId(friendId)
local sortFunc = function(a, b)
if a.CreateTime ~= b.CreateTime then
return a.CreateTime > b.CreateTime
else
if a.MsgType == ChatMsgType.Tips then
if b.MsgType == ChatMsgType.Tips then
return a.GiftStatus > b.GiftStatus
end
return true
end
end
end
table.sort(msgData, sortFunc)
return msgData
end
-- 获取私聊好友id列表
function XChatManager.GetPrivateChatGroupData(nowID)
--初始化数据
local chatFriendIdList = XChatManager.GetHaveChatDataFriendIds()
local targetInList = false
for _, id in ipairs(chatFriendIdList) do
if id == nowID then
targetInList = true
break
end
end
if not targetInList then
tableInsert(chatFriendIdList, 1, nowID)
end
local dynamicListData = {}
for _, v in ipairs(chatFriendIdList) do
local friendInfo = XDataCenter.SocialManager.GetFriendInfo(v)
tableInsert(dynamicListData, friendInfo)
end
return dynamicListData
end
--新增私聊消息
function XChatManager.AddPrivateChatData(friendId, chatData, isInit, ignoreNotify)
if XDataCenter.SocialManager.GetBlackData(friendId) then
return
end
--好友聊天数据结构
local friendChats = PrivateChatMap[friendId]
if not friendChats then
friendChats = {}
friendChats.ChatMap = {}
friendChats.LastChat = nil
PrivateChatMap[friendId] = friendChats
end
friendChats.LastChat = chatData
friendChats.ChatMap = friendChats.ChatMap or {}
tableInsert(friendChats.ChatMap, chatData)
if not isInit or not chatData.IsRead then
if not ignoreNotify then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_PRIVATECHAT, chatData)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_PRIVATECHAT, chatData)
end
end
end
--获取已聊天过的好友id列表
function XChatManager.GetHaveChatDataFriendIds()
local list = {}
for friendId, chatInfo in pairs(PrivateChatMap) do
if chatInfo and chatInfo.ChatMap then
for _, _ in pairs(chatInfo.ChatMap) do
tableInsert(list, friendId)
break
end
end
end
if #list >= 2 then
local sortByCreateTime = function(l, r)
local lchat = XChatManager.GetLastPrivateChatByFriendId(l)
local rchat = XChatManager.GetLastPrivateChatByFriendId(r)
if lchat.CreateTime > rchat.CreateTime then
return true
else
return false
end
end
table.sort(list, sortByCreateTime)
end
return list
end
--更新礼物信息
function XChatManager.UpdateGiftData(friendId, giftId, status, giftCount)
local friendChats = PrivateChatMap[friendId]
if not friendChats or not friendChats.ChatMap then
return
end
for _, v in pairs(friendChats.ChatMap) do
if (v.MsgType == ChatMsgType.Gift or v.MsgType == ChatMsgType.Tips) and v.GiftId == giftId and v.SenderId == friendId then
friendChats.LastChat = v
v.GiftStatus = status
if giftCount and giftCount > 0 then
v.GiftCount = giftCount
end
end
end
--保存消息
XChatManager.SaveSpecifyFriendsChatContent(friendId)
end
--获取指定好友聊天列表
function XChatManager.GetPrivateChatsByFriendId(friendId)
local list = {}
if (PrivateChatMap[friendId] and PrivateChatMap[friendId].ChatMap) then
for _, chat in pairs(PrivateChatMap[friendId].ChatMap) do
tableInsert(list, chat)
end
end
return list
end
--获取好友最后一条聊天
function XChatManager.GetLastPrivateChatByFriendId(friendId)
local lastChat = nil
local info = PrivateChatMap[friendId]
if (info) then
lastChat = info.LastChat
end
return lastChat
end
--获取好友未读聊天数量
function XChatManager.GetPrivateUnreadChatCountByFriendId(friendId)
local count = 0
local info = PrivateChatMap[friendId]
if (info and info.ChatMap) then
for _, chat in pairs(info.ChatMap) do
if (not chat.IsRead) then
count = count + 1
end
end
end
return count
end
--设置指定好友全部聊天为已读
function XChatManager.SetPrivateChatReadByFriendId(friendId)
local friendChat = PrivateChatMap[friendId]
local count = 0
if friendChat and friendChat.ChatMap then
for _, chat in pairs(friendChat.ChatMap) do
if not chat.IsRead then
chat.IsRead = true
count = count + 1
end
end
end
--保存消息
XChatManager.SaveSpecifyFriendsChatContent(friendId)
if count > 0 then
XEventManager.DispatchEvent(XEventId.EVENT_FRIEND_READ_PRIVATE_MSG)
end
end
--检测好友是否有自己可以领取的礼物
function XChatManager.CheckDoesHaveGiftByFriendId(friendId)
local friendChats = PrivateChatMap[friendId]
if not friendChats or not friendChats.ChatMap then
return false
end
for _, v in pairs(friendChats.ChatMap) do
if v:CheckHaveGift() then
return true
end
end
return false
end
---------------------------------Chat Record-----------------------------------
local ChatRecordTag = "ChatRecord_%d_%d" --标识 + 好友id + 自己id
--读取指定好友的聊天内容
function XChatManager.ReadSpecifyFriendsChatContent(friendId)
local key = string.format(ChatRecordTag, friendId, XPlayer.Id)
if CS.UnityEngine.PlayerPrefs.HasKey(key) then
local chatRecord = CS.UnityEngine.PlayerPrefs.GetString(key)
local msgTab = string.Split(chatRecord, '\n')
if msgTab ~= nil and #msgTab > 0 then
for index = 1, #msgTab do
local content = msgTab[index]
if (not string.IsNilOrEmpty(content)) then
local tab = string.Split(content, '\t')
if tab ~= nil then
if XChatManager.CheckIsRemove(tonumber(tab[3])) then
local chatData = XChatData.New()
chatData.ChannelType = ChatChannelType.Private
chatData.SenderId = tonumber(tab[1])
chatData.TargetId = tonumber(tab[2])
chatData.CreateTime = tonumber(tab[3])
chatData.Content = tab[4]
chatData.MsgType = tonumber(tab[5])
chatData.GiftId = tonumber(tab[6])
chatData.GiftCount = tonumber(tab[7])
chatData.GiftStatus = tonumber(tab[8])
chatData.IsRead = tonumber(tab[9]) == 1
chatData.CustomContent = tab[10]
if XPlayer.Id == chatData.SenderId then
chatData.Icon = XPlayer.CurrHeadPortraitId
chatData.NickName = XPlayer.Name
chatData.HeadFrameId = XPlayer.CurrHeadFrameId
else
local friendInfo = XDataCenter.SocialManager.GetFriendInfo(friendId)
if friendInfo then
chatData.Icon = friendInfo.Icon
chatData.NickName = friendInfo.NickName
chatData.HeadFrameId = friendInfo.HeadFrameId
end
end
XChatManager.ProcessExtraContent(chatData)
XChatManager.AddPrivateChatData(friendId, chatData, true)
end
end
end
end
end
end
end
--检测该消息是否是七天前的
function XChatManager.CheckIsRemove(time)
if time == nil then
return false
end
local curTime = XTime.GetServerNowTimestamp()
return curTime - time <= REMOVE_CHAT_RECORD_OF_DAY * 24 * 60 * 60
end
function XChatManager.DeleteGuildChat(guildId)
GuildChatList = {}
ChatList[ChatChannelType.Guild] = GuildChatList
local key = XDataCenter.GuildManager.GetGuildChannelKey(guildId)
if CS.UnityEngine.PlayerPrefs.HasKey(key) then
CS.UnityEngine.PlayerPrefs.DeleteKey(key)
CS.UnityEngine.PlayerPrefs.Save()
end
end
-- 登录初始化公会聊天内容
function XChatManager.InitLocalCacheGuildChatContent()
if not XDataCenter.GuildManager.IsJoinGuild() then return end
local guildId = XDataCenter.GuildManager.GetGuildId()
local key = XDataCenter.GuildManager.GetGuildChannelKey(guildId)
if CS.UnityEngine.PlayerPrefs.HasKey(key) then
GuildChatList = {}
ChatList[ChatChannelType.Guild] = GuildChatList
local chatRecord = CS.UnityEngine.PlayerPrefs.GetString(key)
local allLines = string.Split(chatRecord, '\n')
if allLines ~= nil and #allLines > 0 then
for i = 1, #allLines do
local content = allLines[i]
if (not string.IsNilOrEmpty(content)) then
local tab = string.Split(content, '\t')
if tab ~= nil then
local chatData = XChatData.New()
chatData.SenderId = tonumber(tab[1])
chatData.TargetId = tonumber(tab[2])
chatData.CreateTime = tonumber(tab[3])
chatData.Content = tab[4]
chatData.MsgType = tonumber(tab[5])
chatData.IsRead = tonumber(tab[6])
chatData.MessageId = tonumber(tab[7])
chatData.Icon = tonumber(tab[8])
chatData.CustomContent = tab[9]
chatData.NickName = tab[10]
chatData.GuildRankLevel = tonumber(tab[11])
chatData.ChannelType = tonumber(tab[12])
chatData.HeadFrameId = tonumber(tab[13])
chatData.CollectWordId = tonumber(tab[14])
chatData.NameplateId = tonumber(tab[15]) or 0
tableInsert(GuildChatList, chatData)
end
end
end
end
end
end
-- 合并客户端,服务端公会聊天
function XChatManager.MergeClientAndServerGuildChat(serverChat)
if #serverChat <= 0 then return end
if #GuildChatList <= 0 then
if #serverChat > 0 then
for _, chatData in pairs(serverChat) do
tableInsert(GuildChatList, chatData)
end
return
end
end
local clientTailIndex = 1
local clientTailCreateTime = GuildChatList[clientTailIndex].CreateTime
local serverTailIndex = #serverChat
local serverTailCreateTime = serverChat[serverTailIndex].CreateTime
local serverHeadIndex = 1
local serverHeadCreateTime = serverChat[serverHeadIndex].CreateTime
-- 服务端缓存与客户端缓存完全重叠
if clientTailCreateTime > serverHeadCreateTime then
return
end
-- 服务端缓存与客户端缓存部分重叠
local beginIndex = 0
if serverTailCreateTime <= clientTailCreateTime and clientTailCreateTime <= serverHeadCreateTime then
local clientHeadChat = GuildChatList[clientTailIndex]
for i = #serverChat, 1, -1 do
local curServerChat = serverChat[i]
if clientHeadChat.CreateTime == curServerChat.CreateTime and
clientHeadChat.SenderId == curServerChat.SenderId and
clientHeadChat.Content == curServerChat.Content then
beginIndex = i - 1
break
end
if clientHeadChat.CreateTime < curServerChat.CreateTime then
beginIndex = i
break
end
end
if beginIndex > 0 and beginIndex <= #serverChat then
for i = beginIndex, 1, -1 do
tableInsert(GuildChatList, 1, serverChat[i])
end
end
XChatManager.SaveGuildChatContent()
return
end
-- 服务端缓存与客户端缓存完成不重叠
if clientTailCreateTime < serverTailCreateTime then
for i = #serverChat, 1, -1 do
tableInsert(GuildChatList, 1, serverChat[i])
end
end
XChatManager.SaveGuildChatContent()
end
-- 存储公会聊天内容
function XChatManager.SaveGuildChatContent()
if not XDataCenter.GuildManager.IsJoinGuild() then return end
local splitMark = "\n"
for i = #GuildChatList-GuildSaveCount, 1, -1 do
local chat = GuildChatList[i]
local list = {}
if chat ~= nil and type(chat) == 'table' and i <= XGuildConfig.GuildChatCacheCount then
tableInsert(list, chat.SenderId)
tableInsert(list, chat.TargetId)
tableInsert(list, chat.CreateTime)
tableInsert(list, chat.Content)
tableInsert(list, chat.MsgType)
tableInsert(list, (chat.IsRead and "1" or "0"))
tableInsert(list, chat.MessageId)
tableInsert(list, chat.Icon)
tableInsert(list, (chat.CustomContent or ""))
tableInsert(list, (chat.NickName or ""))
tableInsert(list, (chat.GuildRankLevel or "0"))
tableInsert(list, (chat.ChannelType or "0"))
tableInsert(list, (chat.HeadFrameId or "0"))
tableInsert(list, (chat.CollectWordId or "0"))
tableInsert(list, (chat.NameplateId or "0"))
end
GuildSaveCount = GuildSaveCount + 1
local chatStr = table.concat(list, "\t")
GuildChatContent = string.format("%s%s%s", chatStr, splitMark, GuildChatContent)
end
if GuildChatContent ~= nil and GuildChatContent ~= '' then
local guildId = XDataCenter.GuildManager.GetGuildId()
local key = XDataCenter.GuildManager.GetGuildChannelKey(guildId)
CS.UnityEngine.PlayerPrefs.SetString(key, GuildChatContent)
CS.UnityEngine.PlayerPrefs.Save()
end
end
-- 关键字匹配
function XChatManager.KeywordMatch(channelType, chatData)
local nowTime = XTime.GetServerNowTimestamp()
local firstMatchIndex = nil
local minMatchPos = XMath.IntMax()
for index, info in ipairs(EffectInfo) do
local isMatch = true
isMatch = isMatch and nowTime > info.BeginTime and nowTime < info.EndTime
isMatch = isMatch and nowTime > LastEffectCoolTime + info.CoolTime
isMatch = isMatch and chatData.MsgType == ChatMsgType.Normal or chatData.MsgType == ChatMsgType.RoomMsg
if not isMatch then goto CONTINUE end
if info.TriggerType == EffectTriggerType.Me then
isMatch = isMatch and chatData.SenderId == XPlayer.Id
elseif info.TriggerType == EffectTriggerType.Other then
isMatch = isMatch and chatData.SenderId ~= XPlayer.Id
end
if info.Channel and next(info.Channel) then
local isPartMatch = false
for _,channel in ipairs(info.Channel) do
isPartMatch = isPartMatch or channel == channelType
end
isMatch = isMatch and isPartMatch
end
if not isMatch then goto CONTINUE end
-- 开始匹配具体内容
if info.Keyword and next(info.Keyword) then
for _,pattern in ipairs(info.Keyword) do
local matchPos = string.find(chatData.Content, pattern)
if matchPos and matchPos < minMatchPos then
firstMatchIndex = index
minMatchPos = matchPos
end
end
end
:: CONTINUE ::
end
if firstMatchIndex then
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_MATCH_EFFECT, EffectInfo[firstMatchIndex])
return
end
end
-- 设置特效播放完毕的时间
function XChatManager.SetEffectEnd(time)
LastEffectCoolTime = time or XTime.GetServerNowTimestamp()
end
-- 设置最后一次读消息的时间
function XChatManager.SetChatRead(type)
local key = string.format("%s%d" ,XChatConfigs.KEY_LAST_READ_CHAT_TIME, type)
if next(ChatList[type]) then
LastReadChatTime[type] = ChatList[type][1].CreateTime
else
local nowTime = XTime.GetServerNowTimestamp()
LastReadChatTime[type] = nowTime
-- XLog.Warning("nowTime",XTime.TimestampToLocalDateTimeString(nowTime),type)
end
XSaveTool.SaveData(key, LastReadChatTime[type])
end
-- 获取未读信息数量
function XChatManager.GetUnreadChatCount(type)
local count = 0
local chatList = XChatManager.GetChatList(type)
if not (chatList and next(chatList)) then
return count
end
for i = 1, #chatList do
local chat = chatList[i]
if chat.CreateTime > LastReadChatTime[type] then
count = count + 1
end
end
return count
end
function XChatManager.CheckRedPointByType(type)
-- return XChatManager.GetUnreadChatCount(type) > 0
local chatList = XChatManager.GetChatList(type)
if not (chatList and next(chatList)) then
return false
end
-- 除了好友消息,其他类型都是将最新消息插入到表头
-- XLog.Warning(chatList)
-- XLog.Warning(type, chatList[1].CreateTime > LastReadChatTime[type], chatList[1].CreateTime, XTime.TimestampToLocalDateTimeString(LastReadChatTime[type]),XTime.TimestampToLocalDateTimeString(chatList[1].CreateTime))
return chatList[1].CreateTime > LastReadChatTime[type]
end
function XChatManager.GetLatestChatData(type)
if type then
return ChatList[type][1]
else
-- 默认返回最后一次公会或者世界聊天内容
local worldMsg = ChatList[ChatChannelType.World][1]
local guildMsg = ChatList[ChatChannelType.Guild][1]
local latestMsg
local latestTime = 0
if guildMsg then
latestMsg = guildMsg
latestTime = guildMsg.CreateTime
end
if worldMsg and worldMsg.CreateTime > latestTime then
latestMsg = worldMsg
latestTime = worldMsg.CreateTime
end
return latestMsg
end
end
-- 删除上一个公会的聊天缓存
function XChatManager.DeleteLastGuildChatContent(lastGuildId)
if XDataCenter.GuideManager.IsJoinGuild() then
local guildId = XDataCenter.GuildManager.GetGuildId()
if guildId == lastGuildId then return end
end
local lastGuildKey = XDataCenter.GuildManager.GetGuildChannelKey(lastGuildId)
if CS.UnityEngine.PlayerPrefs.HasKey(lastGuildKey) then
CS.UnityEngine.PlayerPrefs.DeleteKey(lastGuildKey)
CS.UnityEngine.PlayerPrefs.Save()
end
end
--存储指定好友的聊天内容
function XChatManager.SaveSpecifyFriendsChatContent(friendId)
local chatList = XChatManager.GetPrivateDynamicList(friendId)
if chatList == nil or #chatList == 0 then
return
end
local saveContent = ''
for index = 1, #chatList do
local chat = chatList[index]
if chat ~= nil and type(chat) == 'table' then
saveContent = saveContent .. chat.SenderId .. '\t'
saveContent = saveContent .. chat.TargetId .. '\t'
saveContent = saveContent .. chat.CreateTime .. '\t'
saveContent = saveContent .. chat.Content .. '\t'
saveContent = saveContent .. chat.MsgType .. "\t"
saveContent = saveContent .. tostring(chat.GiftId) .. "\t"
saveContent = saveContent .. tostring(chat.GiftCount) .. "\t"
saveContent = saveContent .. tostring(chat.GiftStatus) .. "\t"
saveContent = saveContent .. (chat.IsRead and "1" or "0") .. "\t"
saveContent = saveContent .. (chat.CustomContent or "") .. "\n"
end
end
if saveContent ~= nil and saveContent ~= '' then
local key = string.format(ChatRecordTag, friendId, XPlayer.Id)
CS.UnityEngine.PlayerPrefs.SetString(key, saveContent)
CS.UnityEngine.PlayerPrefs.Save()
end
end
--清除指定好友的聊天内容
function XChatManager.ClearFriendChatContent(friendId)
local key = string.format(ChatRecordTag, friendId, XPlayer.Id)
PrivateChatMap[friendId] = nil
if CS.UnityEngine.PlayerPrefs.HasKey(key) then
CS.UnityEngine.PlayerPrefs.DeleteKey(key)
CS.UnityEngine.PlayerPrefs.Save()
end
end
--获取所有私聊信息
function XChatManager.GetAllPrivateChatMsgCount()
if not PrivateChatMap then
return 0
end
local count = 0
for _, v in pairs(PrivateChatMap) do
local info = v
if (info and info.ChatMap) then
for _, chat in pairs(info.ChatMap) do
if (not chat.IsRead) then
count = count + 1
end
end
end
end
return count
end
function XChatManager.CheckCd()
if LastChatCoolTime > 0 and LastChatCoolTime + CHAT_INTERVAL_TIME > XTime.GetServerNowTimestamp() then
XUiManager.TipCode(XCode.ChatManagerRefreshTimeCooling)
return false
end
return true
end
--发送聊天
function XChatManager.SendChat(chatData, cb)
XNetwork.Call(MethodName.SendChat, { ChatData = chatData, TargetIdList = chatData.TargetIds }, function(response)
LastChatCoolTime = response.RefreshTime
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
if chatData.ChannelType == ChatChannelType.World then
if cb then
cb(CHAT_INTERVAL_TIME + LastChatCoolTime - XTime.GetServerNowTimestamp(), response.ChatData)
end
end
return
end
if cb then
cb(CHAT_INTERVAL_TIME + LastChatCoolTime - XTime.GetServerNowTimestamp(), response.ChatData)
end
XDataCenter.ChatManager.CheckChat(chatData.Content)
end)
end
----------------------------------------重复聊天发言检测-----------------------------------
local CheckChatTimer
local CheckChatList = {}
local CheckChatId = 1
local WaitDelectChatList = {}
local CheckContent = {}
function XChatManager.CheckChat(content)
if not content then return end
--先检测是否是过滤内容
local filters = XChatConfigs.GetRepeatChatForbidStringFilter()
if filters then
for _, filterStr in pairs(filters) do
if content == filterStr then
return
end
end
end
--提取字符串中的英文+汉字
local pureStr = XTool.GetPureStr(content)
if not pureStr then return end
local chatData = {
Id = CheckChatId,
Time = 0,
Content = pureStr,
RepeatCount = 0
}
CheckChatList[CheckChatId] = chatData
CheckChatId = CheckChatId + 1
CheckContent[pureStr] = true
if not CheckChatTimer then XChatManager.StartCheckChatTimer() end
end
function XChatManager.StartCheckChatTimer()
CheckChatTimer = XScheduleManager.ScheduleForever(function()
--是否进行了检测(检查列表是否空列)
local haveCheck = false
for _, chat in pairs(CheckChatList) do
haveCheck = true
chat.Time = chat.Time + CSTime.deltaTime
if CheckContent[chat.Content] then
chat.RepeatCount = chat.RepeatCount + 1
if chat.RepeatCount >= XChatConfigs.GetRepeatChatForbidRepeatCount() then
XChatManager.CatchRepeatChat(chat.RepeatCount)
end
end
if chat.Time >= XChatConfigs.GetRepeatChatForbidCalculateTime() then
table.insert(WaitDelectChatList, chat.Id)
end
end
for _, delectChatId in pairs(WaitDelectChatList) do
if CheckChatList[delectChatId] then
CheckChatList[delectChatId] = nil
end
end
if not haveCheck then
XScheduleManager.UnSchedule(CheckChatTimer)
CheckChatTimer = nil
return
end
WaitDelectChatList = {}
CheckContent = {}
end, 0)
end
function XChatManager.CatchRepeatChat(repeatCount)
XNetwork.Call(MethodName.CatchRepeatChat, { Times = repeatCount }, function(response)
if response.Code ~= XCode.Success then
local text = CS.XTextManager.GetCodeText(response.Code)
XLog.Error(text)
return
end
XLog.Debug("捕捉到10秒内的第" .. repeatCount .. "次重复发言!已发送成功!")
end)
end
----------------------------------------重复聊天发言检测 end-----------------------------------
--收取单个礼物
function XChatManager.GetGift(giftId, callback)
callback = callback or function() end
XNetwork.Call(MethodName.GetGift, { GiftId = giftId or 0 }, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
return
end
callback(response.RewardGoodsList)
end)
end
--群收礼物
function XChatManager.GetAllGiftsRequest(callback)
if not XChatManager.CheckHasGift() then
XUiManager.TipError(CS.XTextManager.GetText("ChatManagerGetGiftNotGift"))
return
end
XNetwork.Call(MethodName.GetAllGiftsRequest, nil, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
return
end
if #response.RewardGoodsList <= 0 then
XUiManager.TipError(CS.XTextManager.GetText("ChatManagerGetGiftNotGift"))
return
end
if callback then
callback(response.GiftInfoList, response.RewardGoodsList)
end
end)
end
-- 离线消息
function XChatManager.GetOfflineMessageRequest(msgId, cb)
XNetwork.Call(MethodName.GetOfflineMessageRequest, { MessageId = msgId }, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
return
end
-- 处理离线的消息
XChatManager.HandleOfflineMessage(response.Messages)
if cb then
cb()
end
end)
end
function XChatManager.HandleOfflineMessage(offlineMessages)
if not offlineMessages then return end
local lastChatData = nil
local earliestChatTime = XMath.IntMax()
for _, chatData in pairs(offlineMessages) do
XChatManager.ProcessExtraContent(chatData)
XChatManager.OnSynChat(chatData, true)
if earliestChatTime < chatData.CreateTime then
earliestChatTime = chatData.CreateTime
end
lastChatData = chatData
end
for _, type in ipairs(ChatChannelType) do
if earliestChatTime < LastReadChatTime[type] then
LastReadChatTime[type] = earliestChatTime
local key = string.format("%s%d" ,XChatConfigs.KEY_LAST_READ_CHAT_TIME, type)
XSaveTool.SaveData(key, LastReadChatTime[type])
end
end
-- 只在最后检查一次红点
if lastChatData then
local data = XChatData.New(lastChatData)
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_PRIVATECHAT, data)
end
end
function XChatManager.UpdateLocalOfflineRecord(messageId)
if messageId > MessageId then
MessageId = messageId
local key = string.format("%s%s", OfflineMessageTag, tostring(XPlayer.Id))
CS.UnityEngine.PlayerPrefs.SetInt(key, MessageId)
CS.UnityEngine.PlayerPrefs.Save()
end
end
function XChatManager.GetLocalOfflineRecord()
local key = string.format("%s%s", OfflineMessageTag, tostring(XPlayer.Id))
if CS.UnityEngine.PlayerPrefs.HasKey(key) then
MessageId = CS.UnityEngine.PlayerPrefs.GetInt(key, MessageId)
end
return MessageId
end
-- 【聊天分频道】
function XChatManager.GetCurrentChatChannelId()
return CurrentChatChannelId
end
-- 切换聊天频道
function XChatManager.SelectChatChannel(channelId, succeedCb, failedCb)
if channelId == CurrentChatChannelId then return end
XNetwork.Call(MethodName.SelectChatChannelRequest, { ChannelId = channelId - 1 }, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
if failedCb then
failedCb()
end
return
end
CurrentChatChannelId = channelId
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_CHANNEL_CHANGED)
if succeedCb then
succeedCb()
end
end)
end
-- 登录初始化聊天频道
function XChatManager.InitChatChannel()
XNetwork.Call(MethodName.EnterWorldChatRequest, {}, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
return
end
CurrentChatChannelId = response.ChannelId + 1
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_CHANNEL_CHANGED)
end)
end
local RecruitChannelId = -1
-- 获取频道消息
function XChatManager.GetWorldChannelInfos(cb)
XNetwork.Call(MethodName.GetWorldChannelInfoRequest, {}, function(response)
if response.Code ~= XCode.Success then
XUiManager.TipCode(response.Code)
return
end
ChatChannelInfos = response.ChannelInfos
local lastIndex = #ChatChannelInfos
for index, v in pairs(ChatChannelInfos) do
v.ChannelId = v.ChannelId + 1
if index == lastIndex then v.IsRecruitChannel = true end
end
RecruitChannelId = lastIndex
if cb then
cb(ChatChannelInfos)
end
end)
end
function XChatManager.GetRecruitChannelId()
return RecruitChannelId
end
function XChatManager.GetAllChannelInfos()
return ChatChannelInfos
end
function XChatManager.OnChatChannelChanged(notifyData)
if not notifyData then return end
local notifyChannelId = notifyData.ChannelId + 1
if CurrentChatChannelId ~= notifyChannelId then
CurrentChatChannelId = notifyChannelId
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_SERVER_CHANNEL_CHANGED, notifyChannelId)
end
end
function XChatManager.UpdateGiftResetTime(resetTime)
TodayResetTime = resetTime
end
function XChatManager.CheckHasGift()
for _, chatInfo in pairs(PrivateChatMap) do
for _, chat in pairs(chatInfo.ChatMap) do
if chat.MsgType == ChatMsgType.Gift and chat.GiftStatus == ChatGiftState.WaitReceive and chat.SenderId ~= XPlayer.Id then
return true
end
end
end
return false
end
function XChatManager.UpdateGiftStatus()
for _, chatInfo in pairs(PrivateChatMap) do
for _, chat in pairs(chatInfo.ChatMap) do
if TodayResetTime > 0
and chat.MsgType == ChatMsgType.Gift
and chat.GiftStatus == ChatGiftState.WaitReceive
and chat.CreateTime < (TodayResetTime - ONE_DAY_SECONDS) then
chat.GiftStatus = ChatGiftState.Fetched
end
end
end
end
-- 创建礼物文本
function XChatManager.CreateGiftTips(chatData)
if not chatData then
return ""
end
-- 发礼物提示
if chatData.GiftStatus == ChatGiftState.WaitReceive then
if chatData.SenderId == XPlayer.Id then
local friend = XDataCenter.SocialManager.GetFriendInfo(chatData.TargetId)
if friend then
local name = XDataCenter.SocialManager.GetPlayerRemark(chatData.TargetId, chatData.NickName)
return CS.XTextManager.GetText("GiftMoneySendNotReceive", name, chatData.GiftCount)
end
else
local name = XDataCenter.SocialManager.GetPlayerRemark(chatData.SenderId, chatData.NickName)
return CS.XTextManager.GetText("GiftMoneyReceiveNotReceive", name, chatData.GiftCount)
end
-- 领礼物提示
elseif chatData.GiftStatus == ChatGiftState.Received then
-- 自己领礼物
if chatData.SenderId ~= XPlayer.Id then
local friend = XDataCenter.SocialManager.GetFriendInfo(chatData.SenderId)
local name = XDataCenter.SocialManager.GetPlayerRemark(chatData.SenderId, chatData.NickName)
if friend then
return CS.XTextManager.GetText("GiftMoneyReceiveHaveReceive", name, chatData.GiftCount)
else
return CS.XTextManager.GetText("GiftMoneyReceiveHaveReceive", "", chatData.GiftCount)
end
else
-- 别人领礼物
local friend = XDataCenter.SocialManager.GetFriendInfo(chatData.TargetId)
local name = XDataCenter.SocialManager.GetPlayerRemark(chatData.TargetId, chatData.NickName)
if friend then
return CS.XTextManager.GetText("GiftMoneySendHaveReceive", name, chatData.GiftCount)
end
end
end
return ""
end
function XChatManager.ProcessExtraContent(chatData)
if not chatData then
return
end
local customContent = XMessagePack.Decode(chatData.CustomContent)
if not customContent then
return
end
if string.find(chatData.Content, "room") then
chatData.Content = string.gsub(chatData.Content, "room", customContent)
end
end
function XChatManager.NotifyChatMessage(chatData)
XChatManager.ProcessExtraContent(chatData)
XChatManager.OnSynChat(chatData)
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_MSG_SYNC)
end
function XChatManager.NotifyPrivateChat(chatData)
if not chatData or not chatData.ChatMessages then
return
end
if XDataCenter.SocialManager.GetBlackData(chatData.SenderId) then
return
end
local lastChatMsg
for _, chatMsg in ipairs(chatData.ChatMessages) do
lastChatMsg = XChatData.New(chatMsg)
XChatManager.ProcessExtraContent(chatMsg)
XChatManager.OnSynChat(chatMsg, true)
end
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_MSG_SYNC)
if lastChatMsg then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_PRIVATECHAT, lastChatMsg)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_PRIVATECHAT, lastChatMsg)
end
end
function XChatManager.NotifyWorldChat(chatData)
if not chatData or not chatData.ChatMessages then
return
end
local lastChatMsg
for _, chatMsg in ipairs(chatData.ChatMessages) do
if not XDataCenter.SocialManager.GetBlackData(chatMsg.SenderId) then
XChatManager.ProcessExtraContent(chatMsg)
lastChatMsg = XChatData.New(chatMsg)
HandleWorldChat(lastChatMsg)
end
end
if lastChatMsg then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_WORLD_MSG, lastChatMsg)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_WORLD_MSG, lastChatMsg)
end
end
function XChatManager.NotifyMentorChat(chatData)
if not chatData or not chatData.ChatMessages then
return
end
local lastChatMsg
for _, chatMsg in ipairs(chatData.ChatMessages) do
XChatManager.ProcessExtraContent(chatMsg)
lastChatMsg = XChatData.New(chatMsg)
HandleMentorChat(lastChatMsg)
end
if lastChatMsg then
XEventManager.DispatchEvent(XEventId.EVENT_CHAT_RECEIVE_MENTOR_MSG, lastChatMsg)
CsXGameEventManager.Instance:Notify(XEventId.EVENT_CHAT_RECEIVE_MENTOR_MSG, lastChatMsg)
end
end
function XChatManager.NotifyChatEmoji(emojiData)
if not emojiData.Emoji then
return
end
EmojiDatasDic[emojiData.Emoji.Id] = XChatEmoji.New(emojiData.Emoji)
end
function XChatManager.NotifyChatLoginData(loginData)
TodayResetTime = loginData.RefreshTime
for __, v in pairs(loginData.UnlockEmojis) do
EmojiDatasDic[v.Id] = XChatEmoji.New(v)
end
end
XChatManager.Init()
return XChatManager
end
--同步聊天
XRpc.NotifyChatMessage = function(chatData)
XDataCenter.ChatManager.NotifyChatMessage(chatData)
end
XRpc.NotifyPrivateChat = function(chatData)
XDataCenter.ChatManager.NotifyPrivateChat(chatData)
end
XRpc.NotifyTodayGiftResetTime = function(notifyData)
XDataCenter.ChatManager.UpdateGiftResetTime(notifyData.ResetTime)
end
XRpc.NotifyWorldChat = function(chatData)
XDataCenter.ChatManager.NotifyWorldChat(chatData)
end
XRpc.NotifyMentorChat = function(chatData)
XDataCenter.ChatManager.NotifyMentorChat(chatData)
end
-- 聊天频道切换
XRpc.NotifyChatChannelChange = function(notifyData)
XDataCenter.ChatManager.OnChatChannelChanged(notifyData)
end
XRpc.NotifyChatLoginData = function(loginData)
XDataCenter.ChatManager.NotifyChatLoginData(loginData)
end
XRpc.NotifyChatEmoji = function(emojiData)
XDataCenter.ChatManager.NotifyChatEmoji(emojiData)
end