Skip to content

Entity Stats System

Hytale’s Entity Stats System provides a flexible framework for managing entity attributes like Health, Stamina, Mana, and Oxygen. The system supports dynamic modifiers, conditional regeneration, and custom stat types.

EntityStatMap (Component)
├── EntityStatValue[] - Individual stat instances
│ ├── value, min, max - Current and bounds
│ ├── RegeneratingValue[] - Regeneration handlers
│ └── Map<String, Modifier> - Active modifiers
├── StatModifiersManager - Recalculates modifiers from equipment/effects
└── EntityStatType (Asset) - Stat definition from JSON

Represents a single stat instance on an entity:

import com.hypixel.hytale.server.core.modules.entitystats.EntityStatValue;
public class EntityStatValue {
// Get the current value
public float get();
// Get as percentage between min and max (0.0 to 1.0)
public float asPercentage();
// Bounds
public float getMin();
public float getMax();
// Modifiers
@Nullable
public Modifier getModifier(String key);
@Nullable
public Map<String, Modifier> getModifiers();
}

A component that holds all stat values for an entity:

import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap;
import com.hypixel.hytale.server.core.modules.entitystats.EntityStatsModule;
// Get the component type
ComponentType<EntityStore, EntityStatMap> statMapType =
EntityStatsModule.get().getEntityStatMapComponentType();
// Get from entity
EntityStatMap stats = store.getComponent(entityRef, statMapType);
// Get stat by index
EntityStatValue health = stats.get(DefaultEntityStatTypes.getHealth());
EntityStatMap stats = /* get from entity */;
int healthIndex = DefaultEntityStatTypes.getHealth();
// Set to specific value (clamped to min/max)
stats.setStatValue(healthIndex, 50.0f);
// Add to current value
stats.addStatValue(healthIndex, 10.0f);
// Subtract from current value
stats.subtractStatValue(healthIndex, 5.0f);
// Set to minimum
stats.minimizeStatValue(healthIndex);
// Set to maximum
stats.maximizeStatValue(healthIndex);

For client prediction, use the Predictable enum to control network synchronization:

import com.hypixel.hytale.server.core.modules.entitystats.EntityStatMap.Predictable;
// NONE - Normal server update (default)
stats.setStatValue(Predictable.NONE, healthIndex, 50.0f);
// SELF - Client can predict this change locally
stats.addStatValue(Predictable.SELF, staminaIndex, -10.0f);
// ALL - All viewers can predict this change
stats.subtractStatValue(Predictable.ALL, healthIndex, 25.0f);

Hytale provides several built-in stat types:

import com.hypixel.hytale.server.core.modules.entitystats.asset.DefaultEntityStatTypes;
int health = DefaultEntityStatTypes.getHealth();
int oxygen = DefaultEntityStatTypes.getOxygen();
int stamina = DefaultEntityStatTypes.getStamina();
int mana = DefaultEntityStatTypes.getMana();
int signatureEnergy = DefaultEntityStatTypes.getSignatureEnergy();
int ammo = DefaultEntityStatTypes.getAmmo();
Stat TypeDescription
HealthEntity health points
OxygenBreath underwater
StaminaUsed for sprinting and actions
ManaMagic resource
SignatureEnergySpecial ability resource
AmmoRanged weapon ammunition

Modifiers adjust stat bounds (min/max) dynamically. They’re used by armor, effects, and items.

The most common modifier type:

import com.hypixel.hytale.server.core.modules.entitystats.modifier.StaticModifier;
import com.hypixel.hytale.server.core.modules.entitystats.modifier.Modifier.ModifierTarget;
// Additive: value + amount
StaticModifier armorBonus = new StaticModifier(
ModifierTarget.MAX,
StaticModifier.CalculationType.ADDITIVE,
20.0f // +20 max health
);
// Multiplicative: value * amount
StaticModifier percentBoost = new StaticModifier(
ModifierTarget.MAX,
StaticModifier.CalculationType.MULTIPLICATIVE,
1.5f // 1.5x max health
);
EntityStatMap stats = /* ... */;
int healthIndex = DefaultEntityStatTypes.getHealth();
// Add a modifier with a unique key
StaticModifier modifier = new StaticModifier(
ModifierTarget.MAX,
StaticModifier.CalculationType.ADDITIVE,
50.0f
);
stats.putModifier(healthIndex, "my_plugin_bonus", modifier);
// Get existing modifier
Modifier existing = stats.getModifier(healthIndex, "my_plugin_bonus");
// Remove modifier
stats.removeModifier(healthIndex, "my_plugin_bonus");
Key PatternSource
Effect_ADDITIVEEntity effects
Effect_MULTIPLICATIVEEntity effects
Armor_ADDITIVEEquipped armor
Armor_MULTIPLICATIVEEquipped armor

