Skip to content

Events

CuriosPaper provides custom Bukkit events that your plugins can listen to. These let you react to accessory changes, loot generation, mob drops, and recipe crafting.

AccessoryEquipEvent

Fired when a player equips, unequips, or swaps an accessory.

Example 1: Logging Accessory Changes

import org.bg52.curiospaper.event.AccessoryEquipEvent;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class AccessoryLogger implements Listener {

    @EventHandler
    public void onAccessoryEquip(AccessoryEquipEvent event) {
        Player player = event.getPlayer();
        String slotType = event.getSlotType();
        int slotIndex = event.getSlotIndex();

        switch (event.getAction()) {
            case EQUIP:
                String itemName = event.getNewItem().getItemMeta().getDisplayName();
                player.sendMessage(ChatColor.GREEN + "✓ Equipped " + itemName
                    + " in " + slotType + " slot " + slotIndex);
                break;

            case UNEQUIP:
                String oldName = event.getPreviousItem().getItemMeta().getDisplayName();
                player.sendMessage(ChatColor.RED + "✗ Unequipped " + oldName
                    + " from " + slotType + " slot " + slotIndex);
                break;

            case SWAP:
                player.sendMessage(ChatColor.YELLOW + "↔ Swapped items in "
                    + slotType + " slot " + slotIndex);
                break;
        }
    }
}

Example 2: Restricting Accessories by Permission

Prevent players from equipping certain slot types without permission:

import org.bg52.curiospaper.event.AccessoryEquipEvent;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class AccessoryRestriction implements Listener {

    @EventHandler
    public void onAccessoryEquip(AccessoryEquipEvent event) {
        if (event.getAction() == AccessoryEquipEvent.Action.UNEQUIP) return;

        String slotType = event.getSlotType();
        String permission = "myplugin.slot." + slotType;

        // Check if the player has permission for this slot type
        if (!event.getPlayer().hasPermission(permission)) {
            event.setCancelled(true);
            event.getPlayer().sendMessage(ChatColor.RED
                + "You don't have permission to use " + slotType + " slots!");
        }
    }
}

Example 3: Accessory Set Bonus System

Grant bonus effects when a player has a full set of matching accessories:

import org.bg52.curiospaper.CuriosPaper;
import org.bg52.curiospaper.api.CuriosPaperAPI;
import org.bg52.curiospaper.event.AccessoryEquipEvent;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.potion.PotionEffect;
import org.bukkit.potion.PotionEffectType;

import java.util.List;

public class SetBonusListener implements Listener {

    private final CuriosPaperAPI api;
    private static final String SET_PREFIX = "&c&lInferno ";

    public SetBonusListener() {
        this.api = CuriosPaper.getInstance().getCuriosPaperAPI();
    }

    @EventHandler
    public void onAccessoryChange(AccessoryEquipEvent event) {
        Player player = event.getPlayer();

        // Check after a 1-tick delay so the item is actually in the slot
        player.getServer().getScheduler().runTaskLater(
            CuriosPaper.getInstance(), () -> checkSetBonus(player), 1L);
    }

    private void checkSetBonus(Player player) {
        int setPieces = 0;

        for (String slotType : api.getAllSlotTypes()) {
            List<ItemStack> items = api.getEquippedItems(player, slotType);
            for (ItemStack item : items) {
                if (item != null && item.hasItemMeta()
                    && item.getItemMeta().getDisplayName().contains("Inferno")) {
                    setPieces++;
                }
            }
        }

        if (setPieces >= 3) {
            player.addPotionEffect(new PotionEffect(
                PotionEffectType.FIRE_RESISTANCE, 200, 0, true, false));
            player.sendMessage(ChatColor.GOLD + "★ Inferno Set Bonus: Fire Resistance!");
        }
        if (setPieces >= 2) {
            player.addPotionEffect(new PotionEffect(
                PotionEffectType.INCREASE_DAMAGE, 200, 0, true, false));
        }
    }
}

