Skip to main content
This documentation is for NameplateBuilder v4.260326.2 with API v2.0.0.
Select your current API version below to see what needs to change.

What Changed

API 2.0.0 has two changes:
  1. All method names were renamed for clarity (required - your code won’t compile until you rename them)
  2. Resolvers were added as a new way to provide segment text (optional but recommended - your existing tick systems still work)

Step 1: Update Dependencies

Replace the API jar in your libs/ folder and update both files:build.gradle:
dependencies {
    compileOnly files('libs/NameplateBuilder-API-2.0.0.jar')
}
manifest.json:
{
  "Dependencies": {
    "Frotty27:NameplateBuilder": ">=4.260326.2"
  }
}

Step 2: Rename Methods

Find and replace these five method names across your code. The behavior is identical - only the names changed.
FindReplace with
NameplateAPI.describe(NameplateAPI.define(
NameplateAPI.describeVariants(NameplateAPI.defineVariants(
NameplateAPI.undescribe(NameplateAPI.undefine(
NameplateAPI.register(NameplateAPI.setText(
NameplateAPI.remove(NameplateAPI.clearText(
After this step, your code compiles and works exactly as before. You’re done with the required migration.NameplateData methods are unchanged. If you use data.setText(), data.getText(), etc. directly on the component, nothing needs to change.This step is optional. Your renamed setText() / clearText() code works fine. But if your segment’s value comes from an ECS component on the entity (health, stats, faction, etc.), resolvers are simpler and more efficient.The idea: Instead of writing a tick system that reads a component and calls setText() every tick, you give NameplateBuilder a function that does the reading. NameplateBuilder calls it automatically - no tick system needed.

Before (1.0.0 pattern)

You had to write a tick system class, register it, handle spawn initialization with CommandBuffer, and update every tick:
// In setup():
NameplateAPI.define(this, "health", "Health",
        SegmentTarget.ALL, "67/69");

getEntityStoreRegistry().registerSystem(
    new HealthNameplateSystem(NameplateAPI.getComponentType()));
// Separate tick system class:
final class HealthNameplateSystem extends EntityTickingSystem<EntityStore> {
    // ... constructor, getQuery(), getGroup() ...

    @Override
    public void tick(float deltaTime, int index, ArchetypeChunk<EntityStore> chunk,
                     Store<EntityStore> store, CommandBuffer<EntityStore> commandBuffer) {
        // Check if entity has stats
        EntityStatMap stats = chunk.getComponent(index, statMapType);
        if (stats == null) return;

        Ref<EntityStore> entityRef = chunk.getReferenceTo(index);

        // Initialize if needed (can't use setText here - store is locked)
        if (store.getComponent(entityRef, nameplateDataType) == null) {
            NameplateData data = new NameplateData();
            data.setText("health", computeHealth(stats));
            commandBuffer.putComponent(entityRef, nameplateDataType, data);
            return;
        }

        // Update every tick
        NameplateData data = chunk.getComponent(index, nameplateDataType);
        if (data != null) {
            data.setText("health", computeHealth(stats));
        }
    }
}

After (2.0.0 with resolver)

Everything is in setup(). No tick system class needed:
@Override
protected void setup() {
    NameplateAPI.define(this, "health", "Health",
            SegmentTarget.ALL, "67/69")
        .requires(EntityStatMap.getComponentType())
        .resolver((store, entityRef, variantIndex) -> {
            EntityStatMap stats = store.getComponent(entityRef, statMapType);
            if (stats == null) return null;
            int current = Math.round(stats.get(health).get());
            int max = Math.round(stats.get(health).getMax());
            return current + "/" + max;
        });
}
What you can delete: The entire tick system class (HealthNameplateSystem), its registration in setup(), and the CommandBuffer initialization logic. The resolver replaces all of it.You can also add .cacheTicks(100) for data that rarely changes (faction, level, tier) to avoid recomputing every tick. See Resolvers for the full guide.

When to Keep Using setText()

Keep your existing setText() / clearText() code if your segment’s value doesn’t come from an ECS component. For example:
  • A bounty stored in your mod’s config file or database
  • A title assigned by an admin via a chat command
  • A buff applied through an event, not stored as a component
In these cases there’s no component for a resolver to read, so setText() is the right approach.Rule of thumb: If you’re reading a component inside a tick system and calling setText() with the result, that’s a resolver. If you’re reacting to an event or command, keep setText().

Summary

WhatRequired?Action
API jarYesReplace with NameplateBuilder-API-2.0.0.jar
Manifest versionYesChange to ">=4.260326.2"
Rename 5 methodsYesdescribe -> define, register -> setText, remove -> clearText, etc.
Switch tick systems to resolversRecommendedReplace component-reading tick systems with .resolver()
Keep setText() for external dataKeep as-isNo change needed for event/command/database-driven segments
NameplateData methodsNo changedata.setText(), data.getText(), etc. are identical