Package appeng.tile.crafting

Source Code of appeng.tile.crafting.TileMolecularAssembler

package appeng.tile.crafting;

import io.netty.buffer.ByteBuf;

import java.io.IOException;
import java.util.ArrayList;

import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import net.minecraftforge.common.util.ForgeDirection;
import appeng.api.AEApi;
import appeng.api.config.Actionable;
import appeng.api.config.PowerMultiplier;
import appeng.api.config.RedstoneMode;
import appeng.api.config.Settings;
import appeng.api.config.Upgrades;
import appeng.api.implementations.IPowerChannelState;
import appeng.api.implementations.IUpgradeableHost;
import appeng.api.implementations.tiles.ICraftingMachine;
import appeng.api.networking.IGridNode;
import appeng.api.networking.crafting.ICraftingPatternDetails;
import appeng.api.networking.events.MENetworkEventSubscribe;
import appeng.api.networking.events.MENetworkPowerStatusChange;
import appeng.api.networking.ticking.IGridTickable;
import appeng.api.networking.ticking.TickRateModulation;
import appeng.api.networking.ticking.TickingRequest;
import appeng.api.parts.ISimplifiedBundle;
import appeng.api.storage.data.IAEItemStack;
import appeng.api.util.AECableType;
import appeng.api.util.DimensionalCoord;
import appeng.api.util.IConfigManager;
import appeng.container.ContainerNull;
import appeng.core.sync.network.NetworkHandler;
import appeng.core.sync.packets.PacketAssemblerAnimation;
import appeng.items.misc.ItemEncodedPattern;
import appeng.me.GridAccessException;
import appeng.parts.automation.UpgradeInventory;
import appeng.tile.TileEvent;
import appeng.tile.events.TileEventType;
import appeng.tile.grid.AENetworkInvTile;
import appeng.tile.inventory.AppEngInternalInventory;
import appeng.tile.inventory.InvOperation;
import appeng.util.ConfigManager;
import appeng.util.IConfigManagerHost;
import appeng.util.InventoryAdaptor;
import appeng.util.Platform;
import appeng.util.item.AEItemStack;
import cpw.mods.fml.common.FMLCommonHandler;
import cpw.mods.fml.common.network.NetworkRegistry.TargetPoint;