Example 4: Economy Integration

Charge players for equipping accessories:

import org.bg52.curiospaper.event.AccessoryEquipEvent;
import org.bukkit.ChatColor;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
// Assumes you have a Vault-compatible economy plugin
// import net.milkbowl.vault.economy.Economy;

public class AccessoryCostListener implements Listener {

    // private Economy economy; // Inject via Vault

    @EventHandler
    public void onAccessoryEquip(AccessoryEquipEvent event) {
        if (event.getAction() != AccessoryEquipEvent.Action.EQUIP) return;

        Player player = event.getPlayer();
        double cost = getSlotCost(event.getSlotType());

        if (cost <= 0) return;

        // Check if player can afford the cost
        // if (!economy.has(player, cost)) {
        //     event.setCancelled(true);
        //     player.sendMessage(ChatColor.RED + "You need $" + cost + " to equip here!");
        //     return;
        // }

        // Charge the player
        // economy.withdrawPlayer(player, cost);
        // player.sendMessage(ChatColor.GREEN + "Charged $" + cost + " for equipping.");
    }

    private double getSlotCost(String slotType) {
        switch (slotType) {
            case "ring": return 100.0;
            case "necklace": return 250.0;
            case "charm": return 50.0;
            default: return 0.0;
        }
    }
}

AccessoryEquipEvent Properties

Method Return Description
getPlayer() Player The player equipping/unequipping
getSlotType() String The slot type key (e.g., "ring")
getSlotIndex() int The index within the slot type
getPreviousItem() ItemStack The item previously in the slot (may be null)
getNewItem() ItemStack The new item being placed (may be null)
getAction() Action EQUIP, UNEQUIP, or SWAP
isCancelled() boolean Whether the event is cancelled
setCancelled(boolean) void Cancel the event

Actions

Action Previous Item New Item
EQUIP null Item being equipped
UNEQUIP Item being removed null
SWAP Item being replaced New item

CuriosLootGenerateEvent

Fired when a custom CuriosPaper item is about to be generated inside a loot container (chest, barrel, brushable block). This event is cancellable and allows modifying the generated item.

Example: Restricting Loot by World

import org.bg52.curiospaper.event.CuriosLootGenerateEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class LootWorldRestriction implements Listener {

    @EventHandler
    public void onLootGenerate(CuriosLootGenerateEvent event) {
        String tableKey = event.getLootTableKey();

        // Only allow custom items in nether loot tables
        if (!tableKey.contains("nether") && !tableKey.contains("bastion")) {
            event.setCancelled(true);
        }
    }
}

Example: Modifying Generated Loot

import org.bg52.curiospaper.event.CuriosLootGenerateEvent;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;
import java.util.List;

public class LootEnhancer implements Listener {

    @EventHandler
    public void onLootGenerate(CuriosLootGenerateEvent event) {
        // Add a special lore tag to all loot-generated accessories
        ItemStack item = event.getItem();
        ItemMeta meta = item.getItemMeta();
        if (meta != null) {
            List<String> lore = meta.getLore();
            if (lore == null) lore = new ArrayList<>();
            lore.add("");
            lore.add("§8§o✦ Found in a dungeon chest ✦");
            meta.setLore(lore);
            item.setItemMeta(meta);
            event.setItem(item);
        }
    }
}

CuriosLootGenerateEvent Properties

Method Return Description
getLootTableKey() String The namespaced key of the loot table (e.g., minecraft:chests/simple_dungeon)
getCustomItemId() String The internal ID of the custom item being generated
getItem() ItemStack The item being generated
setItem(ItemStack) void Replace the item to be generated
isCancelled() boolean Whether the generation is cancelled
setCancelled(boolean) void Cancel item generation (item will not appear in chest)

CuriosMobDropEvent

Fired when a custom CuriosPaper item is about to be dropped by a mob on death. This event is cancellable and allows modifying the dropped item.

Example: Logging Mob Drops

