!Added consumable application events

This commit is contained in:
Indyuce 2020-08-12 00:07:57 +02:00
parent 940d898980
commit 2eaa8713b5
15 changed files with 430 additions and 74 deletions

View File

@ -104,9 +104,11 @@ public class ItemTier {
}
/**
* @return Reads a random item in the deconstruction drop table
* @return Reads the deconstruction drop table. This may return a list
* containing multiple items and they should all be added to the
* player's inventory
*/
public List<ItemStack> generateDeconstructedItem(PlayerData player) {
public List<ItemStack> getDeconstructedLoot(PlayerData player) {
return hasDropTable() ? deconstruct.read(player, false) : new ArrayList<>();
}

View File

@ -12,6 +12,7 @@ public abstract class PlayerDataEvent extends PlayerEvent implements Cancellable
public PlayerDataEvent(PlayerData playerData) {
super(playerData.getPlayer());
this.playerData = playerData;
}

View File

@ -2,7 +2,6 @@ package net.Indyuce.mmoitems.api.event.blocks;
import java.util.List;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
@ -10,12 +9,10 @@ import net.Indyuce.mmoitems.api.block.CustomBlock;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.player.PlayerData;
public class CustomBlockDropEvent extends PlayerDataEvent implements Cancellable {
public class CustomBlockDropEvent extends PlayerDataEvent {
private final CustomBlock block;
private final List<ItemStack> drops;
private boolean cancelled;
private static final HandlerList handlers = new HandlerList();
public CustomBlockDropEvent(PlayerData playerData, CustomBlock block, List<ItemStack> drops) {
@ -33,16 +30,6 @@ public class CustomBlockDropEvent extends PlayerDataEvent implements Cancellable
return drops;
}
@Override
public boolean isCancelled() {
return cancelled;
}
@Override
public void setCancelled(boolean value) {
cancelled = value;
}
@Override
public HandlerList getHandlers() {
return handlers;

View File

@ -1,11 +1,12 @@
package net.Indyuce.mmoitems.api.event;
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
public class GemStoneAppliedEvent extends PlayerDataEvent {
public class ApplyGemStoneEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem gemStone, targetItem;
@ -20,7 +21,7 @@ public class GemStoneAppliedEvent extends PlayerDataEvent {
* @param target
* Item on which the gem is being applied
*/
public GemStoneAppliedEvent(PlayerData playerData, MMOItem gemStone, MMOItem targetItem) {
public ApplyGemStoneEvent(PlayerData playerData, MMOItem gemStone, MMOItem targetItem) {
super(playerData);
this.gemStone = gemStone;

View File

@ -0,0 +1,48 @@
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.mmogroup.mmolib.api.item.NBTItem;
public class ApplySoulboundEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable;
private final NBTItem target;
/**
* Called when a player tries to apply soulbound onto an item
*
* @param playerData
* Player soulbinding the item
* @param consumable
* Consumable used to bind the item
* @param target
* Item being soulbound
*/
public ApplySoulboundEvent(PlayerData playerData, MMOItem consumable, NBTItem target) {
super(playerData);
this.consumable = consumable;
this.target = target;
}
public MMOItem getConsumable() {
return consumable;
}
public NBTItem getTargetItem() {
return target;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,48 @@
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.mmogroup.mmolib.api.item.NBTItem;
public class BreakSoulboundEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable;
private final NBTItem target;
/**
* Called when a player tries to break an item soulbound
*
* @param playerData
* Player breaking the soulbound
* @param consumable
* Consumable used to break the soulbound
* @param target
* Item with soulbound
*/
public BreakSoulboundEvent(PlayerData playerData, MMOItem consumable, NBTItem target) {
super(playerData);
this.consumable = consumable;
this.target = target;
}
public MMOItem getConsumable() {
return consumable;
}
public NBTItem getTargetItem() {
return target;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,60 @@
package net.Indyuce.mmoitems.api.event.item;
import java.util.List;
import org.bukkit.event.HandlerList;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.mmogroup.mmolib.api.item.NBTItem;
public class DeconstructItemEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable;
private final NBTItem deconstructed;
private final List<ItemStack> loot;
/**
* Called when a player deconstructs an item using a consumable
*
* @param playerData
* Player deconstructing the item
* @param consumable
* Consumable used to deconstruct the item
* @param unidentified
* Item being deconstructed
* @param loot
* Items which will be given to the player if the item is
* successfully deconstructed
*/
public DeconstructItemEvent(PlayerData playerData, MMOItem consumable, NBTItem deconstructed, List<ItemStack> loot) {
super(playerData);
this.consumable = consumable;
this.deconstructed = deconstructed;
this.loot = loot;
}
public MMOItem getConsumable() {
return consumable;
}
public NBTItem getDeconstructedItem() {
return deconstructed;
}
public List<ItemStack> getLoot() {
return loot;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,48 @@
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.mmogroup.mmolib.api.item.NBTItem;
public class IdentifyItemEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable;
private final NBTItem unidentified;
/**
* Called when a player tries to identify an item using a consumable
*
* @param playerData
* Player identifying the item
* @param consumable
* Consumable used to identify the item
* @param unidentified
* Item being identified
*/
public IdentifyItemEvent(PlayerData playerData, MMOItem consumable, NBTItem unidentified) {
super(playerData);
this.consumable = consumable;
this.unidentified = unidentified;
}
public MMOItem getConsumable() {
return consumable;
}
public NBTItem getUnidentifiedItem() {
return unidentified;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -1,42 +1,28 @@
package net.Indyuce.mmoitems.api.event;
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.entity.Player;
import org.bukkit.event.Cancellable;
import org.bukkit.event.HandlerList;
import org.bukkit.event.player.PlayerEvent;
import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.player.PlayerData;
public class ItemEquipEvent extends PlayerEvent implements Cancellable {
public class ItemEquipEvent extends PlayerDataEvent implements Cancellable {
private static final HandlerList handlers = new HandlerList();
private boolean cancelled = false;
private PlayerData playerData;
private ItemStack item;
private final ItemStack item;
public ItemEquipEvent(Player player, ItemStack item) {
super(player);
super(PlayerData.get(player));
this.item = item;
this.playerData = PlayerData.get(player);
}
public ItemStack getItem() {
return item;
}
public void setCancelled(boolean bool) {
cancelled = bool;
}
public PlayerData getPlayerData() {
return playerData;
}
public boolean isCancelled() {
return cancelled;
}
public HandlerList getHandlers() {
return handlers;
}

View File

@ -0,0 +1,61 @@
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.mmogroup.mmolib.api.item.NBTItem;
public class RepairItemEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable;
private final NBTItem target;
private int repaired;
/**
* Called when a player repairs an item using a consumable
*
* @param playerData
* Player repairing the item
* @param consumable
* Consumable used to repair the item
* @param target
* Item being repaired
* @param repaired
* Amount of durability being repaired
*/
public RepairItemEvent(PlayerData playerData, MMOItem consumable, NBTItem target, int repaired) {
super(playerData);
this.consumable = consumable;
this.target = target;
this.repaired = repaired;
}
public MMOItem getConsumable() {
return consumable;
}
public NBTItem getTargetItem() {
return target;
}
public int getRepaired() {
return repaired;
}
public void setRepaired(int repaired) {
this.repaired = repaired;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -0,0 +1,62 @@
package net.Indyuce.mmoitems.api.event.item;
import org.bukkit.event.HandlerList;
import net.Indyuce.mmoitems.api.event.PlayerDataEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.player.PlayerData;
import net.Indyuce.mmoitems.stat.data.UpgradeData;
public class UpgradeItemEvent extends PlayerDataEvent {
private static final HandlerList handlers = new HandlerList();
private final MMOItem consumable, target;
private final UpgradeData consumableData, targetData;
/**
* Called when a player upgrades an item using a consumable
*
* @param playerData
* Player upgrading the item
* @param consumable
* Consumable used to upgrade the item
* @param target
* Item being upgraded
* @param consumableData
* Upgrade info about the consumable
* @param targetData
* Upgrade info about the target item
*/
public UpgradeItemEvent(PlayerData playerData, MMOItem consumable, MMOItem target, UpgradeData consumableData, UpgradeData targetData) {
super(playerData);
this.consumable = consumable;
this.target = target;
this.consumableData = consumableData;
this.targetData = targetData;
}
public MMOItem getConsumable() {
return consumable;
}
public MMOItem getTargetItem() {
return target;
}
public UpgradeData getConsumableData() {
return consumableData;
}
public UpgradeData getTargetData() {
return targetData;
}
public HandlerList getHandlers() {
return handlers;
}
public static HandlerList getHandlerList() {
return handlers;
}
}

View File

@ -2,6 +2,7 @@ package net.Indyuce.mmoitems.api.interaction;
import java.util.List;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.Sound;
@ -14,6 +15,12 @@ import net.Indyuce.mmoitems.MMOItems;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.ItemTier;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.event.item.ApplySoulboundEvent;
import net.Indyuce.mmoitems.api.event.item.BreakSoulboundEvent;
import net.Indyuce.mmoitems.api.event.item.DeconstructItemEvent;
import net.Indyuce.mmoitems.api.event.item.IdentifyItemEvent;
import net.Indyuce.mmoitems.api.event.item.RepairItemEvent;
import net.Indyuce.mmoitems.api.event.item.UpgradeItemEvent;
import net.Indyuce.mmoitems.api.interaction.util.DurabilityItem;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
@ -40,22 +47,31 @@ public class Consumable extends UseItem {
return MMOItems.plugin.getFlags().isFlagAllowed(player, CustomFlag.MI_CONSUMABLES) && playerData.getRPG().canUse(getNBTItem(), true);
}
/*
* this boolean is used to check if the consumable has applied at least once
* of its item options. if so, the consumable should be consumed
/**
* @param event
* The click event
* @param target
* The item on which the consumable is being applied
* @return If the consumable has applied at least once of its item options
* ie if it should be consumed
*/
public boolean useOnItem(InventoryClickEvent event, NBTItem target) {
if (event.getClickedInventory() != event.getWhoClicked().getInventory())
return false;
/*
* unidentified items do not have any type, so you must check if the
* Unidentified items do not have any type, so you must check if the
* item has a type first.
*/
Type targetType = target.getType();
if (targetType == null) {
String unidentifiedItemTag = target.getString("MMOITEMS_UNIDENTIFIED_ITEM");
if (getNBTItem().getBoolean("MMOITEMS_CAN_IDENTIFY") && !unidentifiedItemTag.equals("")) {
if (getNBTItem().getBoolean("MMOITEMS_CAN_IDENTIFY") && target.hasTag("MMOITEMS_UNIDENTIFIED_ITEM")) {
IdentifyItemEvent called = new IdentifyItemEvent(playerData, mmoitem, target);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
event.setCurrentItem(new IdentifiedItem(target).identify());
Message.SUCCESSFULLY_IDENTIFIED.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(event.getCurrentItem())).send(player);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2);
@ -65,27 +81,33 @@ public class Consumable extends UseItem {
}
/*
* deconstructing an item. usually consumables do not deconstruct and
* repair items at the same time so there's no pb with that
* Deconstructing an item, usually consumables do not deconstruct and
* repair items at the same time so there should not be any problem with
* that
*/
String itemTierTag = target.getString("MMOITEMS_TIER");
if (getNBTItem().getBoolean("MMOITEMS_CAN_DECONSTRUCT") && !itemTierTag.equals("")) {
if (!itemTierTag.equals("") && getNBTItem().getBoolean("MMOITEMS_CAN_DECONSTRUCT")) {
ItemTier tier = MMOItems.plugin.getTiers().get(itemTierTag);
List<ItemStack> deconstructed = tier.generateDeconstructedItem(playerData);
if (!deconstructed.isEmpty()) {
List<ItemStack> loot = tier.getDeconstructedLoot(playerData);
if (!loot.isEmpty()) {
DeconstructItemEvent called = new DeconstructItemEvent(playerData, mmoitem, target, loot);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
Message.SUCCESSFULLY_DECONSTRUCTED.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(event.getCurrentItem())).send(player);
event.getCurrentItem().setAmount(event.getCurrentItem().getAmount() - 1);
for (ItemStack drop : player.getInventory().addItem(deconstructed.toArray(new ItemStack[deconstructed.size()])).values())
for (ItemStack drop : player.getInventory().addItem(loot.toArray(new ItemStack[loot.size()])).values())
player.getWorld().dropItem(player.getLocation(), drop);
player.playSound(player.getLocation(), Sound.ENTITY_PLAYER_LEVELUP, 1, 2);
return true;
}
return true;
}
/*
* upgrading an item. it is better not to repair an item while upgrading
* it.
* Upgrading an item, it is sbetter not to repair an item while
* upgrading it.
*/
if (getNBTItem().hasTag("MMOITEMS_UPGRADE") && target.hasTag("MMOITEMS_UPGRADE")) {
if (target.getItem().getAmount() > 1) {
@ -109,11 +131,16 @@ public class Consumable extends UseItem {
return false;
}
UpgradeItemEvent called = new UpgradeItemEvent(playerData, mmoitem, targetMMO, consumableSharpening, targetSharpening);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
targetSharpening.upgrade(targetMMO);
NBTItem result = targetMMO.newBuilder().buildNBT();
/*
* safe check, if the specs the item has after ugprade are too high
* Safe check, if the specs the item has after ugprade are too high
* for the player, then cancel upgrading because the player would
* not be able to use it.
*/
@ -157,6 +184,12 @@ public class Consumable extends UseItem {
}
if (random.nextDouble() < soulbindingChance / 100) {
ApplySoulboundEvent called = new ApplySoulboundEvent(playerData, mmoitem, target);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
int soulboundLevel = (int) Math.max(1, getNBTItem().getStat(ItemStat.SOULBOUND_LEVEL));
(targetMMO = new LiveMMOItem(target)).setData(ItemStat.SOULBOUND,
ItemStat.SOULBOUND.newSoulboundData(player.getUniqueId(), player.getName(), soulboundLevel));
@ -174,7 +207,7 @@ public class Consumable extends UseItem {
}
/*
* breaking the item's current soulbound. it has a random factor
* Breaking the item's current soulbound. It has a random factor
* determined by the soulbound break chance, and the consumable needs to
* have at least the soulbound's level to be able to break the item
* soulbound.
@ -197,6 +230,12 @@ public class Consumable extends UseItem {
}
if (random.nextDouble() < soulboundBreakChance / 100) {
BreakSoulboundEvent called = new BreakSoulboundEvent(playerData, mmoitem, target);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
(targetMMO = new LiveMMOItem(target)).removeData(ItemStat.SOULBOUND);
target.getItem().setItemMeta(targetMMO.newBuilder().build().getItemMeta());
Message.SUCCESSFULLY_BREAK_BIND.format(ChatColor.YELLOW, "#level#", MMOUtils.intToRoman(soulbound.getLevel())).send(player,
@ -211,7 +250,7 @@ public class Consumable extends UseItem {
}
/*
* item repairing, does not apply if there's no repair power or if the
* Item repairing, does not apply if there's no repair power or if the
* item still has all its uses left
*/
int repairPower = (int) getNBTItem().getStat(ItemStat.REPAIR);
@ -219,10 +258,17 @@ public class Consumable extends UseItem {
// custom durability
if (target.hasTag("MMOITEMS_DURABILITY")) {
RepairItemEvent called = new RepairItemEvent(playerData, mmoitem, target, repairPower);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
DurabilityItem durItem = new DurabilityItem(player, target);
if (durItem.getDurability() < durItem.getMaxDurability()) {
target.getItem().setItemMeta(durItem.addDurability(repairPower).toItem().getItemMeta());
Message.REPAIRED_ITEM.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(target.getItem()), "#amount#", "" + repairPower)
target.getItem().setItemMeta(durItem.addDurability(called.getRepaired()).toItem().getItemMeta());
Message.REPAIRED_ITEM
.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(target.getItem()), "#amount#", "" + called.getRepaired())
.send(player);
}
return true;
@ -231,8 +277,15 @@ public class Consumable extends UseItem {
// vanilla durability
if (!target.getBoolean("Unbreakable")
&& MMOLib.plugin.getVersion().getWrapper().isDamaged(target.getItem(), target.getItem().getItemMeta())) {
MMOLib.plugin.getVersion().getWrapper().repair(target.getItem(), repairPower);
Message.REPAIRED_ITEM.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(target.getItem()), "#amount#", "" + repairPower)
RepairItemEvent called = new RepairItemEvent(playerData, mmoitem, target, repairPower);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return false;
MMOLib.plugin.getVersion().getWrapper().repair(target.getItem(), called.getRepaired());
Message.REPAIRED_ITEM
.format(ChatColor.YELLOW, "#item#", MMOUtils.getDisplayName(target.getItem()), "#amount#", "" + called.getRepaired())
.send(player);
return true;
}
@ -241,11 +294,10 @@ public class Consumable extends UseItem {
return false;
}
/*
* when the method returns true, one item will be taken away from the player
* inventory
/**
* @return If the item should be consumed
*/
public boolean useWithoutItem(boolean consume) {
public boolean useWithoutItem() {
NBTItem nbtItem = getNBTItem();
if (nbtItem.getBoolean("MMOITEMS_INEDIBLE"))
@ -325,7 +377,7 @@ public class Consumable extends UseItem {
return false;
}
return consume && !nbtItem.getBoolean("MMOITEMS_DISABLE_RIGHT_CLICK_CONSUME");
return !nbtItem.getBoolean("MMOITEMS_DISABLE_RIGHT_CLICK_CONSUME");
}
public boolean hasVanillaEating() {

View File

@ -8,7 +8,7 @@ import org.bukkit.inventory.ItemStack;
import net.Indyuce.mmoitems.MMOUtils;
import net.Indyuce.mmoitems.api.Type;
import net.Indyuce.mmoitems.api.event.GemStoneAppliedEvent;
import net.Indyuce.mmoitems.api.event.item.ApplyGemStoneEvent;
import net.Indyuce.mmoitems.api.item.mmoitem.LiveMMOItem;
import net.Indyuce.mmoitems.api.item.mmoitem.MMOItem;
import net.Indyuce.mmoitems.api.util.message.Message;
@ -61,7 +61,7 @@ public class GemStone extends UseItem {
return new ApplyResult(ResultType.FAILURE);
}
GemStoneAppliedEvent called = new GemStoneAppliedEvent(playerData, mmoitem, targetMMO);
ApplyGemStoneEvent called = new ApplyGemStoneEvent(playerData, mmoitem, targetMMO);
Bukkit.getPluginManager().callEvent(called);
if (called.isCancelled())
return new ApplyResult(ResultType.NONE);

View File

@ -91,7 +91,7 @@ public class ItemUse implements Listener {
if (useItem instanceof Consumable) {
event.setCancelled(true);
if (((Consumable) useItem).useWithoutItem(true))
if (((Consumable) useItem).useWithoutItem())
event.getItem().setAmount(event.getItem().getAmount() - 1);
}
}
@ -320,7 +320,7 @@ public class ItemUse implements Listener {
return;
}
if (!((Consumable) useItem).useWithoutItem(true)) {
if (!((Consumable) useItem).useWithoutItem()) {
event.setCancelled(true);
return;
}

View File

@ -56,7 +56,7 @@ public class UpgradeData implements StatData, RandomStatData {
}
public boolean canLevelUp() {
return !hasMaxUpgrades() || level < max;
return max == 0 || level < max;
}
public boolean destroysOnFail() {
@ -72,11 +72,11 @@ public class UpgradeData implements StatData, RandomStatData {
}
public void upgrade(MMOItem mmoitem) {
if(!MMOItems.plugin.getUpgrades().hasTemplate(template)) {
if (!MMOItems.plugin.getUpgrades().hasTemplate(template)) {
MMOItems.plugin.getLogger().warning("Couldn't find upgrade template '" + template + "'. Does it exist?");
return;
}
// change display name
String suffix = MMOLib.plugin.parseColors(MMOItems.plugin.getConfig().getString("item-upgrading.name-suffix"));
if (MMOItems.plugin.getConfig().getBoolean("item-upgrading.display-in-name"))