zoukankan      html  css  js  c++  java
  • 游戏好友系统与邮件系统实现

    好友系统实现:

    每个玩家在内存上都会有自己的一个map记录他的好友信息。

    这个结构体大致如下:

    struct FriendData
    {
        uint32_t rid;
        //目前我们之间的状态
        uint32_t status;
    
        //记录对方的data
        uint32_t peerRid;
        uint32_t peerName;
        uint32_t peerLevel;
        uint32_t peerVip;
        ....
        ....
    };
    
    map<uint32_t, FriendData> m_myFriend;

    假设A玩家添加了B玩家位他的好友,那么除了A玩家的内存上要增加B玩家的数据外,B玩家也应该会有A玩家的数据。

    一个好的设计原则是:彼此不操作对方的内存数据

    从内存上的实现会需要以下几个静态变量(只需要一份即可):

    //发送好友申请的玩家数据,这样对方同意好友申请的时候才知道发起者的数据
    struct RequestSenderInfo
    {
        //发起好友请求的玩家的数据
        uint32_t rid;
        string name;
        uint32_t level;
        ...
        ...
    };
    //我目前收到的好友申请
    static map<uint32_t, vector<RequestSenderInfo>> m_applyList;
    
    //我发起的好友申请后收到的回应,其中FriendData就是回应者的数据; 
    static map<uint32_t, vector<FriendData>> m_responseList;
    
    //我目前收到的好友删除申请。
    static map<uint32_t, vector<uint32_t>> m_deleteList;

    假设A玩家给B玩家发起了一条好友申请:

    1.A玩家会操作m_applyList,将B玩家的Rid作为Key,打包自己A玩家的数据放入m_applyList中;

    2.B玩家通过定时器或者前端请求的方式去查找m_applyList知道B玩家有了好友申请。

      1.B玩家拒绝A玩家的好友申请:B玩家会操作m_responseList以A玩家作为Key,将拒绝的结果打包在FriendData的status中放入m_responseList

      2.B玩家同意A玩家的好友申请:B玩家会操作m_responseLIst以A玩家作为Key,将自己B玩家的数据和同意的结果打包进FriendData中放入m_responseList

    3.A玩家通过定时器或者前端请求的方式去查找m_responseList知道了B玩家的是接受还是拒绝,以此来是否将B玩家放入自己的m_myFriend中;

    当B玩家从好友列表中删除A玩家后:

    1.B玩家会操作m_deleteList,以A玩家的Rid为Key,将自己B玩家的Rid放入m_deleteList中;

    2.A玩家通过定时器或者前端请求的方式去查找m_deleteList发现了B玩家删除了自己,自己A玩家也从m_myFriend中删除B玩家。

    以上就是好友系统的内存操作,简洁明了。A玩家不操作B玩家的内存数据,同理B玩家也不操作A玩家的内存数据,因此无需关心对方的数据是否已经从数据库载入内存;

    数据库表的结构如下:

    当B玩家同意好友的时候往数据库写两条数据。

    一条是A玩家中B玩家的数据,一条是B玩家中A玩家的数据。这个设计感觉不是特别好,但是目前没有想出特别好的方法;

    邮件系统实现:

    邮件系统的实现有几个问题需要解决:

    一、邮件Id的唯一性

    二、如果每个玩家的内存单独维护一个邮件Id。就会遇到一个问题:排行榜发奖的时候,如果玩家的数据不在内存上,如何知道这个玩家邮件的Id。就要存在Load这个玩家档的情况。

    三、全服邮件如何发给每一个玩家

    我的实现是:普通邮件采用全服唯一邮件mailId的形式。系统邮件采用另一个全服唯一邮件sysMailId的形式

    系统邮件在数据库的存储位置是:以rid=服务器id的形式分数据库、指定sysMailId字段的形式存储到数据库表内

    数据结构设计为:

    struct DataMail
    {
        uint32_t rid
        uint32_t mailId;
        uint32_t sysMailId;
        uint32_t readTs;
        uint32_t sendTime;
        char send[19];
        char title[100];
        char text[512];
        char attachments[512];
    };
    static uint32_t nextSysMailId;
    static vector<DataMail> vSystemMail;
    static uint32_t nextMailId;
    map<uint32_t, DataMail> m_userMail;

    对于问题一如何做到全服唯一的普通邮件mailId:

    进程一启动的时候不可能加载本服所有邮件然后对最后一封邮件mailId++的形式来拿到最大的mailId;因此会在另一个表Attr表内rid=本服Id且type=xx存一个nextMailId,每个玩家在新增一封邮件的时候都会修改这个值。

    如果发的是普通邮件(玩家通关某个关卡),会设置Rid、mailId且sysMailId=0存入数据库中;

    如果普通邮件的发放玩家不在内存上时,由于普通邮件采用的是全服唯一的mailId,因此依然能指定Rid和mailId存入数据库内;

    如果通过后台发的是全服(更新补偿、服务器异常补偿)邮件,会单独将rid设置为本服(例如1服为1),mailId和sysMailId相等存到数据库中;

    玩家如何拿到这份全服邮件

    玩家登录Load档完自己邮件的数据以后会遍历系统邮件,判断自己是否有sysMailId的邮件,如果没有则走普通邮件的流程给自己的数据库表中添加一封邮件;

    邮件数据库表的设计结构为:

  • 相关阅读:
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    SpringCloudAlibaba
    如何使用webify快速构建Nuxt应用
    “我,不懂代码,36岁转行开发”
  • 原文地址:https://www.cnblogs.com/jialin0x7c9/p/12733765.html
Copyright © 2011-2022 走看看