forked from xjboss/KCauldronX
f3a73d8d68
Spigot patch: 0157-Use-FastMatches-for-ItemStack-Dirty-Check.patch
215 lines
9.4 KiB
Diff
215 lines
9.4 KiB
Diff
--- ../src-base/minecraft/net/minecraft/inventory/Container.java
|
|
+++ ../src-work/minecraft/net/minecraft/inventory/Container.java
|
|
@@ -13,6 +13,17 @@
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.MathHelper;
|
|
|
|
+// CraftBukkit start
|
|
+import java.util.HashMap;
|
|
+import java.util.Map;
|
|
+import net.minecraft.entity.player.EntityPlayerMP;
|
|
+import org.bukkit.craftbukkit.inventory.CraftInventory;
|
|
+import org.bukkit.craftbukkit.inventory.CraftItemStack;
|
|
+import org.bukkit.event.Event.Result;
|
|
+import org.bukkit.event.inventory.InventoryDragEvent;
|
|
+import org.bukkit.inventory.InventoryView;
|
|
+// CraftBukkit end
|
|
+
|
|
public abstract class Container
|
|
{
|
|
public List inventoryItemStacks = new ArrayList();
|
|
@@ -21,12 +32,52 @@
|
|
@SideOnly(Side.CLIENT)
|
|
private short transactionID;
|
|
private int field_94535_f = -1;
|
|
- private int field_94536_g;
|
|
+ public int field_94536_g; // CraftBukkit - private -> public
|
|
private final Set field_94537_h = new HashSet();
|
|
+ public InventoryView bukkitView = null; // Cauldron
|
|
+ private int tickCount = 0; // Spigot
|
|
protected List crafters = new ArrayList();
|
|
private Set playerList = new HashSet();
|
|
private static final String __OBFID = "CL_00001730";
|
|
|
|
+ // CraftBukkit start
|
|
+ public boolean checkReachable = true;
|
|
+ public InventoryView getBukkitView() { return bukkitView; } // Cauldron
|
|
+ public void transferTo(Container other, org.bukkit.craftbukkit.entity.CraftHumanEntity player)
|
|
+ {
|
|
+ InventoryView source = this.getBukkitView(), destination = other.getBukkitView();
|
|
+ // Cauldron start - add null checks to skip modded inventories with no Bukkit wrappers, and
|
|
+ // catch AbstractMethodErrors for modded IInventory's with no onClose()
|
|
+ if (source != null) {
|
|
+ try {
|
|
+ ((CraftInventory) source.getTopInventory()).getInventory().onClose(player);
|
|
+ } catch (AbstractMethodError ex) {
|
|
+ // modded
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ ((CraftInventory) source.getBottomInventory()).getInventory().onClose(player);
|
|
+ } catch (AbstractMethodError ex) {
|
|
+ // modded
|
|
+ }
|
|
+ }
|
|
+ if (destination != null) {
|
|
+ try {
|
|
+ ((CraftInventory) destination.getTopInventory()).getInventory().onOpen(player);
|
|
+ } catch (AbstractMethodError ex) {
|
|
+ // modded
|
|
+ }
|
|
+
|
|
+ try {
|
|
+ ((CraftInventory) destination.getBottomInventory()).getInventory().onOpen(player);
|
|
+ } catch (AbstractMethodError ex) {
|
|
+ // modded
|
|
+ }
|
|
+ }
|
|
+ // Cauldron end
|
|
+ }
|
|
+ // CraftBukkit end
|
|
+
|
|
protected Slot addSlotToContainer(Slot p_75146_1_)
|
|
{
|
|
p_75146_1_.slotNumber = this.inventorySlots.size();
|
|
@@ -39,7 +90,11 @@
|
|
{
|
|
if (this.crafters.contains(p_75132_1_))
|
|
{
|
|
- throw new IllegalArgumentException("Listener already listening");
|
|
+ // Cauldron start - As we do not create a new player object on respawn, we need to update the client with changes if listener already exists
|
|
+ //throw new IllegalArgumentException("Listener already listening");
|
|
+ p_75132_1_.sendContainerAndContentsToPlayer(this, this.getInventory());
|
|
+ this.detectAndSendChanges();
|
|
+ // Cauldron end
|
|
}
|
|
else
|
|
{
|
|
@@ -74,7 +129,7 @@
|
|
ItemStack itemstack = ((Slot)this.inventorySlots.get(i)).getStack();
|
|
ItemStack itemstack1 = (ItemStack)this.inventoryItemStacks.get(i);
|
|
|
|
- if (!ItemStack.areItemStacksEqual(itemstack1, itemstack))
|
|
+ if (!areItemStacksEqual(itemstack1, itemstack))
|
|
{
|
|
itemstack1 = itemstack == null ? null : itemstack.copy();
|
|
this.inventoryItemStacks.set(i, itemstack1);
|
|
@@ -85,6 +140,7 @@
|
|
}
|
|
}
|
|
}
|
|
+ tickCount++;
|
|
}
|
|
|
|
public boolean enchantItem(EntityPlayer p_75140_1_, int p_75140_2_)
|
|
@@ -109,6 +165,10 @@
|
|
|
|
public Slot getSlot(int p_75139_1_)
|
|
{
|
|
+ // Cauldron start - vanilla compatibility. fixes NPE with ProjectRed's Item Stock Keeper
|
|
+ if (p_75139_1_ < 0 || p_75139_1_ >= this.inventorySlots.size())
|
|
+ return null;
|
|
+ // Cauldron end
|
|
return (Slot)this.inventorySlots.get(p_75139_1_);
|
|
}
|
|
|
|
@@ -168,6 +228,7 @@
|
|
itemstack3 = inventoryplayer.getItemStack().copy();
|
|
i1 = inventoryplayer.getItemStack().stackSize;
|
|
Iterator iterator = this.field_94537_h.iterator();
|
|
+ Map<Integer, ItemStack> draggedSlots = new HashMap<Integer, ItemStack>(); // CraftBukkit - Store slots from drag in map (raw slot id -> new stack)
|
|
|
|
while (iterator.hasNext())
|
|
{
|
|
@@ -190,18 +251,55 @@
|
|
}
|
|
|
|
i1 -= itemstack1.stackSize - j1;
|
|
- slot1.putStack(itemstack1);
|
|
+ draggedSlots.put(slot1.slotNumber, itemstack1); // CraftBukkit - Put in map instead of setting
|
|
}
|
|
}
|
|
|
|
- itemstack3.stackSize = i1;
|
|
+ // CraftBukkit start - InventoryDragEvent
|
|
+ InventoryView view = getBukkitView();
|
|
+ org.bukkit.inventory.ItemStack newcursor = CraftItemStack.asCraftMirror(itemstack3);
|
|
+ newcursor.setAmount(i1);
|
|
+ Map<Integer, org.bukkit.inventory.ItemStack> eventmap = new HashMap<Integer, org.bukkit.inventory.ItemStack>();
|
|
|
|
- if (itemstack3.stackSize <= 0)
|
|
+ for (Map.Entry<Integer, ItemStack> ditem : draggedSlots.entrySet())
|
|
{
|
|
- itemstack3 = null;
|
|
+ eventmap.put(ditem.getKey(), CraftItemStack.asBukkitCopy(ditem.getValue()));
|
|
}
|
|
|
|
- inventoryplayer.setItemStack(itemstack3);
|
|
+ // It's essential that we set the cursor to the new value here to prevent item duplication if a plugin closes the inventory.
|
|
+ ItemStack oldCursor = inventoryplayer.getItemStack();
|
|
+ inventoryplayer.setItemStack(CraftItemStack.asNMSCopy(newcursor));
|
|
+ InventoryDragEvent event = new InventoryDragEvent(view, (newcursor.getType() != org.bukkit.Material.AIR ? newcursor : null), CraftItemStack.asBukkitCopy(oldCursor), this.field_94535_f == i1, eventmap); // Should be dragButton
|
|
+ p_75144_4_.worldObj.getServer().getPluginManager().callEvent(event);
|
|
+ // Whether or not a change was made to the inventory that requires an update.
|
|
+ boolean needsUpdate = event.getResult() != Result.DEFAULT;
|
|
+
|
|
+ if (event.getResult() != Result.DENY)
|
|
+ {
|
|
+ for (Map.Entry<Integer, ItemStack> dslot : draggedSlots.entrySet())
|
|
+ {
|
|
+ view.setItem(dslot.getKey(), CraftItemStack.asBukkitCopy(dslot.getValue()));
|
|
+ }
|
|
+
|
|
+ // The only time the carried item will be set to null is if the inventory is closed by the server.
|
|
+ // If the inventory is closed by the server, then the cursor items are dropped. This is why we change the cursor early.
|
|
+ if (inventoryplayer.getItemStack() != null)
|
|
+ {
|
|
+ inventoryplayer.setItemStack(CraftItemStack.asNMSCopy(event.getCursor()));
|
|
+ needsUpdate = true;
|
|
+ }
|
|
+ }
|
|
+ else
|
|
+ {
|
|
+ inventoryplayer.setItemStack(oldCursor);
|
|
+ }
|
|
+
|
|
+ if (needsUpdate && p_75144_4_ instanceof EntityPlayerMP)
|
|
+ {
|
|
+ ((EntityPlayerMP) p_75144_4_).sendContainerToPlayer(this);
|
|
+ }
|
|
+
|
|
+ // CraftBukkit end
|
|
}
|
|
|
|
this.func_94533_d();
|
|
@@ -235,10 +333,17 @@
|
|
|
|
if (p_75144_2_ == 1)
|
|
{
|
|
- p_75144_4_.dropPlayerItemWithRandomChoice(inventoryplayer.getItemStack().splitStack(1), true);
|
|
+ // CraftBukkit start - Store a reference
|
|
+ ItemStack itemstack4 = inventoryplayer.getItemStack();
|
|
|
|
if (inventoryplayer.getItemStack().stackSize == 0)
|
|
{
|
|
+ p_75144_4_.dropPlayerItemWithRandomChoice(inventoryplayer.getItemStack().splitStack(1), true);
|
|
+ }
|
|
+
|
|
+ if (itemstack4.stackSize == 0)
|
|
+ {
|
|
+ // CraftBukkit end
|
|
inventoryplayer.setItemStack((ItemStack)null);
|
|
}
|
|
}
|
|
@@ -730,4 +835,10 @@
|
|
return MathHelper.floor_float(f * 14.0F) + (i > 0 ? 1 : 0);
|
|
}
|
|
}
|
|
+
|
|
+ // Spigot start
|
|
+ public boolean areItemStacksEqual(ItemStack is1, ItemStack is2) {
|
|
+ return tickCount % 20 == 0 ? ItemStack.areItemStacksEqual(is1, is2) : ItemStack.fastMatches(is1, is2);
|
|
+ }
|
|
+ // Spigot
|
|
}
|