CitizenData

The complete data model for a single citizen. Every property you can configure in the UI — and many more — is accessible here as a Java field. CitizenData is what you modify, then pass back to CitizensManager to apply the changes to the live NPC.

package com.electro.hycitizens.models;
📝

Modifying a citizen

After changing fields on a CitizenData, you must call the appropriate update method on CitizensManager to push those changes to the live NPC. Just setting a field on its own does not update anything in the world. See CitizensManager for which update method to use for which change.

Core Identity

getId

String getId()

The citizen's unique internal ID. Auto-generated on creation. Used as the key in config files and as the argument to most CitizensManager methods. Read-only.

getName / setName

String getName()
void setName(String name)

The citizen's display name, shown as a floating hologram above their head. You can create multi-line nametags by embedding \n in the name string. After changing, call manager.updateCitizenHologram(citizen, true).

getModelId / setModelId

String getModelId()
void setModelId(String modelId)

The Hytale model asset ID. For player-model citizens use "Player" and set setPlayerModel(true). For entity types, use the entity's model ID. After changing, call manager.updateCitizen(citizen, true) for a full respawn.

isPlayerModel / setPlayerModel

boolean isPlayerModel()
void setPlayerModel(boolean playerModel)

When true, the citizen uses the Hytale player model and can have a custom skin applied via username or skin data. When false, it uses any other entity model.

getScale / setScale

float getScale()
void setScale(float scale)

The citizen's size multiplier. Valid range: 0.01 to 500. Default: 1.0. Scale also affects the hologram's vertical position automatically.

Position & World

getWorldUUID / setWorldUUID

UUID getWorldUUID()
void setWorldUUID(@Nonnull UUID worldUUID)

The UUID of the world this citizen lives in. Must be set before calling addCitizen.

getPosition / setPosition

Vector3d getPosition()
void setPosition(@Nonnull Vector3d position)

The citizen's configured spawn position. For patrolling or wandering citizens, their actual live position may differ — use getCurrentPosition() for that.

getRotation / setRotation

Vector3f getRotation()
void setRotation(@Nonnull Vector3f rotation)

The citizen's initial facing direction as a Euler rotation.

getCurrentPosition

Vector3d getCurrentPosition()

The citizen's actual live position in the world. Updated every 5 seconds for moving citizens. Read-only — do not set this directly.

Appearance

isHideNametag / setHideNametag

boolean isHideNametag()
void setHideNametag(boolean hideNametag)

When true, no hologram is rendered above the citizen. Default: false.

isHideNpc / setHideNpc

boolean isHideNpc()
void setHideNpc(boolean hideNpc)

When true, the NPC entity itself is invisible (only the nametag hologram remains, if not hidden). Default: false.

getNametagOffset / setNametagOffset

float getNametagOffset()
void setNametagOffset(float nametagOffset)

An additional vertical offset applied to the nametag hologram. Useful for tweaking alignment on non-standard model sizes.

getRotateTowardsPlayer / setRotateTowardsPlayer

boolean getRotateTowardsPlayer()
void setRotateTowardsPlayer(boolean rotateTowardsPlayer)

When true, the citizen smoothly turns to face the nearest player within 25 blocks. Only works for IDLE movement type. Default: false.

Skin (Player Models Only)

getSkinUsername / setSkinUsername

String getSkinUsername()
void setSkinUsername(String skinUsername)

The Minecraft username whose skin this citizen uses. HyCitizens fetches the skin from Mojang's API and caches it. Leave empty if using a custom skin from the Skin Customizer.

isUseLiveSkin / setUseLiveSkin

boolean isUseLiveSkin()
void setUseLiveSkin(boolean useLiveSkin)

When true, the skin is refreshed from Mojang every 30 minutes so it stays up to date with any skin changes the player makes. Default: false.

getCachedSkin / setCachedSkin

PlayerSkin getCachedSkin()
void setCachedSkin(PlayerSkin cachedSkin)

The locally cached skin data. You generally don't need to set this directly — CitizensManager.updateCitizenSkin() fetches and caches it automatically.

Equipped Items

Item fields take a Hytale item ID string, or null to clear the slot. After changing any of these, call manager.updateCitizenNPCItems(citizen) and manager.saveCitizen(citizen).

FieldSlot
getNpcHand() / setNpcHand(String)Main hand
getNpcOffHand() / setNpcOffHand(String)Off hand
getNpcHelmet() / setNpcHelmet(String)Head armor slot
getNpcChest() / setNpcChest(String)Chest armor slot
getNpcGloves() / setNpcGloves(String)Hands/gloves slot
getNpcLeggings() / setNpcLeggings(String)Legs armor slot
citizen.setNpcHand("Weapon_Sword_Iron");
citizen.setNpcHelmet("Armor_Helmet_Iron");
manager.updateCitizenNPCItems(citizen);
manager.saveCitizen(citizen);

Attitude & Combat Behavior

getAttitude / setAttitude

String getAttitude()
void setAttitude(String attitude)

Controls how the citizen behaves toward nearby players. After changing, call manager.updateCitizenNPC(citizen, true).

ValueBehavior
"PASSIVE"Never attacks. Invulnerable regardless of takesDamage setting. Default.
"NEUTRAL"Doesn't attack unless provoked. Requires WANDER movement.
"AGGRESSIVE"Actively attacks nearby players on sight. Requires takesDamage(true) and WANDER movement.

isTakesDamage / setTakesDamage

boolean isTakesDamage()
void setTakesDamage(boolean takesDamage)

When true, the citizen can receive damage from players. When false, the citizen is invulnerable. PASSIVE citizens are always invulnerable regardless of this setting. Default: false.

