An open API service indexing awesome lists of open source software.

https://github.com/piegamesde/nbt

Named Binary Tag (NBT) library for Java with focus on usability and performance
https://github.com/piegamesde/nbt

minecraft nbt-library

Last synced: 3 months ago
JSON representation

Named Binary Tag (NBT) library for Java with focus on usability and performance

Awesome Lists containing this project

README

        

# NBT [![](https://jitpack.io/v/piegamesde/nbt.svg)](https://jitpack.io/#piegamesde/nbt)

Named Binary Tag (NBT) library for Java at the end of a long fork chain. This has been forked from flow-nbt, which itself has its root in JNBT.

NBT is a tag based binary format designed to carry large amounts of binary data with smaller amounts of additional data. See [one of the wikis](https://wiki.vg/NBT) for more information

## Features

- Hide the pain through the usage of Java 8's `Optional`
- Parse whole Region files in the Anvil format
- Helper methods to analyse a chunk's content (e.g. parse the Minecraft packed palette data)
- Option to keep all arrays as `byte[]` to improve performance
- Compatible with Minecraft 1.16

## Getting started

Go to [Jitpack.io](https://jitpack.io/#piegamesde/gson-fire) and follow the instructions.

Dependency string in Gradle:
```groovy
dependencies {
implementation 'com.github.piegamesde:nbt:3.0.1'
}
```

Maven:
```xml

com.github.piegamesde
nbt
3.0.1

```

## Usage

### NBT file usage

Entry points to the API are the `NBTInputStream` and `NBTOutputStream` classes, which are used to read or write one complex NBT tag. Different data compressions are available. NBT data is stored in a `Tag`. A tag has a name and a value, there is one sub-class for each tag type. Because casting yourself around the NBT tree is not a lot of fun, there are a ton of helper methods that return the cast type if possible, or an empty `Optional` if not. This leverages the whole power and syntax sugar of Java's `Optional` class.

If you don't like `Optional`, you can still call `Tag::getValue` and manually cast things around. There are cases where this is actually preferable.

```java
try (NBTInputStream in = new NBTInputStream(Files.newInputStream(myPath), NBTInputStream.GZIP_COMPRESSION)) {
/* Read all the data into a tag */
Tag> dataRaw = in.readTag();
/* Those helper method give an `Optional` that's better to use than a plain downcast */
CompoundTag data = dataRaw.getAsCompoundTag().get();

// Do something with the data in here:

/* Directly access child values with the correct type, if present */
int version = data.getIntValue("version").get();
/* Get sub tags (not only their value) as well */
CompoundTag subData = data.getCompoundTag("subDataTag");

/* Reald-world use case example (simplified): get the player dimension of a Minecraft level.dat, but the data type changed from int to string over time. */
var dimension = subData.getIntValue("Dimension")
.map(dim -> (new String[] { "Overworld", "Nether", "End"})[dim])
.orElseGet(() -> subData.getStringValue("Dimension").get());
}
```

### Region/Anvil file usage

A Minecraft save file can be loaded using class `RegionFile`. It allows reading and writing chunks and metadata. The (lazily) loaded data of a chunk is represented through a `Chunk` object, which may give access to its data (usually containing a `ComoundTag`). Saving modified chunks back to the region file is also supported.

```java
try (RegionFile regionFile = new RegionFile(Paths.get(myWorld, "region", "r.0.0.mca"))) {
List list = regionFile.listChunks();
for (int i : list) {
Chunk chunk = regionFile.loadChunk(i);
CompoundTag data = chunk.readTag();
}
}
```

### Primitive array optimization

- Pass `rawArrays = true` when initializing the `NBTInputStream`
- All primitive arrays will now be parsed as `ByteArrayTag`
- Use methods like `ByteArrayTag::getShortArrayValue` to lazily convert the bytes as needed
- If a specialized `Tag` subclass is somehow required, this can be done as well using e.g. `ByteArrayTag::getAsIntArrayTag`

```java
try (NBTInputStream in = new NBTInputStream(Files.newInputStream(myPath), NBTInputStream.GZIP_COMPRESSION, true)) {
CompoundTag data = in.readTag().getAsCompoundTag().get();

ByteArrayTag array = data.getByteArrayValue("uuid").get();
int[] uuid = array.getIntArrayValue();
}
```