Use builder for creating armored elytras

- All armored elytra creation/modification is now handled by the ArmoredElytraBuilder class.
- When creating a new armored elytra, the existing NBT data is now no longer removed.
This commit is contained in:
Pim van der Loos 2021-11-03 17:56:53 +01:00
parent daafa5572c
commit 4c8cf55021
No known key found for this signature in database
GPG Key ID: C16F020ADAE6D5A8
14 changed files with 645 additions and 308 deletions

View File

@ -9,11 +9,11 @@ import nl.pim16aap2.armoredElytra.handlers.LoginHandler;
import nl.pim16aap2.armoredElytra.handlers.NetheriteUpgradeListener;
import nl.pim16aap2.armoredElytra.handlers.SmithingTableCraftHandler;
import nl.pim16aap2.armoredElytra.handlers.Uninstaller;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ArmorTierName;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.MinecraftVersion;
import nl.pim16aap2.armoredElytra.util.UpdateManager;
import nl.pim16aap2.armoredElytra.util.messages.Message;
@ -22,7 +22,7 @@ import org.bstats.bukkit.Metrics;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.enchantments.Enchantment;
import org.bukkit.entity.Player;
import org.bukkit.entity.HumanEntity;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
@ -183,13 +183,13 @@ public class ArmoredElytra extends JavaPlugin implements Listener
messages.getString(Message.TIER_SHORT_NETHERITE)));
}
public boolean playerHasCraftPerm(Player player, ArmorTier armorTier)
public boolean playerHasCraftPerm(HumanEntity player, ArmorTier armorTier)
{
return getConfigLoader().bypassCraftPerm() ||
player.hasPermission("armoredelytra.craft." + ArmorTier.getName(armorTier));
}
public boolean playerHasWearPerm(Player player, ArmorTier armorTier)
public boolean playerHasWearPerm(HumanEntity player, ArmorTier armorTier)
{
return getConfigLoader().bypassWearPerm() ||
player.hasPermission("armoredelytra.wear." + ArmorTier.getName(armorTier));
@ -202,13 +202,13 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
// Send a message to a player in a specific color.
public void messagePlayer(Player player, ChatColor color, String str)
public void messagePlayer(HumanEntity player, ChatColor color, String str)
{
player.sendMessage(color + str);
}
// Send a message to a player.
public void messagePlayer(Player player, String str)
public void messagePlayer(HumanEntity player, String str)
{
messagePlayer(player, ChatColor.WHITE, str);
}
@ -222,7 +222,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
// Send the usageDeniedMessage message to the player.
public void usageDeniedMessage(Player player, ArmorTier armorTier)
public void usageDeniedMessage(HumanEntity player, ArmorTier armorTier)
{
final String message = getMessageWithTierNames(Message.MESSAGES_USAGEDENIED, armorTier);
if (!message.equals("NONE"))
@ -230,14 +230,14 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
// Send the elytraReceivedMessage message to the player.
public void elytraReceivedMessage(Player player, ArmorTier armorTier)
public void elytraReceivedMessage(HumanEntity player, ArmorTier armorTier)
{
final String message = getMessageWithTierNames(Message.MESSAGES_ELYTRARECEIVED, armorTier);
if (!message.equals("NONE"))
messagePlayer(player, ChatColor.GREEN, message);
}
public void sendNoGivePermissionMessage(Player player, ArmorTier armorTier)
public void sendNoGivePermissionMessage(HumanEntity player, ArmorTier armorTier)
{
final String message = getMessageWithTierNames(Message.MESSAGES_NOGIVEPERMISSION, armorTier);
messagePlayer(player, ChatColor.RED, message);
@ -263,7 +263,7 @@ public class ArmoredElytra extends JavaPlugin implements Listener
}
// Give the provided player the provided item.
public void giveArmoredElytraToPlayer(Player player, ItemStack item)
public void giveArmoredElytraToPlayer(HumanEntity player, ItemStack item)
{
if (item != null)
player.getInventory().addItem(item);

View File

@ -1,16 +1,14 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.Action;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.Util;
import nl.pim16aap2.armoredElytra.util.XMaterial;
import org.bukkit.ChatColor;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
@ -23,6 +21,7 @@ import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.ItemMeta;
import javax.annotation.Nullable;
import java.util.logging.Level;
public class AnvilHandler extends ArmoredElytraHandler implements Listener
@ -49,7 +48,7 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
// Ignoring:
// - Elytra (not armored) + !chestplate -> None
// - * + * -> None
private Action isValidInput(ItemStack itemOne, ItemStack itemTwo)
private Action isValidInput(ArmorTier itemOneTier, ItemStack itemOne, ItemStack itemTwo)
{
if (itemOne == null || itemTwo == null)
return Action.NONE;
@ -57,32 +56,30 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
if (itemOne.getType() != Material.ELYTRA)
return Action.NONE;
Material matTwo = itemTwo.getType();
final Material matTwo = itemTwo.getType();
// If the elytra is to be combined with chest armor...
if (Util.isChestPlate(matTwo))
return creationEnabled ? Action.CREATE : Action.NONE;
ArmorTier tier = nbtEditor.getArmorTier(itemOne);
if (tier != ArmorTier.NONE)
if (itemOneTier != ArmorTier.NONE)
{
// If the armored elytra is to be enchanted using an enchanted book...
if (matTwo == Material.ENCHANTED_BOOK)
return config.allowAddingEnchantments() ? Action.ENCHANT : Action.BLOCK;
// If the armored elytra is to be repaired using its repair item...
if (ArmorTier.getRepairItem(tier) == matTwo)
return durabilityManager.getRealDurability(itemOne, tier) == 0 ? Action.BLOCK : Action.REPAIR;
if (ArmorTier.getRepairItem(itemOneTier) == matTwo)
return durabilityManager.getRealDurability(itemOne, itemOneTier) == 0 ? Action.BLOCK : Action.REPAIR;
// If the armored elytra is to be combined with another armored elytra of the same tier...
if (nbtEditor.getArmorTier(itemTwo) == tier)
if (nbtEditor.getArmorTier(itemTwo) == itemOneTier)
return creationEnabled ? Action.COMBINE : Action.NONE;
// If the armored elytra is not of the leather tier, but itemTwo is leather,
// Pick the block action, as that would repair the elytra by default (vanilla).
// Also block Armored Elytra + Elytra and Elytra + Membrane
if (tier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA ||
if (itemOneTier != ArmorTier.LEATHER && matTwo == Material.LEATHER || matTwo == Material.ELYTRA ||
matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial()))
return Action.BLOCK;
}
@ -93,10 +90,11 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
@EventHandler(priority = EventPriority.LOWEST)
private void onAnvilInventoryOpen(PrepareAnvilEvent event)
{
Player player = (Player) event.getView().getPlayer();
if (!(event.getView().getPlayer() instanceof Player player))
return;
ItemStack itemA = event.getInventory().getItem(0);
ItemStack itemB = event.getInventory().getItem(1);
ItemStack result;
if (itemA != null && itemB != null)
// If itemB is the (armored) elytra, while itemA isn't, switch itemA and itemB.
@ -107,81 +105,57 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
itemB = tmp;
}
// Check if there are items in both input slots.
if (itemA != null && itemB != null)
{
final Action action = isValidInput(itemA, itemB);
ArmorTier newTier = ArmorTier.NONE;
final ArmorTier curTier = nbtEditor.getArmorTier(itemA);
int newDurability = 0;
final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemA, plugin);
switch (action)
{
case REPAIR:
newTier = curTier;
newDurability = durabilityManager.getRepairedDurability(itemA, itemB.getAmount(), curTier);
break;
case COMBINE:
newTier = curTier;
newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier);
enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin));
break;
case CREATE:
newTier = Util.armorToTier(itemB.getType());
newDurability = durabilityManager.getCombinedDurability(itemA, itemB, curTier, newTier);
enchantments.merge(EnchantmentContainer.getEnchantments(itemB, plugin));
break;
case ENCHANT:
newTier = curTier;
newDurability = durabilityManager.getRealDurability(itemA, newTier);
// If there aren't any illegal enchantments on the book, continue as normal.
// Otherwise... Block.
final EnchantmentContainer enchantmentsB = EnchantmentContainer.getEnchantments(itemB, plugin);
if (enchantmentsB.getEnchantmentCount() > 0)
{
enchantments.merge(enchantmentsB);
break;
}
//$FALL-THROUGH$
case BLOCK:
event.setResult(null);
player.updateInventory();
//$FALL-THROUGH$
case NONE:
return;
}
if (plugin.playerHasCraftPerm(player, newTier))
{
result = new ItemStack(Material.ELYTRA, 1);
enchantments.applyEnchantments(result);
durabilityManager.setDurability(result, newDurability, newTier);
final String name = getElytraResultName(itemA, action, newTier, event.getInventory().getRenameText());
final Color color = getItemColor(itemA, itemB);
result = nbtEditor.addArmorNBTTags(result, newTier, config.unbreakable(), name, color);
event.setResult(result);
return;
}
}
// If one of the input items is null and the other an armored elytra, remove the result.
// This prevents some naming issues.
if ((itemA == null ^ itemB == null) &&
nbtEditor.getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE)
event.setResult(null);
if (itemA == null || itemB == null)
return;
final ArmorTier currentArmorTier = nbtEditor.getArmorTier(itemA);
final Action action = isValidInput(currentArmorTier, itemA, itemB);
if (action == Action.NONE)
return;
final ArmorTier newArmorTier;
if (action == Action.CREATE)
newArmorTier = Util.armorToTier(itemB);
else if (action == Action.COMBINE)
newArmorTier = nbtEditor.getArmorTier(itemB);
else
newArmorTier = currentArmorTier;
final @Nullable String name = getElytraResultName(itemA, action, currentArmorTier, newArmorTier,
event.getInventory().getRenameText());
final @Nullable ItemStack result =
!plugin.playerHasCraftPerm(player, newArmorTier) ? null :
switch (action)
{
case REPAIR -> armoredElytraBuilder.repair(itemA, itemB, name);
case ENCHANT -> armoredElytraBuilder.enchant(itemA, itemB, name);
case COMBINE, CREATE -> armoredElytraBuilder.combine(itemA, itemB, newArmorTier, name);
case BLOCK -> null;
//noinspection ConstantConditions
case NONE -> itemA;
};
event.setResult(result);
player.updateInventory();
}
private String getElytraResultName(final ItemStack baseItem, final Action action,
final ArmorTier armorTier, final String renameText)
private @Nullable String getElytraResultName(final ItemStack baseItem, final Action action,
final ArmorTier currentArmorTier, final ArmorTier newArmorTier,
final String renameText)
{
final String tierName = plugin.getArmoredElytraName(armorTier);
if (renameText == null || !config.allowRenaming())
final String currentTierName = plugin.getArmoredElytraName(currentArmorTier);
final String tierName = plugin.getArmoredElytraName(newArmorTier);
if (renameText == null || !config.allowRenaming() ||
ChatColor.stripColor(currentTierName).equals(ChatColor.stripColor(renameText)))
return tierName;
final ItemMeta meta = baseItem.getItemMeta();
@ -201,11 +175,10 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
@EventHandler
public void onInventoryClick(InventoryClickEvent e)
{
if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player))
if (e.getRawSlot() != 2 || !(e.getWhoClicked() instanceof Player player))
return;
// Check if the event was a player who interacted with an anvil.
Player player = (Player) e.getWhoClicked();
if (e.getView().getType() != InventoryType.ANVIL)
return;
@ -226,17 +199,18 @@ public class AnvilHandler extends ArmoredElytraHandler implements Listener
return;
}
if (anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null &&
anvilInventory.getItem(2) != null && anvilInventory.getItem(2).getType() == Material.ELYTRA)
final @Nullable ItemStack item0 = anvilInventory.getItem(0);
final @Nullable ItemStack item1 = anvilInventory.getItem(1);
final @Nullable ItemStack item2 = anvilInventory.getItem(2);
if (item0 != null && item1 != null && item2 != null && item2.getType() == Material.ELYTRA)
{
ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2));
final ArmorTier armortier = nbtEditor.getArmorTier(anvilInventory.getItem(2));
// If there's an armored elytra in the final slot...
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier))
{
final ItemStack result = anvilInventory.getItem(2);
// Give the result to the player and clear the anvil's inventory.
if (!giveItemToPlayer(player, result, e.isShiftClick()))
if (!giveItemToPlayer(player, item2, e.isShiftClick()))
return;
// Clean the anvil's inventory after transferring the items.

View File

@ -1,15 +1,12 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import javax.annotation.CheckReturnValue;
@ -20,55 +17,30 @@ import javax.annotation.CheckReturnValue;
*/
abstract class ArmoredElytraHandler
{
private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor();
protected final ArmoredElytra plugin;
protected final boolean creationEnabled;
protected final ConfigLoader config;
protected final NBTEditor nbtEditor;
protected final DurabilityManager durabilityManager;
protected final ArmoredElytraBuilder armoredElytraBuilder;
protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
DurabilityManager durabilityManager, ConfigLoader config,
ArmoredElytraBuilder armoredElytraBuilder)
{
this.plugin = plugin;
this.creationEnabled = creationEnabled;
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
this.config = config;
this.armoredElytraBuilder = armoredElytraBuilder;
}
/**
* Gets the color of the item if the item has a color.
* <p>
* See {@link LeatherArmorMeta#getColor()}.
*
* @param itemA The first {@link ItemStack} to check.
* @param itemB The second {@link ItemStack} to check.
* @return The color of the item, if it has a color, otherwise null.
*/
protected Color getItemColor(final ItemStack itemA, final ItemStack itemB)
protected ArmoredElytraHandler(ArmoredElytra plugin, boolean creationEnabled, NBTEditor nbtEditor,
DurabilityManager durabilityManager, ConfigLoader config)
{
final Color colorA = getItemColor(itemA);
if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR))
return colorA;
final Color colorB = getItemColor(itemB);
return colorB != null ? colorB : colorA;
}
private Color getItemColor(final ItemStack itemStack)
{
if (itemStack == null)
return null;
if (itemStack.getType() == Material.ELYTRA)
return nbtEditor.getColorOfArmoredElytra(itemStack);
if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta))
return null;
return ((LeatherArmorMeta) itemStack.getItemMeta()).getColor();
this(plugin, creationEnabled, nbtEditor, durabilityManager, config,
new ArmoredElytraBuilder(nbtEditor, durabilityManager, config, plugin));
}
/**
@ -76,8 +48,8 @@ abstract class ArmoredElytraHandler
*
* @param player The player to give the item to.
* @param item The item to give.
* @param direct Whether or not to put it in the player's inventory. When set to false it will be put in their
* cursor instead.
* @param direct Whether to put it in the player's inventory. When set to false it will be put in their cursor
* instead.
* @return True if the item could be given to the player, otherwise false (e.g. when their inventory is full).
*/
@CheckReturnValue

