Understanding Minestom Tags System

Concept explanation of how Tags provide type-safe custom data storage using NBT

java (17+) 2025-11-03 minestom tags nbt data concepts

Description

Minestom’s Tags system provides a type-safe way to store custom data on entities, items, blocks, and other objects using NBT (Named Binary Tag) format. Tags are efficient, persistent, and allow you to attach custom properties without modifying core classes.

Key Concepts

What are Tags?

Tags are typed key-value pairs that can be attached to various objects:

  • Entities: Store custom entity properties
  • Items: Store item metadata and custom data
  • Blocks: Store block state and custom properties
  • Other objects: Any object implementing TagReadable/TagWritable

NBT Format

Tags use NBT (Named Binary Tag) format, which is:

  • Efficient: Compact binary representation
  • Persistent: Can be saved to disk
  • Type-safe: Strong typing prevents errors
  • Compatible: Works with Minecraft’s NBT system

Tag Types

  • String: Text data
  • Integer: Whole numbers
  • Double: Decimal numbers
  • Float: Floating point numbers
  • Boolean: True/false values
  • Byte/Short/Long: Various integer sizes
  • Compound: Nested tag structures
  • List: Arrays of tags

Tag Interfaces

  • TagReadable: Objects that can read tags
  • TagWritable: Objects that can write tags
  • Most entities, items, and blocks implement both

Tag Lifecycle

  1. Create tag: Define tag with type and name
  2. Set tag: Store value on object
  3. Get tag: Retrieve value from object
  4. Check tag: Verify tag exists
  5. Remove tag: Delete tag from object
  6. Serialize: Tags are automatically serialized with objects

Persistence

  • Tags are automatically saved with entities/items
  • Survive server restarts (if configured)
  • Can be exported/imported
  • Compatible with Minecraft’s save format

Use Cases

  • Entity properties: Store custom entity data (health, level, etc.)
  • Item metadata: Store item-specific data (durability, enchantments)
  • Block state: Store custom block properties
  • Player data: Store player-specific information
  • Game state: Track game-specific data

Benefits

  • Type safety: Compile-time type checking
  • Efficiency: Optimized NBT storage
  • Persistence: Automatic saving/loading
  • Flexibility: Store any type of data
  • Compatibility: Works with Minecraft’s data format

Best Practices

  • Use descriptive tag names (namespace them: “plugin:tag_name”)
  • Store tags as static final fields for reuse
  • Check for null when reading tags
  • Use appropriate types (don’t store numbers as strings)
  • Clean up unused tags
  • Document tag usage in your code
  • Consider tag size (large compounds can be expensive)

Code

RAW
// Creating tagsTag<String> nameTag = Tag.String("custom_name");Tag<Integer> levelTag = Tag.Integer("player_level");Tag<Double> balanceTag = Tag.Double("player_balance");Tag<Boolean> isVipTag = Tag.Boolean("is_vip");// Setting tags (on objects that implement TagWritable)Player player = // ... get playerif (player instanceof TagWritable writable) {    writable.setTag(nameTag, "CustomPlayer");    writable.setTag(levelTag, 50);    writable.setTag(balanceTag, 1000.0);    writable.setTag(isVipTag, true);}// Reading tags (on objects that implement TagReadable)if (player instanceof TagReadable readable) {    String name = readable.getTag(nameTag); // May return null    Integer level = readable.getTag(levelTag);    Double balance = readable.getTag(balanceTag);    Boolean isVip = readable.getTag(isVipTag);}// Checking if tag existsif (player instanceof TagReadable readable) {    if (readable.hasTag(levelTag)) {        // Tag exists    }}// Removing tagsif (player instanceof TagWritable writable) {    writable.removeTag(levelTag);}// Using tags in custom entity classpublic class CustomEntity extends EntityLiving {    private static final Tag<String> CUSTOM_DATA = Tag.String("custom_data");    private static final Tag<Integer> CUSTOM_LEVEL = Tag.Integer("custom_level");        public void setCustomData(String data) {        setTag(CUSTOM_DATA, data);    }        public String getCustomData() {        return getTag(CUSTOM_DATA);    }        public void setCustomLevel(int level) {        setTag(CUSTOM_LEVEL, level);    }        public int getCustomLevel() {        Integer level = getTag(CUSTOM_LEVEL);        return level != null ? level : 0;    }}// Tags persist across server restarts (if entity is saved)// Tags are automatically serialized with entity data// Tags use efficient NBT format for storage

Comments

No comments yet. Be the first to comment!