组队优化

组队优化

需求

组队优化

配置相关

  • cs_match_rule.xml
  • 添加字段 team_convene_tm,表示发送队伍召集的时间间隔,秒;可不配置,默认60秒

双端交互

发送队伍召集 [新增]

交互协议

// 队伍召集条件类型
enum TeamConveneConditionType
{
    condition_division = 0,   // 段位要求
    condition_win_rate,       // 胜率要求
    condition_escape_rate,    // 逃跑率要求
    condition_level,          // 等级要求

    condition_count,
};

// 队伍召集条件
struct TeamConveneConditionItem
{
    unsigned int type;
    int  value;  // 0:没有这个条件要求, -1:这个条件不限制,大于0:对应的条件检查值
};

// 队伍召集发出请求
ABROAD_TEAM_CONVENE_SEND_REQ = 48436
struct ClientTeamConveneSendReq : public PacketBase
{
    static const unsigned int sc_max_condition_count = 4;

    // 发送频道
    enum emToChannel
    {
        channel_hall = 1,
        channel_guild = 2,
    };

    // 发送频道
    enum emToChannel
    {
        channel_hall = 1,
        channel_guild = 2,
    };

    unsigned int toChannel;  // emToChannel组合值
    unsigned int usingGoodsBaseId;  // 发送到大厅需要消耗诏令
    unsigned int msgLen;
    TeamConveneConditionItem conditions[sc_max_condition_count];  // 注意这里是定长4
    char conveneMsg[1024]; // 召集口号

    unsigned int GetLen()
    { 
        return sizeof(ClientTeamConveneSendReq) - sizeof(conveneMsg) + msgLen - sizeof(conditions) + count * sizeof(TeamConveneConditionItem);
    }

    ClientTeamConveneSendReq() :PacketBase(ABROAD_TEAM_CONVENE_SEND_REQ, sizeof(ClientTeamConveneSendReq))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientTeamConveneSendReq));
    }
};

// 队伍召集发出请求的回复
ABROAD_TEAM_CONVENE_SEND_REP = 48437
struct ClientTeamConveneSendRep : public PacketBase
{
    enum emResult
    {
        ok = 0,
        fail_frequently,        // 队伍召集发送太频繁
        fail_not_master,        // 队伍召集只能队长发送
        fail_start_game,        // 队伍已开始游戏
        fail_team_not_find,        // 队伍召集找不到队伍
        fail_self_not_meet,     // 自己不满足召集条件
        fail_noempty_pos,       // 队伍当前已满员
    };

    unsigned int result;
    unsigned int nextSendCountDown; // 下一次可发送的倒计时,result=ok/fail_frequently时有效
    ClientTeamConveneSendRep() :PacketBase(ABROAD_TEAM_CONVENE_SEND_REP, sizeof(ClientTeamConveneSendRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientTeamConveneSendRep));
    }
};

说明

  • 注意请求协议中的conditions数组是定长4;
  • 客户端根据选择的召集条件填充请求内容,无限制的条件的value为0;
  • 客户端发送之前先检查自身条件是否满足:入队条件、是否加入公会、是否有诏令等;
  • 服务端收到请求,检查是否可以发送召集;可以发送召集,则回复客户端,并发送聊天消息通知;

聊天消息通知 [修改]

交互协议

enum emchachannel
    {
        chanel_privatechat = 1, //私聊
        chanel_gametable,       //游戏中的桌子,旁观可以看到吗  
        chanel_user_speaker,    //小喇叭

        chanel_gm_speaker,      //gm小喇叭,不用花钱,呵呵
        chanel_gm_command,      //gm命令
        chanel_sys,             //系统广播

        chanel_user_little_speaker,    //小喇叭,只在当前模式的一个场中

        chanel_god_camp_lucky_item,     //神将营获得幸运物品奖励, chatmsg保存的结构如下:itemId(4个字节) itemCount(4个字节) itemId itemCount.......

        chanel_guild,            //公会频道
        chanel_gametable_team,    // 队伍频道    
        chanel_gamecamp,        // 阵营频道
        chanel_gametable_nowordsfilter,       //游戏中的桌子,不过滤屏蔽词

        chanel_mobile_action = 1000,
        chanel_mobile_system_private    = 1001,
        chanel_user_little_speaker_action        = 1002,    //带功能尾巴的信息,全局发送,要消耗小喇叭
        chanel_guild_action = 1003,        //公会功能频道
        chanel_lua_activity = 1004,    //lua活动
        chanel_team_convene = 1005,    //队伍召集,发送到大厅要消耗小喇叭,发送到公会不用

        channel_liveshow = 1100,        //直播消息通道
        chanel_num,// /  \在这个上面加频道消息类型
    };

enum EmMsgType
{
    MSGTYPE_NONE            = 0,    //无
    MSGTYPE_GUILD_ROLL,                //公会roll点
    MSGTYPE_GUILD_RECRUI,            //公会招募
    MSGTYPE_BAOXIANG,                // 宝箱
    MSGTYPE_ROOM_ROLL,                //房间roll点 
    MSGTYPE_GUILD_CREATE,            //公会创建
    MSGTYPE_GUILD_LEVELUP,            //公会升级
    MSGTYPE_GUILD_SHOP,                //公会道具购买
    MSGTYPE_NIANSHOU,                // 年兽
    MSGTYPE_TTRANKNEW1V1_RANKLV,    //天梯新1v1等级
    MSGTYPE_COMPOSE,                // 合成
    MSGTYPE_FEIGE,                    // 飞哥来了
    MSGTYPE_MARRIAGE,                // 结婚
    MSGTYPE_VOICE,                    // 短语音
    MSGTYPE_MATCHREWARD,            // 比赛奖励
    MSGTYPE_PHONESHOP,                // 手机商城
    MSGTYPE_EXHIBIT,
    MSGTYPE_LIVESHOW_NTF,            //直播时通知
    MSGTYPE_LIVESHOW_BULLET,        //直播聊天消息
    MSGTYPE_ANCHOR_GIFT,            //直播礼物
    MSGTYPE_EMAIL_BORDACAST,        //邮件广播
    MSGTYPE_LUA_ACTIVITY,            //lua活动
    MSGTYPE_HALL_TEAM_CONVENE,            //发往大厅的队伍召集
    MSGTYPE_GUILD_TEAM_CONVENE,         //发往公会的队伍召集
    //MSGTYPE_END                = 255,    //结尾
};

