Developer API
HyCitizens exposes a code-first API for creating, updating, and controlling citizens at runtime. This guide focuses on the real integration flow used in production plugins.
Audience
This section is for Java plugin developers. If you are configuring citizens in-game, start with the User Guide.
1. Add Dependency
Declare HyCitizens as a runtime dependency so your plugin loads after it:
{
"Dependencies": {
"electro:HyCitizens": "*"
}
}
Also include the HyCitizens jar as a compile dependency in your build so your IDE resolves API types.
2. Get The Manager
CitizensManager manager = HyCitizensPlugin.get().getCitizensManager();
CitizensManager is the entry point for almost all runtime work.
3. Core Mental Model
Use a two-step flow:
| Step | What you do |
|---|---|
| Edit data | Modify a CitizenData object. |
| Apply update | Call the matching CitizensManager update method to push changes to the live entity. |
4. Pick The Right Update Method
| Method | Use for |
|---|---|
updateCitizen(citizen, save) |
Full respawn (NPC plus nametag representation). |
updateCitizenNPC(citizen, save) |
NPC-only changes: combat, detection, path behavior, skin/model internals. |
updateCitizenHologram(citizen, save) |
Name and nametag presentation changes. This now updates either inline NPC nameplate or separate hologram entities automatically. |
updateCitizenNPCItems(citizen) |
Equipment changes without respawning. |
5. Nametag Rendering Rules
HyCitizens now uses adaptive nametag rendering:
- Inline NPC
Nameplatewhen all are true: NPC visible, exactly one non-empty name line, nametag offset is 0. - Separate nametag entities when any are true:
hideNpc=true, multiple non-empty name lines, or non-zero nametag offset. hideNametag=truedisables both inline and separate nametag rendering.
For name, hideNametag, hideNpc, or nametagOffset changes, call updateCitizenHologram(citizen, true).
6. Minimal Create Example
CitizensManager manager = HyCitizensPlugin.get().getCitizensManager();
CitizenData citizen = new CitizenData(
"town_captain",
"Captain Rhea",
"Player",
worldUuid,
new Vector3d(0, 70, 0),
new Vector3f(0, 0, 0),
1.0f,
null,
new ArrayList<>(),
"",
"",
List.of(),
true,
false,
"Simon",
null,
0L,
true
);
citizen.setMessagesConfig(new MessagesConfig(
List.of(new CitizenMessage("{GOLD}Welcome to the city.", "F_KEY", 0f)),
"SEQUENTIAL",
true
));
manager.addCitizen(citizen, true);
Where To Go Next
| Page | Why read it |
|---|---|
| CitizensManager | Full runtime lifecycle and method-by-method behavior. |
| CitizenData | Every field, update requirements, and runtime state notes. |
| Events | Interaction/death hooks and cancellation patterns. |
| Full Example | End-to-end setup with messages, combat, patrol, and listeners. |
Production tip: batch multiple field edits, then call one update method and one save call. This avoids extra respawns and disk writes.