Tutorial 2 — Adding Your First Mob Affix

A mob affix is a modifier applied to living entities that changes their behaviour or stats. This tutorial adds a simple affix that gives mobs bonus armor, then registers it so it can be applied to entities.

Prerequisites: Complete Tutorial 1 first.


1. Create a key holder for affixes

An ExileKeyHolder is a typed container for a group of related registry entries. Create one for your mod's affixes:

public class MyAffixHolder extends ExileKeyHolder<ExileMobAffix> {

    public MyAffixHolder(String modid) {
        super(modid, LibDatabase.MOB_AFFIX);
    }

    // Declare all your affixes here as public fields.
    public ExileKey<ExileMobAffix, KeyInfo> IRON_HIDE = ExileKey.ofId(
        this,
        "my_mod:iron_hide",  // unique GUID — modid:name format is strongly recommended
        x -> {
            var data = AttributeMobAffix.Data.of(
                Attributes.ARMOR,
                UUID.fromString("a1b2c3d4-e5f6-7890-abcd-ef1234567890"), // stable UUID
                AttributeModifier.Operation.ADDITION,
                new AffixNumberRange(5, 20)  // min 5 armor at 0%, max 20 at 100%
            );
            return new AttributeMobAffix(
                ExileMobAffix.Affects.MOB,
                x.GUID(),
                1000,  // weight — higher = more common
                data,
                AffixTranslation.ofAttribute(Ref.MODID)
            );
        }
    );
}

Notes on the UUID: Every AttributeMobAffix needs a stable, unique UUID. Generate one offline and hardcode it. Two affixes with the same UUID will conflict on the same entity.


2. Register the key holder

Add your holder to MyModConstructor.getAllKeyHolders():

public static final MyAffixHolder AFFIXES = new MyAffixHolder("my_mod");

@Override
public List<ExileKeyHolder> getAllKeyHolders() {
    return List.of(AFFIXES);
}

OrderedModConstructor.register calls holder.init() on each holder, which schedules the factory to run when the EXILE_REGISTRY_GATHER event fires for MOB_AFFIX.


3. Apply the affix to entities

Affixes are pulled from ExileEvents.GRAB_MOB_AFFIXES each tick. Register a listener in your mod constructor (or CommonInit):

ExileEvents.GRAB_MOB_AFFIXES.register(new EventConsumer<GrabMobAffixesEvent>() {
    @Override
    public void accept(GrabMobAffixesEvent e) {
        // Only apply to Zombies, at 75% power.
        if (e.en instanceof Zombie) {
            e.add(new ExileAffixData(MyModConstructor.AFFIXES.IRON_HIDE.GUID(), 75));
        }
    }
});

A good place to register this listener is inside registerDatabaseEntries() in your OrderedModConstructor, or in a static initializer that runs at mod load.


4. Test in-game

Run the client, spawn a Zombie, and inspect its attributes with:

/attribute @e[type=minecraft:zombie,limit=1] minecraft:generic.armor get

The value should be 5–20 above the base armor value, depending on how other mods set the power percentage.


What you learned

  • How to declare a named affix with ExileKey.ofId inside an ExileKeyHolder.
  • How to use AttributeMobAffix with a fixed UUID and a numeric range.
  • How to hook GRAB_MOB_AFFIXES to apply affixes conditionally.

Next steps