ModeledNPCs API

API Version 8.0  ·  Last Updated March 2025

ModeledNPCs API provides comprehensive access to NPC management, AI pathfinding, escorts, ModelEngine/MythicMobs integration, traders, quests, dialogs, glowing, hover detection, NPC states, scheduling, and hologram animations. This API allows developers to programmatically create, manage, and interact with NPCs in their Bukkit/Spigot plugins.

Key Features

Create and manage ModelEngine and MythicMobs NPCs
Advanced AI pathfinding and patrol routes
Player escort system with custom animations
Trader GUI integration
Quest and dialog management
Per-player NPC visibility
Custom effects and animations
Auto-look system
Per-player glowing with color support
Hover detection with action-bar hints
NPC states (idle, busy, combat, etc.)
In-game hour scheduling
Animated holograms
LuxDialogues integration

Installation

Maven

Add JitPack repository to your pom.xml:

<repositories>
    <repository>
        <id>jitpack.io</id>
        <url>https://www.jitpack.io</url>
    </repository>
</repositories>

Add the dependency:

<dependency>
    <groupId>com.github.el211</groupId>
    <artifactId>ModeledNPCS-API</artifactId>
    <version>8.0</version>
</dependency>

Gradle

Add JitPack repository to your build.gradle:

dependencyResolutionManagement {
    repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
    repositories {
        mavenCentral()
        maven { url 'https://www.jitpack.io' }
    }
}

Add the dependency:

dependencies {
    implementation 'com.github.el211:ModeledNPCS-API:8.0'
}

Plugin Dependency

Add ModeledNPCS as a dependency in your plugin.yml:

depend: [ModeledNPCS]

Getting Started

Accessing the API

import fr.elias.npcs.api.ModeledNPCsAPI;
import fr.elias.npcs.data.INPCData;
import org.bukkit.plugin.java.JavaPlugin;

public class MyPlugin extends JavaPlugin {

    private ModeledNPCsAPI npcAPI;

    @Override
    public void onEnable() {
        if (!Bukkit.getPluginManager().isPluginEnabled("ModeledNPCS")) {
            getLogger().severe("ModeledNPCS not found! Disabling plugin.");
            Bukkit.getPluginManager().disablePlugin(this);
            return;
        }

        npcAPI = ModeledNPCsAPI.get();
        getLogger().info("Successfully hooked into ModeledNPCS API!");
    }
}

Basic NPC Access

getNPCById

INPCData getNPCById(int id);
INPCData npc = npcAPI.getNPCById(1);
if (npc != null) {
    plugin.getLogger().info("Found NPC: " + npc.getName());
}

getEntityByNPCId

Entity getEntityByNPCId(int id);
Entity entity = npcAPI.getEntityByNPCId(1);
if (entity instanceof LivingEntity) {
    ((LivingEntity) entity).setHealth(20.0);
}

getAllNPCIds

List<Integer> getAllNPCIds();
List<Integer> allIDs = npcAPI.getAllNPCIds();
player.sendMessage("Total NPCs: " + allIDs.size());

getAllNPCs

Map<Integer, INPCData> getAllNPCs();
Map<Integer, INPCData> allNPCs = npcAPI.getAllNPCs();
for (INPCData npc : allNPCs.values()) {
    plugin.getLogger().info("NPC: " + npc.getName());
}

Display Names & Nametags

// Get display name (priority: customDisplayName > customName > name)
String getNPCDisplayName(int npcId);

// Get raw display name (may contain color codes like <green>, &a)
String getNPCDisplayNameRaw(int npcId);

// Get formatted display name for a specific player (with PlaceholderAPI)
String getNPCDisplayNameFor(Player viewer, int npcId);

// Set display name and hologram height
void setNPCDisplayName(int id, String name, double height);

// Reapply names and holograms
void reapplyNPCName(int npcId);
void reapplyAllNPCNames();

// Hide/show nametag
void hideNPCNametag(int npcId);
void showNPCNametag(int npcId);
boolean isNPCNametagHidden(int npcId);
npcAPI.setNPCDisplayName(1, "&6&lShop Keeper", 2.5);

String displayName = npcAPI.getNPCDisplayNameFor(player, 1);

npcAPI.hideNPCNametag(1);
if (npcAPI.isNPCNametagHidden(1)) {
    player.sendMessage("NPC nametag is hidden!");
}
npcAPI.showNPCNametag(1);