View File

@ -1,13 +1,13 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.ArmoredElytraBuilder;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import org.bukkit.Bukkit;
import org.bukkit.ChatColor;
import org.bukkit.Material;
import org.bukkit.NamespacedKey;
import org.bukkit.command.Command;
import org.bukkit.command.CommandExecutor;
@ -23,15 +23,13 @@ import java.util.logging.Level;
public class CommandHandler implements CommandExecutor
{
private final ArmoredElytra plugin;
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
private static Field BY_KEY_FIELD;
private final ArmoredElytraBuilder armoredElytraBuilder;
public CommandHandler(ArmoredElytra plugin, NBTEditor nbtEditor, DurabilityManager durabilityManager)
{
this.plugin = plugin;
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
armoredElytraBuilder = new ArmoredElytraBuilder(nbtEditor, durabilityManager, plugin.getConfigLoader(), plugin);
}
@Override
@ -86,10 +84,7 @@ public class CommandHandler implements CommandExecutor
if (allowed)
{
plugin.elytraReceivedMessage(receiver, armorTier);
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
plugin.getConfigLoader().unbreakable());
durabilityManager.setDurability(newElytra, 0, armorTier);
plugin.giveArmoredElytraToPlayer(receiver, newElytra);
plugin.giveArmoredElytraToPlayer(receiver, armoredElytraBuilder.newArmoredElytra(armorTier));
}
else
plugin.sendNoGivePermissionMessage(player, armorTier);
@ -115,7 +110,6 @@ public class CommandHandler implements CommandExecutor
if (args.length == 2)
{
ItemStack newElytra;
final String tier = args[1];
player = Bukkit.getPlayer(args[0]);
if (player != null)
@ -125,11 +119,7 @@ public class CommandHandler implements CommandExecutor
return false;
plugin.elytraReceivedMessage(player, armorTier);
newElytra = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), armorTier,
plugin.getConfigLoader().unbreakable());
durabilityManager.setDurability(newElytra, 0, armorTier);
plugin.giveArmoredElytraToPlayer(player, newElytra);
plugin.giveArmoredElytraToPlayer(player, armoredElytraBuilder.newArmoredElytra(armorTier));
plugin.myLogger(Level.INFO, ("Giving an armored elytra of the " + ArmorTier.getArmor(armorTier) +
" armor tier to player " + player.getName()));
return true;

