我在Ubuntu的CLI上创建了一个将NBT转换为JSON的工具
假设
-
Ubuntu 18.04.3 LTS
bash
jqを使用
# apt install jq
概述
由于在Ubuntu的命令行上运行Minecraft服务器时,我想要解析Minecraft的保存数据,所以我研究了Minecraft保存数据的格式以及将其转换为JSON字符串的方法。然而,我并没有得到我期望的结果,因此我用Perl编写了以下的NBT和JSON互相转换的程序。
-
MirrgieRiana / nbt_to_json_perl https://github.com/MirrgieRiana/nbt_to_json_perl
背景 – 背景概述
我在运行Minecraft服务器,出现了希望在Ubuntu命令行上解析Minecraft保存数据的需求。
NBT
Minecraft游戏数据以NBT格式进行描述,这是一种带有类型的二进制JSON格式。保存数据大部分都是以这种格式编写的。
详细的说明交给维基百科吧。
-
NBTフォーマット – Minecraft Wiki https://minecraft-ja.gamepedia.com/NBT%E3%83%95%E3%82%A9%E3%83%BC%E3%83%9E%E3%83%83%E3%83%88
现有的程序
NBT浏览器
NBTExplorer 在 Linux 的 CLI 环境下似乎不具备直接把数据转化为 JSON 的工具。
-
NBTExplorer https://www.minecraftforum.net/forums/mapping-and-modding-java-edition/minecraft-tools/1262665-nbtexplorer-nbt-editor-for-windows-and-mac
作为Windows平台上的GUI NBT编辑软件,它非常出色,但由于这次要使用没有GUI的Ubuntu,所以无法使用。
NBTUtilみたいな名前のツールが同封されており、これはWindowsのコマンドプロンプト(Bashからも可能)からならコマンドでNBTを独特のフォーマットに文字列化できる。JSONにもできるかもしれないが、Windows環境が求められたので無視した。
将nbt2json(midnightfreddie)转换为JSON格式。
-
GitHub – midnightfreddie/nbt2json https://github.com/midnightfreddie/nbt2json
有一个使用Go语言编写的工具。
我想要安装它,但是由于我不了解Go语言的用法,所以我选择忽略它,觉得自己制作一个简化版可能会更快。
海晶石-NBT
-
PrismarineJS /
prismarine-nbt https://github.com/PrismarineJS/prismarine-nbt
这个模块好像是为了Node而设计的。它看起来相当不错,似乎比我在这篇文章中创建的东西要更好。
JSON-to-NBT-Converter(KSashaDF)翻译成中文的说法:JSON转NBT转换器(KSashaDF)
-
KSashaDF /
JSON-to-NBT-Converter https://github.com/KSashaDF/JSON-to-NBT-Converter
截至2020年2月27日,目前看起来不太完美,表现好似并不理想。
产物
我编写了下面的程序。
-
MirrgieRiana / nbt_to_json_perl https://github.com/MirrgieRiana/nbt_to_json_perl
本来在这里打算写一些使用示例,但最终我在README文件中做了很多解说,因此这里只简要提及一下。
将NBT二进制文件转化为JSON格式
使用nbt2json可以将NBT二进制数据转换为JSON。但是需要注意的是,Minecraft的存档数据通常是经过gzip压缩的。nbt2json只接受非压缩的NBT二进制数据。
-
$ cat sample/1.nbt | ./nbt2json
{"key":"","type":10,"value":[{"key":"list","type":9,"value":{"type":1,"values":[1,2]}},{"key":"double","type":6,"value":"0x3fd0000000000000=0.25"},{"key":"int","type":3,"value":-1}]}
方便化和整形
添加-c参数可以方便地输出格式化的结果。
这里的c代表方便化,p代表格式化。如果添加-c参数,则Compound标签会变成JSON对象,但需要注意标签的顺序不会被保留。
-
$ cat sample/1.nbt | ./nbt2json -cp
{
"C": {
"Alist": {
"type": "byte",
"values": [
1,
2
]
},
"Ddouble": "0x3fd0000000000000=0.25",
"Iint": -1
}
}
反向转换
json2nbt -c是nbt2json -cp的反函数,它从JSON调用并生成NBT。
-c除了在Compound标签内部的标签顺序被破坏外,基本上返回原始的NBT。
nbt2json有许多选项,但是其中一些选项即使直接传给json2nbt,它也能够读取。
浮点数在使用浮点数表示法时,可能会出现多个二进制对应一个字符的情况,如NaN或非规范数。
因此,在使用json2nbt进行反向转换时,浮点数会被输出为16进制字符串和10进制表示的一对。
通过使用nbt2json -H或nbt2json -B,所有数字都会被强制转换为16进制字符串或二进制字符串。
尽管json2nbt没有-H或-B选项,但它也可以接受不使用这些选项的输入。
-
$ cat sample/1.nbt | ./nbt2json -cp | ./json2nbt -c | ./nbt2json -cp
{
"C": {
"Alist": {
"type": "byte",
"values": [
1,
2
]
},
"Ddouble": "0x3fd0000000000000=0.25",
"Iint": -1
}
}
使用e选项的示例
level.datを読んでワールドのSeed値を得たい場合、jqとかを使うよりも次のように直接perlの変数を書き換えるのがよい。
-
$ cat level.dat | inflate-gzip | nbt2json -cp -e ‘$_ = $_->{C}->{CData}->{LRandomSeed}’
7546217594578327695
如果先将JSON全部输出,然后再使用jq,那么除了转换数据会有额外的开销之外,JSON在处理64位整数方面也存在问题。
-
$ cat level.dat | inflate-gzip | nbt2json -cp | jq ‘.C.CData.LRandomSeed’
7546217594578328000
在这种情况下,建议使用-H选项将其转换为十六进制字符串进行输出。
-
$ cat level.dat | inflate-gzip | nbt2json -cpH | jq ‘.C.CData.LRandomSeed’
"0x6c443070ec80dfb0"