Location & Movement

Location getNPCLocation(int npcId);
void moveNPC(int npcId, Location newLocation);
Location spawn = new Location(world, 100, 64, 100);
npcAPI.moveNPC(1, spawn);

Creation & Deletion

// type is "modelengine" or "mythicmobs" — returns new ID or -1 on failure
int createNPC(String type, String name, Location location);

void deleteNPC(int npcId);
void respawnNPC(int id);
void updateNPC(int id);
int npcId = npcAPI.createNPC("modelengine", "my_custom_model", player.getLocation());
if (npcId != -1) {
    player.sendMessage("Created NPC with ID: " + npcId);
}

npcAPI.deleteNPC(1);

Permissions & Visibility

boolean canPlayerViewNPC(int npcId, Player player);

Commands

List<String> getNPCCommands(int npcId);
void addCommandToNPC(int id, String command);
void runNPCCommands(int id, Player player);
npcAPI.addCommandToNPC(1, "player: warp spawn");
npcAPI.addCommandToNPC(1, "console: give {player} diamond 1");
npcAPI.addCommandToNPC(1, "message: &aWelcome to the server!");

Effects

List<INPCEffect> getNPCEffects(int npcId);
void playInteractEffects(int id, Player player);
void restartLoopedEffect(int id);

Auto-Look

void enableAutoLook(int id);
void disableAutoLook(int id);

AI & Pathfinding

void addRouteWaypoint(int npcId, Location location);
void clearRoute(int npcId);
npcAPI.addRouteWaypoint(1, new Location(world, 100, 64, 100));
npcAPI.addRouteWaypoint(1, new Location(world, 150, 64, 100));
npcAPI.addRouteWaypoint(1, new Location(world, 150, 64, 150));

Escort System

void startEscort(int npcId, Player player);
void stopEscort(UUID playerId);
void setEscortAnimation(int npcId, String animationName);
String getEscortAnimation(int npcId);
npcAPI.setEscortAnimation(1, "walk");
npcAPI.startEscort(1, player);
npcAPI.stopEscort(player.getUniqueId());

Glowing System

void setNPCGlow(int npcId, Player player, ChatColor color);
void removeNPCGlow(int npcId, Player player);
void setNPCGlowForAll(int npcId, ChatColor color);
void removeNPCGlowForAll(int npcId);
void toggleNPCGlow(int npcId, Player player, boolean enabled, ChatColor color);
// Per-player glow
npcAPI.setNPCGlow(1, player, ChatColor.GREEN);
npcAPI.removeNPCGlow(1, player);

// All players
npcAPI.setNPCGlowForAll(1, ChatColor.RED);
npcAPI.removeNPCGlowForAll(1);

// Toggle
npcAPI.toggleNPCGlow(1, player, true, ChatColor.YELLOW);
npcAPI.toggleNPCGlow(1, player, false, null);

Hover System

// Returns NPC ID, or -1 if player is not hovering any NPC
int getHoveredNPCId(Player player);
boolean isPlayerHoveringNPC(Player player, int npcId);

// Per-NPC hover enable/disable (persisted to npc-extras.yml)
void setNPCHoverEnabled(int npcId, boolean enabled);
boolean isNPCHoverEnabled(int npcId);

// Action-bar hint. Empty string = use global config default.
void setNPCHoverHint(int npcId, String hint);
String getNPCHoverHint(int npcId);

// ModelEngine animation while hovered. Empty string = disabled.
void setNPCHoverAnimation(int npcId, String animation);
String getNPCHoverAnimation(int npcId);
int hoveredId = npcAPI.getHoveredNPCId(player);
if (hoveredId != -1) {
    player.sendMessage("You are looking at NPC #" + hoveredId);
}

npcAPI.setNPCHoverHint(1, "&ePress &6[E]&e to interact!");
npcAPI.setNPCHoverAnimation(1, "wave");

NPC States

States drive the animation and hologram suffix defined in npc-extras.yml. Use "default" to reset.

void setNPCState(int npcId, String state);
String getNPCState(int npcId);
npcAPI.setNPCState(1, "busy");
String state = npcAPI.getNPCState(1);
npcAPI.setNPCState(1, "default");

Schedule System

Restrict NPCs to an in-game hour window. Outside the window they are treated as inactive.

