mirror of
https://github.com/SquidDev-CC/CC-Tweaked
synced 2025-11-15 12:37:13 +00:00
304 lines
8.6 KiB
Java
304 lines
8.6 KiB
Java
/*
|
|
* This file is part of ComputerCraft - http://www.computercraft.info
|
|
* Copyright Daniel Ratcliffe, 2011-2021. Do not distribute without permission.
|
|
* Send enquiries to dratcliffe@gmail.com
|
|
*/
|
|
package dan200.computercraft.shared.util;
|
|
|
|
import net.minecraft.inventory.Inventory;
|
|
import net.minecraft.inventory.SidedInventory;
|
|
import net.minecraft.item.ItemStack;
|
|
import net.minecraft.util.math.Direction;
|
|
|
|
import javax.annotation.Nonnull;
|
|
|
|
/**
|
|
* The most cutesy alternative of {@code IItemHandler} the world has ever seen.
|
|
*/
|
|
public interface ItemStorage
|
|
{
|
|
static ItemStorage wrap( Inventory inventory )
|
|
{
|
|
return new InventoryWrapper( inventory );
|
|
}
|
|
|
|
static ItemStorage wrap( @Nonnull SidedInventory inventory, @Nonnull Direction facing )
|
|
{
|
|
return new SidedInventoryWrapper( inventory, facing );
|
|
}
|
|
|
|
static ItemStorage wrap( @Nonnull Inventory inventory, @Nonnull Direction facing )
|
|
{
|
|
return inventory instanceof SidedInventory ? new SidedInventoryWrapper( (SidedInventory) inventory, facing ) : new InventoryWrapper( inventory );
|
|
}
|
|
|
|
static boolean areStackable( @Nonnull ItemStack a, @Nonnull ItemStack b )
|
|
{
|
|
return a == b || (a.getItem() == b.getItem() && ItemStack.areNbtEqual( a, b ));
|
|
}
|
|
|
|
int size();
|
|
|
|
@Nonnull
|
|
ItemStack getStack( int slot );
|
|
|
|
@Nonnull
|
|
ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate );
|
|
|
|
@Nonnull
|
|
ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate );
|
|
|
|
default ItemStorage view( int start, int size )
|
|
{
|
|
return new View( this, start, size );
|
|
}
|
|
|
|
class InventoryWrapper implements ItemStorage
|
|
{
|
|
private final Inventory inventory;
|
|
|
|
InventoryWrapper( Inventory inventory )
|
|
{
|
|
this.inventory = inventory;
|
|
}
|
|
|
|
@Override
|
|
public int size()
|
|
{
|
|
return inventory.size();
|
|
}
|
|
|
|
@Override
|
|
@Nonnull
|
|
public ItemStack getStack( int slot )
|
|
{
|
|
return inventory.getStack( slot );
|
|
}
|
|
|
|
@Override
|
|
@Nonnull
|
|
public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
|
|
{
|
|
ItemStack existing = inventory.getStack( slot );
|
|
if( existing.isEmpty() || !canExtract( slot, existing ) || (!filter.isEmpty() && !areStackable( existing, filter )) )
|
|
{
|
|
return ItemStack.EMPTY;
|
|
}
|
|
|
|
if( simulate )
|
|
{
|
|
existing = existing.copy();
|
|
if( existing.getCount() > limit )
|
|
{
|
|
existing.setCount( limit );
|
|
}
|
|
return existing;
|
|
}
|
|
else if( existing.getCount() < limit )
|
|
{
|
|
setAndDirty( slot, ItemStack.EMPTY );
|
|
return existing;
|
|
}
|
|
else
|
|
{
|
|
ItemStack result = existing.split( limit );
|
|
setAndDirty( slot, existing );
|
|
return result;
|
|
}
|
|
}
|
|
|
|
protected boolean canExtract( int slot, ItemStack stack )
|
|
{
|
|
return true;
|
|
}
|
|
|
|
private void setAndDirty( int slot, @Nonnull ItemStack stack )
|
|
{
|
|
inventory.setStack( slot, stack );
|
|
inventory.markDirty();
|
|
}
|
|
|
|
@Override
|
|
@Nonnull
|
|
public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
|
|
{
|
|
if( stack.isEmpty() || !inventory.isValid( slot, stack ) )
|
|
{
|
|
return stack;
|
|
}
|
|
|
|
ItemStack existing = inventory.getStack( slot );
|
|
if( existing.isEmpty() )
|
|
{
|
|
int limit = Math.min( stack.getMaxCount(), inventory.getMaxCountPerStack() );
|
|
if( limit <= 0 )
|
|
{
|
|
return stack;
|
|
}
|
|
|
|
if( stack.getCount() < limit )
|
|
{
|
|
if( !simulate )
|
|
{
|
|
setAndDirty( slot, stack );
|
|
}
|
|
return ItemStack.EMPTY;
|
|
}
|
|
else
|
|
{
|
|
stack = stack.copy();
|
|
ItemStack insert = stack.split( limit );
|
|
if( !simulate )
|
|
{
|
|
setAndDirty( slot, insert );
|
|
}
|
|
return stack;
|
|
}
|
|
}
|
|
else if( areStackable( stack, existing ) )
|
|
{
|
|
int limit = Math.min( existing.getMaxCount(), inventory.getMaxCountPerStack() ) - existing.getCount();
|
|
if( limit <= 0 )
|
|
{
|
|
return stack;
|
|
}
|
|
|
|
if( stack.getCount() < limit )
|
|
{
|
|
if( !simulate )
|
|
{
|
|
existing.increment( stack.getCount() );
|
|
setAndDirty( slot, existing );
|
|
}
|
|
return ItemStack.EMPTY;
|
|
}
|
|
else
|
|
{
|
|
stack = stack.copy();
|
|
stack.decrement( limit );
|
|
if( !simulate )
|
|
{
|
|
existing.increment( limit );
|
|
setAndDirty( slot, existing );
|
|
}
|
|
return stack;
|
|
}
|
|
}
|
|
else
|
|
{
|
|
return stack;
|
|
}
|
|
}
|
|
}
|
|
|
|
class SidedInventoryWrapper extends InventoryWrapper
|
|
{
|
|
private final SidedInventory inventory;
|
|
private final Direction facing;
|
|
|
|
SidedInventoryWrapper( SidedInventory inventory, Direction facing )
|
|
{
|
|
super( inventory );
|
|
this.inventory = inventory;
|
|
this.facing = facing;
|
|
}
|
|
|
|
@Override
|
|
protected boolean canExtract( int slot, ItemStack stack )
|
|
{
|
|
return super.canExtract( slot, stack ) && inventory.canExtract( slot, stack, facing );
|
|
}
|
|
|
|
@Override
|
|
public int size()
|
|
{
|
|
return inventory.getAvailableSlots( facing ).length;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
|
|
{
|
|
int[] slots = inventory.getAvailableSlots( facing );
|
|
return slot >= 0 && slot < slots.length ? super.take( slots[slot], limit, filter, simulate ) : ItemStack.EMPTY;
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
|
|
{
|
|
int[] slots = inventory.getAvailableSlots( facing );
|
|
if( slot < 0 || slot >= slots.length )
|
|
{
|
|
return stack;
|
|
}
|
|
|
|
int mappedSlot = slots[slot];
|
|
if( !inventory.canInsert( slot, stack, facing ) )
|
|
{
|
|
return stack;
|
|
}
|
|
return super.store( mappedSlot, stack, simulate );
|
|
}
|
|
}
|
|
|
|
class View implements ItemStorage
|
|
{
|
|
private final ItemStorage parent;
|
|
private final int start;
|
|
private final int size;
|
|
|
|
View( ItemStorage parent, int start, int size )
|
|
{
|
|
this.parent = parent;
|
|
this.start = start;
|
|
this.size = size;
|
|
}
|
|
|
|
@Override
|
|
public int size()
|
|
{
|
|
return size;
|
|
}
|
|
|
|
@Override
|
|
@Nonnull
|
|
public ItemStack getStack( int slot )
|
|
{
|
|
if( slot < start || slot >= start + size )
|
|
{
|
|
return ItemStack.EMPTY;
|
|
}
|
|
return parent.getStack( slot - start );
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public ItemStack take( int slot, int limit, @Nonnull ItemStack filter, boolean simulate )
|
|
{
|
|
if( slot < start || slot >= start + size )
|
|
{
|
|
return ItemStack.EMPTY;
|
|
}
|
|
return parent.take( slot - start, limit, filter, simulate );
|
|
}
|
|
|
|
@Nonnull
|
|
@Override
|
|
public ItemStack store( int slot, @Nonnull ItemStack stack, boolean simulate )
|
|
{
|
|
if( slot < start || slot >= start + size )
|
|
{
|
|
return stack;
|
|
}
|
|
return parent.store( slot - start, stack, simulate );
|
|
}
|
|
|
|
@Override
|
|
public ItemStorage view( int start, int size )
|
|
{
|
|
return new View( parent, this.start + start, size );
|
|
}
|
|
}
|
|
}
|