diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/listeners/HopperListener.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/listeners/HopperListener.java index 58a29c1..a921996 100644 --- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/listeners/HopperListener.java +++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/listeners/HopperListener.java @@ -3,6 +3,7 @@ package com.jamesdpeters.minecraft.chests.listeners; import com.jamesdpeters.minecraft.chests.ChestsPlusPlus; import com.jamesdpeters.minecraft.chests.api.ApiSpecific; import com.jamesdpeters.minecraft.chests.filters.HopperFilter; +import com.jamesdpeters.minecraft.chests.lang.Message; import com.jamesdpeters.minecraft.chests.misc.Utils; import com.jamesdpeters.minecraft.chests.runnables.VirtualChestToHopper; import com.jamesdpeters.minecraft.chests.serialize.Config; @@ -24,21 +25,58 @@ import org.bukkit.event.Listener; import org.bukkit.event.inventory.InventoryMoveItemEvent; import org.bukkit.event.inventory.InventoryPickupItemEvent; import org.bukkit.event.player.PlayerInteractEntityEvent; -import org.bukkit.scheduler.BukkitRunnable; + +import java.util.ArrayList; +import java.util.List; public class HopperListener implements Listener { + private static List hoppersTicked; + + static { + hoppersTicked = new ArrayList<>(); + } + + private static void setHopperTicked(Location hopper){ + hoppersTicked.add(hopper); + Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> { + hoppersTicked.remove(hopper); + },1); + } + @EventHandler(priority = EventPriority.HIGHEST) public void onHopperMoveEvent(InventoryMoveItemEvent event) { //TO HOPPER if (event.getDestination().getHolder() instanceof Hopper) { - if (event.getDestination().getLocation() != null) { - if (event.getDestination().getLocation().getBlock().isBlockPowered()) return; + Location hopperLoc = event.getDestination().getLocation(); + if (hopperLoc != null) { + if (hopperLoc.getBlock().isBlockPowered()) return; + } + if (!event.isCancelled()) { + event.setCancelled(true); + + // If Hopper has just ticked return - This is needed since cancelling the Event causes Spigot to check + // all other slots whereas Paper doesn't. + if (hoppersTicked.contains(hopperLoc)) return; + + // If hopper is pulling from hopper ignore since two events get called! + if ((event.getInitiator() == event.getDestination()) && hopperLoc != null) { + setHopperTicked(hopperLoc); + + // Move the items in the next tick - since the InventoryMoveItemEvent places the moved item back + // into the source inventory when the event is cancelled. + Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> { + // Moves the item to the destination inventory and if an item was moved updates the hoppers. + if (VirtualChestToHopper.move(hopperLoc, event.getSource(), event.getDestination())) { + // Updates the state of the destination inventory to fix comparator bug. + hopperLoc.getBlock().getState().update(true, true); + // Updates the state of the source inventory + Location sourceHopperLoc = event.getSource().getLocation(); + if (sourceHopperLoc != null) sourceHopperLoc.getBlock().getState().update(); + } + }); + } } - if (!event.isCancelled()) Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> { - VirtualChestToHopper.move(event.getDestination().getLocation(), event.getSource(), event.getDestination()); - }, 1); - event.setCancelled(true); } } @@ -51,20 +89,17 @@ public class HopperListener implements Listener { if (storage != null) { if (!event.isCancelled()) { event.setCancelled(true); - new BukkitRunnable() { - @Override - public void run() { - if (location != null) { - int hopperAmount = SpigotConfig.getWorldSettings(location.getWorld()).getHopperAmount(); - if (Utils.hopperMove(event.getSource(), hopperAmount, storage.getInventory())) { - storage.updateDisplayItem(); - } - if (event.getDestination().getHolder() != null) - event.getDestination().getHolder().getInventory().clear(); - if (storage.getInventory().getViewers().size() > 0) storage.sort(); + Bukkit.getScheduler().scheduleSyncDelayedTask(ChestsPlusPlus.PLUGIN, () -> { + if (location != null) { + int hopperAmount = SpigotConfig.getWorldSettings(location.getWorld()).getHopperAmount(); + if (Utils.hopperMove(event.getSource(), hopperAmount, storage.getInventory())) { + storage.updateDisplayItem(); } + if (event.getDestination().getHolder() != null) + event.getDestination().getHolder().getInventory().clear(); + if (storage.getInventory().getViewers().size() > 0) storage.sort(); } - }.runTaskLater(ChestsPlusPlus.PLUGIN, 1); + },1); } } } @@ -93,13 +128,13 @@ public class HopperListener implements Listener { if (!itemFrame.getItem().getType().equals(Material.AIR)) rotation = rotation.rotateClockwise(); if (rotation.equals(Rotation.FLIPPED)) { - event.getPlayer().sendMessage(ChatColor.AQUA + "ItemFrame now filters all types of this item! e.g Enchanted Books."); + event.getPlayer().sendMessage(ChatColor.AQUA + Message.ITEM_FRAME_FILTER_ALL_TYPES.getString()); } else if (rotation.equals(Rotation.NONE)) { - event.getPlayer().sendMessage(ChatColor.GREEN + "ItemFrame is in default filtering mode. Rotate Item Frame to change mode!"); + event.getPlayer().sendMessage(ChatColor.GREEN + Message.ITEM_FRAME_FILTER_DEFAULT.getString()); } else if (rotation.equals(Rotation.CLOCKWISE)) { - event.getPlayer().sendMessage(ChatColor.DARK_RED + "ItemFrame now prevents this item from being accepted in the hopper!"); + event.getPlayer().sendMessage(ChatColor.DARK_RED + Message.ITEM_FRAME_FILTER_DENY.getString()); } else if (rotation.equals(Rotation.COUNTER_CLOCKWISE)) { - event.getPlayer().sendMessage(ChatColor.GOLD + "ItemFrame now prevents all types of this item from being accepted in the hopper! e.g Enchanted Books."); + event.getPlayer().sendMessage(ChatColor.GOLD + Message.ITEM_FRAME_FILTER_DENY_ALL_TYPES.getString()); } } } diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Values.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Values.java index e116563..d4f5f0d 100644 --- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Values.java +++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/misc/Values.java @@ -14,4 +14,5 @@ public class Values { public final static NamespacedKey playerUUID = new NamespacedKey(ChestsPlusPlus.PLUGIN, "playerUUID"); public final static NamespacedKey PluginKey = new NamespacedKey(ChestsPlusPlus.PLUGIN, "ChestsPlusPlus"); public final static NamespacedKey storageID = new NamespacedKey(ChestsPlusPlus.PLUGIN, "storageID"); + public final static NamespacedKey hopperTicked = new NamespacedKey(ChestsPlusPlus.PLUGIN, "hopperTicked"); } diff --git a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/runnables/VirtualChestToHopper.java b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/runnables/VirtualChestToHopper.java index aa29b5b..b35df65 100644 --- a/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/runnables/VirtualChestToHopper.java +++ b/ChestsPlusPlus_Main/src/main/java/com/jamesdpeters/minecraft/chests/runnables/VirtualChestToHopper.java @@ -43,7 +43,7 @@ public class VirtualChestToHopper extends BukkitRunnable { if (below.getBlock().isBlockIndirectlyPowered() || below.getBlock().isBlockPowered()) { continue; } - if (move(hopper.getLocation(), hopper.getInventory(), storage.getInventory())) { + if (move(hopper.getLocation(), storage.getInventory(), hopper.getInventory())) { storage.updateDisplayItem(); } if (storage.getInventory().getViewers().size() > 0) storage.sort();