View File

@ -5,10 +5,10 @@ import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorEquipEvent;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorListener;
import nl.pim16aap2.armoredElytra.lib.armorequip.ArmorType;
import nl.pim16aap2.armoredElytra.lib.armorequip.DispenserArmorListener;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.Util;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import org.bukkit.Bukkit;
@ -63,9 +63,8 @@ public class EventHandlers implements Listener
@EventHandler(ignoreCancelled = true, priority = EventPriority.LOWEST)
public void onPlayerDamage(EntityDamageEvent e)
{
if (!(e.getEntity() instanceof Player))
if (!(e.getEntity() instanceof final Player p))
return;
final Player p = (Player) e.getEntity();
final ItemStack elytra = p.getInventory().getChestplate();
if (elytra == null)

View File

@ -1,8 +1,8 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Material;
import org.bukkit.event.EventHandler;

View File

@ -1,18 +1,19 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.PrepareSmithingEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.SmithingInventory;
import javax.annotation.Nullable;
public class NetheriteUpgradeListener extends SmithingTableListener
{
public NetheriteUpgradeListener(final ArmoredElytra plugin, NBTEditor nbtEditor,
@ -21,43 +22,47 @@ public class NetheriteUpgradeListener extends SmithingTableListener
super(plugin, false, nbtEditor, durabilityManager, config);
}
@Override @EventHandler(ignoreCancelled = true)
@EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event)
{
super.onSmithingTableUsage(event);
final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents();
final ItemStack itemStackA = contents[0];
final ItemStack itemStackB = contents[1];
if (!validInput(itemStackA, itemStackB))
return;
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), ArmorTier.NETHERITE))
return;
event.setResult(armoredElytraBuilder
.newBuilder()
.ofElytra(itemStackA)
.upgradeToTier(ArmorTier.NETHERITE)
.build());
}
@Override
protected ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB)
private boolean validInput(@Nullable ItemStack itemStackA, @Nullable ItemStack itemStackB)
{
if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA ||
plugin.getNbtEditor().getArmorTier(itemStackA) != ArmorTier.DIAMOND ||
itemStackB.getType() != Material.NETHERITE_INGOT)
return ArmorTier.NONE;
return false;
// For some reason, adding multiple netherite ingots causes the view to not update properly.
// The resulting armored elytra is hidden and the red cross indicates the combination is impossible.
// But if you click on where the output was supposed to be, it DOES work for some reason.
// It kinda works if you add a slight delay, but I don't really like that. Might revisit this later. CBA now.
if (itemStackA.getAmount() != 1 || itemStackB.getAmount() != 1)
return ArmorTier.NONE;
return ArmorTier.NETHERITE;
return itemStackA.getAmount() == 1 && itemStackB.getAmount() == 1;
}
@Override
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent event)
{
if (!isAESmithingTableEvent(event))
return;
// These casts may look unchecked, but it was checked by isSmithingTableEvent already.
SmithingInventory smithingInventory = (SmithingInventory) event.getInventory();
Player player = (Player) event.getWhoClicked();
if (!giveItemToPlayer(player, smithingInventory.getItem(2), event.isShiftClick()))
return;
smithingInventory.clear();
super.onInventoryClick(event);
}
}

