联众升级协议分析 续篇(四)
云网(Mailto:jimzj@21cn.com" rel="nofollow">jimzj@21cn.com)
接上篇
XML:namespace prefix = o ns = "urn:schemas-microsoft-com:Office:office" />
二、发牌命令
原来我分析牌时,因为是先从出牌入手的,所以得到的牌的代号只有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
来自 “ ITPUB博客 ” ,链接:http://blog.itpub.net/10794571/viewspace-974813/,如需转载,请注明出处,否则将追究法律责任。
转载于:http://blog.itpub.net/10794571/viewspace-974813/