1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-01-12 02:10:30 +00:00

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

View File

@ -224,7 +224,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
m_inventoryChanged = false; m_inventoryChanged = false;
for( int n = 0; n < getSizeInventory(); n++ ) 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 class TileTurtle extends TileComputerBase implements ITurtleTile, Default
if( slot < getSizeInventory() ) if( slot < getSizeInventory() )
{ {
m_inventory.set( slot, new ItemStack( tag ) ); 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.blocks.TileComputerBase;
import dan200.computercraft.shared.computer.core.ComputerFamily; import dan200.computercraft.shared.computer.core.ComputerFamily;
import dan200.computercraft.shared.computer.core.ServerComputer; import dan200.computercraft.shared.computer.core.ServerComputer;
import dan200.computercraft.shared.turtle.blocks.TileTurtle; import dan200.computercraft.shared.turtle.blocks.TileTurtle;
import dan200.computercraft.shared.util.Colour; import dan200.computercraft.shared.util.*;
import dan200.computercraft.shared.util.ColourUtils;
import dan200.computercraft.shared.util.Holiday;
import dan200.computercraft.shared.util.HolidayUtil;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.MoverType; import net.minecraft.entity.MoverType;
@ -40,6 +37,7 @@ import net.minecraft.util.math.Vec3d;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants; import net.minecraftforge.common.util.Constants;
import net.minecraftforge.items.IItemHandlerModifiable; import net.minecraftforge.items.IItemHandlerModifiable;
import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import java.util.*; import java.util.*;
@ -53,6 +51,9 @@ public class TurtleBrain implements ITurtleAccess
private ComputerProxy m_proxy; private ComputerProxy m_proxy;
private GameProfile m_owningPlayer; 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 Queue<TurtleCommandQueueEntry> m_commandQueue = new ArrayDeque<>();
private int m_commandsIssued = 0; private int m_commandsIssued = 0;
@ -531,14 +532,14 @@ public class TurtleBrain implements ITurtleAccess
@Override @Override
public IInventory getInventory() public IInventory getInventory()
{ {
return m_owner; return m_inventory;
} }
@Nonnull @Nonnull
@Override @Override
public IItemHandlerModifiable getItemHandler() public IItemHandlerModifiable getItemHandler()
{ {
return m_owner.getItemHandler(); return m_inventoryWrapper;
} }
@Override @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 final class InventoryUtil
return shareTagA.equals( shareTagB ); return shareTagA.equals( shareTagB );
} }
@Nonnull
public static ItemStack copyItem( @Nonnull ItemStack a )
{
return a.copy();
}
// Methods for finding inventories: // Methods for finding inventories:
public static IItemHandler getInventory( World world, BlockPos pos, EnumFacing side ) public static IItemHandler getInventory( World world, BlockPos pos, EnumFacing side )