Package xk.xact.core.tileentities

Source Code of xk.xact.core.tileentities.TileWorkbench

package xk.xact.core.tileentities;


import cpw.mods.fml.common.registry.GameRegistry;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.item.crafting.CraftingManager;
import net.minecraft.nbt.NBTBase;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.nbt.NBTTagList;
import net.minecraft.network.INetworkManager;
import net.minecraft.network.packet.Packet;
import net.minecraft.network.packet.Packet132TileEntityData;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.MinecraftForge;
import net.minecraftforge.event.entity.player.PlayerDestroyItemEvent;
import xk.xact.api.OverriddenBlock;
import xk.xact.inventory.Inventory;
import xk.xact.inventory.InventoryUtils;
import xk.xact.util.Utils;

import java.util.HashMap;
import java.util.Map;

// the TE for the vanilla crafting table
public class TileWorkbench extends TileEntity implements ISidedInventory, OverriddenBlock {

  public Inventory craftingGrid; // size 9
  public Inventory outputInv; // size 1
  public Inventory subGrid; // size 9;

  public TileWorkbench() {
    this.craftingGrid = new Inventory( 9, "craftingGrid" );
    this.outputInv = new Inventory( 1, "outputInv" ) {

      @Override
      public ItemStack decrStackSize(int slotID, int amount) {
        ItemStack stackInSlot = getStackInSlot( slotID );
        if( stackInSlot != null ) {
          setInventorySlotContents( slotID, null );
        }
        return stackInSlot;
      }
    };
    this.subGrid = new Inventory( 9, "subGrid" );
  }

  ///////////////
  ///// NBT

  public void readFromNBT(NBTTagCompound compound) {
    super.readFromNBT( compound );

    craftingGrid.readFromNBT( compound );
    outputInv.readFromNBT( compound );
    subGrid.readFromNBT( compound );

    // Extra Fields
    NBTTagList list = compound.getTagList( "extraFields" );
    if( list != null ) {
      int count = list.tagCount();
      for(int i=0; i<count; i++) {
        NBTBase tag = list.tagAt( i );
        if( tag != null ) {
          Object field = Utils.readFieldFromNBT( tag );
          String name = tag.getName();
          if( field != null ) {
            extraFields.put( name, field );
          }
        }
      }
    }
  }

  public void writeToNBT(NBTTagCompound compound) {
    super.writeToNBT( compound );

    craftingGrid.writeToNBT( compound );
    outputInv.writeToNBT( compound );
    subGrid.writeToNBT( compound );

    // Extra Fields
    NBTTagList list = new NBTTagList( "extraFields" );
    for(String key : extraFields.keySet()) {
      Utils.appendFieldToNBTList( list, key, extraFields.get( key ) );
    }
  }

  @Override
  public void onDataPacket(INetworkManager net, Packet132TileEntityData packet) {
    if( packet.actionType == 0 )
      readFromNBT( packet.data );
  }

  @Override
  public Packet getDescriptionPacket() {
    NBTTagCompound nbt = new NBTTagCompound();
    writeToNBT( nbt );
    return new Packet132TileEntityData( xCoord, yCoord, zCoord, 0, nbt );
  }

  /* ********** Automation ********** *

  The bottom side is for extraction, all other sides are for insertion.

  If a recipe is set:
    * the input slots will accept items if they match the items on the grid. (Insert only)
    * the output slot may allow extraction if canCraft returns true.

  If a recipe is not set:
    * the input slots will NOT accept items, and will be available from the bottom for extraction (Extract only).
    * the output slot will NOT be available.
  */

  /**
   * Whether if there is a valid recipe set in the crafting grid.
   */
  private boolean hasRecipe() {
    return outputInv.getStackInSlot( 0 ) != null;
  }

  /**
   * Whether if automation can craft the current recipe in the crafting grid.
   */
  private boolean canCraft() {
    if( !hasRecipe() )
      return false;
    InventoryCrafting grid = InventoryUtils.simulateCraftingInventory( null, subGrid );
    ItemStack result = CraftingManager.getInstance().findMatchingRecipe( grid, worldObj );
    return InventoryUtils.similarStacks( outputInv.getStackInSlot( 0 ), result, true );
  }

