HomeServer/lualib-src/Server-main/AllServer/GameServer/Mail.lua
2024-11-20 15:41:37 +08:00

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