import org.bg52.curiospaper.event.CuriosMobDropEvent;
import org.bukkit.entity.LivingEntity;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class MobDropLogger implements Listener {

    @EventHandler
    public void onMobDrop(CuriosMobDropEvent event) {
        LivingEntity mob = event.getEntity();
        String itemId = event.getCustomItemId();

        mob.getServer().getLogger().info(
            "[CuriosDrop] " + mob.getType().name()
            + " dropped custom item: " + itemId
            + " at " + mob.getLocation().toVector()
        );
    }
}

Example: Boosting Drops with Looting Enchantment

import org.bg52.curiospaper.event.CuriosMobDropEvent;
import org.bukkit.entity.Player;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;

public class LootingBoost implements Listener {

    @EventHandler
    public void onMobDrop(CuriosMobDropEvent event) {
        // Check if the killer has the looting enchantment
        if (event.getEntity().getKiller() != null) {
            Player killer = event.getEntity().getKiller();
            int lootingLevel = killer.getInventory()
                .getItemInMainHand().getEnchantmentLevel(Enchantment.LOOTING);

            if (lootingLevel > 0) {
                ItemStack item = event.getItem();
                // Each looting level adds 1 extra item (up to max 5)
                item.setAmount(Math.min(5, item.getAmount() + lootingLevel));
                event.setItem(item);
            }
        }
    }
}

Example: Cancelling Drops in Certain Regions

import org.bg52.curiospaper.event.CuriosMobDropEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class RegionDropRestriction implements Listener {

    @EventHandler
    public void onMobDrop(CuriosMobDropEvent event) {
        // Prevent custom drops in the spawn world
        if (event.getEntity().getWorld().getName().equals("world_spawn")) {
            event.setCancelled(true);
        }
    }
}

CuriosMobDropEvent Properties

Method Return Description
getEntity() LivingEntity The mob that is dropping the item
getCustomItemId() String The internal ID of the custom item being dropped
getItem() ItemStack The item being dropped
setItem(ItemStack) void Replace the item to be dropped
isCancelled() boolean Whether the drop is cancelled
setCancelled(boolean) void Cancel the drop (item will not appear)

CuriosRecipeTransferEvent

Fired when a crafting recipe produces a custom CuriosPaper item, allowing you to modify the result or transfer custom data.

Example: Adding Crafter Attribution

import org.bg52.curiospaper.event.CuriosRecipeTransferEvent;
import org.bukkit.ChatColor;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;

import java.util.ArrayList;
import java.util.List;

public class CraftingAttributionListener implements Listener {

    @EventHandler
    public void onRecipeTransfer(CuriosRecipeTransferEvent event) {
        ItemStack result = event.getResult();
        if (result == null || !result.hasItemMeta()) return;

        // Add a "Crafted by" lore line to all custom-crafted accessories
        ItemMeta meta = result.getItemMeta();
        List<String> lore = meta.getLore();
        if (lore == null) lore = new ArrayList<>();
        lore.add("");
        lore.add(ChatColor.DARK_GRAY + "✦ Hand-crafted accessory");
        meta.setLore(lore);
        result.setItemMeta(meta);
    }
}

CuriosRecipeTransferEvent Properties

Method Return Description
getInventory() Inventory The crafting inventory
getResult() ItemStack The crafted result item
getSource() ItemStack The source ingredient item
isCancelled() boolean Whether the transfer is cancelled
setCancelled(boolean) void Cancel the transfer


CuriosCraftEvent

Fired when a custom CuriosPaper item is crafted, smelted, smith-transformed, or repaired. This event is fired after any data transfer has occurred and allows for final modification of the result item.

Example: Tracking Crafted Items

import org.bg52.curiospaper.event.CuriosCraftEvent;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class CraftTracker implements Listener {

    @EventHandler
    public void onCuriosCraft(CuriosCraftEvent event) {
        String itemId = event.getItemId();
        event.getInventory().getViewers().forEach(player -> 
            player.sendMessage("§aYou just created a: " + itemId));
    }
}

