blob: a17b4d9f4a0f31711a4a5291973388b04997c280 [file] [log] [blame] [view] [raw]
# NBT
[![Build Status](https://travis-ci.org/Querz/NBT.svg?branch=master)](https://travis-ci.org/Querz/NBT) [![](https://jitpack.io/v/Querz/NBT.svg)](https://jitpack.io/#Querz/NBT)
#### A java implementation of the [NBT protocol](http://minecraft.gamepedia.com/NBT_format), including a way to implement custom tags.
---
### Specification
According to the [specification](http://minecraft.gamepedia.com/NBT_format), there are currently 13 different types of tags:
| Tag class | Superclass | ID | Payload |
| --------- | ---------- | -- | ----------- |
| [EndTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/EndTag.java) | [Tag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/Tag.java) | 0 | None |
| [ByteTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ByteTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 1 | 1 byte / 8 bits, signed |
| [ShortTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ShortTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 2 | 2 bytes / 16 bits, signed, big endian |
| [IntTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/IntTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 3 | 4 bytes / 32 bits, signed, big endian |
| [LongTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/LongTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 4 | 8 bytes / 64 bits, signed, big endian |
| [FloatTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/FloatTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 5 | 4 bytes / 32 bits, signed, big endian, IEEE 754-2008, binary32 |
| [DoubleTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/DoubleTag.java) | [NumberTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/NumberTag.java) | 6 | 8 bytes / 64 bits, signed, big endian, IEEE 754-2008, binary64 |
| [ByteArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ByteArrayTag.java) | [ArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ArrayTag.java) | 7 | `IntTag`'s payload *size*, then *size* `ByteTag`'s payloads |
| [StringTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/StringTag.java) | [Tag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/Tag.java) | 8 | `ShortTag`'s payload *length*, then a UTF-8 string with size *length* |
| [ListTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ListTag.java) | [Tag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/Tag.java) | 9 | `ByteTag`'s payload *tagId*, then `IntTag`'s payload *size*, then *size* tags' payloads, all of type *tagId* |
| [CompoundTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/CompoundTag.java) | [Tag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/Tag.java) | 10 | Fully formed tags, followed by an `EndTag` |
| [IntArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/IntArrayTag.java) | [ArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ArrayTag.java) | 11 | `IntTag`'s payload *size*, then *size* `IntTag`'s payloads |
| [LongArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/LongArrayTag.java) | [ArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/ArrayTag.java) | 12 | `IntTag`'s payload *size*, then *size* `LongTag`'s payloads |
* The `EndTag` is only used to mark the end of a `CompoundTag` in its serialized state or an empty `ListTag`.
* The maximum depth of the NBT structure is 512. If the depth exceeds this restriction during serialization, deserialization or String conversion, a `MaxDepthReachedException` is thrown. This usually happens when a circular reference exists in the NBT structure. The NBT specification does not allow circular references, as there is no tag to represent this.
---
### Example usage:
The following code snippet shows how to create a `CompoundTag`:
```java
CompoundTag ct = new CompoundTag();
ct.put("byte", new ByteTag((byte) 1));
ct.put("double", new DoubleTag(1.234));
ct.putString("string", "stringValue");
```
An example on how to use `ListTag`:
```java
ListTag<FloatTag> fl = new ListTag<>();
fl.add(new FloatTag(1.234f);
fl.addFloat(5.678f);
```
---
### Utility
There are several utility methods to make your life easier if you use this library.
#### NBTUtil
`NBTUtil.writeTag()` lets you write a Tag into a gzip compressed or uncompressed file in one line (not counting exception handling). Files are gzip compressed by default.
Example usage:
```java
NBTUtil.writeTag(tag, "filename.dat");
```
`NBTUtil.readTag()` reads any file containing NBT data. No worry about compression, it will automatically uncompress gzip compressed files.
Example usage:
```java
Tag tag = NBTUtil.readTag("filename.dat");
```
#### Playing Minecraft?
Each tag can be converted into a JSON-like NBT String used in Minecraft commands.
Example usage:
```java
CompoundTag c = new CompoundTag();
c.putByte("blah", (byte) 5);
c.putString("foo", "bär");
String s = c.toTagString();
//output: {blah:5b,foo:"bär"}
```
There are also some tools to read, change and write MCA files:
For example:
```java
//This changes the InhabitedTime field of the chunk at x=68, z=81 to 0
MCAFile mcaFile = MCAUtil.readMCAFile("r.2.2.mca");
CompoundTag tag = mcaFile.getChunkData(68, 81);
tag.getCompoundTag("Level").setLong("InhabitedTime", 0L);
MCAUtil.writeMCAFile("r.2.2.mca", mcaFile);
```
---
### Custom tags
Interested in more advanced features, and the default NBT protocol just isn't enough? Simply create your own tags!
There are 4 example classes in `net.querz.nbt.custom` that show how to implement custom tags:
| Class | ID | Description |
| ------------- | :-: | ----------- |
| [ObjectTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/custom/ObjectTag.java) | 90 | A wrapper tag that serializes and deserializes any object using the default java serialization. |
| [ShortArrayTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/custom/ShortArrayTag.java) | 100 | In addition to the already existing `ByteArrayTag`, `IntArrayTag` and `LongArrayTag`. |
| [CharTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/custom/CharTag.java) | 110 | `Character` (char) tag. |
| [StructTag](https://github.com/Querz/NBT/blob/master/src/main/java/net/querz/nbt/custom/StructTag.java) | 120 | Similar to the `ListTag`, but with the ability to store multiple types. |
To be able to use a custom tag with deserialization, it needs to have a public no-args constructor and its id and class must be registered during runtime with `TagFactory.registerCustomTag()`.