private boolean canCrystalize() {
   if (crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()] == null) {
     return false;
   } else {
     ItemStack itemStackToOutput =
         CrystalizerRecipes.instance()
             .getCrystalizingResult(crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()]);
     if (itemStackToOutput == null) return false;
     if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] == null) return true;
     if (!crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].isItemEqual(itemStackToOutput))
       return false;
     int result =
         crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].stackSize
             + itemStackToOutput.stackSize;
     return result <= getInventoryStackLimit()
         && result <= crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].getMaxStackSize();
   }
 }
  public void crystalizeItem() {
    if (canCrystalize()) {
      ItemStack itemstack =
          CrystalizerRecipes.instance()
              .getCrystalizingResult(crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()]);

      if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] == null) {
        crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] = itemstack.copy();
      } else if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].getItem()
          == itemstack.getItem()) {
        crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].stackSize += itemstack.stackSize;
      }

      --crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()].stackSize;

      if (crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()].stackSize <= 0) {
        crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()] = null;
      }
    }
  }
public class TileEntityCrystalizer extends TileEntityLockable
    implements IUpdatePlayerListBox, ISidedInventory {
  public enum slotEnum {
    INPUT_SLOT,
    OUTPUT_SLOT
  }

  private static final int[] slotsTop = new int[] {slotEnum.INPUT_SLOT.ordinal()};
  private static final int[] slotsBottom = new int[] {slotEnum.OUTPUT_SLOT.ordinal()};
  private static final int[] slotsSides = new int[] {slotEnum.INPUT_SLOT.ordinal()};
  private ItemStack[] crystalizerItemStackArray = new ItemStack[2];
  private int timeCanCrystalize;
  private int currentItemCrystalizeTime;
  private int ticksCrystalizingItemSoFar;
  private int ticksPerItem;
  private String crystalizerCustomName;
  public int crystalizeTime = 200;

  @Override
  public boolean shouldRefresh(
      World parWorld, BlockPos parPos, IBlockState parOldState, IBlockState parNewState) {
    return false;
  }

  @Override
  public int getSizeInventory() {
    return crystalizerItemStackArray.length;
  }

  @Override
  public ItemStack getStackInSlot(int index) {
    return crystalizerItemStackArray[index];
  }

  @Override
  public ItemStack decrStackSize(int index, int count) {
    if (crystalizerItemStackArray[index] != null) {
      ItemStack itemstack;

      if (crystalizerItemStackArray[index].stackSize <= count) {
        itemstack = crystalizerItemStackArray[index];
        crystalizerItemStackArray[index] = null;
        return itemstack;
      } else {
        itemstack = crystalizerItemStackArray[index].splitStack(count);

        if (crystalizerItemStackArray[index].stackSize == 0) {
          crystalizerItemStackArray[index] = null;
        }

        return itemstack;
      }
    } else {
      return null;
    }
  }

  @Override
  public ItemStack getStackInSlotOnClosing(int index) {
    if (crystalizerItemStackArray[index] != null) {
      ItemStack itemstack = crystalizerItemStackArray[index];
      crystalizerItemStackArray[index] = null;
      return itemstack;
    } else {
      return null;
    }
  }

  @Override
  public void setInventorySlotContents(int index, ItemStack stack) {
    boolean isSameItemStackAlreadyInSlot =
        stack != null
            && stack.isItemEqual(crystalizerItemStackArray[index])
            && ItemStack.areItemStackTagsEqual(stack, crystalizerItemStackArray[index]);
    crystalizerItemStackArray[index] = stack;

    if (stack != null && stack.stackSize > getInventoryStackLimit()) {
      stack.stackSize = getInventoryStackLimit();
    }

    if (index == slotEnum.INPUT_SLOT.ordinal() && !isSameItemStackAlreadyInSlot) {
      ticksPerItem = timeToCrystalizeOneItem(stack);
      ticksCrystalizingItemSoFar = 0;
      markDirty();
    }
  }

  @Override
  public String getName() {
    return hasCustomName() ? crystalizerCustomName : "container.crystalizer";
  }

  @Override
  public boolean hasCustomName() {
    return crystalizerCustomName != null && crystalizerCustomName.length() > 0;
  }

  public void setCustomInventoryName(String parCustomName) {
    crystalizerCustomName = parCustomName;
  }

  @Override
  public void readFromNBT(NBTTagCompound compound) {
    super.readFromNBT(compound);
    NBTTagList nbttaglist = compound.getTagList("Items", 10);
    crystalizerItemStackArray = new ItemStack[getSizeInventory()];

    for (int i = 0; i < nbttaglist.tagCount(); ++i) {
      NBTTagCompound nbtTagCompound = nbttaglist.getCompoundTagAt(i);
      byte b0 = nbtTagCompound.getByte("Slot");

      if (b0 >= 0 && b0 < crystalizerItemStackArray.length) {
        crystalizerItemStackArray[b0] = ItemStack.loadItemStackFromNBT(nbtTagCompound);
      }
    }

    timeCanCrystalize = compound.getShort("CrystalizeTime");
    ticksCrystalizingItemSoFar = compound.getShort("SubmergeTime");
    ticksPerItem = compound.getShort("SubmergeTimeTotal");

    if (compound.hasKey("CustomName", 8)) {
      crystalizerCustomName = compound.getString("CustomName");
    }
  }

  @Override
  public void writeToNBT(NBTTagCompound compound) {
    super.writeToNBT(compound);
    compound.setShort("CrystalizeTime", (short) timeCanCrystalize);
    compound.setShort("SubmergeTime", (short) ticksCrystalizingItemSoFar);
    compound.setShort("SubmergeTimeTotal", (short) ticksPerItem);
    NBTTagList nbttaglist = new NBTTagList();

    for (int i = 0; i < crystalizerItemStackArray.length; ++i) {
      if (crystalizerItemStackArray[i] != null) {
        NBTTagCompound nbtTagCompound = new NBTTagCompound();
        nbtTagCompound.setByte("Slot", (byte) i);
        crystalizerItemStackArray[i].writeToNBT(nbtTagCompound);
        nbttaglist.appendTag(nbtTagCompound);
      }
    }

    compound.setTag("Items", nbttaglist);

    if (hasCustomName()) {
      compound.setString("CustomName", crystalizerCustomName);
    }
  }

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

  public boolean crystalizingSomething() {
    return true;
  }

  @SideOnly(Side.CLIENT)
  public static boolean func_174903_a(IInventory parIInventory) {
    return true;
  }

  @Override
  public void update() {
    boolean hasBeenCrystalizing = crystalizingSomething();
    boolean changedCrystalizingState = false;

    if (crystalizingSomething()) {
      --timeCanCrystalize;
    }

    if (!worldObj.isRemote) {
      if (crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()] != null) {
        if (!crystalizingSomething() && canCrystalize()) {
          timeCanCrystalize = 150;

          if (crystalizingSomething()) {
            changedCrystalizingState = true;
          }
        }

        if (crystalizingSomething() && canCrystalize()) {
          ++ticksCrystalizingItemSoFar;

          if (ticksCrystalizingItemSoFar == ticksPerItem) {
            ticksCrystalizingItemSoFar = 0;
            ticksPerItem = timeToCrystalizeOneItem(crystalizerItemStackArray[0]);
            crystalizeItem();
            changedCrystalizingState = true;
          }
        } else {
          ticksCrystalizingItemSoFar = 0;
        }
      }

      if (hasBeenCrystalizing != crystalizingSomething()) {
        changedCrystalizingState = true;
        BlockCrystalizer.changeBlockBasedOnCrystalizingStatus(
            crystalizingSomething(), worldObj, pos);
      }
    }

    if (changedCrystalizingState) {
      markDirty();
    }
  }

  public int timeToCrystalizeOneItem(ItemStack parItemStack) {
    return crystalizeTime;
  }

  private boolean canCrystalize() {
    if (crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()] == null) {
      return false;
    } else {
      ItemStack itemStackToOutput =
          CrystalizerRecipes.instance()
              .getCrystalizingResult(crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()]);
      if (itemStackToOutput == null) return false;
      if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] == null) return true;
      if (!crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].isItemEqual(itemStackToOutput))
        return false;
      int result =
          crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].stackSize
              + itemStackToOutput.stackSize;
      return result <= getInventoryStackLimit()
          && result <= crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].getMaxStackSize();
    }
  }

  public void crystalizeItem() {
    if (canCrystalize()) {
      ItemStack itemstack =
          CrystalizerRecipes.instance()
              .getCrystalizingResult(crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()]);

      if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] == null) {
        crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()] = itemstack.copy();
      } else if (crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].getItem()
          == itemstack.getItem()) {
        crystalizerItemStackArray[slotEnum.OUTPUT_SLOT.ordinal()].stackSize += itemstack.stackSize;
      }

      --crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()].stackSize;

      if (crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()].stackSize <= 0) {
        crystalizerItemStackArray[slotEnum.INPUT_SLOT.ordinal()] = null;
      }
    }
  }

  @Override
  public boolean isUseableByPlayer(EntityPlayer playerIn) {
    return worldObj.getTileEntity(pos) != this
        ? false
        : playerIn.getDistanceSq(pos.getX() + 0.5D, pos.getY() + 0.5D, pos.getZ() + 0.5D) <= 64.0D;
  }

  @Override
  public void openInventory(EntityPlayer playerIn) {}

  @Override
  public void closeInventory(EntityPlayer playerIn) {}

  @Override
  public boolean isItemValidForSlot(int index, ItemStack stack) {
    return index == slotEnum.INPUT_SLOT.ordinal() ? true : false;
  }

  @Override
  public int[] getSlotsForFace(EnumFacing side) {
    return side == EnumFacing.DOWN ? slotsBottom : (side == EnumFacing.UP ? slotsTop : slotsSides);
  }

  @Override
  public boolean canInsertItem(int index, ItemStack itemStackIn, EnumFacing direction) {
    return isItemValidForSlot(index, itemStackIn);
  }

  @Override
  public boolean canExtractItem(int parSlotIndex, ItemStack parStack, EnumFacing parFacing) {
    return true;
  }

  @Override
  public String getGuiID() {
    return "metalmagics:crystalizer";
  }

  @Override
  public Container createContainer(InventoryPlayer playerInventory, EntityPlayer playerIn) {
    System.out.println("TileEntityCrystalizer createContainer()");
    return new ContainerCrystalizer(playerInventory, this);
  }

  @Override
  public int getField(int id) {
    switch (id) {
      case 0:
        return timeCanCrystalize;
      case 1:
        return currentItemCrystalizeTime;
      case 2:
        return ticksCrystalizingItemSoFar;
      case 3:
        return ticksPerItem;
      default:
        return 0;
    }
  }

  @Override
  public void setField(int id, int value) {
    switch (id) {
      case 0:
        timeCanCrystalize = value;
        break;
      case 1:
        currentItemCrystalizeTime = value;
        break;
      case 2:
        ticksCrystalizingItemSoFar = value;
        break;
      case 3:
        ticksPerItem = value;
        break;
      default:
        break;
    }
  }

  @Override
  public int getFieldCount() {
    return 4;
  }

  @Override
  public void clear() {
    for (int i = 0; i < crystalizerItemStackArray.length; ++i) {
      crystalizerItemStackArray[i] = null;
    }
  }
}