添加聊天记录(接口协议)

聊天记录

需求说明

聊天缓存

大厅聊天记录

说明

  1. 服务器记录玩家在大厅发送的最新的若干条消息,客户端每次登录后可以获取这些大厅消息并显示;
  2. 大厅聊天记录条数根据配置而定;
  3. 服务器记录的数据只保存在缓存中,重启后数据会丢失

交互协议

协议号

ABROAD_CLIENT_HALL_CHAT_HISTORY_REQ = 48401,  // 大厅聊天记录请求
ABROAD_CLIENT_HALL_CHAT_HISTORY_REP = 48402,  // 大厅聊天记录回复

协议内容

struct ClientHallChatHistoryReq : PacketBase
{
    unsigned int timestamp;
    ClientHallChatHistoryReq() : PacketBase(ABROAD_CLIENT_HALL_CHAT_HISTORY_REQ, sizeof(ClientHallChatHistoryReq))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientHallChatHistoryReq));
    }
};

struct ClientHallChatHistoryRep : PacketBase
{
    static const unsigned int sc_max_chat_cnt = 100;
    struct TChatData
    {
        unsigned int timestamp;
        unsigned char vip;
        unsigned char sex;
        unsigned int head;
        unsigned char officiallevel;
        unsigned int division;
        unsigned char level;
        char nick[sc_max_nickname_len];
        char text[256];
        friend bostream& operator<<(bostream& bos, const TChatData& t)
        {
            bos << t.timestamp << t.vip << t.sex << t.head << t.officiallevel << t.division << t.level << t.nick << t.text;
            return bos;
        }
    };
    unsigned char count;
    TChatData chats[sc_max_chat_cnt];
    friend bostream& operator<<(bostream& bos, const ClientHallChatHistoryRep& t)
    {
        bos << t.count;
        for (unsigned char i = 0; i < t.count&& i < sc_max_chat_cnt; ++i)
            bos << t.chats[i];
        return bos;
    }
    ClientHallChatHistoryRep() : PacketBase(ABROAD_CLIENT_HALL_CHAT_HISTORY_REP, sizeof(ClientHallChatHistoryRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientHallChatHistoryRep));
    }
};

公会聊天记录

说明

  1. 服务器记录公会玩家在公会发送的最新的若干条消息,客户端每次登录后可以获取所在公会的历史消息并显示;
  2. 公会聊天记录条数根据配置而定;
  3. 服务器记录的数据会保存在缓存和数据库中

交互协议

协议号

CLIENT_GUILD_CHAT_HISTORY_REQ = 24059,   // 公会聊天记录请求
CLIENT_GUILD_CHAT_HISTORY_REP = 24060,   // 公会聊天记录回复

协议内容

struct ClientGdsChatHistoryReq : PacketBase
{
    unsigned int timestamp;
    ClientGdsChatHistoryReq() : PacketBase(CLIENT_GUILD_CHAT_HISTORY_REQ, sizeof(ClientGdsChatHistoryReq))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientGdsChatHistoryReq));
    }
};

struct ClientGdsChatHistoryRep : PacketBase
{
    static const unsigned int sc_max_chat_cnt = 100;
    struct TChatData
    {
        unsigned int timestamp;
        unsigned char vip;
        unsigned char sex;
        unsigned int head;
        unsigned char officiallevel;
        unsigned int division;
        unsigned char level;
        char nick[sc_max_nickname_len];
        char text[256];
        friend bostream& operator<<(bostream& bos, const TChatData& t)
        {
            bos << t.timestamp << t.vip << t.sex << t.head << t.officiallevel << t.division << t.level << t.nick << t.text;
            return bos;
        }
    };
    unsigned char count;
    TChatData chats[sc_max_chat_cnt];
    friend bostream& operator<<(bostream& bos, const ClientGdsChatHistoryRep& t)
    {
        bos << t.count;
        for (unsigned char i = 0; i < t.count&& i < sc_max_chat_cnt; ++i)
            bos << t.chats[i];
        return bos;
    }
    ClientGdsChatHistoryRep() : PacketBase(CLIENT_GUILD_CHAT_HISTORY_REP, sizeof(ClientGdsChatHistoryRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientGdsChatHistoryRep));
    }
};

