我在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"
bannerAds