465 lines
18 KiB
Lua
465 lines
18 KiB
Lua
local skynet = require "skynet"
|
|
local oo = require "Class"
|
|
local log = require "Log"
|
|
local pb = require "pb"
|
|
local redisKeyUrl = require "RedisKeyUrl"
|
|
local sqlUrl = require "SqlUrl"
|
|
local mailManage = require "MailManage"
|
|
local dataType = require "DataType"
|
|
local errorInfo = require "ErrorInfo"
|
|
local json = require "json"
|
|
local Mail = oo.class()
|
|
|
|
Mail.MailOpType_1 = 1 --获取邮件列表
|
|
Mail.MailOpType_2 = 2 --查阅/领取奖品
|
|
|
|
Mail.MailOpStatus_Suc = 1 --操作状态成功
|
|
Mail.MailOpStatus_NoMailID = 2 --不存在该邮件ID
|
|
Mail.MailOpStatus_AlreadyGet = 3 --已经领取了
|
|
|
|
Mail.MailType_AllServer = 1 --全服邮件
|
|
Mail.MailType_User = 2 --用户邮件
|
|
|
|
Mail.MaxSendCount = 100 --一次发送最大数量
|
|
|
|
function Mail:Init()
|
|
self.mailList = {}
|
|
end
|
|
|
|
--每5秒调一次
|
|
function Mail:On5SecTimer()
|
|
self:BatchAddMail()
|
|
end
|
|
|
|
--从后台刷新邮件列表
|
|
function Mail:RefreshMailList()
|
|
--向后端请求
|
|
local param = {}
|
|
local web = skynet.server.gameConfig.WebConfig.host .. ":" .. skynet.server.gameConfig.WebConfig.port
|
|
local url = skynet.server.common.getMailUrl
|
|
local status, body = skynet.server.httpClient:PostJson(web, url, json:encode(param), "http")
|
|
|
|
if 200 == status then
|
|
local newbody = json:decode(body)
|
|
if 200 == newbody.code then
|
|
--判断旧的邮件是否还能继续使用
|
|
if next(self.mailList)~=nil then
|
|
for k ,v in pairs(self.mailList) do
|
|
local isCanGet = false
|
|
for k1, v1 in pairs(newbody.data) do
|
|
if k==v1.mailModel.mailId then
|
|
isCanGet = true
|
|
break
|
|
end
|
|
end
|
|
v.isCanGet = isCanGet
|
|
end
|
|
end
|
|
|
|
--添加新的邮件
|
|
for k, v in pairs(newbody.data) do
|
|
local mailId = v.mailModel.mailId
|
|
if not self.mailList[mailId] then
|
|
self.mailList[mailId] = {}
|
|
local curMail = self.mailList[mailId]
|
|
curMail.mailInfo = v.mailModel
|
|
curMail.award = v.giftArticlesModels
|
|
curMail.isCanGet = true
|
|
curMail.isSendAllOnlineUser = false --是否发送所有在线玩家
|
|
|
|
if "全服" == curMail.mailInfo.mailCondition then
|
|
curMail.mailType = self.MailType_AllServer
|
|
elseif "ID" == curMail.mailInfo.mailCondition then
|
|
curMail.mailType = self.MailType_User
|
|
local t1 = skynet.GetTime()
|
|
local count = 0
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|
--给指定在线玩家发送新邮件
|
|
local uidList = skynet.server.common:Split( curMail.mailInfo.uidlist, ",")
|
|
for k, v in pairs(uidList) do
|
|
for userId, value in pairs(playerList) do
|
|
if value.player.account == v and skynet.server.playerCenter.Status_Playing == value.status then
|
|
self:AddMail(value.player, mailId , curMail.mailInfo , curMail.award , true )
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
log.info(string.format("邮箱 部分玩家发送邮件 发送数量 %d 时间花费 %d ", count, skynet.GetTime() - t1))
|
|
end
|
|
end
|
|
end
|
|
elseif 702 == newbody.code then
|
|
--s2cData.code = errorInfo.ErrorCode.AlreadyGet
|
|
if next(self.mailList)~=nil then
|
|
for k ,v in pairs(self.mailList) do
|
|
v.isCanGet = false
|
|
end
|
|
end
|
|
end
|
|
else
|
|
log.info("邮箱刷新 获取数据失败 status ", status)
|
|
end
|
|
end
|
|
|
|
--邮件历史
|
|
function Mail:History(player, c2sData, s2cData)
|
|
c2sData.data = assert(pb.decode("C2SMailHistory", c2sData.data))
|
|
local data = {}
|
|
data.mailInfo = {}
|
|
for k, v in pairs(player.gameData.mail.mailList) do
|
|
for k1, v1 in pairs(player.gameData.mail.historyMail) do
|
|
if v1 == v.mailId then
|
|
table.insert(data.mailInfo, v)
|
|
end
|
|
end
|
|
end
|
|
s2cData.cmd = pb.enum("MsgType", "CMD_S2C_MailHistory")
|
|
s2cData.data = assert(pb.encode("S2CMailHistory", data))
|
|
end
|
|
|
|
--邮件领取奖励
|
|
function Mail:Award(player, c2sData, s2cData)
|
|
c2sData.data = assert(pb.decode("C2SMailAward", c2sData.data))
|
|
local mailId = c2sData.data.mailId
|
|
local data = {}
|
|
data.mailInfo = {}
|
|
if not mailId then
|
|
s2cData.code = errorInfo.ErrorCode.ErrRequestParams
|
|
else
|
|
local isExist = false
|
|
local nowTime = skynet.GetTime()
|
|
for k, v in pairs(player.gameData.mail.mailList) do
|
|
if mailId == v.mailId and dataType.MailStatus_NoGet == v.status and nowTime<v.failureTime then
|
|
--未获取,可以正常领取
|
|
isExist = true
|
|
self:Bonus(player, mailId, v.award)
|
|
v.status = dataType.MailStatus_AlreadyGet
|
|
--告诉后台该玩家领取了邮件
|
|
local param = { mailId = mailId, playerId = player.account }
|
|
local web = skynet.server.gameConfig.WebConfig.host .. ":" .. skynet.server.gameConfig.WebConfig.port
|
|
local url = skynet.server.common.useMailUrl
|
|
local status, body = skynet.server.httpClient:PostJson(web, url, json:encode(param), "http")
|
|
local newbody = json:decode(body)
|
|
skynet.server.msgTips:Reduce(player , 23)
|
|
data.mailInfo = v
|
|
break
|
|
elseif mailId == v.mailId and dataType.MailStatus_AlreadyGet == v.Status then
|
|
--已经领取了,无法再次领取
|
|
isExist = true
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyGet
|
|
data.mailInfo = v
|
|
break
|
|
elseif mailId == v.mailId and nowTime >= v.failureTime then
|
|
--已经领取了,无法再次领取
|
|
isExist = true
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyGet
|
|
data.mailInfo = v
|
|
break
|
|
end
|
|
end
|
|
|
|
if not isExist then
|
|
s2cData.code = errorInfo.ErrorCode.NoExistMailID
|
|
end
|
|
end
|
|
s2cData.cmd = pb.enum("MsgType", "CMD_S2C_MailAward")
|
|
s2cData.data = assert(pb.encode("S2CMailAward", data))
|
|
end
|
|
|
|
--邮件读取
|
|
function Mail:Read(player, c2sData, s2cData)
|
|
c2sData.data = assert(pb.decode("C2SReadMail", c2sData.data))
|
|
local mailId = c2sData.data.mailId
|
|
local data = {}
|
|
data.mailInfo = {}
|
|
if not mailId then
|
|
s2cData.code = errorInfo.ErrorCode.ErrRequestParams
|
|
else
|
|
for k, v in pairs(player.gameData.mail.mailList) do
|
|
if mailId == v.mailId then
|
|
-- 修改邮件的读取状态
|
|
v.status = dataType.MailStatus_AlreadyGet
|
|
skynet.server.msgTips:Reduce(player , 23)
|
|
data.mailInfo = v
|
|
end
|
|
end
|
|
end
|
|
s2cData.cmd = pb.enum("MsgType", "CMD_S2C_ReadMail")
|
|
s2cData.data = assert(pb.encode("S2CReadMail", data))
|
|
log.info(string.format("玩家 %d 读取邮件 ID", player.userId, mailId))
|
|
end
|
|
|
|
--删除已读邮件
|
|
function Mail:DeleteRead(player, c2sData, s2cData)
|
|
c2sData.data = assert(pb.decode("C2SReadMail", c2sData.data))
|
|
local data = {}
|
|
data.mailInfo = {}
|
|
if player.gameData.mail.mailList then
|
|
-- 当玩家有邮件才进行以下逻辑
|
|
for k, v in pairs(player.gameData.mail.mailList) do
|
|
-- 领取或者读取过的邮件就删除 否则返回给客户端1
|
|
if dataType.MailStatus_AlreadyGet == v.status then
|
|
player.gameData.mail.mailList[k] = nil
|
|
else
|
|
table.insert(data.mailInfo, v)
|
|
end
|
|
end
|
|
end
|
|
s2cData.cmd = pb.enum("MsgType", "CMD_S2C_DeleteReadMail")
|
|
s2cData.data = assert(pb.encode("S2CDeleteReadMail", data))
|
|
log.info(string.format("删除 玩家 %d 读取过的邮件", player.userId))
|
|
end
|
|
|
|
--一键领取邮件奖励
|
|
function Mail:AllAward(player, c2sData, s2cData)
|
|
c2sData.data = assert(pb.decode("C2SMailAllAward", c2sData.data))
|
|
local data = {}
|
|
data.mailInfo = {}
|
|
local nowTime = skynet.GetTime()
|
|
for k, v in pairs(player.gameData.mail.mailList) do
|
|
if dataType.MailStatus_NoGet == v.status and pb.enum("PBMailInfo.MailType", "Award") == v.mailType and nowTime<v.failureTime then
|
|
--未获取,可以正常领取
|
|
self:Bonus(player, v.mailId, v.award)
|
|
v.status = dataType.MailStatus_AlreadyGet
|
|
--告诉后台该玩家领取了邮件
|
|
local param = { mailId = v.mailId, playerId = player.account }
|
|
local web = skynet.server.gameConfig.WebConfig.host .. ":" .. skynet.server.gameConfig.WebConfig.port
|
|
local url = skynet.server.common.useMailUrl
|
|
local status, body = skynet.server.httpClient:PostJson(web, url, json:encode(param), "http")
|
|
local newbody = json:decode(body)
|
|
|
|
-- 将邮件信息返回
|
|
table.insert(data.mailInfo, v)
|
|
--消除红点
|
|
skynet.server.msgTips:Reduce(player , 23)
|
|
elseif dataType.MailStatus_AlreadyGet == v.Status then
|
|
--已经领取了,无法再次领取
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyGet
|
|
elseif nowTime>=v.failureTime then
|
|
--邮件已经过期,无法进行领取 删除对应邮件
|
|
player.gameData.mail.mailList[k] = nil
|
|
s2cData.code = errorInfo.ErrorCode.AlreadyGet
|
|
end
|
|
end
|
|
s2cData.cmd = pb.enum("MsgType", "CMD_S2C_MailAllAward")
|
|
s2cData.data = assert(pb.encode("S2CMailAllAward", data))
|
|
end
|
|
|
|
--发放邮件奖励
|
|
function Mail:Bonus(player, mailId, award)
|
|
for k, v in pairs(award) do
|
|
if v.type >= dataType.GoodsType_Furniture and v.type <= dataType.GoodsType_PetClothes then
|
|
skynet.server.bag:AddGoods(player, v.type, v.id, v.count)
|
|
end
|
|
--货币直接发放相应数量就行
|
|
if v.type <10 then
|
|
if dataType.GoodsType_Coin == v.type then
|
|
player:MoneyChange(pb.enum("EnumGoodsType", "Coin"), v.count)
|
|
elseif dataType.GoodsType_Clovers == v.type then
|
|
player:MoneyChange(pb.enum("EnumGoodsType", "Clovers"), v.count)
|
|
elseif dataType.GoodsType_Volute == v.type then
|
|
player:MoneyChange(pb.enum("EnumGoodsType", "VoluteCoin"), v.count)
|
|
end
|
|
end
|
|
if not v.id then
|
|
log.info(string.format("玩家 %d 邮件 ID %s 领取奖励 类型 %d 数量 %d", player.userId, mailId, v.type, v.count))
|
|
else
|
|
log.info(string.format("玩家 %d 邮件 ID %s 领取奖励 类型 %d ID %d 数量 %d", player.userId, mailId, v.type, v.id, v.count))
|
|
end
|
|
end
|
|
end
|
|
|
|
--发送新邮件给在线玩家
|
|
function Mail:SendMailToOnlineUser( mailId )
|
|
local mailInfo = self.mailList[mailId].mailInfo
|
|
local award = self.mailList[mailId].award
|
|
if not mailInfo or not award then
|
|
return
|
|
end
|
|
|
|
local t1 = skynet.GetTime()
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|
local count = 0
|
|
if "全服" == mailInfo.mailCondition then
|
|
--给在线玩家发送新邮件
|
|
for userId, value in pairs(playerList) do
|
|
if skynet.server.playerCenter.Status_Playing == value.status then
|
|
--self:AddMail(value.player, mailId, mailInfo, award)
|
|
count = count + 1
|
|
end
|
|
end
|
|
log.info(string.format("邮箱 全玩家发送邮件 发送数量 %d 时间花费 %d ", count, skynet.GetTime() - t1))
|
|
elseif "ID" == mailInfo.mailCondition then
|
|
--给指定在线玩家发送新邮件
|
|
local uidList = skynet.server.common:Split(mailInfo.uidlist, ",")
|
|
for k, v in pairs(uidList) do
|
|
for userId, value in pairs(playerList) do
|
|
if value.player.account == v and skynet.server.playerCenter.Status_Playing == value.status then
|
|
--self:AddMail(value.player, mailId, mailInfo, award)
|
|
count = count + 1
|
|
end
|
|
end
|
|
end
|
|
log.info(string.format("邮箱 部分玩家发送邮件 发送数量 %d 时间花费 %d ", count, skynet.GetTime() - t1))
|
|
end
|
|
end
|
|
|
|
--批量发送邮件
|
|
function Mail:BatchAddMail()
|
|
local t1 = skynet.GetTime()
|
|
local playerList = skynet.server.playerCenter:GetPlayerList()
|
|
local sendCount = 0 --此次发送邮件数量
|
|
local isSendMail = true --是否继续发送邮件
|
|
for mailId, v1 in pairs( self.mailList ) do
|
|
local count = 0
|
|
if self.MailType_AllServer == v1.mailType and v1.isCanGet and not v1.isSendAllOnlineUser then --全服邮件 能发送 并且未发送完
|
|
for userId, value in pairs(playerList) do
|
|
if skynet.server.playerCenter.Status_Playing == value.status and not value.onlineMailList[ mailId ] then --在线玩家并且未接收该邮件
|
|
self:AddMail( value.player , mailId , v1.mailInfo , v1.award , true )
|
|
value.onlineMailList[ mailId ] = 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 在线已发送结束 ", mailId ))
|
|
else
|
|
log.info(string.format("邮箱 全服邮件 %s 发送 发送数量 %d 时间花费 %d ", mailId , count, skynet.GetTime() - t1))
|
|
end
|
|
end
|
|
|
|
if not isSendMail then
|
|
break
|
|
end
|
|
end
|
|
end
|
|
|
|
--添加邮件
|
|
function Mail:AddMail(player , mailId , mailInfo , award , isWebSend)
|
|
--玩家已经存在该邮件了,不再发送
|
|
if self:IsExist(player, mailId) then
|
|
return true
|
|
end
|
|
|
|
local nowTime = os.time()
|
|
--过了或者未到有效时间,不再发送
|
|
if isWebSend then
|
|
if nowTime>skynet.server.common:GetTime(mailInfo.playerFailureTime) or nowTime < skynet.server.common:GetTime(mailInfo.playerEffectiveTime) then
|
|
return true
|
|
end
|
|
end
|
|
|
|
--[[
|
|
--玩家的APP版本是否符合
|
|
if self.basicInfo.appVersion < mailInfo.appVersion then
|
|
return
|
|
end
|
|
|
|
--玩家的渠道是否符合
|
|
if self.basicInfo.channel ~= mailInfo.channel and "all" ~= mailInfo.channel then
|
|
return
|
|
end
|
|
|
|
--玩家的系统不符也不发
|
|
if self.basicInfo.platform ~= mailInfo.system and "all" ~= mailInfo.system then
|
|
return
|
|
end
|
|
]]
|
|
local mail = player.gameData.mail
|
|
local mailType = nil
|
|
if "信息" == mailInfo.mailType then
|
|
mailType = pb.enum("PBMailInfo.MailType", "Message")
|
|
elseif "奖励" == mailInfo.mailType then
|
|
mailType = pb.enum("PBMailInfo.MailType", "Award")
|
|
end
|
|
|
|
local curIndex = mail.curIndex
|
|
mail.mailList[curIndex] = {}
|
|
mail.mailList[curIndex].mailId = mailId
|
|
mail.mailList[curIndex].status = dataType.MailStatus_NoGet
|
|
mail.mailList[curIndex].mailType = mailType
|
|
mail.mailList[curIndex].mailSubType = 1
|
|
mail.mailList[curIndex].title = mailInfo.mailTitle
|
|
mail.mailList[curIndex].content = mailInfo.mailText
|
|
mail.mailList[curIndex].award = {} --奖励
|
|
|
|
if award then
|
|
if not isWebSend then
|
|
--不是来自后台的邮件
|
|
for k, v in pairs(award) do
|
|
if v.type == 0 then
|
|
table.insert(mail.mailList[curIndex].award, { type = v.id, count = v.count })
|
|
else
|
|
table.insert(mail.mailList[curIndex].award, { type = v.type, id = v.id, count = v.count })
|
|
end
|
|
end
|
|
else
|
|
--来自后台的邮件
|
|
for k, v in pairs(award) do
|
|
local goodsType = skynet.server.common:AwardTypeStrToInt(v.articlesType)
|
|
if goodsType == dataType.GoodsType_Init then
|
|
table.insert(mail.mailList[curIndex].award, { type = v.articlesId, count = v.articlesNumber })
|
|
else
|
|
table.insert(mail.mailList[curIndex].award, { type = goodsType, id = v.articlesId, count = v.articlesNumber })
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
mail.mailList[curIndex].receiveTime = skynet.GetTime()
|
|
mail.mailList[curIndex].failureTime = skynet.server.common:GetAfterSomeHour(mailInfo.mailEffectiveTime * 24) --邮件的失效时间就是玩家获取到邮件之后的多少天
|
|
|
|
--插入玩家领取过的邮件ID
|
|
table.insert(mail.historyMail, mailId)
|
|
|
|
--增加邮件红点
|
|
skynet.server.msgTips:Add(player , 23)
|
|
|
|
--玩家最多30条最近的邮件记录
|
|
mail.curIndex = mail.curIndex + 1
|
|
if mail.curIndex >= 30 then
|
|
mail.curIndex = 1
|
|
end
|
|
--skynet.server.gameServer:SendMsgToUser(self.userId, "CMD_S2C_Mail", data)
|
|
log.info(string.format("玩家 %d 邮箱 新增邮件 ID %s ", player.userId, mailId))
|
|
end
|
|
|
|
--检查玩家是否有新邮件
|
|
function Mail:CheckNewMail(player)
|
|
for mailId, value in pairs(self.mailList) do
|
|
if not self:IsExist(player, mailId) and value.isCanGet then
|
|
if "全服" == value.mailInfo.mailCondition then
|
|
self:AddMail(player, mailId, value.mailInfo , value.award , true )
|
|
elseif "ID" == value.mailInfo.mailCondition then
|
|
local uidList = skynet.server.common:Split(value.mailInfo.uidlist, ",")
|
|
for k, v in pairs(uidList) do
|
|
--如果存在本人邮件就发送
|
|
if player.account == v then
|
|
self:AddMail(player, mailId , value.mailInfo , value.award , true )
|
|
break
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
end
|
|
|
|
--是否存在邮件
|
|
function Mail:IsExist(player, mailId)
|
|
for k, v in pairs(player.gameData.mail.historyMail) do
|
|
if mailId == v then
|
|
return true
|
|
end
|
|
end
|
|
return false
|
|
end
|
|
|
|
skynet.server.mail = Mail
|
|
return Mail |