--- a/net/minecraft/server/TileEntityHopper.java +++ b/net/minecraft/server/TileEntityHopper.java @@ -7,12 +7,51 @@ import java.util.stream.IntStream; 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<ItemStack> items; private int j; private long k; + // CraftBukkit start - add fields and methods + public List<HumanEntity> transaction = new java.util.ArrayList<HumanEntity>(); + private int maxStack = MAX_STACK; + + public List<ItemStack> getContents() { + return this.items; + } + + public void onOpen(CraftHumanEntity who) { + transaction.add(who); + } + + public void onClose(CraftHumanEntity who) { + transaction.remove(who); + } + + public List<HumanEntity> getViewers() { + return transaction; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + public void setMaxStackSize(int size) { + maxStack = size; + } + // CraftBukkit end + public TileEntityHopper() { super(TileEntityTypes.HOPPER); this.items = NonNullList.a(5, ItemStack.b); @@ -138,7 +177,28 @@ 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); + // CraftBukkit end if (itemstack1.isEmpty()) { iinventory.update(); @@ -203,7 +263,34 @@ 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); + // CraftBukkit end if (itemstack2.isEmpty()) { iinventory.update(); @@ -218,6 +305,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);