Custom stat types are defined in JSON asset files.

Create a file at Entity/Stats/MyCustomStat.json:

{
"Id": "MyCustomStat",
"InitialValue": 100.0,
"Min": 0.0,
"Max": 100.0,
"Shared": true,
"IgnoreInvulnerability": false,
"ResetType": "InitialValue",
"Regenerating": [
{
"Interval": 1.0,
"Amount": 5.0,
"RegenType": "ADDITIVE",
"ClampAtZero": true,
"Conditions": [
{
"Type": "OutOfCombat",
"DelaySeconds": 3.0
}
]
}
],
"MinValueEffects": {
"TriggerAtZero": false,
"SoundEventId": "MyMod:StatEmpty"
}
}
FieldTypeDescription
IdStringUnique identifier
InitialValueFloatStarting value
MinFloatMinimum bound
MaxFloatMaximum bound
SharedBooleanVisible to other players
IgnoreInvulnerabilityBooleanCan decrease when invulnerable
MinValueEffectsObjectEffects triggered at min value (sound, particles, interactions)
MaxValueEffectsObjectEffects triggered at max value (sound, particles, interactions)
ResetTypeEnumInitialValue or MaxValue
RegeneratingArrayRegeneration rules
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
// Get stat index by ID
int customStatIndex = EntityStatType.getAssetMap().getIndex("MyCustomStat");
// Use with EntityStatMap
EntityStatMap stats = /* ... */;
EntityStatValue customStat = stats.get(customStatIndex);
float current = customStat.get();
float percent = customStat.asPercentage();

Conditions control when regeneration occurs:

ConditionDescription
OutOfCombatTrue after delay since last combat action
GlidingTrue when entity is gliding
ChargingTrue when entity is charging an attack
EnvironmentTrue when in specific environments
LogicConditionCombine conditions with AND/OR
StatCompare stat value against threshold
AliveTrue when entity is alive
NoDamageTakenTrue after delay since taking damage
SuffocatingTrue when entity cannot breathe at its current position
SprintingTrue when entity is sprinting
PlayerCheck player game mode
RegenHealthAlways true (reserved for health regen rules)
WieldingTrue when entity is wielding an item
import com.hypixel.hytale.assetstore.event.LoadedAssetsEvent;
import com.hypixel.hytale.server.core.modules.entitystats.asset.EntityStatType;
public class MyResourcePlugin extends JavaPlugin {
private int focusStatIndex = Integer.MIN_VALUE;
@Override
protected void setup() {
// Register listener to cache stat index when assets are loaded
getEventRegistry().register(
LoadedAssetsEvent.class,
EntityStatType.class,
this::onEntityStatTypesLoaded
);
}
private void onEntityStatTypesLoaded(LoadedAssetsEvent<?, ?, ?> event) {
// Called when EntityStatType assets are loaded or reloaded
focusStatIndex = EntityStatType.getAssetMap().getIndex("Focus");
}
public void consumeFocus(Ref<EntityStore> ref, Store<EntityStore> store, float amount) {
if (focusStatIndex == Integer.MIN_VALUE) return; // Assets not loaded yet
EntityStatMap stats = store.getComponent(ref, EntityStatMap.getComponentType());
if (stats == null) return;
EntityStatValue focus = stats.get(focusStatIndex);
if (focus == null || focus.get() < amount) {
return; // Not enough focus
}
stats.subtractStatValue(Predictable.SELF, focusStatIndex, amount);
}
public void addFocusModifier(Ref<EntityStore> ref, Store<EntityStore> store) {
if (focusStatIndex == Integer.MIN_VALUE) return; // Assets not loaded yet
EntityStatMap stats = store.getComponent(ref, EntityStatMap.getComponentType());
if (stats == null) return;
StaticModifier bonus = new StaticModifier(
Modifier.ModifierTarget.MAX,
StaticModifier.CalculationType.ADDITIVE,
25.0f
);
stats.putModifier(focusStatIndex, "focus_mastery", bonus);
}
}
  1. Use stat indices - Cache indices from EntityStatType.getAssetMap().getIndex() for performance
  2. Unique modifier keys - Use plugin-prefixed keys like "myplugin_bonus" to avoid conflicts
  3. Respect invulnerability - Check IgnoreInvulnerability when dealing damage
  4. Use Predictable wisely - Only use SELF or ALL for changes the client can accurately predict
  5. Clean up modifiers - Remove modifiers when effects expire or equipment is removed
  6. Consider network traffic - Shared: false stats don’t sync to other players
  7. Handle missing stats - Always null-check when getting EntityStatValue