--- a/net/minecraft/world/level/block/entity/TileEntityHopper.java +++ b/net/minecraft/world/level/block/entity/TileEntityHopper.java @@ -33,6 +33,18 @@ import net.minecraft.world.phys.shapes.OperatorBoolean; import net.minecraft.world.phys.shapes.VoxelShapes; +// CraftBukkit start +import net.minecraft.world.InventoryLargeChest; +import net.minecraft.world.entity.vehicle.EntityMinecartHopper; +import org.bukkit.Bukkit; +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 { public static final int MOVE_ITEM_SPEED = 8; @@ -41,6 +53,36 @@ private int cooldownTime; private long tickedGameTime; + // 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; + } + + @Override + public int getMaxStackSize() { + return maxStack; + } + + public void setMaxStackSize(int size) { + maxStack = size; + } + // CraftBukkit end + public TileEntityHopper(BlockPosition blockposition, IBlockData iblockdata) { super(TileEntityTypes.HOPPER, blockposition, iblockdata); this.items = NonNullList.a(5, ItemStack.EMPTY); @@ -115,7 +157,7 @@ boolean flag = false; if (!tileentityhopper.isEmpty()) { - flag = a(world, blockposition, iblockdata, (IInventory) tileentityhopper); + flag = a(world, blockposition, iblockdata, (IInventory) tileentityhopper, tileentityhopper); // CraftBukkit } if (!tileentityhopper.i()) { @@ -149,7 +191,7 @@ return false; } - private static boolean a(World world, BlockPosition blockposition, IBlockData iblockdata, IInventory iinventory) { + private static boolean a(World world, BlockPosition blockposition, IBlockData iblockdata, IInventory iinventory, TileEntityHopper hopper) { // CraftBukkit IInventory iinventory1 = b(world, blockposition, iblockdata); if (iinventory1 == null) { @@ -163,7 +205,28 @@ for (int i = 0; i < iinventory.getSize(); ++i) { if (!iinventory.getItem(i).isEmpty()) { ItemStack itemstack = iinventory.getItem(i).cloneItemStack(); - ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.splitStack(i, 1), enumdirection); + // ItemStack itemstack1 = addItem(iinventory, iinventory1, iinventory.splitStack(i, 1), enumdirection); + + // CraftBukkit start - Call event when pushing items into other inventories + CraftItemStack oitemstack = CraftItemStack.asCraftMirror(iinventory.splitStack(i, 1)); + + Inventory destinationInventory; + // Have to special case large chests as they work oddly + if (iinventory1 instanceof InventoryLargeChest) { + destinationInventory = new org.bukkit.craftbukkit.inventory.CraftInventoryDoubleChest((InventoryLargeChest) iinventory1); + } else { + destinationInventory = iinventory1.getOwner().getInventory(); + } + + InventoryMoveItemEvent event = new InventoryMoveItemEvent(iinventory.getOwner().getInventory(), oitemstack.clone(), destinationInventory, true); + world.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + hopper.setItem(i, itemstack); + hopper.setCooldown(8); // Delay hopper checks + return false; + } + ItemStack itemstack1 = addItem(iinventory, iinventory1, CraftItemStack.asNMSCopy(event.getItem()), enumdirection); + // CraftBukkit end if (itemstack1.isEmpty()) { iinventory1.update(); @@ -228,7 +291,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); + + Bukkit.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(); @@ -243,6 +333,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.level.getCraftServer().getPluginManager().callEvent(event); + if (event.isCancelled()) { + return false; + } + // CraftBukkit end ItemStack itemstack = entityitem.getItemStack().cloneItemStack(); ItemStack itemstack1 = addItem((IInventory) null, iinventory, itemstack, (EnumDirection) null);