离线聊天

说明

  1. 好友之间、陌生人之间是否可以发离线消息、能发送几条根据配置而定;
  2. 服务端将离线消息加入对应的离线消息的redis数据库队列,公共支持部那边会从里面取出数据推送;
  3. 服务端需要记录两个玩家之间发送的离线消息条数,只保存在缓存中,重启会清空数据;
  4. 离线数据以玩家的账号进行区分记录,但客户端不知道其他玩家的账号,需要告知客户端其他玩家的MD5账号

交互协议

发送消息的在线玩家

  • 发送成功通过原有消息号SS_C_CHATMSG_NTF=20613通知玩家,在该协议内容中新增接收玩家的MD5账号 listener_account_md5

    //聊天消息通知客户端
          struct SSCChatmsgNtf_Mobile : public PacketBase
          {
              struct Patch
              {
                  char                            sex;
                  unsigned int                    sgx3;
                  unsigned char                    msgtype;
                  int                                param1;
                  unsigned char                    officiallevel;
                  unsigned char                    officialrank;
                  unsigned int                    division;
                  unsigned short                    level;
                  char                            guild_name[sc_max_guildname_len];
                  char                            listener_account_md5[16];   //说话的目标人账号的MD5值
                  Patch() { memset(this, 0, sizeof(Patch));}    
              };
    
              unsigned int                    channel;                            // 频道CServerChatMsgReq::emchachannel,或者信道号码
              unsigned short                    msglen;
              unsigned int                    using_goodsbaseid;                    // 正在使用的聊天泡泡
              unsigned int                    vip;                                // vip字段
              char                            spokesman[sc_max_nickname_len];        // 说话者昵称
              char                            listener[sc_max_nickname_len];        // 说话的目标人
              char                            chatmsg[1024];
              //Patch                            patch;                                //chatmsg是变长,所以需要序列化在协议最后
    
              SSCChatmsgNtf_Mobile() : PacketBase(SS_C_CHATMSG_NTF, sizeof(SSCChatmsgNtf_Mobile))
              {
                  PRO_ZERO_MEMORY(this, sizeof(SSCChatmsgNtf_Mobile));
              }
          };
    
  • 发送失败通过原有消息号SS_C_CHATMSG_REP=20612通知,新增失败原因 fail_offline_friend_limit、fail_offline_notfriend_limit、fail_offline_friend_forbid、fail_offline_notfriend_forbid

    //如果失败会通知客户端
    struct CServerChatMsgRep : public PacketBase
    {
      // 历史原因,这个协议只有失败时才会发
      enum 
      {
          fail_unknown = 0,
          fail_level,
          fail_send_cnt,
          fail_target_cnt,
          fail_no_goods,
          fail_no_guild,
          fail_report_system_forbidden, //举报系统禁言中
          fail_offline_friend_limit, //好友离线消息发送次数达到上限
          fail_offline_notfriend_limit, //非好友离线消息发送次数达到上限
          fail_offline_friend_forbid, //不可以给好友发送离线消息
          fail_offline_notfriend_forbid, //不可以给非好友发送离线消息
      };
      unsigned char   random;   //失败的时候使用来通知客户端
      unsigned char   result;
      unsigned int    param;
      CServerChatMsgRep() : PacketBase(SS_C_CHATMSG_REP, sizeof(CServerChatMsgRep))
      {
          PRO_ZERO_MEMORY(this, sizeof(CServerChatMsgRep));
      }
    };
    

redis数据库离线消息队列

  • 队列名称: queue:delaymsg:39 (39是内网区号)
  • 内容
    {"account":"kinglq002","content":"#21","fromaccount":"kinglq001","timespan":1603742104,"type":1}
    timespan:消息发送的时间戳
    type:消息类型,1表示离线聊天(后续有扩展可增加)