From b07f28c30ce3b45649b3f7c0847095dfe3f72690 Mon Sep 17 00:00:00 2001 From: SquidDev Date: Tue, 9 May 2017 00:41:20 +0100 Subject: [PATCH] Replace most inventory handling code with IItemHandlers - Make InventoryUtil deal with item handlers instead. This significantly simplifies the implementation, the interface now does most of the hard work. - Add InvWrapper item handlers to printers, disk drives and turtles - Add IItemHandlerModifiable accessor to ITurtleAccess - Migrate all other inventory code (mostly turtle commands) to use item handlers instead. --- .../api/turtle/ITurtleAccess.java | 13 + .../peripheral/diskdrive/TileDiskDrive.java | 35 ++- .../peripheral/printer/TilePrinter.java | 51 +++- .../shared/pocket/apis/PocketAPI.java | 5 +- .../shared/turtle/blocks/TileTurtle.java | 29 ++ .../shared/turtle/core/TurtleBrain.java | 8 + .../turtle/core/TurtleCraftCommand.java | 2 +- .../shared/turtle/core/TurtleDropCommand.java | 9 +- .../turtle/core/TurtleEquipCommand.java | 7 +- .../turtle/core/TurtlePlaceCommand.java | 2 +- .../shared/turtle/core/TurtlePlayer.java | 2 +- .../turtle/core/TurtleRefuelCommand.java | 6 +- .../shared/turtle/core/TurtleSuckCommand.java | 11 +- .../turtle/core/TurtleTransferToCommand.java | 6 +- .../shared/turtle/upgrades/TurtleTool.java | 7 +- .../shared/util/InventoryUtil.java | 280 +++++------------- 16 files changed, 230 insertions(+), 243 deletions(-) diff --git a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java index 0b00b6945..42a51690b 100644 --- a/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java +++ b/src/main/java/dan200/computercraft/api/turtle/ITurtleAccess.java @@ -15,6 +15,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import javax.annotation.Nullable; @@ -138,10 +139,22 @@ public interface ITurtleAccess * Get the inventory of this turtle * * @return This turtle's inventory + * @see #getItemHandler() */ @Nonnull IInventory getInventory(); + /** + * Get the inventory of this turtle as an {@link IItemHandlerModifiable}. + * + * @return This turtle's inventory + * @see #getInventory() + * @see IItemHandlerModifiable + * @see net.minecraftforge.items.CapabilityItemHandler#ITEM_HANDLER_CAPABILITY + */ + @Nonnull + IItemHandlerModifiable getItemHandler(); + /** * Determine whether this turtle will require fuel when performing actions. * diff --git a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java index 7bad34116..093825132 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/diskdrive/TileDiskDrive.java @@ -22,16 +22,27 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.*; -import net.minecraft.util.math.*; -import net.minecraft.util.text.*; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.EnumHand; +import net.minecraft.util.ITickable; +import net.minecraft.util.SoundEvent; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.InvWrapper; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.HashMap; import java.util.Map; import java.util.Set; +import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + public class TileDiskDrive extends TilePeripheralBase implements IInventory, ITickable { @@ -50,6 +61,7 @@ private static class MountInfo private final Map m_computers; private ItemStack m_diskStack; + private final IItemHandlerModifiable m_itemHandler = new InvWrapper( this ); private IMount m_diskMount; private boolean m_recordQueued; @@ -681,4 +693,21 @@ private void stopRecord() { ComputerCraft.playRecord( null, null, worldObj, getPos() ); } + + @Override + public boolean hasCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + return capability == ITEM_HANDLER_CAPABILITY || super.hasCapability( capability, facing ); + } + + @Nonnull + @Override + public T getCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + if( capability == ITEM_HANDLER_CAPABILITY ) + { + return ITEM_HANDLER_CAPABILITY.cast( m_itemHandler ); + } + return super.getCapability( capability, facing ); + } } diff --git a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java index f54d07425..47a91a7e5 100644 --- a/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java +++ b/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java @@ -23,13 +23,22 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.nbt.NBTTagList; -import net.minecraft.util.*; -import net.minecraft.util.math.*; -import net.minecraft.util.text.*; +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.text.ITextComponent; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextComponentTranslation; import net.minecraft.world.World; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.InvWrapper; +import net.minecraftforge.items.wrapper.SidedInvWrapper; import javax.annotation.Nonnull; +import javax.annotation.Nullable; + +import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; public class TilePrinter extends TilePeripheralBase implements IInventory, ISidedInventory @@ -43,6 +52,9 @@ public class TilePrinter extends TilePeripheralBase // Members private final ItemStack[] m_inventory; + private final IItemHandlerModifiable m_itemHandlerAll = new InvWrapper( this ); + private IItemHandlerModifiable[] m_itemHandlerSides; + private final Terminal m_page; private String m_pageTitle; private boolean m_printing; @@ -532,7 +544,7 @@ private boolean outputPage() ItemStack stack = ItemPrintout.createSingleFromTitleAndText( m_pageTitle, lines, colours ); synchronized( m_inventory ) { - ItemStack remainder = InventoryUtil.storeItems( stack, this, 7, 6, 7 ); + ItemStack remainder = InventoryUtil.storeItems( stack, m_itemHandlerAll, 7, 6, 7 ); if( remainder == null ) { m_printing = false; @@ -596,4 +608,35 @@ private void updateAnim() setAnim( anim ); } } + + @Override + public boolean hasCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + return capability == ITEM_HANDLER_CAPABILITY || super.hasCapability( capability, facing ); + } + + @Nonnull + @Override + public T getCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + if( capability == ITEM_HANDLER_CAPABILITY ) + { + if( facing == null ) + { + return ITEM_HANDLER_CAPABILITY.cast( m_itemHandlerAll ); + } + else + { + IItemHandlerModifiable[] handlers = m_itemHandlerSides; + if( handlers == null ) handlers = m_itemHandlerSides = new IItemHandlerModifiable[ 6 ]; + + int i = facing.ordinal(); + IItemHandlerModifiable handler = handlers[ i ]; + if( handler == null ) handler = handlers[ i ] = new SidedInvWrapper( this, facing ); + + return ITEM_HANDLER_CAPABILITY.cast( handler ); + } + } + return super.getCapability( capability, facing ); + } } diff --git a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java index 6b8576db0..11b024642 100644 --- a/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java +++ b/src/main/java/dan200/computercraft/shared/pocket/apis/PocketAPI.java @@ -18,6 +18,7 @@ import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.item.ItemStack; +import net.minecraftforge.items.wrapper.PlayerMainInvWrapper; import javax.annotation.Nonnull; @@ -100,7 +101,7 @@ public Object[] execute() throws LuaException ItemStack stack = previousUpgrade.getCraftingItem(); if( stack != null ) { - stack = InventoryUtil.storeItems( stack, inventory, 0, 36, inventory.currentItem ); + stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.currentItem ); if( stack != null ) { WorldUtil.dropItemStack( stack, player.worldObj, player.posX, player.posY, player.posZ ); @@ -139,7 +140,7 @@ public Object[] execute() throws LuaException ItemStack stack = previousUpgrade.getCraftingItem(); if( stack != null ) { - stack = InventoryUtil.storeItems( stack, inventory, 0, 36, inventory.currentItem ); + stack = InventoryUtil.storeItems( stack, new PlayerMainInvWrapper( inventory ), inventory.currentItem ); if( stack != null ) { WorldUtil.dropItemStack( stack, player.worldObj, player.posX, player.posY, player.posZ ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java index 09c80c0b9..15cda06af 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java +++ b/src/main/java/dan200/computercraft/shared/turtle/blocks/TileTurtle.java @@ -40,11 +40,17 @@ import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextComponentTranslation; +import net.minecraftforge.common.capabilities.Capability; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.items.IItemHandlerModifiable; +import net.minecraftforge.items.wrapper.InvWrapper; import javax.annotation.Nonnull; +import javax.annotation.Nullable; import java.util.List; +import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY; + public class TileTurtle extends TileComputerBase implements ITurtleTile, IInventory, ITickable { @@ -65,6 +71,7 @@ enum MoveState private ItemStack[] m_inventory; private ItemStack[] m_previousInventory; + private final IItemHandlerModifiable m_itemHandler = new InvWrapper( this ); private boolean m_inventoryChanged; private TurtleBrain m_brain; private MoveState m_moveState; @@ -714,4 +721,26 @@ public void transferStateFrom( TileTurtle copy ) m_brain.setOwner( this ); copy.m_moveState = MoveState.MOVED; } + + public IItemHandlerModifiable getItemHandler() + { + return m_itemHandler; + } + + @Override + public boolean hasCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + return capability == ITEM_HANDLER_CAPABILITY || super.hasCapability( capability, facing ); + } + + @Nonnull + @Override + public T getCapability( @Nonnull Capability capability, @Nullable EnumFacing facing ) + { + if( capability == ITEM_HANDLER_CAPABILITY ) + { + return ITEM_HANDLER_CAPABILITY.cast( m_itemHandler ); + } + return super.getCapability( capability, facing ); + } } diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java index 594a51cc3..129c6163c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleBrain.java @@ -34,6 +34,7 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraftforge.common.util.Constants; +import net.minecraftforge.items.IItemHandlerModifiable; import javax.annotation.Nonnull; import java.lang.ref.WeakReference; @@ -649,6 +650,13 @@ public IInventory getInventory() return m_owner; } + @Nonnull + @Override + public IItemHandlerModifiable getItemHandler() + { + return m_owner.getItemHandler(); + } + @Override public boolean isFuelNeeded() { diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java index d358db525..846b63c3d 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleCraftCommand.java @@ -40,7 +40,7 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) // Store the results for( ItemStack stack : results ) { - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { // Drop the remainder diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java index 892d522c1..5c47e20f0 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleDropCommand.java @@ -17,6 +17,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; @@ -46,7 +47,7 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) EnumFacing direction = m_direction.toWorldDir( turtle ); // Get things to drop - ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); if( stack == null ) { return TurtleCommandResult.failure( "No items to drop" ); @@ -58,15 +59,15 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) BlockPos newPosition = oldPosition.offset( direction ); EnumFacing side = direction.getOpposite(); - IInventory inventory = InventoryUtil.getInventory( world, newPosition, side ); + IItemHandler inventory = InventoryUtil.getInventory( world, newPosition, side ); if( inventory != null ) { // Drop the item into the inventory - ItemStack remainder = InventoryUtil.storeItems( stack, inventory, side ); + ItemStack remainder = InventoryUtil.storeItems( stack, inventory ); if( remainder != null ) { // Put the remainder back in the turtle - InventoryUtil.storeItems( remainder, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot() ); } // Return true if we stored anything diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java index 966b24c56..7ecb08cbc 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleEquipCommand.java @@ -14,6 +14,7 @@ import net.minecraft.inventory.IInventory; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; @@ -33,7 +34,7 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) // Determine the upgrade to equipLeft ITurtleUpgrade newUpgrade; ItemStack newUpgradeStack; - IInventory inventory = turtle.getInventory(); + IItemHandler inventory = turtle.getItemHandler(); ItemStack selectedStack = inventory.getStackInSlot( turtle.getSelectedSlot() ); if( selectedStack != null ) { @@ -68,19 +69,17 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Consume new upgrades item InventoryUtil.takeItems( 1, inventory, turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); - inventory.markDirty(); } if( oldUpgradeStack != null ) { // Store old upgrades item - ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, inventory, 0, inventory.getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( oldUpgradeStack, inventory, turtle.getSelectedSlot() ); if( remainder != null ) { // If there's no room for the items, drop them BlockPos position = turtle.getPosition(); WorldUtil.dropItemStack( remainder, turtle.getWorld(), position, turtle.getDirection() ); } - inventory.markDirty(); } turtle.setUpgrade( m_side, newUpgrade ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java index 4d02774d1..8420ca0b6 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlaceCommand.java @@ -227,7 +227,7 @@ private static ItemStack deployOnEntity( ItemStack stack, final ITurtleAccess tu @Override public void consumeDrop( Entity entity, ItemStack drop ) { - ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { WorldUtil.dropItemStack( remainder, world, position, turtle.getDirection().getOpposite() ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java index 25fb5b7a1..ecbc5f095 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtlePlayer.java @@ -54,7 +54,7 @@ public ItemStack unloadInventory( ITurtleAccess turtle ) ItemStack stack = inventory.getStackInSlot( i ); if( stack != null ) { - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { WorldUtil.dropItemStack( remainder, turtle.getWorld(), dropPosition, dropDirection ); diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java index 0ade611a2..04974f681 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleRefuelCommand.java @@ -42,14 +42,14 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Otherwise, refuel for real // Remove items from inventory - ItemStack stack = InventoryUtil.takeItems( m_limit, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + ItemStack stack = InventoryUtil.takeItems( m_limit, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); if( stack != null ) { TurtleCommandResult result = refuel( turtle, stack, false ); if( !result.isSuccess() ) { // If the items weren't burnt, put them back - InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); } return result; } @@ -83,7 +83,7 @@ private TurtleCommandResult refuel( ITurtleAccess turtle, ItemStack stack, boole // Store the replacement item in the inventory if( replacementStack != null ) { - InventoryUtil.storeItems( replacementStack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + InventoryUtil.storeItems( replacementStack, turtle.getItemHandler(), turtle.getSelectedSlot() ); } // Animate diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java index 2d5271647..cca4e7b5f 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleSuckCommand.java @@ -20,6 +20,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.EnumFacing; import net.minecraft.world.World; +import net.minecraftforge.items.IItemHandler; import javax.annotation.Nonnull; import java.util.List; @@ -55,19 +56,19 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) BlockPos newPosition = WorldUtil.moveCoords( oldPosition, direction ); EnumFacing side = direction.getOpposite(); - IInventory inventory = InventoryUtil.getInventory( world, newPosition, side ); + IItemHandler inventory = InventoryUtil.getInventory( world, newPosition, side ); if( inventory != null ) { // Take from inventory of thing in front - ItemStack stack = InventoryUtil.takeItems( m_quantity, inventory, side ); + ItemStack stack = InventoryUtil.takeItems( m_quantity, inventory ); if( stack != null ) { // Try to place into the turtle - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { // Put the remainder back in the inventory - InventoryUtil.storeItems( remainder, inventory, side ); + InventoryUtil.storeItems( remainder, inventory ); } // Return true if we consumed anything @@ -115,7 +116,7 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) storeStack = stack; leaveStack = null; } - ItemStack remainder = InventoryUtil.storeItems( storeStack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( storeStack, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != storeStack ) { storedItems = true; diff --git a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java index 37bf17ee1..c8f658db3 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java +++ b/src/main/java/dan200/computercraft/shared/turtle/core/TurtleTransferToCommand.java @@ -31,7 +31,7 @@ public TurtleTransferToCommand( int slot, int limit ) public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) { // Take stack - ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + ItemStack stack = InventoryUtil.takeItems( m_quantity, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); if( stack == null ) { turtle.playAnimation( TurtleAnimation.Wait ); @@ -39,11 +39,11 @@ public TurtleCommandResult execute( @Nonnull ITurtleAccess turtle ) } // Store stack - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), m_slot, 1, m_slot ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), m_slot, 1, m_slot ); if( remainder != null ) { // Put the remainder back - InventoryUtil.storeItems( remainder, turtle.getInventory(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); + InventoryUtil.storeItems( remainder, turtle.getItemHandler(), turtle.getSelectedSlot(), 1, turtle.getSelectedSlot() ); } // Return true if we moved anything diff --git a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java index 787a8532a..7cb93394c 100644 --- a/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java +++ b/src/main/java/dan200/computercraft/shared/turtle/upgrades/TurtleTool.java @@ -36,6 +36,7 @@ import javax.annotation.Nonnull; import javax.vecmath.Matrix4f; +import java.util.List; public class TurtleTool implements ITurtleUpgrade { @@ -180,7 +181,7 @@ private TurtleCommandResult attack( final ITurtleAccess turtle, EnumFacing direc @Override public void consumeDrop( Entity entity, ItemStack drop ) { - ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( drop, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { WorldUtil.dropItemStack( remainder, world, position, turtle.getDirection().getOpposite() ); @@ -261,12 +262,12 @@ private TurtleCommandResult dig( ITurtleAccess turtle, EnumFacing direction ) // Consume the items the block drops if( canHarvestBlock( world, newPosition ) ) { - java.util.List items = getBlockDropped( world, newPosition ); + List items = getBlockDropped( world, newPosition ); if( items != null && items.size() > 0 ) { for( ItemStack stack : items ) { - ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getInventory(), 0, turtle.getInventory().getSizeInventory(), turtle.getSelectedSlot() ); + ItemStack remainder = InventoryUtil.storeItems( stack, turtle.getItemHandler(), turtle.getSelectedSlot() ); if( remainder != null ) { // If there's no room for the items, drop them diff --git a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java index 5e37ef95c..4a76ae806 100644 --- a/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java +++ b/src/main/java/dan200/computercraft/shared/util/InventoryUtil.java @@ -6,19 +6,20 @@ package dan200.computercraft.shared.util; -import net.minecraft.block.Block; import net.minecraft.entity.Entity; -import net.minecraft.init.Blocks; import net.minecraft.inventory.IInventory; import net.minecraft.inventory.ISidedInventory; -import net.minecraft.inventory.InventoryLargeChest; import net.minecraft.item.ItemStack; import net.minecraft.tileentity.TileEntity; -import net.minecraft.util.math.BlockPos; import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.ILockableContainer; import net.minecraft.world.World; +import net.minecraftforge.items.CapabilityItemHandler; +import net.minecraftforge.items.IItemHandler; +import net.minecraftforge.items.ItemHandlerHelper; +import net.minecraftforge.items.wrapper.InvWrapper; +import net.minecraftforge.items.wrapper.SidedInvWrapper; import org.apache.commons.lang3.tuple.Pair; public class InventoryUtil @@ -27,35 +28,12 @@ public class InventoryUtil public static boolean areItemsEqual( ItemStack a, ItemStack b ) { - if( areItemsStackable( a, b ) ) - { - if( a == null || a.stackSize == b.stackSize ) - { - return true; - } - } - return false; + return a == b || ItemStack.areItemStacksEqual( a, b ); } public static boolean areItemsStackable( ItemStack a, ItemStack b ) { - if( a == b ) - { - return true; - } - - if( a != null && b != null && a.getItem() == b.getItem() ) - { - if( a.getItemDamage() == b.getItemDamage() ) - { - if( (a.getTagCompound() == null && b.getTagCompound() == null) || - (a.getTagCompound() != null && b.getTagCompound() != null && a.getTagCompound().equals( b.getTagCompound() ) ) ) - { - return true; - } - } - } - return false; + return a == b || ItemHandlerHelper.canItemStacksStack( a, b ); } public static ItemStack copyItem( ItemStack a ) @@ -69,40 +47,28 @@ public static ItemStack copyItem( ItemStack a ) // Methods for finding inventories: - public static IInventory getInventory( World world, BlockPos pos, EnumFacing side ) + public static IItemHandler getInventory( World world, BlockPos pos, EnumFacing side ) { // Look for tile with inventory int y = pos.getY(); if( y >= 0 && y < world.getHeight() ) { TileEntity tileEntity = world.getTileEntity( pos ); - if( tileEntity != null && tileEntity instanceof IInventory ) + if( tileEntity != null ) { - // Special case code for double chests - Block block = world.getBlockState( pos ).getBlock(); - if( block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST ) + IItemHandler itemHandler = tileEntity.getCapability( CapabilityItemHandler.ITEM_HANDLER_CAPABILITY, side ); + if( itemHandler != null ) { - // Check if it's a double chest, and return a combined inventory if so - if( world.getBlockState( pos.west() ).getBlock() == block ) - { - return new InventoryLargeChest( "Large chest", (ILockableContainer)world.getTileEntity( pos.west() ), (ILockableContainer)tileEntity ); - } - if( world.getBlockState( pos.east() ).getBlock() == block ) - { - return new InventoryLargeChest( "Large chest", (ILockableContainer)tileEntity, (ILockableContainer)world.getTileEntity( pos.east() ) ); - } - if( world.getBlockState( pos.north() ).getBlock() == block ) - { - return new InventoryLargeChest( "Large chest", (ILockableContainer)world.getTileEntity( pos.north() ), (ILockableContainer)tileEntity ); - } - if( world.getBlockState( pos.south() ).getBlock() == block ) - { - return new InventoryLargeChest( "Large chest", (ILockableContainer)tileEntity, (ILockableContainer)world.getTileEntity( pos.south() ) ); - } + return itemHandler; + } + else if( side != null && tileEntity instanceof ISidedInventory ) + { + return new SidedInvWrapper( (ISidedInventory) tileEntity, side ); + } + else if( tileEntity instanceof IInventory ) + { + return new InvWrapper( (IInventory) tileEntity ); } - - // Otherwise, get tile inventory - return (IInventory)tileEntity; } } @@ -122,60 +88,52 @@ public static IInventory getInventory( World world, BlockPos pos, EnumFacing sid Entity entity = hit.getKey(); if( entity instanceof IInventory ) { - return (IInventory) entity; + return new InvWrapper( (IInventory) entity ); } } return null; } - + // Methods for placing into inventories: - - public static ItemStack storeItems( ItemStack itemstack, IInventory inventory, int start, int range, int begin ) + + public static ItemStack storeItems( ItemStack itemstack, IItemHandler inventory, int start, int range, int begin ) { int[] slots = makeSlotList( start, range, begin ); - return storeItems( itemstack, inventory, slots, null ); + return storeItems( itemstack, inventory, slots ); } - public static ItemStack storeItems( ItemStack itemstack, IInventory inventory, EnumFacing side ) + public static ItemStack storeItems( ItemStack itemstack, IItemHandler inventory, int begin ) { - // Try ISidedInventory - if( inventory instanceof ISidedInventory ) - { - // Place into ISidedInventory - ISidedInventory sidedInventory = (ISidedInventory)inventory; - int[] slots = sidedInventory.getSlotsForFace( side ); - return storeItems( itemstack, inventory, slots, side ); - } - - // No ISidedInventory, store into any slot - int[] slots = makeSlotList( 0, inventory.getSizeInventory(), 0 ); // TODO: optimise this out? - return storeItems( itemstack, inventory, slots, side ); + int[] slots = makeSlotList( 0, inventory.getSlots(), begin ); + return storeItems( itemstack, inventory, slots ); } - + + public static ItemStack storeItems( ItemStack itemstack, IItemHandler inventory ) + { + int[] slots = makeSlotList( 0, inventory.getSlots(), 0 ); // TODO: optimise this out? + return storeItems( itemstack, inventory, slots ); + } + // Methods for taking out of inventories - - public static ItemStack takeItems( int count, IInventory inventory, int start, int range, int begin ) + + public static ItemStack takeItems( int count, IItemHandler inventory, int start, int range, int begin ) { int[] slots = makeSlotList( start, range, begin ); - return takeItems( count, inventory, slots, null ); + return takeItems( count, inventory, slots ); } - - public static ItemStack takeItems( int count, IInventory inventory, EnumFacing side ) - { - // Try ISidedInventory - if( inventory instanceof ISidedInventory ) - { - // Place into ISidedInventory - ISidedInventory sidedInventory = (ISidedInventory)inventory; - int[] slots = sidedInventory.getSlotsForFace( side ); - return takeItems( count, inventory, slots, side ); - } - // No ISidedInventory, store into any slot - int[] slots = makeSlotList( 0, inventory.getSizeInventory(), 0 ); - return takeItems( count, inventory, slots, side ); + public static ItemStack takeItems( int count, IItemHandler inventory, int begin ) + { + int[] slots = makeSlotList( 0, inventory.getSlots(), begin ); + return takeItems( count, inventory, slots ); } - + + public static ItemStack takeItems( int count, IItemHandler inventory ) + { + int[] slots = makeSlotList( 0, inventory.getSlots(), 0 ); + return takeItems( count, inventory, slots ); + } + // Private methods private static int[] makeSlotList( int start, int range, int begin ) @@ -184,16 +142,16 @@ private static int[] makeSlotList( int start, int range, int begin ) { return null; } - - int[] slots = new int[range]; - for( int n=0; n= remainder.stackSize ) - { - // Items fit completely in slot - inventory.setInventorySlotContents( slot, remainder ); - inventory.markDirty(); - return null; - } - else - { - // Items fit partially in slot - remainder = remainder.copy(); - inventory.setInventorySlotContents( slot, remainder.splitStack( space ) ); - } - } - else if( areItemsStackable( slotContents, remainder ) ) - { - // Slot is occupied, but matching - int space = Math.min( slotContents.getMaxStackSize(), inventory.getInventoryStackLimit() ) - slotContents.stackSize; - if( space >= remainder.stackSize ) - { - // Items fit completely in slot - slotContents.stackSize += remainder.stackSize; - inventory.setInventorySlotContents( slot, slotContents ); - inventory.markDirty(); - return null; - } - else if( space > 0 ) - { - // Items fit partially in slot - remainder = remainder.copy(); - remainder.stackSize -= space; - slotContents.stackSize += space; - inventory.setInventorySlotContents( slot, slotContents ); - } - } - } - } - - // If the output isn't the input, inform the change - if( remainder != stack ) - { - inventory.markDirty(); + if( remainder == null ) break; + remainder = inventory.insertItem( slot, remainder, false ); } return remainder; } - private static boolean canPlaceItemThroughFace( IInventory inventory, int slot, ItemStack itemstack, EnumFacing face ) - { - if( inventory.isItemValidForSlot( slot, itemstack ) ) - { - if( face != null && inventory instanceof ISidedInventory ) - { - ISidedInventory sided = (ISidedInventory)inventory; - return sided.canInsertItem( slot, itemstack, face ); - } - return true; - } - return false; - } - - private static ItemStack takeItems( int count, IInventory inventory, int[] slots, EnumFacing face ) + private static ItemStack takeItems( int count, IItemHandler inventory, int[] slots ) { if( slots == null ) { @@ -287,65 +184,30 @@ private static ItemStack takeItems( int count, IInventory inventory, int[] slots int countRemaining = count; for( int slot : slots ) { - if( countRemaining > 0 ) + if( countRemaining <= 0 ) break; + + ItemStack stack = inventory.getStackInSlot( slot ); + if( stack != null ) { - ItemStack stack = inventory.getStackInSlot( slot ); - if( stack != null && canTakeItemThroughFace( inventory, slot, stack, face ) ) + if( partialStack == null || areItemsStackable( stack, partialStack ) ) { - if( partialStack == null || areItemsStackable( stack, partialStack ) ) + ItemStack extracted = inventory.extractItem( slot, countRemaining, false ); + if( extracted != null ) { - // Found a matching thing - if( countRemaining >= stack.stackSize ) + countRemaining -= extracted.stackSize; + if( partialStack == null ) { - // Eat the thing whole - inventory.setInventorySlotContents( slot, null ); - if( partialStack == null ) - { - partialStack = stack; - countRemaining = Math.min( countRemaining, partialStack.getItem().getItemStackLimit( partialStack ) ) - stack.stackSize; - } - else - { - partialStack.stackSize += stack.stackSize; - countRemaining -= stack.stackSize; - } + partialStack = extracted; } else { - // Eat part of the thing - ItemStack splitStack = stack.splitStack( countRemaining ); - if( partialStack == null ) - { - partialStack = splitStack; - countRemaining = Math.min( countRemaining, partialStack.getItem().getItemStackLimit( partialStack ) ) - splitStack.stackSize; - } - else - { - partialStack.stackSize += splitStack.stackSize; - countRemaining -= splitStack.stackSize; - } + partialStack.stackSize += extracted.stackSize; } } } } } - // Return the final stack - if( partialStack != null ) - { - inventory.markDirty(); - return partialStack; - } - return null; - } - - private static boolean canTakeItemThroughFace( IInventory inventory, int slot, ItemStack itemstack, EnumFacing face ) - { - if( face != null && inventory instanceof ISidedInventory ) - { - ISidedInventory sided = (ISidedInventory)inventory; - return sided.canExtractItem( slot, itemstack, face ); - } - return true; + return partialStack; } }