Fix item dupe in own inventory
Reduce desync for other actions in own inventory Closes #182
This commit is contained in:
		@@ -16,7 +16,8 @@
 | 
			
		||||
 | 
			
		||||
package com.lishid.openinv.listeners;
 | 
			
		||||
 | 
			
		||||
import com.lishid.openinv.IOpenInv;
 | 
			
		||||
import com.lishid.openinv.OpenInv;
 | 
			
		||||
import com.lishid.openinv.internal.ISpecialPlayerInventory;
 | 
			
		||||
import com.lishid.openinv.util.InventoryAccess;
 | 
			
		||||
import com.lishid.openinv.util.Permissions;
 | 
			
		||||
import org.bukkit.GameMode;
 | 
			
		||||
@@ -25,11 +26,14 @@ import org.bukkit.entity.Player;
 | 
			
		||||
import org.bukkit.event.EventHandler;
 | 
			
		||||
import org.bukkit.event.EventPriority;
 | 
			
		||||
import org.bukkit.event.Listener;
 | 
			
		||||
import org.bukkit.event.inventory.InventoryAction;
 | 
			
		||||
import org.bukkit.event.inventory.InventoryClickEvent;
 | 
			
		||||
import org.bukkit.event.inventory.InventoryCloseEvent;
 | 
			
		||||
import org.bukkit.event.inventory.InventoryDragEvent;
 | 
			
		||||
import org.bukkit.event.inventory.InventoryInteractEvent;
 | 
			
		||||
import org.bukkit.inventory.Inventory;
 | 
			
		||||
import org.bukkit.inventory.ItemStack;
 | 
			
		||||
import org.jetbrains.annotations.NotNull;
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * Listener for inventory-related events to prevent modification of inventories where not allowed.
 | 
			
		||||
@@ -38,14 +42,14 @@ import org.bukkit.inventory.Inventory;
 | 
			
		||||
 */
 | 
			
		||||
public class InventoryListener implements Listener {
 | 
			
		||||
 | 
			
		||||
    private final IOpenInv plugin;
 | 
			
		||||
    private final OpenInv plugin;
 | 
			
		||||
 | 
			
		||||
    public InventoryListener(final IOpenInv plugin) {
 | 
			
		||||
    public InventoryListener(final OpenInv plugin) {
 | 
			
		||||
        this.plugin = plugin;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @EventHandler
 | 
			
		||||
    public void onInventoryClose(final InventoryCloseEvent event) {
 | 
			
		||||
    public void onInventoryClose(@NotNull final InventoryCloseEvent event) {
 | 
			
		||||
        if (!(event.getPlayer() instanceof Player)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
@@ -58,37 +62,92 @@ public class InventoryListener implements Listener {
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @EventHandler(priority = EventPriority.LOWEST)
 | 
			
		||||
    public void onInventoryClick(InventoryClickEvent event) {
 | 
			
		||||
        onInventoryInteract(event);
 | 
			
		||||
    public void onInventoryClick(@NotNull final InventoryClickEvent event) {
 | 
			
		||||
        if (handleInventoryInteract(event)) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Only specially handle actions in the player's own inventory.
 | 
			
		||||
        if (!event.getWhoClicked().equals(event.getView().getTopInventory().getHolder())) {
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Safe cast - has to be a player to be the holder of a special player inventory.
 | 
			
		||||
        Player player = (Player) event.getWhoClicked();
 | 
			
		||||
 | 
			
		||||
        if (event.getAction() != InventoryAction.MOVE_TO_OTHER_INVENTORY) {
 | 
			
		||||
            // All own-inventory interactions require updates to display properly.
 | 
			
		||||
            // Update in same tick after event completion.
 | 
			
		||||
            this.plugin.getServer().getScheduler().runTask(this.plugin, player::updateInventory);
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Extra handling for MOVE_TO_OTHER_INVENTORY - apparently Mojang no longer removes the item from the target
 | 
			
		||||
        // inventory prior to adding it to existing stacks.
 | 
			
		||||
        ItemStack currentItem = event.getCurrentItem();
 | 
			
		||||
        if (currentItem == null) {
 | 
			
		||||
            // Other plugin doing some sort of handling (would be NOTHING for null item otherwise), ignore.
 | 
			
		||||
            return;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ItemStack clone = currentItem.clone();
 | 
			
		||||
        event.setCurrentItem(null);
 | 
			
		||||
 | 
			
		||||
        // Complete add action in same tick after event completion.
 | 
			
		||||
        this.plugin.getServer().getScheduler().runTask(this.plugin, () -> {
 | 
			
		||||
            player.getInventory().addItem(clone);
 | 
			
		||||
            player.updateInventory();
 | 
			
		||||
        });
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @EventHandler(priority = EventPriority.LOWEST)
 | 
			
		||||
    public void onInventoryDrag(InventoryDragEvent event) {
 | 
			
		||||
        onInventoryInteract(event);
 | 
			
		||||
    public void onInventoryDrag(@NotNull final InventoryDragEvent event) {
 | 
			
		||||
        handleInventoryInteract(event);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void onInventoryInteract(InventoryInteractEvent event) {
 | 
			
		||||
    /**
 | 
			
		||||
     * Handle common InventoryInteractEvent functions.
 | 
			
		||||
     *
 | 
			
		||||
     * @param event the InventoryInteractEvent
 | 
			
		||||
     * @return true unless the top inventory is an opened player inventory
 | 
			
		||||
     */
 | 
			
		||||
    private boolean handleInventoryInteract(@NotNull final InventoryInteractEvent event) {
 | 
			
		||||
        HumanEntity entity = event.getWhoClicked();
 | 
			
		||||
 | 
			
		||||
        // Un-cancel spectator interactions.
 | 
			
		||||
        if (Permissions.SPECTATE.hasPermission(entity) && entity.getGameMode() == GameMode.SPECTATOR) {
 | 
			
		||||
            event.setCancelled(false);
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        if (event.isCancelled()) {
 | 
			
		||||
            return;
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        Inventory inventory = event.getInventory();
 | 
			
		||||
        Inventory inventory = event.getView().getTopInventory();
 | 
			
		||||
 | 
			
		||||
        if (InventoryAccess.isPlayerInventory(inventory)) {
 | 
			
		||||
            if (!Permissions.EDITINV.hasPermission(entity)) {
 | 
			
		||||
                event.setCancelled(true);
 | 
			
		||||
            }
 | 
			
		||||
        } else if (InventoryAccess.isEnderChest(inventory)) {
 | 
			
		||||
        // Is the inventory a special ender chest?
 | 
			
		||||
        if (InventoryAccess.isEnderChest(inventory)) {
 | 
			
		||||
            // Disallow ender chest interaction for users without edit permission.
 | 
			
		||||
            if (!Permissions.EDITENDER.hasPermission(entity)) {
 | 
			
		||||
                event.setCancelled(true);
 | 
			
		||||
            }
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        ISpecialPlayerInventory playerInventory = InventoryAccess.getPlayerInventory(inventory);
 | 
			
		||||
 | 
			
		||||
        // Ignore inventories other than special player inventories.
 | 
			
		||||
        if (playerInventory == null) {
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        // Disallow player inventory interaction for users without edit permission.
 | 
			
		||||
        if (!Permissions.EDITINV.hasPermission(entity)) {
 | 
			
		||||
            event.setCancelled(true);
 | 
			
		||||
            return true;
 | 
			
		||||
        }
 | 
			
		||||
 | 
			
		||||
        return false;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user