/*
* 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 mods.railcraft.api.core.items.IStackFilter;
import mods.railcraft.api.crafting.IBlastFurnaceRecipe;
import mods.railcraft.api.crafting.RailcraftCraftingManager;
import mods.railcraft.common.blocks.RailcraftBlocks;
import mods.railcraft.common.blocks.machine.IEnumMachine;
import mods.railcraft.common.blocks.machine.MultiBlockPattern;
import mods.railcraft.common.blocks.machine.TileMultiBlock;
import mods.railcraft.common.blocks.machine.TileMultiBlockOven;
import mods.railcraft.common.gui.EnumGui;
import mods.railcraft.common.gui.GuiHandler;
import mods.railcraft.common.plugins.forge.FuelPlugin;
import mods.railcraft.common.util.inventory.AdjacentInventoryCache;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.inventory.InventorySorter;
import mods.railcraft.common.util.inventory.wrappers.InventoryMapper;
import mods.railcraft.common.util.misc.Game;
import mods.railcraft.common.util.misc.ITileFilter;
import net.minecraft.block.Block;
import net.minecraft.block.material.Material;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.inventory.IInventory;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraft.world.World;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
public class TileBlastFurnace extends TileMultiBlockOven implements ISidedInventory {
public static final IStackFilter INPUT_FILTER = new IStackFilter() {
@Override
public boolean matches(ItemStack stack) {
return RailcraftCraftingManager.blastFurnace.getRecipe(stack) != null;
}
};
public static final IStackFilter FUEL_FILTER = new IStackFilter() {
@Override
public boolean matches(ItemStack stack) {
return stack != null && InvTools.isItemEqual(stack, RailcraftCraftingManager.blastFurnace.getFuels());
}
};
public static final int SLOT_INPUT = 0;
public static final int SLOT_FUEL = 1;
public static final int SLOT_OUTPUT = 2;
private static final int FUEL_PER_TICK = 5;
private static final int[] SLOTS = InvTools.buildSlotArray(0, 3);
private final static List<MultiBlockPattern> patterns = new ArrayList<MultiBlockPattern>();
private final IInventory invFuel = new InventoryMapper(this, SLOT_FUEL, 1);
private final IInventory invInput = new InventoryMapper(this, SLOT_INPUT, 1);
private final IInventory invOutput = new InventoryMapper(this, SLOT_OUTPUT, 1);
private final AdjacentInventoryCache invCache = new AdjacentInventoryCache(this, tileCache, new ITileFilter() {
@Override
public boolean matches(TileEntity tile) {
if (tile instanceof TileBlastFurnace)
return false;
if (tile instanceof IInventory)
return ((IInventory) tile).getSizeInventory() >= 27;
return false;
}
}, InventorySorter.SIZE_DECENDING);
static {
char[][][] map = {
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'B', 'W', 'B', 'O'},
{'O', 'W', 'B', 'W', 'O'},
{'O', 'B', 'W', 'B', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'B', 'A', 'B', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'B', 'A', 'B', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'},
{'O', 'O', 'O', 'O', 'O'}
}
};
patterns.add(new MultiBlockPattern(map, 2, 1, 2));
}
/**
* The number of ticks that the furnace will keep burning
*/
public int burnTime = 0;
/**
* The number of ticks that a fresh copy of the currently-burning item would
* keep the furnace burning for
*/
public int currentItemBurnTime = 0;
public boolean clientBurning = false;
private int finishedAt;
public TileBlastFurnace() {
super("railcraft.gui.blast.furnace", 3, patterns);
}
public static void placeBlastFurnace(World world, int x, int y, int z, ItemStack input, ItemStack output, ItemStack fuel) {
for (MultiBlockPattern pattern : TileBlastFurnace.patterns) {
Map<Character, Integer> blockMapping = new HashMap<Character, Integer>();
blockMapping.put('B', EnumMachineAlpha.BLAST_FURNACE.ordinal());
blockMapping.put('W', EnumMachineAlpha.BLAST_FURNACE.ordinal());
TileEntity tile = pattern.placeStructure(world, x, y, z, RailcraftBlocks.getBlockMachineAlpha(), blockMapping);
if (tile instanceof TileBlastFurnace) {
TileBlastFurnace master = (TileBlastFurnace) tile;
master.inv.setInventorySlotContents(TileBlastFurnace.SLOT_INPUT, input);
master.inv.setInventorySlotContents(TileBlastFurnace.SLOT_OUTPUT, output);
}
return;
}
}
@Override
public IEnumMachine getMachineType() {
return EnumMachineAlpha.BLAST_FURNACE;
}
@Override
public IIcon getIcon(int side) {
if (side > 1 && getPatternMarker() == 'W' && isStructureValid()) {
if (isBurning())
return getMachineType().getTexture(7);
return getMachineType().getTexture(6);
}
return getMachineType().getTexture(0);
}
@Override
protected boolean isMapPositionValid(int i, int j, int k, char mapPos) {
Block block = worldObj.getBlock(i, j, k);
switch (mapPos) {
case 'O':
if (block != RailcraftBlocks.getBlockMachineAlpha() || worldObj.getBlockMetadata(i, j, k) != getBlockMetadata())
return true;
break;
case 'B':
case 'W':
if (block == RailcraftBlocks.getBlockMachineAlpha() && worldObj.getBlockMetadata(i, j, k) == getBlockMetadata())
return true;
break;
case 'A':
if (block.isAir(worldObj, i, j, k) || block.getMaterial() == Material.lava)
return true;
break;
}
return false;
}
@Override
public int getTotalCookTime() {
ItemStack input = getStackInSlot(SLOT_INPUT);
IBlastFurnaceRecipe recipe = RailcraftCraftingManager.blastFurnace.getRecipe(input);
if (recipe != null)
return recipe.getCookTime();
return 1;
}
@Override
public int getBurnProgressScaled(int i) {
if (burnTime <= 0 || currentItemBurnTime <= 0)
return 0;
int scale = burnTime * i / currentItemBurnTime;
scale = Math.min(scale, i);
scale = Math.max(scale, 0);
return scale;
}
private void setLavaIdle() {
int xLava = xCoord + 1;
int yLava = yCoord + 1;
int zLava = zCoord + 1;
if (worldObj.isAirBlock(xLava, yLava, zLava))
worldObj.setBlock(xLava, yLava, zLava, Blocks.lava, 7, 3);
}
private void setLavaBurn() {
int xLava = xCoord + 1;
int yLava = yCoord + 1;
int zLava = zCoord + 1;
if (worldObj.isAirBlock(xLava, yLava, zLava))
worldObj.setBlock(xLava, yLava, zLava, Blocks.flowing_lava, 1, 3);
yLava += 1;
if (worldObj.isAirBlock(xLava, yLava, zLava))
worldObj.setBlock(xLava, yLava, zLava, Blocks.flowing_lava, 1, 3);
}
// private void destroyLava() {
// int xLava = xCoord + 1;
// int yLava = yCoord + 2;
// int zLava = zCoord + 1;
// if (worldObj.getBlock(xLava, yLava, zLava).getMaterial() == Material.lava)
// worldObj.setBlockToAir(xLava, yLava, zLava);
// yLava -= 1;
// if (worldObj.getBlock(xLava, yLava, zLava).getMaterial() == Material.lava)
// worldObj.setBlockToAir(xLava, yLava, zLava);
// }
@Override
public void updateEntity() {
super.updateEntity();
if (Game.isNotHost(getWorld()))
return;
TileBlastFurnace mBlock = (TileBlastFurnace) getMasterBlock();
if (mBlock != null)
InvTools.moveOneItem(invCache.getAdjacentInventories(), mBlock.invFuel, FUEL_FILTER);
if (isMaster()) {
boolean wasBurning = isBurning();
if (clock > finishedAt + 10)
if (cookTime <= 0)
setCooking(false);
if (burnTime >= FUEL_PER_TICK)
burnTime -= FUEL_PER_TICK;
else
burnTime = 0;
if (isBurning())
setLavaBurn();
else
setLavaIdle();
ItemStack input = getStackInSlot(SLOT_INPUT);
if (input != null && input.stackSize > 0) {
ItemStack output = getStackInSlot(SLOT_OUTPUT);
IBlastFurnaceRecipe recipe = RailcraftCraftingManager.blastFurnace.getRecipe(input);
if (recipe != null && recipe.isRoomForOutput(output)) {
if (paused) return;
if (burnTime <= FUEL_PER_TICK * 2) {
ItemStack fuel = getStackInSlot(SLOT_FUEL);
if (FUEL_FILTER.matches(fuel)) {
int itemBurnTime = FuelPlugin.getBurnTime(fuel);
if (itemBurnTime > 0) {
currentItemBurnTime = itemBurnTime + burnTime;
burnTime = currentItemBurnTime;
setInventorySlotContents(SLOT_FUEL, InvTools.depleteItem(fuel));
}
}
}
if (isBurning()) {
cookTime++;
setCooking(true);
if (cookTime >= recipe.getCookTime()) {
cookTime = 0;
finishedAt = clock;
if (output == null)
setInventorySlotContents(SLOT_OUTPUT, recipe.getOutput());
else
output.stackSize += recipe.getOutputStackSize();
decrStackSize(SLOT_INPUT, 1);
}
}
} else {
cookTime = 0;
setCooking(false);
}
} else {
cookTime = 0;
setCooking(false);
}
if (wasBurning != isBurning())
sendUpdateToClient();
}
}
@Override
public boolean openGui(EntityPlayer player) {
TileMultiBlock masterBlock = getMasterBlock();
if (masterBlock != null) {
GuiHandler.openGui(EnumGui.BLAST_FURNACE, player, worldObj, masterBlock.xCoord, masterBlock.yCoord, masterBlock.zCoord);
return true;
}
return false;
}
@Override
public void writeToNBT(NBTTagCompound data) {
super.writeToNBT(data);
data.setInteger("burnTime", burnTime);
data.setInteger("currentItemBurnTime", currentItemBurnTime);
}
@Override
public void readFromNBT(NBTTagCompound data) {
super.readFromNBT(data);
burnTime = data.getInteger("burnTime");
currentItemBurnTime = data.getInteger("currentItemBurnTime");
}
@Override
public void writePacketData(DataOutputStream data) throws IOException {
super.writePacketData(data);
data.writeBoolean(burnTime > 0);
}
@Override
public void readPacketData(DataInputStream data) throws IOException {
super.readPacketData(data);
clientBurning = data.readBoolean();
}
@Override
public boolean needsFuel() {
ItemStack fuel = getStackInSlot(SLOT_FUEL);
return fuel == null || fuel.stackSize < 8;
}
@Override
public boolean isBurning() {
TileBlastFurnace mBlock = (TileBlastFurnace) getMasterBlock();
if (mBlock != null)
if (worldObj.isRemote)
return mBlock.clientBurning;
else
return mBlock.burnTime > 0;
return false;
}
@Override
public boolean isItemValidForSlot(int slot, ItemStack stack) {
if (!super.isItemValidForSlot(slot, stack))
return false;
switch (slot) {
case SLOT_OUTPUT:
return false;
case SLOT_FUEL:
return FUEL_FILTER.matches(stack);
case SLOT_INPUT:
return INPUT_FILTER.matches(stack);
}
return false;
}
@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_OUTPUT;
}
}