就这样写个像样的邮件系统,赶紧收藏

今天写下邮件系统,也是计划中的文章。走起

邮件系统几乎是每个游戏必备的,虽然没什么复杂的,但是还是稍微写一下,给某些没写过的同学参考下

7dc3f00c33045a055d2bc6b110abe548.png

注:网上随便找了个游戏的邮件界面,没找到之前做的游戏的邮件界面

需求
通用系统几乎没什么策划案的事,因为这种都是统一的实现。我们自己理一下项目需求

1、发送邮件

2、删除邮件,

3、读取邮件

4、支持发送附件,在附件中可以支持道具的领取

5、支持不同的邮件群组类型,比如系统邮件,公会邮件,战斗邮件

6、支持配置不同类型的邮件的正文配置,比如排行榜的邮件,公会解散的邮件等等

还可以扩展一些根据游戏的邮件类型

代码设计
设计数据库
根据需求我们设计表字段如下

9a1d7d852d2711d818b6d5d8fdd99487.png

注:有不明白的可以留言给我交流

接口设计
因为邮件是通用功能,所以接口要尽量的简单,可以多些一些接口,我们定义一个工具类,下面的是一些底层接口

 
//查询邮件
public Letter sendLetter(int sendId, int groupId) throws SQLException;
 
//发送邮件
public void sendLetter(int sendId, int recId, int groupId,int titleId, String param,String attach) throws SQLException;
 
//读取单个邮件(修改读取状态)
public ErrorVO readLetter(PlayerLetter lett, int roleid) throws SQLException;
 
//一键已读
public ErrorVO readAllLetters(int roleId, int groupId) throws SQLException;
 
// 一键领取附件
public ErrorVO attachedAll(int roleId int groupId) throws SQLException;
 
//一键删除无附件邮件
public ErrorVO delAllLetters(int roleId, int groupId) throws SQLException;


对应表的entity 可以使用工具根据数据库表生成,因为本地没有安装数据库,就不展示了

邮件组类型,组类型决定了对应的邮件在客户端的分类,在这边我随便写了三个组别,系统邮件,战斗邮件,个人邮件

/
**
* 邮件组类型
*/
public enum LetterGroupType {
   //系统
   LETT_SYS( 1),
   //战斗
   LETT_FIGHT( 2),
   //个人
   LETT_PLAYER(5),;
   private int type;
 
   LetterGroupType(int type) {
       this.type = type;
  }
 
   public int getType() {
       return type;
  }
 
   public static LetterGroupType valueOf(int emailType) {
       for (LetterGroupType bt : values()) {
           if (emailType == bt.getType()) {
               return bt;
          }
      }
       return null;
  }
 
}


邮件标题类型枚举,我随意写了两个,根据具体游戏增加吧


/**
* 邮件标题类型
*/
public enum LetterTitleType {
   // 等级排行榜邮件
   LV_RANK_MAIL(1),
   // 在线奖励邮件
   ONLINE_MAIL(2),
  ;
   
private final int type;
 
private LetterTitleType(int type) {
this.type =  type;
}
 
public int getType() {
return type;
}
 
}


基本的都搞定了我们定下参数的规则:

groupId  决定了客户端显示的组别

titleId 决定了显示的邮件标题和邮件的内容

比如 titleId = 1 排行榜奖励,在配置表中可以配置


客户端通过读取标题id的配置文件,设置邮件标题和邮件内容,具体的参数可以从邮件的param中读取,{ } 是占位符,根据顺序进行增加

具体使用
其他模块调用,比如某个玩家在等级排行榜中获得了第11名,则发送邮件调用如下

LetterUtil.sendSysMail(1,LetterTitleType.LV_RANK_MAIL,"奖励",11)
注:这个接口是在底层接口的基础上进行扩展的,因为是发送的等级排行榜

所以一些参数是默认的,比如:

sendRid = 0,

groupId = LetterGroupType.LETT_SYS,

发送时间是当前时间。

我没有提及的问题:
1、客户端红点问题,在有新邮件的时候推送新邮件的数量

2、邮件因为是一个不需要及时响应的行为,所以可以将任务放到线程池执行,不阻塞当前线程

3、上层接口的设计,上面代码里我只展示了最基本的接口,在使用的地方也没有展示具体的逻辑

4、数据的写库问题,因为我本地没装数据库,也每个项目的情况不同,可以自己适配项目的数据写入

5、和客户端协议通信没有展示,基本上就是一个协议内容就是表数据的转换

6、邮件过期的处理,可以在程序内加定时器进行定时处理,至于附件的处理逻辑可以和策划进行沟通,是自动领取还是直接删掉。

总结:
邮件不难,只要按常规的逻辑写就行了

但是要注意邮件的附件的领取状态要及时更新,防止被刷奖励。

今天就这样吧,因为本地没有数据库,具体的实现就留给你了,如有问题可以留言给我。

(完)