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 activity = require "Activity" local json =require "json" local redisKeyUrl = require "RedisKeyUrl" local Subscribe = oo.class() --初始时间戳 local initTime = 0 --构造函数 function Subscribe:Init() end -- 每次登录需要进行修改的数据 function Subscribe:LoginInitData(player) --初始化内存 if player.gameData.subscribe == nil then player.gameData.subscribe={ isDrawRewardAll = false , isDrawRewardAllTime = os.time()} end --处理重置时间 if not skynet.server.common:IsSameDay(os.time(),player.gameData.subscribe.isDrawRewardAllTime) then --修改奖励为已发送 player.gameData.subscribe.isDrawRewardAll = false player.gameData.subscribe.isDrawRewardAllTime = os.time() end --取消订阅推送 self:UpdateOnlineTime( player , 1) end --获取订阅消息信息 function Subscribe:GetSubscribeInfo(player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SSubscribeGetSubscribeInfo", c2sData.data )) s2cData.cmd = pb.enum("MsgType","CMD_S2C_SubscribeGetSubscribeInfo") --参数 local subscribeType = c2sData.data.subscribeType --返回信息 local data =self:GetPlayerSubscribeInfo(player,subscribeType) s2cData.data = assert(pb.encode("S2CSubscribeGetSubscribeInfo", data)) end --获取玩家订阅数据,subscribeType 类型,1 微信,。。。 function Subscribe:GetPlayerSubscribeInfo(player,subscribeType) local data = {} data.subscribeInfo={} --获取已订阅的数据,这里直接取redis里面的数据(订阅信息只存redis) local redisKey = string.format(redisKeyUrl.ThirdSubscribe, player.account) --获取订阅信息 local subscribeDataStr = skynet.server.redis:hget(redisKey,subscribeType) --存在订阅信息 if subscribeDataStr ~= nil then --反序列化 local subscribeData = json:decode(subscribeDataStr) if subscribeData == nil or next(subscribeData) == nil then log.debug(string.format("微信订阅序列号错误,redisKey:%s,subscribeType:%s,subscribeData:%s",redisKey,tostring(subscribeType),subscribeDataStr)) return data end for key, value in pairs(subscribeData) do --是否未过期 if value.expireTime > os.time() or value.expireTime == 0 then local subscribe = {} subscribe.subscribeId = value.subscribeId if value.subscribeStatus == 2 then--已推送,这里显示成已订阅 subscribe.subscribeStatus = 1 else subscribe.subscribeStatus = value.subscribeStatus end table.insert(data.subscribeInfo, subscribe) end end else log.debug(string.format("微信订阅不存在任何订阅信息,redisKey:%s,subscribeType:%s",redisKey,tostring(subscribeType))) end --是否领取所有订阅奖励 data.isDrawRewardAll=(player.gameData.subscribe ~= nil and player.gameData.subscribe.isDrawRewardAll ~= nil and player.gameData.subscribe.isDrawRewardAll) and true or false return data end --table去重 function RemoveRepeat(t) local unique={} for _, value in ipairs(t) do unique[value] = true end local newt={} for index,_ in pairs(unique) do table.insert(newt,index) end return newt end --订阅消息 function Subscribe:SubscribeMsg(player , c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SSubscribeSubscribeMsg", c2sData.data )) s2cData.cmd = pb.enum("MsgType","CMD_S2C_SubscribeSubscribeMsg") --参数 local subscribeType = c2sData.data.subscribeType local subscribeIdList = c2sData.data.subscribeIdList local uniqueId = c2sData.data.uniqueId local isAllSubscribe = c2sData.data.isAllSubscribe --subscribeIdList去重复 subscribeIdList = RemoveRepeat(subscribeIdList) --返回信息 local data = {} --订阅状态 1 订阅成功,2 订阅失败 data.subscribeStatus = 2 data.subscribeIdList = subscribeIdList --判断参数 if subscribeType == nil or subscribeIdList == nil or next(subscribeIdList) ==nil or uniqueId == nil then log.debug("参数错误") s2cData.code = errorInfo.ErrorCode.ErrRequestParam return end --订阅类型配置 local cfgSubscriptions = skynet.server.gameConfig:GetAllCfg("Subscription") if not cfgSubscriptions then log.debug("cfgSubscriptions is nil") return end --获取已订阅的数据,这里直接取redis里面的数据(订阅信息只存redis) local redisKey = string.format(redisKeyUrl.ThirdSubscribe, player.account) --获取订阅信息 local subscribeDataStr = skynet.server.redis:hget(redisKey,subscribeType) --反序列化对象 local subscribeData = {} --存在数据 if subscribeDataStr then --反序列化 subscribeData = json:decode(subscribeDataStr) end for _, subscribeId in ipairs(subscribeIdList) do local cfgSubscription = {} for _,value in pairs(cfgSubscriptions) do if value.id == subscribeId then cfgSubscription = value end end if not next(cfgSubscription) then log.error("cfgSubscription is nil") s2cData.code = errorInfo.ErrorCode.NoExistCfg return end --是否开放订阅 if cfgSubscription.subscribeLvl > player.gameData.level then log.error("cfgSubscription.subscribeLvl > player.gameData.level") -- s2cData.code = errorInfo.ErrorCode.LevelLimit -- return goto coroutine end --判断是否已订阅,已订阅先删除 for index, value in ipairs(subscribeData) do if value.subscribeId == subscribeId then log.debug(string.format("该玩家 %d 已经订阅该类型 %d,订阅id %d",player.userId,subscribeType,value.subscribeId)) -- s2cData.code = errorInfo.ErrorCode.ActivityClosed -- return goto coroutine elseif value.subscribeId == subscribeId then table.remove(subscribeData,index) break end end --获取结束时间 0:永久订阅 local expireTime = 0 if cfgSubscription.subscribeTriggerTime > 0 then expireTime=skynet.server.common:GetAfterSomeHour(cfgSubscription.subscribeTriggerTime) end --添加新的订阅信息 table.insert(subscribeData,{ subscribeId = subscribeId,--任务id subscribeStatus = 1,--1:已订阅,2:已推送,3 取消订阅 triggerTimestamp = initTime,--触发时间戳 expireTime = expireTime, uniqueId = uniqueId}) --订阅有效期,0:永久订阅 ::coroutine:: end --保存数据到redis if next(subscribeData) then --保存rendis skynet.server.redis:hset(redisKey,subscribeType,json:encode(subscribeData)) --保存到全部订阅数据 skynet.server.redis:sadd(redisKeyUrl.ThirdSubscribeSetKeys,player.account) --订阅状态 1 订阅成功,2 订阅失败 data.subscribeStatus = 1 end --是否首次全部订阅 if player.gameData.subscribe==nil then player.gameData.subscribe={ isDrawRewardAll = false , isDrawRewardAllTime = os.time()} end --没有领取奖励 if not player.gameData.subscribe.isDrawRewardAll and isAllSubscribe then --local isConAllSubscribe = true -- --计算已经订阅数量 -- for _, value in ipairs(cfgSubscriptions) do -- if value.subscribeTriggerTime <=0 then -- for _, value2 in ipairs(subscribeData) do -- if value.id ~= value2.subscribeId then -- isConAllSubscribe = false -- break -- end -- end -- end -- if not isConAllSubscribe then -- break -- end -- end -- --发奖奖励 -- if isConAllSubscribe then local cfgSValue = skynet.server.gameConfig:GetPlayerAllCfg( player , "SValue") --发放奖励 local eventId = pb.enum("EnumMoneyChangeEventID","EventID_120") player:GiveReward(cfgSValue.miniProgramAllSubReward ,eventId,1) --修改奖励为已发送 player.gameData.subscribe.isDrawRewardAll = true player.gameData.subscribe.isDrawRewardAllTime = os.time() --返回值 data.rewardId = cfgSValue.miniProgramAllSubReward --end end s2cData.data = assert(pb.encode("S2CSubscribeSubscribeMsg", data)) end --取消订阅 function Subscribe:UnSubscribe(player, c2sData , s2cData ) c2sData.data = assert(pb.decode("C2SSubscribeUnSubscribe", c2sData.data )) s2cData.cmd = pb.enum("MsgType","CMD_S2C_SubscribeUnSubscribe") --参数 local subscribeType = c2sData.data.subscribeType local subscribeId = c2sData.data.subscribeId --返回信息 local data = {} data.subscribeId = subscribeId --判断参数 if subscribeType == nil or subscribeId == nil then log.debug("参数错误") s2cData.code = errorInfo.ErrorCode.ErrRequestParam return end --订阅类型配置 local cfgSubscriptions = skynet.server.gameConfig:GetAllCfg("Subscription") if not cfgSubscriptions then log.error("cfgSubscriptions is nil") s2cData.code = errorInfo.ErrorCode.NoExistCfg return end local cfgSubscription = {} for _,value in pairs(cfgSubscriptions) do if value.id == subscribeId then cfgSubscription = value end end if not next(cfgSubscription) then log.error("cfgSubscription is nil") s2cData.code = errorInfo.ErrorCode.NoExistCfg return end --是否开放订阅 if cfgSubscription.subscribeLvl > player.gameData.level then log.error("cfgSubscription.subscribeLvl > player.gameData.level") s2cData.code = errorInfo.ErrorCode.LevelLimit return end --获取已订阅的数据,这里直接取redis里面的数据(订阅信息只存redis) local redisKey = string.format(redisKeyUrl.ThirdSubscribe, player.account) --获取订阅信息 local subscribeDataStr = skynet.server.redis:hget(redisKey,subscribeType) --反序列化对象 local subscribeData = {} --存在数据 if subscribeDataStr then --反序列化 subscribeData = json:decode(subscribeDataStr) end --是否存在 local exist =false --判断是否已订阅 for index, value in ipairs(subscribeData) do --是否有延时过期 if value.subscribeId == subscribeId and cfgSubscription.subscribeTriggerTime > 0 then value.subscribeStatus = 3 --1 已订阅,2 未订阅,3 取消订阅 exist = true break elseif value.subscribeId == subscribeId then table.remove(subscribeData,index) exist = true break end end --获取结束时间 0:永久订阅 local expireTime = 0 if cfgSubscription.subscribeTriggerTime > 0 then expireTime=skynet.server.common:GetAfterSomeHour(cfgSubscription.subscribeTriggerTime) end --如果不存在数据则添加 if #subscribeData == 0 or (exist == false and cfgSubscription.subscribeTriggerTime > 0) then --添加新的订阅信息 table.insert(subscribeData,{ subscribeId = subscribeId,--任务id subscribeStatus = 3,--1 已订阅,2 已推送,3 取消订阅 triggerTimestamp = initTime,--触发时间戳 expireTime = expireTime,--订阅有效期,0:永久订阅 uniqueId = "uniqueId"}) --唯一id,这里随便填写,不会推送 end --保存rendis skynet.server.redis:hset(redisKey,subscribeType,json:encode(subscribeData)) --订阅状态 1 订阅成功,2 订阅失败 data.subscribeStatus = 3 s2cData.data = assert(pb.encode("S2CSubscribeUnSubscribe", data)) end --更新离线时间 类型,目前只有微信1 function Subscribe:UpdateOfflineTime(player,subscribeType) function Do() log.debug("触发离线订阅 时间计算,accid:",player.account) local cfgLevel = skynet.server.gameConfig:GetPlayerCurCfg( player , "Level" , player.gameData.level ) if not cfgLevel then log.debug("cfgLevel is nil") return true end --获取已订阅的数据,这里直接取redis里面的数据(订阅信息只存redis) local redisKey = string.format(redisKeyUrl.ThirdSubscribe, player.account) --获取订阅信息 local subscribeDataStr = skynet.server.redis:hget(redisKey,subscribeType) --反序列化对象 local subscribeData = {} --不存在存在数据 if not subscribeDataStr or subscribeDataStr == "" then log.debug("微信订阅 subscribeDataStr is nil") return true end --反序列化 subscribeData = json:decode(subscribeDataStr) --未订阅 if not subscribeData or next(subscribeData) == nil then log.debug("微信订阅 subscribeData is nil") return true end local isUpdate =false --判断是否已订阅 for _, value in ipairs(subscribeData) do --游戏更新不走离线逻辑 if value.subscribeId == 8 then goto continue end --未过期,未推送 if (value.expireTime > os.time() or value.expireTime == 0) and value.subscribeStatus == 1 then --默认0 local triggerTimestamp = initTime --更新推送时间 if value.subscribeId == 1 then triggerTimestamp = os.time()+cfgLevel.offlineUpperTime elseif value.subscribeId == 2 then--花盆植物全部成熟 if player.gameData.flowerpot ~= nil and next( player.gameData.flowerpot) ~=nil then for k1, v1 in pairs( player.gameData.flowerpot ) do if (triggerTimestamp ==0 or triggerTimestamp > v1.flowerpotInfo.totalTime) and v1.flowerpotInfo.totalTime > os.time() then triggerTimestamp = v1.flowerpotInfo.totalTime end end end elseif value.subscribeId == 3 then--好味食堂进货完成 if player.gameData.shop[skynet.server.cuisineShop.ShopType] ~= nil and player.gameData.shop[skynet.server.cuisineShop.ShopType].restockInfos~=nil and player.gameData.shop[skynet.server.cuisineShop.ShopType].restockInfos.finishTime > os.time() then triggerTimestamp = player.gameData.shop[skynet.server.cuisineShop.ShopType].restockInfos.finishTime end elseif value.subscribeId == 4 then--萌宠乐园出游完成 if player.gameData.shop[skynet.server.petShop.shopType] ~= nil and player.gameData.shop[skynet.server.petShop.shopType].petTravel ~=nil and next(player.gameData.shop[skynet.server.petShop.shopType].petTravel) ~= nil and player.gameData.shop[skynet.server.petShop.shopType].petTravel[1].finishTime >os.time() then triggerTimestamp = player.gameData.shop[skynet.server.petShop.shopType].petTravel[1].finishTime end elseif value.subscribeId == 5 then--朝夕渔店鱼饵补充 local nowtamp = os.time() local now = os.date("*t", nowtamp) --12点提醒一次 if now.hour < 12 then triggerTimestamp = os.time({ year = now.year, month = now.month, day=now.day, hour=12, min=0, sec=0 }) else triggerTimestamp = os.time({ year = now.year, month = now.month, day=now.day, hour=12, min=0, sec=0 })+ 24 * 60 * 60 end elseif value.subscribeId == 6 then--恋家置业租房完成 --长租 if player.gameData.houseRent.longLeaseInfo ~= nil and next(player.gameData.houseRent.longLeaseInfo) ~=nil then for _, house in ipairs(player.gameData.houseRent.longLeaseInfo) do if house.remainRentTime > triggerTimestamp and house.leaseStatus == 2 then triggerTimestamp = house.remainRentTime end end end --短租 if player.gameData.houseRent.shortLeaseInfo ~= nil and next(player.gameData.houseRent.shortLeaseInfo) ~=nil then for _, house in ipairs(player.gameData.houseRent.shortLeaseInfo) do if house.remainRentTime > triggerTimestamp and house.leaseStatus == 2 then triggerTimestamp = house.remainRentTime end end end elseif value.subscribeId == 7 then--艺间造型剪刀补充 local curShop = player.gameData.shop[ skynet.server.styleShop.shopType ] triggerTimestamp = (19 - curShop.energy.energy) * 120 + curShop.energy.nextRefillTime --如果已经满了,就不通知了 if triggerTimestamp < os.time() then triggerTimestamp=0 end elseif value.subscribeId == 8 then--游戏更新 --游戏更新时间,这里暂时写死 triggerTimestamp=self:GameUpdateTime() end --已经满足条件 if triggerTimestamp<0 then triggerTimestamp=os.time() end --更新缓存 value.triggerTimestamp=triggerTimestamp log.debug(string.format("微信订阅 更新触发时间 subscribeId:%d,triggerTimestamp:%d",value.subscribeId ,value.triggerTimestamp)) --已推送修改成未推送 if value.subscribeStatus == 2 then value.subscribeStatus = 1 end isUpdate =true end ::continue:: end --暂无更新 if not isUpdate then log.debug("微信订阅 没有更新") return true end --获取订阅信息 skynet.server.redis:hset(redisKey,subscribeType,json:encode(subscribeData)) log.debug("微信订阅离线处理完成!") return true end local ret,err = pcall(Do) if not ret or not err then local account = player.basicInfo.accountName local userId = player.userId log.debug("内部错误信息 Subscribe:UpdateOfflineTime ", account , userId ,ret ,err) return false end return true end --更新在线,在线不推送任何订阅 类型,目前只有微信1 function Subscribe:UpdateOnlineTime(player,subscribeType) local cfgLevel = skynet.server.gameConfig:GetPlayerCurCfg( player , "Level" , player.gameData.level ) if not cfgLevel then return end --获取已订阅的数据,这里直接取redis里面的数据(订阅信息只存redis) local redisKey = string.format(redisKeyUrl.ThirdSubscribe, player.account) --获取订阅信息 local subscribeDataStr = skynet.server.redis:hget(redisKey,subscribeType) --反序列化对象 local subscribeData = {} --不存在存在数据 if not subscribeDataStr or subscribeDataStr == "" then return end --反序列化 local subscribeInfoList = json:decode(subscribeDataStr) --未订阅 if not subscribeInfoList or next(subscribeInfoList) == nil then return end local isUpdate =false --倒序遍历,删除不影响table后续索引 for i = #subscribeInfoList, 1, -1 do local subscribeInfo = subscribeInfoList[i] --不存在存在数据 if subscribeInfo == nil or next(subscribeInfo) == nil then goto coroutine end --判断是否过期 if subscribeInfo.expireTime < os.time() and subscribeInfo.expireTime ~= 0 then --删除订阅信息 table.remove(subscribeInfoList,i) else --未过期,在线 暂时取消推送 --更新缓存 subscribeInfo.triggerTimestamp = 0 --当前在线,没有推送时间 end -- 跳出当前循环 ::coroutine:: end --更新redis if next(subscribeInfoList) ~= nil then --更新订阅信息 skynet.server.redis:hset(redisKey,subscribeType,json:encode(subscribeInfoList)) else --删除 skynet.server.redis:hdel(redisKey,subscribeType) --删除索引 skynet.server.redis:srem(redisKeyUrl.ThirdSubscribeSetKeys,player.account) end log.debug("在线订阅处理完成") end --游戏更新时间 function Subscribe:GameUpdateTime() --手动设置时间 local uptime={ year = 2054,month = 07,day = 20, hour = 12,min = 12,sec = 12, } return os.time(uptime) end skynet.server.subscribe = Subscribe return Subscribe