A serverside user interface library for Minecraft: Java Edition
—
NBT (Named Binary Tag) data handling with serialization support and integration with Minecraft's data component system. Adventure provides comprehensive NBT support for complex data structures.
Interface for holding and managing NBT binary tag data with serialization support.
/**
* Holds NBT binary tag data with serialization support
*/
interface BinaryTagHolder extends Examinable {
/**
* Gets the binary tag data
* @return the binary tag
* @throws IOException if data cannot be read
*/
@NotNull BinaryTag get() throws IOException;
/**
* Gets the NBT data as a string representation
* @return the string representation
*/
String string();
/**
* Encodes a binary tag into a holder
* @param nbt the binary tag to encode
* @return new binary tag holder
*/
static BinaryTagHolder encode(BinaryTag nbt);
/**
* Creates a holder from an NBT string
* @param string the NBT string
* @return new binary tag holder
*/
static BinaryTagHolder of(String string);
/**
* Creates an empty binary tag holder
* @return empty holder
*/
static BinaryTagHolder empty();
}Base interface for components that display NBT data from various sources.
/**
* Base interface for components displaying NBT data
*/
interface NBTComponent<C extends NBTComponent<C, B>, B extends NBTComponentBuilder<C, B>>
extends BuildableComponent<C, B> {
/**
* Gets the NBT path expression
* @return the NBT path
*/
String nbtPath();
/**
* Gets whether to interpret NBT as text components
* @return true if should interpret as components
*/
boolean interpret();
/**
* Gets the separator for multiple NBT results
* @return the separator component or null
*/
@Nullable Component separator();
/**
* Sets the NBT path expression
* @param nbtPath the path
* @return component with new path
*/
C nbtPath(String nbtPath);
/**
* Sets whether to interpret NBT as components
* @param interpret whether to interpret
* @return component with new interpret setting
*/
C interpret(boolean interpret);
/**
* Sets the separator for multiple NBT results
* @param separator the separator or null
* @return component with new separator
*/
C separator(@Nullable ComponentLike separator);
}Component that displays NBT data from a block at a specific position.
/**
* Component displaying block NBT data
*/
interface BlockNBTComponent extends NBTComponent<BlockNBTComponent, BlockNBTComponent.Builder> {
/**
* Gets the block position
* @return the position
*/
Pos pos();
/**
* Sets the block position
* @param pos the new position
* @return component with new position
*/
BlockNBTComponent pos(Pos pos);
/**
* Creates a block NBT component
* @param nbtPath the NBT path
* @param pos the block position
* @return new block NBT component
*/
static BlockNBTComponent blockNBT(String nbtPath, Pos pos);
/**
* Block position for NBT access
*/
interface Pos extends Examinable {
/**
* Gets the X coordinate
* @return the X coordinate
*/
int x();
/**
* Gets the Y coordinate
* @return the Y coordinate
*/
int y();
/**
* Gets the Z coordinate
* @return the Z coordinate
*/
int z();
/**
* Creates a block position
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return new position
*/
static Pos of(int x, int y, int z);
/**
* Creates an absolute position
* @param x the X coordinate
* @param y the Y coordinate
* @param z the Z coordinate
* @return new absolute position
*/
static Pos absolute(int x, int y, int z);
/**
* Creates a relative position
* @param x the X offset
* @param y the Y offset
* @param z the Z offset
* @return new relative position
*/
static Pos relative(int x, int y, int z);
}
interface Builder extends NBTComponentBuilder<BlockNBTComponent, Builder> {
/**
* Sets the block position
* @param pos the position
* @return this builder
*/
Builder pos(Pos pos);
}
}Component that displays NBT data from entities matching a selector.
/**
* Component displaying entity NBT data
*/
interface EntityNBTComponent extends NBTComponent<EntityNBTComponent, EntityNBTComponent.Builder> {
/**
* Gets the entity selector
* @return the selector string
*/
String selector();
/**
* Sets the entity selector
* @param selector the new selector
* @return component with new selector
*/
EntityNBTComponent selector(String selector);
/**
* Creates an entity NBT component
* @param nbtPath the NBT path
* @param selector the entity selector
* @return new entity NBT component
*/
static EntityNBTComponent entityNBT(String nbtPath, String selector);
interface Builder extends NBTComponentBuilder<EntityNBTComponent, Builder> {
/**
* Sets the entity selector
* @param selector the selector
* @return this builder
*/
Builder selector(String selector);
}
}Component that displays NBT data from command storage.
/**
* Component displaying command storage NBT data
*/
interface StorageNBTComponent extends NBTComponent<StorageNBTComponent, StorageNBTComponent.Builder> {
/**
* Gets the storage key
* @return the storage key
*/
Key storage();
/**
* Sets the storage key
* @param storage the new storage key
* @return component with new storage key
*/
StorageNBTComponent storage(Key storage);
/**
* Creates a storage NBT component
* @param nbtPath the NBT path
* @param storage the storage key
* @return new storage NBT component
*/
static StorageNBTComponent storageNBT(String nbtPath, Key storage);
interface Builder extends NBTComponentBuilder<StorageNBTComponent, Builder> {
/**
* Sets the storage key
* @param storage the storage key
* @return this builder
*/
Builder storage(Key storage);
}
}Specialized builder interface for NBT components.
/**
* Specialized builder for NBT components
*/
interface NBTComponentBuilder<C extends NBTComponent<C, B>, B extends NBTComponentBuilder<C, B>>
extends ComponentBuilder<C, B> {
/**
* Sets the NBT path expression
* @param nbtPath the path
* @return this builder
*/
B nbtPath(String nbtPath);
/**
* Sets whether to interpret NBT as components
* @param interpret whether to interpret
* @return this builder
*/
B interpret(boolean interpret);
/**
* Sets the separator for multiple NBT results
* @param separator the separator or null
* @return this builder
*/
B separator(@Nullable ComponentLike separator);
}Usage Examples:
import net.kyori.adventure.text.Component;
import net.kyori.adventure.nbt.api.BinaryTagHolder;
import net.kyori.adventure.key.Key;
// Block NBT component showing a sign's text
Component signText = Component.blockNBT(
"front_text.messages[0]",
BlockNBTComponent.Pos.absolute(100, 64, 200)
);
// Entity NBT component showing player's health
Component playerHealth = Component.entityNBT(
"Health",
"@p" // Nearest player selector
);
// Storage NBT component from command storage
Component storedValue = Component.storageNBT(
"custom_data.score",
Key.key("myserver", "player_data")
);
// NBT component with interpretation and separator
Component inventoryDisplay = Component.blockNBT()
.nbtPath("Items[].tag.display.Name")
.pos(BlockNBTComponent.Pos.relative(0, -1, 0))
.interpret(true) // Interpret NBT as text components
.separator(Component.text(", "))
.build();
// Binary tag holder usage
String nbtString = "{id:\"minecraft:diamond_sword\",Count:1b}";
BinaryTagHolder holder = BinaryTagHolder.of(nbtString);
// Use in hover events
Component itemDisplay = Component.text("Diamond Sword")
.hoverEvent(HoverEvent.showItem(
Key.key("minecraft:diamond_sword"),
1,
holder
));NBT path expressions allow precise selection of data from NBT structures:
// Simple field access
"Health" // Root field
"Inventory[0]" // Array element
"CustomName" // String field
// Nested field access
"tag.display.Name" // Nested object fields
"Items[0].tag.Damage" // Array element with nested field
"Attributes[{Name:\"generic.max_health\"}].Base" // Filtered array access
// Multiple results
"Inventory[].id" // All item IDs in inventory
"Effects[].Id" // All potion effect IDspublic class NBTPathExamples {
// Player data access
public static Component getPlayerLevel() {
return Component.entityNBT("XpLevel", "@s");
}
public static Component getPlayerGamemode() {
return Component.entityNBT("playerGameType", "@s");
}
// Inventory item display
public static Component getHeldItemName() {
return Component.entityNBT(
"SelectedItem.tag.display.Name",
"@s"
).interpret(true);
}
// Block data access
public static Component getChestContents(int x, int y, int z) {
return Component.blockNBT(
"Items[].tag.display.Name",
BlockNBTComponent.Pos.absolute(x, y, z)
).interpret(true)
.separator(Component.text(", "));
}
// Sign text access
public static Component getSignLine(int x, int y, int z, int line) {
return Component.blockNBT(
"front_text.messages[" + line + "]",
BlockNBTComponent.Pos.absolute(x, y, z)
).interpret(true);
}
// Command storage access
public static Component getStoredPlayerName(String playerId) {
return Component.storageNBT(
"players." + playerId + ".name",
Key.key("myserver", "playerdata")
);
}
}public class DataComponentIntegration {
// Item data component access
public static Component getItemName() {
return Component.entityNBT(
"SelectedItem.components.\"minecraft:item_name\"",
"@s"
).interpret(true);
}
public static Component getItemLore() {
return Component.entityNBT(
"SelectedItem.components.\"minecraft:lore\"[]",
"@s"
).interpret(true)
.separator(Component.newline());
}
// Custom data component
public static Component getCustomData(String path) {
return Component.entityNBT(
"SelectedItem.components.\"minecraft:custom_data\"." + path,
"@s"
);
}
// Enchantment data
public static Component getEnchantments() {
return Component.entityNBT(
"SelectedItem.components.\"minecraft:enchantments\".levels",
"@s"
);
}
}public class NBTValidator {
public static boolean isValidNBTPath(String path) {
// Basic NBT path validation
if (path == null || path.isEmpty()) {
return false;
}
// Check for valid characters and structure
return path.matches("^[a-zA-Z0-9_.\\[\\]{}\"':@-]+$");
}
public static boolean isValidSelector(String selector) {
// Basic entity selector validation
return selector != null &&
(selector.startsWith("@") || selector.matches("^[a-zA-Z0-9_-]+$"));
}
public static BinaryTagHolder sanitizeNBT(BinaryTagHolder holder) {
try {
BinaryTag tag = holder.get();
// Validate and sanitize NBT data
if (isValidNBTStructure(tag)) {
return holder;
} else {
return BinaryTagHolder.empty();
}
} catch (IOException e) {
return BinaryTagHolder.empty();
}
}
private static boolean isValidNBTStructure(BinaryTag tag) {
// Implement NBT structure validation
// Check for malicious or oversized data
return true; // Simplified
}
}public class NBTOptimization {
// Cache frequently accessed NBT paths
private static final Map<String, Component> NBT_CACHE = new ConcurrentHashMap<>();
public static Component getCachedNBT(String cacheKey, Supplier<Component> nbtSupplier) {
return NBT_CACHE.computeIfAbsent(cacheKey, k -> nbtSupplier.get());
}
// Batch NBT operations
public static List<Component> getBatchedBlockNBT(List<BlockNBTRequest> requests) {
return requests.parallelStream()
.map(req -> Component.blockNBT(req.path(), req.pos()))
.collect(Collectors.toList());
}
// Lazy NBT evaluation
public static Component createLazyNBT(String path, String selector) {
return Component.text("[Loading...]")
.hoverEvent(HoverEvent.showText(
Component.entityNBT(path, selector)
));
}
// Efficient NBT string building
public static String buildNBTString(Map<String, Object> data) {
StringBuilder nbt = new StringBuilder("{");
boolean first = true;
for (Map.Entry<String, Object> entry : data.entrySet()) {
if (!first) nbt.append(",");
nbt.append(entry.getKey()).append(":").append(formatNBTValue(entry.getValue()));
first = false;
}
nbt.append("}");
return nbt.toString();
}
private static String formatNBTValue(Object value) {
if (value instanceof String) {
return "\"" + value + "\"";
} else if (value instanceof Number) {
return value.toString();
} else if (value instanceof Boolean) {
return value.toString() + "b";
}
return "\"" + value + "\"";
}
}Install with Tessl CLI
npx tessl i tessl/maven-net-kyori--adventure-api