123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404 |
- local skynet = require "skynet"
- local schema = require "model.schema"
- local logger = require "logger"
- local keygen = require "model.keygen"
- local cjson = require "cjson"
- local reward = require "model.reward"
- local util = require "util"
- local asset = require "model.asset"
- local log = require "model.log"
- local common_fun = require "model.common_fun"
- local equip
- local hero
- cjson.encode_sparse_array(true, 1)
- local s_mailbox = skynet.localname(".mailbox")
- local cjson_decode = cjson.decode -- 解码
- local cjson_encode = cjson.encode -- 编码
- local CMD = {}
- local REQUEST = {}
- local mailbox = {}
- local TYPE_TAB = 'table'
- local _M = schema.new('mail', {
- tm = 0, -- 玩家最近全服邮件收取时间
- list = {
- --[[
- [id] = {
- read = false, 是否已读
- attach = true, 是否有附件
- receive = true, 是否已领取
- }
- ]]
- }
- })
- function mailbox.list_request_interests() return REQUEST end
- function mailbox.list_command_interests() return CMD end
- --
- function mailbox.parse(character)
- local d = _M.load(character)
- if not d.list then
- d.list = {}
- _M.persist(character)
- end
- end
- local function optimize_array(a)
- if a and next(a) then
- return a
- end
- end
- ------------------------------ mailbox -------------------------------------
- -- 更新全局邮件收取时间
- local function update_tm(character)
- local data = _M.assert_get(character)
- data.tm = os.time()
- _M.persist(character)
- end
- local function update_state(character, id, attachment)
- local d = _M.assert_get(character)
- d.list[id] = {
- attach = next(attachment or {}) and true or false,
- read = false,
- receive = false,
- }
- _M.persist(character)
- return d.list[id]
- end
- -- 取出服务器中的所有邮件
- local function get_ser_mail(character)
- local data = _M.assert_get(character)
- local tm = os.time()
- data.tm = (data.tm == 0) and tm or data.tm
- _M.persist(character)
- return skynet.call(s_mailbox, "lua", "get_all_mail", data.tm, character.uid)
- end
- -- 检查是否能添加成功
- local function check_bag(attachment, bag_residue)
- for k, v in pairs(attachment) do
- local id = v.id
- local num = v.num
- local item_type = common_fun.goods_type(id)
- if item_type == GOODS_HERO then
- bag_residue.hero = (bag_residue.hero or 0) - num
- if bag_residue.hero <= 0 then
- return STD_ERR.HERO_FULL
- end
- elseif item_type == GOODS_EQUIP then
- bag_residue.equip = (bag_residue.equip or 0) - num
- if bag_residue.equip <= 0 then
- return STD_ERR.EQUIP_FULL
- end
- end
- end
- return 0
- end
- local function will_send_award(attachment, detail)
- for k, v in pairs(attachment) do
- table.insert(detail, v)
- end
- end
- local function tidy_award(character, list, ret_id, detail, log)
- local bag_residue = { -- 剩余空间
- hero = hero.hero_surplus(character),
- equip = equip.equip_surplus(character),
- }
- local sign, temp
- for _, v in pairs(list) do
- temp = cjson_decode(v)
- temp.source = temp.source or {}
- sign = check_bag(temp.attachment, bag_residue)
- if temp.attachment and sign == 0 then
- will_send_award(temp.attachment, detail)
- table.insert(log, {
- module = temp.source.module,
- brief = temp.source.brief,
- context = temp.source.context,
- detail = temp.attachment or {},
- })
- table.insert(ret_id, temp.id)
- elseif not temp.attachment then
- -- return -6 -- 邮件的附件为空
- table.insert(ret_id, temp.id)
- else
- return sign
- end
- end
- end
- local function send_log(character, temp_log)
- skynet.fork(function()
- for _, data in pairs(temp_log) do
- local record = {
- currency = data.detail.currency,
- }
- if next(record) then
- log.reward(character, data.module, data.brief, data.context, record)
- end
- end
- end)
- end
- ------------------------------ mailbox -------------------------------------
- --[[
- 统一邮件发送接口
- number subject: 邮件的主题, 使用参数表的 mail_proto[k].type
- string body: 邮件需要的参数,多参数使用 “ ,” 分割 , 无参数,为 ""
- table attachment: 邮件的附件,格式按照物品添加格式处理
- table source: 邮件的来源{
- module, -- 发送模块
- brief, -- 说明
- context, -- 上下文
- }
- ]]
- function mailbox.send(character, subject, body, attachment, source, must_mail)
- local id = keygen()
- local now = os.time()
- local content = {
- id = id,
- date = now,
- subject = subject,
- body = body,
- attachment = attachment or {},
- source = source,
- }
- skynet.call(s_mailbox,"lua","save_mail", id, cjson_encode(content), character.uid, must_mail)
- local data = update_state(character, id, attachment)
- content.read = data.read
- content.attach = data.attach
- content.receive = data.receive
-
- if character.send then
- content.source = nil
- character.send('send_mail', {list = {[1] = content}})
- end
- end
- function mailbox.ready(character)
- local data = _M.assert_get(character)
- if type(data) ~= TYPE_TAB then
- assert(false,string.format("邮件系统取出玩家数据失败 %s", character.uid))
- end
- -- 玩家上线将自己的地址保存到服务器
- skynet.call(s_mailbox,"lua","online", skynet.self(), character.uid, (data.tm == 0) and os.time() or data.tm)
- update_tm(character)
- mailbox.noread_mail(character)
- end
- function mailbox.saybye(character)
- -- TODO: 玩家下线时的处理
- update_tm(character)
- skynet.call(s_mailbox,"lua","offline", skynet.self(), character.uid)
- end
- function mailbox.launch(character)
- equip = require "model.equip"
- hero = require "model.hero"
- end
- function CMD.newmail(character, content, id)
- -- 修改玩家全服邮件最后收取时间
- update_tm(character)
- -- 发送邮件
- local temp_mail = cjson_decode(content)
- local data = update_state(character, temp_mail.id, temp_mail.attachment)
- temp_mail.read = data.read
- temp_mail.attach = data.attach
- temp_mail.receive = data.receive
- temp_mail.source = nil
- character.send('send_mail', {list = {[1] = temp_mail}})
- end
- -- 删除邮件
- function mailbox.del_mail(character, list)
- if #list <= 0 then
- return STD_ERR.COMMON_PARM_ERR
- end
- local d = _M.assert_get(character)
- local del = {}
- for _, v in ipairs(list or {}) do
- if d.list[v] and
- (d.list[v].attach and d.list[v].receive or false) or
- (not d.list[v].attach and d.list[v].read) or
- false then
- table.insert(del, v)
- d.list[v] = nil
- end
- end
- if not next(del) then
- return STD_ERR.COMMON_PARM_ERR
- end
- local err = skynet.call(s_mailbox,"lua","del_mail", character.uid, del)
- _M.persist(character)
- return err, del
- end
- -- 取出玩家邮件
- function mailbox.get_mail(character)
- local err, list = get_ser_mail(character)
- local temp = {}
- local temp_mail = {}
- local d = _M.assert_get(character)
- for k, v in pairs(list or {}) do
- temp_mail = cjson_decode(v)
- local data = d.list[temp_mail.id]
- if not data then
- data = update_state(character, temp_mail.id, temp_mail.attachment)
- end
- temp_mail.attach = data.attach
- temp_mail.read = data.read
- temp_mail.receive = data.receive
- temp_mail.source = nil
- table.insert( temp, temp_mail)
- end
- return err, temp
- end
- -- TODO: 统计未读取邮件,并推送给客户端
- function mailbox.noread_mail(character)
- local err, list = get_ser_mail(character)
- local temp_mail = {}
- local d = _M.assert_get(character)
- local noread = 0 -- 未读的文件
- local needread = 0 -- 有文本的文件
- local sum = 0
- local change = false
- local temp_list = {}
- for _, v in pairs(list or {}) do
- temp_mail = cjson_decode(v)
- local id = temp_mail.id
- temp_list[id] = 1
- if not d.list[id] then
- change = true
- d.list[id] = {
- read = false,
- attach = next(temp_mail.attachment or {}) and true or false
- }
- end
-
- if not d.list[id].read then
- noread = noread + 1
- end
- if d.list[id].attach and not d.list[id].receive then
- needread = needread + 1
- end
- sum = sum + 1
- end
- -- 清楚因过期被删掉的邮件
- for k in pairs(d.list or {}) do
- if not temp_list[k] then
- change = true
- d.list[k] = nil
- end
- end
- if change then
- _M.persist(character)
- end
- character.send("simple_mail", {num = sum, noread = noread, needread = needread})
- return sum, noread
- end
- -- 提取邮件附件
- function mailbox.get_mail_goods(character, list, bonekey)
- if #list <= 0 then
- return STD_ERR.MAILBOX_PARM_LIMIT -- 参数错误
- end
- local del_list = {}
- local d = _M.assert_get(character)
- for _, v in ipairs(list or {}) do
- if d.list[v] and d.list[v].attach and not d.list[v].receive then
- table.insert(del_list, v)
- end
- end
- local err, list = skynet.call(s_mailbox,"lua","get_goods",character.uid, del_list)
- if not err then
- return STD_ERR.MAILBOX_FAIL -- 取出邮件失败
- end
- local ret_id = {}
- local detail = {}
- local temp_log = {}
- local err = 0
- -- 整理邮件奖励
- err = tidy_award(character, list, ret_id, detail, temp_log) or 0
- if #ret_id > 0 then
- local _, lost = reward(character, {
- module = "mailbox",
- brief = 'mailbox.get_mail_goods', --数据统计
- context = string.format("批量领取邮件的附件,领取邮件的数量 num = %s", #ret_id),
- detail = detail,
- notify = {flags="get_mail_goods"},
- })
- assert(lost == nil, string.format("邮件系统发送奖励,奖励物品超过了背包的上限。ids = %s", cjson_encode(ret_id)))
- -- 发送log
- send_log(character, temp_log)
- local flag = false
- for _, mid in ipairs(ret_id) do
- d.list[mid] = d.list[mid] or {}
- d.list[mid].receive = true
- flag = true
- end
- if flag then
- _M.persist(character)
- end
- end
- return err, optimize_array(ret_id)
- end
- function mailbox.flag(character, list)
- list = list or {}
- local d = _M.assert_get(character)
- for _, mid in ipairs(list) do
- d.list[mid].read = true
- end
- _M.persist(character)
- return {errno = 0}
- end
- -- 取出玩家邮件
- function REQUEST.get_mail(character)
- local err, list = mailbox.get_mail(character)
- return {errno = err, list = list}
- end
- -- 取出邮件附件
- function REQUEST.get_mail_goods(character, args)
- local err, ids = mailbox.get_mail_goods(character, args.list, args.bonekey)
- return {errno = err, list = ids}
- end
- -- 删除邮件
- function REQUEST.del_mail(character, args)
- local err, list = mailbox.del_mail(character, args.list)
- return {errno = err, list = list}
- end
- -- 已读邮件标记
- function REQUEST.flag_mail(character, args)
- local err = mailbox.flag(character, args.list)
- return {errno = err}
- end
- return mailbox
|