找回密码
 点一下
查看: 10512|回复: 47

[中文版首发]《魔兽争霸III 数据包格式规范》(帖子版+下载版DOC)

[复制链接]
发表于 2010-2-4 13:56:49 | 显示全部楼层 |阅读模式
这个是GA小黑屋的强力人士ca(Soar)同学2天前写的一篇DOC文档。里面详细阐述了War3局域网游戏的数据包格式。

不过CA同学在国外呆久了,习惯写英文文档,所以这个其实是英文版的。他将其中文化交由我来完成了。

于是这个便是经过头目中文化的《魔兽争霸III 游戏数据包格式规范中文版》。

经原作者同意,译文略有增补,主要是修正原文一些缺失和易混淆之处。

英文原文首发于ca的BLOG
http://www.soardev.com/blog/

请大家特别注意:作者Soar是个中国人。
对了Soar就是MPQMaster的作者,请膜拜。

完整DOC文档下载在此,帖子版见1-5楼。

War3GamePackets.rar

22 KB, 下载次数: 978

评分

参与人数 1威望 +5 收起 理由
Flyingsnow + 5 鹿过磨白

查看全部评分

 楼主| 发表于 2010-2-4 13:57:16 | 显示全部楼层



魔兽争霸III数据包规范

v0.3 by Soar Qin
(麦德三世 译)



1. 本文涉及的数据包种类


    a)     魔兽争霸III拥有以下类型的数据包

      i.       局域网UDP数据包。

      这类数据包都用于在游戏准备阶段广播/检测游戏信息。


      ii.      游戏中TCP数据包。

      这类数据包在游戏准备阶段和实际游戏阶段都会被用到。

      我会分两部分来介绍这类数据包。


      iii.    Battle.net TCP/UDP 数据包。

      有时间的话,我会用一份单独的doc文档来介绍这部分。

      目前可暂且参考 http://www.bnetdocs.org.


    b)     本规范中仅讨论前二类数据包。

回复

使用道具 举报

 楼主| 发表于 2010-2-4 13:57:29 | 显示全部楼层
1. 数据包头

魔兽争霸III中使用的所有数据包都拥有四字节的包头,具体如下表:




字节 / 类型

用途

1 / uint8

魔数标志位。

0xF7 – 局域网UDP或游戏中TCP数据包(本文中所有数据包都采用这个标志)

0xFF -- Battle.net战网数据包

1 / uint8

操作码。详情参考第3、4、5部分。

2 / uint16

数据包长度(包括4字节的包头部分)。


回复

使用道具 举报

 楼主| 发表于 2010-2-4 13:57:37 | 显示全部楼层
1. 局域网UDP数据包

a)     操作码0x2F

这种数据包用于查询局域网游戏,它可用于两种场合:1.应答0x31或0x32数据包以查询指定游戏的信息。2.玩家进入局域网游戏界面时发送。向255.255.255.255广播以查询所有可加入的游戏。

字节 / 类型

用途

4 / uint32

以低位在前的方式表示游戏类型。

'W3XP' = TFT    'WAR3' = ROC

4 / uint32

游戏版本。

比如War3 1.24,这里就填24。

4 / uint32

游戏ID, 广播时置零。



b)     操作码0x30

用于应答UDP 0x2F数据包,该数据包包含完整的游戏信息。

字节 / 类型

用途

4 / uint32

以低位在前的方式表示操作系统信息。

'IX86' = Windows    'XMAC' = Mac OS X

4 / uint32

以低位在前的方式表示游戏类型。

4 / uint32

游戏ID。

4 / uint32

系统时钟(比如Windows就用GetTickCount()来获得)。

N/以'\\0'结束的字符串

这是一个经过编码的字符串,包含着大量重要的游戏信息。参考附注。

4 / uint32

玩家位置数。

4 / uint32

游戏标志。据我所知 0x01 = 剧情游戏;0x09 = 自定义游戏。

4 / uint32

游戏内玩家数。

4 / uint32

非电脑玩家位置数。

   综上所述,我们可以得出这样的公式:显示的游戏内玩家数=游戏内玩家数+(位置数-非电脑位置数)

4 / uint32

未知。通常是0-0x80

2 / uint16

以低位在前方式表示用于侦听连接的TCP游戏端口。




附注(编码字符串):

所有值为偶数的字节都+1。因此所有编码后的字节都是奇数。并用一个控制字节来保存接下去7字节的转换方式。

因为所有空字节都会变成1,因此编码字符串内不会包含空字节。但空字节用于表征字符串的结束。