View File

@ -1,14 +1,13 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Bukkit;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.PrepareSmithingEvent;
@ -26,15 +25,26 @@ public class SmithingTableCraftHandler extends SmithingTableListener
.registerEvents(new AnvilHandler(plugin, false, nbtEditor, durabilityManager, config), plugin);
}
@Override
@EventHandler(ignoreCancelled = true)
public void onSmithingTableUsage(final PrepareSmithingEvent event)
{
super.onSmithingTableUsage(event);
final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents();
final ItemStack itemStackA = contents[0];
final ItemStack itemStackB = contents[1];
final ArmorTier newArmorTier = getNewArmorTier(itemStackA, itemStackB);
if (newArmorTier == ArmorTier.NONE)
return;
if (!plugin.playerHasCraftPerm(event.getView().getPlayer(), newArmorTier))
return;
event.setResult(armoredElytraBuilder.combine(itemStackA, itemStackB, newArmorTier, null));
}
@Override
protected ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB)
protected ArmorTier getNewArmorTier(ItemStack itemStackA, ItemStack itemStackB)
{
if (itemStackA == null || itemStackB == null ||
itemStackA.getType() != Material.ELYTRA || !Util.isChestPlate(itemStackB))
@ -43,17 +53,10 @@ public class SmithingTableCraftHandler extends SmithingTableListener
return Util.armorToTier(itemStackB.getType());
}
@Override
@EventHandler(ignoreCancelled = true)
public void onInventoryClick(InventoryClickEvent e)
public void onInventoryClick(InventoryClickEvent event)
{
if (!isAESmithingTableEvent(e))
return;
final SmithingInventory smithingInventory = (SmithingInventory) e.getInventory();
final ItemStack result = smithingInventory.getItem(2);
// This cast may look unchecked, but it was checked by isSmithingTableEvent already.
if (!giveItemToPlayer((Player) e.getWhoClicked(), result, e.isShiftClick()))
return;
smithingInventory.clear();
super.onInventoryClick(event);
}
}

