Skip to main content

Rtag

Welcome to Rtag wiki, here you find information about Rtag usage, including the usages with Minecraft server customization.

// Using Item
RtagItem tag = new RtagItem(item);
// Using Entity
RtagEntity tag = new RtagEntity(entity);
// Using block
RtagBlock tag = new RtagBlock(block);


// --- Put values
// Set the value "Custom Text" at "display.Name" path
tag.set("Custom Text", "display", "Name");
// Or set an integer at "someKey" path
tag.set(40, "someKey");
// Including compatibility with any type of object like MyObject
MyObject myobject = new MyObject();
tag.set(myobject, "any", "path");
// Merge values into tag
tag.merge(Map.of("asd", 123, "someKey", 41), true);

// So you can add lists
tag.set(new ArrayList(), "list", "path");
// And add values into list
tag.add((short) 3, "list", "path");
// Or replace the values of existing list
tag.set((short) 5, "list", "path", 0); // index 0

// --- Get values
// Value from path "display" -> "Name"
String name = tag.get("display", "Name");
// Safe value get from path "someKey", or -1 by default
int intValue = tag.getOptional("someKey").or(-1);
int sameValue = tag.getOptional("someKey").asInt(-1); // This method try to convert any type to int
// Explicit value get for custom objects
MyObject sameobject = tag.getOptional("any", "path").as(MyObject.class);

// Get lists
List<Short> list = tag.get("list", "path");
// Get list value from index
short listValue = tag.get("list", "path", 0); // index 0

// Get the entire object tag as Map of Java objects
Map<String, Object> map = tag.get();

// --- Load changes into object
// Load changes into original object
tag.load();
// RtagItem as the option to create an item copy with changes loaded
ItemStack itemCopy = tag.loadCopy();

// --- Update current tag if the original object was edited
tag.update();

About Rtag

Rtag is a library whose idea was planned around 2020, but the development starts in 2022 due to commercial limitations about attachment to old systems by most developers.

This library was created to solve the need to develop a Minecraft server with a wide variety of custom things avoiding a bad performance impact on big servers, using an "easy to understand" way to handle NBT.

You don't need to be an expert with NBT tags, just with simple methods you can set and get normal Java objects.

Get Rtag

version

Requirements

  • At least Minecraft 1.8.8: Rtag is made to be used in latest Minecraft versions, old versions support is only for commercial purposes.
  • Minimum Java 11

Dependency

To use Rtag in your project without shading you need to add first as a dependency and tell your users to download Rtag from their Spigot page.

repositories {
maven { url 'https://jitpack.io' }
}

dependencies {
compileOnly 'com.saicone.rtag:rtag:VERSION'
// Other modules
compileOnly 'com.saicone.rtag:rtag-block:VERSION'
compileOnly 'com.saicone.rtag:rtag-entity:VERSION'
compileOnly 'com.saicone.rtag:rtag-item:VERSION'
}

Shaded Dependency

Rtag it's completely shadeable, you can implement rtag directly in your plugin (no download requried by the user).

plugins {
id 'com.github.johnrengelman.shadow' version '8.1.1'
}

repositories {
maven { url 'https://jitpack.io' }
}

dependencies {
implementation 'com.saicone.rtag:rtag:VERSION'
// Other modules
implementation 'com.saicone.rtag:rtag-block:VERSION'
implementation 'com.saicone.rtag:rtag-entity:VERSION'
implementation 'com.saicone.rtag:rtag-item:VERSION'
}

jar.dependsOn (shadowJar)

shadowJar {
// Relocate rtag (DO NOT IGNORE THIS)
relocate 'com.saicone.rtag', project.group + '.libs.rtag'
// Exclude unused classes (optional)
minimize()
}

Why Rtag

There are other libraries to edit NBT tags, why should Rtag be used over the others?

Speed like direct calls

Rtag abuses of static final MethodHandle to convert the use of reflected methods as if they were direct calls, so it works to edit NBT tags in non-async operations without producing a bad performance impact on big servers.

Easy to understand

You don't need to be an expert with NBT tags, just with simple methods you can set and get normal Java objects using tree-like path.

Rtag rtag = new Rtag();
rtag.set(compound, "Normal string", "Custom", "Tag", "Path");
String string = rtag.get(compound, "Custom", "Tag", "Path");