编码字符串以一个控制字节开头。

控制字节中第1-7位(不包括第0位)分别依次对应控制字节后的7个字节。

第0位无作用,永远设为1。

解码方式如下:

如果对应位为'1',那么该字符不作修改。

如果对应位为'0',那么该字符的值要减去1。

解码完一个控制字节其后的七个字节后,接下去的字节又是一个新的控制字节。

重复操作直到数据流中出现NULL字符。



用C语言解码的样例:

[codes=c]
char* EncodedString;
char* DecodedString;
char  mask;
int   pos=0, dpos=0;
while (EncodedString[pos] != 0)
{
  if (pos%8 == 0) mask=EncodedString[pos];
  else
  {
    if ((mask & (0x1 << (pos%8))) == 0)
      DecodedString[dpos++] = EncodedString[pos] - 1;
    else
      DecodedString[dpos++] = EncodedString[pos];
  }
  pos++;
}
[/codes]
编码方案的另一种理解方式如下:

每个字符的第0位都移到控制字节,然后本身设为1。

解码后字符串的结构:

字节 / 类型

用途

4 / uint32

游戏设置。

1 / uint8

永远为0。

2 / uint16

地图宽度。

2 / uint16

地图高度。

4 / uint32

地图本地校验码。

N/以'\\0'结束的字符串

地图名。

N/以'\\0'结束的字符串

主机用户名。

1 / uint8

永远为0(也算个以'\\0'结束的字符串?)

20 / uint8[20]

地图本地SHA-1哈希值,这一段是1.23版后添加的,以防止地图互通。

关于SHA-1哈希和地图校验的算法,我会在另一篇文章里讨论。



c)     操作码0x31

主机建立游戏后会向255.255.255.255广播该数据包。

字节 / 类型

用途

4 / uint32

以低位在前的方式表示游戏类型。

4 / uint32

游戏版本。

4 / uint32

游戏ID(初始为1,随着逐个游戏的创建而自增)。



d)     操作码0x32

游戏内玩家数发生变更后会向255.255.255.255广播该数据包。

字节 / 类型

用途

4 / uint32

游戏ID。

4 / uint32

显示的游戏内玩家数。

4 / uint32

玩家位置总数。



e)     操作码0x33

游戏取消后会向255.255.255.255广播该数据包。

字节 / 类型

用途

4 / uint32

游戏ID

回复

使用道具 举报

 楼主| 发表于 2010-2-4 13:58:02 | 显示全部楼层
1. 游戏准备阶段的TCP包

a)     操作码0x01

保持连接存活,也用于游戏进行中。

字节 / 类型

用途

4 / uint32

系统时钟(比如Windows就用GetTickCount()来获得)。



b)     操作码0x04

向新加入的玩家发送,告诉他们各个玩家位置的状态及他们所处的位置。

字节 / 类型

用途

2 / uint16

接下去5段信息的总长度(到“开始位置数”为止,不包括本段的2个字节。)

1 / uint8

玩家位记录的条数,这里记为RN。

9 * RN / 玩家位记录 * RN

每条玩家位记录代表每个玩家位的详细信息。每条记录的结构如下:

uint8   玩家ID。0为电脑,0xFF为空。

uint8   地图下载进度。0-100,0xFF代表'?'。

uint8   玩家位状态。0-空,1-关闭,2-已有玩家。

uint8   是否电脑。0-活人,1-电脑。

uint8   队伍。0-11,12代表ob/裁判。

uint8   颜色。0-11,12代表ob/裁判。

uint8   种族。

0x01-人类,0x02-兽人,

0x04-暗夜精灵,0x08-亡灵,

0x20-随机,0x40-地图未指定。

uint8   AI等级。0-简单,1-普通,2-疯狂

uint8   生命百分比。

通常为50,60,70,80,90,100。用GHost++可设为其他值。

4 / uint32

游戏的初始随机种子。

1 / uint8

队伍和种族锁定标记:

0x01 – 队伍已锁定

0x02 – 种族已锁定

0x04 – 种族为随机(无法与0x02共用)

1 / uint8

地图开始位置数。

1 / uint8

为新加入玩家分配的玩家位。

16 / sockaddr_in

主机用getpeername()获得的目标玩家地址。



c)     操作码0x06

向新加入的玩家发送,告诉他们已经在游戏中的玩家列表,每个对应玩家会发一个0x06的包。

字节 / 类型

用途

4 / uint32

始终为0x02,可能是sockaddr_in的结尾数字?