boolean isNPCActive(int npcId);

// Pass -1 for both to disable scheduling
void setNPCSchedule(int npcId, int startHour, int endHour);
int getNPCScheduleStart(int npcId); // -1 if not set
int getNPCScheduleEnd(int npcId);   // -1 if not set
npcAPI.setNPCSchedule(1, 6, 18); // active in-game hours 6–18

if (npcAPI.isNPCActive(1)) {
    player.sendMessage("The NPC is available!");
} else {
    player.sendMessage("This NPC is not available right now.");
}

npcAPI.setNPCSchedule(1, -1, -1); // always active

Hologram Animation

void setNPCHologramFrames(int npcId, List<String> frames);
List<String> getNPCHologramFrames(int npcId);

// Interval in ticks between frame changes (default: 20)
void setNPCHologramFrameInterval(int npcId, int ticks);
int getNPCHologramFrameInterval(int npcId);
List<String> frames = Arrays.asList("&6Shop Keeper", "&eShop Keeper", "&aShop Keeper");
npcAPI.setNPCHologramFrames(1, frames);
npcAPI.setNPCHologramFrameInterval(1, 10); // change every 0.5 seconds

LuxDialogues Integration

boolean isLuxDialoguesAvailable();

// Returns true if triggered, false if not configured or unavailable
boolean triggerLuxDialogue(Player player, int npcId);
boolean isPlayerInLuxDialogue(Player player);

void setNPCLuxDialogue(int npcId, String dialogueId);
String getNPCLuxDialogue(int npcId);
void setNPCLuxFirstPage(int npcId, String page);
String getNPCLuxFirstPage(int npcId); // defaults to "1"
if (npcAPI.isLuxDialoguesAvailable()) {
    npcAPI.setNPCLuxDialogue(1, "welcome_dialogue");
    npcAPI.setNPCLuxFirstPage(1, "1");
    npcAPI.triggerLuxDialogue(player, 1);
}

ModelEngine Integration

void applyModelEngineModel(LivingEntity entity, String blueprint, int npcId);
void respawnModelEngineNPC(int id);

MythicMobs Integration

void spawnMythicMobsNPC(int id, String mobName, Location loc,
                        List<String> commands, String permission, UUID internalUUID);

void spawnMythicMobsNPCFull(int id, String mobName, Location location,
                            List<String> commands, String permission,
                            UUID internalUUID, String customName, String displayName,
                            double hologramHeight, boolean autoLook);

void updateMythicMobName(int id, INPCData npcData);

Trader System

void openTraderGUI(Player player, int npcId);
TraderManager getTraderManager();
npcAPI.openTraderGUI(player, 1);

Quest System

void assignQuest(Player player, String questName);
QuestStatus getQuestStatus(Player player, String questName);
npcAPI.assignQuest(player, "starter_quest");

Dialog System

void openDialog(Player player, int npcId);

Events

NPCInteractEvent

Fired when a player interacts with an NPC.

import fr.elias.npcs.events.NPCInteractEvent;

@EventHandler
public void onNPCInteract(NPCInteractEvent event) {
    Player player = event.getPlayer();
    int npcId = event.getNpcId();

    event.setCancelled(true);
    player.sendMessage("You clicked NPC #" + npcId);
}

NPCHoverEvent

Fired when a player starts or stops hovering an NPC (aiming their crosshair at it within the configured range).

Note: Cancelling an ENTER action prevents the scale-up, sound, and action-bar hint from being applied for that transition. It does not suppress future checks.
import fr.elias.npcs.events.NPCHoverEvent;

@EventHandler
public void onNPCHover(NPCHoverEvent event) {
    Player player = event.getPlayer();
    INPCData npc = event.getNPCData();
    NPCHoverEvent.HoverAction action = event.getAction();

    if (action == NPCHoverEvent.HoverAction.ENTER) {
        player.sendMessage("You are now hovering: " + npc.getName());
    } else {
        player.sendMessage("You stopped hovering: " + npc.getName());
    }
}
HoverActionDescription
ENTERPlayer's crosshair just entered the NPC's hover cone
LEAVEPlayer's crosshair just left the NPC's hover cone

NPCStateChangeEvent

Fired when an NPC's active state changes via setNPCState() or the /mnpc state command.

Note: Cancelling the event prevents the new state (animation + hologram suffix) from being applied.
import fr.elias.npcs.events.NPCStateChangeEvent;

