diff --git a/patches/minecraft/net/minecraft/tileentity/TileEntityHopper.java.patch b/patches/minecraft/net/minecraft/tileentity/TileEntityHopper.java.patch index 7f1500896..8819a4104 100644 --- a/patches/minecraft/net/minecraft/tileentity/TileEntityHopper.java.patch +++ b/patches/minecraft/net/minecraft/tileentity/TileEntityHopper.java.patch @@ -43,3 +43,10 @@ { TileEntity tileentity = p_145893_0_.func_175625_s(blockpos); +@@ -589,4 +599,6 @@ + { + return this.field_145900_a; + } ++ ++ public long getLastUpdateTime() { return field_190578_g; } // Forge + } diff --git a/src/main/java/net/minecraftforge/items/VanillaHopperItemHandler.java b/src/main/java/net/minecraftforge/items/VanillaHopperItemHandler.java index 3a758b88d..a2a835b7d 100644 --- a/src/main/java/net/minecraftforge/items/VanillaHopperItemHandler.java +++ b/src/main/java/net/minecraftforge/items/VanillaHopperItemHandler.java @@ -39,17 +39,31 @@ public class VanillaHopperItemHandler extends InvWrapper @Nonnull public ItemStack insertItem(int slot, @Nonnull ItemStack stack, boolean simulate) { - if (stack.func_190926_b()) - return ItemStack.field_190927_a; - if (simulate || !hopper.mayTransfer()) - return super.insertItem(slot, stack, simulate); - - int curStackSize = stack.func_190916_E(); - ItemStack itemStack = super.insertItem(slot, stack, false); - if (itemStack.func_190926_b() || curStackSize != itemStack.func_190916_E()) + if (simulate) { - hopper.setTransferCooldown(8); + return super.insertItem(slot, stack, simulate); + } + else + { + boolean wasEmpty = getInv().func_191420_l(); + + int originalStackSize = stack.func_190916_E(); + stack = super.insertItem(slot, stack, simulate); + + if (wasEmpty && originalStackSize > stack.func_190916_E()) + { + if (!hopper.mayTransfer()) + { + // This cooldown is always set to 8 in vanilla with one exception: + // Hopper -> Hopper transfer sets this cooldown to 7 when this hopper + // has not been updated as recently as the one pushing items into it. + // This vanilla behavior is preserved by VanillaInventoryCodeHooks#insertStack, + // the cooldown is set properly by the hopper that is pushing items into this one. + hopper.setTransferCooldown(8); + } + } + + return stack; } - return itemStack; } } diff --git a/src/main/java/net/minecraftforge/items/VanillaInventoryCodeHooks.java b/src/main/java/net/minecraftforge/items/VanillaInventoryCodeHooks.java index 141496d40..0a91f5d17 100644 --- a/src/main/java/net/minecraftforge/items/VanillaInventoryCodeHooks.java +++ b/src/main/java/net/minecraftforge/items/VanillaInventoryCodeHooks.java @@ -19,6 +19,8 @@ package net.minecraftforge.items; +import javafx.util.Pair; +import net.minecraft.block.Block; import net.minecraft.block.BlockDropper; import net.minecraft.block.BlockHopper; import net.minecraft.item.ItemStack; @@ -26,23 +28,27 @@ import net.minecraft.tileentity.IHopper; import net.minecraft.tileentity.TileEntity; import net.minecraft.tileentity.TileEntityDispenser; import net.minecraft.tileentity.TileEntityHopper; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; import net.minecraft.world.World; import javax.annotation.Nonnull; +import javax.annotation.Nullable; public class VanillaInventoryCodeHooks { - //Return: Null if we did nothing {no IItemHandler}, True if we moved an item, False if we moved no items + /** + * Copied from TileEntityHopper#captureDroppedItems and added capability support + * @return Null if we did nothing {no IItemHandler}, True if we moved an item, False if we moved no items + */ public static Boolean extractHook(IHopper dest) { - TileEntity tileEntity = dest.getWorld().getTileEntity(new BlockPos(dest.getXPos(), dest.getYPos() + 1, dest.getZPos())); - - if (tileEntity == null || !tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN)) + Pair itemHandlerResult = getItemHandler(dest, EnumFacing.UP); + if (itemHandlerResult == null) return null; - IItemHandler handler = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, EnumFacing.DOWN); + IItemHandler handler = itemHandlerResult.getKey(); for (int i = 0; i < handler.getSlots(); i++) { @@ -72,68 +78,203 @@ public class VanillaInventoryCodeHooks return false; } + /** + * Copied from BlockDropper#dispense and added capability support + */ public static boolean dropperInsertHook(World world, BlockPos pos, TileEntityDispenser dropper, int slot, @Nonnull ItemStack stack) { EnumFacing enumfacing = world.getBlockState(pos).getValue(BlockDropper.FACING); - BlockPos offsetPos = pos.offset(enumfacing); - TileEntity tileEntity = world.getTileEntity(offsetPos); - if (tileEntity == null) - return true; - if (!tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, enumfacing.getOpposite())) - return true; - - IItemHandler capability = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, enumfacing.getOpposite()); - - ItemStack result = ItemHandlerHelper.insertItem(capability, ItemHandlerHelper.copyStackWithSize(stack, 1), false); - - if (result.func_190926_b()) + BlockPos blockpos = pos.offset(enumfacing); + Pair destinationResult = getItemHandler(world, (double) blockpos.getX(), (double) blockpos.getY(), (double) blockpos.getZ(), enumfacing.getOpposite()); + if (destinationResult == null) { - result = stack.copy(); - result.func_190918_g(1); + return true; } else { - result = stack.copy(); + IItemHandler itemHandler = destinationResult.getKey(); + Object destination = destinationResult.getValue(); + ItemStack dispensedStack = stack.copy().splitStack(1); + ItemStack remainder = putStackInInventoryAllSlots(dropper, destination, itemHandler, dispensedStack); + + if (remainder.func_190926_b()) + { + remainder = stack.copy(); + remainder.func_190918_g(1); + } + else + { + remainder = stack.copy(); + } + + dropper.setInventorySlotContents(slot, remainder); + return false; } - dropper.setInventorySlotContents(slot, result); - dropper.markDirty(); - return false; } + /** + * Copied from TileEntityHopper#transferItemsOut and added capability support + */ public static boolean insertHook(TileEntityHopper hopper) { - return insertHook(hopper, BlockHopper.getFacing(hopper.getBlockMetadata())); + EnumFacing hopperFacing = BlockHopper.getFacing(hopper.getBlockMetadata()); + Pair destinationResult = getItemHandler(hopper, hopperFacing); + if (destinationResult == null) + { + return false; + } + else + { + IItemHandler itemHandler = destinationResult.getKey(); + Object destination = destinationResult.getValue(); + if (isFull(itemHandler)) + { + return false; + } + else + { + for (int i = 0; i < hopper.getSizeInventory(); ++i) + { + if (!hopper.getStackInSlot(i).func_190926_b()) + { + ItemStack originalSlotContents = hopper.getStackInSlot(i).copy(); + ItemStack insertStack = hopper.decrStackSize(i, 1); + ItemStack remainder = putStackInInventoryAllSlots(hopper, destination, itemHandler, insertStack); + + if (remainder.func_190926_b()) + { + return true; + } + + hopper.setInventorySlotContents(i, originalSlotContents); + } + } + + return false; + } + } } - public static boolean insertHook(IHopper hopper, EnumFacing facing) + private static ItemStack putStackInInventoryAllSlots(TileEntity source, Object destination, IItemHandler destInventory, ItemStack stack) { - TileEntity tileEntity = hopper.getWorld().getTileEntity( - new BlockPos(hopper.getXPos(), hopper.getYPos(), hopper.getZPos()).offset(facing)); - - if (tileEntity == null) - return false; - if (!tileEntity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite())) - return false; - - IItemHandler handler = tileEntity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, facing.getOpposite()); - - for (int i = 0; i < hopper.getSizeInventory(); i++) + for (int slot = 0; slot < destInventory.getSlots() && !stack.func_190926_b(); slot++) { - ItemStack stackInSlot = hopper.getStackInSlot(i); - if (!stackInSlot.func_190926_b()) + stack = insertStack(source, destination, destInventory, stack, slot); + } + return stack; + } + + /** + * Copied from TileEntityHopper#insertStack and added capability support + */ + private static ItemStack insertStack(TileEntity source, Object destination, IItemHandler destInventory, ItemStack stack, int slot) + { + ItemStack itemstack = destInventory.getStackInSlot(slot); + + if (destInventory.insertItem(slot, stack, true).func_190926_b()) + { + boolean insertedItem = false; + boolean inventoryWasEmpty = isEmpty(destInventory); + + if (itemstack.func_190926_b()) { - ItemStack insert = stackInSlot.copy(); - insert.func_190920_e(1); - ItemStack newStack = ItemHandlerHelper.insertItem(handler, insert, true); - if (newStack.func_190926_b()) + destInventory.insertItem(slot, stack, false); + stack = ItemStack.field_190927_a; + insertedItem = true; + } + else if (ItemHandlerHelper.canItemStacksStack(itemstack, stack)) + { + int originalSize = stack.func_190916_E(); + stack = destInventory.insertItem(slot, stack, false); + insertedItem = originalSize < stack.func_190916_E(); + } + + if (insertedItem) + { + if (inventoryWasEmpty && destination instanceof TileEntityHopper) { - ItemHandlerHelper.insertItem(handler, hopper.decrStackSize(i, 1), false); - hopper.markDirty(); - return true; + TileEntityHopper destinationHopper = (TileEntityHopper)destination; + + if (!destinationHopper.mayTransfer()) + { + int k = 0; + + if (source instanceof TileEntityHopper) + { + if (destinationHopper.getLastUpdateTime() >= ((TileEntityHopper) source).getLastUpdateTime()) + { + k = 1; + } + } + + destinationHopper.setTransferCooldown(8 - k); + } } } } + return stack; + } + + @Nullable + private static Pair getItemHandler(IHopper hopper, EnumFacing hopperFacing) + { + double x = hopper.getXPos() + (double) hopperFacing.getFrontOffsetX(); + double y = hopper.getYPos() + (double) hopperFacing.getFrontOffsetY(); + double z = hopper.getZPos() + (double) hopperFacing.getFrontOffsetZ(); + return getItemHandler(hopper.getWorld(), x, y, z, hopperFacing.getOpposite()); + } + + private static boolean isFull(IItemHandler itemHandler) + { + for (int slot = 0; slot < itemHandler.getSlots(); slot++) + { + ItemStack stackInSlot = itemHandler.getStackInSlot(slot); + if (stackInSlot.func_190926_b() || stackInSlot.func_190916_E() != stackInSlot.getMaxStackSize()) + { + return false; + } + } return true; } + + private static boolean isEmpty(IItemHandler itemHandler) + { + for (int slot = 0; slot < itemHandler.getSlots(); slot++) + { + ItemStack stackInSlot = itemHandler.getStackInSlot(slot); + if (stackInSlot.func_190916_E() > 0) + { + return false; + } + } + return true; + } + + @Nullable + public static Pair getItemHandler(World worldIn, double x, double y, double z, final EnumFacing side) + { + Pair destination = null; + int i = MathHelper.floor_double(x); + int j = MathHelper.floor_double(y); + int k = MathHelper.floor_double(z); + BlockPos blockpos = new BlockPos(i, j, k); + net.minecraft.block.state.IBlockState state = worldIn.getBlockState(blockpos); + Block block = state.getBlock(); + + if (block.hasTileEntity(state)) + { + TileEntity tileentity = worldIn.getTileEntity(blockpos); + if (tileentity != null) + { + if (tileentity.hasCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side)) + { + IItemHandler capability = tileentity.getCapability(CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side); + destination = new Pair(capability, tileentity); + } + } + } + + return destination; + } }