@SuppressWarnings("deprecation")
 @EventHandler(priority = EventPriority.LOWEST)
 public void onFurnaceInsert(InventoryClickEvent e) {
   if (e.getInventory().getType() == InventoryType.FURNACE
       && e.getCursor() != null
       && (e.getRawSlot() == 0 || e.getSlot() == 1)) {
     if (!e.isShiftClick()) {
       ItemStack item = e.getCurrentItem();
       e.setCurrentItem(e.getCursor());
       e.setCursor(item);
       e.setCancelled(true);
       PlayerInventory.update((Player) e.getWhoClicked());
     }
   }
 }
 @Override
 public void onClicked(InventoryClickEvent event) {
   int newValue = value;
   if (event.isLeftClick()) {
     newValue -= event.isShiftClick() ? altIncr : incr;
   } else if (event.isRightClick()) {
     newValue += event.isShiftClick() ? altIncr : incr;
   }
   newValue = Math.max(Math.min(newValue, range.getMaximumInteger()), range.getMinimumInteger());
   if (newValue != value && callback.run(newValue)) {
     value = newValue;
     event.setCurrentItem(getTexture());
   } else {
     // vetoed by the block!
     if (event.getWhoClicked() instanceof Player) {
       STBUtil.complain((Player) event.getWhoClicked());
     }
   }
 }
 @EventHandler(ignoreCancelled = true)
 public void onFurnaceInsert(final InventoryClickEvent event) {
   if (event.getInventory().getType() != InventoryType.FURNACE) {
     return;
   }
   if (event.getRawSlot() == 0 && event.getCursor().getType() != Material.AIR) {
     if (!validateSmeltingIngredient(event.getCursor())) {
       event.setCancelled(true);
     }
   } else if (event.getRawSlot() >= event.getView().getTopInventory().getSize()) {
     if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY) {
       if (!validateSmeltingIngredient(event.getCurrentItem())
           && !STBUtil.isFuel(event.getCurrentItem().getType())) {
         event.setCancelled(true);
         int newSlot = findNewSlot(event);
         if (newSlot >= 0) {
           event.getWhoClicked().getInventory().setItem(newSlot, event.getCurrentItem());
           event.setCurrentItem(null);
         }
       }
     }
   } else if (event.getRawSlot() == 2
       && SensibleToolbox.getItemRegistry().isSTBItem(event.getCurrentItem())) {
     // work around CB bug where shift-clicking custom items out of furnace seems
     // to cause a de-sync, leaving phantom items in the furnace
     Bukkit.getScheduler()
         .runTask(
             plugin,
             new Runnable() {
               @Override
               public void run() {
                 STBUtil.forceInventoryRefresh(event.getInventory());
               }
             });
   }
 }
  @SuppressWarnings("deprecation")
  @EventHandler
  public void onInventoryClick(InventoryClickEvent event) {
    // controller.getLogger().info("CLICK: " + event.getAction() + ", " + event.getClick() + " on "
    // + event.getSlotType() + " in "+ event.getInventory().getType() + " slots: " + event.getSlot()
    // + ":" + event.getRawSlot());

    if (event.isCancelled()) return;
    if (!(event.getWhoClicked() instanceof Player)) return;

    Player player = (Player) event.getWhoClicked();
    Mage apiMage = controller.getMage(player);

    if (!(apiMage instanceof com.elmakers.mine.bukkit.magic.Mage)) return;
    final com.elmakers.mine.bukkit.magic.Mage mage = (com.elmakers.mine.bukkit.magic.Mage) apiMage;

    GUIAction gui = mage.getActiveGUI();
    if (gui != null) {
      gui.clicked(event);
      return;
    }

    // Check for temporary items and skill items
    InventoryAction action = event.getAction();
    InventoryType inventoryType = event.getInventory().getType();
    ItemStack clickedItem = event.getCurrentItem();

    boolean isDrop =
        event.getClick() == ClickType.DROP || event.getClick() == ClickType.CONTROL_DROP;
    boolean isSkill = clickedItem != null && Wand.isSkill(clickedItem);

    // Preventing putting skills in containers
    if (isSkill && inventoryType != InventoryType.CRAFTING) {
      if (!isDrop) {
        event.setCancelled(true);
      }
      return;
    }

    // Check for right-click-to-use
    if (isSkill && action == InventoryAction.PICKUP_HALF) {
      Spell spell = mage.getSpell(Wand.getSpell(clickedItem));
      if (spell != null) {
        spell.cast();
      }
      player.closeInventory();
      event.setCancelled(true);
      return;
    }

    if (clickedItem != null && NMSUtils.isTemporary(clickedItem)) {
      String message = NMSUtils.getTemporaryMessage(clickedItem);
      if (message != null && message.length() > 1) {
        mage.sendMessage(message);
      }
      ItemStack replacement = NMSUtils.getReplacement(clickedItem);
      event.setCurrentItem(replacement);
      event.setCancelled(true);
      return;
    }

    // Check for wearing spells
    ItemStack heldItem = event.getCursor();
    if (heldItem != null && event.getSlotType() == InventoryType.SlotType.ARMOR) {
      if (Wand.isSpell(heldItem)) {
        event.setCancelled(true);
        return;
      }
      if (Wand.isWand(clickedItem) || Wand.isWand(heldItem)) {
        controller.onArmorUpdated(mage);
      }
    }
    boolean isHotbar =
        event.getAction() == InventoryAction.HOTBAR_SWAP
            || event.getAction() == InventoryAction.HOTBAR_MOVE_AND_READD;
    if (isHotbar && event.getSlotType() == InventoryType.SlotType.ARMOR) {
      int slot = event.getHotbarButton();
      ItemStack item = mage.getPlayer().getInventory().getItem(slot);
      if (item != null && Wand.isSpell(item)) {
        event.setCancelled(true);
        return;
      }
      controller.onArmorUpdated(mage);
    }

    Wand activeWand = mage.getActiveWand();

    boolean isChest =
        inventoryType == InventoryType.CHEST
            || inventoryType == InventoryType.HOPPER
            || inventoryType == InventoryType.DISPENSER
            || inventoryType == InventoryType.DROPPER;
    boolean clickedWand = Wand.isWand(clickedItem);
    boolean isContainerSlot = event.getSlot() == event.getRawSlot();

    if (activeWand != null && activeWand.isInventoryOpen()) {
      // Kind of a hack to avoid hotbar items with 0 amounts disappearing :(
      Inventory inventory = player.getInventory();
      for (int i = 0; i < 8; i++) {
        ItemStack item = inventory.getItem(i);
        if (item != null && item.getAmount() == 0) {
          item.setAmount(1);
        }
      }

      // Don't allow the offhand slot to be messed with while the spell inventory is open
      if (event.getRawSlot() == 45) {
        event.setCancelled(true);
        return;
      }

      if (Wand.isSpell(clickedItem) && clickedItem.getAmount() != 1) {
        clickedItem.setAmount(1);
      }
      if (clickedWand) {
        event.setCancelled(true);
        if (dropChangesPages) {
          activeWand.cycleInventory();
        } else {
          activeWand.cycleHotbar(1);
        }
        return;
      }

      // So many ways to try and move the wand around, that we have to watch for!
      if (isHotbar && Wand.isWand(player.getInventory().getItem(event.getHotbarButton()))) {
        event.setCancelled(true);
        return;
      }

      // Can't wear spells
      if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY && clickedItem != null) {
        if (controller.isWearable(clickedItem)) {
          event.setCancelled(true);
          return;
        }
      }

      // Safety check for something that ought not to be possible
      // but perhaps happens with lag?
      if (Wand.isWand(event.getCursor())) {
        activeWand.closeInventory();
        event.setCursor(null);
        event.setCancelled(true);
        return;
      }
    } else if (activeWand != null) {
      // Check for changes that could have been made to the active wand
      Integer activeSlot = player.getInventory().getHeldItemSlot();
      if (activeSlot != null
          && (event.getSlot() == activeSlot
              || (event.getAction() == InventoryAction.HOTBAR_SWAP
                  && event.getHotbarButton() == activeSlot))) {
        mage.checkWand();
        activeWand = mage.getActiveWand();
      }
    } else if (clickedWand
        && Wand.Undroppable
        && !player.hasPermission("Magic.wand.override_drop")
        && isChest
        && !isContainerSlot) {
      Wand wand = new Wand(controller, clickedItem);
      if (wand.isUndroppable()) {
        event.setCancelled(true);
        return;
      }
    }

    // Check for armor changing
    if (event.getAction() == InventoryAction.MOVE_TO_OTHER_INVENTORY && clickedItem != null) {
      if (controller.isWearable(clickedItem)) {
        controller.onArmorUpdated(mage);
      }
    }

    // Check for dropping items out of a wand's inventory
    // or dropping undroppable wands
    if (isDrop) {
      if (clickedWand) {
        Wand wand = new Wand(controller, clickedItem);
        if (wand.isUndroppable()) {
          event.setCancelled(true);
          if (activeWand != null) {
            if (activeWand.getHotbarCount() > 1) {
              activeWand.cycleHotbar(1);
            } else {
              activeWand.closeInventory();
            }
          }
          return;
        }
      }
      if (activeWand != null && activeWand.isInventoryOpen()) {

        ItemStack droppedItem = clickedItem;

        if (!Wand.isSpell(droppedItem)) {
          mage.giveItem(droppedItem);
          event.setCurrentItem(null);
          event.setCancelled(true);
          return;
        }

        // This is a hack to deal with spells on cooldown disappearing,
        // Since the event handler doesn't match the zero-count itemstacks
        Integer slot = event.getSlot();
        int heldSlot = player.getInventory().getHeldItemSlot();
        Inventory hotbar = activeWand.getHotbar();
        if (hotbar != null
            && slot >= 0
            && slot <= hotbar.getSize()
            && slot != heldSlot
            && activeWand.getMode() == WandMode.INVENTORY) {
          if (slot > heldSlot) slot--;
          if (slot < hotbar.getSize()) {
            droppedItem = hotbar.getItem(slot);
          } else {
            slot = null;
          }
        } else {
          slot = null;
        }

        if (!controller.isSpellDroppingEnabled()) {
          player.closeInventory();
          String spellName = Wand.getSpell(droppedItem);
          if (spellName != null && !activeWand.isManualQuickCastDisabled()) {
            Spell spell = mage.getSpell(spellName);
            if (spell != null) {
              activeWand.cast(spell);
              // Just in case a spell has levelled up... jeez!
              if (hotbar != null && slot != null) {
                droppedItem = hotbar.getItem(slot);
              }
            }
          }
          event.setCancelled(true);

          // This is needed to avoid spells on cooldown disappearing from the hotbar
          if (hotbar != null && slot != null && mage.getActiveGUI() == null) {
            player.getInventory().setItem(event.getSlot(), droppedItem);
            player.updateInventory();
          }

          return;
        }
        ItemStack newDrop = controller.removeItemFromWand(activeWand, droppedItem);

        if (newDrop != null) {
          Location location = player.getLocation();
          Item item = location.getWorld().dropItem(location, newDrop);
          item.setVelocity(location.getDirection().normalize());
        } else {
          event.setCancelled(true);
        }
      }
      return;
    }

    // Check for wand cycling with active inventory
    if (activeWand != null) {
      WandMode wandMode = activeWand.getMode();
      if ((wandMode == WandMode.INVENTORY && inventoryType == InventoryType.CRAFTING)
          || (wandMode == WandMode.CHEST && inventoryType == InventoryType.CHEST)) {
        if (activeWand.isInventoryOpen()) {
          if (event.getAction() == InventoryAction.NOTHING) {
            int direction = event.getClick() == ClickType.LEFT ? 1 : -1;
            activeWand.cycleInventory(direction);
            event.setCancelled(true);
            return;
          }

          if (event.getSlotType() == InventoryType.SlotType.ARMOR) {
            event.setCancelled(true);
            return;
          }

          // Chest mode falls back to selection from here.
          if (event.getAction() == InventoryAction.PICKUP_HALF || wandMode == WandMode.CHEST) {
            controller.onPlayerActivateIcon(mage, activeWand, clickedItem);
            player.closeInventory();
            event.setCancelled(true);
          }
        }
      }
    }
  }