The Enchants API enables external plugins to interact with PhantomDungeons sword enchant system. Query enchant metadata, manage player progression, upgrade enchants with economy integration, and create custom enchant implementations with full control over behaviour.
Getting Started
Follow these steps to integrate with the enchant system.
1
Get the Instance
Access the singleton API instance from the static provider.
Example.java
importme.fergs.phantomdungeons.modules.enchants.api.EnchantAPI;// Get the singleton instanceEnchantAPI enchantAPI =EnchantAPI.get();
Note: Ensure PhantomDungeons is listed as a dependency in your plugin.yml to guarantee the API is initialized before your plugin loads.
2
Cache for Performance
Store the API instance in your plugin for better performance.
MyPlugin.java
publicclassMyPluginextendsJavaPlugin{privateEnchantAPI enchantAPI;@OverridepublicvoidonEnable(){try{this.enchantAPI=EnchantAPI.get();getLogger().info("✓ Hooked into Enchants!");}catch(IllegalStateExceptione){getLogger().warning("PhantomDungeons not loaded!");}}publicEnchantAPIgetEnchantAPI(){return enchantAPI;}}
3
Safe Null Checks
Always ensure the API is available before using it.
ExampleCheck.java
if(enchantAPI ==null){getLogger().warning("Enchants API not available!");return;}
Core Operations
Querying Enchant Metadata
Enchant metadata is cached in memory for instant lookups. Use these methods to get enchant information.
EnchantQueries.java
// Check if an enchant exists in the systemif(!enchantAPI.hasEnchant("flame-strike")){player.sendMessage("§cThis enchant does not exist!");return;}// Get detailed enchant configurationEnchantConfig config =enchantAPI.getEnchant("flame-strike");if(config !=null){System.out.println("Max Level: "+config.getProgression().maxLevel());System.out.println("Currency: "+config.getUpgrade().currency());}// Get all available enchantsMap<String,EnchantConfig> allEnchants =enchantAPI.getAllEnchants();for(String enchantId :enchantAPI.getEnchantIds()){System.out.println("Enchant: "+ enchantId);}
Checking Player Progress
Read a player's enchant level and unlock status.
Upgrading Enchants
Upgrade an enchant for a player. The API handles currency deduction and events.
Upgrade Costs
Query the cost of upgrading an enchant.
Advanced Management
Setting Enchant Levels
Directly set an enchant level for a player (use with caution).
Maximum Levels
Query or check maximum enchant levels.
Creating Custom Enchants
Step 1: Create a Config File
First, create an enchant configuration file in the enchants/ folder:
In plugins/PhantomDungeons/enchants/ with the filename {enchant-id}.yml
Can I have unlimited enchants?
Yes! Add as many .yml files as you want in the enchants folder.
Does the API work for offline players?
Yes. Most methods accept UUID in addition to Player objects.
What happens on server restart?
All enchant data is hardcoded into the players sword, we decided to do this approach as it can allow for dynamic gameplay.
Can I remove/hide an enchant from the system?
Remove its .yml config file and restart the server. Players keep their unlocked levels in the sword's NBT.
How do custom implementations interact with config?
Custom implementations read progression/activation from config, but override logic with their own implementation.
Is enchant proc async?
90% Yes. All enchant executions are async. Use Bukkit.getScheduler().runTask() if you need the main thread. However, if the event queue needs flushed due to excessive events, it will process them on the main thread (known as a Flush & Reset). Our team is actively working on a more performant approach to solve this issue.
// Get an enchant's current level for a player
int level = enchantAPI.getEnchantLevel(player, "flame-strike");
player.sendMessage("§7Flame Strike Level: §a" + level);
// Check if an enchant is unlocked (level > 0)
if (enchantAPI.isEnchantUnlocked(player, "chain-lightning")) {
player.sendMessage("§aYou have Chain Lightning!");
} else {
player.sendMessage("§cYou haven't unlocked Chain Lightning yet.");
}
// Check if an enchant is at maximum level
if (enchantAPI.isMaxLevel(player, "void-rift")) {
player.sendMessage("§6This enchant is fully upgraded!");
}
// Get all unlocked enchants for a player
Map<String, Integer> unlockedEnchants = enchantAPI.getUnlockedEnchants(player);
for (Map.Entry<String, Integer> entry : unlockedEnchants.entrySet()) {
System.out.println(entry.getKey() + ": Level " + entry.getValue());
}
UpgradeEnchant.java
// Attempt to upgrade an enchant
enchantAPI.upgradeEnchant(player, "flame-strike")
.thenAccept(success -> {
if (success) {
int newLevel = enchantAPI.getEnchantLevel(player, "flame-strike");
player.sendMessage("§aUpgraded! New Level: " + newLevel);
} else {
player.sendMessage("§cUpgrade failed (insufficient funds or max level).");
}
});
UpgradeCost.java
// Get the cost to upgrade from current level to next level
int currentLevel = enchantAPI.getEnchantLevel(player, "flame-strike");
double cost = enchantAPI.getUpgradeCost("flame-strike", currentLevel);
String currency = enchantAPI.getEnchantCurrency("flame-strike");
player.sendMessage("§7Next upgrade costs: §a" + cost + " " + currency);
// Check if player can afford the upgrade
EconomyAPI economy = EconomyAPI.get();
if (economy.hasBalance(player, currency, cost)) {
player.sendMessage("§aYou can afford this upgrade!");
}
AdminSetLevel.java
// Set an enchant to a specific level
enchantAPI.setEnchantLevel(player, "flame-strike", 5)
.thenRun(() -> {
player.sendMessage("§aEnchant level set to 5!");
});
// Reset all enchants for a player
enchantAPI.resetAllEnchants(player)
.thenRun(() -> {
player.sendMessage("§cAll your enchants have been reset!");
});
MaxLevel.java
// Get the maximum level for an enchant type
int maxLevel = enchantAPI.getMaxLevel("chain-lightning");
player.sendMessage("§7Max Level: §a" + maxLevel);
// Check if player is at max level
if (enchantAPI.isMaxLevel(player, "void-rift")) {
player.sendMessage("§6This enchant is fully upgraded!");
} else {
int currentLevel = enchantAPI.getEnchantLevel(player, "void-rift");
int remaining = enchantAPI.getMaxLevel("void-rift") - currentLevel;
player.sendMessage("§7Levels remaining: " + remaining);
}
my-custom-enchant.yml
enchant-id: my-custom-enchant
display-name: "&6My Custom Enchant"
progression:
max-level: 5
base-bonus: 10.0
bonus-per-level: 5.0
activation:
trigger: HIT_MOB # HIT_MOB or MOB_DEATH
cooldown-ticks: 100
base-chance: 25.0 # % chance at level 1
chance-per-level: 15.0 # Additional % per level
upgrade:
currency: money # Use currency ID from economies/
base-cost: 500.0
cost-multiplier: 1.5 # Each level costs 1.5x more
EnchantEventListener.java
// When an enchant procs
@EventHandler
public void onEnchantProc(PlayerEnchantProcAttemptEvent event) {
Player player = event.getPlayer();
String enchantId = event.getEnchantId();
int level = event.getLevel();
double chance = event.getProcChance();
player.sendActionBar("§6" + enchantId + " " + level + " (Chance: " + chance + "%)");
}