Skip to main content

RPG Leveling API

API for external mods to interact with the RPG Leveling system. Mod authors are welcome to integrate with RPG Leveling — use this API to grant XP, listen for level-ups, read player level, and more. See Share XP with teammates for an example (PartyPro); dependency setup and full reference are below. Simple integration! Import the API classes directly. Just declare the dependency in manifest.json and the plugin must be installed on the server or same mods folder.

Adding as Dependency

Step 1: Declare Dependency in manifest.json

Add to your plugin’s manifest.json:
{
  "OptionalDependencies": {
    "Zuxaw:RPGLeveling": "*"
  }
}
Or if you require it:
{
  "Dependencies": {
    "Zuxaw:RPGLeveling": ">=0.2.0"
  }
}

Step 2: Import and Use

Just import the API classes directly:
import org.zuxaw.plugin.api.RPGLevelingAPI;
import org.zuxaw.plugin.api.XPSource;

// Check if available and use
if (RPGLevelingAPI.isAvailable()) {
    RPGLevelingAPI api = RPGLevelingAPI.get();
    if (api != null) {
        api.addXP(playerUuid, 100.0);
    }
}

Quick Start

import org.zuxaw.plugin.api.RPGLevelingAPI;
import org.zuxaw.plugin.api.XPSource;

// Check API availability
if (RPGLevelingAPI.isAvailable()) {
    RPGLevelingAPI api = RPGLevelingAPI.get();
    if (api != null) {
        // Add XP to a player
        api.addXP(playerUuid, 100.0);
        
        // Listen for XP gains
        api.registerExperienceGainedListener(event -> {
            event.setXpAmount(event.getXpAmount() * 1.5);
        });
        
        // Listen for level ups
        api.registerLevelUpListener(event -> {
            int level = event.getNewLevel();
            // Your code here
        });
    }
}

Adding Experience

// Basic usage
api.addXP(playerUuid, 100.0);

// With custom source
XPSource QUEST = XPSource.create("QUEST");
api.addXP(playerUuid, 100.0, QUEST);
Built-in Sources:
  • XPSource.ENTITY_KILL — XP from killing entities
  • XPSource.COMMAND — XP from admin commands
Create Custom Sources:
XPSource QUEST = XPSource.create("QUEST");
XPSource PARTY_SHARE = XPSource.create("PARTY_SHARE");

Experience Gained Events

Modify or cancel XP before it’s awarded.
api.registerExperienceGainedListener(event -> {
    // Access all event properties
    PlayerRef player = event.getPlayer();
    double xp = event.getXpAmount();
    XPSource source = event.getSource();
    boolean cancelled = event.isCancelled();
    Object sourceContext = event.getSourceContext();
    
    // Modify XP
    event.setXpAmount(xp * 2.0);
    
    // Cancel XP
    event.setCancelled(true);
});

All Available Properties

PropertyTypeDescriptionMutable
getPlayer()PlayerRefPlayer gaining XPNo
getXpAmount()doubleCurrent XP amountYes (via setXpAmount())
setXpAmount(double)voidChange XP amount
getSource()XPSourceSource of XPNo
isCancelled()booleanCheck if cancelledYes (via setCancelled())
setCancelled(boolean)voidCancel or allow XP
getSourceContext()ObjectRaw source context (nullable)No
getEntityKillContext()EntityKillContextEntity kill data (for ENTITY_KILL only)No

XPSource Properties

PropertyTypeDescription
getName()StringSource name (e.g., “ENTITY_KILL”, “QUEST”)
getMetadata()ObjectOptional metadata (nullable)
equals(Object)booleanCompare sources by name

EntityKillContext Properties (for ENTITY_KILL only)

PropertyTypeDescription
getEntityUuid()UUIDUUID of killed entity
getEntityLevel()intLevel of killed entity (0 if unknown)
hasEntityLevel()booleanWhether level is known

Example — Entity Kill

api.registerExperienceGainedListener(event -> {
    XPSource source = event.getSource();
    
    // Check if entity kill
    if (source.equals(XPSource.ENTITY_KILL)) {
        EntityKillContext context = event.getEntityKillContext();
        if (context != null) {
            UUID entityUuid = context.getEntityUuid();
            int entityLevel = context.getEntityLevel();
            
            // Apply bonus based on entity level
            if (entityLevel >= 50) {
                event.setXpAmount(event.getXpAmount() * 1.5);
            }
        }
    }
});

Example — Custom Source

XPSource QUEST = XPSource.create("QUEST");

api.registerExperienceGainedListener(event -> {
    XPSource source = event.getSource();
    
    // Check source by name
    if (source.getName().equals("QUEST")) {
        // Or check by equals
        if (source.equals(QUEST)) {
            // Modify XP for quests
            event.setXpAmount(event.getXpAmount() * 1.2);
        }
    }
    
    // Access source metadata (if custom source has it)
    Object metadata = source.getMetadata();
    if (metadata != null) {
        // Your custom logic
    }
});

