D2S是用GO编写的二进制解析器,用于解析.d2s文件。这是游戏Diablo II用于保存有关某个字符的所有信息的二进制格式。
该软件包是为Diablo II的私人服务器构建的,称为Slash Diablo,为服务器上的所有字符构建了军械库。任何人都可以在任何给定时间点看到有关特定角色的所有内容。这是一些例子。
$ go get github.com/nokka/d2s package main
import (
"fmt"
"log"
"os"
"github.com/nokka/d2s"
)
func main () {
path := "nokka.d2s"
file , err := os . Open ( path )
if err != nil {
log . Fatal ( "Error while opening .d2s file" , err )
}
defer file . Close ()
char , err := d2s . Parse ( file )
if err != nil {
log . Fatal ( err )
}
// Prints character name and class.
fmt . Println ( char . Header . Name )
fmt . Println ( char . Header . Class )
}标头是765 byte长结构,其中包含大多数字符元数据。
| 抵消 | 字节 | 描述 |
|---|---|---|
| 0 | 4 | 标识符 |
| 4 | 4 | 版本ID |
| 8 | 4 | 文件大小 |
| 12 | 4 | 校验和 |
| 16 | 4 | 活跃武器 |
| 20 | 16 | 角色名称 |
| 36 | 1 | 角色状态 |
| 37 | 1 | 角色进展 |
| 38 | 2 | 未知 |
| 40 | 1 | 角色类 |
| 41 | 2 | 未知 |
| 43 | 1 | 角色级别 |
| 44 | 4 | 未知 |
| 48 | 4 | 上一次比赛 |
| 52 | 4 | 未知 |
| 56 | 64 | 分配的技能 |
| 120 | 4 | 左鼠标按钮技能ID |
| 124 | 4 | 右鼠标按钮技能ID |
| 128 | 4 | 左交换鼠标按钮技能ID |
| 132 | 4 | 右交换鼠标按钮技能ID |
| 136 | 32 | 字符菜单外观 |
| 168 | 3 | 困难 |
| 171 | 4 | 地图ID |
| 175 | 2 | 未知 |
| 177 | 2 | 雇佣军死亡 |
| 179 | 4 | 雇佣军身份证 |
| 183 | 2 | 雇佣名称ID |
| 185 | 2 | 雇佣军类型 |
| 187 | 4 | 雇佣经验 |
| 191 | 144 | 未知 |
| 335 | 298 | 任务 |
| 633 | 81 | 航点 |
| 714 | 51 | NPC介绍 |
字符名称为[16]byte该字节将包含名称,每个byte一个字母。这个名称可以长16个字符,一个较短的名称将在名称后面的0x00填充,直到我们达到16 bytes 。
-或_ 。 角色状态是一个byte ,根据角色的状态,将设置不同的位。仍然没有弄清楚它们,但这是最重要的。
| 7 | 6 | 5 | 4 | 3 | 2 | 1 | 0 |
|---|---|---|---|---|---|---|---|
| ? | 梯子 | 扩张 | ? | 死了 | 铁杆 | ? | ? |
尚未实施。
每当您杀死ACT老板时,价值都会增加。
| 价值 | 标准 | 铁杆 |
|---|---|---|
| 0-3 | - | - |
| 4-7 | 先生/夫人 | 计数/伯爵夫人 |
| 8-11 | 主/女士 | 公爵/公爵夫人 |
| 12 | 男爵/男爵夫人 | 国王/王后 |
| 价值 | 扩张 | 扩展铁杆 |
|---|---|---|
| 0-3 | - | - |
| 5-8 | 杀手 | 驱逐舰 |
| 10-13 | 冠军 | 征服者 |
| 15 | 族长/族长 | 监护人 |
字符类是一个byte ,其中不同的值代表类。
| 班级 | 价值 |
|---|---|
| 亚马逊 | 0x00 |
| 巫婆 | 0x01 |
| 死灵法师 | 0x02 |
| 圣骑士 | 0x03 |
| 野蛮人 | 0x04 |
| 德鲁伊 | 0x05 |
| 刺客 | 0x06 |
上次播放保存为unit32 Unix Timestamp,例如1495882861 。
分配的技能部分是16个技能ID的一个数组,每个技能ID是4 byte整数(UINT32)。如果未分配技能,则值为0x00 。
任务结构是298 byte部分,描述了游戏中的所有任务,但还包含有关ACT旅行和NPC介绍的数据。每个任务是2 byte长。
| 抵消 | 字节 | 内容 |
|---|---|---|
| 335 | 4 | 哇! |
| 339 | 6 | 未知 |
一个任务长2 byte ,我创建了一个通用quest结构,该结构是否已完成,该结构是否完成。每个任务都有许多独特的位置,具体取决于任务的不同里程碑。例如,如果您是否消耗了Quest“冰监狱”的抵抗滚动。
| 少量 | 描述 |
|---|---|
| 0 | 任务完成了 |
冰狱是我唯一不愿实施的任务,因为我需要知道角色是否会增加滚动的阻力。
| 少量 | 描述 |
|---|---|
| 0 | 任务完成了 |
| 7 | 消耗滚动 |
这种结构将其重复3次,一次是正常,噩梦和地狱。偏移是任务结构的偏移。
| 抵消 | 字节 | 描述 |
|---|---|---|
| 0 | 2 | 如果您在Act I中被介绍给Warriv,则设置为1 |
| 2 | [6]quest | 所有六个对Act I的任务。 |
| 14 | 2 | 如果您参加了第二幕,则设置为1 。 |
| 16 | 2 | 如果您被介绍给Jeryn,则设置为1 。 |
| 18 | [6]quest | 所有六项诉讼的任务。 |
| 30 | 2 | 如果您参加了第三幕,则设置为1 。 |
| 32 | 2 | 如果您被介绍给Hratli,则设置为1 。 |
| 34 | [6]quest | 所有六个行为的任务。 |
| 46 | 2 | 如果您旅行第四行,则设置为1 。 |
| 48 | 2 | 如果您被介绍给第四幕,则设置为1 。 (如果您旅行就拥有它) |
| 50 | [6]quest | ACT IV只有3个任务,因此该结构在这里有6个空字节。 |
| 62 | 2 | 如果您曾1 V. V. |
| 64 | 2 | 在完成恐怖结束并与第四幕中的该隐交谈后,似乎已设置为1。 |
| 66 | 4 | 似乎是某种填充。 |
| 70 | [6]quest | 所有六个对第五号法案的任务。 |
| 82 | 14 | 在所有任务数据之后,某种填充。 |
未实施
未实施
遵循标题是“属性”部分,该部分布局由9 bit属性ID组成,其次是n bit长度属性值。该部分以9 bit值为0x1ff终止。值得一提的是,这些领域有点逆转。基本上,如果您发现00100111位,它们将被逆转为11100100 。
| ID | 属性 |
|---|---|
| 0 | 力量 |
| 1 | 活力 |
| 2 | 灵巧 |
| 3 | 活力 |
| 4 | 未使用的统计数据 |
| 5 | 未使用的技能 |
| 6 | 当前的HP |
| 7 | 最大HP |
| 8 | 当前法力 |
| 9 | 麦克马娜 |
| 10 | 当前的耐力 |
| 11 | 马克斯耐力 |
| 12 | 等级 |
| 13 | 经验 |
| 14 | 金子 |
| 15 | 藏有黄金 |
| 位长度 | 属性 |
|---|---|
| 10 | 力量 |
| 10 | 活力 |
| 10 | 灵巧 |
| 10 | 活力 |
| 10 | 未使用的统计数据 |
| 8 | 未使用的技能 |
| 21 | 当前的HP |
| 21 | 最大HP |
| 21 | 当前法力 |
| 21 | 麦克马娜 |
| 21 | 当前的耐力 |
| 21 | 马克斯耐力 |
| 7 | 等级 |
| 32 | 经验 |
| 25 | 金子 |
| 25 | 藏有黄金 |
for {
// 1. read 9 bits id. (reverse them)
// 2. if the id is 0x1ff, terminate the loop
// 3. read bit length from attribute map for that id.
// 4. read bit length nr of bits.
}技能是一个32 byte部分,其中包含2 byte标头,具有if值和30 byte的技能数据。每个班级都有30个技能,因此每种技能都可以获得1 byte 。关于技能映射的棘手部分是,每个班级都有不同的偏移量,其中特定于类技能的技能图,然后将30个索引进入地图。因此,例如,刺客的抵消为251 。这意味着刺客技能在251和281的索引之间,正好是30个索引。
| 类型 | 字节 | 价值 |
|---|---|---|
| 标题 | 2 | if |
| 技能 | 30 | [30]技能 |
| 班级 | 抵消 |
|---|---|
| 亚马逊 | 6 |
| 巫婆 | 36 |
| 死灵法师 | 66 |
| 圣骑士 | 96 |
| 野蛮人 | 126 |
| 德鲁伊 | 221 |
| 刺客 | 251 |
这是迄今为止最棘手的部分。项目部分以4 byte标头开始,其中包含jm值JM和一个uint16值,该值是您当前字符的项目。配备,库存,储藏,立方体和皮带全部包括。
本节的字节长度在阅读完整之前是未知的,因为每个项目的位长度取决于其质量,插座数量和拥有的魔法属性。
每个项目都遵循某种模式,这是:
每个项目都以111位的简单数据开始,所有项目都包含。这是像项目类型一样的信息,如果它是插座,则位置ID(例如配备或存放)等。
每个项目还具有一个名为SimpleItem的布尔值,该布尔值长1一点,如果将其设置为1 ,则该项目不含更多位,而下一个项目开始。
如果该项目不是简单的项目,则意味着它将在最初的111位之后具有大量数据。其中一些例子是稀有级别,神奇的后缀,神奇的词缀,如果是鲁棒,个性化的,是集合的一部分,特定于班级等。
最后但并非最不重要的一点是,该物品是否会列出神奇的属性列表,具体取决于它是否是Runeword,魔术,稀有,制作,独特的部分等等。
这些列表类似于我们将阅读的属性部分:
9 bit idn bits of magical properties0x1ff terminator当我们击中终结器0x1ff时,下一个项目开始。
神奇的属性是可能发生在项目上的独特属性,每个属性的位长度不同,地图很大。
这是具有ID 83的魔法属性,每个3位长3位。
83 : {Bits: [] uint { 3 , 3 }, Name : "+{1} to {0} Skill Levels" },所有神奇的属性都映射在item.go文件中。
如果您的角色目前已经死亡,并且当您进入游戏时,尸体就在地面上,则设备的物品将在此项目结构中。这是一个包含标题JM尸体标题16 bytes然后是类似于项目列表的项目数。
阅读尸体项目的确切方式与上一部分一样。
如果您的角色是在破坏的扩张之王中创建的,如果将包含2个部分。
雇佣部门以2 byte标头为带有jf值的2个字节,然后是一个4 byte项目标头,其中包含雇佣军目前佩戴的物品数量。这些项目像其他任何项目列表一样读取。
如果您的角色既是死灵法师又是扩展字符,则本节以3 byte标头开始,其中前两个字节是标头kf然后是一个名为hasGolem的布尔值,如果此值为真,则有一个项目列表,其长度列表,其长度为1。
请参阅贡献。