NPC is an operator-focused visual NPC plugin for Axolotl-PM API 5. It stores definitions in plugin_data/NPC/npcs.yml and renders stationary Human, Vanilla actor, block, boat, minecart, and TNT NPCs to Bedrock clients.
NPC actors are visual actors. They do not have mob AI, pathfinding, combat, drops, breeding, or world-entity persistence. The continuous behaviors are optional look-at rotation and the visual fly state for supported flying actors. The plugin keeps the Slapper-style command workflow while providing a PMForms editor for operators.
| Requirement | Version or scope |
|---|---|
| Axolotl-PM | API 5.0.0 or newer within the supported API 5 boundary |
| PHP | 8.4 is the repository build baseline |
| PMForms | Bundled into the built PHAR by DevTools. A separate forms plugin is not required |
| BedrockQuery | Optional. Needed only for remote player-count mode |
| PureChat, PurePerms, ScoreHud | Optional runtime integrations |
| Economy plugin | Optional. The built-in adapters check SimpleEconomy, EcoAPI, TownCoins, and TownEconomy |
Development is pinned to axolotl-pm/pocketmine-mp ~5.51.1 and PMForms 2.3.1 in composer.lock. CI uses AxolotlBucketLabs DevTools v4.0.0. The plugin manifest declares API 5.0.0. The repository does not claim that every Axolotl-PM development revision is compatible without testing that revision.
- Download an
NPC.pharfrom a repository release or CI artifact. - Copy it to the server's
plugins/directory. - Start or restart the server.
- Run
/npc helpas an operator.
The built PHAR contains the PMForms virion. Do not copy the PMForms source into the server's plugin directory.
The operator UI requires npc.admin. The command itself uses npc.command, and the /rca compatibility command uses npc.rca.
NPC uses English by default. Set settings.language in config.yml to select one of the bundled locale codes:
settings:
language: vieThe available codes are bul, chs, deu, eng, fra, ita, jpn, kor, lav, nld, rus, spa, tur, and vie. The selected language applies to command feedback and the operator UI. Technical identifiers, command syntax, UUIDs, configured NPC text, and catalog data remain unchanged. Missing entries fall back to English, so custom locale files can be extended without breaking the plugin.
The shortest in-game workflow is:
/npc
Create NPC
Enter an ID and a nametag
Submit
The UI creates a Human NPC at the player's location. It snapshots the creator's current skin, geometry, scale, hand, off-hand, and armor loadout. The new NPC faces the creator's current direction and enables look-at rotation by default.
The same workflow is available from commands:
/npc create NPC_0 Welcome
/npc type NPC_0 zombie
/npc namevisibility NPC_0 hover
IDs are stable strings. The UI suggests NPC_0, NPC_1, and so on, but an operator may enter any valid unused ID. IDs are not padded with leading zeroes.
/npc and /npc ui open the PMForms editor. The main menu contains only creation and listing. Entity and emote browsers are opened from the relevant editor section instead of being placed in the main menu.
The editor is capability-aware:
- Human NPCs expose skin, equipment, player emotes, and random-emote controls.
- Mob NPCs expose supported actor variants and actor animations.
falling_blockexposes a block visual.- Boat, minecart, and TNT actors do not show Human-only appearance controls.
- Variant controls are shown only for entity types that have registered variants.
- The NPC list is grouped by world.
- Closing a form does not reopen an unrelated menu. Direct sneak-right-click editing returns to the direct editor origin.
An operator with npc.admin can sneak and right-click an NPC to open its editor directly.
The tables below show /npc commands. The /slapper alias uses the same parser, and /rca remains a separate compatibility command.
| Command | Purpose |
|---|---|
/npc |
Open the operator UI when run by a player |
/npc ui |
Open the operator UI explicitly |
/npc help |
Show the command list |
/npc create <id> [name] |
Create a Human NPC at the player's location |
/npc spawn <entity-type> [name] |
Create a new NPC with a selected visual type |
/npc list |
List saved NPC IDs and their worlds |
/npc entities |
List entity types accepted by the current catalog |
/npc id |
Start a hit session that reports the stable ID and runtime entity ID |
/npc remove <id> |
Remove a saved NPC and its spawned actor |
/npc remove |
Start a hit session that removes the selected NPC |
/npc cancel |
Cancel a pending ID or remove hit session |
/npc tp <id> |
Teleport the executing player to an NPC |
/npc updateall |
Save the current definitions and respawn all NPCs |
/npc reload |
Reload definitions from npcs.yml |
/npc debug |
Print runtime and definition information |
/npc version |
Print the plugin version |
/npc rotate <id> <on or off> |
Enable or disable look-at rotation |
/npc rotation-distance <id> <blocks> |
Set the nearest-player look-at range |
| Command | Purpose |
|---|---|
/npc setname <id> <name> |
Replace the first nametag line |
/npc setline <id> <line> <text> |
Set a nametag line from 1 to 16 |
/npc addcommand <id> <action> |
Add a shared action |
/npc clearcommands <id> |
Remove all shared actions |
/npc hitcommand <id> <action> |
Add an action for left-click hit events |
/npc interactcommand <id> <action> |
Add an action for right-click interact events |
/npc interaction-mode <id> shared |
Use the shared action list for both event types |
/npc interaction-mode <id> separate |
Run shared actions and the trigger-specific list |
/npc cooldown <id> <seconds> |
Set the per-player interaction cooldown |
/rca <player> <command> |
Run a command as an online player. This is a compatibility command |
Actions support three forms:
message:&aWelcome, {player}!
console:say {player} clicked the NPC
spawnpoint
An action without a prefix runs as the interacting player. console: actions are trusted operator configuration and should not be exposed to untrusted users.
| Command | Purpose |
|---|---|
/npc type <id> <entity-type> |
Change the visual actor type |
/npc block <id> <block-name or clear> |
Set or clear the block used by falling_block |
/npc equipment <id> <slot> <item or clear> |
Set one Human equipment slot |
/npc skin <id> <relative-file or player or clear> |
Use a local raw skin, copy the executing player's skin, or clear it |
/npc skin-url <id> <https-url or clear> |
Fetch a remote Human skin through the configured allowlist |
/npc scale <id> <size> |
Set a Human or actor scale from 0.1 to 4.0 |
Equipment slots are hand, offhand, helmet, chestplate, leggings, and boots. Standard server item aliases are accepted.
The UI provides an option to copy all or selected equipment slots from the executing player. This is available only for Human NPCs.
| Command | Purpose |
|---|---|
/npc animation <id> <type> [interval] [trigger] |
Configure none, fly, arm_swing, hurt, critical_hit, or magic_critical |
/npc emote <id> <name or UUID> [interval] [trigger] |
Configure a Bedrock player emote for a Human NPC |
/npc emotes [search] |
Search the bundled emote catalog |
/npc random-emote <id> <on or off> [seconds] [emote...] |
Enable a random player-emote pool |
/npc particle <id> <on|off> |
Enable or disable particles |
/npc particle-type <id> <type> |
Select a particle type |
/npc sound <id> <on|off> |
Enable or disable interaction sound |
/npc sound-type <id> <type> |
Select a vanilla sound event or legacy alias |
Animation triggers are timer, spawn, right_click, and left_click.
Player emotes are separate from actor animations. The bundled catalog is loaded from resources/emotes.jsonl. It contains the current checked-in title and UUID snapshot. The built-in aliases include wave, simple_clap, over_there, over_here, bow, saluting, and thinking. A valid Bedrock emote UUID can also be entered directly.
The current catalog includes visual variants for entities such as Armadillo, Axolotl, Cat, Fox, Frog, Llama, Mooshroom, Panda, Parrot, Rabbit, Sheep, Shulker, Wolf, and Tropical Fish. Run /npc entities for entity types and use the UI editor for the variant options available to the selected type.
fly is a visual animation state for supported flying actors such as Bee. It is not mob AI. The NPC does not pathfind or move through the world. animation-sound: true can send a nearby vanilla flap sound for flying actors.
Nametag visibility uses the native Slapper-style metadata path:
| Mode | Client behavior |
|---|---|
always |
The nametag is visible and always shown |
hover |
The nametag is visible but not forced always-on. Bedrock decides when the player is looking at the actor |
never |
The nametag is hidden |
hover is client-defined. It is not a server-side raycast against the NPC's body or text. The legacy nametag-visible: true|false field and /npc namevisible <id> <on|off> command remain supported and map to always or never.
Look-at rotation is independent of nametag visibility. When enabled, the NPC updates its body and head orientation toward the nearest connected, living, non-spectator player within rotation-distance. The calculation uses the player's eye height. When no valid player is in range, it restores the saved creation orientation. Shulkers use a cardinal body direction because their Bedrock actor is block-attached.
Set the source used by {player_count} with /npc playercount:
| Mode | Value |
|---|---|
none |
Empty value |
server |
Players online on this server |
world |
Players in the configured NPC world |
query |
Players returned by the optional BedrockQuery integration |
Example:
/npc playercount NPC_0 world world
/npc playercount NPC_0 query lobby.example.com 19132
Remote query mode is asynchronous. If BedrockQuery is not installed or the target is unavailable, the NPC remains loaded and exposes an offline status instead of crashing the plugin.
The following placeholders are available in lines and are evaluated for the NPC definition:
{npc} Stable NPC ID
{npc_id} Explicit alias for the stable NPC ID
{world} NPC world name
{entity_type} Canonical NPC entity type, for example bee
{variant} Persisted entity variant/color value, when supported
{color} Slapper-compatible section-sign color prefix (§)
{online} Server player count
{players} Selected player-count value
{server_players} Server player count
{world_players} Player count in the NPC world
{player_count} Selected player-count value
{query_players} Remote query online count
{query_max} Remote query maximum count
{query_status} Remote query status
The following placeholders are available in click actions and are resolved for the interacting player:
{player} {player_uuid} {name} {display_name}
{npc} {npc_id} {world} {entity_type} {variant}
{npc_x} {npc_y} {npc_z} {npc_yaw} {npc_pitch}
{online} {players}
{prefix} {suffix} {rank}
{balance} {money} {coins}
{prefix} and {suffix} use PureChat when available. {rank} uses PurePerms when available. Economy placeholders try SimpleEconomy, EcoAPI, TownCoins, and TownEconomy in that order.
{player} and {player_uuid} are action-only values because click commands have an interacting player. Nametag lines are shared entity metadata and therefore cannot contain a different player value for each viewer.
Nametag line breaks accept {line}, {newLine}, {newline}, {newLines}, {newlines}, {breakLine}, {breakline}, \\n, \\r\\n, \\r, and literal newline characters. Minecraft color codes use &a style or native § formatting.
ScoreHud is optional. NPC detects it at runtime and does not fail to load when ScoreHud is absent. The integration resolves and refreshes these tags:
{npc.count}
{npc.ids}
{npc.server_players}
{npc.world_players}
{npc.nearest_id}
{npc.nearest_name}
{npc.nearest_distance}
{npc.nearest_entity_id}
{npc.nearest_type}
{npc.nearest_variant}
{npc.nearest_world}
{npc.nearest_nametag_visibility}
{npc.nearest_animation}
{npc.nearest_emote}
{npc.nearest_motion}
The count, ID list, and nearest-NPC values are scoped to the viewer's current world. npc.nearest_animation reports fly, arm_swing, hurt, critical_hit, magic_critical, or none. npc.nearest_motion reports fly or none.
The plugin creates plugin_data/NPC/config.yml on first start. The active skin URL settings are:
skin-url:
enabled: true
allowed-hosts:
- textures.minecraft.net
- raw.githubusercontent.com
max-bytes: 1048576
timeout-seconds: 8Remote skins must use HTTPS on port 443 and an exact host from allowed-hosts. Redirects are disabled. The asynchronous downloader validates DNS addresses, rejects private and reserved ranges, enforces the size and timeout limits, and accepts only 64x32, 64x64, or 128x128 skin images. Remote URLs are available only for Human NPCs.
NPC definitions are stored in plugin_data/NPC/npcs.yml. The current file schema is version 4. Prefer the UI or commands for edits. If the file must be edited manually, stop the server first and keep IDs unique.
version: 4
npcs:
NPC_0:
world: world
x: 0.5
y: 65.0
z: 0.5
yaw: 0.0
pitch: 0.0
lines:
- "&aWelcome"
- "&7Online: &f{online}"
commands:
- "message:&aWelcome, {player}!"
interaction-mode: shared
cooldown: 2
rotate: true
rotation-distance: 64
entity-type: human
nametag-visibility: always
particle: false
particle-type: flame
particle-count: 8
particle-spread: 0.35
sound: false
sound-type: click
animation-type: none
animation-id: ""
animation-trigger: timer
animation-interval: 100
animation-sound: true
player-count-mode: server
player-count-world: ""
query-host: ""
query-port: 19132
query-interval: 200
scale: 1
equipment: {}Older definitions using nametag-visible continue to load. When nametag-visibility is absent, true maps to always and false maps to never. Walking and path fields are not part of the current NPC model.
Human NPC creation stores a local RGBA skin, cape, geometry, and when available a Bedrock SkinData snapshot under plugin_data/NPC/skins/. The snapshot allows a Persona-style skin to remain usable after the optional PersonaSkin plugin is removed. Existing NPCs cannot reconstruct Persona metadata that was never saved. Capture the player's skin again with /npc skin <id> player when needed.
The plugin keeps a small Slapper compatibility surface without installing or loading the old Slapper plugin:
/slapper spawn Human [name]
/slapper edit <id> name <name>
/slapper edit <id> addcommand <action>
/slapper edit <id> delcommand <action>
/slapper edit <id> listcommands
/slapper edit <id> hand <item|clear>
/slapper edit <id> helmet|chestplate|leggings|boots <item|clear>
/slapper edit <id> scale <size>
/slapper edit <id> tphere
/slapper edit <id> tpto
Numeric runtime entity IDs returned by /npc id are accepted by ID-first edit and remove commands while the actor is spawned. The persistent NPC ID remains the source of truth.
| Plugin or library | Use |
|---|---|
| PureChat | {prefix} and {suffix} action placeholders |
| PurePerms | {rank} action placeholder |
| SimpleEconomy, EcoAPI, TownCoins, TownEconomy | {balance}, {money}, and {coins} action placeholders |
| BedrockQuery | Asynchronous remote player-count mode |
| ScoreHud | npc.* tags |
| PersonaSkin | Optional while capturing a Persona skin. NPC persists the captured data independently |
| PMForms | Build-time virion. It is shaded into the PHAR |
All integrations are capability-checked. NPC can start without any of these optional plugins.
The repository uses Composer for the locked Axolotl-PM and PMForms sources and DevTools for virion preparation, PHPStan, and PHAR packaging. A local build requires PHP 8.4 and the Axolotl-PM extensions required by the selected server checkout.
$php = 'C:\path\to\php.exe'
$devtools = 'C:\path\to\DevTools'
& composer install --no-dev --no-scripts --no-plugins --no-autoloader --no-interaction --no-progress
& $php "$devtools\bin\devtools.php" prepare --project="$PWD" --virions="$PWD\.devtools-virions" --json
& $php "$devtools\bin\devtools.php" doctor --project="$PWD" --virions="$PWD\.devtools-virions" --json
& $php -d phar.readonly=0 "$devtools\bin\devtools.php" build --project="$PWD" --virions="$PWD\.devtools-virions" --out="$PWD\build" --overwrite --json
& $php "$devtools\bin\devtools.php" inspect --project="$PWD" --artifact="$PWD\build\NPC.phar" --jsonThe CI workflow runs PHP lint, the model smoke test, DevTools preparation, PHPStan at max level, PHAR packaging, and a manifest check. Runtime smoke on a server checkout is a separate verification layer from source tests and artifact inspection.
NpcManager is the stable runtime facade. Focused services own the parts that do not need to be mixed with lifecycle orchestration:
storage/NpcRepositoryhandlesnpcs.ymlloading, migration, validation, and saving.asset/NpcAssetServicehandles skin data, Persona snapshots, equipment, and block parsing.model/VanillaEntityProfileis the entity capability registry for hitbox size, eye height, rotation mode, and compatible UI controls.display/NpcDisplayServicehandles nametag rendering and visibility metadata.display/NpcLookAtServicehandles nearest-player body and head rotation.effect/NpcEffectsServicehandles particles, sound, actor animation, and player emotes.integration/NpcCommandServicehandles action commands and optional placeholder adapters.
The public commands, UI flow, persistence schema, and entity packet behavior remain exposed through NpcManager and Main.
The plugin PHP namespace is AxolotlBucketLabs\NPC. Integrations that import plugin classes must use this namespace.
NPC was created by NhanAZ and is maintained by AxolotlBucketLabs.
NPC is released under the MIT License. Axolotl-PM, PMForms, BedrockQuery, ScoreHud, and other optional integrations remain licensed by their respective projects.