//聊天消息通知客户端
SS_C_CHATMSG_NTF=20613
//聊天消息通知客户端
struct SSCChatmsgNtf_Mobile : public PacketBase
{
    struct Patch
    {
        char                            sex;
        unsigned int                    sgx3;
        unsigned char                    msgtype;   // EmMsgType
        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[33];   //说话的目标人账号的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));
    }
};

说明

  • emchachannel新加channel类型 chanel_team_convene = 1005, //队伍召集,发送到大厅要消耗小喇叭,发送到公会不用;老版本不会处理;
  • EmMsgType新加类型MSGTYPE_HALL_TEAM_CONVENE、MSGTYPE_GUILD_TEAM_CONVENE;
  • 当channel=chanel_team_convene时,大厅(msgtype=MSGTYPE_HALL_TEAM_CONVENE)和公会(msgtype=MSGTYPE_GUILD_TEAM_CONVENE)收到聊天消息则需要解析chatmsg用于展示队伍召集链接,chatmsg格式:
    “%s{%d,%d,%d,%d,%d,%d,%s,[%d:%d,%d:%d…]}”,取值意思如下
    召集口号{
    消息类型(10),
    模式model,
    模式section,
    队伍id,
    现有队员人数,
    最大队员人数,
    队长昵称,
    [
    检查类型:检查值,
    检查类型:检查值,

    ]
    }

队伍召集进入 [新增]

交互协议

// 队伍召集加入请求
ABROAD_TEAM_CONVENE_ENTER_REQ = 48438
struct ClientTeamConveneEnterReq : public PacketBase
{
    static const unsigned int sc_max_condition_count = 10;

    enum emFromChannel
    {
        channel_hall = 1,
        channel_guild = 2,
    };

    unsigned int fromChannel;
    unsigned int teamId;
    unsigned int count;
    TeamConveneConditionItem conditions[sc_max_condition_count];

    ClientTeamConveneEnterReq() :PacketBase(ABROAD_TEAM_CONVENE_ENTER_REQ, sizeof(ClientTeamConveneEnterReq))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientTeamConveneEnterReq));
    }
};

// 队伍召集加入回复
ABROAD_TEAM_CONVENE_ENTER_REP = 48439
struct ClientTeamConveneEnterRep : public PacketBase
{
    enum emResult
    {
        ok = 0,
        fail,
        fail_already_in,            // 我已经在这个队伍
        fail_team_not_exist,        // 队伍不存在
        fail_in_team,               // 我在其他队伍中
        fail_in_game,               // 我在游戏中
        fail_team_start_game,        // 队伍已开始游戏
        fail_not_meet_division,        // 不满足段位要求
        fail_not_meet_winrate,        // 不满足胜率要求
        fail_not_meet_escaperate,   // 不满足逃跑率要求
        fail_not_meet_level,        // 不满足等级要求
        fail_enterpage,             // 进入分页失败
        fail_locked,                // 排位赛被锁定了
        fail_escape_punish,         // 逃跑惩罚中
        fail_max_match_cnt_per_day, // 达到每天匹配上限了
        fail_readyoffline_punish,   // 匹配超时未准备惩罚中
        fail_noempty_pos,           // 队伍没有空位置了
        fail_target_check,          // 队伍不可加入了
    };

    unsigned int result;
    unsigned int fromChannel;
    unsigned int teamId;
    char         enterNickName[sc_max_nickname_len];

    // 成功更新数据
    //失败更新数据 fail_not_meet_division/fail_not_meet_winrate/fail_not_meet_escaperate/fail_not_meet_level/fail_noempty_pos
    unsigned int msgLen;
    char conveneMsg[1024];
    ClientTeamConveneEnterRep() :PacketBase(ABROAD_TEAM_CONVENE_SEND_REP, sizeof(ClientTeamConveneEnterRep))
    {
        PRO_ZERO_MEMORY(this, sizeof(ClientTeamConveneEnterRep));
    }
};

说明

  • 客户端从大厅或公会点击队伍召集链接,最好可以做个条件检查,不满足则不用发送请求,满足需要将召集条件填充到请求协议中;
  • 进入失败,根据result进行相应处理,具体看协议,最新条件保存在conveneMsg,解析同上;
  • 进入成功,队伍里的队员都会收到通知;

日志记录

召集发布日志

  • 日志和大厅聊天数据一样记录到kafka上;
  • param1=4;
  • log_info里面的msg_type=1005,msg表示发送的信息,params表示召集发送到哪里(1:大厅,2:公会,3:大厅+公会)

召集进入日志

  • mysql tblcommon*
  • op_type=1934,param1=从哪里进入(1:大厅,2:公会), param2:队伍id, log_info:队伍召集口令

测试注意点

  • 发送到大厅需要消耗诏令,发送到公会不用;