Skip to main content
NMEntities is one jar with two layers. The mob, NPC, spawner and effect layer is org.nexomaker.api, documented in the rest of this section. Underneath it sits the embedded BetterModel engine, whose own API ships in the same jar under kr.toxicity.model.api — and that is where models, animations, bones and hitboxes live. That package is not relocated when the plugin jar is shaded, so your addon can call it directly with no extra dependency. NMEntitiesAPI deliberately does not wrap it: the engine API is large, well-documented in its own javadoc, and re-exporting it would only add a layer to keep in step.
This is the vendored engine’s surface, not ours. It is stable in practice and every addon that does model work uses it, but it is versioned by the engine rather than by NMEntities — an engine upgrade can move things here in a way it never will in org.nexomaker.api. Pin the plugin version you compile against.

Bukkit types to platform types

The engine is platform-agnostic, so it speaks PlatformEntity, PlatformPlayer, PlatformLocation rather than Bukkit types. One static class converts:

Finding a model

Player-model limbs live in a parallel set: BetterModel.limb(name), limbOrNull(name), limbs(), limbKeys(). A model name is the .bbmodel filename without its extension — the same string a mob’s model: field takes. Note that a model being loaded is not the same as it being a registered mob; the engine sees every model in models/, the /nme commands only see the ones declared as mobs.

Putting a model on any entity

This is the thing config can’t do: attach a model to an entity NMEntities did not spawn — another plugin’s boss, a vanilla mob, an armour stand you placed yourself.
create(...) always builds a fresh tracker; getOrCreate(...) reuses one already on that entity. Both take an optional TrackerModifier and an optional Consumer that runs before the first update, so you can configure the tracker before any packet goes out. To find what is already attached, go through the registry:
An entity can carry more than one model at once, which is why the registry sits between the entity and its trackers.

Animations

animate returns false when the model has no animation by that name. For anything beyond “play it”, pass an AnimationModifier:
The builder covers predicate (a BooleanSupplier gating whether it plays), start and end keyframes, priority, loop type, speed (fixed or a supplier, so it can follow the mob’s movement speed), override, and player for an animation only one viewer sees. AnimationModifier.DEFAULT and DEFAULT_WITH_PLAY_ONCE are there for the common cases. replace(target, animation, modifier) swaps one animation for another while it is running — the clean way to change gait without a visible reset. The effect DSL’s animation mechanics drive this same tracker, so an addon playing an animation from code and a config line doing it produce identical results.

Who can see it

Per-player visibility is a packet-level thing — the entity is untouched, so vanish plugins, spectator logic and instanced content can all use it without side effects.

Bones

Every bone in the Blockbench model is a RenderedBone you can reach and restyle at runtime:
The available actions are brightness, glow, glowColor, viewRange, tint, previousTint, enchant, togglePart, itemStack, billboard, itemMapping, moveDuration, plus composite(...) to apply several at once and perBone(...) to compute a different action per bone. BonePredicate.name("head") matches by name, BonePredicate.tag(...) by bone tag, and BonePredicate.TRUE hits every bone. Predicates compose with and, or and negate.

Hitboxes and headshots

Models carry per-bone hitboxes, and a tracker can listen to what happens to them. This is how you build damage zones today:
HitBoxDamagedEvent is cancellable and its damage is mutable, so you can multiply, floor or veto per bone. HitBoxInteractAtEvent gives you the same for right-clicks, carrying the player, the hand and the exact hit position on the bone.
Configurable damage zones — headshot multipliers declared in a mob’s YAML — are on the roadmap. Until then this listener is the supported way to do it, and it is what that feature will be built on.

Engine events

The engine has its own event type, ModelEvent, rather than one Bukkit event class per event. There are two ways to listen. Through Bukkit. Every engine event is delivered wrapped in a single BetterModelBukkitEvent:
Through the event bus, which is narrower and unregisterable:
BukkitEventApplication holds a weak reference to your plugin and checks that it is still enabled, so a disabled addon stops receiving events without leaking.

The events

AnimationSignalEvent is worth calling out: you place a signal on a keyframe in Blockbench and it reaches your addon at exactly that frame — sound on footfall, damage on the frame the sword lands. NMEntities’ own events — mob spawns, NPC interactions, reloads — are ordinary Bukkit events and live in org.nexomaker.api.event.