@EventHandler
public void onNPCStateChange(NPCStateChangeEvent event) {
    INPCData npc = event.getNPCData();
    String from = event.getPreviousState();
    String to = event.getNewState();

    Bukkit.broadcastMessage("NPC " + npc.getName() + " state: " + from + " -> " + to);
}

Data Interfaces

INPCData

// Identity
int getId();
String getName();
String getType();

// Display
String getCustomName();
String getCustomDisplayName();

// Location
Location getLocation();
void setLocation(Location location);

// Commands
List<String> getCommands();
void addCommand(String command);

// Visibility
String getViewPermission();
boolean hasViewPermission(Player player);

// Features
boolean isAutoLook();
double getEscortSpeed();
String getLoopedAnimation();
String getInteractAnimation();
String getEscortAnimation();

// Effects
List<? extends INPCEffect> getEffects();

INPCEffect

String getEffectType();
int getDuration();
int getAmplifier();

Code Examples

Example 1: Create Quest NPC

public void createQuestNPC(Player player) {
    int npcId = npcAPI.createNPC("modelengine", "quest_giver", player.getLocation());

    if (npcId == -1) {
        player.sendMessage("§cFailed to create NPC!");
        return;
    }

    npcAPI.setNPCDisplayName(npcId, "&6Quest Giver", 2.5);
    npcAPI.enableAutoLook(npcId);
    npcAPI.addCommandToNPC(npcId, "message: &aWelcome adventurer!");

    player.sendMessage("§aQuest NPC created with ID: " + npcId);
}

Example 2: Create Patrol Route

public void createPatrolRoute(int npcId) {
    npcAPI.clearRoute(npcId);

    World world = Bukkit.getWorld("world");
    npcAPI.addRouteWaypoint(npcId, new Location(world, 100, 64, 100));
    npcAPI.addRouteWaypoint(npcId, new Location(world, 150, 64, 100));
    npcAPI.addRouteWaypoint(npcId, new Location(world, 150, 64, 150));
    npcAPI.addRouteWaypoint(npcId, new Location(world, 100, 64, 150));
}

Example 3: Escort System

public void setupEscortNPC(int npcId, Player player) {
    npcAPI.setEscortAnimation(npcId, "walk");
    npcAPI.startEscort(npcId, player);

    player.sendMessage("§aThe NPC will now escort you!");

    Bukkit.getScheduler().runTaskLater(plugin, () -> {
        npcAPI.stopEscort(player.getUniqueId());
        player.sendMessage("§cEscort ended.");
    }, 1200L);
}

Example 4: Dynamic Trader

@EventHandler
public void onNPCInteract(NPCInteractEvent event) {
    Player player = event.getPlayer();
    int npcId = event.getNpcId();

    if (npcAPI.getTraderManager().hasTrader(npcId)) {
        event.setCancelled(true);

        if (!player.hasPermission("myshop.use")) {
            player.sendMessage("§cYou don't have permission to use this shop!");
            return;
        }

        npcAPI.openTraderGUI(player, npcId);
    }
}

Example 5: Glowing on Hover

@EventHandler
public void onNPCHover(NPCHoverEvent event) {
    Player player = event.getPlayer();
    int npcId = event.getNPCData().getId();

    if (event.getAction() == NPCHoverEvent.HoverAction.ENTER) {
        npcAPI.setNPCGlow(npcId, player, ChatColor.GREEN);
    } else {
        npcAPI.removeNPCGlow(npcId, player);
    }
}

Example 6: NPC State with Event

@EventHandler
public void onNPCInteract(NPCInteractEvent event) {
    int npcId = event.getNpcId();

    if (npcAPI.getNPCState(npcId).equals("default")) {
        npcAPI.setNPCState(npcId, "busy");
        event.getPlayer().sendMessage("§cThis NPC is now busy!");
        event.setCancelled(true);
    }
}

Example 7: Multi-Language Support

public void setLocalizedName(int npcId, Player player) {
    String displayName;

    switch (player.getLocale()) {
        case "fr_FR": displayName = "&6Marchand"; break;
        case "es_ES": displayName = "&6Comerciante"; break;
        default:      displayName = "&6Merchant"; break;
    }

    npcAPI.setNPCDisplayName(npcId, displayName, 2.5);
}