The main RtagEditor instances have methods to make tag editing easier.

RtagItem tag = new RtagItem(item);
tag.setUnbreakable(true);
tag.setRepairCost(20);
int level = tag.getEnchantmentLevel("unbreaking"); // Enchantment enum, name or id

RtagEntity tag = new RtagEntity(entity);
tag.setAttributeBase("generic.attackDamage", 0.5);

RtagBlock tag = new RtagBlock(block);
tag.setCustomName("§eColored name");

So you can edit objects using functions inside RtagEditor instances and return any type of object.

ItemStack item = ...;
// Edit original
RtagItem.edit(item, tag -> {
tag.set("Custom Text", "display", "name");
tag.set(30, "someKey");
});
// Return a copy
ItemStack copy = RtagItem.edit(item, tag -> {
tag.set(30, "someKey");
return tag.loadCopy();
});

Store custom objects

By default, Rtag uses the Gson library inside Bukkit to (de)serialize custom objects, but you need to get them using explicit conversion.

You can register (de)serializers in Rtag instance to set and get custom objects with automatic conversion.

Rtag rtag = new Rtag();
MyObject myObject = new MyObject();

rtag.set(compound, myObject, "CustomTagPath");
MyObject sameObject = rtag.getOptional(compound, "CustomTagPath").as(MyObject.class);

TagStream instances

With ItemTagStream instance you can convert items into Base64|File|Bytes|Map|String and viceversa. Including cross-version support! Save an item on any version and get on any version without compatibility problems. Materials, enchantments, potions... etc, all will be converted!

ItemTagStream tag = ItemTagStream.INSTANCE;

String string = tag.toBase64(item);
ItemStack sameItem = tag.fromBase64(string)[0];

Textured heads

With SkullTexture class you can get textured heads from base64, url, texture ID, player name or uuid.

// Base64
ItemStack head = SkullTexture.getTexturedHead("eyJ0ZXh0dXJlcyI6eyJTS0lOIjp7InVybCI6Imh0dHA6Ly90ZXh0dXJlcy5taW5lY3JhZnQubmV0L3RleHR1cmUvZmVkZmEyZTBmZGVhMGMwNDIzODA0Y2RiNWI2MmFkMDVhNmU5MTRjMDQ2YzRhM2I3ZTM1NWJmODEyNjkxMjVmZCJ9fQ==");
// URL
ItemStack head = SkullTexture.getTexturedHead("http://textures.minecraft.net/texture/fedfa2e0fdea0c0423804cdb5b62ad05a6e914c046c4a3b7e355bf81269125fd");
// Texture ID
ItemStack head = SkullTexture.getTexturedHead("fedfa2e0fdea0c0423804cdb5b62ad05a6e914c046c4a3b7e355bf81269125fd");
// Player name
ItemStack head = SkullTexture.getTexturedHead("Rubenicos");
// Player UUID
ItemStack head = SkullTexture.getTexturedHead("7ca003dc-175f-4f1f-b490-5651045311ad");

Chat Component

With ChatComponent class you can convert (json) strings into chat components and viceversa.

// To component
Object component = ChatComponent.fromJson("{\"bold\":true,\"italic\":false,\"color\":\"dark_purple\",\"text\":\"Colored text!\"}");
Object sameComponent = ChatComponent.fromString("§5§lColored text!");

// From component
String json = ChatComponent.toJson(component);
String string = ChatComponent.toString(component);

// Cross-compatibility
String json = ChatComponent.toJson("§5§lColored text!");
String string = ChatComponent.toString("{\"bold\":true,\"italic\":false,\"color\":\"dark_purple\",\"text\":\"Colored text!\"}");

Including pretty nbt formatter to colorize nbt tags like /data Minecraft command.

Object nbt = ...;

// Pretty format into chat component
Object component = ChatComponent.toPrettyComponent(nbt, null);
// Into json with 2 spaces as indent
String json = ChatComponent.toPrettyJson(nbt, " ");
// Into colored string
String colored = ChatComponent.toPrettyString(nbt, null);

// Using other color palette (You can use your own one)
String colored = ChatComponent.toPrettyString(nbt, null, ChatComponent.NBT_PALETTE_BUNGEE);