1 / uint8

在玩家位信息中显示的玩家ID。

N/以'\\0'结束的字符串

玩家名。最长16字节(包括结尾的'\\0')。

1 / uint8

后续的额外字节数。局域网游戏中总是1。

N / uint8[N]

额外字节。局域网游戏中总是一个\\0字节。

16 / sockaddr_in

从getpeername()获得的该玩家地址。

16 / sockaddr_in

从NAT路由(如果有)获得的该玩家地址(似乎只用于Battle.net战网)。



d)     操作码0x07

玩家离开游戏时向所有玩家发送。也用于游戏进行中。

字节 / 类型

用途

1 / uint8

玩家ID。

4 / uint32

离开原因标志。这部分还需进一步研究。



e)     操作码0x08

当玩家的地图载入完成后向所有玩家发送(此时主机将会从客户端处收到0x23数据包),这样所有玩家的读取界面上,该玩家的姓名板背景会变成绿色。

字节 / 类型

用途

1 / uint8

玩家ID。



f)      操作码0x09

和0x04基本相同,但缺少最后两段。当任何玩家位相关信息发生改变时向所有玩家发送。(比如说正在下载地图,玩家改变位置等等。)

字节 / 类型

用途

2 / uint16

接下去5段信息的总长度(到“开始位置数”为止,不包括本段的2个字节。)

1 / uint8

玩家位记录的条数,这里记为RN。

9 * RN / 玩家位记录 * RN

每条玩家位记录代表每个玩家位的详细信息。每条记录的结构如下:

uint8   玩家ID。0为电脑,0xFF为空。

uint8   地图下载进度。0-100,0xFF代表'?'。

uint8   玩家位状态。0-空,1-关闭,2-已有玩家。

uint8   是否电脑。0-活人,1-电脑。

uint8   队伍。0-11,12代表ob/裁判。

uint8   颜色。0-11,12代表ob/裁判。

uint8   种族。

0x01-人类,0x02-兽人,

0x04-暗夜精灵,0x08-亡灵,

0x20-随机,0x40-地图未指定。

uint8   AI等级。0-简单,1-普通,2-疯狂

uint8   生命百分比。

通常为50,60,70,80,90,100。用GHost++可设为其他值。

4 / uint32

游戏的初始随机种子。

1 / uint8

队伍和种族锁定标记:

0x01 – 队伍已锁定

0x02 – 种族已锁定

0x04 – 种族为随机(无法与0x02共用)

1 / uint8

地图开始位置数。



g)     操作码0x0A

只包含4字节的包头,当主机按下开始游戏,并开始倒数5秒时发送。



h)     操作码0x0B

只包含4字节的包头,当5秒计时结束时发送,提醒所有玩家进入载入界面。



i)       操作码0x0F

向聊天信息的接收者发送。

如果是私密/小队频道的聊天,而且发送者和接收者可通过TCP连接,那么这个数据包是直接发送的。

否则玩家会先向主机发送一个0x28数据包,主机再发给所有接收者。

注意某些平台会阻断客户端之间的连接,因此所有聊天信息都要通过主机来传递,这就存在潜在的安全问题,可能导致私聊信息泄露。

字节 / 类型

用途

1 / uint8

需发送聊天信息的目标玩家数,这里记为PN

PN / uint8 * PN

每个uint8保存一个目标玩家ID。

1 / uint8

聊天信息发送者的玩家ID

1 / uint8

聊天信息标志。

0x10-准备阶段,0x20-游戏阶段

4 / uint32

发送目标标志。

0x00 – 向所有玩家发送

0x01 – 向盟友发送

0x02 – 向OB/裁判发送

0x03-0x0E – 向特定玩家发送(玩家ID=值-2)

当聊天信息标志为0x10(即游戏准备阶段)时,这段信息将被排除。

N/以'\\0'结束的字符串

聊天字符串。





j)       操作码0x1B

只包含4字节的包头,向玩家发布,告诉他们你已断开游戏,即使是主动退出游戏的情况。同样适用于游戏进行阶段。



k)     操作码0x1E

这是当一个玩家加入游戏的时候向主机发送的第一份数据包,包含了该玩家的信息。

字节 / 类型

用途

4 / uint32

游戏ID。

4 / uint32

游戏开始后经过的毫秒数。

1 / uint8

始终为0。

2 / uint16

客户端的游戏端口。用于地图信息交换、直接私聊、主机变更等等。

4 / uint32

客户端会话计数器。初始值为1,每加入一个游戏都会自增。

