1
0
mirror of https://github.com/SquidDev-CC/CC-Tweaked synced 2025-11-05 08:03:01 +00:00

Merge branch 'master' into mc-1.14.x

This commit is contained in:
SquidDev
2019-08-04 10:57:20 +01:00
72 changed files with 1329 additions and 498 deletions

View File

@@ -144,7 +144,9 @@ public interface ITurtleAccess
GameProfile getOwningPlayer();
/**
* Get the inventory of this turtle
* Get the inventory of this turtle.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getItemHandler()
@@ -155,6 +157,8 @@ public interface ITurtleAccess
/**
* Get the inventory of this turtle as an {@link IItemHandlerModifiable}.
*
* Note: this inventory should only be accessed and modified on the server thread.
*
* @return This turtle's inventory
* @see #getInventory()
* @see IItemHandlerModifiable

View File

@@ -98,8 +98,8 @@ public interface ITurtleUpgrade
* Will only be called for Tool turtle. Called when turtle.dig() or turtle.attack() is called
* by the turtle, and the tool is required to do some work.
*
* Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig}for digging,
* {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
* Conforming implementations should fire {@link BlockEvent.BreakEvent} and {@link TurtleBlockEvent.Dig} for
* digging, {@link AttackEntityEvent} and {@link TurtleAttackEvent} for attacking.
*
* @param turtle Access to the turtle that the tool resides on.
* @param side Which side of the turtle (left or right) the tool resides on.

View File

@@ -11,6 +11,7 @@ import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.media.IMedia;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.shared.MediaProviders;
import dan200.computercraft.shared.media.items.ItemDisk;
import dan200.computercraft.shared.util.StringUtil;
import net.minecraft.item.ItemStack;
@@ -19,11 +20,11 @@ import javax.annotation.Nonnull;
import static dan200.computercraft.core.apis.ArgumentHelper.optString;
public class DiskDrivePeripheral implements IPeripheral
class DiskDrivePeripheral implements IPeripheral
{
private final TileDiskDrive m_diskDrive;
public DiskDrivePeripheral( TileDiskDrive diskDrive )
DiskDrivePeripheral( TileDiskDrive diskDrive )
{
m_diskDrive = diskDrive;
}
@@ -55,7 +56,7 @@ public class DiskDrivePeripheral implements IPeripheral
}
@Override
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] arguments ) throws LuaException, InterruptedException
{
switch( method )
{
@@ -63,21 +64,26 @@ public class DiskDrivePeripheral implements IPeripheral
return new Object[] { !m_diskDrive.getDiskStack().isEmpty() };
case 1: // getDiskLabel
{
IMedia media = m_diskDrive.getDiskMedia();
return media == null ? null : new Object[] { media.getLabel( m_diskDrive.getDiskStack() ) };
ItemStack stack = m_diskDrive.getDiskStack();
IMedia media = MediaProviders.get( stack );
return media == null ? null : new Object[] { media.getLabel( stack ) };
}
case 2: // setDiskLabel
{
String label = optString( arguments, 0, null );
IMedia media = m_diskDrive.getDiskMedia();
if( media == null ) return null;
return context.executeMainThreadTask( () -> {
ItemStack stack = m_diskDrive.getDiskStack();
IMedia media = MediaProviders.get( stack );
if( media == null ) return null;
ItemStack disk = m_diskDrive.getDiskStack();
label = StringUtil.normaliseLabel( label );
if( !media.setLabel( disk, label ) ) throw new LuaException( "Disk label cannot be changed" );
m_diskDrive.setDiskStack( disk );
return null;
if( !media.setLabel( stack, StringUtil.normaliseLabel( label ) ) )
{
throw new LuaException( "Disk label cannot be changed" );
}
m_diskDrive.setDiskStack( stack );
return null;
} );
}
case 3: // hasData
return new Object[] { m_diskDrive.getDiskMountPath( computer ) != null };
@@ -86,14 +92,16 @@ public class DiskDrivePeripheral implements IPeripheral
case 5:
{
// hasAudio
IMedia media = m_diskDrive.getDiskMedia();
return new Object[] { media != null && media.getAudio( m_diskDrive.getDiskStack() ) != null };
ItemStack stack = m_diskDrive.getDiskStack();
IMedia media = MediaProviders.get( stack );
return new Object[] { media != null && media.getAudio( stack ) != null };
}
case 6:
{
// getAudioTitle
IMedia media = m_diskDrive.getDiskMedia();
return new Object[] { media != null ? media.getAudioTitle( m_diskDrive.getDiskStack() ) : false };
ItemStack stack = m_diskDrive.getDiskStack();
IMedia media = MediaProviders.get( stack );
return new Object[] { media != null ? media.getAudioTitle( stack ) : false };
}
case 7: // playAudio
m_diskDrive.playDiskAudio();
@@ -129,8 +137,7 @@ public class DiskDrivePeripheral implements IPeripheral
@Override
public boolean equals( IPeripheral other )
{
if( this == other ) return true;
return other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).m_diskDrive == m_diskDrive;
return this == other || other instanceof DiskDrivePeripheral && ((DiskDrivePeripheral) other).m_diskDrive == m_diskDrive;
}
@Nonnull

View File

@@ -320,35 +320,31 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
}
@Nonnull
public ItemStack getDiskStack()
ItemStack getDiskStack()
{
return getStackInSlot( 0 );
}
public void setDiskStack( @Nonnull ItemStack stack )
void setDiskStack( @Nonnull ItemStack stack )
{
setInventorySlotContents( 0, stack );
}
public IMedia getDiskMedia()
private IMedia getDiskMedia()
{
return MediaProviders.get( getDiskStack() );
}
public String getDiskMountPath( IComputerAccess computer )
String getDiskMountPath( IComputerAccess computer )
{
synchronized( this )
{
if( m_computers.containsKey( computer ) )
{
MountInfo info = m_computers.get( computer );
return info.mountPath;
}
MountInfo info = m_computers.get( computer );
return info != null ? info.mountPath : null;
}
return null;
}
public void mount( IComputerAccess computer )
void mount( IComputerAccess computer )
{
synchronized( this )
{
@@ -357,7 +353,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
}
}
public void unmount( IComputerAccess computer )
void unmount( IComputerAccess computer )
{
synchronized( this )
{
@@ -366,7 +362,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
}
}
public void playDiskAudio()
void playDiskAudio()
{
synchronized( this )
{
@@ -379,7 +375,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
}
}
public void stopDiskAudio()
void stopDiskAudio()
{
synchronized( this )
{
@@ -388,7 +384,7 @@ public final class TileDiskDrive extends TileGeneric implements DefaultInventory
}
}
public void ejectDisk()
void ejectDisk()
{
synchronized( this )
{

View File

@@ -11,6 +11,7 @@ import dan200.computercraft.api.lua.LuaException;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.util.StringUtil;
import javax.annotation.Nonnull;
@@ -51,8 +52,13 @@ public class PrinterPeripheral implements IPeripheral
}
@Override
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException
public Object[] callMethod( @Nonnull IComputerAccess computer, @Nonnull ILuaContext context, int method, @Nonnull Object[] args ) throws LuaException, InterruptedException
{
// FIXME: There's a theoretical race condition here between getCurrentPage and then using the page. Ideally
// we'd lock on the page, consume it, and unlock.
// FIXME: None of our page modification functions actually mark the tile as dirty, so the page may not be
// persisted correctly.
switch( method )
{
case 0: // write
@@ -89,10 +95,13 @@ public class PrinterPeripheral implements IPeripheral
return new Object[] { width, height };
}
case 4: // newPage
return new Object[] { m_printer.startNewPage() };
return context.executeMainThreadTask( () -> new Object[] { m_printer.startNewPage() } );
case 5: // endPage
getCurrentPage();
return new Object[] { m_printer.endCurrentPage() };
return context.executeMainThreadTask( () -> {
getCurrentPage();
return new Object[] { m_printer.endCurrentPage() };
} );
case 6: // getInkLevel
return new Object[] { m_printer.getInkLevel() };
case 7:
@@ -100,7 +109,7 @@ public class PrinterPeripheral implements IPeripheral
// setPageTitle
String title = optString( args, 0, "" );
getCurrentPage();
m_printer.setPageTitle( title );
m_printer.setPageTitle( StringUtil.normaliseLabel( title ) );
return null;
}
case 8: // getPaperLevel
@@ -123,13 +132,11 @@ public class PrinterPeripheral implements IPeripheral
return m_printer;
}
@Nonnull
private Terminal getCurrentPage() throws LuaException
{
Terminal currentPage = m_printer.getCurrentPage();
if( currentPage == null )
{
throw new LuaException( "Page not started" );
}
if( currentPage == null ) throw new LuaException( "Page not started" );
return currentPage;
}
}

View File

@@ -120,10 +120,7 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
}
// Read inventory
synchronized( m_inventory )
{
ItemStackHelper.loadAllItems( nbt, m_inventory );
}
ItemStackHelper.loadAllItems( nbt, m_inventory );
}
@Nonnull
@@ -141,15 +138,12 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
}
// Write inventory
synchronized( m_inventory )
{
ItemStackHelper.saveAllItems( nbt, m_inventory );
}
ItemStackHelper.saveAllItems( nbt, m_inventory );
return super.write( nbt );
}
public boolean isPrinting()
boolean isPrinting()
{
return m_printing;
}
@@ -173,73 +167,59 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
@Nonnull
@Override
public ItemStack getStackInSlot( int i )
public ItemStack getStackInSlot( int slot )
{
return m_inventory.get( i );
return m_inventory.get( slot );
}
@Nonnull
@Override
public ItemStack removeStackFromSlot( int i )
public ItemStack removeStackFromSlot( int slot )
{
synchronized( m_inventory )
{
ItemStack result = m_inventory.get( i );
m_inventory.set( i, ItemStack.EMPTY );
markDirty();
updateBlockState();
return result;
}
ItemStack result = m_inventory.get( slot );
m_inventory.set( slot, ItemStack.EMPTY );
markDirty();
updateBlockState();
return result;
}
@Nonnull
@Override
public ItemStack decrStackSize( int i, int j )
public ItemStack decrStackSize( int slot, int count )
{
synchronized( m_inventory )
ItemStack stack = m_inventory.get( slot );
if( stack.isEmpty() ) return ItemStack.EMPTY;
if( stack.getCount() <= count )
{
if( m_inventory.get( i ).isEmpty() ) return ItemStack.EMPTY;
if( m_inventory.get( i ).getCount() <= j )
{
ItemStack itemstack = m_inventory.get( i );
m_inventory.set( i, ItemStack.EMPTY );
markDirty();
updateBlockState();
return itemstack;
}
ItemStack part = m_inventory.get( i ).split( j );
if( m_inventory.get( i ).isEmpty() )
{
m_inventory.set( i, ItemStack.EMPTY );
updateBlockState();
}
markDirty();
return part;
setInventorySlotContents( slot, ItemStack.EMPTY );
return stack;
}
ItemStack part = stack.split( count );
if( m_inventory.get( slot ).isEmpty() )
{
m_inventory.set( slot, ItemStack.EMPTY );
updateBlockState();
}
markDirty();
return part;
}
@Override
public void setInventorySlotContents( int i, @Nonnull ItemStack stack )
public void setInventorySlotContents( int slot, @Nonnull ItemStack stack )
{
synchronized( m_inventory )
{
m_inventory.set( i, stack );
markDirty();
updateBlockState();
}
m_inventory.set( slot, stack );
markDirty();
updateBlockState();
}
@Override
public void clear()
{
synchronized( m_inventory )
{
for( int i = 0; i < m_inventory.size(); i++ ) m_inventory.set( i, ItemStack.EMPTY );
markDirty();
updateBlockState();
}
for( int i = 0; i < m_inventory.size(); i++ ) m_inventory.set( i, ItemStack.EMPTY );
markDirty();
updateBlockState();
}
@Override
@@ -290,14 +270,18 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
return new PrinterPeripheral( this );
}
public Terminal getCurrentPage()
@Nullable
Terminal getCurrentPage()
{
return m_printing ? m_page : null;
synchronized( m_page )
{
return m_printing ? m_page : null;
}
}
public boolean startNewPage()
boolean startNewPage()
{
synchronized( m_inventory )
synchronized( m_page )
{
if( !canInputPage() ) return false;
if( m_printing && !outputPage() ) return false;
@@ -305,49 +289,36 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
}
}
public boolean endCurrentPage()
boolean endCurrentPage()
{
synchronized( m_inventory )
synchronized( m_page )
{
if( m_printing && outputPage() )
{
return true;
}
}
return false;
}
public int getInkLevel()
{
synchronized( m_inventory )
{
ItemStack inkStack = m_inventory.get( 0 );
return isInk( inkStack ) ? inkStack.getCount() : 0;
return m_printing && outputPage();
}
}
public int getPaperLevel()
int getInkLevel()
{
ItemStack inkStack = m_inventory.get( 0 );
return isInk( inkStack ) ? inkStack.getCount() : 0;
}
int getPaperLevel()
{
int count = 0;
synchronized( m_inventory )
for( int i = 1; i < 7; i++ )
{
for( int i = 1; i < 7; i++ )
{
ItemStack paperStack = m_inventory.get( i );
if( !paperStack.isEmpty() && isPaper( paperStack ) )
{
count += paperStack.getCount();
}
}
ItemStack paperStack = m_inventory.get( i );
if( isPaper( paperStack ) ) count += paperStack.getCount();
}
return count;
}
public void setPageTitle( String title )
void setPageTitle( String title )
{
if( m_printing )
synchronized( m_page )
{
m_pageTitle = title;
if( m_printing ) m_pageTitle = title;
}
}
@@ -365,116 +336,100 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
private boolean canInputPage()
{
synchronized( m_inventory )
{
ItemStack inkStack = m_inventory.get( 0 );
return !inkStack.isEmpty() && isInk( inkStack ) && getPaperLevel() > 0;
}
ItemStack inkStack = m_inventory.get( 0 );
return !inkStack.isEmpty() && isInk( inkStack ) && getPaperLevel() > 0;
}
private boolean inputPage()
{
synchronized( m_inventory )
ItemStack inkStack = m_inventory.get( 0 );
if( !isInk( inkStack ) ) return false;
for( int i = 1; i < 7; i++ )
{
ItemStack inkStack = m_inventory.get( 0 );
if( !isInk( inkStack ) ) return false;
ItemStack paperStack = m_inventory.get( i );
if( paperStack.isEmpty() || !isPaper( paperStack ) ) continue;
for( int i = 1; i < 7; i++ )
// Setup the new page
DyeColor dye = ColourUtils.getStackColour( inkStack );
m_page.setTextColour( dye != null ? dye.getId() : 15 );
m_page.clear();
if( paperStack.getItem() instanceof ItemPrintout )
{
ItemStack paperStack = m_inventory.get( i );
if( !paperStack.isEmpty() && isPaper( paperStack ) )
m_pageTitle = ItemPrintout.getTitle( paperStack );
String[] text = ItemPrintout.getText( paperStack );
String[] textColour = ItemPrintout.getColours( paperStack );
for( int y = 0; y < m_page.getHeight(); y++ )
{
// Setup the new page
DyeColor dye = ColourUtils.getStackColour( inkStack );
m_page.setTextColour( dye != null ? dye.getId() : 15 );
m_page.clear();
if( paperStack.getItem() instanceof ItemPrintout )
{
m_pageTitle = ItemPrintout.getTitle( paperStack );
String[] text = ItemPrintout.getText( paperStack );
String[] textColour = ItemPrintout.getColours( paperStack );
for( int y = 0; y < m_page.getHeight(); y++ )
{
m_page.setLine( y, text[y], textColour[y], "" );
}
}
else
{
m_pageTitle = "";
}
m_page.setCursorPos( 0, 0 );
// Decrement ink
inkStack.shrink( 1 );
if( inkStack.isEmpty() ) m_inventory.set( 0, ItemStack.EMPTY );
// Decrement paper
paperStack.shrink( 1 );
if( paperStack.isEmpty() )
{
m_inventory.set( i, ItemStack.EMPTY );
updateBlockState();
}
markDirty();
m_printing = true;
return true;
m_page.setLine( y, text[y], textColour[y], "" );
}
}
return false;
else
{
m_pageTitle = "";
}
m_page.setCursorPos( 0, 0 );
// Decrement ink
inkStack.shrink( 1 );
if( inkStack.isEmpty() ) m_inventory.set( 0, ItemStack.EMPTY );
// Decrement paper
paperStack.shrink( 1 );
if( paperStack.isEmpty() )
{
m_inventory.set( i, ItemStack.EMPTY );
updateBlockState();
}
markDirty();
m_printing = true;
return true;
}
return false;
}
private boolean outputPage()
{
synchronized( m_page )
int height = m_page.getHeight();
String[] lines = new String[height];
String[] colours = new String[height];
for( int i = 0; i < height; i++ )
{
int height = m_page.getHeight();
String[] lines = new String[height];
String[] colours = new String[height];
for( int i = 0; i < height; i++ )
{
lines[i] = m_page.getLine( i ).toString();
colours[i] = m_page.getTextColourLine( i ).toString();
}
ItemStack stack = ItemPrintout.createSingleFromTitleAndText( m_pageTitle, lines, colours );
synchronized( m_inventory )
{
for( int slot : BOTTOM_SLOTS )
{
if( m_inventory.get( slot ).isEmpty() )
{
setInventorySlotContents( slot, stack );
m_printing = false;
return true;
}
}
}
return false;
lines[i] = m_page.getLine( i ).toString();
colours[i] = m_page.getTextColourLine( i ).toString();
}
ItemStack stack = ItemPrintout.createSingleFromTitleAndText( m_pageTitle, lines, colours );
for( int slot : BOTTOM_SLOTS )
{
if( m_inventory.get( slot ).isEmpty() )
{
setInventorySlotContents( slot, stack );
m_printing = false;
return true;
}
}
return false;
}
private void ejectContents()
{
synchronized( m_inventory )
for( int i = 0; i < 13; i++ )
{
for( int i = 0; i < 13; i++ )
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() )
{
// Remove the stack from the inventory
setInventorySlotContents( i, ItemStack.EMPTY );
// Remove the stack from the inventory
setInventorySlotContents( i, ItemStack.EMPTY );
// Spawn the item in the world
BlockPos pos = getPos();
double x = pos.getX() + 0.5;
double y = pos.getY() + 0.75;
double z = pos.getZ() + 0.5;
WorldUtil.dropItemStack( stack, getWorld(), x, y, z );
}
// Spawn the item in the world
BlockPos pos = getPos();
double x = pos.getX() + 0.5;
double y = pos.getY() + 0.75;
double z = pos.getZ() + 0.5;
WorldUtil.dropItemStack( stack, getWorld(), x, y, z );
}
}
}
@@ -482,25 +437,22 @@ public final class TilePrinter extends TileGeneric implements DefaultSidedInvent
private void updateBlockState()
{
boolean top = false, bottom = false;
synchronized( m_inventory )
for( int i = 1; i < 7; i++ )
{
for( int i = 1; i < 7; i++ )
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
top = true;
break;
}
top = true;
break;
}
for( int i = 7; i < 13; i++ )
}
for( int i = 7; i < 13; i++ )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
ItemStack stack = m_inventory.get( i );
if( !stack.isEmpty() && isPaper( stack ) )
{
bottom = true;
break;
}
bottom = true;
break;
}
}

View File

@@ -31,9 +31,13 @@ public final class FurnaceRefuelHandler implements TurtleRefuelEvent.Handler
@Override
public int refuel( @Nonnull ITurtleAccess turtle, @Nonnull ItemStack currentStack, int slot, int limit )
{
ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false );
int fuelToGive = getFuelPerItem( stack ) * stack.getCount();
int fuelSpaceLeft = turtle.getFuelLimit() - turtle.getFuelLevel();
int fuelPerItem = getFuelPerItem( turtle.getItemHandler().getStackInSlot( slot ) );
int fuelItemLimit = (int) Math.ceil( fuelSpaceLeft / (double) fuelPerItem );
if( limit > fuelItemLimit ) limit = fuelItemLimit;
ItemStack stack = turtle.getItemHandler().extractItem( slot, limit, false );
int fuelToGive = fuelPerItem * stack.getCount();
// Store the replacement item in the inventory
ItemStack replacementStack = stack.getItem().getContainerItem( stack );
if( !replacementStack.isEmpty() )

View File

@@ -335,9 +335,11 @@ public class TurtleAPI implements ILuaAPI
return tryCommand( context, new TurtleInspectCommand( InteractDirection.Up ) );
case 40: // inspectDown
return tryCommand( context, new TurtleInspectCommand( InteractDirection.Down ) );
case 41:
case 41: // getItemDetail
{
// getItemDetail
// FIXME: There's a race condition here if the stack is being modified (mutating NBT, etc...)
// on another thread. The obvious solution is to move this into a command, but some programs rely
// on this having a 0-tick delay.
int slot = parseOptionalSlotNumber( args, 0, m_turtle.getSelectedSlot() );
ItemStack stack = m_turtle.getInventory().getStackInSlot( slot );
if( stack.isEmpty() ) return new Object[] { null };

View File

@@ -153,7 +153,7 @@ public class BlockTurtle extends BlockComputerBase<TileTurtle> implements IWater
@Override
public float getExplosionResistance( BlockState state, IWorldReader world, BlockPos pos, @Nullable Entity exploder, Explosion explosion )
{
if( getFamily() == ComputerFamily.Advanced && (exploder instanceof LivingEntity || exploder instanceof DamagingProjectileEntity) )
if( getFamily() == ComputerFamily.Advanced || exploder instanceof LivingEntity || exploder instanceof DamagingProjectileEntity )
{
return 2000;
}

View File

@@ -49,13 +49,12 @@ import net.minecraftforge.items.wrapper.InvWrapper;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.Collections;
import static net.minecraftforge.items.CapabilityItemHandler.ITEM_HANDLER_CAPABILITY;
public class TileTurtle extends TileComputerBase implements ITurtleTile, DefaultInventory
{
// Statics
public static final int INVENTORY_SIZE = 16;
public static final int INVENTORY_WIDTH = 4;
public static final int INVENTORY_HEIGHT = 4;
@@ -70,8 +69,6 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
type -> new TileTurtle( type, ComputerFamily.Advanced )
);
// Members
enum MoveState
{
NOT_MOVED,
@@ -79,25 +76,20 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
MOVED
}
private NonNullList<ItemStack> m_inventory;
private NonNullList<ItemStack> m_previousInventory;
private final NonNullList<ItemStack> m_inventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
private final NonNullList<ItemStack> m_previousInventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
private final IItemHandlerModifiable m_itemHandler = new InvWrapper( this );
private LazyOptional<IItemHandlerModifiable> itemHandlerCap;
private boolean m_inventoryChanged;
private TurtleBrain m_brain;
private MoveState m_moveState;
private boolean m_inventoryChanged = false;
private TurtleBrain m_brain = new TurtleBrain( this );
private MoveState m_moveState = MoveState.NOT_MOVED;
public TileTurtle( TileEntityType<? extends TileGeneric> type, ComputerFamily family )
{
super( type, family );
m_inventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
m_previousInventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
m_inventoryChanged = false;
m_brain = new TurtleBrain( this );
m_moveState = MoveState.NOT_MOVED;
}
public boolean hasMoved()
private boolean hasMoved()
{
return m_moveState == MoveState.MOVED;
}
@@ -237,18 +229,15 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
{
super.tick();
m_brain.update();
synchronized( m_inventory )
if( !getWorld().isRemote && m_inventoryChanged )
{
if( !getWorld().isRemote && m_inventoryChanged )
{
ServerComputer computer = getServerComputer();
if( computer != null ) computer.queueEvent( "turtle_inventory" );
ServerComputer computer = getServerComputer();
if( computer != null ) computer.queueEvent( "turtle_inventory" );
m_inventoryChanged = false;
for( int n = 0; n < getSizeInventory(); n++ )
{
m_previousInventory.set( n, InventoryUtil.copyItem( getStackInSlot( n ) ) );
}
m_inventoryChanged = false;
for( int n = 0; n < getSizeInventory(); n++ )
{
m_previousInventory.set( n, InventoryUtil.copyItem( getStackInSlot( n ) ) );
}
}
}
@@ -288,8 +277,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
// Read inventory
ListNBT nbttaglist = nbt.getList( "Items", Constants.NBT.TAG_COMPOUND );
m_inventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
m_previousInventory = NonNullList.withSize( INVENTORY_SIZE, ItemStack.EMPTY );
m_inventory.clear();
m_previousInventory.clear();
for( int i = 0; i < nbttaglist.size(); i++ )
{
CompoundNBT tag = nbttaglist.getCompound( i );
@@ -396,7 +385,7 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
return m_brain.getToolRenderAngle( side, f );
}
public void setOwningPlayer( GameProfile player )
void setOwningPlayer( GameProfile player )
{
m_brain.setOwningPlayer( player );
markDirty();
@@ -424,109 +413,76 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
@Override
public ItemStack getStackInSlot( int slot )
{
if( slot >= 0 && slot < INVENTORY_SIZE )
{
synchronized( m_inventory )
{
return m_inventory.get( slot );
}
}
return ItemStack.EMPTY;
return slot >= 0 && slot < INVENTORY_SIZE ? m_inventory.get( slot ) : ItemStack.EMPTY;
}
@Nonnull
@Override
public ItemStack removeStackFromSlot( int slot )
{
synchronized( m_inventory )
{
ItemStack result = getStackInSlot( slot );
setInventorySlotContents( slot, ItemStack.EMPTY );
return result;
}
ItemStack result = getStackInSlot( slot );
setInventorySlotContents( slot, ItemStack.EMPTY );
return result;
}
@Nonnull
@Override
public ItemStack decrStackSize( int slot, int count )
{
if( count == 0 )
if( count == 0 ) return ItemStack.EMPTY;
ItemStack stack = getStackInSlot( slot );
if( stack.isEmpty() ) return ItemStack.EMPTY;
if( stack.getCount() <= count )
{
return ItemStack.EMPTY;
setInventorySlotContents( slot, ItemStack.EMPTY );
return stack;
}
synchronized( m_inventory )
{
ItemStack stack = getStackInSlot( slot );
if( stack.isEmpty() )
{
return ItemStack.EMPTY;
}
if( stack.getCount() <= count )
{
setInventorySlotContents( slot, ItemStack.EMPTY );
return stack;
}
ItemStack part = stack.split( count );
onInventoryDefinitelyChanged();
return part;
}
ItemStack part = stack.split( count );
onInventoryDefinitelyChanged();
return part;
}
@Override
public void setInventorySlotContents( int i, @Nonnull ItemStack stack )
{
if( i >= 0 && i < INVENTORY_SIZE )
if( i >= 0 && i < INVENTORY_SIZE && !InventoryUtil.areItemsEqual( stack, m_inventory.get( i ) ) )
{
synchronized( m_inventory )
{
if( !InventoryUtil.areItemsEqual( stack, m_inventory.get( i ) ) )
{
m_inventory.set( i, stack );
onInventoryDefinitelyChanged();
}
}
m_inventory.set( i, stack );
onInventoryDefinitelyChanged();
}
}
@Override
public void clear()
{
synchronized( m_inventory )
boolean changed = false;
for( int i = 0; i < INVENTORY_SIZE; i++ )
{
boolean changed = false;
for( int i = 0; i < INVENTORY_SIZE; i++ )
if( !m_inventory.get( i ).isEmpty() )
{
if( !m_inventory.get( i ).isEmpty() )
{
m_inventory.set( i, ItemStack.EMPTY );
changed = true;
}
}
if( changed )
{
onInventoryDefinitelyChanged();
m_inventory.set( i, ItemStack.EMPTY );
changed = true;
}
}
if( changed ) onInventoryDefinitelyChanged();
}
@Override
public void markDirty()
{
super.markDirty();
synchronized( m_inventory )
if( !m_inventoryChanged )
{
if( !m_inventoryChanged )
for( int n = 0; n < getSizeInventory(); n++ )
{
for( int n = 0; n < getSizeInventory(); n++ )
if( !ItemStack.areItemStacksEqual( getStackInSlot( n ), m_previousInventory.get( n ) ) )
{
if( !ItemStack.areItemStacksEqual( getStackInSlot( n ), m_previousInventory.get( n ) ) )
{
m_inventoryChanged = true;
break;
}
m_inventoryChanged = true;
break;
}
}
}
@@ -587,8 +543,8 @@ public class TileTurtle extends TileComputerBase implements ITurtleTile, Default
public void transferStateFrom( TileTurtle copy )
{
super.transferStateFrom( copy );
m_inventory = copy.m_inventory;
m_previousInventory = copy.m_previousInventory;
Collections.copy( m_inventory, copy.m_inventory );
Collections.copy( m_previousInventory, copy.m_previousInventory );
m_inventoryChanged = copy.m_inventoryChanged;
m_brain = copy.m_brain;
m_brain.setOwner( this );

View File

@@ -248,7 +248,7 @@ public class TurtleTool extends AbstractTurtleUpgrade
boolean canHarvest = state.canHarvestBlock( world, blockPosition, turtlePlayer );
boolean canBreak = state.removedByPlayer( world, blockPosition, turtlePlayer, canHarvest, fluidState );
if( canBreak ) state.getBlock().onPlayerDestroy( world, blockPosition, state );
if( canHarvest )
if( canHarvest && canBreak )
{
state.getBlock().harvestBlock( world, turtlePlayer, blockPosition, state, tile, turtlePlayer.getHeldItemMainhand() );
}