Extract anvil events to separate class

- Extracted all anvil-related events from the EventHandlers class into the new AnvilHandlers class. This separation makes it possible to load different types of creation methods later (smithing table).
This commit is contained in:
Pim van der Loos 2020-11-24 10:54:17 +01:00
parent 8e80e86e32
commit 8a7f56e07e
No known key found for this signature in database
GPG Key ID: C16F020ADAE6D5A8
4 changed files with 293 additions and 268 deletions

View File

@ -17,12 +17,6 @@
<id>CodeMC</id>
<url>https://repo.codemc.org/repository/maven-public/</url>
</repository>
<!-- Item-NBT-API-->
<repository>
<id>jitpack.io</id>
<url>https://jitpack.io</url>
</repository>
</repositories>
<dependencies>

View File

@ -1,5 +1,6 @@
package nl.pim16aap2.armoredElytra;
import nl.pim16aap2.armoredElytra.handlers.AnvilHandler;
import nl.pim16aap2.armoredElytra.handlers.CommandHandler;
import nl.pim16aap2.armoredElytra.handlers.EventHandlers;
import nl.pim16aap2.armoredElytra.handlers.FlyDurabilityHandler;
@ -21,6 +22,7 @@ import org.bukkit.entity.Player;
import org.bukkit.event.Listener;
import org.bukkit.inventory.ItemStack;
import org.bukkit.plugin.java.JavaPlugin;
import sun.reflect.generics.reflectiveObjects.NotImplementedException;
import java.util.EnumMap;
import java.util.Map;
@ -82,7 +84,13 @@ public class ArmoredElytra extends JavaPlugin implements Listener
myLogger(Level.INFO,
"Stats disabled, not loading stats :(... Please consider enabling it! I am a simple man, seeing higher user numbers helps me stay motivated!");
Bukkit.getPluginManager().registerEvents(new EventHandlers(this, config.craftingInSmithingTable()), this);
if (config.craftingInSmithingTable())
throw new NotImplementedException();
else
{
Bukkit.getPluginManager().registerEvents(new AnvilHandler(this, !config.uninstallMode()), this);
}
Bukkit.getPluginManager().registerEvents(new EventHandlers(this), this);
getCommand("ArmoredElytra").setExecutor(new CommandHandler(this));
// Load the plugin normally if not in uninstall mode.

View File

@ -0,0 +1,281 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.enchantment.EnchantmentManager;
import nl.pim16aap2.armoredElytra.util.Action;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util;
import nl.pim16aap2.armoredElytra.util.XMaterial;
import org.bukkit.Material;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import java.util.logging.Level;
public class AnvilHandler implements Listener
{
private final ArmoredElytra plugin;
private final boolean creationEnabled;
public AnvilHandler(final ArmoredElytra plugin, final boolean creationEnabled)
{
this.plugin = plugin;
this.creationEnabled = creationEnabled;
}
private void cleanAnvilInventory(AnvilInventory anvilInventory)
{
if (anvilInventory.getItem(0) != null)
anvilInventory.getItem(0).setAmount(0);
if (anvilInventory.getItem(1) != null)
anvilInventory.getItem(1).setAmount(anvilInventory.getItem(1).getAmount() - 1);
if (anvilInventory.getItem(2) != null)
anvilInventory.getItem(2).setAmount(0);
}
// Repair an Armored Elytra
private short repairItem(short curDur, ItemStack repairItem)
{
// Get the multiplier for the repair items.
double mult = 0.01;
if (repairItem.getType().equals(Material.LEATHER))
mult *= (100.0f / plugin.getConfigLoader().LEATHER_TO_FULL());
else if (repairItem.getType().equals(Material.GOLD_INGOT))
mult *= (100.0f / plugin.getConfigLoader().GOLD_TO_FULL());
else if (repairItem.getType().equals(Material.IRON_INGOT))
mult *= (100.0f / plugin.getConfigLoader().IRON_TO_FULL());
else if (repairItem.getType().equals(Material.DIAMOND))
mult *= (100.0f / plugin.getConfigLoader().DIAMONDS_TO_FULL());
else if (repairItem.getType().equals(XMaterial.NETHERITE_INGOT.parseMaterial()))
mult *= (100.0f / plugin.getConfigLoader().NETHERITE_TO_FULL());
int maxDurability = Material.ELYTRA.getMaxDurability();
int newDurability = (int) (curDur - (maxDurability * mult));
return (short) (newDurability <= 0 ? 0 : newDurability);
}
// Valid inputs:
// - Elytra (armored or not) + chestplate -> Create Armored Elytra
// - Elytra (armored) + enchanted book -> Enchant
// - Elytra (armored) + its repair item -> Repair
// - Elytra (armored) + other elytra (armored) -> Combine (Enchant + Repair)
// ! Elytra (armored, !leather) + leather/membrane -> Block
//
// Ignoring:
// - Elytra (not armored) + !chestplate -> None
// - * + * -> None
private Action isValidInput(ItemStack itemOne, ItemStack itemTwo)
{
if (itemOne == null || itemTwo == null)
return Action.NONE;
// If itemTwo is the elytra, while itemOne isn't, switch itemOne and itemTwo.
if (itemTwo.getType() == Material.ELYTRA && itemOne.getType() != Material.ELYTRA)
{
ItemStack tmp = itemOne;
itemOne = itemTwo;
itemTwo = tmp;
}
if (itemOne.getType() != Material.ELYTRA)
return Action.NONE;
Material matTwo = itemTwo.getType();
// If the elytra is to be combined with chest armor...
if (Util.isChestPlate(matTwo))
return Action.CREATE;
ArmorTier tier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemOne);
if (tier != ArmorTier.NONE)
{
// If the armored elytra is to be enchanted using an enchanted book...
if (matTwo == Material.ENCHANTED_BOOK)
return Action.ENCHANT;
// If the armored elytra is to be repaired using its repair item...
if (ArmorTier.getRepairItem(tier) == matTwo)
return itemOne.getDurability() == 0 ? Action.NONE : Action.REPAIR;
// If the armored elytra is to be combined with another armored elytra of the
// same tier...
// TODO: Should this also be disabled by "creationEnabled"?
if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemTwo) == tier)
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 ||
matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial()))
return Action.BLOCK;
}
return Action.NONE;
}
// Handle all anvil related stuff for this plugin.
@EventHandler
private void onAnvilInventoryOpen(PrepareAnvilEvent event)
{
Player player = (Player) event.getView().getPlayer();
ItemStack itemA = event.getInventory().getItem(0);
ItemStack itemB = event.getInventory().getItem(1);
ItemStack result = null;
if (itemA != null && itemB != null)
// If itemB is the elytra, while itemA isn't, switch itemA and itemB.
if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA)
{
result = itemA;
itemA = itemB;
itemB = result;
result = null;
}
// Check if there are items in both input slots.
if (itemA != null && itemB != null)
{
Action action = isValidInput(itemA, itemB);
ArmorTier newTier = ArmorTier.NONE;
ArmorTier curTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA);
short durability = 0;
EnchantmentManager enchantments = new EnchantmentManager(itemA);
switch (action)
{
case REPAIR:
newTier = curTier;
durability = repairItem(itemA.getDurability(), itemB);
break;
case COMBINE:
newTier = curTier;
durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability()
- itemB.getDurability());
durability = durability < 0 ? 0 : durability;
enchantments.merge(new EnchantmentManager(itemB));
break;
case CREATE:
newTier = Util.armorToTier(itemB.getType());
durability = 0;
enchantments.merge(new EnchantmentManager(itemB));
break;
case ENCHANT:
newTier = curTier;
durability = itemA.getDurability();
// If there aren't any illegal enchantments on the book, continue as normal.
// Otherwise... Block.
EnchantmentManager enchantmentsB = new EnchantmentManager(itemB);
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.apply(result);
result.setDurability(durability);
result = ArmoredElytra.getInstance().getNbtEditor()
.addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable());
event.setResult(result);
}
}
// If one of the input items is null and the other an armored elytra, remove the result.
// This prevent some naming issues.
// TODO: Allow renaming armored elytras.
if ((itemA == null ^ itemB == null) &&
ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE)
event.setResult(null);
player.updateInventory();
}
// Let the player take items out of the anvil.
@EventHandler
public void onInventoryClick(InventoryClickEvent e)
{
if (!(e.getWhoClicked() instanceof 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;
AnvilInventory anvilInventory;
// Try to cast inventory being used in the event to an anvil inventory.
// This will throw a ClassCastException when a CraftInventoryCustom is used.
try
{
anvilInventory = (AnvilInventory) e.getInventory();
}
catch (ClassCastException exception)
{
// Print warning to console and exit onInventoryClick event (no support for
// custom inventories as they are usually used for GUI's).
plugin.debugMsg(Level.WARNING, "Could not cast inventory to anvilInventory for player " + player.getName()
+ "! Armored Elytras cannot be crafted!");
exception.printStackTrace();
return;
}
int slot = e.getRawSlot();
if (slot == 2 && anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null &&
anvilInventory.getItem(2) != null && anvilInventory.getItem(2).getType() == Material.ELYTRA)
{
ArmorTier armortier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(anvilInventory.getItem(2));
// If there's an armored elytra in the final slot...
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier))
{
// Create a new armored elytra and give that one to the player instead of the
// result.
// This is done because after putting item0 in AFTER item1, the first letter of
// the color code shows up, this gets rid of that problem.
ItemStack result = ArmoredElytra.getInstance().getNbtEditor()
.addArmorNBTTags(anvilInventory.getItem(2), armortier,
plugin.getConfigLoader().unbreakable());
// Give the result to the player and clear the anvil's inventory.
if (e.isShiftClick())
{
// If the player's inventory is full, don't do anything.
if (player.getInventory().firstEmpty() == -1)
return;
player.getInventory().addItem(result);
}
else
player.setItemOnCursor(result);
// Clean the anvil's inventory after transferring the items.
cleanAnvilInventory(anvilInventory);
player.updateInventory();
return;
}
}
}
}

View File

@ -1,16 +1,13 @@
package nl.pim16aap2.armoredElytra.handlers;
import nl.pim16aap2.armoredElytra.ArmoredElytra;
import nl.pim16aap2.armoredElytra.enchantment.EnchantmentManager;
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.util.Action;
import nl.pim16aap2.armoredElytra.util.AllowedToWearEnum;
import nl.pim16aap2.armoredElytra.util.ArmorTier;
import nl.pim16aap2.armoredElytra.util.Util;
import nl.pim16aap2.armoredElytra.util.XMaterial;
import nl.pim16aap2.armoredElytra.util.messages.Message;
import org.bukkit.Bukkit;
import org.bukkit.Material;
@ -20,26 +17,18 @@ import org.bukkit.event.EventHandler;
import org.bukkit.event.Listener;
import org.bukkit.event.entity.EntityDamageEvent;
import org.bukkit.event.entity.EntityDamageEvent.DamageCause;
import org.bukkit.event.inventory.InventoryClickEvent;
import org.bukkit.event.inventory.InventoryType;
import org.bukkit.event.inventory.PrepareAnvilEvent;
import org.bukkit.inventory.AnvilInventory;
import org.bukkit.inventory.ItemStack;
import java.util.ArrayList;
import java.util.Random;
import java.util.logging.Level;
public class EventHandlers implements Listener
{
private final ArmoredElytra plugin;
private final boolean creationEnabled;
public EventHandlers(ArmoredElytra plugin, boolean creationEnabled)
public EventHandlers(ArmoredElytra plugin)
{
this.plugin = plugin;
this.creationEnabled = creationEnabled;
initializeArmorEquipEvent();
}
@ -56,255 +45,6 @@ public class EventHandlers implements Listener
player.updateInventory();
}
private void cleanAnvilInventory(AnvilInventory anvilInventory)
{
if (anvilInventory.getItem(0) != null)
anvilInventory.getItem(0).setAmount(0);
if (anvilInventory.getItem(1) != null)
anvilInventory.getItem(1).setAmount(anvilInventory.getItem(1).getAmount() - 1);
if (anvilInventory.getItem(2) != null)
anvilInventory.getItem(2).setAmount(0);
}
// Repair an Armored Elytra
private short repairItem(short curDur, ItemStack repairItem)
{
// Get the multiplier for the repair items.
double mult = 0.01;
if (repairItem.getType().equals(Material.LEATHER))
mult *= (100.0f / plugin.getConfigLoader().LEATHER_TO_FULL());
else if (repairItem.getType().equals(Material.GOLD_INGOT))
mult *= (100.0f / plugin.getConfigLoader().GOLD_TO_FULL());
else if (repairItem.getType().equals(Material.IRON_INGOT))
mult *= (100.0f / plugin.getConfigLoader().IRON_TO_FULL());
else if (repairItem.getType().equals(Material.DIAMOND))
mult *= (100.0f / plugin.getConfigLoader().DIAMONDS_TO_FULL());
else if (repairItem.getType().equals(XMaterial.NETHERITE_INGOT.parseMaterial()))
mult *= (100.0f / plugin.getConfigLoader().NETHERITE_TO_FULL());
int maxDurability = Material.ELYTRA.getMaxDurability();
int newDurability = (int) (curDur - (maxDurability * mult));
return (short) (newDurability <= 0 ? 0 : newDurability);
}
// Valid inputs:
// - Elytra (armored or not) + chestplate -> Create Armored Elytra
// - Elytra (armored) + enchanted book -> Enchant
// - Elytra (armored) + its repair item -> Repair
// - Elytra (armored) + other elytra (armored) -> Combine (Enchant + Repair)
// ! Elytra (armored, !leather) + leather/membrane -> Block
//
// Ignoring:
// - Elytra (not armored) + !chestplate -> None
// - * + * -> None
private Action isValidInput(ItemStack itemOne, ItemStack itemTwo)
{
if (itemOne == null || itemTwo == null)
return Action.NONE;
// If itemTwo is the elytra, while itemOne isn't, switch itemOne and itemTwo.
if (itemTwo.getType() == Material.ELYTRA && itemOne.getType() != Material.ELYTRA)
{
ItemStack tmp = itemOne;
itemOne = itemTwo;
itemTwo = tmp;
}
if (itemOne.getType() != Material.ELYTRA)
return Action.NONE;
Material matTwo = itemTwo.getType();
// If the elytra is to be combined with chest armor...
if (Util.isChestPlate(matTwo))
return Action.CREATE;
ArmorTier tier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemOne);
if (tier != ArmorTier.NONE)
{
// If the armored elytra is to be enchanted using an enchanted book...
if (matTwo == Material.ENCHANTED_BOOK)
return Action.ENCHANT;
// If the armored elytra is to be repaired using its repair item...
if (ArmorTier.getRepairItem(tier) == matTwo)
return itemOne.getDurability() == 0 ? Action.NONE : Action.REPAIR;
// If the armored elytra is to be combined with another armored elytra of the
// same tier...
// TODO: Should this also be disabled by "creationEnabled"?
if (ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemTwo) == tier)
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 ||
matTwo.equals(XMaterial.PHANTOM_MEMBRANE.parseMaterial()))
return Action.BLOCK;
}
return Action.NONE;
}
// Handle all anvil related stuff for this plugin.
@EventHandler
private void onAnvilInventoryOpen(PrepareAnvilEvent event)
{
Player player = (Player) event.getView().getPlayer();
ItemStack itemA = event.getInventory().getItem(0);
ItemStack itemB = event.getInventory().getItem(1);
ItemStack result = null;
if (itemA != null && itemB != null)
// If itemB is the elytra, while itemA isn't, switch itemA and itemB.
if (itemB.getType() == Material.ELYTRA && itemA.getType() != Material.ELYTRA)
{
result = itemA;
itemA = itemB;
itemB = result;
result = null;
}
// Check if there are items in both input slots.
if (itemA != null && itemB != null)
{
Action action = isValidInput(itemA, itemB);
ArmorTier newTier = ArmorTier.NONE;
ArmorTier curTier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA);
short durability = 0;
EnchantmentManager enchantments = new EnchantmentManager(itemA);
switch (action)
{
case REPAIR:
newTier = curTier;
durability = repairItem(itemA.getDurability(), itemB);
break;
case COMBINE:
newTier = curTier;
durability = (short) (-itemA.getType().getMaxDurability() - itemA.getDurability()
- itemB.getDurability());
durability = durability < 0 ? 0 : durability;
enchantments.merge(new EnchantmentManager(itemB));
break;
case CREATE:
newTier = Util.armorToTier(itemB.getType());
durability = 0;
enchantments.merge(new EnchantmentManager(itemB));
break;
case ENCHANT:
newTier = curTier;
durability = itemA.getDurability();
// If there aren't any illegal enchantments on the book, continue as normal.
// Otherwise... Block.
EnchantmentManager enchantmentsB = new EnchantmentManager(itemB);
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.apply(result);
result.setDurability(durability);
result = ArmoredElytra.getInstance().getNbtEditor()
.addArmorNBTTags(result, newTier, plugin.getConfigLoader().unbreakable());
event.setResult(result);
}
}
// If one of the input items is null and the other an armored elytra, remove the result.
// This prevent some naming issues.
// TODO: Allow renaming armored elytras.
if ((itemA == null ^ itemB == null) &&
ArmoredElytra.getInstance().getNbtEditor().getArmorTier(itemA == null ? itemB : itemA) != ArmorTier.NONE)
event.setResult(null);
player.updateInventory();
}
// Let the player take items out of the anvil.
@EventHandler
public void onInventoryClick(InventoryClickEvent e)
{
if (!(e.getWhoClicked() instanceof 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;
AnvilInventory anvilInventory;
// Try to cast inventory being used in the event to an anvil inventory.
// This will throw a ClassCastException when a CraftInventoryCustom is used.
try
{
anvilInventory = (AnvilInventory) e.getInventory();
}
catch (ClassCastException exception)
{
// Print warning to console and exit onInventoryClick event (no support for
// custom inventories as they are usually used for GUI's).
plugin.debugMsg(Level.WARNING, "Could not cast inventory to anvilInventory for player " + player.getName()
+ "! Armored Elytras cannot be crafted!");
exception.printStackTrace();
return;
}
int slot = e.getRawSlot();
if (slot == 2 && anvilInventory.getItem(0) != null && anvilInventory.getItem(1) != null &&
anvilInventory.getItem(2) != null && anvilInventory.getItem(2).getType() == Material.ELYTRA)
{
ArmorTier armortier = ArmoredElytra.getInstance().getNbtEditor().getArmorTier(anvilInventory.getItem(2));
// If there's an armored elytra in the final slot...
if (armortier != ArmorTier.NONE && plugin.playerHasCraftPerm(player, armortier))
{
// Create a new armored elytra and give that one to the player instead of the
// result.
// This is done because after putting item0 in AFTER item1, the first letter of
// the color code shows up, this gets rid of that problem.
ItemStack result = ArmoredElytra.getInstance().getNbtEditor()
.addArmorNBTTags(anvilInventory.getItem(2), armortier,
plugin.getConfigLoader().unbreakable());
// Give the result to the player and clear the anvil's inventory.
if (e.isShiftClick())
{
// If the player's inventory is full, don't do anything.
if (player.getInventory().firstEmpty() == -1)
return;
player.getInventory().addItem(result);
}
else
player.setItemOnCursor(result);
// Clean the anvil's inventory after transferring the items.
cleanAnvilInventory(anvilInventory);
player.updateInventory();
return;
}
}
}
// Make sure the player has the correct permission and that the item is not
// broken.
private AllowedToWearEnum isAllowedToWear(ItemStack elytra, Player player, ArmorTier armorTier)
@ -322,6 +62,7 @@ public class EventHandlers implements Listener
@EventHandler(ignoreCancelled = true)
public void onPlayerDamage(EntityDamageEvent e)
{
System.out.println("onPlayerDamage!");
if (!(e.getEntity() instanceof Player))
return;
@ -381,6 +122,7 @@ public class EventHandlers implements Listener
@EventHandler
public void onEquip(ArmorEquipEvent e)
{
System.out.println("onEquip!");
if (e.getMethod().equals(ArmorEquipEvent.EquipMethod.DEATH) ||
e.getMethod().equals(ArmorEquipEvent.EquipMethod.BROKE))
return;