Overview
AstralMobs is a Paper plugin that adds blueprint-driven custom mobs to the AstralRealms network. Server operators define mobs entirely in YAML — one blueprint per file, dropped in the plugin's blueprints/ folder. Every mob is a server-side Pig entity spoofed on the client to display as any vanilla mob type (EVOKER, WITHER, WARDEN, CREEPER, ...), allowing full control over AI goals, movement, equipment, effects, and skill casting while preserving vanilla client rendering.
Core concept: Pig-backed architecture
Every custom mob spawned in-game is actually a Pig entity server-side — the NMSMob class extends Pig. The client sees a completely different entity type through a PacketEvents listener that intercepts SPAWN_ENTITY and ENTITY_METADATA packets to spoof the mob's appearance. This hybrid design offers two key advantages:
Consistent entity behavior — one entity class carries any vanilla appearance, letting the plugin drive all AI and movement without wrestling with individual entity type classes.
Custom animations & poses — the plugin can override client-side metadata (including pose index) to animate type-specific stances that vanilla entity classes would never allow (e.g., a Warden stuck in its ROARING pose, or a custom charging animation).
The mob blueprint
A MobBlueprint is the single YAML-backed model that drives everything about a custom mob:
Field | Type | Purpose |
|---|---|---|
| string | Unique blueprint identifier |
| EntityType | Vanilla mob type the client renders (EVOKER, WITHER, CREEPER, SKELETON, ...) |
| double | Max health |
| text component | Mob's name (supports color/formatting) |
| object | Client-side flags (silent, invisible, invulnerable, prevent-drops, etc.) |
| map | Entity attributes (follow_range, movement_speed, scale, step_height, ...) |
| list | Requirement-gated armor/hand items per slot |
| list | Requirement-gated potion effects |
| YAML object map | AI goals (follow-target, cast-skill, idle, wander, ...) |
| YAML object map | Target acquisition rules (detect range, line-of-sight, player-only, ...) |
| object | Movement strategy (walking, flying, creaking) |
| action list | Fired once when mob spawns |
| action list | Fired once when mob dies |
| string | Blueprint id of mob to spawn riding this one |
| bool | If true, passenger's AI drives the vehicle (default: true) |
| bool | If true, all damage to vehicle goes to passenger instead |
| bool | If true, vehicle dies when passenger dies |
| bool | If true, passenger is removed when vehicle dies |
Blueprints are loaded by BlueprintService.load(), which reads every .yml file under <plugin>/blueprints/ recursively, deserializes each as a MobBlueprint using Configurate, and indexes by id. See Mob Blueprints for the full field-by-field reference.
Config-only AI & behavior
All mob behavior lives in YAML — no Java required:
Goal selectors (
goal-selectors) define the mob's action loop: chase targets, cast skills, wander idle, etc. Each goal has priority, flags (MOVE, LOOK, JUMP), and requirement conditions checked on every tick.Target selectors (
target-selectors) define how the mob finds targets: range, must-see (line-of-sight), must-reach (navigable path), mode (NEAREST, FURTHEST), scan interval.Move control (
move-control) sets the movement strategy:walking(pathfinding),flying(ignores terrain), orcreaking(stationary, no movement).Actions (
spawn-actions,death-actions, per-goalstart-actions/stop-actions/interrupt-actions) fire at lifecycle events or goal transitions, using the AstralCore action DSL.Requirements (on goals, equipment, effects) gate behavior behind expression-based conditions checking
%mob_*%placeholders, timers, and memory state.
Each spawned mob gets fresh copies of all goals/selectors/move-control so state changes to one mob don't affect others.
Scripted patterns via memory & timers
Mobs have a per-instance memory map (arbitrary key-value pairs) and timers map (tracking elapsed milliseconds) for multi-stage boss patterns:
Memory — store custom state with
store-memoryaction; read with%mob_memory_<key>%placeholder (default "0").Timers — start with
start-timeraction; read with%mob_timer_<key>%placeholder to check cooldowns and phase transitions (milliseconds elapsed since start).
Example: an evoker boss uses five overlapping cast-skill goals with different priorities and requirement windows (e.g., "only fire this ability if the laser cooldown is between 2000–2999ms"), orchestrated entirely in YAML via memory and timer gates. See amob-blueprints.md for the evoker-boss example.
AstralSkill integration
The cast-skill goal type triggers registered AstralSkill skills by id on cooldown. The mob aims the skill toward its target via SkillService.castThroughPos, and the skill fires off the mob's position. AstralSkill is a soft dependency — if absent, the goal silently no-ops and movement continues. See Casting Skills for full syntax.
Passenger support
Blueprints can define a passenger (another blueprint id) that spawns riding on top of the mob. Options control:
Movement — by default, the passenger's AI goals drive where the pair moves via
PassengerFollowMoveControl. SetpassengerControlsVehicle: falseto let the vehicle move independently.Damage — set
redirectDamage: trueto send all incoming damage to the passenger instead.Death sync — link deaths:
killVehicleOnPassengerDeathorremovePassengerOnDeath.
Runtime lifecycle
MobService.summon(blueprint, location):
Creates an
NMSMob(Pig with the spoofed type).Applies blueprint: display name, health, attributes, equipment, effects, move control, goals, selectors, spawn-actions.
Spawns the entity with
CreatureSpawnEvent.SpawnReason.CUSTOM.Registers it in
MobService.entities(ConcurrentHashMap keyed by UUID).
MobService runs three repeating update loops:
Health display (configurable interval) — refreshes the mob's name tag with a health bar.
Gear evaluation (every tick by default) — re-checks requirement conditions on equipment/effects and updates them.
Metadata reconciliation (every 10 ticks) — re-broadcasts client-side metadata overrides to self-heal dropped spoof packets.
On mob death, death-actions fire. On plugin disable, all mobs are removed and tasks cancelled.
Services
Service | Responsibility |
|---|---|
| Load and index blueprints from |
| Spawn/track/update mobs, run repeating tasks (display, gear, metadata). |
Listener | Trigger |
|---|---|
| Hooks |
| Spoof entity type and apply metadata overrides on |
Registered actions
Mob actions support the %mob_*% placeholder namespace and AstralCore requirement/action DSL:
Action | Scope | Purpose |
|---|---|---|
| Global | Spawn another mob at a location |
| Per-mob | Store a value in mob's memory map |
| Per-mob | Start a named timer on the mob |
| Per-mob | Trigger a vanilla entity status (animation, sound) |
| Per-mob | Override client-side metadata (e.g., pose) |
See Mob Actions for full documentation.
Placeholders
Mobs expose a %mob_*% namespace with the following members:
Placeholder | Type | Notes |
|---|---|---|
| string | Client-side spoofed entity type |
| string | Unique id |
| double | Current health |
| double | Max health |
| double | Health as fraction 0.0–1.0 |
| object | Custom memory value (default "0") |
| long | Milliseconds since |
| string | Current target's name |
| string | Current target's entity type |
| double | Distance to target in blocks |
| string | Simple class name of running goal, or "none" |
| bool | Whether this mob has a passenger |
| bool | Whether this mob is riding another |
| bool | Whether this mob has a target |
| Location | Mob's current position |
| Location | Mob's position + 1 block up |
| mob | The riding mob (if any) |
| mob | The mob this one rides (if any) |
See Placeholders for full documentation.
Commands
Command | Syntax | Permission |
|---|---|---|
|
|
|
|
|
|
Dependencies
Dependency | Required | Notes |
|---|---|---|
Paper 1.21.x | Yes |
|
AstralCore | Yes | Configuration, placeholders, action/requirement DSL, commands |
PacketEvents | Yes | Entity type spoofing via packet listeners |
LibBL | Yes | Backs the non-boss overhead health-text display ( |
AstralSkill | Optional |
|
Configuration surface
AstralMobs loads two config files:
config.yml—mobHealth(MiniMessage template for the health display),forceUpdateInterval(health-display refresh ticks; 0 disables the loop),requirementUpdateInterval(gear-check ticks; effectively 1 = every tick, since the loop clamps to a minimum of 1).messages.yml— localised strings for/mobs reload.
All mob definitions live in blueprints/ folder, loaded recursively.
What ships in the repo
Example blueprints under /Volumes/Untitled/Development/Astral-Realms/internal-documentation/configuration-examples/AstralMobs/blueprints/:
overworld/ — creeper, skeleton, spider, cave-spider, zombie, ninja-zombie, slime, warden (boss,
cast-skill+ pose/status animations)illagers/ — evoker, evoker-boss (multi-phase pattern with memory/timer logic), illusioner, illusioner-minion, pillager, ravager-boss, vex, vindicator, witch
nether/ — blaze, magma-cube, magma-cube-small, piglin, piglin-brute, wither-skeleton, wither (boss, stationary multi-phase), zombified_piglin
Next steps
Installation — deploying the plugin.
Configuration — config.yml and messages.yml.
Commands —
/mobs summonand/mobs reload.Messages — localised strings.
Blueprint YAML Reference — every blueprint field in detail.
Attributes & Metadata — entity properties and client overrides.
AI Goals, Targeting & Movement — goal types and selector rules.
Casting Skills — AstralSkill integration.
Mob Actions — spawn/death/goal-stage actions.
Placeholders —
%mob_*%namespace.Developer API —
MobsAPIand custom events.