[关闭]
@satgo1546 2015-08-17T14:37:03.000000Z 字数 4196 阅读 2144

Named Binary Tag specification

Minecraft


NBT (Named Binary Tag) is a tag based binary format designed to carry large amounts of binary data with smaller amounts of additional data. An NBT file consists of a single GZIPped Named Tag of type TAG_Compound.

A Named Tag has the following format:

byte tagType
TAG_String name
[payload]

The tagType is a single byte defining the contents of the payload of the tag.

The name is a descriptive name, and can be anything (eg "cat", "banana", "Hello World!"). It has nothing to do with the tagType. The purpose for this name is to name tags so parsing is easier and can be made to only look for certain recognized tag names. Exception: If tagType is TAG_End, the name is skipped and assumed to be "".

The [payload] varies by tagType.

Note that ONLY Named Tags carry the name and tagType data. Explicitly identified Tags (such as TAG_String above) only contains the payload.

The tag types and respective payloads are:

Decoding example:
(Use http://www.minecraft.net/docs/test.nbt to test your implementation)

First we start by reading a Named Tag.
After unzipping the stream, the first byte is a 10. That means the tag is a TAG_Compound (as expected by the specification).

The next two bytes are 0 and 11, meaning the name string consists of 11 UTF-8 characters. In this case, they happen to be "hello world".
That means our root tag is named "hello world". We can now move on to the payload.

From the specification, we see that TAG_Compound consists of a series of Named Tags, so we read another byte to find the tagType.
It happens to be an 8. The name is 4 letters long, and happens to be "name". Type 8 is TAG_String, meaning we read another two bytes to get the length,
then read that many bytes to get the contents. In this case, it's "Bananrama".

So now we know the TAG_Compound contains a TAG_String named "name" with the content "Bananrama"

We move on to reading the next Named Tag, and get a 0. This is TAG_End, which always has an implied name of "". That means that the list of entries
in the TAG_Compound is over, and indeed all of the NBT file.

So we ended up with this:

  1. TAG_Compound("hello world"): 1 entries
  2. {
  3. TAG_String("name"): Bananrama
  4. }

For a slightly longer test, download http://www.minecraft.net/docs/bigtest.nbt
You should end up with this:

  1. TAG_Compound("Level"): 11 entries
  2. {
  3. TAG_Short("shortTest"): 32767
  4. TAG_Long("longTest"): 9223372036854775807
  5. TAG_Float("floatTest"): 0.49823147
  6. TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ÅÄÖ!
  7. TAG_Int("intTest"): 2147483647
  8. TAG_Compound("nested compound test"): 2 entries
  9. {
  10. TAG_Compound("ham"): 2 entries
  11. {
  12. TAG_String("name"): Hampus
  13. TAG_Float("value"): 0.75
  14. }
  15. TAG_Compound("egg"): 2 entries
  16. {
  17. TAG_String("name"): Eggbert
  18. TAG_Float("value"): 0.5
  19. }
  20. }
  21. TAG_List("listTest (long)"): 5 entries of type TAG_Long
  22. {
  23. TAG_Long: 11
  24. TAG_Long: 12
  25. TAG_Long: 13
  26. TAG_Long: 14
  27. TAG_Long: 15
  28. }
  29. TAG_Byte("byteTest"): 127
  30. TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
  31. {
  32. TAG_Compound: 2 entries
  33. {
  34. TAG_String("name"): Compound tag #0
  35. TAG_Long("created-on"): 1264099775885
  36. }
  37. TAG_Compound: 2 entries
  38. {
  39. TAG_String("name"): Compound tag #1
  40. TAG_Long("created-on"): 1264099775885
  41. }
  42. }
  43. TAG_Byte_Array("byteArrayTest (the first 1000 values of (n*n*255+n*7)%100, starting with n=0 (0, 62, 34, 16, 8, ...))"): [1000 bytes]
  44. TAG_Double("doubleTest"): 0.4931287132182315
  45. }
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注