CuriosCraftEvent Properties

Method Return Description
getInventory() Inventory The inventory where the craft is occurring
getItemId() String The internal ID of the custom item being created
getResult() ItemStack The result item
setResult(ItemStack) void Replace the result item
isCancelled() boolean Whether the event is cancelled
setCancelled(boolean) void Cancel the craft

CuriosModelEquipEvent

Fired when a curios item's 3D model is about to be equipped or displayed on a player. This event allows other plugins to modify the model item, material, custom model data, and item model component on the fly.

Example: Dynamically Changing Model Materials

import org.bg52.curiospaper.event.CuriosModelEquipEvent;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;

public class ModelMaterialChanger implements Listener {

    @EventHandler
    public void onModelEquip(CuriosModelEquipEvent event) {
        // Change all models to gold material for a specific player
        if (event.getPlayer().getName().equals("Midas")) {
            event.setModelMaterial(Material.GOLD_BLOCK);
        }
    }
}

CuriosModelEquipEvent Properties

Method Return Description
getPlayer() Player The player for whom the model is being equipped
getCuriosityStack() ItemStack The curios item stack that triggered the 3D model
getSlotType() String The type of the curios slot (e.g., "ring", "back")
getSlotIndex() int The index of the curios slot
getModelMaterial() Material The material that will be used for the model helmet
setModelMaterial(Material) void Set the material for the model helmet
getCustomModelData() Integer The custom model data that will be applied
setCustomModelData(Integer) void Set the custom model data
getItemModel() String The item model string (for 1.21.4+)
setItemModel(String) void Set the item model string

CuriosMobModelEquipEvent

Fired when a mob is about to equip a 3D model. Similar to CuriosModelEquipEvent, but for entities other than players.

Example: Randomizing Mob Accessory Models

import org.bg52.curiospaper.event.CuriosMobModelEquipEvent;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import java.util.Random;

public class MobModelRandomizer implements Listener {
    private final Random random = new Random();

    @EventHandler
    public void onMobModelEquip(CuriosMobModelEquipEvent event) {
        if (random.nextBoolean()) {
            event.setCustomModelData(1001); // Use a variant model
        }
    }
}

CuriosMobModelEquipEvent Properties

Method Return Description
getEntity() LivingEntity The mob equipping the model
getItemId() String The internal ID of the curios item
getModelMaterial() Material The material that will be used for the model helmet
setModelMaterial(Material) void Set the material for the model helmet
getCustomModelData() Integer The custom model data that will be applied
setCustomModelData(Integer) void Set the custom model data
getItemModel() String The item model string (for 1.21.4+)
setItemModel(String) void Set the item model string

Event Summary

Event When It Fires Cancellable Can Modify Item
AccessoryEquipEvent Player equips/unequips/swaps an accessory
CuriosLootGenerateEvent Custom item generated in a loot container
CuriosMobDropEvent Custom item dropped by a killed mob
CuriosRecipeTransferEvent Custom item crafted via a recipe (data transfer)
CuriosCraftEvent Custom item crafted/smelted/repaired (final)
CuriosModelEquipEvent 3D model about to be displayed on player
CuriosMobModelEquipEvent 3D model about to be displayed on mob

Registering Listeners

import org.bukkit.plugin.java.JavaPlugin;

public class MyPlugin extends JavaPlugin {

    @Override
    public void onEnable() {
        // Register all your CuriosPaper event listeners
        getServer().getPluginManager().registerEvents(new AccessoryLogger(), this);
        getServer().getPluginManager().registerEvents(new LootWorldRestriction(), this);
        getServer().getPluginManager().registerEvents(new MobDropLogger(), this);
        getServer().getPluginManager().registerEvents(new CraftingAttributionListener(), this);
        getServer().getPluginManager().registerEvents(new CraftTracker(), this);
        getServer().getPluginManager().registerEvents(new ModelMaterialChanger(), this);
    }
}