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:
@@ -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
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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 )
|
||||
{
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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() )
|
||||
|
||||
@@ -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 };
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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() );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user