local _isDebug = false local specialConfig=ConfigManager.GetConfig(ConfigName.SpecialConfig) local function __DebugLog(str) if _isDebug then Log("" .. str .. "") end end ChatManager = {} local this = ChatManager -- 定时刷新时间 local _DeltaTime = 5 -- 定时刷新数据的通道枚举 local _CHANNEL = { CHAT_CHANNEL.SYSTEM, -- 系统 CHAT_CHANNEL.FAMILY, -- CHAT_CHANNEL.GLOBAL, -- 世界 CHAT_CHANNEL.JUMP_SERVER,-- 跨服 } this.SYS_MSG_TYPE = { [0] = {name = Language[10350]}, [1] = {name = Language[10351]}, [2] = {name = Language[10352]}, [9] = {name = Language[10352]} } -- 聊天中要显示时间的时间间隔(毫秒) this.ShowTimeDT = 300000 --初始化 function this.Initialize() -- 记录玩家上线的时间,小于这个时间的聊天消息(出好友外)不显示(毫秒) this.LoginTimeStamp = 0 -- 数据 this.ChatList = {} this.FriendChatList = {} -- msgId标志位,用于记录当前最新消息的消息号,刷新时按此消息号进行数据刷新 this.MsgIdFlag = {} -- 我在世界发言中的时间冷却 this.MyChatTimeStamp = 0 -- 判断是否正在获取聊天信息(避免请求后台运行时请求积累) this.IsGetMsg = 0 --跑马灯的速度(1秒移动的像素) this.horseRunSpeed=tonumber(specialConfig[31].Value) -- 跨服状态改变,清空跨服聊天 Game.GlobalEvent:AddEvent(GameEvent.JumpServerHeightLadder.CrossStateChange, function() this.SetMsgIdFlag(CHAT_CHANNEL.JUMP_SERVER, 0) this.ChatList[CHAT_CHANNEL.JUMP_SERVER] = {} NetManager.RequestChatMsg(CHAT_CHANNEL.JUMP_SERVER, 0, function(data) this.ChatDataAdapter(CHAT_CHANNEL.JUMP_SERVER, data) end) end) end -- 每两秒刷新一次数据 function this.TimeUpdate() if this.IsGetMsg > 0 then return end -- 不包括好友数据 for _, channel in pairs(_CHANNEL) do local isOpen = this.IsChannelOpen(channel) if isOpen then local msgId = this.GetMsgIdFlag(channel) this.IsGetMsg = this.IsGetMsg + 1 NetManager.RequestChatMsg(channel, msgId, function(data) this.IsGetMsg = this.IsGetMsg - 1 this.ChatDataAdapter(channel, data) end) end end -- 刷新主界面消息 this.RefreshMainPanelShowMsg() end -- 聊天界面开启之后开始计时 -- 开始刷新聊天数据 function this.StartChatDataUpdate() -- 开始定时刷新 if not this._CountDownTimer then this._CountDownTimer = Timer.New(this.TimeUpdate, _DeltaTime, -1, true) this._CountDownTimer:Start() end end --关闭聊天数据刷新 function this.StopChatDataUpdate() -- -- 关闭定时刷新 -- if this._CountDownTimer then -- this._CountDownTimer:Stop() -- this._CountDownTimer = nil -- end end -- 聊天通达是否开启 function this.IsChannelOpen(channel) if channel == CHAT_CHANNEL.FAMILY then local isOpen = ActTimeCtrlManager.SingleFuncState(FUNCTION_OPEN_TYPE.GUILD) if not isOpen then return false, ActTimeCtrlManager.SystemOpenTip(FUNCTION_OPEN_TYPE.GUILD) end if isOpen and PlayerManager.familyId == 0 then return false, Language[10370] end elseif channel == CHAT_CHANNEL.JUMP_SERVER then -- 开服前七天, 未跨服都显示未跨服 if not CheckFunctionOpen(FUNCTION_OPEN_TYPE.CROSS_CART) or PlayerManager.isCross == 0 then return false, "未划分跨服分组" end end return true end -- 公会聊天数据由服务器推送 function this.ReceiveFamilyChat(msg) if msg.type ~= 2 then return end local info = msg.chatInfo this.ChatDataAdapter(CHAT_CHANNEL.FAMILY, {chatInfo = {info}}) end -- 初始化数据 function this.InitData(func) -- 保存当前时间 this.LoginTimeStamp = GetTimeStamp() * 1000 -- 第一次获取数据 local index = 0 local maxIndex = 0 local function serverCB(channel, data) -- 保存服务器数据 this.ChatDataAdapter(channel, data) index = index + 1 if index >= maxIndex then -- 刷新主界面消息 this.RefreshMainPanelShowMsg() -- 执行回调 if func then func() end end end -- 开始发送请求 for _, channel in pairs(_CHANNEL) do local isOpen = this.IsChannelOpen(channel) if isOpen then maxIndex = maxIndex + 1 NetManager.RequestChatMsg(channel, 0, function(data) serverCB(channel, data) end) end end end -- 聊天界面发送消息 function this.RequestSendChatMsg(channel, content, func) -- 好友消息不能通过此接口发送 if CHAT_CHANNEL.FRIEND == channel then return end -- 限制发言等级 if not ActTimeCtrlManager.SingleFuncState(FUNCTION_OPEN_TYPE.CHAT) then PopupTipPanel.ShowTip(Language[10353]) return end -- 消息正确性检测 if string.len(content) <= 0 then PopupTipPanel.ShowTip(Language[10354]) return end -- 世界发言冷却时间 if channel == CHAT_CHANNEL.GLOBAL or channel == CHAT_CHANNEL.JUMP_SERVER then local curTimeStamp = GetTimeStamp() if curTimeStamp - this.MyChatTimeStamp < 3 then PopupTipPanel.ShowTip(Language[10355]) return end this.MyChatTimeStamp = curTimeStamp -- 世界发言消息特殊处理 content = string.format("%d|%s", GLOBAL_CHAT_TYPE.COMMON, content) elseif channel == CHAT_CHANNEL.FAMILY then -- 公会发言消息特殊处理 content = string.format("%d|%s", GLOBAL_CHAT_TYPE.COMMON, content) end -- 检测屏蔽字(改为后端检测) -- 发送消息 NetManager.RequestSendChatMsg(channel, content, 0, function(msg) local msgId = this.GetMsgIdFlag(channel) -- 获取当前最新消息的消息号 --- messageId ~= 0 表示发送的消息包含屏蔽字段,该消息不会被广播,但是发送者在世界聊天中可以看到自己的消息 --- 所以我们需要在前端保存这条消息,但是消息号设置为上一条的消息号,以保证在获取以后的数据时不会丢失数据。 if msg.chatInfo.messageId ~= 0 then msg.chatInfo.messageId = -1 local data = { chatInfo = {msg.chatInfo} } __DebugLog(Language[10356]) this.ChatDataAdapter(channel, data) if func then func() end else __DebugLog(Language[10357]) -- if channel == CHAT_CHANNEL.FAMILY then -- if func then func() end -- else NetManager.RequestChatMsg(channel, msgId, function(data) this.ChatDataAdapter(channel, data) if func then func() end end) -- end end end) end -- function this.RequestGMCommand(command, func) -- 世界发言消息特殊处理 local content = string.format("%d|%s", GLOBAL_CHAT_TYPE.COMMON, command) -- 请求发送 NetManager.RequestSendChatMsg(CHAT_CHANNEL.GLOBAL, content, 0, function(msg) PopupTipPanel.ShowTip(Language[10358]) if func then func() end end) end -- 设置相应通道的消息的最新消息号 function this.SetMsgIdFlag(channel, msgId) if not this.MsgIdFlag then this.MsgIdFlag = {} end this.MsgIdFlag[channel] = msgId end -- 获取最新消息号 function this.GetMsgIdFlag(channel) if not this.MsgIdFlag then this.MsgIdFlag = {} end return this.MsgIdFlag[channel] or 0 end -- 数据处理 function this.ChatDataAdapter(channel, data) __DebugLog("ChatDataAdapter++++++++++++++++++++++++++++++"..channel) -- 好友数据特殊处理 if channel == CHAT_CHANNEL.FRIEND then return end -- 先对数据排个序 table.sort(data.chatInfo, function(a, b) return a.times < b.times end) -- 初始化 if not this.ChatList[channel] then this.ChatList[channel] = {} end -- 数据没有变化,则不刷新 local len = #data.chatInfo if len == 0 then return end --- 判断messageId是否符合要求,新数据得第一条messageId必须比旧数据最后一条大, --- mssageId相等表示包含敏感字未发出的消息,此消息需要在前端展示,但是不会发送给其他人 --__DebugLog("++++++++++++++++++++++++++++++"..channel) for i = 1, len do local newChat = data.chatInfo[i] local newMsgId = tonumber(newChat.messageId) -- 新消息的消息号 local msgIdFlag = this.GetMsgIdFlag(channel) -- 获取当前最新消息号 __DebugLog("消息内容:"..newChat.msg) __DebugLog("消息类型:"..newChat.messageType) __DebugLog("本地最新消息"..msgIdFlag..",新消息的消息号:"..newMsgId) local msgStr = string.split(newChat.msg,"|") if channel == CHAT_CHANNEL.SYSTEM then for i = 2, #msgStr do --1 需要翻译 local oneStr = string.sub(msgStr[i],1,1) if tonumber(oneStr) == 1 then msgStr[i] = tostring(string.sub(msgStr[i],2)) msgStr[i] = GetLanguageStrById(msgStr[i]) else msgStr[i] = tostring(string.sub(msgStr[i],2)) end end newChat.msg = string.format( GetLanguageStrById(msgStr[1]), tostring(msgStr[2]), tostring(msgStr[3]), tostring(msgStr[4]), tostring(msgStr[5]), tostring(msgStr[6]) ) elseif channel == CHAT_CHANNEL.FAMILY then local msgs = string.split(newChat.msg,"#") -- 公会红包的消息需要处理一下 local msgType = tonumber(msgs[1]) if msgType == GLOBAL_CHAT_TYPE.GUILD_REDPACKET then if tonumber(newChat.times) > this.LoginTimeStamp then -- 公会红包暂时不再显示跑马灯 -- newChat.msg = this.AnalysisGlobalChat(newChat.msg).content -- newChat.messageType = 8 -- 公会红包的类型 -- newChat.speed = this.horseRunSpeed -- newChat.multiple = 1 if PlayerManager.uid~=tonumber(msgs[2]) then __DebugLog("处理聊天数据") GuildRedPacketManager.isCheck = true --MyGuildManager.PackageNum=MyGuildManager.PackageNum+1 --CheckRedPointStatus(RedPointType.Guild_RedPacket) --CheckRedPointStatus(RedPointType.Guid_GetPackage) MyGuildManager.ReuqsetRedPackage() end end end end __DebugLog("消息内容:"..newChat.msg) if msgIdFlag < newMsgId or newMsgId == -1 then if newMsgId ~= -1 then -- 消息号为-1表示屏蔽消息,保存数据但不保存消息号, this.SetMsgIdFlag(channel, newMsgId) -- 保存当前消息的消息号,避免下次刷新时还会请求 end if channel ~= CHAT_CHANNEL.SYSTEM or tonumber(newChat.times) > this.LoginTimeStamp then -- 登录时间之前的系统消息都不显示 if channel ~= CHAT_CHANNEL.SYSTEM or this.IsShowInChatPanel(newChat.messageType) then if not GoodFriendManager.IsInBlackList(newChat.senderId) then -- 判断是否在黑名单中 table.insert(this.ChatList[channel], newChat) if #this.ChatList[channel] >= PUBLIC_CHAT_MAX_NUM then -- 判断如果超出最大数量,删除最早得数据 table.remove(this.ChatList[channel], 1) end end end -- 跑马灯数据,保存到跑马灯管理器中 if this.IsShowInHorseRace(newChat.messageType) then __DebugLog("显示跑马灯:"..newChat.msg) HorseRaceManager.AddRaceData(newChat) end end end __DebugLog("--") end __DebugLog("++++++++++++++++++++++++++++++"..channel) -- 更新事件 Game.GlobalEvent:DispatchEvent(GameEvent.Chat.OnChatDataChanged, channel) end -- 获取好友聊天列表 function this.GetFriendChatChannelList() local list = {} local friendChatList = FriendChatManager.GetAllChatList() for friendId, chatList in pairs(friendChatList) do if GoodFriendManager.IsMyFriend(friendId) then -- 获取最后一条数据 local chat = chatList[#chatList] -- 我发的消息前面加一个我 local content = chat.msg if chat.senderId == PlayerManager.uid then content = Language[10364]..content end local data = { friendId = friendId, content = content, times = chat.times } table.insert(list, data) end end -- 先对数据排个序 table.sort(list, function(a, b) return a.times > b.times end) return list end -- 获取数据 function this.GetChatList(channel) -- 好友 if channel == CHAT_CHANNEL.FRIEND then return this.GetFriendChatChannelList() end return this.ChatList[channel] or {} end -- 刷新主界面显示的消息 this._MainPanelChat = nil local _MainChatList = { CHAT_CHANNEL.GLOBAL, CHAT_CHANNEL.SYSTEM, CHAT_CHANNEL.FAMILY, CHAT_CHANNEL.JUMP_SERVER, } function this.RefreshMainPanelShowMsg() -- 获取当前应该显示的数据 local channel = nil local msg = nil for _, cnl in pairs(_MainChatList) do local isOpen = this.IsChannelOpen(cnl) if isOpen then local chatList = this.GetChatList(cnl) local chat = chatList[#chatList] if chat then if not msg or msg.times < chat.times then channel = cnl msg = chat end end end end -- 没有要显示的数据 if not msg then return end -- 保存数据 this._MainPanelChat = { channel = channel, chat = msg } -- 发送事件刷新 Game.GlobalEvent:DispatchEvent(GameEvent.Chat.OnMainChatChanged) end -- 获取主界面显示的消息 function this.GetMainPanelShowMsg() return this._MainPanelChat end -- 请求发送公会邀请 function this.RequestSendGuildInvite(func) if not PlayerManager.familyId then return end -- 判断是否在冷却 local _CurTimeStamp = GetTimeStamp() if this._GuildInviteTimeStamp and _CurTimeStamp - this._GuildInviteTimeStamp < GUILD_INVITE_CD then local cd = math.floor(GUILD_INVITE_CD - (_CurTimeStamp - this._GuildInviteTimeStamp)) PopupTipPanel.ShowTip(cd..Language[10365]) return end -- 构建字符串 local channel = CHAT_CHANNEL.GLOBAL local guildData = MyGuildManager.GetMyGuildInfo() local content = string.format( "%d#%d#%d#%s#%d#%d|", GLOBAL_CHAT_TYPE.GUILD_INVITE, PlayerManager.familyId, guildData.levle, guildData.name, guildData.playerIntoLevel, guildData.joinType ) -- 发送消息 NetManager.RequestSendChatMsg(channel, content, 0, function() local msgId = this.GetMsgIdFlag(channel) NetManager.RequestChatMsg(channel, msgId, function(data) this.ChatDataAdapter(channel, data) if func then func() end end) this._GuildInviteTimeStamp = GetTimeStamp() end) end -- 请求发送公会援助邀请 function this.RequestSendGuildAid(itemId1,itemId2,func) if not PlayerManager.familyId then return end -- 构建字符串 local channel = CHAT_CHANNEL.FAMILY local guildData = MyGuildManager.GetMyGuildInfo() local content = "" if itemId2 then content = string.format("%s#%s#%s#%s#%s#%s", (ConfigManager.GetConfigData(ConfigName.ErrorCodeHint,121).Desc), PlayerManager.nickName, (ConfigManager.GetConfigData(ConfigName.ItemConfig,itemId1).Name), tostring(ConfigManager.GetConfigData(ConfigName.GuildHelpConfig,1).RecourseTime[2]), (ConfigManager.GetConfigData(ConfigName.ItemConfig,itemId2).Name), tostring(ConfigManager.GetConfigData(ConfigName.GuildHelpConfig,1).RecourseTime[2]) ) else content = string.format("%s#%s#%s#%s", (ConfigManager.GetConfigData(ConfigName.ErrorCodeHint,120).Desc), PlayerManager.nickName, (ConfigManager.GetConfigData(ConfigName.ItemConfig,itemId1).Name), tostring(ConfigManager.GetConfigData(ConfigName.GuildHelpConfig,1).RecourseTime[2]) ) end content = string.format( "%d#%s", GLOBAL_CHAT_TYPE.GUILD_AID, content ) -- 发送消息 NetManager.RequestSendChatMsg(channel, content, 0, function() local msgId = this.GetMsgIdFlag(channel) NetManager.RequestChatMsg(channel, msgId, function(data) if func then func() end end) end) end -- 请求发送公会副本 function this.RequestSendGuildTranscript(func) if not PlayerManager.familyId then return end -- 构建字符串 local channel = CHAT_CHANNEL.FAMILY local guildData = MyGuildManager.GetMyGuildInfo() local content = string.format( GetLanguageStrById(Language[10314]), PlayerManager.nickName) this.RequestSendChatMsg(channel, content, function() end) end -- 请求发送公会红包信息 function this.RequestSendRedPacket(curIndex,func) local redpack=ConfigManager.GetConfigData(ConfigName.GuildRedPackConfig,curIndex) if not PlayerManager.familyId then return end -- 构建字符串 local channel = CHAT_CHANNEL.FAMILY local content = string.format( "%d#%s#%s",--"%d#%d#%d#%s#%d#%d|", GLOBAL_CHAT_TYPE.GUILD_REDPACKET, PlayerManager.nickName, redpack.Name ) -- 发送消息 NetManager.RequestSendChatMsg(channel, content, 0, function() local msgId = this.GetMsgIdFlag(channel) NetManager.RequestChatMsg(channel, msgId, function(data) if func then func() end end) end) end -- 解析世界聊天数据 function this.AnalysisGlobalChat(msg) local chat = {} local msgList = string.split(msg, "|") local headStr = table.remove(msgList, 1) local headList = string.split(headStr, "#") chat.type = tonumber(headList[1]) if chat.type == GLOBAL_CHAT_TYPE.COMMON then chat.content = table.concat(msgList, "|") elseif chat.type == GLOBAL_CHAT_TYPE.GUILD_INVITE then chat.gId = tonumber(headList[2]) chat.gLv = tonumber(headList[3]) chat.gName = headList[4] chat.gLimitLv = tonumber(headList[5]) chat.joinType = tonumber(headList[6]) chat.content = string.format( GetLanguageStrById(Language[12238]), chat.gLv, chat.gName, chat.gLimitLv) elseif chat.type==GLOBAL_CHAT_TYPE.GUILD_REDPACKET then chat.nickName=headList[2] chat.redpackName=GetLanguageStrById(headList[3]) chat.content = string.format( GetLanguageStrById(Language[12239]), chat.nickName, chat.redpackName) elseif chat.type==GLOBAL_CHAT_TYPE.GUILD_AID then --chat.content = headList[2] chat.content = string.format(GetLanguageStrById(headList[2]), GetLanguageStrById(tostring(headList[3])), GetLanguageStrById(tostring(headList[4])), GetLanguageStrById(tostring(headList[5])), GetLanguageStrById(tostring(headList[6])), GetLanguageStrById(tostring(headList[7])), GetLanguageStrById(tostring(headList[8])) ) end return chat end -- 判断是否需要在聊天中显示 function this.IsShowInChatPanel(msgType) local config = ConfigManager.TryGetConfigDataByKey(ConfigName.SystemMessageConfig, "Type", msgType) if not config then return false end return config.SystemShow == 1 end -- 判断是否需要在跑马灯中显示 function this.IsShowInHorseRace(msgType) local config = ConfigManager.TryGetConfigDataByKey(ConfigName.SystemMessageConfig, "Type", msgType) if not config then return false end return config.lanternShow == 1 end return this