/*
* 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 java.util.ArrayList;
import java.util.List;
import mods.railcraft.api.electricity.IElectricGrid;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.IIcon;
import net.minecraftforge.common.util.ForgeDirection;
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.beta.ISteamUser;
import mods.railcraft.common.blocks.machine.beta.TileBoilerFirebox;
import mods.railcraft.common.gui.EnumGui;
import mods.railcraft.common.gui.GuiHandler;
import mods.railcraft.common.items.RailcraftPartItems;
import mods.railcraft.common.fluids.Fluids;
import mods.railcraft.common.plugins.buildcraft.triggers.INeedsMaintenance;
import mods.railcraft.common.plugins.ic2.IC2Plugin;
import mods.railcraft.common.util.inventory.InvTools;
import mods.railcraft.common.util.inventory.StandaloneInventory;
import mods.railcraft.common.fluids.FluidHelper;
import mods.railcraft.common.fluids.TankManager;
import mods.railcraft.common.fluids.tanks.FakeTank;
import mods.railcraft.common.fluids.tanks.FilteredTank;
import mods.railcraft.common.plugins.forge.WorldPlugin;
import mods.railcraft.common.plugins.ic2.IMultiEmitterDelegate;
import mods.railcraft.common.plugins.ic2.TileIC2MultiEmitterDelegate;
import mods.railcraft.common.util.misc.Game;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;
/**
*
* @author CovertJaguar <http://www.railcraft.info>
*/
public class TileSteamTurbine extends TileMultiBlock implements IMultiEmitterDelegate, IFluidHandler, INeedsMaintenance, ISteamUser, IElectricGrid {
enum Texture {
END_TL(6), END_TR(7), END_BL(8), END_BR(9), SIDE_A(0), SIDE_B(10), GUAGE(11);
private final int index;
private Texture(int index) {
this.index = index;
}
public IIcon getIcon() {
return EnumMachineAlpha.TURBINE.getTexture(index);
}
}
private static final int DAMAGE_CHANCE = 200;
private static final int IC2_OUTPUT = 200;
private static final int BC_OUTPUT = 64;
private static final int STEAM_USAGE = 320;
private static final int WATER_OUTPUT = 4;
private static final List<MultiBlockPattern> patterns = new ArrayList<MultiBlockPattern>();
private static ItemStack sampleRotor = null;
public static ItemStack getSampleRotor() {
if (sampleRotor == null)
sampleRotor = RailcraftPartItems.getTurbineRotor();
return sampleRotor;
}
private final StandaloneInventory inv = new StandaloneInventory(1, this);
public float output;
private final FluidStack waterFilter = Fluids.WATER.get(2);
protected final FilteredTank tankSteam = new FilteredTank(FluidHelper.BUCKET_VOLUME * 4, Fluids.STEAM.get(), this);
protected final FilteredTank tankWater = new FilteredTank(FluidHelper.BUCKET_VOLUME * 4, Fluids.WATER.get(), this);
protected final TankManager tankManager = new TankManager();
public static final int TANK_STEAM = 0;
public static final int TANK_WATER = 1;
private byte gaugeState = 0;
// mainGauge is a renderer field
public double mainGauge;
private double energy;
private TileEntity emitterDelegate;
private final ChargeHandler chargeHandler = new ChargeHandler(this, ChargeHandler.ConnectType.BLOCK);
static {
char[][][] map1 = {
{
{'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', 'B', 'B', 'O'},
{'O', 'B', 'B', 'B', 'O'},
{'O', 'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O', 'O'},
{'O', 'B', 'W', 'B', 'O'},
{'O', 'B', 'W', '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'}
}
};
patterns.add(new MultiBlockPattern(map1));
char[][][] map2 = {
{
{'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', 'B', 'O'},
{'O', 'B', 'B', 'O'},
{'O', 'B', 'B', 'O'},
{'O', 'O', 'O', 'O'}
},
{
{'O', 'O', 'O', 'O'},
{'O', 'B', 'B', 'O'},
{'O', 'W', 'W', 'O'},
{'O', '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'}
}
};
patterns.add(new MultiBlockPattern(map2));
}
public TileSteamTurbine() {
super(patterns);
tankManager.add(tankSteam); // Steam
tankManager.add(tankWater); // Water
}
@Override
public IEnumMachine getMachineType() {
return EnumMachineAlpha.TURBINE;
}
@Override
public ChargeHandler getChargeHandler() {
return chargeHandler;
}
@Override
public void updateEntity() {
super.updateEntity();
if (Game.isHost(worldObj)) {
if (isStructureValid())
chargeHandler.tick();
double chargeNeeded = chargeHandler.getCapacity() - chargeHandler.getCharge();
if (chargeNeeded > 0) {
double draw = (chargeNeeded / IC2_OUTPUT) * BC_OUTPUT;
double e = getEnergy();
if (e < draw)
draw = e;
removeEnergy(draw);
chargeHandler.addCharge((draw / BC_OUTPUT) * IC2_OUTPUT);
}
if (isMaster()) {
addToNet();
boolean addedEnergy = false;
if (energy < BC_OUTPUT * 2) {
FluidStack steam = tankManager.drain(TANK_STEAM, STEAM_USAGE, false);
// if(steam != null) System.out.println("steam=" + steam.amount);
if (steam != null && steam.amount >= STEAM_USAGE) {
ItemStack rotor = inv.getStackInSlot(0);
if (InvTools.isItemEqual(rotor, getSampleRotor()) /*&& rotor.getItemDamage() < rotor.getMaxDamage() - 5*/) {
addedEnergy = true;
energy += BC_OUTPUT;
tankManager.drain(TANK_STEAM, STEAM_USAGE, true);
if (worldObj.rand.nextInt(4) != 0)
tankWater.fill(waterFilter, true);
if (worldObj.rand.nextInt(DAMAGE_CHANCE) == 0)
inv.setInventorySlotContents(0, InvTools.damageItem(rotor, 1));
}
}
}
output = (float) ((output * 49D + (addedEnergy ? 100D : 0D)) / 50D);
// System.out.println("output=" + output);
// System.out.println("addedEnergy=" + addedEnergy);
if (clock % 4 == 0) {
gaugeState = (byte) getOutput();
WorldPlugin.addBlockEvent(worldObj, xCoord, yCoord, zCoord, getBlockType(), 1, gaugeState);
}
}
}
TankManager tMan = getTankManager();
if (tMan != null)
tMan.outputLiquid(getOutputs(), 0, WATER_OUTPUT);
}
private IFluidHandler getOutputOnSide(ForgeDirection side) {
TileEntity tile = tileCache.getTileOnSide(side);
if (tile instanceof TileBoilerFirebox)
return (IFluidHandler) tile;
return null;
}
private IFluidHandler[] getOutputs() {
IFluidHandler[] outputs = new IFluidHandler[6];
for (int side = 2; side < 6; side++) {
ForgeDirection dir = ForgeDirection.getOrientation(side);
outputs[side] = getOutputOnSide(dir);
}
return outputs;
}
private void addToNet() {
if (emitterDelegate == null)
try {
emitterDelegate = new TileIC2MultiEmitterDelegate(this);
IC2Plugin.addTileToNet(emitterDelegate);
} catch (Throwable error) {
Game.logErrorAPI("IndustrialCraft", error, null);
}
}
private void dropFromNet() {
if (emitterDelegate != null) {
IC2Plugin.removeTileFromNet(emitterDelegate);
emitterDelegate = null;
}
}
@Override
public void onChunkUnload() {
super.onChunkUnload();
dropFromNet();
}
@Override
public void invalidate() {
super.invalidate();
dropFromNet();
}
@Override
protected void onMasterReset() {
super.onMasterReset();
dropFromNet();
}
@Override
public void onBlockRemoval() {
super.onBlockRemoval();
InvTools.dropInventory(inv, worldObj, xCoord, yCoord, zCoord);
}
@Override
public boolean openGui(EntityPlayer player) {
TileMultiBlock mBlock = getMasterBlock();
if (mBlock != null) {
GuiHandler.openGui(EnumGui.TURBINE, player, worldObj, mBlock.xCoord, mBlock.yCoord, mBlock.zCoord);
return true;
}
return false;
}
public boolean hasEnergy() {
return getEnergy() >= BC_OUTPUT;
}
public void removeEnergy(double amount) {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock != null) {
mBlock.energy -= amount;
if (mBlock.energy < 0) mBlock.energy = 0;
}
}
public double getEnergy() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock == null)
return 0;
return mBlock.energy;
}
public float getOutput() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock == null)
return 0;
return mBlock.output;
}
public float getMainGauge() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock == null)
return 0;
return mBlock.gaugeState * 0.01F;
}
@Override
public IIcon getIcon(int side) {
if (isStructureValid()) {
int patIndex = patterns.indexOf(getPattern());
if (side == 0 || side == 1) {
if (patIndex == 0)
return Texture.SIDE_B.getIcon();
return Texture.SIDE_A.getIcon();
}
if (getPatternMarker() == 'W')
return Texture.GUAGE.getIcon();
if (patIndex == 0)
switch (side) {
case 2:
if (getPatternPositionY() == 2) {
if (getPatternPositionX() == 2)
return Texture.END_TL.getIcon();
return Texture.END_TR.getIcon();
}
if (getPatternPositionX() == 2)
return Texture.END_BL.getIcon();
return Texture.END_BR.getIcon();
case 3:
if (getPatternPositionY() == 2) {
if (getPatternPositionX() == 1)
return Texture.END_TL.getIcon();
return Texture.END_TR.getIcon();
}
if (getPatternPositionX() == 1)
return Texture.END_BL.getIcon();
return Texture.END_BR.getIcon();
}
else
switch (side) {
case 4:
if (getPatternPositionY() == 2) {
if (getPatternPositionZ() == 1)
return Texture.END_TL.getIcon();
return Texture.END_TR.getIcon();
}
if (getPatternPositionZ() == 1)
return Texture.END_BL.getIcon();
return Texture.END_BR.getIcon();
case 5:
if (getPatternPositionY() == 2) {
if (getPatternPositionZ() == 2)
return Texture.END_TL.getIcon();
return Texture.END_TR.getIcon();
}
if (getPatternPositionZ() == 2)
return Texture.END_BL.getIcon();
return Texture.END_BR.getIcon();
}
}
return Texture.SIDE_A.getIcon();
}
@Override
public void writeToNBT(NBTTagCompound data) {
super.writeToNBT(data);
inv.writeToNBT("rotor", data);
tankManager.writeTanksToNBT(data);
chargeHandler.writeToNBT(data);
data.setFloat("energy", (float) energy);
data.setFloat("output", output);
}
@Override
public void readFromNBT(NBTTagCompound data) {
super.readFromNBT(data);
inv.readFromNBT("rotor", data);
tankManager.readTanksFromNBT(data);
chargeHandler.readFromNBT(data);
energy = data.getFloat("energy");
output = data.getFloat("output");
}
@Override
public boolean receiveClientEvent(int id, int value) {
if (id == 1) {
gaugeState = (byte) value;
return true;
}
return super.receiveClientEvent(id, value);
}
@Override
public double getOfferedEnergy() {
if (hasEnergy())
return IC2_OUTPUT;
return 0;
}
@Override
public void drawEnergy(double amount) {
removeEnergy((amount / IC2_OUTPUT) * BC_OUTPUT);
}
@Override
public int getSourceTier() {
return 3;
}
@Override
public boolean emitsEnergyTo(TileEntity receiver, ForgeDirection direction) {
return true;
}
@Override
public TileEntity getTile() {
return this;
}
@Override
public List<TileEntity> getSubTiles() {
return getComponents();
}
public StandaloneInventory getInventory() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock != null)
return mBlock.inv;
return inv;
}
public TankManager getTankManager() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock != null)
return mBlock.tankManager;
return null;
}
@Override
public int fill(ForgeDirection from, FluidStack resource, boolean doFill) {
TankManager tMan = getTankManager();
if (tMan != null) return tMan.fill(TANK_STEAM, resource, doFill);
return 0;
}
@Override
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain) {
TankManager tMan = getTankManager();
if (tMan != null) return tMan.drain(TANK_WATER, maxDrain, doDrain);
return null;
}
@Override
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain) {
if (Fluids.WATER.is(resource))
return drain(from, resource.amount, doDrain);
return null;
}
@Override
public FluidTankInfo[] getTankInfo(ForgeDirection side) {
TankManager tMan = getTankManager();
if (tMan != null) return tMan.getTankInfo();
return FakeTank.INFO;
}
@Override
public boolean canFill(ForgeDirection from, Fluid fluid) {
return fluid == null || Fluids.STEAM.is(fluid);
}
@Override
public boolean canDrain(ForgeDirection from, Fluid fluid) {
return fluid == null || Fluids.WATER.is(fluid);
}
// @Override
// public void onDisable(int duration) {
// TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
// if (mBlock != null) {
// mBlock.disabled = duration;
// }
// }
//
// @Override
// public boolean isDisabled() {
// TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
// if (mBlock != null) {
// return mBlock.disabled <= 0;
// }
// return true;
// }
@Override
public boolean needsMaintenance() {
TileSteamTurbine mBlock = (TileSteamTurbine) getMasterBlock();
if (mBlock != null) {
ItemStack rotor = mBlock.inv.getStackInSlot(0);
if (rotor == null)
return true;
if (!InvTools.isItemEqual(rotor, getSampleRotor()))
return true;
if (rotor.getItemDamage() / (double) rotor.getMaxDamage() > 0.75f)
return true;
}
return false;
}
}