> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nameplatebuilder.frotty27.com/llms.txt
> Use this file to discover all available pages before exploring further.

# Quick Start

> Add your own nameplate segment in under 5 minutes.

<Info>This documentation is written for **NameplateBuilder >= v4.260326.7** with **API >= v2.2.0**.</Info>

This page walks you through adding a custom nameplate segment from scratch.

## How It Works

Normally in Hytale, each entity has one `Nameplate` component. If two mods both try to set it, they overwrite each other. NameplateBuilder fixes this by letting each mod register named **segments** (like `"health"`, `"guild"`, `"bounty"`), and combining them into one nameplate per entity. Players get a UI to pick which segments they want to see, reorder them, and customize how they look.

**Your job as a modder is two things:**

1. **Define** your segment - tell NameplateBuilder it exists (name, icon, example text)
2. **Give it a value** - tell NameplateBuilder how to compute the text for each entity

That's it. NameplateBuilder handles everything else: combining segments, the player UI, saving preferences, cleaning up on death, etc.

## Step 1 - Manifest Dependency

Add NameplateBuilder as a dependency in your `manifest.json` so it loads before your mod:

```json theme={null}
{
  "Dependencies": {
    "Frotty27:NameplateBuilder": ">=4.260326.7"
  }
}
```

## Step 2 - API Jar

Download the API jar from [CurseForge](https://www.curseforge.com/hytale/mods/nameplatebuilder-api), place it in your `libs/` folder, and add it to your `build.gradle`:

```groovy theme={null}
dependencies {
    compileOnly files('libs/NameplateBuilder-API-2.2.0.jar')
}
```

You only need this lightweight jar to compile against. It does not get bundled into your mod.

## Step 3 - Define Your Segment

Call `NameplateAPI.define()` in your plugin's `setup()` method. This tells NameplateBuilder that your segment exists so it shows up in the player UI:

```java theme={null}
import com.frotty27.nameplatebuilder.api.NameplateAPI;
import com.frotty27.nameplatebuilder.api.SegmentTarget;

public final class MyModPlugin extends JavaPlugin {

    public MyModPlugin(JavaPluginInit init) {
        super(init);
    }

    @Override
    protected void setup() {
        NameplateAPI.define(this, "bounty", "Bounty",
                SegmentTarget.NPCS, "$500");
    }
}
```

**What this does:** Registers your segment in the `/npb` player UI with:

* `"bounty"` - a unique ID for your segment (only your mod uses this)
* `"Bounty"` - the display name players see in the UI
* `SegmentTarget.NPCS` - a hint that this is for NPCs (can also be `ALL` or `PLAYERS`)
* `"$500"` - example text shown as a preview in the UI

**What this does NOT do:** It does not put any text on any entity yet. The segment appears in the UI, but entities won't show it until you provide a value.

## Step 4 - Provide a Value (Resolver)

Now you need to tell NameplateBuilder what text to show for each entity. You do this with a **resolver** - a function that receives an entity and returns the text to display. NameplateBuilder calls it automatically for every visible entity.

Chain `.resolver()` directly onto your `define()` call:

```java theme={null}
@Override
protected void setup() {
    // Store a reference to the component type your mod uses
    ComponentType<EntityStore, BountyComponent> bountyType =
        BountyComponent.getComponentType();

    NameplateAPI.define(this, "bounty", "Bounty",
            SegmentTarget.NPCS, "$500")
        .resolver((store, entityRef, variantIndex) -> {
            // Read the entity's bounty component
            BountyComponent bounty = store.getComponent(entityRef, bountyType);

            // No bounty on this entity? Return null to skip it.
            if (bounty == null) return null;

            // Return the text to display
            return "$" + bounty.getAmount();
        });
}
```

**What this does:** Every tick, for every entity a player can see, NameplateBuilder calls your resolver. Your function reads data from the entity and returns a string. If the entity doesn't have a bounty, you return `null` and the segment is skipped for that entity.

**That's it.** No tick systems to write, no components to manage, no cleanup to handle. Your segment now works: players can add "Bounty" to their nameplate chain via `/npb`, and they'll see `$500` (or whatever the actual bounty is) above NPCs that have a `BountyComponent`.

## A More Realistic Example

Here's a complete plugin with two segments - one that reads health stats and one that reads a faction component:

```java theme={null}
@Override
protected void setup() {
    ComponentType<EntityStore, EntityStatMap> statMapType =
        EntityStatMap.getComponentType();
    ComponentType<EntityStore, FactionComponent> factionType =
        FactionComponent.getComponentType();

    // Health segment - reads from the entity's stat map
    NameplateAPI.define(this, "health", "Health",
            SegmentTarget.ALL, "67/69")
        .requires(statMapType)  // optimization: only run for entities that have stats
        .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;
        });

    // Faction segment - reads from a faction component, rarely changes
    NameplateAPI.define(this, "faction", "Faction",
            SegmentTarget.NPCS, "<Undead>")
        .requires(factionType)
        .cacheTicks(100)  // only recompute every 100 ticks since factions rarely change
        .resolver((store, entityRef, variantIndex) -> {
            FactionComponent faction = store.getComponent(entityRef, factionType);
            if (faction == null) return null;
            return "<" + faction.getName() + ">";
        });
}
```

Notice the two extra methods:

* **`.requires(componentType)`** - An optimization. Tells NameplateBuilder to only call your resolver for entities that have this component in their archetype. Entities without it are skipped entirely.
* **`.cacheTicks(100)`** - Another optimization. Caches the result for 100 ticks (\~3 seconds) instead of recomputing every tick. Use this for values that don't change often.

## What About Manual Text?

The resolver pattern above covers **most use cases** - any time your segment's value comes from an ECS component on the entity (health, stats, faction, level, tier, etc.).

There is one scenario where resolvers don't work: when the value doesn't come from a component at all. For example, if an admin runs a chat command like `/setbounty goblin 500` and you want to store that bounty externally (in a config or database, not as a component on the entity), there's no component for the resolver to read.

For that case, you can push text directly:

```java theme={null}
// Somewhere in your command handler:
NameplateAPI.setText(store, entityRef, "bounty", "$500");

// Later, to remove it:
NameplateAPI.clearText(store, entityRef, "bounty");
```

You still call `define()` in `setup()` the same way - you just skip the `.resolver()` part. See **[Manual Text](/modding/manual-text)** for the full guide including tick system patterns.

**Rule of thumb:** If your data lives on the entity as a component, use a resolver. If it doesn't, use manual text.

## Next Steps

* **[Resolvers](/modding/resolvers)** - `requires()`, `cacheTicks()`, and format variant support
* **[Manual Text](/modding/manual-text)** - `setText()`, `clearText()`, tick system patterns
* **[Format Variants](/modding/format-variants)** - Let players pick between display formats (e.g. "42/67" vs "63%")
* **[Advanced](/modding/advanced)** - Hidden metadata keys, cleanup, and edge cases