View File

@ -1,18 +1,15 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.nbtEditor.DurabilityManager;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.DurabilityManager;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.PrepareSmithingEvent;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.SmithingInventory;
@ -26,47 +23,19 @@ abstract class SmithingTableListener extends ArmoredElytraHandler implements Lis
super(plugin, creationEnabled, nbtEditor, durabilityManager, config);
}
public void onSmithingTableUsage(final PrepareSmithingEvent event)
protected void onInventoryClick(InventoryClickEvent event)
{
final SmithingInventory inventory = event.getInventory();
final ItemStack[] contents = inventory.getContents();
final ItemStack itemStackA = contents[0];
final ItemStack itemStackB = contents[1];
final ArmorTier newTier = getArmorTier(itemStackA, itemStackB);
if (newTier == ArmorTier.NONE)
if (!isAESmithingTableEvent(event))
return;
final SmithingInventory smithingInventory = (SmithingInventory) event.getInventory();
final ItemStack result = smithingInventory.getItem(2);
final Player player = (Player) event.getView().getPlayer();
if (plugin.playerHasCraftPerm(player, newTier))
{
final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(itemStackA, plugin);
enchantments.merge(EnchantmentContainer.getEnchantments(itemStackB, plugin));
final Color color = getItemColor(itemStackA, itemStackB);
final ItemStack result = nbtEditor.addArmorNBTTags(new ItemStack(Material.ELYTRA, 1), newTier,
plugin.getConfigLoader().unbreakable(), color);
durabilityManager.setCombinedDurability(result, itemStackA, itemStackB,
nbtEditor.getArmorTier(itemStackA), newTier);
enchantments.applyEnchantments(result);
event.setResult(result);
}
// This cast may look unchecked, but it was checked by isSmithingTableEvent already.
if (!giveItemToPlayer((Player) event.getWhoClicked(), result, event.isShiftClick()))
return;
smithingInventory.clear();
}
/**
* Checks if the provided input {@link ItemStack}s form a valid input pattern for a smithing table, and, if so,
* which tier it combines into.
*
* @param itemStackA The first {@link ItemStack}.
* @param itemStackB The second {@link ItemStack}.
* @return The {@link ArmorTier} as figured out from the input pattern. If the pattern is invalid, {@link
* ArmorTier#NONE} is returned.
*/
protected abstract ArmorTier getArmorTier(ItemStack itemStackA, ItemStack itemStackB);
/**
* Checks if an {@link InventoryClickEvent} is useful for this plugin. I.e., it is about a smithing inventory and
* there is an (armored) elytra involved somehow.

View File

@ -0,0 +1,469 @@
package nl.pim16aap2.armoredElytra.nbtEditor;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.EnchantmentContainer;
import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Bukkit;
import org.bukkit.Color;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;
import org.bukkit.inventory.meta.LeatherArmorMeta;
import javax.annotation.Nullable;
import java.util.List;
@SuppressWarnings({"unused", "UnusedReturnValue", "ClassCanBeRecord"})
public class ArmoredElytraBuilder
{
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
private final ConfigLoader config;
private final ArmoredElytra plugin;
public ArmoredElytraBuilder(NBTEditor nbtEditor, DurabilityManager durabilityManager,
ConfigLoader config, ArmoredElytra plugin)
{
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
this.config = config;
this.plugin = plugin;
}
/**
* Creates a new builder for an armored elytra.
*
* @return The first step of the new builder.
*/
public IStep0 newBuilder()
{
return new Builder(nbtEditor, durabilityManager, config, plugin);
}
/**
* Shortcut for repairing an armored elytra.
*
* @param armoredElytra The armored elytra to repair.
* @param repairItems The repair item(s) to use for repairing the armored elytra. It is assumed that they are of
* the correct type.
* @param name The new name of the output armored elytra. When this is null, {@link
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public @Nullable ItemStack repair(ItemStack armoredElytra, ItemStack repairItems, @Nullable String name)
{
return newBuilder().ofElytra(armoredElytra).repair(repairItems.getAmount()).withName(name).build();
}
/**
* Shortcut for enchanting an armored elytra.
*
* @param armoredElytra The armored elytra to repair.
* @param sourceItem The source item from which to copy the enchantments from.
* @param name The new name of the output armored elytra. When this is null, {@link
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public @Nullable ItemStack enchant(ItemStack armoredElytra, ItemStack sourceItem, @Nullable String name)
{
final EnchantmentContainer enchantments = EnchantmentContainer.getEnchantments(sourceItem, plugin);
if (enchantments.isEmpty())
return null;
return newBuilder().ofElytra(armoredElytra).addEnchantments(enchantments).withName(name).build();
}
/**
* Shortcut for creating a new armored elytra from two items.
*
* @param elytra The input item. This should be an (armored) elytra.
* @param combiner The item to combine with the elytra. This should either be an armored elytra of the same
* non-NONE tier as the input elytra or a chestplate.
* @param armorTier The armor tier of the input item. If this is not known, use {@link #combine(ItemStack,
* ItemStack, String)} instead.
* @param name The new name of the output armored elytra. When this is null, {@link
* ArmoredElytra#getArmoredElytraName(ArmorTier)} is used to set the name.
* @return The new armored elytra.
*/
public ItemStack combine(ItemStack elytra, ItemStack combiner, ArmorTier armorTier, @Nullable String name)
{
return newBuilder().ofElytra(elytra).combineWith(combiner, armorTier).withName(name).build();
}
/**
* See {@link #combine(ItemStack, ItemStack, ArmorTier, String)} for unknown armor tiers.
*/
public ItemStack combine(ItemStack elytra, ItemStack combiner, @Nullable String name)
{
return newBuilder().ofElytra(elytra).combineWith(combiner).withName(name).build();
}
/**
* Creates a new armored elytra of a specific tier.
*
* @param armorTier The tier of the new armored elytra.
* @return The new armored elytra.
*/
public ItemStack newArmoredElytra(ArmorTier armorTier)
{
return newBuilder().newItem(armorTier).build();
}
/**
* Represents the third and last step of the armored elytra build process.
*/
public interface IStep2
{
/**
* Specifies the new name of the armored elytra.
*
* @param name The new name of the armored elytra. When this is null (default), the default name for the new
* tier will be used.
* @return The current builder step.
*/
IStep2 withName(@Nullable String name);
/**
* Specifies the new color of the armored elytra.
*
* @param color The new color of the armored elytra. When this is null (default), the color to use is inferred
* from the creation process.
* @return The current builder step.
*/
IStep2 withColor(@Nullable Color color);
/**
* Specifies the new lore of the armored elytra.
*
* @param lore The new lore of the armored elytra. When this is null (default), the default lore for the new
* tier will be used.
* @return The current builder step.
*/
IStep2 withLore(@Nullable List<String> lore);
/**
* Specifies whether the armored elytra should be unbreakable.
* <p>
* By default, this value is read from {@link ConfigLoader#unbreakable()}.
*
* @param isUnbreakable True if the armored elytra should be unbreakable.
* @return The current builder step.
*/
IStep2 unbreakable(boolean isUnbreakable);
/**
* Constructs the armored elytra from the provided configuration.
*
* @return The new armored elytra.
*/
ItemStack build();
}
/**
* Represents the second and last step of the armored elytra build process.
*/
public interface IStep1
{
/**
* Repairs the armored elytra provided as input.
*
* @param count The amount of repair items to process.
* @return The next step of the builder process.
*/
IStep2 repair(int count);
/**
* Adds a set of enchantments to the armored elytra.
*
* @param enchantmentContainer The enchantments to add.
* @return The next step of the builder process.
*/
IStep2 addEnchantments(EnchantmentContainer enchantmentContainer);
/**
* Adds a set of enchantments to the armored elytra.
*
* @param sourceItem The source item from which to take the enchantments.
* @return The next step of the builder process.
*/
IStep2 addEnchantments(ItemStack sourceItem);
/**
* Combines the input elytra with another item.
*
* @param item The item to combine with the input elytra. This can either be a chestplate or, if the input
* elytra is an armored one, another armored elytra.
* @param armorTier The armor tier of the input item. If this is not known, use {@link #combineWith(ItemStack)}
* instead.
* @return The next step of the builder process.
*/
IStep2 combineWith(ItemStack item, ArmorTier armorTier);
/**
* See {@link #combineWith(ItemStack, ArmorTier)}. Used when the armor tier of the input item is not known.
*
* @return The next step of the builder process.
*/
IStep2 combineWith(ItemStack item);
/**
* Upgrades the elytra to a specific armor tier.
*
* @param armorTier The new armor tier.
* @return The next step of the builder process.
*/
IStep2 upgradeToTier(ArmorTier armorTier);
}
/**
* Represents the first and last step of the armored elytra build process.
*/
public interface IStep0
{
/**
* Use an elytra as base item to create the new armored elytra from.
*
* @param elytra An itemstack that represents an elytra. It does not matter whether the elytra is armored or
* not.
* @return The next step of the builder process.
*/
IStep1 ofElytra(ItemStack elytra);
/**
* Creates a fresh new armored elytra of a specific tier.
*
* @param armorTier The tier of the new armored elytra.
* @return The next step of the builder process.
*/
IStep2 newItem(ArmorTier armorTier);
}
private static final class Builder implements IStep0, IStep1, IStep2
{
private static final Color DEFAULT_LEATHER_COLOR = Bukkit.getServer().getItemFactory().getDefaultLeatherColor();
private final NBTEditor nbtEditor;
private final DurabilityManager durabilityManager;
private final ConfigLoader config;
private final ArmoredElytra plugin;
// These aren't nullable, as they are set by the only entry points.
/**
* The new armored elytra that will be returned at the end of the build process.
*/
private ItemStack newArmoredElytra;
/**
* The combined enchantments of the input items.
*/
private EnchantmentContainer combinedEnchantments;
/**
* The current armor tier of the input elytra.
*/
private ArmorTier currentArmorTier;
/**
* The durability of the output armored elytra.
*/
private int durability;
/**
* The armor tier of the output armored elytra. This defaults to {@link #currentArmorTier} if this isn't set.
*/
private @Nullable ArmorTier newArmorTier;
/**
* The name of the output armored elytra. This defaults to {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}
* when not overridden.
*/
private @Nullable String name;
/**
* The lore of the output armored elytra. This defaults to {@link ArmoredElytra#getElytraLore(ArmorTier)} when
* not overridden.
*/
private @Nullable List<String> lore;
/**
* The color of the output armored elytra. By default, the existing color (if any is used). When combined with
* another item, the color is inferred using {@link #getItemColor(ItemStack, ItemStack)}.
*/
private @Nullable Color color;
/**
* Whether the output armored elytra should be unbreakable. This defaults to {@link ConfigLoader#unbreakable()}
* when not overridden.
*/
private boolean isUnbreakable;
private Builder(NBTEditor nbtEditor, DurabilityManager durabilityManager,
ConfigLoader config, ArmoredElytra plugin)
{
this.nbtEditor = nbtEditor;
this.durabilityManager = durabilityManager;
this.config = config;
this.plugin = plugin;
}
@Override
public ItemStack build()
{
// Get default values if unset.
newArmorTier = newArmorTier == null ? currentArmorTier : newArmorTier;
name = name == null ? plugin.getArmoredElytraName(newArmorTier) : name;
lore = lore == null ? plugin.getElytraLore(newArmorTier) : lore;
final ItemStack output = nbtEditor.addArmorNBTTags(newArmoredElytra, newArmorTier,
isUnbreakable, name, lore, color);
durabilityManager.setDurability(output, durability, newArmorTier);
combinedEnchantments.applyEnchantments(output);
return output;
}
@Override
public IStep2 withName(@Nullable String name)
{
this.name = name;
return this;
}
@Override
public IStep2 withColor(@Nullable Color color)
{
this.color = color;
return this;
}
@Override
public IStep2 withLore(@Nullable List<String> lore)
{
this.lore = lore;
return this;
}
@Override
public IStep2 unbreakable(boolean isUnbreakable)
{
this.isUnbreakable = isUnbreakable;
return this;
}
@Override
public IStep2 repair(int count)
{
if (currentArmorTier == ArmorTier.NONE)
throw new IllegalArgumentException("Non-armored elytras cannot be repaired!");
durabilityManager.getRepairedDurability(newArmoredElytra, count, currentArmorTier);
return this;
}
@Override
public IStep2 addEnchantments(EnchantmentContainer enchantmentContainer)
{
combinedEnchantments.merge(enchantmentContainer);
return this;
}
@Override
public IStep2 addEnchantments(ItemStack sourceItem)
{
return addEnchantments(EnchantmentContainer.getEnchantments(sourceItem, plugin));
}
@Override
public IStep2 combineWith(ItemStack item, ArmorTier armorTier)
{
if (armorTier == ArmorTier.NONE && !Util.isChestPlate(item))
throw new IllegalArgumentException("Non-armored elytras can only be combined with chest plates!");
newArmorTier = armorTier;
if (currentArmorTier == ArmorTier.NONE &&
item.getType().equals(Material.ELYTRA) && newArmorTier != ArmorTier.NONE)
throw new IllegalArgumentException("A regular elytra cannot be combined with an armored one!");
withColor(getItemColor(newArmoredElytra, item));
unbreakable(config.unbreakable());
addEnchantments(item);
durability = durabilityManager.getCombinedDurability(newArmoredElytra, item,
currentArmorTier, newArmorTier);
return this;
}
@Override
public IStep2 combineWith(ItemStack item)
{
final ArmorTier armorTier = item.getType().equals(Material.ELYTRA) ?
nbtEditor.getArmorTier(item) : Util.armorToTier(item.getType());
return combineWith(item, armorTier);
}
@Override
public IStep2 upgradeToTier(ArmorTier armorTier)
{
newArmorTier = armorTier;
return this;
}
@Override
public IStep1 ofElytra(ItemStack elytra)
{
if (!elytra.getType().equals(Material.ELYTRA))
throw new IllegalArgumentException("Expected elytra as input, but got: " + elytra);
newArmoredElytra = new ItemStack(elytra);
if (currentArmorTier == null)
currentArmorTier = nbtEditor.getArmorTier(elytra);
combinedEnchantments = EnchantmentContainer.getEnchantments(newArmoredElytra, plugin);
durability = durabilityManager.getRealDurability(newArmoredElytra, currentArmorTier);
return this;
}
@Override
public IStep2 newItem(ArmorTier armorTier)
{
currentArmorTier = newArmorTier = armorTier;
ofElytra(new ItemStack(Material.ELYTRA));
return this;
}
/**
* Gets the color of the item if the item has a color.
* <p>
* See {@link LeatherArmorMeta#getColor()}.
*
* @param itemA The first {@link ItemStack} to check.
* @param itemB The second {@link ItemStack} to check.
* @return The color of the item, if it has a color, otherwise null.
*/
private @Nullable Color getItemColor(final ItemStack itemA, final ItemStack itemB)
{
final @Nullable Color colorA = getItemColor(itemA);
if (colorA != null && !colorA.equals(DEFAULT_LEATHER_COLOR))
return colorA;
final @Nullable Color colorB = getItemColor(itemB);
return colorB != null ? colorB : colorA;
}
/**
* Gets the colors of an item if available.
* <p>
* This currently only applies to leather armor(ed elytras).
*
* @param itemStack The item to analyze.
* @return The color of the item, if available, otherwise null.
*/
private @Nullable Color getItemColor(final ItemStack itemStack)
{
if (itemStack.getType() == Material.ELYTRA)
return nbtEditor.getColorOfArmoredElytra(itemStack);
if (!itemStack.hasItemMeta() || !(itemStack.getItemMeta() instanceof LeatherArmorMeta))
return null;
return ((LeatherArmorMeta) itemStack.getItemMeta()).getColor();
}
}
}