public class TileMolecularAssembler extends AENetworkInvTile implements IUpgradeableHost, IConfigManagerHost,
    IGridTickable, ICraftingMachine, IPowerChannelState
{

  static final int[] sides = new int[] { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9 };
  static final ItemStack assemblerStack = AEApi.instance().blocks().blockMolecularAssembler.stack( 1 );

  private final InventoryCrafting craftingInv = new InventoryCrafting( new ContainerNull(), 3, 3 );
  private final AppEngInternalInventory inv = new AppEngInternalInventory( this, 9 + 2 );
  private final IConfigManager settings = new ConfigManager( this );
  private final UpgradeInventory upgrades = new UpgradeInventory( assemblerStack, this, getUpgradeSlots() );

  private ForgeDirection pushDirection = ForgeDirection.UNKNOWN;
  private ItemStack myPattern = null;
  private ICraftingPatternDetails myPlan = null;
  private double progress = 0;
  private boolean isAwake = false;
  private boolean forcePlan = false;

  private boolean reboot = true;
  public ISimplifiedBundle lightCache;

  @Override
  public boolean pushPattern(ICraftingPatternDetails patternDetails, InventoryCrafting table, ForgeDirection where)
  {
    if ( myPattern == null )
    {
      boolean isEmpty = true;
      for (int x = 0; x < inv.getSizeInventory(); x++)
        isEmpty = inv.getStackInSlot( x ) == null && isEmpty;

      if ( isEmpty && patternDetails.isCraftable() )
      {
        forcePlan = true;
        myPlan = patternDetails;
        pushDirection = where;

        for (int x = 0; x < table.getSizeInventory(); x++)
          inv.setInventorySlotContents( x, table.getStackInSlot( x ) );

        updateSleepiness();
        markDirty();
        return true;
      }
    }
    return false;
  }

  private void recalculatePlan()
  {
    reboot = true;

    if ( forcePlan )
      return;

    ItemStack is = inv.getStackInSlot( 10 );

    if ( is != null && is.getItem() instanceof ItemEncodedPattern )
    {
      if ( !Platform.isSameItem( is, myPattern ) )
      {
        World w = getWorldObj();
        ItemEncodedPattern iep = (ItemEncodedPattern) is.getItem();
        ICraftingPatternDetails ph = iep.getPatternForItem( is, w );

        if ( ph != null && ph.isCraftable() )
        {
          progress = 0;
          myPattern = is;
          myPlan = ph;
        }
      }
    }
    else
    {
      progress = 0;
      forcePlan = false;
      myPlan = null;
      myPattern = null;
      pushDirection = ForgeDirection.UNKNOWN;
    }

    updateSleepiness();
  }

  private void updateSleepiness()
  {
    boolean wasEnabled = isAwake;
    isAwake = myPlan != null && hasMats() || canPush();
    if ( wasEnabled != isAwake )
    {
      try
      {
        if ( isAwake )
          gridProxy.getTick().wakeDevice( gridProxy.getNode() );
        else
          gridProxy.getTick().sleepDevice( gridProxy.getNode() );
      }
      catch (GridAccessException e)
      {
        // :P
      }
    }
  }

  private boolean canPush()
  {
    return inv.getStackInSlot( 9 ) != null;
  }

  @Override
  public int getInstalledUpgrades(Upgrades u)
  {
    return upgrades.getInstalledUpgrades( u );
  }

  protected int getUpgradeSlots()
  {
    return 5;
  }

  @TileEvent(TileEventType.NETWORK_READ)
  public boolean readFromStream_TileMolecularAssembler(ByteBuf data)
  {
    boolean oldPower = isPowered;
    isPowered = data.readBoolean();
    return isPowered != oldPower;
  }

  @TileEvent(TileEventType.NETWORK_WRITE)
  public void writeToStream_TileMolecularAssembler(ByteBuf data)
  {
    data.writeBoolean( isPowered );
  }

  @TileEvent(TileEventType.WORLD_NBT_WRITE)
  public void writeToNBT_TileMolecularAssembler(NBTTagCompound data)
  {
    if ( forcePlan && myPlan != null )
    {
      ItemStack pattern = myPlan.getPattern();
      if ( pattern != null )
      {
        NBTTagCompound compound = new NBTTagCompound();
        pattern.writeToNBT( compound );
        data.setTag( "myPlan", compound );
        data.setInteger( "pushDirection", pushDirection.ordinal() );
      }
    }

    upgrades.writeToNBT( data, "upgrades" );
    inv.writeToNBT( data, "inv" );
    settings.writeToNBT( data );
  }

  @TileEvent(TileEventType.WORLD_NBT_READ)
  public void readFromNBT_TileMolecularAssembler(NBTTagCompound data)
  {
    if ( data.hasKey( "myPlan" ) )
    {
      ItemStack myPat = ItemStack.loadItemStackFromNBT( data.getCompoundTag( "myPlan" ) );

      if ( myPat != null && myPat.getItem() instanceof ItemEncodedPattern )
      {
        World w = getWorldObj();
        ItemEncodedPattern iep = (ItemEncodedPattern) myPat.getItem();
        ICraftingPatternDetails ph = iep.getPatternForItem( myPat, w );
        if ( ph != null && ph.isCraftable() )
        {
          forcePlan = true;
          myPlan = ph;
          pushDirection = ForgeDirection.getOrientation( data.getInteger( "pushDirection" ) );
        }
      }
    }

    upgrades.readFromNBT( data, "upgrades" );
    inv.readFromNBT( data, "inv" );
    settings.readFromNBT( data );
    recalculatePlan();
  }

  public TileMolecularAssembler() {
    settings.registerSetting( Settings.REDSTONE_CONTROLLED, RedstoneMode.IGNORE );
    inv.setMaxStackSize( 1 );
    gridProxy.setIdlePowerUsage( 0.0 );
  }

  @Override
  public boolean isItemValidForSlot(int i, ItemStack itemstack)
  {
    if ( i >= 9 )
      return false;

    if ( hasPattern() )
      return myPlan.isValidItemForSlot( i, itemstack, getWorldObj() );

    return false;
  }

  @Override
  public boolean acceptsPlans()
  {
    return inv.getStackInSlot( 10 ) == null;
  }

  private boolean hasPattern()
  {
    return myPlan != null && inv.getStackInSlot( 10 ) != null;
  }

  @Override
  public boolean canExtractItem(int i, ItemStack itemstack, int j)
  {
    return i == 9;
  }

  @Override
  public IInventory getInternalInventory()
  {
    return inv;
  }

  @Override
  public void onChangeInventory(IInventory inv, int slot, InvOperation mc, ItemStack removed, ItemStack added)
  {
    if ( inv == this.inv )
      recalculatePlan();
  }

  @Override
  public int[] getAccessibleSlotsBySide(ForgeDirection whichSide)
  {
    return sides;
  }

  @Override
  public AECableType getCableConnectionType(ForgeDirection dir)
  {
    return AECableType.COVERED;
  }

  @Override
  public DimensionalCoord getLocation()
  {
    return new DimensionalCoord( this );
  }

  @Override
  public IConfigManager getConfigManager()
  {
    return settings;
  }

  @Override
  public IInventory getInventoryByName(String name)
  {
    if ( name.equals( "upgrades" ) )
      return upgrades;

    if ( name.equals( "mac" ) )
      return inv;

    return null;
  }

  @Override
  public void updateSetting(IConfigManager manager, Enum settingName, Enum newValue)
  {

  }

  @Override
  public int getInventoryStackLimit()
  {
    return 1;
  }

  public int getCraftingProgress()
  {
    return (int) progress;
  }

  @Override
  public void getDrops(World w, int x, int y, int z, ArrayList<ItemStack> drops)
  {
    super.getDrops( w, x, y, z, drops );

    for (int h = 0; h < upgrades.getSizeInventory(); h++)
    {
      ItemStack is = upgrades.getStackInSlot( h );
      if ( is != null )
        drops.add( is );
    }
  }

  @Override
  public TickingRequest getTickingRequest(IGridNode node)
  {
    recalculatePlan();
    updateSleepiness();
    return new TickingRequest( 1, 1, !isAwake, false );
  }

  private boolean hasMats()
  {
    if ( myPlan == null )
      return false;

    for (int x = 0; x < craftingInv.getSizeInventory(); x++)
      craftingInv.setInventorySlotContents( x, inv.getStackInSlot( x ) );

    return myPlan.getOutput( craftingInv, getWorldObj() ) != null;
  }

  @Override
  public TickRateModulation tickingRequest(IGridNode node, int TicksSinceLastCall)
  {
    if ( inv.getStackInSlot( 9 ) != null )
    {
      pushOut( inv.getStackInSlot( 9 ) );

      // did it eject?
      if ( inv.getStackInSlot( 9 ) == null )
        markDirty();

      ejectHeldItems();
      updateSleepiness();
      progress = 0;
      return isAwake ? TickRateModulation.IDLE : TickRateModulation.SLEEP;
    }

    if ( myPlan == null )
    {
      updateSleepiness();
      return TickRateModulation.SLEEP;
    }

    if ( reboot )
      TicksSinceLastCall = 1;

    if ( !isAwake )
      return TickRateModulation.SLEEP;

    reboot = false;
    int speed = 10;
    switch (upgrades.getInstalledUpgrades( Upgrades.SPEED ))
    {
    case 0:
      progress += userPower( TicksSinceLastCall, speed = 10, 1.0 );
      break;
    case 1:
      progress += userPower( TicksSinceLastCall, speed = 13, 1.3 );
      break;
    case 2:
      progress += userPower( TicksSinceLastCall, speed = 17, 1.7 );
      break;
    case 3:
      progress += userPower( TicksSinceLastCall, speed = 20, 2.0 );
      break;
    case 4:
      progress += userPower( TicksSinceLastCall, speed = 25, 2.5 );
      break;
    case 5:
      progress += userPower( TicksSinceLastCall, speed = 50, 5.0 );
      break;
    }

    if ( progress >= 100 )
    {
      for (int x = 0; x < craftingInv.getSizeInventory(); x++)
        craftingInv.setInventorySlotContents( x, inv.getStackInSlot( x ) );

      progress = 0;
      ItemStack output = myPlan.getOutput( craftingInv, getWorldObj() );
      if ( output != null )
      {
        FMLCommonHandler.instance().firePlayerCraftingEvent( Platform.getPlayer( (WorldServer) getWorldObj() ), output, craftingInv );

        pushOut( output.copy() );

        for (int x = 0; x < craftingInv.getSizeInventory(); x++)
          inv.setInventorySlotContents( x, Platform.getContainerItem( craftingInv.getStackInSlot( x ) ) );

        if ( inv.getStackInSlot( 10 ) == null )
        {
          forcePlan = false;
          myPlan = null;
          pushDirection = ForgeDirection.UNKNOWN;
        }

        ejectHeldItems();

        try
        {
          TargetPoint where = new TargetPoint( worldObj.provider.dimensionId, xCoord, yCoord, zCoord, 32 );
          IAEItemStack item = AEItemStack.create( output );
          NetworkHandler.instance.sendToAllAround( new PacketAssemblerAnimation( xCoord, yCoord, zCoord, (byte) speed, item ), where );
        }
        catch (IOException e)
        {
          // ;P
        }

        markDirty();
        updateSleepiness();
        return isAwake ? TickRateModulation.IDLE : TickRateModulation.SLEEP;
      }
    }

    return TickRateModulation.FASTER;
  }

  private void ejectHeldItems()
  {
    if ( inv.getStackInSlot( 9 ) == null )
    {
      for (int x = 0; x < 9; x++)
      {
        ItemStack is = inv.getStackInSlot( x );
        if ( is != null )
        {
          if ( myPlan == null || !myPlan.isValidItemForSlot( x, is, worldObj ) )
          {
            inv.setInventorySlotContents( 9, is );
            inv.setInventorySlotContents( x, null );
            markDirty();
            return;
          }
        }
      }
    }
  }

  private int userPower(int ticksPassed, int bonusValue, double acceleratorTax)
  {
    try
    {
      return (int) (gridProxy.getEnergy().extractAEPower( ticksPassed * bonusValue * acceleratorTax, Actionable.MODULATE, PowerMultiplier.CONFIG ) / acceleratorTax);
    }
    catch (GridAccessException e)
    {
      return 0;
    }
  }

  private void pushOut(ItemStack output)
  {
    if ( pushDirection == ForgeDirection.UNKNOWN )
    {
      for (ForgeDirection d : ForgeDirection.VALID_DIRECTIONS)
        output = pushTo( output, d );
    }
    else
      output = pushTo( output, pushDirection );

    if ( output == null && forcePlan )
    {
      forcePlan = false;
      recalculatePlan();
    }

    inv.setInventorySlotContents( 9, output );
  }

  private ItemStack pushTo(ItemStack output, ForgeDirection d)
  {
    if ( output == null )
      return output;

    TileEntity te = getWorldObj().getTileEntity( xCoord + d.offsetX, yCoord + d.offsetY, zCoord + d.offsetZ );

    if ( te == null )
      return output;

    InventoryAdaptor adaptor = InventoryAdaptor.getAdaptor( te, d.getOpposite() );

    if ( adaptor == null )
      return output;

    int size = output.stackSize;
    output = adaptor.addItems( output );
    int newSize = output == null ? 0 : output.stackSize;

    if ( size != newSize )
      markDirty();

    return output;
  }

  boolean isPowered = false;

  @MENetworkEventSubscribe
  public void onPowerEvent(MENetworkPowerStatusChange p)
  {
    updatePowerState();
  }

  private void updatePowerState()
  {
    boolean newState = false;

    try
    {
      newState = gridProxy.isActive() && gridProxy.getEnergy().extractAEPower( 1, Actionable.SIMULATE, PowerMultiplier.CONFIG ) > 0.0001;
    }
    catch (GridAccessException ignored)
    {

    }

    if ( newState != isPowered )
    {
      isPowered = newState;
      markForUpdate();
    }
  }

  @Override
  public boolean isPowered()
  {
    return isPowered;
  }

  @Override
  public boolean isActive()
  {
    return isPowered;
  }

}
TOP

Related Classes of appeng.tile.crafting.TileMolecularAssembler

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.