我在学习的过程中,简单的梳理了下邮件系统的结构,并且尝试实现了个用Lua些的简易版邮件系统
概念:
一般的游戏中,邮件分为两种,一种是系统邮件,一种是活动邮件,
系统邮件就是运维发给玩家的邮件,如补偿,公告之类的,
活动邮件就是我们内部发送的,如:活动过期玩家有的奖励没有领,这个时候通过邮件发送未领取的奖励给玩家,
开发:只需要安装好 Lua 环境即可,是以类的形式进行开发,以便于更好的管理整个邮件
邮件的内容和操作:
内容:
通常一封邮件内容有如下:
邮件的uid,接收人,标题,内容,奖励,发送邮件的时间,
邮件的状态(这里的状态指的是,邮件是否已读,已领取或已删除),
发件人的类型,发送人的名字
但是管理邮件的管理有却很简单(根据实际情况来定)这里只有两个字段:
总的邮件内容,邮件的数量
操作:
一般操作邮件的形式有,查看邮件,领取邮件,一键领取,一键删除
,这里的删除不是真正的删除,对玩家而言属于删除,对我们而言只是把它隐藏了
--------- start ----------
创建邮件管理类,用于管理整个邮件,mail_mgr.lua
local MailMgr = MailMgr or {}
local mgt = mgt or {
__index = MailMgr
}
function MailMgr:new(player_idx)
local mgr = {}
setmetatable(mgr, mgt)
mgr.player_idx= player_idx
mgr:init()
return mgr
end
function MailMgr:init()
self.mails_ = {} -- 总的邮件内容
self.count_ = 0 -- 邮件数量
end
-- 获取邮件的数量
function MailMgr:count(num)
if not num then
return self.count_
end
self.count_ = num
end
-- 添加一封邮件,每添加一封邮件就需要把数量和邮件的下标+1
function MailMgr:addMail(mail)
local idx = mail:index()
if idx < 1 then
idx = self:count() + 1
self:count(idx)
mail:index(idx)
end
self.mails_[idx] = mail
end
-- 获得指定的邮件
function MailMgr:getMail(m_idx)
local mail = self.mails_[m_idx]
if not mail then
return
end
if mail:state() == MAIL_DELETE then
return
end
return mail
end
-- 获得全部邮件列表
function MailMgr:getMailList()
return self.mails_
end
-- 删除邮件
function MailMgr:remMail(m_idx, m_state)
local mail = self.mails_[m_idx]
if not mail then
return
end
mail:state(m_state)
return mail
end
一个管理邮件的管理类就写好了,接下来是邮件类,新建 mail.lua
local Mail = Mail or {}
local mt = mt or {
__index = Mail
}
function Mail:new(id, recver, send_tm, title, content, sender, sender_name)
local mail = {}
setmetatable(mail, mt)
mail.uid_ = id -- 邮件 uid
mail.recver_ = recver -- 接收人
mail.title_ = title -- 标题
mail.content_ = content -- 内容
mail.send_tm_ = send_tm -- 发送时间
mail.state_ = 0 -- 邮件状态
mail.sender_ = sender -- 发件人类型 1系统邮件,0活动邮件
mail.sender_name = sender_name -- 发送人名字
mail:init()
return mail
end
function Mail:init()
self.grids_ = {} -- 奖励
self.is_dirty_ = false -- 脏标记(存数据用)
self.idx_ = 0 -- 邮件的下标(第几封邮件)
end
-- 把邮件的奖励拆开插入到奖励表里面
function Mail:addGrid(type_idx, count)
table.insert(self.grids_, {type_idx, count})
return true
end
function Mail:index(idx)
if not idx then return self.idx_ end
self.idx_ = idx
end
-- 邮件的状态
function Mail:state(stat)
if not stat then
return self.state_
end
self.state_ = stat
end
function Mail:grids()
return self.grids_
end
接下来是玩家类:这些领取,删除等操作都是玩家来完成的,
因为这不是在正在开发环境中,所有我们要手动初始化下一下管理类的表,函数也需要用全局的来代替
function getMailMgr()
return mail_mgr_
end
local mail_mgr_ = MailMgr:new()
player_mail.lua
-- 为了方便,邮件的状态就写在一起,
-- 我们可以另外新建一个lua文件来存放这些状态(maildef.lua)
local MAIL_UN_READ = 0 -- 未读
local MAIL_READ = 1 -- 已读
local MAIL_RECEIVED = 2 -- 已领取
local MAIL_DELETE = 3 -- 已删除
local MAIL_MAXLEN_TITLE = 32 -- 标题最大长度
local MAIL_MAXLEN_CONTENT = 1024 -- 内容最大长度
-- 读邮件 (邮件idx是通过前端发送过来的)
function MailRead(mail_idx)
local mail_mgr = getMailMgr()
if not mail_mgr then
return
end
local mail = mail_mgr:getMail(mail_idx)
if mail:state() == MAIL_UN_READ then
mail:state(MAIL_READ)
end
end
-- 领取邮件 or 删除邮件
-- 前端通过状态来决定邮件是显示领取还是删除
function deleteMail(mail_idx)
local mail_mgr = getMailMgr()
if not mail_mgr then
return
end
local mail = mail_mgr:getMail(mail_idx)
if not mail then
return
end
-- 如果未领取
if mail:state() < MAIL_DELETE then
local list = {}
local flag = 1
local item_id, item_num
for k, v in pairs(mail:grids()) do
item_id, item_num = unpack(v)
table.insert(list, {item_id, item_num, flag})
end
-- 这里调用发送奖励的借口即可
end
-- 把邮件置为删除的状态
mail_mgr:remMail(mail_idx, MAIL_DELETE )
end
-- 一键删除
function allDeleteMail()
local mail_mgr = getMailMgr()
if not mail_mgr then
return
end
-- 获得所有邮件列表
for m_idx, mail in pairs(mail_mgr:getMailList()) do
if mail:state() < MAIL_DELETE then
-- 如果有未领取邮件则调用发奖励的接口发送奖励到玩家背包
-- 置位删除状态
mail_mgr:remMail(m_idx, MAIL_DELETE )
end
end
end
这里还需要提供一个发邮件接口给自己用和运维用
function sendMail(char_idx, title, content, grids, is_send, sname)
local sender = 0
sname = sname or 'system'
if not title or string.len(title) > MAIL_MAXLEN_TITLE then
title = 'title'
end
if not content or string.len(content) > MAIL_MAXLEN_CONTENT then
content = 'content'
end
local send_tm = os.time()
grids = grids or {}
local mail = Mail:new(0, char_idx, send_tm, title, content, sender, sname)
local item_id, item_num
for _, v in pairs(grids) do
item_id, item_num = unpack(v)
if item_num < 1 then
item_num = 1
end
mail:addGrid(item_id, item_num)
end
local mail_mgr = getMailMgr()
mail_mgr:addMail(mail)
-- 最后把新邮件入库,因为数据库的设计邮件的uid是自增类型,所以不用担心锁表的问题
end
这样我们就可以通过这个接口来发送邮件
sendMail(11111, “China”, “Nine”, {{6,100}}, true, “activity”)
sendMail(22222, “China”, “Nine”, {{6,1000}}, true, “activity”)
打印出来的结果: