package com.songoda.epicenchants.listeners; import com.songoda.epicenchants.events.ArmorEquipEvent; import com.songoda.epicenchants.events.ArmorEquipEvent.ArmorType; import com.songoda.epicenchants.events.ArmorEquipEvent.EquipMethod; import org.bukkit.Bukkit; import org.bukkit.Material; import org.bukkit.entity.Player; import org.bukkit.event.Event.Result; import org.bukkit.event.EventHandler; import org.bukkit.event.Listener; import org.bukkit.event.block.Action; import org.bukkit.event.entity.PlayerDeathEvent; import org.bukkit.event.inventory.ClickType; import org.bukkit.event.inventory.InventoryAction; import org.bukkit.event.inventory.InventoryClickEvent; import org.bukkit.event.inventory.InventoryDragEvent; import org.bukkit.event.inventory.InventoryType; import org.bukkit.event.inventory.InventoryType.SlotType; import org.bukkit.event.player.PlayerInteractEvent; import org.bukkit.event.player.PlayerItemBreakEvent; import org.bukkit.inventory.ItemStack; import static org.bukkit.event.EventPriority.HIGHEST; public class ArmorListener implements Listener { @EventHandler(ignoreCancelled = true) public final void onInventoryClick(final InventoryClickEvent e) { boolean shift = false, numberKey = false; if (e.getAction() == InventoryAction.NOTHING) { return; } if (!(e.getWhoClicked() instanceof Player)) { return; } if (e.getSlotType() != SlotType.ARMOR && e.getSlotType() != SlotType.QUICKBAR && e.getSlotType() != SlotType.CONTAINER) { return; } if (e.getClickedInventory() != null && !e.getClickedInventory().getType().equals(InventoryType.PLAYER)) { return; } if (!e.getInventory().getType().equals(InventoryType.CRAFTING) && !e.getInventory().getType().equals(InventoryType.PLAYER)) { return; } if (e.getClick().equals(ClickType.SHIFT_LEFT) || e.getClick().equals(ClickType.SHIFT_RIGHT)) { shift = true; } if (e.getClick().equals(ClickType.NUMBER_KEY)) { numberKey = true; } ArmorType newArmorType = ArmorType.matchType(shift ? e.getCurrentItem() : e.getCursor()); if (!shift && newArmorType != null && e.getRawSlot() != newArmorType.getSlot()) { // Used for drag and drop checking to make sure you aren't trying to place a helmet in the boots slot. return; } if (shift) { newArmorType = ArmorType.matchType(e.getCurrentItem()); if (newArmorType != null) { boolean equipping = true; if (e.getRawSlot() == newArmorType.getSlot()) { equipping = false; } if (newArmorType.equals(ArmorType.HELMET) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getHelmet())) || newArmorType.equals(ArmorType.CHESTPLATE) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getChestplate())) || newArmorType.equals(ArmorType.LEGGINGS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getLeggings())) || newArmorType.equals(ArmorType.BOOTS) && (equipping == isAirOrNull(e.getWhoClicked().getInventory().getBoots()))) { ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), EquipMethod.SHIFT_CLICK, newArmorType, equipping ? null : e.getCurrentItem(), equipping ? e.getCurrentItem() : null); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent); if (armorEquipEvent.isCancelled()) { e.setCancelled(true); } } } } else { ItemStack newArmorPiece = e.getCursor(); ItemStack oldArmorPiece = e.getCurrentItem(); if (numberKey) { if (e.getClickedInventory().getType().equals(InventoryType.PLAYER)) {// Prevents shit in the 2by2 crafting // e.getClickedInventory() == The players inventory // e.getHotBarButton() == key people are pressing to equip or unequip the item to or from. // e.getRawSlot() == The slot the item is going to. // e.getSlot() == Armor slot, can't use e.getRawSlot() as that gives a hotbar slot ;-; ItemStack hotbarItem = e.getClickedInventory().getItem(e.getHotbarButton()); if (!isAirOrNull(hotbarItem)) {// Equipping newArmorType = ArmorType.matchType(hotbarItem); newArmorPiece = hotbarItem; oldArmorPiece = e.getClickedInventory().getItem(e.getSlot()); } else {// Unequipping newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor()); } } } else { if (isAirOrNull(e.getCursor()) && !isAirOrNull(e.getCurrentItem())) {// unequip with no new item going into the slot. newArmorType = ArmorType.matchType(e.getCurrentItem()); } // e.getCurrentItem() == Unequip // e.getCursor() == Equip // newArmorType = ArmorType.matchType(!isAirOrNull(e.getCurrentItem()) ? e.getCurrentItem() : e.getCursor()); } if (newArmorType != null && e.getRawSlot() == newArmorType.getSlot()) { EquipMethod method = EquipMethod.PICK_DROP; if (e.getAction().equals(InventoryAction.HOTBAR_SWAP) || numberKey) method = EquipMethod.HOTBAR_SWAP; ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) e.getWhoClicked(), method, newArmorType, oldArmorPiece, newArmorPiece); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent); if (armorEquipEvent.isCancelled()) { e.setCancelled(true); } } } } @EventHandler(priority = HIGHEST) public void playerInteractEvent(PlayerInteractEvent e) { if (e.getAction() == Action.PHYSICAL) { return; } if (e.getAction() == Action.RIGHT_CLICK_AIR || e.getAction() == Action.RIGHT_CLICK_BLOCK) { final Player player = e.getPlayer(); if (e.getClickedBlock() != null && e.getAction() == Action.RIGHT_CLICK_BLOCK) {// Having both of these checks is useless, might as well do it though. // Some blocks have actions when you right click them which stops the client from equipping the armor in hand. /*if (VersionDependent.getBlackList().stream().anyMatch(type -> e.getClickedBlock().getType().equals(type))) { return; }*/ } ArmorType newArmorType = ArmorType.matchType(e.getItem()); if (newArmorType != null) { if (newArmorType.equals(ArmorType.HELMET) && isAirOrNull(e.getPlayer().getInventory().getHelmet()) || newArmorType.equals(ArmorType.CHESTPLATE) && isAirOrNull(e.getPlayer().getInventory().getChestplate()) || newArmorType.equals(ArmorType.LEGGINGS) && isAirOrNull(e.getPlayer().getInventory().getLeggings()) || newArmorType.equals(ArmorType.BOOTS) && isAirOrNull(e.getPlayer().getInventory().getBoots())) { ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(e.getPlayer(), EquipMethod.HOTBAR, ArmorType.matchType(e.getItem()), null, e.getItem()); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent); if (armorEquipEvent.isCancelled()) { e.setCancelled(true); player.updateInventory(); } } } } } @EventHandler public void inventoryDrag(InventoryDragEvent event) { if (event.getRawSlots().isEmpty()) { return; } ArmorType type = ArmorType.matchType(event.getOldCursor()); if (type != null && type.getSlot() == event.getRawSlots().stream().findFirst().orElse(0)) { ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent((Player) event.getWhoClicked(), EquipMethod.DRAG, type, null, event.getOldCursor()); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent); if (armorEquipEvent.isCancelled()) { event.setResult(Result.DENY); event.setCancelled(true); } } } @EventHandler public void itemBreakEvent(PlayerItemBreakEvent e) { ArmorType type = ArmorType.matchType(e.getBrokenItem()); if (type != null) { Player p = e.getPlayer(); ArmorEquipEvent armorEquipEvent = new ArmorEquipEvent(p, EquipMethod.BROKE, type, e.getBrokenItem(), null); Bukkit.getServer().getPluginManager().callEvent(armorEquipEvent); if (armorEquipEvent.isCancelled()) { ItemStack i = e.getBrokenItem().clone(); i.setAmount(1); i.setDurability((short) (i.getDurability() - 1)); switch (type) { case HELMET: p.getInventory().setHelmet(i); break; case CHESTPLATE: p.getInventory().setChestplate(i); break; case LEGGINGS: p.getInventory().setLeggings(i); break; case BOOTS: p.getInventory().setBoots(i); break; } } } } @EventHandler public void playerDeathEvent(PlayerDeathEvent event) { for (ItemStack i : event.getEntity().getInventory().getArmorContents()) { if (!isAirOrNull(i)) { Bukkit.getServer().getPluginManager().callEvent(new ArmorEquipEvent(event.getEntity(), EquipMethod.DEATH, ArmorType.matchType(i), i, null)); // No way to cancel a death event. } } } /** * A utility method to support versions that use null or air ItemStacks. */ private boolean isAirOrNull(ItemStack item) { return item == null || item.getType().equals(Material.AIR); } }