Catalog
  1. 思路:
  2. 准备:
  3. 实践1:
  4. 实践2:
NBT-TAG小记

最近闲来无事和朋友闲谈,突然聊到了Minecraft和其中一个文件level.dat。尽管我用软件修改过这个文件,但是如何解析这个文件我并不知道。于是心血来潮尝试了一下。

思路:

  1. 反编译Minecraft查找相关函数。
  2. Hex查看,并分析方法。

准备:

  1. 学习一下NBT相关知识。
  2. 网上查询可知level.dat文件是个压缩文件格式是gzip。故解压得到同名文件levellevel是一个NBT标签格式的文件,至此问题就变成了如何从零解析nbt格式的文件。
  3. 用notepad++打开,可以看到,一些字符串和乱码。推测是加密后的数据。

实践1:

  1. 打开jd-gui, 把XXX.jar丢进去,由于我并没有游戏本体,所以就用服务端代替了。搜索定位到WorldLoader.class

  2. 从这段代码可以看出来,它是如何读取dat文件的。这两个箭头分别是解压和读取。

3.之后由于不太了解Java所以并没有找到相关解密代码,所以放弃了这条路,换了另一条路。

实践2:

  1. 网上找一个NbtEditor。读取了一下level.dat从图中我们得知,这个文件的结构,最上面是一个空名的TAG_Compound,下面是名为Data的TAG_Compound,然后才是其他的数据。

  2. 用Sublime Text 打开level 并用hex模式查看。通过查询资料可知,所有的标签都有一个独立的ID和名称。标签的第一个字节为标签类型(ID),其后两字节为存储名称的长度,之后以UTF-8格式的字符串的方式存储标签。

  3. 如上图所述,0a 00 00 第一个字节0a是代表标签ID,0a转换成10进制就是10。他所代表的就是TAG_Compound。
    后面的00 00是标签名称的长度,由NBTEditor可知第一个标签并没有名称,所以是零。

  4. 知道了规矩,我们就可以尝试解析了,我们先用地图种子练练手。
    我们可以看到04 00 0a,其中04是标签类型对应的是TAG_Long 8 字节 / 64 位;00 0a是标签名称长度,0a是十进制中的10,RandomSeed 刚好就是十位。

  5. 于是我们往RandomSeed后面推8位74 2a17 004f 4271 c6这就是种子的值了。于是我们把它转换从10进制就是8370528147518681542
    可以看到与之前的结果相同。

至此,我们已经大概了解了如何从头读取level.dat文件,但是我有些不解,为啥当时Notch不用Json或XML呢?非要自己造个轮子。

Author: Peter Duan
Link: https://peter-duan.github.io/hexo/2020/07/06/NBT/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.

Comment