  /**
   * Will consume the ingredients and handle the crafting events.
   * Only used by automation.
   *
   * @param result the result of the recipe.
   */
  private void handleExtraction(ItemStack result) {
    GameRegistry.onItemCrafted( Utils.getFakePlayerFor( this ), result, subGrid );

    for( int i = 0; i < subGrid.getSizeInventory(); ++i ) {
      ItemStack stack = subGrid.getStackInSlot( i );

      if( stack != null ) {
        subGrid.decrStackSize( i, 1 );

        if( stack.getItem().hasContainerItem() ) {
          ItemStack itemContainer = stack.getItem().getContainerItemStack( stack );

          if( itemContainer.isItemStackDamageable() && itemContainer.getItemDamage() > itemContainer.getMaxDamage() ) {
            MinecraftForge.EVENT_BUS.post( new PlayerDestroyItemEvent( Utils.getFakePlayerFor( this ), itemContainer ) );
            itemContainer = null;
          }

          if( itemContainer != null && (!stack.getItem().doesContainerItemLeaveCraftingGrid( stack )) ) {
            if( subGrid.getStackInSlot( i ) == null ) {
              subGrid.setInventorySlotContents( i, itemContainer );
            } else {
              Utils.dropItemAsEntity( worldObj, xCoord, yCoord, zCoord, itemContainer );
            }
          }
        }
      }
    }
  }


  private static final int outputSide = 0;
  private static final int inputSide = 1;
  private static final int[][] slots = {
      new int[] { 0 }, // result slot
      new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9 } // grid slots.
  };

  @Override
  public int[] getAccessibleSlotsFromSide(int side) {
    if( side == 0 ) { // bottom
      if( hasRecipe() )
        return slots[outputSide];
    }
    return slots[inputSide];

    // if there is recipe set, bottom side is only the output slot; else, the input slots.
  }

  @Override
  public boolean canInsertItem(int slot, ItemStack item, int side) {
    if( side == 0 )
      return false; // Bottom side is NOT for inserting.
    if( slot < 0 || slot > 9 )
      return false; // out of bounds.
    if( slot == 0 || !hasRecipe() )
      return false; // only insert on grid slots when the recipe is set.

    // Logic reminder: at this point, the recipe is set and its a grid slot.
    ItemStack gridStack = craftingGrid.getStackInSlot( slot - 1 );
    if( gridStack == null )
      return false;

    // Must check for NBT: the vanilla workbench must be the most reliable (strict) device.
    return InventoryUtils.similarStacks( gridStack, item, true );
  }

  @Override
  public boolean canExtractItem(int slot, ItemStack item, int side) {
    if( side != 0 )
      return false; // May only extract from the bottom.
    if( slot < 0 || slot > 9 )
      return false; // out of bounds.
    if( slot == 0 ) { // output slot.
      return canCraft();
    }
    return !hasRecipe(); // can only extract from input slots if there is no recipe set.
  }

  @Override
  public int getSizeInventory() {
    return 10;
  }

  @Override
  public ItemStack getStackInSlot(int slot) {
    if( slot == 0 ) {
      if( canCraft() )
        return Utils.copyOf( outputInv.getStackInSlot( 0 ) );
      return null;
    }
    return subGrid.getStackInSlot( slot - 1 );
  }

  @Override
  public ItemStack decrStackSize(int slot, int amount) {
    if( slot == 0 ) { // output slot.
      if( hasRecipe() ) {
        ItemStack result = getStackInSlot( 0 );
        if( result != null ) {
          handleExtraction( result );
        }
        return result;
      }
      return null;
    } else {
      return subGrid.decrStackSize( slot - 1, amount );
    }
  }

  @Override
  public ItemStack getStackInSlotOnClosing(int slot) {
    return null;
  }

  @Override
  public void setInventorySlotContents(int slot, ItemStack itemstack) {
    if( slot == 0 ) {
      if( hasRecipe() ) {
        ItemStack result = getStackInSlot( 0 );
        if( result != null && itemstack == null ) { // trying to clear the slot by placing null?
          handleExtraction( result );
        }
      }
    } else {
      subGrid.setInventorySlotContents( slot-1, itemstack );
    }
  }

  @Override
  public String getInvName() {
    return "workbench";
  }

  @Override
  public boolean isInvNameLocalized() {
    return false;
  }

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

  @Override
  public boolean isUseableByPlayer(EntityPlayer player) {
    return true;
  }

  @Override
  public void openChest() { }

  @Override
  public void closeChest() { }

  @Override
  public boolean isItemValidForSlot(int slot, ItemStack item) {
    if( slot == 0 )
      return false;

    // Temp fix: Vanilla Hopper won't obey IInventory.getInventoryStackLimit()
    if( subGrid.getStackInSlot( slot - 1 ) != null )
      return false;

    ItemStack gridStack = craftingGrid.getStackInSlot( slot - 1 );
    return InventoryUtils.similarStacks( gridStack, item, true );
  }


  // ----- OverriddenBlock -----

  private Map<String, Object> extraFields = new HashMap<String, Object>();

  @Override
  @SuppressWarnings("unchecked")
  public <T> T getField(Class<T> clazz, String name) {
    return (T) extraFields.get( name );
  }

  @Override
  public <T> void setField(Class<T> clazz, String name, T value) {
    extraFields.put( name, value );
  }

}
TOP

Related Classes of xk.xact.core.tileentities.TileWorkbench

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.