> ## Documentation Index
> Fetch the complete documentation index at: https://docs.nmentities.net/llms.txt
> Use this file to discover all available pages before exploring further.

# Mobs & Factions

> Spawn and inspect registered mobs from code, drive factions and threat, and ship bundled mob definitions.

`NMEntitiesAPI.mobs()` is the registry of every mob NMEntities knows about, plus the operations that act on live ones.

## Lookup and spawning

```java theme={null}
Entity boss = NMEntitiesAPI.mobs().spawn("sir_toast", location);   // full spawn pipeline
String id    = NMEntitiesAPI.mobs().mobId(someEntity);              // null if not an NME mob
boolean ours = NMEntitiesAPI.mobs().isMob(someEntity);
NMEntitiesAPI.mobs().fireTrigger(boss, "cast", player);             // fire any trigger by name

MobDefinition def = NMEntitiesAPI.mobs().get("sir_toast");
Set<String> all = NMEntitiesAPI.mobs().ids();
Collection<MobDefinition> defs = NMEntitiesAPI.mobs().all();
```

`spawn` runs the same pipeline as `/nme spawn`: model, stats and `+onSpawn` effects. `fireTrigger` accepts built-in trigger names and [any trigger your addon registered](extending-effects#custom-triggers).

### Finding a mob that vanished

```java theme={null}
Map<String, String> broken = NMEntitiesAPI.mobs().disabled(); // id -> reason
```

`disabled()` returns the mobs that are configured but **not** registered, usually because their model was deleted or renamed. They are deliberately absent from `ids()`, `all()` and `get()` so a broken mob never reaches a menu or a spawn. This is how you find out why one disappeared.

## Factions and threat

Every mob may belong to a faction. Relations live in `factions.yml`, and allies never target each other or generate threat. Threat tables are per-mob, fed by damage, and decide retargeting. See [Factions & Threat](factions-threat) for the config side.

```java theme={null}
String side = NMEntitiesAPI.mobs().factionOf(entity);   // "players" for players, null = no side
NMEntitiesAPI.mobs().setFaction(entity, "undead");      // override for this entity's lifetime
NMEntitiesAPI.mobs().clearFaction(entity);              // back to its configured side

boolean friendly = NMEntitiesAPI.mobs().areAllies(mob, other);
FactionRelation rel = NMEntitiesAPI.mobs().relationBetween(mob, other); // ALLY / NEUTRAL / ENEMY

NMEntitiesAPI.mobs().addThreat(mob, player, 25.0);      // allies never generate threat
double held = NMEntitiesAPI.mobs().threatOf(mob, player);
Map<Entity, Double> table = NMEntitiesAPI.mobs().threatTable(mob); // most threatening first
NMEntitiesAPI.mobs().clearThreat(mob);                  // forget the fight entirely
```

<Note>
  Relations are **one-way**. `relationBetween(a, b)` need not equal `relationBetween(b, a)`.
</Note>

`threatTable` returns a `Map` rather than a list of pairs on purpose: Kotlin's `Pair` is relocated inside the shaded jar, so an addon could not name the type.

## Shipping bundled mobs

An addon can ship mob definitions from code. They merge into the registry and are **not** wiped when configs reload.

```java theme={null}
NMEntitiesAPI.mobs().contribute(Map.of(
    "flame_knight",
    new MobDefinition(
        "flame_knight",        // id
        "flame_knight_model",  // model — null for a vanilla, model-less mob
        EntityType.ZOMBIE,     // base
        "&cFlame Knight",      // display
        80.0,                  // health
        10.0,                  // damage
        null,                  // armor
        null,                  // speed
        null,                  // scale
        null,                  // glowing
        null,                  // gravity
        null,                  // invulnerable
        true,                  // persistent
        null,                  // nameVisible
        null,                  // ai
        null,                  // silent
        null,                  // collidable
        null,                  // invisible
        null,                  // child (a mob id — String, not a flag)
        null,                  // canPickUpItems
        null,                  // knockbackResistance
        null,                  // followRange
        null,                  // attackKnockback
        "undead",              // faction
        null,                  // equipment (MobEquipment)
        null,                  // aging (MobAging)
        List.of())));          // effects
```

`MobDefinition` fields, in order: `id`, `model`, `base`, `display`, `health`, `damage`, `armor`, `speed`, `scale`, `glowing`, `gravity`, `invulnerable`, `persistent`, `nameVisible`, `ai`, `silent`, `collidable`, `invisible`, `child`, `canPickUpItems`, `knockbackResistance`, `followRange`, `attackKnockback`, `faction`, `equipment`, `aging`, `effects`. Everything after `base` is optional, and `model` may be `null` too — a mob with no model is the plain `base` entity with your stats and effects on it. [Mob Fields](mob-fields) documents what each one means and the range it accepts.

<Warning>
  Unlike [`SpawnRule`](addon-natural-spawns#constructor-shapes), `MobDefinition` is **not** `@JvmOverloads`. From Java you must pass every argument, `null` for the ones you don't want — and the list grows as fields are added, so a Java addon has to be recompiled against each version. From Kotlin, named arguments and defaults work as usual, which is what you want here.
</Warning>

`equipment` is a `MobEquipment(Map<EquipmentSlot, ItemStack> pieces, Map<EquipmentSlot, Float> dropChances)` — drop chance defaults to `0`, not vanilla's \~8.5%, so a contributed boss doesn't seed the floor with free gear. `aging` is a `MobAging(String growsInto, long after)`: the id of the next stage and how many ticks alive before it grows.

A server owner can still override any contributed mob by defining the same id in a `Mobs/` file — your addon supplies sensible defaults, the owner has the last word.
