local skynet = require "skynet" local oo = require "Class" local log = require "Log" local pb = require "pb" local dataType = require "DataType" local errorInfo = require "ErrorInfo" local json = require "json" local common = require "Common" local Announcement = oo.class() Announcement.AnnouncementOpType_1 = 1 --获取公告列表 Announcement.AnnouncementOpStatus_Suc = 1 --操作状态成功 Announcement.AnnouncementOpStatus_NoAnnouncementID = 2 --不存在该公告ID Announcement.EventAnnouncement = 1 --活动公告 Announcement.UpdateAnnouncement = 2 --更新公告 Announcement.PeripheralAnnouncement = 3 --周边公告 Announcement.NextAnnouncement = 4 --下次预告 Announcement.MaxSendCount = 100 --一次发送最大数量 function Announcement:Init() self.announcementList = {} end --每5秒调一次 function Announcement:On5SecTimer() self:BatchSend() end --从后台刷新公告列表 function Announcement:RefreshAnnouncementList() --向后端请求 local param = {} local web = skynet.server.gameConfig.WebConfig.host .. ":" .. skynet.server.gameConfig.WebConfig.port local url = skynet.server.common.getAnnouncementUrl local status, body = skynet.server.httpClient:PostJson(web, url, json:encode(param), "http") if 200 == status then -- newbody 即后台的 ResultModel local newbody = json:decode(body) if 200 == newbody.code then --判断旧的公告是否还能继续使用 if next(Announcement.announcementList)~=nil then for k ,v in pairs(Announcement.announcementList) do local canGet = false for k1, v1 in pairs(newbody.data) do if v.announcementId==v1.id then canGet = true break end end v.canGet = canGet end end --添加新的公告 for k, v in pairs(newbody.data) do local announcementId = v.id if not Announcement.announcementList[announcementId] then Announcement.announcementList[announcementId] = {} local curAnnounce = Announcement.announcementList[announcementId] curAnnounce.announcementId = announcementId curAnnounce.status = dataType.AnnouncementStatus_NoGet curAnnounce.announcementRemarks = v.remarks curAnnounce.announcementWeight = v.weight curAnnounce.title = v.announcementTitle curAnnounce.content = v.announcementText curAnnounce.receiveTime = skynet.GetTime()--skynet.server.common:GetStrTime(skynet.GetTime()) curAnnounce.announcementType = v.announcementType curAnnounce.canGet = true curAnnounce.isSendAllOnlineUser = false --是否发送所有在线玩家 --只显示一张图片 if v.img then curAnnounce.image = v.img[1] end --Announcement:SendAnnouncementToOnlineUser(announcementId, v) end end elseif 802 == newbody.code then --s2cData.code = errorInfo.ErrorCode.AlreadyGet --将所有公告的获取状态修改为不可获取 if next(Announcement.announcementList)~=nil then for k ,v in pairs(Announcement.announcementList) do v.canGet = false end end end else log.info("公告刷新 获取数据失败 status ", status or 0) end end --公告历史 function Announcement:History(player, c2sData, s2cData) c2sData.data = assert(pb.decode("C2SAnnouncementHistory", c2sData.data)) local data = {} data.announcementInfo = {} for k, v in pairs(player.gameData.announcement.historyAnnouncement) do for k1 , v1 in pairs(Announcement.announcementList) do if v1.canGet then for k2 ,v2 in pairs(player.gameData.announcement.announcementList) do if v==k1 and v2.announcementId == v and not v2.look then table.insert(data.announcementInfo ,v1) if v1.announcementType == Announcement.EventAnnouncement then skynet.server.msgTips:Reduce(player , 44) v2.look = true elseif v1.announcementType == Announcement.UpdateAnnouncement then skynet.server.msgTips:Reduce(player , 45) v2.look = true elseif v1.announcementType == Announcement.PeripheralAnnouncement then skynet.server.msgTips:Reduce(player , 46) v2.look = true elseif v1.announcementType == Announcement.NextAnnouncement then skynet.server.msgTips:Reduce(player , 47) v2.look = true end elseif v==k1 and v2.announcementId ==v and v2.look then table.insert(data.announcementInfo ,v1) end end end end end s2cData.cmd = pb.enum("MsgType", "CMD_S2C_AnnouncementHistory") s2cData.data = assert(pb.encode("S2CAnnouncementHistory", data)) end --发送新公告给在线玩家 function Announcement:SendAnnouncementToOnlineUser(announcementId, announcementInfo) local playerList = skynet.server.playerCenter:GetPlayerList() local t1 = skynet.GetTime() local count = 0 --给在线玩家发送新公告 for userId, value in pairs(playerList) do if skynet.server.playerCenter.Status_Playing == value.status then Announcement:AddAnnouncement(value.player, announcementId, announcementInfo) count = count + 1 end end log.info(string.format("公告板 全玩家发送公告 发送数量 %d 时间花费 %d ", count, skynet.GetTime() - t1)) end --添加公告 function Announcement:AddAnnouncement(player, announcementId, announcementInfo) --玩家已经存在该公告了,不再发送 if Announcement:IsExist(player, announcementId) then return true end --[[ --玩家的APP版本是否符合 if self.basicInfo.appVersion < AnnouncementInfo.appVersion then return end --玩家的渠道是否符合 if self.basicInfo.channel ~= AnnouncementInfo.channel and "all" ~= AnnouncementInfo.channel then return end --玩家的系统不符也不发 if self.basicInfo.platform ~= AnnouncementInfo.operatingSystem and "all" ~= AnnouncementInfo.operatingSystem then return end ]] local announcement = player.gameData.announcement local curIndex = announcement.curIndex announcement.announcementList[curIndex] = {} announcement.announcementList[curIndex].announcementId = announcementId announcement.announcementList[curIndex].look = false --announcement.announcementList[curIndex].status = dataType.AnnouncementStatus_NoGet --announcement.announcementList[curIndex].AnnouncementRemarks = AnnouncementInfo.remarks --announcement.announcementList[curIndex].AnnouncementWeight = AnnouncementInfo.weight --announcement.announcementList[curIndex].title = AnnouncementInfo.announcementTitle --announcement.announcementList[curIndex].content = AnnouncementInfo.announcementText --announcement.announcementList[curIndex].receiveTime = skynet.GetTime()--skynet.server.common:GetStrTime(skynet.GetTime()) --announcement.announcementList[curIndex].announcementType = AnnouncementInfo.announcementType --插入玩家收到过的公告ID table.insert(announcement.historyAnnouncement, announcementId) --玩家最多30条最近的公告记录 announcement.curIndex = announcement.curIndex + 1 if announcement.curIndex >= 30 then announcement.curIndex = 1 end --打包数据给客户端 local data = {} data.announcementInfo = {} table.insert(data.announcementInfo , announcementInfo) skynet.server.gameServer:SendMsgToUser(player.userId, "CMD_S2C_AnnouncementNew", data) log.info(string.format("玩家 %d 公告版 新增公告 ID %s ", player.userId, announcementId)) end --检查玩家是否有新公告 function Announcement:CheckNewAnnouncement(player) --重置公告红点 skynet.server.msgTips:Reset(player , 44) skynet.server.msgTips:Reset(player , 45) skynet.server.msgTips:Reset(player , 46) skynet.server.msgTips:Reset(player , 47) for k, v in pairs(Announcement.announcementList) do if not Announcement:IsExist(player, k) and v.canGet then Announcement:AddAnnouncement(player, k, v) end end --红点系统 if next(player.gameData.announcement.announcementList) ~= nil then for k , v in pairs(player.gameData.announcement.announcementList) do -- 如果玩家有未查看到的公告则添加对应的红点 if not v.look then for k1 , v1 in pairs(Announcement.announcementList) do --添加对应红点 判断一下公告类型 if v.announcementId==v1.announcementId and v1.announcementType == Announcement.EventAnnouncement and not v.look then skynet.server.msgTips:Add(player , 44) elseif v.announcementId==v1.announcementId and v1.announcementType == Announcement.UpdateAnnouncement and not v.look then skynet.server.msgTips:Add(player , 45) elseif v.announcementId==v1.announcementId and v1.announcementType == Announcement.PeripheralAnnouncement and not v.look then skynet.server.msgTips:Add(player , 46) elseif v.announcementId==v1.announcementId and v1.announcementType == Announcement.NextAnnouncement and not v.look then skynet.server.msgTips:Add(player , 47) end end end end end end --是否存在公告 function Announcement:IsExist(player, announcementId) for k, v in pairs(player.gameData.announcement.historyAnnouncement) do if announcementId == v then return true end end return false end --批量发送公告 function Announcement:BatchSend() local t1 = skynet.GetTime() local playerList = skynet.server.playerCenter:GetPlayerList() local sendCount = 0 --此次发送邮件数量 local isSendMail = true --是否继续发送邮件 for announceId, v1 in pairs( self.announcementList ) do local count = 0 if self.MailType_AllServer == v1.mailType and v1.canGet and not v1.isSendAllOnlineUser then --全服邮件 能发送 并且未发送完 for userId, value in pairs(playerList) do if skynet.server.playerCenter.Status_Playing == value.status and not value.onlineAnnounceList[ announceId ] then --在线玩家并且未接收该邮件 self:AddAnnouncement(value.player, announceId, v1) value.onlineAnnounceList[ announceId ] = true count = count + 1 sendCount = sendCount + 1 if sendCount >= self.MaxSendCount then isSendMail = false break end end end if 0 == count then v1.isSendAllOnlineUser = true log.info(string.format("公告 全服公告 %s 在线已发送结束 ", announceId )) else log.info(string.format("公告 全服公告 %s 发送 发送数量 %d 时间花费 %d ", announceId , count, skynet.GetTime() - t1)) end end if not isSendMail then break end end end --相当于单例 skynet.server.announcement = Announcement return Announcement