Level Up Events

React when players level up.
api.registerLevelUpListener(event -> {
    PlayerRef player = event.getPlayer();
    int oldLevel = event.getOldLevel();
    int newLevel = event.getNewLevel();
    int levelsGained = event.getLevelsGained();
    
    // Your code here
});
Available Methods:
MethodReturnsDescription
getPlayer()PlayerRefPlayer who leveled up
getOldLevel()intLevel before leveling up
getNewLevel()intLevel after leveling up
getLevelsGained()intNumber of levels gained

Getting Player Information

When you only have a UUID (e.g. from a command or async context), use the UUID overload. It uses Holder only and may return incorrect data when Holder is null.
// By UUID (Holder-only; use playerRef+store when you have Store)
PlayerLevelInfo info = api.getPlayerLevelInfo(playerUuid);
if (info != null) {
    int level = info.getLevel();
    double xp = info.getExperience();
    double xpNeeded = info.getXpNeededForNext();
    boolean isMax = info.isMaxLevel();
}

// Quick access by UUID
int level = api.getPlayerLevel(playerUuid);
double xp = api.getPlayerXP(playerUuid);
boolean isMax = api.isPlayerMaxLevel(playerUuid);
When you have a PlayerRef and Store (e.g. in a system tick or GUI), use the two-arg overload for correct level/XP. Store is required.
// By PlayerRef + Store (required; call from world thread)
PlayerLevelInfo info = api.getPlayerLevelInfo(playerRef, store);
int level = info.getLevel();
double xp = info.getExperience();
double xpNeeded = info.getXpNeededForNext();
boolean isMax = info.isMaxLevel();

Common Use Cases

Party XP Sharing

XPSource PARTY_SHARE = XPSource.create("PARTY_SHARE");

api.registerExperienceGainedListener(event -> {
    if (event.getSource().equals(XPSource.ENTITY_KILL)) {
        // Cancel original XP
        event.setCancelled(true);
        
        // Share XP with party (your party system code)
        double sharedXP = event.getXpAmount() / partySize;
        for (UUID member : partyMembers) {
            api.addXP(member, sharedXP, PARTY_SHARE);
        }
    }
});

Quest Rewards

XPSource QUEST = XPSource.create("QUEST");

// When quest completes
api.addXP(playerUuid, questXPReward, QUEST);

Level-Based Actions

api.registerLevelUpListener(event -> {
    int level = event.getNewLevel();
    // Your reward/notification code here
});

API Methods Reference

Availability & Version

MethodReturnsDescription
get()RPGLevelingAPIGet API instance (null if not loaded)
isAvailable()booleanCheck if API is available
getVersion()StringGet API version (e.g., “0.2.0”)

Listener Management

MethodReturnsDescription
registerExperienceGainedListener(listener)voidRegister XP gain handler
unregisterExperienceGainedListener(listener)booleanUnregister handler (returns true if was registered)
isExperienceGainedListenerRegistered(listener)booleanCheck if handler is registered
getExperienceGainedListenerCount()intGet number of registered handlers
registerLevelUpListener(listener)voidRegister level up handler
unregisterLevelUpListener(listener)booleanUnregister handler (returns true if was registered)
isLevelUpListenerRegistered(listener)booleanCheck if handler is registered
getLevelUpListenerCount()intGet number of registered handlers

Level reads (player and monster)

Use the API for all level reads so behavior is consistent across the plugin and external mods.
MethodReturnsDescription
getPlayerLevelInfo(playerUuid)PlayerLevelInfo or nullFull level/XP info for a player by UUID (Holder-only; use playerRef+store when you have Store for correct data)
getPlayerLevelInfo(playerRef, store)PlayerLevelInfoFull level/XP info for a player by PlayerRef; store required (call from world thread)
getPlayerLevel(playerUuid)intPlayer level (-1 if not found)
getMonsterLevel(store, npcRef)intMonster/NPC level (1–100, or 0 if unknown). Uses cache, entity overrides (ZoneLevelConfig), or computed from HP/zone. Use when you have the entity Store and Ref (e.g. in damage/defense systems).

Notes

  • All methods are thread-safe
  • Level reads: Use getPlayerLevelInfo / getPlayerLevel for player level and getMonsterLevel(store, npcRef) for monster level so behavior is consistent everywhere (plugin and external mods use the same API). When you have an entity Store (e.g. in systems or GUI), call getPlayerLevelInfo(playerRef, store) — store is required for correct data when Holder is null.
  • XP amounts must be positive
  • Players must be online to receive XP
  • Level ups are handled automatically
  • Events fire in registration order
  • Handler errors are logged but don’t stop other handlers
  • API instance is automatically refreshed on plugin reload