编解码 NBT

Go-MC 提供了一个功能完善的 NBT 操作库,可以用于方便、高效地处理各种NBT结构。这里会介绍这个 NBT 库提供的核心API。

使用 NBT 库,需要导入以下包:

import "github.com/Tnze/go-mc/nbt"

Go Reference

该 NBT 库的用法与标准库的 encoding/json 库比较相似,查看文档及示例很容易理解,这里是一些注意事项。

不同类型的Go变量会被转换为不同的 NBT 标签,对应关系如下:

Go 类型NBT 标签
bool, int8, uint8TagByte
int16, uint16TagShort
int32, uint32TagInt
int64, uint64TagLong
float32TagFloat
float64TagDouble
stringTagString
struct, mapTagCompound
[]bool, []int8, []uint8TagByteArray
[]int32, []uint32TagIntArray
[]int64, []uint64TagLongArray
[]TTagList

NBT库内部使用反射来实现以上功能,但是实现了 nbt.Marshalernbt.Unmarshaler 接口的值不会被反射,NBT 库会调用它们自身的实现。

你可以通过实现这两个接口实现自定义类型的支持。NBT库也有三个特殊类型实现了这两个接口,你可以利用它们完成一些特殊功能:

  • nbt.RawMessage - “原始数据”类型,NBT 数据将被原样保存,可以容纳任意合法的NBT数据。
  • nbt.StringifiedMessage - 以 S-NBT 格式保存数据,可以与 string 相互转换。
  • dynbt.Value - “动态”类型,可以保存任意数据,并且提供了方便的API用于操控 NBT。

结构体标签和选项 · Supported Struct Tags and Options

你可以给结构体标记 Tag 以指定 nbt 库如何将其编码为 NBT 及 如何将 NBT 解码到其之上。目前支持的标签有以下两个:

  • nbt - 用于指定名称和参数
  • nbtkey - 只用于指定名称 (可以包含逗号 ,

The nbt tag

大多数情况下,你只需要用这个 tag 来设置 NBT 标签名。

nbt tag 的格式: <nbt tag>[,opt].

这是一个逗号分隔的列表。 第一项是标签名,其余部分为选项。

像这样:

type MyStruct struct {
    Name string `nbt:"name"`
}

使用 - 可以让 NBT 库忽略某个字段:

type MyStruct struct {
    Internal string `nbt:"-"`
}

使用 omitempty 可以让 NBT 库仅在为零值时忽略某个字段:

type MyStruct struct {
    Name string `nbt:"name,omitempty"`
}

类型为 []byte[]int32[]int64 的值默认将被分别编码为 TagByteArrayTagIntArrayTagLongArray
你可以通过 list 标记将它们指定为 TagList

type MyStruct struct {
    Data []byte `nbt:"data,list"`
}

The nbtkey tag

官方 JSON 标准库有一个严重的问题:无法指定包含逗号的key(逗号后面的会被识别为其他选项) (例如 {"a,b" : "c"}

Go官方是非常自傲的,仅仅因为他们“觉得”key里不应该有逗号,他们就不让你加逗号,尽管JSON标准是完全支持的。
但是我们不一样,对这种需求我们提供了支持的方案:

type MyStruct struct {
    AB string `nbt:",omitempty" nbtkey:"a,b"`
}