Proxy the current turtle's inventory

Previously we were just returning the current tile. However, if someone
was holding a reference to this inventory (such as a GUI), then it'd be
outdated and invalid once the turtle had moved.

This caused a couple of issues:
 - turtle_inventory events would not be fired when moving items in the
   turtle GUI.
 - As of 75e2845c01, turtles would no
   longer share their inventory state after moving. Thus, removing items
   from a GUI using an invalid inventory would move them from an old
   tile, duplicating the items.

Fixes #298, fixes #300
This commit is contained in:
SquidDev 2019-10-04 16:53:48 +01:00
parent 813e91073d
commit 418420523a
5 changed files with 156 additions and 16 deletions

View File

@ -6,7 +6,6 @@
package dan200.computercraft.shared.media.inventory;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.Container;
import net.minecraft.item.ItemStack;
@ -22,7 +21,7 @@ public class ContainerHeldItem extends Container
public ContainerHeldItem( EntityPlayer player, EnumHand hand )
{
m_hand = hand;
m_stack = InventoryUtil.copyItem( player.getHeldItem( hand ) );
m_stack = player.getHeldItem( hand ).copy();
}
@Nonnull

View File

@ -224,7 +224,7 @@ public void update()
m_inventoryChanged = false;
for( int n = 0; n < getSizeInventory(); n++ )
{
m_previousInventory.set( n, InventoryUtil.copyItem( getStackInSlot( n ) ) );
m_previousInventory.set( n, getStackInSlot( n ).copy() );
}
}
}
@ -268,7 +268,7 @@ public void readFromNBT( NBTTagCompound nbt )
if( slot < getSizeInventory() )
{
m_inventory.set( slot, new ItemStack( tag ) );
m_previousInventory.set( slot, InventoryUtil.copyItem( m_inventory.get( slot ) ) );
m_previousInventory.set( slot, m_inventory.get( slot ).copy() );
}
}

View File

@ -20,10 +20,7 @@
import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.util.Colour;
import dan200.computercraft.shared.util.ColourUtils;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import dan200.computercraft.shared.util.*;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.MoverType;
@ -40,6 +37,7 @@
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
import java.util.*;
@ -53,6 +51,9 @@ public class TurtleBrain implements ITurtleAccess
private ComputerProxy m_proxy;
private GameProfile m_owningPlayer;
private final IInventory m_inventory = (InventoryDelegate) () -> m_owner;
private final IItemHandlerModifiable m_inventoryWrapper = new InvWrapper( m_inventory );
private Queue<TurtleCommandQueueEntry> m_commandQueue = new ArrayDeque<>();
private int m_commandsIssued = 0;
@ -531,14 +532,14 @@ public void setSelectedSlot( int slot )
@Override
public IInventory getInventory()
{
return m_owner;
return m_inventory;
}
@Nonnull
@Override
public IItemHandlerModifiable getItemHandler()
{
return m_owner.getItemHandler();
return m_inventoryWrapper;
}
@Override

View File

@ -0,0 +1,146 @@
/*
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2019. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.util;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.util.text.ITextComponent;
import javax.annotation.Nonnull;
/**
* Provides a delegate over inventories.
*
* This may be used both on {@link net.minecraft.tileentity.TileEntity}s to redirect the inventory to another tile,
* and by other interfaces to have inventories which change their backing store.
*/
@FunctionalInterface
public interface InventoryDelegate extends IInventory
{
IInventory getInventory();
@Override
default int getSizeInventory()
{
return getInventory().getSizeInventory();
}
@Override
default boolean isEmpty()
{
return getInventory().isEmpty();
}
@Nonnull
@Override
default ItemStack getStackInSlot( int slot )
{
return getInventory().getStackInSlot( slot );
}
@Nonnull
@Override
default ItemStack decrStackSize( int slot, int count )
{
return getInventory().decrStackSize( slot, count );
}
@Nonnull
@Override
default ItemStack removeStackFromSlot( int slot )
{
return getInventory().removeStackFromSlot( slot );
}
@Override
default void setInventorySlotContents( int slot, ItemStack stack )
{
getInventory().setInventorySlotContents( slot, stack );
}
@Override
default int getInventoryStackLimit()
{
return getInventory().getInventoryStackLimit();
}
@Override
default void markDirty()
{
getInventory().markDirty();
}
@Override
default boolean isUsableByPlayer( @Nonnull EntityPlayer player )
{
return getInventory().isUsableByPlayer( player );
}
@Override
default void openInventory( @Nonnull EntityPlayer player )
{
getInventory().openInventory( player );
}
@Override
default void closeInventory( @Nonnull EntityPlayer player )
{
getInventory().closeInventory( player );
}
@Override
default boolean isItemValidForSlot( int slot, @Nonnull ItemStack stack )
{
return getInventory().isItemValidForSlot( slot, stack );
}
@Override
default int getField( int id )
{
return getInventory().getField( id );
}
@Override
default void setField( int id, int val )
{
getInventory().setField( id, val );
}
@Override
default int getFieldCount()
{
return getInventory().getFieldCount();
}
@Override
default void clear()
{
getInventory().clear();
}
@Nonnull
@Override
default String getName()
{
return getInventory().getName();
}
@Override
default boolean hasCustomName()
{
return getInventory().hasCustomName();
}
@Nonnull
@Override
default ITextComponent getDisplayName()
{
return getInventory().getDisplayName();
}
}

View File

@ -69,12 +69,6 @@ public static boolean areItemsSimilar( @Nonnull ItemStack a, @Nonnull ItemStack
return shareTagA.equals( shareTagB );
}
@Nonnull
public static ItemStack copyItem( @Nonnull ItemStack a )
{
return a.copy();
}
// Methods for finding inventories:
public static IItemHandler getInventory( World world, BlockPos pos, EnumFacing side )