datastorage/NBT Tag API

Introduction

To use NBT Tag objects to store information, or to interact with the Minecraft server internals which uses this format, BKCommonLib provides wrapper classes to work with them safely. These classes are:

  • CommonTag - for storing actual raw data like floats, doubles, String, arrays, etc. All other tag types extend this one.
  • CommonTagList - for storing integer-indexed values of the same type. Implements List.
  • CommonTagCompound - for storing text-mapped values of different types. Implements Map.
  • NBTUtil - for server-specific operations like loading and saving entities

The CommonTag classes are so-called 'wrapper' classes around actual internal NBT tag objects. They make it easier, and safer, to pass around tags. Internally, no CommonTag objects are stored, only the NBT types. Like all wrapper classes extending BasicWrapper, you can get (and set) the internal handle of the tag. This way you are able to use these objects with internal logic. In general, you will not really use that, but it's there.

Usage

There are several use cases for these tags:

Working with NBT 'handle' Tags

You can construct a CommonTag from the handle using:

CommonTag tag = CommonTag.create(handle);

If you are absolutely certain about the type of handle you pass in, you can cast the result to CommonTagList or Compound directly. After creation you can work on it directly, and changes you perform automatically update the handle you passed in initially.

Creating new tags

To construct new CommonTags from data, there are several options:

CommonTag tag1 = CommonTag.create("myTagName", "text");
CommonTag tag2 = new CommonTag("myIntData", 12);
CommonTagList tagList = new CommonTagList();
CommonTagList tagList = new CommonTagList("MyName", someListOfValues);
CommonTagCompound compound = new CommonTagCompound("SomeMap", someMapOfValues);

When no name is provided, a 'null' name is used. A tag name is not required, a value always is. You can not construct a data tag (CommonTag) without non-null and supported data. For that reason, this will NOT work:

CommonTag myData = new CommonTag("Data", null);
myData.setData(12);

This has to do with the fact that the internal handle can not change after creation, and it is impossible to hotswap this type.

Methods

Name

You can set the name of the tag using setName and get the current name using getName.

Data

All Common Tags provide setData and getData methods. These methods directly change the data stored by the internal implementation. In the case of CommonTagList and Compound, it allows you to directly set a map or list of values, instead of adding or removing a single mapped value.

Values

CommonTagList and Compound implement Map and List in a way that it stores other CommonTags, but if all you want is the value and do not want to create a wrapper class to get it each time, you can use the 'values' methods.

They store multiple values (or entries), so to make a distinction, index or text-mapped data are called values. They are called this way because it obtains the value from a tag stored. CommonTagList has many methods for adding, removing, getting and setting values, CommonTagList has many methods for putting, removing and getting values.

Getting values

At compile time it is never really certain what type of data is stored. For this reason, there are many overloads that automatically convert values. This way you are able to get a 'String' from an int or byte tag, or the other way around, without issues. To do this, you do have to specify the Class type to obtain, or a non-null default. Examples:

CommonTagCompound data = new CommonTagCompound("data");
data.putValue("x", 12);
data.putValue("y", 15);
data.putValue("difficulty", -1);
String textX = data.getValue("x", String.class);
double doubleY= data.getValue("y", 0.0);
Difficulty diffculty = data.getValue("difficulty", Difficulty.class, null);
if (difficulty != null) {
   System.out.println(difficulty);
}

As you can see, it is even possible to obtain a difficulty from the difficulty identifier. The internal conversion system takes care of that for you.

Using tags as lists and maps

CommonTagList and Compound fully implement List and Map respectively. This includes iteration and other logic. For example:

CommonTagList list = new CommonTagList(12, 14, 16, 18, 12, -3);
for (CommonTag tag : list) {
    System.out.println("VALUE: " + tag.getData(0));
}

Also note the getData(0), which gets the data as an Integer with 0 as default if this fails. If you wish to access the data directly, you can use the getAllValues method for list to do so:

for (int value : list.getAllValues(int[].class)) {
    System.out.println(value);
}

Do note that this allocates a new int[] array for the result.

Conclusion

This API allows you to use tags as maps, lists or actual data. Additionally, it provides methods to directly obtain values from lists and maps, without creating new tags. It utilizes the internal conversion system to dynamically obtain values of any type you want, without forced method overloads. This allows further integration of NBT in other, generic classes.


Comments

Posts Quoted:
Reply
Clear All Quotes