/*
* Copyright (c) CovertJaguar, 2014 http://railcraft.info
*
* This code is the property of CovertJaguar
* and may only be used with explicit written
* permission unless otherwise specified on the
* license page at http://railcraft.info/wiki/info:license.
*/
package mods.railcraft.common.blocks.machine.alpha;
import buildcraft.api.statements.IActionExternal;
import java.util.*;
import cofh.api.energy.EnergyStorage;
import cofh.api.energy.IEnergyHandler;
import mods.railcraft.common.blocks.RailcraftTileEntity;
import net.minecraft.inventory.Container;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.InventoryCrafting;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.IIcon;
import net.minecraftforge.common.util.ForgeDirection;
import mods.railcraft.common.blocks.machine.IEnumMachine;
import mods.railcraft.common.blocks.machine.TileMachineBase;
import mods.railcraft.common.core.RailcraftConfig;
import mods.railcraft.common.gui.EnumGui;
import mods.railcraft.common.gui.GuiHandler;
import mods.railcraft.common.plugins.buildcraft.actions.Actions;
import mods.railcraft.common.plugins.buildcraft.triggers.IHasWork;
import mods.railcraft.common.util.crafting.RollingMachineCraftingManager;
import mods.railcraft.common.util.inventory.AdjacentInventoryCache;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.inventory.InventoryConcatenator;
import mods.railcraft.common.util.inventory.InventorySorter;
import mods.railcraft.common.util.inventory.StandaloneInventory;
import mods.railcraft.common.util.inventory.filters.ArrayStackFilter;
import mods.railcraft.common.util.inventory.wrappers.IInvSlot;
import mods.railcraft.common.util.inventory.wrappers.InventoryIterator;
import mods.railcraft.common.util.misc.Game;
import net.minecraft.inventory.ISidedInventory;
public class TileRollingMachine extends TileMachineBase implements IEnergyHandler, ISidedInventory, IHasWork {
private final static int PROCESS_TIME = 100;
private final static int ACTIVATION_POWER = 50;
private final static int MAX_RECEIVE = 1000;
private final static int MAX_ENERGY = ACTIVATION_POWER * PROCESS_TIME;
private final static int SLOT_RESULT = 0;
private static final int[] SLOTS = InvTools.buildSlotArray(0, 10);
private final InventoryCrafting craftMatrix = new InventoryCrafting(new RollingContainer(), 3, 3);
private final StandaloneInventory invResult = new StandaloneInventory(1, "invResult", (IInventory) this);
private final IInventory inv = InventoryConcatenator.make().add(invResult).add(craftMatrix);
private EnergyStorage energyStorage;
public boolean useLast;
private boolean isWorking, paused;
private ItemStack currentReceipe;
private int progress;
private final AdjacentInventoryCache cache = new AdjacentInventoryCache(this, tileCache, null, InventorySorter.SIZE_DECENDING);
private final Set<IActionExternal> actions = new HashSet<IActionExternal>();
private static class RollingContainer extends Container {
@Override
public boolean canInteractWith(EntityPlayer entityplayer) {
return true;
}
}
public TileRollingMachine() {
if (RailcraftConfig.machinesRequirePower())
energyStorage = new EnergyStorage(MAX_ENERGY, MAX_RECEIVE);
}
@Override
public IEnumMachine getMachineType() {
return EnumMachineAlpha.ROLLING_MACHINE;
}
@Override
public IIcon getIcon(int side) {
return getMachineType().getTexture(side);
}
@Override
public void writeToNBT(NBTTagCompound data) {
super.writeToNBT(data);
data.setInteger("progress", progress);
if (energyStorage != null)
energyStorage.writeToNBT(data);
invResult.writeToNBT("invResult", data);
InvTools.writeInvToNBT(craftMatrix, "Crafting", data);
}
@Override
public void readFromNBT(NBTTagCompound data) {
super.readFromNBT(data);
progress = data.getInteger("progress");
if (energyStorage != null)
energyStorage.readFromNBT(data);
invResult.readFromNBT("invResult", data);
InvTools.readInvFromNBT(craftMatrix, "Crafting", data);
}
@Override
public boolean openGui(EntityPlayer player) {
if (player.getDistanceSq(xCoord + 0.5, yCoord + 0.5, zCoord + 0.5) > 64D)
return false;
GuiHandler.openGui(EnumGui.ROLLING_MACHINE, player, worldObj, xCoord, yCoord, zCoord);
return true;
}
@Override
public void markDirty() {
craftMatrix.markDirty();
}
@Override
public void onBlockRemoval() {
super.onBlockRemoval();
InvTools.dropInventory(inv, worldObj, xCoord, yCoord, zCoord);
}
public void setProgress(int progress) {
this.progress = progress;
}
public int getProgress() {
return progress;
}
public int getProgressScaled(int i) {
return (progress * i) / PROCESS_TIME;
}
public InventoryCrafting getCraftMatrix() {
return craftMatrix;
}
@Override
public boolean canUpdate() {
return true;
}
@Override
public void updateEntity() {
super.updateEntity();
if (Game.isNotHost(worldObj))
return;
balanceSlots();
if (clock % 16 == 0)
processActions();
if (paused)
return;
if (clock % 8 == 0) {
currentReceipe = RollingMachineCraftingManager.getInstance().findMatchingRecipe(craftMatrix, worldObj);
if (currentReceipe != null)
findMoreStuff();
}
if (currentReceipe != null && canMakeMore())
if (progress >= PROCESS_TIME) {
isWorking = false;
if (InvTools.isRoomForStack(currentReceipe, invResult)) {
currentReceipe = RollingMachineCraftingManager.getInstance().findMatchingRecipe(craftMatrix, worldObj);
if (currentReceipe != null) {
for (int i = 0; i < craftMatrix.getSizeInventory(); i++) {
craftMatrix.decrStackSize(i, 1);
}
InvTools.moveItemStack(currentReceipe, invResult);
}
useLast = false;
progress = 0;
}
} else {
isWorking = true;
if (energyStorage != null) {
int energy = energyStorage.extractEnergy(ACTIVATION_POWER, true);
if (energy >= ACTIVATION_POWER) {
progress++;
energyStorage.extractEnergy(ACTIVATION_POWER, false);
}
} else
progress++;
}
else {
progress = 0;
isWorking = false;
}
}
/**
* Evenly redistributes items between all the slots.
*/
private void balanceSlots() {
for (IInvSlot slotA : InventoryIterator.getIterable(craftMatrix)) {
ItemStack stackA = slotA.getStackInSlot();
if (stackA == null)
continue;
for (IInvSlot slotB : InventoryIterator.getIterable(craftMatrix)) {
if (slotA.getIndex() == slotB.getIndex())
continue;
ItemStack stackB = slotB.getStackInSlot();
if (stackB == null)
continue;
if (InvTools.isItemEqual(stackA, stackB))
if (stackA.stackSize > stackB.stackSize + 1) {
stackA.stackSize--;
stackB.stackSize++;
return;
}
}
}
}
private void findMoreStuff() {
Collection<IInventory> chests = cache.getAdjacentInventories();
for (IInvSlot slot : InventoryIterator.getIterable(craftMatrix)) {
ItemStack stack = slot.getStackInSlot();
if (stack != null && stack.isStackable() && stack.stackSize == 1) {
ItemStack request = InvTools.removeOneItem(chests, new ArrayStackFilter(stack));
if (request != null) {
stack.stackSize++;
break;
}
if (stack.stackSize > 1)
break;
}
}
}
@Override
public boolean hasWork() {
return isWorking;
}
public void setPaused(boolean p) {
paused = p;
}
private void processActions() {
paused = false;
for (IActionExternal action : actions) {
if (action == Actions.PAUSE)
paused = true;
}
actions.clear();
}
@Override
public void actionActivated(IActionExternal action) {
actions.add(action);
}
public boolean canMakeMore() {
if (RollingMachineCraftingManager.getInstance().findMatchingRecipe(craftMatrix, worldObj) == null)
return false;
if (useLast)
return true;
for (int i = 0; i < craftMatrix.getSizeInventory(); i++) {
ItemStack slot = craftMatrix.getStackInSlot(i);
if (slot != null && slot.stackSize <= 1)
return false;
}
return true;
}
@Override
public int[] getAccessibleSlotsFromSide(int var1) {
return SLOTS;
}
@Override
public boolean canInsertItem(int slot, ItemStack stack, int side) {
return isItemValidForSlot(slot, stack);
}
@Override
public boolean canExtractItem(int slot, ItemStack stack, int side) {
return slot == SLOT_RESULT;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
if (slot == SLOT_RESULT)
return false;
if (stack == null)
return false;
if (!stack.isStackable())
return false;
if (stack.getItem().hasContainerItem(stack))
return false;
if (getStackInSlot(slot) == null)
return false;
return true;
}
@Override
public int getSizeInventory() {
return 10;
}
@Override
public ItemStack getStackInSlot(int slot) {
return inv.getStackInSlot(slot);
}
@Override
public ItemStack decrStackSize(int slot, int count) {
return inv.decrStackSize(slot, count);
}
@Override
public void setInventorySlotContents(int slot, ItemStack stack) {
inv.setInventorySlotContents(slot, stack);
}
@Override
public ItemStack getStackInSlotOnClosing(int slot) {
return inv.getStackInSlotOnClosing(slot);
}
@Override
public void openInventory() {
}
@Override
public void closeInventory() {
}
@Override
public boolean hasCustomInventoryName() {
return false;
}
@Override
public int getInventoryStackLimit() {
return 64;
}
@Override
public boolean isUseableByPlayer(EntityPlayer player) {
return RailcraftTileEntity.isUseableByPlayerHelper(this, player);
}
@Override
public String getInventoryName() {
return getName();
}
public EnergyStorage getEnergyStorage() {
return energyStorage;
}
@Override
public boolean canConnectEnergy(ForgeDirection side) {
return energyStorage != null;
}
@Override
public int receiveEnergy(ForgeDirection from, int maxReceive, boolean simulate) {
if (energyStorage == null)
return 0;
return energyStorage.receiveEnergy(maxReceive, simulate);
}
@Override
public int extractEnergy(ForgeDirection from, int maxExtract, boolean simulate) {
return 0;
}
@Override
public int getEnergyStored(ForgeDirection from) {
if (energyStorage == null)
return 0;
return energyStorage.getEnergyStored();
}
@Override
public int getMaxEnergyStored(ForgeDirection from) {
if (energyStorage == null)
return 0;
return energyStorage.getMaxEnergyStored();
}
}