聯眾升級協議分析 續篇(四) (轉)

themoney發表於2007-10-05
聯眾升級協議分析 續篇(四) (轉)[@more@]

聯眾升級分析 續篇(四)

雲網(to:jimzj@21cn.com">jimzj@21cn.com)

接上篇

 

 :namespace prefix = o ns = "urn:schemas--com::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/,如需轉載,請註明出處,否則將追究法律責任。

相關文章