How-to: Add Mob Affixes
Mob affixes modify living entities through attribute changes or recurring potion effects. This guide covers all three approaches: hardcoded Java, JSON datapacks, and mixed.
Option A: Hardcoded attribute affix
Attribute affixes add or multiply an entity attribute. Use them for permanent stat boosts like extra health, armor, speed, or knockback resistance.
public class MyAffixHolder extends ExileKeyHolder<ExileMobAffix> {
public MyAffixHolder(String modid) {
super(modid, LibDatabase.MOB_AFFIX);
}
public ExileKey<ExileMobAffix, KeyInfo> THICK_HIDE = ExileKey.ofId(
this, "my_mod:thick_hide",
x -> new AttributeMobAffix(
ExileMobAffix.Affects.MOB,
x.GUID(),
1000,
AttributeMobAffix.Data.of(
Attributes.ARMOR,
UUID.fromString("d4e8f1a2-b3c4-5678-9abc-def012345678"),
AttributeModifier.Operation.ADDITION,
new AffixNumberRange(3, 15)
),
AffixTranslation.ofAttribute(Ref.MODID)
)
);
}
Register it via OrderedModConstructor.getAllKeyHolders():
public static final MyAffixHolder AFFIXES = new MyAffixHolder("my_mod");
@Override
public List<ExileKeyHolder> getAllKeyHolders() {
return List.of(AFFIXES);
}
Option B: Hardcoded potion affix
Potion affixes apply a status effect to an entity on a recurring interval (every N seconds).
public ExileKey<ExileMobAffix, KeyInfo> SPEED_BURST = ExileKey.ofId(
this, "my_mod:speed_burst",
x -> new PotionMobAffix(
ExileMobAffix.Affects.MOB,
x.GUID(),
800,
PotionMobAffix.Data.of3sEvery10s(
MobEffects.MOVEMENT_SPEED,
new AffixNumberRange(1, 3) // amplifier range
),
AffixTranslation.ofPotion(Ref.MODID)
)
);
Available factory methods for PotionMobAffix.Data:
| Method | Duration | Reapply interval |
|---|---|---|
of5sEvery10s(effect, amp) |
5 s | 10 s |
of3sEvery10s(effect, amp) |
3 s | 10 s |
of1sEvery10s(effect, amp) |
1 s | 10 s |
ofPermanent(effect, amp) |
10 s | 10 s (effectively constant) |
Option C: JSON datapack affix
Create a file in your datapack at:
src/main/resources/data/<your_namespace>/library_of_exile_mob_affix/<name>.json
Attribute affix JSON
{
"id": "my_mod:thick_hide",
"serializer": "attribute_mob_affix",
"affects": "MOB",
"weight": 1000,
"modid": "my_mod",
"attribute_id": "minecraft:generic.armor",
"uuid": "d4e8f1a2-b3c4-5678-9abc-def012345678",
"operation": "ADDITION",
"number_range": { "min": 3.0, "max": 15.0 }
}
Potion affix JSON
{
"id": "my_mod:speed_burst",
"serializer": "potion_mob_affix",
"affects": "MOB",
"weight": 800,
"modid": "my_mod",
"status_effect_id": "minecraft:speed",
"amplifer": { "min": 1.0, "max": 3.0 },
"duration_ticks": 60,
"apply_every_x_seconds": 10
}
JSON affixes are hot-reloaded on /reload. Hardcoded entries remain until restart.
Applying affixes to entities
Affixes are not applied automatically. You must hook ExileEvents.GRAB_MOB_AFFIXES and return
the affixes you want for each entity. The system calls this at tick 3 (spawn) and every 20 ticks.
ExileEvents.GRAB_MOB_AFFIXES.register(new EventConsumer<GrabMobAffixesEvent>() {
@Override
public void accept(GrabMobAffixesEvent e) {
LivingEntity entity = e.en;
// Apply "thick_hide" to all Creepers at 50% power.
if (entity instanceof Creeper) {
e.add(new ExileAffixData("my_mod:thick_hide", 50));
}
// Apply "speed_burst" to all mobs in the Nether at a random power.
if (entity.level().dimension() == Level.NETHER) {
int power = entity.getRandom().nextInt(101); // 0–100
e.add(new ExileAffixData("my_mod:speed_burst", power));
}
}
});
The perc field (0–100) in ExileAffixData controls where in the AffixNumberRange the stat
lands. At 0% you get min; at 100% you get max.
Applying affixes to players
Set affects = Affects.PLAYER in the affix definition. The same GRAB_MOB_AFFIXES event fires
for players as well. Filter with entity instanceof Player if needed.
Notes
- Hardcoded affixes are registered during
EXILE_REGISTRY_GATHERand cannot be changed at runtime without a restart. - JSON affixes support
"loader": "REPLACE_FIELDS"to partially override a hardcoded entry. - Each UUID in an attribute affix must be globally unique. Reusing a UUID across two affixes on the same entity will cause one to silently override the other.