View File

@ -1,6 +1,8 @@
package nl.pim16aap2.armoredElytra.util;
package nl.pim16aap2.armoredElytra.nbtEditor;
import nl.pim16aap2.armoredElytra.nbtEditor.NBTEditor;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.ConfigLoader;
import nl.pim16aap2.armoredElytra.util.Util;
import org.bukkit.Material;
import org.bukkit.inventory.ItemStack;

View File

@ -118,7 +118,7 @@ public class NBTEditor
return ret;
}
private void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName)
void overwriteNBTValue(ItemMeta meta, Attribute attribute, double value, String modifierName)
{
if (meta.hasAttributeModifiers())
meta.removeAttributeModifier(attribute);
@ -129,7 +129,7 @@ public class NBTEditor
meta.addAttributeModifier(attribute, attributeModifier);
}
private ArmorTier getArmorTier(@Nullable ItemMeta meta)
ArmorTier getArmorTier(@Nullable ItemMeta meta)
{
if (meta == null || !meta.hasAttributeModifiers())
return ArmorTier.NONE;
@ -191,7 +191,7 @@ public class NBTEditor
return rgb == null ? null : Color.fromRGB(rgb);
}
private static ItemMeta getOrCreateItemMeta(ItemStack item)
static ItemMeta getOrCreateItemMeta(ItemStack item)
{
final ItemMeta meta = item.hasItemMeta() ?
item.getItemMeta() :
@ -200,71 +200,4 @@ public class NBTEditor
throw new IllegalArgumentException("Tried to add armor to invalid item: " + item);
return meta;
}
/**
* Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link
* ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is
* applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}.
*
* @param item The item.
* @param armorTier The {@link ArmorTier} that will be added to it.
* @param unbreakable Whether the resulting item should be unbreakable.
* @return The NEW item.
*/
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable)
{
return addArmorNBTTags(item, armorTier, unbreakable, (Color) null);
}
/**
* Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link
* ArmorTier#NONE} has no effect (besides making a copy of the item).
*
* @param item The item.
* @param armorTier The {@link ArmorTier} that will be added to it.
* @param unbreakable Whether the resulting item should be unbreakable.
* @param name The name fo the item.
* @return The NEW item.
*/
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, final String name)
{
return addArmorNBTTags(item, armorTier, unbreakable, name, null, null);
}
/**
* Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link
* ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is
* applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}.
*
* @param item The item.
* @param armorTier The {@link ArmorTier} that will be added to it.
* @param unbreakable Whether the resulting item should be unbreakable.
* @param color The color of the armor to store. May be null.
* @return The NEW item.
*/
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, final Color color)
{
return addArmorNBTTags(item, armorTier, unbreakable,
ArmoredElytra.getInstance().getArmoredElytraName(armorTier),
ArmoredElytra.getInstance().getElytraLore(armorTier), color);
}
/**
* Adds a given {@link ArmorTier} to an item. The item will be cloned. Note that setting the armor tier to {@link
* ArmorTier#NONE} has no effect (besides making a copy of the item). The default name for the given tier is
* applied. See {@link ArmoredElytra#getArmoredElytraName(ArmorTier)}.
*
* @param item The item.
* @param armorTier The {@link ArmorTier} that will be added to it.
* @param unbreakable Whether the resulting item should be unbreakable.
* @param name The name of the item.
* @param color The color of the armor to store. May be null.
* @return The NEW item.
*/
public ItemStack addArmorNBTTags(ItemStack item, ArmorTier armorTier, boolean unbreakable, String name,
Color color)
{
return addArmorNBTTags(item, armorTier, unbreakable, name,
ArmoredElytra.getInstance().getElytraLore(armorTier), color);
}
}

View File

@ -28,6 +28,19 @@ public class EnchantmentContainer
filter(plugin.getConfigLoader().allowedEnchantments());
}
/**
* Copy constructor.
*/
public EnchantmentContainer(EnchantmentContainer other)
{
this(other.enchantments);
}
public EnchantmentContainer()
{
enchantments = new HashMap<>();
}
private EnchantmentContainer(final Map<Enchantment, Integer> enchantments)
{
this.enchantments = new HashMap<>(enchantments);
@ -117,6 +130,8 @@ public class EnchantmentContainer
*/
public void merge(EnchantmentContainer other)
{
if (this == other)
throw new IllegalArgumentException("EnchantmentContainers cannot be combined with themselves!");
enchantments = merge(enchantments, other.enchantments);
}

View File

@ -34,6 +34,12 @@ public class Util
return item.getDurability() >= item.getType().getMaxDurability();
}
// Get the armor tier from a chest plate.
public static ArmorTier armorToTier(ItemStack itemStack)
{
return armorToTier(itemStack.getType());
}
// Get the armor tier from a chest plate.
public static ArmorTier armorToTier(Material mat)
{