ModeledNPCs API
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
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).
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());
}
}
| HoverAction | Description |
|---|---|
ENTER | Player's crosshair just entered the NPC's hover cone |
LEAVE | Player'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.
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);
}