N/以'\\0'结束的字符串

用户名。

2 / uint16

可用的公共端口。这里记为P。

16 * P / sockaddr_in * P

每个公共端口都有一个套接字sockaddr_in结构。



l)       操作码0x21

向主机发送主动离开游戏的信息(主机总是会回复0x1B以断开游戏)。同样适用于游戏进行中。



字节 / 类型

用途

4 / uint32

理由标志。还需进一步研究。



m)   操作码0x23

只包含4字节的包头。告诉主机当前玩家已完成游戏载入。



n)     操作码0x28

该数据包有2个功能:

i. 请求主机转发聊天信息。主机会把此信息转发给目标玩家。同样适用于游戏进行阶段。

ii. 在游戏准备阶段对玩家位进行变更。

字节 / 类型

用途

1 / uint8

需要发送聊天信息的玩家总数,这里记为PN

PN / uint8 * PN

每个uint8保存一个需发送聊天信息的玩家ID。

1 / uint8

聊天信息发送者的玩家ID。

1 / uint8

聊天信息标志。

0x10 – 游戏准备阶段的聊天

0x11 – 变更小队

0x12 – 变更颜色

0x13 – 变更种族

0x14 – 变更生命百分比

0x20 – 游戏进行阶段的聊天

当聊天信息标志 = 0x10或0x20:

字节 / 类型

用途

4 / uint32

发送目标标志。

0x00 – 向所有玩家发送

0x01 – 向盟友发送

0x02 – 向OB/裁判发送

0x03-0x0E – 向特定玩家发送(玩家ID=值-2)

当聊天信息标志为0x10(即游戏准备阶段)时,这段信息将被排除。

N/以'\\0'结束的字符串

聊天信息。

当聊天信息标志 = 0x11-0x14:

字节 / 类型

用途

1 / uint8

数据。

聊天信息标志 = 0x11: 小队

聊天信息标志 = 0x12: 颜色

聊天信息标志 = 0x13: 种族

聊天信息标志 = 0x14: 生命百分比

参考0x04/0x09玩家位信息部分。



o)     操作码0x3D

由主机发送,询问加入的玩家是否拥有当前地图。

客户端将回复0x42数据包。

字节 / 类型

用途

4 / uint32

地图ID(?)

N/以'\\0'结束的字符串

地图路径

4 / uint32

地图大小(单位为字节)。

4 / uint32

整个地图文件的CRC32。

4 / uint32

地图本地校验码。

20 / uint8[20]

地图本地SHA-1哈希值,这一段是1.23版后添加的,以防止地图互通。



p)     操作码0x3F

当目标玩家没有地图(即玩家向主机发送的0x42数据包中可用地图大小<实际地图大小)的时候发送,客户端能够互相直接连接时也会互相发送。(我注意到可能存在一种操作码0x3E用于向非主机玩家查询地图,但尚未测试。)

字节 / 类型

用途

4 / uint32

地图ID(?)

1 / uint8

玩家ID



q)     操作码0x42

向主机发送,报告自己是否有地图或地图下载进度。

字节 / 类型

用途

4 / uint32

地图ID(?)

1 / uint8

下载源玩家ID或主机ID

4 / uint32

可用地图尺寸(下载进度)



r)      操作码0x43

向玩家发送地图数据,即传图。

字节 / 类型

用途

1 / uint8

目标玩家ID

1 / uint8

源玩家ID

4 / uint32

地图ID(?)

4 / uint32

地图文件偏移,用于写入数据。

4 / uint32

后面这段数据的CRC32。

N / uint8[N]

地图数据。



s)      操作码0x44

应答0x43数据包,并汇报已下载地图尺寸以示接受。

注意地图发送者并不会等收到这个包后再发送下一个0x43传图包。

字节 / 类型

用途

1 / uint8

目标玩家ID

1 / uint8

源玩家ID

4 / uint32

地图ID(?)

4 / uint32

已下载的地图尺寸。



t)      操作码0x45

该数据包用于回复0x3F数据包,以拒绝从目标玩家处下载地图。

字节 / 类型

用途

1 / uint8

目标玩家ID

1 / uint8

源玩家ID

4 / uint32

地图ID(?)



u)     操作码0x46

用于应答0x01保持连接存活的数据包。同样适用于游戏进行阶段。

字节 / 类型

用途

4 / uint32

与0x01数据包的值相同。


回复

使用道具 举报

 楼主| 发表于 2010-2-4 13:58:07 | 显示全部楼层
1. 游戏中TCP数据包