isOverrideHealth / setOverrideHealth

boolean isOverrideHealth()
void setOverrideHealth(boolean overrideHealth)

When true, the citizen's max health is set to healthAmount instead of the model default. Default: false.

getHealthAmount / setHealthAmount

float getHealthAmount()
void setHealthAmount(float healthAmount)

The citizen's max health, used when overrideHealth is true. Default: 100.

isOverrideDamage / setOverrideDamage

boolean isOverrideDamage()
void setOverrideDamage(boolean overrideDamage)

When true, the citizen deals damageAmount instead of their model's default damage. Default: false.

getDamageAmount / setDamageAmount

float getDamageAmount()
void setDamageAmount(float damageAmount)

The fixed damage per hit when overrideDamage is true. Default: 10.

// Set up an aggressive guard with 500 HP that deals 25 damage per hit
citizen.setAttitude("AGGRESSIVE");
citizen.setTakesDamage(true);
citizen.setOverrideHealth(true);
citizen.setHealthAmount(500f);
citizen.setOverrideDamage(true);
citizen.setDamageAmount(25f);
manager.updateCitizenNPC(citizen, true);

Respawn Behavior

isRespawnOnDeath / setRespawnOnDeath

boolean isRespawnOnDeath()
void setRespawnOnDeath(boolean respawnOnDeath)

When true, the citizen automatically re-spawns after death. When false, the NPC entity is permanently removed on death (the CitizenData record still exists). Default: true.

getRespawnDelaySeconds / setRespawnDelaySeconds

float getRespawnDelaySeconds()
void setRespawnDelaySeconds(float respawnDelaySeconds)

How many seconds to wait after death before respawning. Default: 5.0.

Interaction & Permissions

getRequiredPermission / setRequiredPermission

String getRequiredPermission()
void setRequiredPermission(String permission)

A permission node the player must have to interact with this citizen. An empty string means no restriction. Default: "".

getNoPermissionMessage / setNoPermissionMessage

String getNoPermissionMessage()
void setNoPermissionMessage(String message)

The message shown in red when a player tries to interact without the required permission. Default: "You do not have permissions".

requiresPermission

boolean requiresPermission()

Returns true if requiredPermission is non-empty.

Groups

getGroup / setGroup

String getGroup()
void setGroup(String group)

Assigns this citizen to a named group. Empty string means no group. Groups are useful for batching operations — see CitizensManager.getCitizensByGroup(). Default: "".

Sub-Configurations

Getter / SetterTypeDescription
getMessagesConfig / setMessagesConfigMessagesConfigMessages and selection mode for interactions.
getCommandActions / setCommandActionsList<CommandAction>Commands to run when interacted with.
getAnimationBehaviors / setAnimationBehaviorsList<AnimationBehavior>Configured animation trigger rules.
getMovementBehavior / setMovementBehaviorMovementBehaviorMovement type and speed settings.
getPathConfig / setPathConfigPathConfigPatrol path assignment.
getDetectionConfig / setDetectionConfigDetectionConfigView range, hearing, and alert timers.
getCombatConfig / setCombatConfigCombatConfigAttack, blocking, chasing, and timing.
getDeathConfig / setDeathConfigDeathConfigDeath drops, messages, and commands.

Runtime State

These fields reflect the citizen's live state in the world. You can read them but should not set them directly under normal circumstances.

getSpawnedUUID

@Nullable UUID getSpawnedUUID()

The UUID of the spawned NPC entity. null if the citizen is not currently spawned in the world.

getNpcRef

@Nullable Ref<EntityStore> getNpcRef()

The live entity reference. Used internally for lookups and interaction matching. Check npcRef != null && npcRef.isValid() before using it.

getSequentialMessageIndex

Map<UUID, Integer> getSequentialMessageIndex()

Per-player tracking of which message index to deliver next in SEQUENTIAL mode. You can clear a player's progress by removing their UUID from this map.

// Reset a player's sequential message index (e.g. after a quest resets)
citizen.getSequentialMessageIndex().remove(playerUUID);

Full Example: Hostile Boss Citizen

CitizenData boss = new CitizenData();
boss.setName("{RED}Shadow Titan\n{GRAY}World Boss");
boss.setWorldUUID(worldUUID);
boss.setPosition(new Vector3d(0, 64, 0));
boss.setRotation(new Vector3f(0, 0, 0));
boss.setModelId("Skeleton");  // Non-player entity model
boss.setGroup("bosses");

// Hostile with lots of health and damage
boss.setAttitude("AGGRESSIVE");
boss.setTakesDamage(true);
boss.setOverrideHealth(true);
boss.setHealthAmount(5000f);
boss.setOverrideDamage(true);
boss.setDamageAmount(75f);
boss.setRespawnOnDeath(true);
boss.setRespawnDelaySeconds(300f); // 5 minute respawn

// Detection and combat
DetectionConfig detection = new DetectionConfig(true);
detection.setViewRange(40f);
detection.setHearingRange(25f);
boss.setDetectionConfig(detection);

CombatConfig combat = new CombatConfig();
combat.setAttackDistance(3.0f);
combat.setChaseSpeed(0.9f);
boss.setCombatConfig(combat);

// Death drops
DeathConfig death = new DeathConfig();
death.setDropItems(List.of(
    new DeathDropItem("legendary_core", 1),
    new DeathDropItem("gold_coin", 100)
));
death.setDeathMessages(List.of(
    new CitizenMessage("{RED}The {CitizenName} has been defeated by {PlayerName}!")
));
boss.setDeathConfig(death);

manager.addCitizen(boss, true);