CC-Tweaked/src/main/java/dan200/computercraft/shared/peripheral/printer/TilePrinter.java

602 lines
16 KiB
Java

/**
* This file is part of ComputerCraft - http://www.computercraft.info
* Copyright Daniel Ratcliffe, 2011-2016. Do not distribute without permission.
* Send enquiries to dratcliffe@gmail.com
*/
package dan200.computercraft.shared.peripheral.printer;
import dan200.computercraft.ComputerCraft;
import dan200.computercraft.api.peripheral.IPeripheral;
import dan200.computercraft.core.terminal.Terminal;
import dan200.computercraft.shared.media.items.ItemPrintout;
import dan200.computercraft.shared.peripheral.PeripheralType;
import dan200.computercraft.shared.peripheral.common.TilePeripheralBase;
import dan200.computercraft.shared.util.InventoryUtil;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Items;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.util.*;
import net.minecraft.util.math.*;
import net.minecraft.util.text.*;
import net.minecraft.world.World;
import net.minecraftforge.common.util.Constants;
public class TilePrinter extends TilePeripheralBase
implements IInventory, ISidedInventory
{
// Statics
private static final int[] bottomSlots = { 7, 8, 9, 10, 11, 12 };
private static final int[] topSlots = { 1, 2, 3, 4, 5, 6 };
private static final int[] sideSlots = { 0 };
// Members
private final ItemStack[] m_inventory;
private final Terminal m_page;
private String m_pageTitle;
private boolean m_printing;
public TilePrinter()
{
m_inventory = new ItemStack[13];
m_page = new Terminal( ItemPrintout.LINE_MAX_LENGTH, ItemPrintout.LINES_PER_PAGE );
m_pageTitle = "";
m_printing = false;
}
@Override
public void destroy()
{
ejectContents();
}
@Override
public boolean onActivate( EntityPlayer player, EnumFacing side, float hitX, float hitY, float hitZ )
{
if( !player.isSneaking() )
{
if( !worldObj.isRemote )
{
ComputerCraft.openPrinterGUI( player, this );
}
return true;
}
return false;
}
@Override
public void readFromNBT(NBTTagCompound nbttagcompound)
{
super.readFromNBT(nbttagcompound);
// Read page
synchronized( m_page )
{
m_printing = nbttagcompound.getBoolean( "printing" );
m_pageTitle = nbttagcompound.getString( "pageTitle" );
m_page.readFromNBT( nbttagcompound );
}
// Read inventory
synchronized( m_inventory )
{
NBTTagList nbttaglist = nbttagcompound.getTagList( "Items", Constants.NBT.TAG_COMPOUND );
for( int i=0; i<nbttaglist.tagCount(); ++i )
{
NBTTagCompound itemTag = nbttaglist.getCompoundTagAt( i );
int j = itemTag.getByte("Slot") & 0xff;
if (j >= 0 && j < m_inventory.length)
{
m_inventory[j] = ItemStack.loadItemStackFromNBT(itemTag);
}
}
}
}
@Override
public NBTTagCompound writeToNBT(NBTTagCompound nbttagcompound)
{
nbttagcompound = super.writeToNBT(nbttagcompound);
// Write page
synchronized( m_page )
{
nbttagcompound.setBoolean( "printing", m_printing );
nbttagcompound.setString( "pageTitle", m_pageTitle );
m_page.writeToNBT( nbttagcompound );
}
// Write inventory
synchronized( m_inventory )
{
NBTTagList nbttaglist = new NBTTagList();
for(int i=0; i<m_inventory.length; ++i)
{
if (m_inventory[i] != null)
{
NBTTagCompound itemtag = new NBTTagCompound();
itemtag.setByte("Slot", (byte)i);
m_inventory[i].writeToNBT(itemtag);
nbttaglist.appendTag(itemtag);
}
}
nbttagcompound.setTag("Items", nbttaglist);
}
return nbttagcompound;
}
@Override
public final void readDescription( NBTTagCompound nbttagcompound )
{
super.readDescription( nbttagcompound );
updateBlock();
}
@Override
public boolean shouldRefresh( World world, BlockPos pos, IBlockState oldState, IBlockState newState )
{
return super.shouldRefresh( world, pos, oldState, newState ) || ComputerCraft.Blocks.peripheral.getPeripheralType( newState ) != PeripheralType.Printer;
}
public boolean isPrinting()
{
return m_printing;
}
// IInventory implementation
@Override
public int getSizeInventory()
{
return m_inventory.length;
}
@Override
public ItemStack getStackInSlot(int i)
{
synchronized( m_inventory )
{
return m_inventory[i];
}
}
@Override
public ItemStack removeStackFromSlot(int i)
{
synchronized( m_inventory )
{
ItemStack result = m_inventory[i];
m_inventory[i] = null;
updateAnim();
return result;
}
}
@Override
public ItemStack decrStackSize(int i, int j)
{
synchronized( m_inventory )
{
if( m_inventory[i] == null )
{
return null;
}
if( m_inventory[i].stackSize <= j )
{
ItemStack itemstack = m_inventory[i];
m_inventory[i] = null;
markDirty();
updateAnim();
return itemstack;
}
ItemStack part = m_inventory[i].splitStack(j);
if( m_inventory[i].stackSize == 0 )
{
m_inventory[i] = null;
updateAnim();
}
markDirty();
return part;
}
}
@Override
public void setInventorySlotContents( int i, ItemStack stack )
{
synchronized( m_inventory )
{
m_inventory[i] = stack;
markDirty();
updateAnim();
}
}
@Override
public void clear()
{
synchronized( m_inventory )
{
for( int i=0; i<m_inventory.length; ++i )
{
m_inventory[i] = null;
}
markDirty();
updateAnim();
}
}
@Override
public boolean hasCustomName()
{
return getLabel() != null;
}
@Override
public String getName()
{
String label = getLabel();
if( label != null )
{
return label;
}
else
{
return "tile.computercraft:printer.name";
}
}
@Override
public ITextComponent getDisplayName()
{
if( hasCustomName() )
{
return new TextComponentString( getName() );
}
else
{
return new TextComponentTranslation( getName() );
}
}
@Override
public int getInventoryStackLimit()
{
return 64;
}
@Override
public void openInventory( EntityPlayer player )
{
}
@Override
public void closeInventory( EntityPlayer player )
{
}
@Override
public boolean isItemValidForSlot( int slot, ItemStack itemstack )
{
return true;
}
@Override
public boolean isUseableByPlayer( EntityPlayer player )
{
return isUsable( player, false );
}
@Override
public int getFieldCount()
{
return 0;
}
@Override
public int getField(int id)
{
return 0;
}
@Override
public void setField(int id, int value)
{
}
// ISidedInventory implementation
@Override
public int[] getSlotsForFace( EnumFacing side )
{
switch( side )
{
case DOWN: return bottomSlots; // Bottom (Out tray)
case UP: return topSlots; // Top (In tray)
default: return sideSlots; // Sides (Ink)
}
}
@Override
public boolean canInsertItem( int slot, ItemStack itemstack, EnumFacing face )
{
return isItemValidForSlot( slot, itemstack );
}
@Override
public boolean canExtractItem( int slot, ItemStack itemstack, EnumFacing face )
{
return true;
}
// IPeripheralTile implementation
@Override
public IPeripheral getPeripheral( EnumFacing side )
{
return new PrinterPeripheral( this );
}
public Terminal getCurrentPage()
{
if( m_printing )
{
return m_page;
}
return null;
}
public boolean startNewPage()
{
synchronized( m_inventory )
{
if( canInputPage() )
{
if( m_printing && !outputPage() )
{
return false;
}
if( inputPage() )
{
return true;
}
}
return false;
}
}
public boolean endCurrentPage()
{
synchronized( m_inventory )
{
if( m_printing && outputPage() )
{
return true;
}
}
return false;
}
public int getInkLevel()
{
synchronized( m_inventory )
{
ItemStack inkStack = m_inventory[0];
if( inkStack != null && isInk(inkStack) )
{
return inkStack.stackSize;
}
}
return 0;
}
public int getPaperLevel()
{
int count = 0;
synchronized( m_inventory )
{
for( int i=1; i<7; ++i )
{
ItemStack paperStack = m_inventory[i];
if( paperStack != null && isPaper(paperStack) )
{
count += paperStack.stackSize;
}
}
}
return count;
}
public void setPageTitle( String title )
{
if( m_printing )
{
m_pageTitle = title;
}
}
private boolean isInk( ItemStack stack )
{
return (stack.getItem() == Items.DYE);
}
private boolean isPaper( ItemStack stack )
{
Item item = stack.getItem();
return ( item == Items.PAPER || (item instanceof ItemPrintout && ItemPrintout.getType( stack ) == ItemPrintout.Type.Single) );
}
private boolean canInputPage()
{
synchronized( m_inventory )
{
ItemStack inkStack = m_inventory[0];
if( inkStack == null || !isInk(inkStack) )
{
return false;
}
if( getPaperLevel() > 0 )
{
return true;
}
return false;
}
}
private boolean inputPage()
{
synchronized( m_inventory )
{
ItemStack inkStack = m_inventory[0];
if( inkStack == null || !isInk(inkStack) )
{
return false;
}
for( int i=1; i<7; ++i )
{
ItemStack paperStack = m_inventory[i];
if( paperStack != null && isPaper(paperStack) )
{
// Decrement ink
inkStack.stackSize--;
if( inkStack.stackSize <= 0 )
{
m_inventory[0] = null;
}
// Decrement paper
paperStack.stackSize--;
if( paperStack.stackSize <= 0 )
{
m_inventory[i] = null;
updateAnim();
}
// Setup the new page
int colour = inkStack.getItemDamage();
if( colour >= 0 && colour < 16 ) {
m_page.setTextColour( 15 - colour );
} else {
m_page.setTextColour( 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 );
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 )
{
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 )
{
ItemStack remainder = InventoryUtil.storeItems( stack, this, 7, 6, 7 );
if( remainder == null )
{
m_printing = false;
return true;
}
}
return false;
}
}
private void ejectContents()
{
synchronized( m_inventory )
{
for( int i=0; i<13; ++i )
{
ItemStack stack = m_inventory[i];
if( stack != null )
{
// Remove the stack from the inventory
setInventorySlotContents( i, null );
// Spawn the item in the world
BlockPos pos = getPos();
double x = (double)pos.getX() + 0.5;
double y = (double)pos.getY() + 0.75;
double z = (double)pos.getZ() + 0.5;
EntityItem entityitem = new EntityItem( worldObj, x, y, z, stack );
entityitem.motionX = worldObj.rand.nextFloat() * 0.2 - 0.1;
entityitem.motionY = worldObj.rand.nextFloat() * 0.2 - 0.1;
entityitem.motionZ = worldObj.rand.nextFloat() * 0.2 - 0.1;
worldObj.spawnEntityInWorld(entityitem);
}
}
}
}
private void updateAnim()
{
synchronized( m_inventory )
{
int anim = 0;
for( int i=1;i<7;++i )
{
ItemStack stack = m_inventory[i];
if( stack != null && isPaper(stack) )
{
anim += 1;
break;
}
}
for( int i=7;i<13;++i )
{
ItemStack stack = m_inventory[i];
if( stack != null && isPaper(stack) )
{
anim += 2;
break;
}
}
setAnim( anim );
}
}
}