联众升级协议分析5

 

联众升级协议分析 续篇(四)

云网(jimzj@21cn.com

接上篇

 

 

二、发牌命令

原来我分析牌时,因为是先从出牌入手的,所以得到的牌的代号只有13个,还有牌的颜色,所以在分析这个命令时一度陷入不能得到结果的地步,不过经过一天的苦想,终于明白过来了,呵呵,在这里先为自己能想到这个干杯一下。J

 

0x0050   17 20 00 00 04 00 00 00-01 00 00 00 16 20 00 00   . ........... ..

0x0060   29 00 00 00 19 00 00 00-FF FF FF FF F4 01 00 00   ).......?..

0x0070   00 00 00 00 38 4A 27 29-13 17 3B 5D 44 32 0F 12   ....8J')..;]D2..

0x0080   5A 58 6A 2E 45 0B 64 24-56 16 3A 3E 05            ZXj.E.d$V.:>.

 

从上面的数据看命令字是0x00002016,再上面一个命令字0x00002017是开始一局游戏标志,这个用来标志一些状态用的;再看一下0x19(也就是十进制的25)呵呵,想一下我们四个人打两付牌时8个底牌,总共是(54*2 – 8 / 4 = 25 刚好,这个位置就是发给我们的牌数(因为还有一付牌,三付牌)我们再看一下数据从38 4A 27 29-13 17 3B 5D 44 32 0F 12 5A 58 6A 2E 45 0B 64 24-56 16 3A 3E 05是不是刚好也就25个,这个就是服务器发给每一个玩家的牌了,在玩这个游戏时,我们在客户端看到的是一个一个牌得到的,但实际上,一开始我们就全部得到了,如果你解开了这个协议,一开始我们就知道了所有自己的牌,不就可以知道了能叫什么颜色,是否能反别人的牌,还有每一种花色的牌的多少,岂不是很好……

       我们定义的数据结构如下:

typedef struct _tagSHJIFaDePaiInfo

{

    int     nCount ;    //牌数

    char    cUser  ;   

    char    cFlag1 ;

    char    cFlag2 ;

    char    cFlag3 ;

 

    int     nFlag1 ;

    int     nFlag2 ;

}SHJIFaDePaiInfo, *lpSHJIFaDePaiInfo ;

结构中不包牌的信息,因为移动指针后,就可以读到牌的信息了(每一个位Byte表示一个牌),如下所示:

 

void __fastcall TFrmMain::RevFaDePaiInfo( char * pPackContent )

{

    SHJIFaDePaiInfo * pInfo = ( SHJIFaDePaiInfo * )pPackContent ;

 

    for( int i = 0 ; i < pInfo->nCount ; i ++ )

    {

        byte btCard = * ((byte *)(( byte * )( pInfo + 1 ) + i * sizeof( byte ))) ;      

              ………………

}

}

三、叫牌命令

每一轮出牌前总会有一个人先叫牌的信息,所以在这里这个命令会在出牌前,可能有多个这样的命令,但最后一个命令就是用户最终叫主了。

 

0x0000   11 20 00 00 18 00 00 00-01 00 E0 00 01 00 00 00   . ........?....

0x0010   01 00 00 00 01 00 00 00-DE 05 00 00 02 00 00 00   ........?......

 

叫牌的内容应该包括,那一个用户叫的牌,牌的颜色(黑桃,红桃,草花,方块),叫牌的数量(一个或一双),从上面的我添加的颜色的数据看到,正好就是这三个位置的信息了,这个可能你的多接收几次数据,对比后才会得到,我也是接收了几次叫牌的信息后才分析出来的:

所以我们定义的叫牌的数据结构如下所示:

typedef struct _tagSHJIJiaoPaiInfo

{

    char    cUser ;     //叫牌用户编号

    char    cFlag0 ;

    char    cFlag1 ;

    char    cFlag2 ;

    char    cColor ;    //颜色(大王=0x35,小王=0x34)

    char    cFlag3 ;

    char    cFlag4 ;

    char    cFlag5 ;

 

    char    cCount ;    //叫的张数

    char    cFlag6 ;

    char    cFlag7 ;

    char    cFlag8 ;

    char    cFlag14 ;

    char    cFlag9 ;

    char    cFlag10 ;

    char    cFlag11 ;

 

    int     nFlag12 ;

    int     nFlag13 ;

}SHJIJiaoPaiInfo, *lpSHJIJiaoPaiInfo ;

 

数据结构中的其它的数据标志位是暂时我还不清楚有什么用途,不过只要知道我们想要的足够的信息就可以了。

下面是取得叫牌的信息:

 

void __fastcall TFrmMain::RevJiaoPaiInfo( char * pPackContent )

{

    SHJIJiaoPaiInfo * pInfo = ( SHJIJiaoPaiInfo * )pPackContent ;

 

    if( m_eZhuColor != ( GAMECARDCOLOR )pInfo->cColor )

    {

        m_eZhuColor = ( GAMECARDCOLOR )pInfo->cColor ;

        ShowInitImagePic( m_cDaJi, m_eZhuColor ) ; //显示在界面上

    }

    SetJiaoPaiPic( pInfo->cUser, m_eZhuColor, pInfo->cCount ) ; //显示那一个用户叫牌

}

 

取得叫牌的信息,你就可以显示在自己的外挂界面上,同时也可以区分用户出牌时主还是付牌了J

 

四、扣底命令

如果你是庄家,会的扣底牌的信息,否则,服务器发送的这个指令中是不包含这个底牌的信息的。

 

0x0000   03 20 00 00 E4 00 00 00-03 00 00 00 1E 00 00 00   . ..?..........

0x0010   03 00 00 00 05 00 00 00-00 00 00 00 01 00 00 00   ................

0x0020   00 00 00 00 01 00 00 00-1D 00 00 00 03 00 00 00   ................

 

在这个指令中,并没有包括底牌的个数据,不知联众在做这个命令字是为会缺了这个?所以你必需自己去计算一下底牌的个数了,不过只有两种,一付牌和三付牌时是6个底,二付牌时是8个底,这样就可以把底牌的信息取得了,在扣底的信息中还包含了是那一个用户扣底的,也就是第一个出牌的户了,这个信息用来指示那一个用户最先出牌,不过如果知道庄家是谁也同样可以知道第一个出牌人的编号。定义的数据结构如下所示:

 

 

typedef struct _tagSHJICaoDiFlag

{

    char    cUser ;     //第一个出牌用户(庄家)

    char    cFlag0 ;

    char    cFlag1 ;

    char    cFlag2 ;

}SHJICaoDiFlag, *lpSHJICaoDiFlag ;

 

typedef struct _tagSHJICaoDiInfo

{

    int     nPosition ; //位置信息

 

    char    cColor ;    //牌颜色

    char    cFlag0 ;

    char    cFlag1 ;

    char    cFlag2 ;

 

    char    cCard  ;    //底牌

    char    cFlag3 ;

    char    cFlag4 ;

    char    cFlag5 ;

 

    int     nFlag6 ;

    int     nFlag7 ;

    int     nFlag8 ;

    int     nFlag9 ;

}SHJICaoDiInfo, *lpSHJICaoDiInfo ;

 

因为前段的信息只有一个,后段的每一个牌的信息是循环出现的,所以从扣底的个数就可以得到每一个底牌的信息了。

 

void __fastcall TFrmMain::RevCaoDiInfo( char * pPackContent, int nLen )

{

    SHJICaoDiFlag * pInfo = ( SHJICaoDiFlag * )pPackContent ;

 

    m_bCanCaculate = true ;  //开始计算标志

 

    m_ZhangJia = (( pInfo->cUser < POS_LEFT || pInfo->cUser > POS_BOT ) ? 0 : pInfo->cUser ) ;   

 

if( nLen == 4 ) return ;   //如果不包括底牌信息返回

 

    //底牌信息

    for( int i = 0 ; i < m_DiPaiCount ; i ++ )  // DiPaiCount是底牌的个数

    {

        SHJICaoDiInfo * pCard = ( SHJICaoDiInfo * )( ( char * )( pInfo + 1 ) + i * sizeof( SHJICaoDiInfo )) ;

 

              //显示在外挂界面上底牌的信息

        UnShowImagePicInfo(( GAMECARDCOLOR )pCard->cColor, pCard->cCard ) ;

        ShowPicOnImage(( GAMECARDCOLOR )pCard->cColor, pCard->cCard, PanelDIPAI ) ;

    }

}

 

取得和底牌信息可以显示在界面上,不必每次看是要自己去点击客户端的查看底牌信息按键,同时如果你是看别人打牌,他设置了不让旁观者看时,你也可以直接看到他的底牌信息,呵呵J


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值