Item-NBT-API Documentation

repository·master·Indexed 19 days ago

https://github.com/tr7zw/item-nbt-api

A library for Minecraft developers to manipulate NBT (Named Binary Tag) data on Items, Tiles, and Entities without requiring direct access to NMS (net.minecraft.server) code. It provides tools for modifying NBT data, storing it in files or formats like YAML, JSON, SQL, and Redis, and maintaining compatibility across different Minecraft versions, including support for Spigot and Paper.

Tokens
7.6K
Snippets
21
Records
30
Agent score
71%

What's inside Item-NBT-API

  1. Create NBT wrappers using NBTProxy interfaces

    master

    You can define custom interfaces extending NBTProxy to create type-safe wrappers around NBT data. The API interprets method names starting with has, get, or set as NBT operations.

    Basic Proxy

    Methods like hasKills() map to nbt.hasTag("kills"), setKills(int) maps to nbt.setInteger("kills", amount), and getKills() maps to nbt.getInteger("kills").

    Advanced Mapping with @NBTTarget

    Use the @NBTTarget annotation to specify the operation type (Type.GET, Type.SET, etc.) and the specific NBT key for a method. This allows a getter to return another NBTProxy interface nested under a specific key.

    Custom Data Types and Handlers

    To support complex types like ItemStack, you must override the init() method in your interface and register the appropriate handler from the NBTHandlers class.

    // Basic Proxy
    interface TestInterface extends NBTProxy {
        boolean hasKills();
        void setKills(int amount);
        int getKills();
    }
    
    // Nested Proxy with @NBTTarget
    interface TestInterface extends NBTProxy {
        @NBTTarget(type = Type.GET, value = "other")
        PointsInterface getOtherInterface();
    }
    
    interface PointsInterface extends NBTProxy {
        int getPoints();
        void setPoints(int points);
    }
    
    // Proxy with Custom Handlers
    interface TestInterface extends NBTProxy {
        @Override
        default void init() {
            registerHandler(ItemStack.class, NBTHandlers.ITEM_STACK);
            registerHandler(ReadableNBT.class, NBTHandlers.STORE_READABLE_TAG);
            registerHandler(ReadWriteNBT.class, NBTHandlers.STORE_READWRITE_TAG);
        }
    
        ItemStack getItem();
        void setItem(ItemStack item);
    }
  2. Use NBT-API as a Maven dependency (Recommended)

    master

    The recommended way to use NBT-API is to depend on its plugin version. This requires adding the CodeMC repository to your pom.xml, adding the item-nbt-api-plugin dependency with provided scope, and declaring the dependency in your plugin configuration file so the server loads NBT-API before your plugin.

    Important: Ensure you use the item-nbt-api-plugin artifact ID for this method, not item-nbt-api.

    <!-- 1. Add Repository to pom.xml -->
    <repositories>
      <repository>
        <id>codemc-repo</id>
        <url>https://repo.codemc.io/repository/maven-public/</url>
        <layout>default</layout>
      </repository>
    </repositories>
    
    <!-- 2. Add Dependency to pom.xml -->
    <dependency>
      <groupId>de.tr7zw</groupId>
      <artifactId>item-nbt-api-plugin</artifactId>
      <version>VERSION</version>
      <scope>provided</scope>
    </dependency>
    
    <!-- 3. Add to plugin.yml (Spigot/Bukkit) -->
    depend: [NBTAPI]
    
    <!-- OR Add to paper-plugin.yml (Paper) -->
    dependencies:
      server:
        NBTAPI:
          load: BEFORE
          required: true
          join-classpath: true
  3. Initialize shaded NBT-API early

    master

    If you have shaded NBT-API into your plugin, it is best practice to call NBT.preloadApi() during your plugin's onEnable() method. This ensures the API is initialized early and allows you to verify that it loaded correctly before proceeding with your plugin's logic. If you do not call this, the API will initialize lazily upon its first usage.

    @Override
    public void onEnable() {
        if (!NBT.preloadApi()) {
            getLogger().warning("NBT-API wasn't initialized properly, disabling the plugin");
            getPluginLoader().disablePlugin(this);
            return;
        }
        // Load other things
    }
  4. Set a skull's skin using NBT

    master

    To apply a custom texture to a player head, you must modify the NBT data of an ItemStack. The implementation details differ based on the Minecraft version.

    For Minecraft 1.20.4 and below

    Use NBT.modify to access the SkullOwner compound. It is highly recommended to use a random UUID for the Id field to prevent texture conflicts between different skulls.

    For Minecraft 1.20.5+

    Use NBT.modifyComponents to access the minecraft:profile component.

    Using Paper API (1.12.2+)

    If you are using the Paper API, you can use SkullMeta and PlayerProfile instead of direct NBT manipulation.

    // For Minecraft 1.20.4 and below
    NBT.modify(item, nbt -> {
        ReadWriteNBT skullOwnerCompound = nbt.getOrCreateCompound("SkullOwner");
        skullOwnerCompound.setUUID("Id", UUID.randomUUID());
        skullOwnerCompound.getOrCreateCompound("Properties")
            .getCompoundList("textures")
            .addCompound()
            .setString("Value", textureValue);
    });
    
    // Workaround for Minecraft 1.20.5+
    NBT.modifyComponents(item, nbt -> {
        ReadWriteNBT profileNbt = nbt.getOrCreateCompound("minecraft:profile");
        profileNbt.setUUID("id", uuid);
        ReadWriteNBT propertiesNbt = profileNbt.getCompoundList("properties").addCompound();
        propertiesNbt.setString("name", "textures");
        propertiesNbt.setString("value", textureValue);
    });
    
    // Using Paper API
    SkullMeta meta = (SkullMeta) item.getItemMeta();
    PlayerProfile playerProfile = Bukkit.createProfile(uuid);
    playerProfile.setProperty(new ProfileProperty("textures", textureValue));
    meta.setPlayerProfile(playerProfile);
    item.setItemMeta(meta);
  5. Store data for normal Blocks using Chunk PDC

    master

    Normal blocks do not have NBT. To store custom data for a block, use the Chunk's Persistent Data Container (PDC). This is available since Minecraft 1.16.4.

    • Mechanism: Data is stored in the Chunk's PDC under a blocks compound. The key is the block's location in the format X_Y_Z.
    • Methods:
      • NBT.readChunkPDC(chunk, ...)
      • NBT.readAndGetChunkPDC(chunk, ...)
      • NBT.modifyAndGetChunkPDC(block, ...)

    Caveats:

    1. Persistence: Data is linked to the location. If the block is broken or moved, the data remains at that location unless manually cleared.
    2. Performance: Storing large amounts of data in chunks increases the chunk's disk size.
    // Modify and retrieve data for a specific block
    boolean bool = NBT.modifyAndGetChunkPDC(block, nbt -> {
        nbt.setString("owner_name", "Player123");
        return nbt.getOrDefault("key", false);
    });
  6. Work with NBT files using NBTFileHandle

    master

    Use NBTFileHandle to manage NBT files on disk. This approach maintains a link to the file, allowing you to apply changes and save them later. Note that NBT.getFileHandle will automatically create the file if it does not exist.

    To work with files without maintaining a persistent link, use NBT.readFile(File) and NBT.writeFile(File, ReadWriteNBT). Unlike the handle approach, readFile will return an empty compound if the file is missing rather than creating it.

    // Using NBTFileHandle (automatically creates file if missing)
    NBTFileHandle nbtFile = NBT.getFileHandle(new File("directory", "test.nbt"));
    nbtFile.setString("foo", "bar");
    nbtFile.save();
    
    // Using direct read/write (does NOT automatically create file)
    File file = new File("directory", "test.nbt");
    ReadWriteNBT nbt = NBT.readFile(file);
    NBT.writeFile(file, nbt);
  7. Update NBT data versions with DataFixerUtil

    master

    Use DataFixerUtil to migrate NBT data from older Minecraft versions to newer ones. This is useful when loading data saved in legacy formats (e.g., 1.12.2) into modern versions (e.g., 1.20.6) where the NBT structure (like item components) has changed.

    • Use DataFixerUtil.fixUpItemData(nbt, fromVersion, toVersion) for specific migrations.
    • Use DataFixerUtil.getCurrentVersion() to target the version currently running on the server.
    // Update 1.12.2 data to 1.20.6
    DataFixerUtil.fixUpItemData(nbt, DataFixerUtil.VERSION1_12_2, DataFixerUtil.VERSION1_20_6);
    
    // Update to the current server version
    DataFixerUtil.fixUpItemData(nbt, DataFixerUtil.VERSION1_12_2, DataFixerUtil.getCurrentVersion());
  8. Get started with Item-NBT-API usage

    master

    Once the API is imported, you can begin adding custom NBT tags to Items, Tiles, or Entities without using NMS (net.minecraft.server).

    Key capabilities include:

    • Modifying NBT data directly.
    • Storing NBT in files or other NBT structures.
    • Storing NBT as Strings in formats like YAML, JSON, SQL, or Redis.

    For implementation details, consult the basic usage documentation or specific code examples (e.g., working with Skulls).

  9. Use NBT-API with Minecraft 1.7.10

    master

    Support for Minecraft 1.7.10 is available but is considered broken and is no longer officially supported. If you must use it, be aware of the following limitations:

    • Use version 1.7.10 of the API.
    • NBTLists may not function correctly.
    • NBTTypes do not work because the 1.7.x Minecraft version lacks the necessary underlying features.