Difference between revisions of "NBT"

From wiki.vg
Jump to navigation Jump to search
 
Line 87: Line 87:
 
       TAG_Long("longTest"): 9223372036854775807
 
       TAG_Long("longTest"): 9223372036854775807
 
       TAG_Float("floatTest"): 0.49823147
 
       TAG_Float("floatTest"): 0.49823147
       TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING !
+
       TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ÅÄÖ!
 
       TAG_Int("intTest"): 2147483647
 
       TAG_Int("intTest"): 2147483647
 
       TAG_Compound("nested compound test"): 2 entries
 
       TAG_Compound("nested compound test"): 2 entries

Revision as of 23:04, 29 November 2011

NBT (Named Binary Tag) is a tag-based binary format designed to carry binary data accompanied by additional data.

An NBT file consists of a single root TAG_Compound and is compressed with GZip.

A single named tag is structured as follows:

Tag Type Name Length Name Payload
1 byte 2 bytes, 16 bit integer, signed, big endian UTF-8 Encoded String Depends on type of tag

There are 10 different types of tags:

Tag Type Value Name Description Comments
0 TAG_End Marks the end of a TAG_Compound. This tag occurs to end a previously opened TAG_Compound. This tag has no name, and no payload.
1 TAG_Byte Payload is a single signed byte (8 bits).
2 TAG_Short Payload is a signed 16 bit integer (big endian).
3 TAG_Int Payload is a signed 32 bit integer (big endian).
4 TAG_Long Payload is a singed 64 bit integer (big endian).
5 TAG_Float Payload is a 32 bit floating point value (big endian, IEEE 754)
6 TAG_Double Payload is a 64 bit floating point value (big endian, IEEE 754)
7 TAG_Byte_Array An array of bytes. Payload consists of four bytes which form a signed 32 bit integer (big endian) which specifies the length of the remainder of the payload.
8 TAG_String A string. Payload consists of two bytes which form a signed 16 bit integer (big endian) which specifies the length of the remainder of the payload. The remainder of the payload is a UTF-8 encoded string.
9 TAG_List A list of tags. Payload consists of one byte which specifies the type of tags found in the list, followed by four bytes which form a signed 32 bit integer (big endian) which specifies the number of tags which form the remainder of the payload. Tags in the list do not specify their type (i.e. they're missing the first byte) and do not have a name (i.e. they do not have two bytes for the length of their name, nor the bytes which makes up the name).
10 TAG_Compound The root of nested tags. Payload consists of sequential named tags. This sequence of named tags ends when a TAG_End is encountered. Note that TAG_Compounds can be nested within themselves, so the next TAG_End is not necessarily the end of this TAG_Compound. Recursion advised.

Note that none of the examples below are GZip'd


Decoding example: http://mc.kev009.com/nbt/test.nbt

The first byte of this file is 10. This means that the first tag is a TAG_Compound (which is to be expected).

We read two more bytes to get the length of the name of this tag. The next two bytes are 0 and 11, meaning the name is 11 bytes long. On a little endian system be sure to reverse them before creating a 16 bit signed integer with them.

We read the next 11 bytes and decode them as per UTF-8. The resulting string is "hello world".

Next we move onto the payload, which, since this is a TAG_Compound, is going to be more tags until we reach the TAG_End which corresponds to our TAG_Compound.

Therefore, we read the next byte to determine the type of the first tag in the TAG_Compound. The next byte is an 8 -- TAG_String.

The next two bytes tell us that the length of the name of this string is 4, and the next 4 bytes UTF-8 decode into "name".

Next we read two more bytes to find the name of the string which is the payload of this tag, these two bytes are 0 and 9. The next 9 bytes UTF-8 decode into "Bananrama".

We read the next byte to get the type of the next named tag, and find that it is 0 -- TAG_End.

Therefore, we are done.

The result:

   TAG_Compound("hello world"): 1 entries
   {
       TAG_String("name"): Bananrama
   }

For a slightly longer test, use http://mc.kev009.com/nbt/bigtest.nbt

You should end up with this:

   TAG_Compound("Level"): 11 entries
   {
      TAG_Short("shortTest"): 32767
      TAG_Long("longTest"): 9223372036854775807
      TAG_Float("floatTest"): 0.49823147
      TAG_String("stringTest"): HELLO WORLD THIS IS A TEST STRING ÅÄÖ!
      TAG_Int("intTest"): 2147483647
      TAG_Compound("nested compound test"): 2 entries
      {
         TAG_Compound("ham"): 2 entries
         {
            TAG_String("name"): Hampus
            TAG_Float("value"): 0.75
         }
         TAG_Compound("egg"): 2 entries
         {
            TAG_String("name"): Eggbert
            TAG_Float("value"): 0.5
         }
      }
      TAG_List("listTest (long)"): 5 entries of type TAG_Long
      {
         TAG_Long: 11
         TAG_Long: 12
         TAG_Long: 13
         TAG_Long: 14
         TAG_Long: 15
      }
      TAG_Byte("byteTest"): 127
      TAG_List("listTest (compound)"): 2 entries of type TAG_Compound
      {
         TAG_Compound: 2 entries
         {
            TAG_String("name"): Compound tag #0
            TAG_Long("created-on"): 1264099775885
         }
         TAG_Compound: 2 entries
         {
            TAG_String("name"): Compound tag #1
            TAG_Long("created-on"): 1264099775885
         }
      }
      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]
      TAG_Double("doubleTest"): 0.4931287132182315
   }