Recap: What a Resolver Does
A resolver is a function you attach to a segment. NameplateBuilder calls it every tick for every visible entity. Your function reads data from the entity and returns a string to display, ornull to skip that entity.
store- The entity store. Use it to read components from the entity.entityRef- A reference to the entity being processed. Pass this tostore.getComponent().variantIndex- Which display format the player chose (0 = default). Explained in Format Variants below.
Archetype Filtering with requires()
Without requires(), NameplateBuilder calls your resolver for every visible entity in the world - players, NPCs, projectiles, everything. Your resolver then has to check if the entity even has the right component and return null if it doesn’t. This works, but it’s wasteful.
With requires(), you tell NameplateBuilder which component your resolver needs. It checks the entity’s archetype (the set of components it was created with) before calling your resolver. If the entity doesn’t have that component, your resolver is never called.
requires() filters by archetype (the entity’s type), not by whether the component has data. In rare cases a component might exist but return null values. The null check is cheap insurance.
Caching with cacheTicks()
By default, your resolver runs every tick (30 times per second). For health or mana that changes constantly, that’s exactly what you want. But for data that rarely changes - like a faction name, level, or title - recomputing every tick is wasteful.
cacheTicks() tells NameplateBuilder to remember the result and reuse it for a set number of ticks before calling your resolver again:
Format Variants
Players can choose between different display formats for a segment. For example, health could be shown as"42/67", "63%", or "||||||------". The variantIndex parameter tells your resolver which format the player selected.
First, register the variant names so the UI knows what to show:
default case. If a new variant is added later or the index is somehow unexpected, the default format is shown instead of crashing.
If your segment only has one display format, don’t call defineVariants() and ignore the variantIndex parameter. The format button won’t appear in the UI.
See Format Variants for more details on variant naming, prefix/suffix wrapping, and bar customization.
Resolver vs Manual Text Priority
If an entity has both a resolver and manual text (set viasetText()) for the same segment, the manual text wins. This is intentional - it lets you override computed values for specific entities when needed.
For example, you might have a resolver that computes health from stats, but use setText() to override one specific boss entity with custom text like "INVULNERABLE".
Complete Example
A fullsetup() method with three segments using different resolver configurations:
Next Steps
- Manual Text - For when your data doesn’t come from an ECS component
- Format Variants - Variant naming, prefix/suffix, and bar customization
- Advanced - Hidden metadata keys, cleanup, and edge cases