CitizensManager
CitizensManager is the runtime API surface for creating, updating, querying, and controlling citizens.
CitizensManager manager = HyCitizensPlugin.get().getCitizensManager();
About the save parameter
Most mutation methods accept save. Use true for persistent changes. Use false while batching multiple edits, then call saveCitizen(citizen) once.
Lifecycle
Create
void addCitizen(@Nonnull CitizenData citizen, boolean save)
Registers a citizen and spawns it in-world.
Save
void saveCitizen(@Nonnull CitizenData citizen)
void saveCitizen(@Nonnull CitizenData citizen, boolean respawnIfRoleChanged)
Writes the citizen to disk. The second overload can force an NPC respawn when role data changes.
Remove Permanently
void removeCitizen(@Nonnull String citizenId)
Deletes from registry and disk, removes role file, and despawns live entities. Cross-world removal is handled with deferred cleanup when needed.
Spawn/Despawn Runtime Only
void spawnCitizen(CitizenData citizen, boolean save)
void despawnCitizen(CitizenData citizen)
Use these for temporary runtime visibility control without deleting the citizen record.
Choosing The Correct Update Method
| Method | What it changes |
|---|---|
updateCitizen(citizen, save) |
Full respawn of citizen representation (NPC plus nametag mode). |
updateCitizenNPC(citizen, save) |
NPC-side behavior/model/combat/path updates. |
updateCitizenHologram(citizen, save) |
Name and nametag presentation updates (inline nameplate or separate entities). |
updateCitizenNPCItems(citizen) |
Live equipment sync without NPC respawn. |
CitizenData c = manager.getCitizen("town_captain");
if (c != null) {
c.setName("Captain Rhea");
c.setNametagOffset(0f);
manager.updateCitizenHologram(c, true);
c.setNpcHand("Weapon_Sword_Steel");
manager.updateCitizenNPCItems(c);
manager.saveCitizen(c);
}
Nametag APIs
boolean shouldUseSeparateNametagEntities(@Nonnull CitizenData citizen)
void refreshNpcNameplate(@Nonnull CitizenData citizen)
These methods expose the adaptive nametag logic used internally:
- Separate entities when
hideNpc=true, name has multiple non-empty lines, ornametagOffset != 0. - Inline NPC
Nameplatewhen NPC is visible, one non-empty line, and offset is zero. hideNametag=truedisables nametag rendering.
Most plugins should call updateCitizenHologram(citizen, save) instead of these directly.
Query APIs
@Nullable CitizenData getCitizen(@Nonnull String citizenId)
@Nonnull List<CitizenData> getAllCitizens()
int getCitizenCount()
boolean citizenExists(@Nonnull String citizenId)
@Nonnull List<CitizenData> getCitizensNear(@Nonnull Vector3d position, double maxDistance)
getCitizensNear uses configured spawn position (citizen.getPosition()), not live movement position.
One-Call Config Helpers
void setCitizenCombatConfig(@Nonnull String citizenId, @Nonnull CombatConfig combatConfig)
void setCitizenDetectionConfig(@Nonnull String citizenId, @Nonnull DetectionConfig detectionConfig)
void setCitizenPathConfig(@Nonnull String citizenId, @Nonnull PathConfig pathConfig)
These update the config object, save, and respawn NPC-side state.
Movement And Patrol
void moveCitizenToPosition(@Nonnull String citizenId, @Nonnull Vector3d position)
void stopCitizenMovement(@Nonnull String citizenId)
void startCitizenPatrol(@Nonnull String citizenId, @Nonnull String pathName)
void stopCitizenPatrol(@Nonnull String citizenId)
boolean isCitizenPatrolling(@Nonnull String citizenId)
String getCitizenActivePatrolPath(@Nonnull String citizenId)
PatrolManager getPatrolManager()
Events
void addCitizenInteractListener(CitizenInteractListener listener)
void removeCitizenInteractListener(CitizenInteractListener listener)
void addCitizenDeathListener(CitizenDeathListener listener)
void removeCitizenDeathListener(CitizenDeathListener listener)
void addCitizenAddedListener(CitizenAddedListener listener)
void removeCitizenAddedListener(CitizenAddedListener listener)
void addCitizenRemovedListener(CitizenRemovedListener listener)
void removeCitizenRemovedListener(CitizenRemovedListener listener)
See Events for detailed listener payloads and cancellation behavior.
Skin And Appearance Runtime
PlayerSkin determineSkin(CitizenData citizen)
void updateCitizenSkin(CitizenData citizen, boolean save)
void updateCitizenSkinFromPlayer(CitizenData citizen, PlayerRef playerRef, boolean save)
void applySkinPreview(CitizenData citizen, PlayerSkin skin)
Groups
List<String> getAllGroups()
void createGroup(@Nonnull String groupName)
void deleteGroup(@Nonnull String groupName)
boolean groupExists(@Nonnull String groupName)
List<CitizenData> getCitizensByGroup(@Nullable String groupName)
Combat Helpers
void autoResolveAttackType(@Nonnull CitizenData citizen)
void forceAttackEntity(@Nonnull CitizenData citizen, @Nonnull String attackInteractionId)
Internal Integration Hooks
boolean isCitizenSpawning(@Nonnull String citizenId)
void processPendingHologramRemovals(@Nonnull World world, long chunkIndex)
void processPendingNpcRemovals(@Nonnull World world, long chunkIndex)
These are primarily used by HyCitizens listeners (for chunk-load recovery/cleanup). Most external plugins should not call them directly.
Common Safe Pattern
CitizenData citizen = manager.getCitizen(id);
if (citizen == null) {
return;
}
// Batch edits
citizen.setHideNpc(false);
citizen.setHideNametag(false);
citizen.setName("Gate Guard");
citizen.setNametagOffset(0f);
// Apply nametag mode + save once
manager.updateCitizenHologram(citizen, true);