--- a/net/minecraft/server/TileEntityHopper.java +++ b/net/minecraft/server/TileEntityHopper.java @@ -7,12 +7,46 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; +// CraftBukkit start +import org.bukkit.craftbukkit.entity.CraftHumanEntity; +import org.bukkit.craftbukkit.inventory.CraftItemStack; +import org.bukkit.entity.HumanEntity; +import org.bukkit.event.inventory.InventoryMoveItemEvent; +import org.bukkit.event.inventory.InventoryPickupItemEvent; +import org.bukkit.inventory.Inventory; +// CraftBukkit end + public class TileEntityHopper extends TileEntityLootable implements IHopper, ITickable { private NonNullList items; private int f; private long j; + // CraftBukkit start - add fields and methods + public List transaction = new java.util.ArrayList(); + private int maxStack = MAX_STACK; + + public List getContents() { + return this.items; + } + + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + public List getViewers() { + return transaction; + } + + public void setMaxStackSize(int size) { + maxStack = size; + } + // CraftBukkit end + public TileEntityHopper() { super(TileEntityTypes.HOPPER); this.items = NonNullList.a(5, ItemStack.a); @@ -72,7 +106,7 @@ } public int getMaxStackSize() { - return 64; + return maxStack; // CraftBukkit } public void Y_() { @@ -165,10 +199,35 @@ for (int i = 0; i < this.getSize(); ++i) { if (!this.getItem(i).isEmpty()) { ItemStack itemstack = this.getItem(i).cloneItemStack(); - ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); + // ItemStack itemstack1 = addItem(this, iinventory, this.splitStack(i, 1), enumdirection); + + // CraftBukkit start - Call event when pushing items into other inventories + CraftItemStack oitemstack = CraftItemStack.asCraftMirror(this.splitStack(i, 1)); + + Inventory destinationInventory; + // Have to special case large chests as they work oddly + if (iinventory instanceof InventoryLargeChest) { + destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { + destinationInventory = iinventory.getOwner().getInventory(); + } + + InventoryMoveItemEvent event = new InventoryMoveItemEvent(this.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); + this.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + this.setItem(i, itemstack); + this.setCooldown(8); // Delay hopper checks + return false; + } + ItemStack itemstack1 = addItem(this, iinventory, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); if (itemstack1.isEmpty()) { - iinventory.update(); + if (event.getItem().equals(oitemstack)) { + iinventory.update(); + } else { + this.setItem(i, itemstack); + } + // CraftBukkit end return true; } @@ -290,10 +349,41 @@ if (!itemstack.isEmpty() && b(iinventory, itemstack, i, enumdirection)) { ItemStack itemstack1 = itemstack.cloneItemStack(); - ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // ItemStack itemstack2 = addItem(iinventory, ihopper, iinventory.splitStack(i, 1), (EnumDirection) null); + // CraftBukkit start - Call event on collection of items from inventories into the hopper + CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, 1)); + + Inventory sourceInventory; + // Have to special case large chests as they work oddly + if (iinventory instanceof InventoryLargeChest) { + sourceInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory); + } else { + sourceInventory = iinventory.getOwner().getInventory(); + } + + InventoryMoveItemEvent event = new InventoryMoveItemEvent(sourceInventory, oitemstack.clone(), ihopper.getOwner().getInventory(), false); + + ihopper.getWorld().getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + iinventory.setItem(i, itemstack1); + + if (ihopper instanceof TileEntityHopper) { + ((TileEntityHopper) ihopper).setCooldown(8); // Delay hopper checks + } else if (ihopper instanceof EntityMinecartHopper) { + ((EntityMinecartHopper) ihopper).setCooldown(4); // Delay hopper minecart checks + } + + return false; + } + ItemStack itemstack2 = addItem(iinventory, ihopper, CraftItemStack.asNMSCopy(event.getItem()), null); if (itemstack2.isEmpty()) { - iinventory.update(); + if (event.getItem().equals(oitemstack)) { + iinventory.update(); + } else { + iinventory.setItem(i, itemstack1); + } + // CraftBukkit end return true; } @@ -305,6 +395,13 @@ public static boolean a(IInventory iinventory, EntityItem entityitem) { boolean flag = false; + // CraftBukkit start + InventoryPickupItemEvent event = new InventoryPickupItemEvent(iinventory.getOwner().getInventory(), (org.bukkit.entity.Item) entityitem.getBukkitEntity()); + entityitem.world.getServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + // CraftBukkit end ItemStack itemstack = entityitem.getItemStack().cloneItemStack(); ItemStack itemstack1 = addItem((IInventory) null, iinventory, itemstack, (EnumDirection) null);