a)     操作码0x0C

游戏数据包,每100毫秒向局域网中所有玩家发送(战网上是250毫秒,有工具可以调整这个值。)。

字节 / 类型

用途

2 / uint16

游戏已用时间,单位是毫秒。

2 / uint16

下一段数据的CRC32的低16位。

注意:如果游戏数据为空,这段数据本身也会被排除,这样整个包就只有6字节。

N / uint8[N]

游戏数据。

如果游戏数据超过1446字节,整段数据将被分割成若干个0x48数据包,并以一个0x0C数据包结尾。这是为了避免某些路由的最大传输单位限制。

游戏数据与录像数据相同因此其格式可以参考以下文档:

http://www.repking.com.cn/w3g_actions.txt

http://www.repking.com.cn/w3g_format.txt

b)     操作码0x0E

这种数据包很少见,只在游戏不同步时发送。尚需进一步研究。



c)     操作码0x14

向玩家发送,告诉他们:你已经被主机踢了。(比如主机离开游戏)

字节 / 类型

用途

1 / uint8

玩家ID



d)     操作码0x48

就是缺少游戏已用时间的游戏数据包,用于游戏数据分多个包发送的情况。

字节 / 类型

用途

2 / uint16

游戏已用时间,单位是毫秒。这里始终是0。

2 / uint16

下一段数据的CRC32的低16位。

注意:如果游戏数据为空,这段数据本身也会被排除,这样整个包就只有6字节。

N / uint8[N]

游戏数据。



e)     操作码0x26

当玩家进行了一些操作时发送给主机。主机会收集所有玩家的操作并发回包含所有玩家操作的0x0C/0x48数据包作为应答。

字节 / 类型

用途

N / uint8[N]

玩家操作数据,参考0x0C以获得更多信息。



f)      操作码0x27

同步数据包,当收到0x0C游戏数据包时发送给主机。

字节 / 类型

用途

4 / uint32

同步哈希值。

主机将在本地计算哈希值,并与每个玩家的0x27数据包比较。一旦不同步现象产生,即0x27数据包的哈希值与主机计算不符,该玩家将立刻被断开。
回复

使用道具 举报

发表于 2010-2-4 14:24:17 | 显示全部楼层

Re:[中文版首发]魔兽争霸III 游戏数据包格式规范(帖子版+下载版DOC)

对thewisp1等研究协议的人来说就是神作。

鹿过膜拜
回复

使用道具 举报

发表于 2010-2-4 14:24:44 | 显示全部楼层
总感觉很厉害的路过了。
回复

使用道具 举报

发表于 2010-2-4 14:25:42 | 显示全部楼层
[s:115]

这只是一把刀,用来切菜还是用来杀人要看你了
回复

使用道具 举报

发表于 2010-2-4 14:30:48 | 显示全部楼层
擦明天回天朝。
回复

使用道具 举报

发表于 2010-2-4 14:32:44 | 显示全部楼层
下载 慢慢看
回复

使用道具 举报

发表于 2010-2-4 14:33:16 | 显示全部楼层
引用第11楼<font color=gre于2010-02-04 14:30发表的  :
擦明天回天朝。

看成了“明天回朝”
回复

使用道具 举报

发表于 2010-2-4 14:37:56 | 显示全部楼层
竟然是MPQmaster的作者,膜拜
回复

使用道具 举报

发表于 2010-2-4 14:45:13 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
回复

使用道具 举报

发表于 2010-2-4 15:15:49 | 显示全部楼层
a.jpg
回复

使用道具 举报

 楼主| 发表于 2010-2-4 15:18:07 | 显示全部楼层
小A电脑还行~~
回复

使用道具 举报

发表于 2010-2-4 15:25:45 | 显示全部楼层
炫耀啊,无聊
回复

使用道具 举报

 楼主| 发表于 2010-2-4 15:28:31 | 显示全部楼层
不过不及我的~~老白的神机就更不用说了~~
回复

使用道具 举报

发表于 2010-2-4 15:34:28 | 显示全部楼层
唔唔~今天刚刚陪配的,记得头的指数有夸张的5.3罢……?
回复

使用道具 举报

发表于 2010-2-4 16:19:04 | 显示全部楼层
路过膜拜
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 点一下

本版积分规则

Archiver|移动端|小黑屋|地精研究院

GMT+8, 2024-12-24 01:17 , Processed in 0.602882 second(s), 25 queries .

Powered by Discuz! X3.5

© 2001-2023 Discuz! Team.

快速回复 返回顶部 返回列表