/*
* 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.util.steam;
import mods.railcraft.common.blocks.RailcraftTileEntity;
import mods.railcraft.common.core.RailcraftConfig;
import mods.railcraft.common.fluids.Fluids;
import mods.railcraft.common.fluids.tanks.StandardTank;
import mods.railcraft.common.gui.widgets.IIndicatorController;
import mods.railcraft.common.gui.widgets.IndicatorController;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraftforge.fluids.FluidStack;
/**
*
* @author CovertJaguar <http://www.railcraft.info/>
*/
public class SteamBoiler {
public double burnTime;
public double currentItemBurnTime;
protected boolean isBurning = false;
protected byte burnCycle;
private final StandardTank tankWater;
private final StandardTank tankSteam;
private double partialConversions = 0;
private double heat = Steam.COLD_TEMP;
private double maxHeat = Steam.MAX_HEAT_LOW;
private double efficiencyModifier = 1;
private int ticksPerCycle = 16;
private RailcraftTileEntity tile;
private IFuelProvider fuelProvider;
public SteamBoiler(StandardTank tankWater, StandardTank tankSteam) {
this.tankWater = tankWater;
this.tankSteam = tankSteam;
}
public SteamBoiler setFuelProvider(IFuelProvider fuelProvider) {
this.fuelProvider = fuelProvider;
return this;
}
public SteamBoiler setTile(RailcraftTileEntity tile) {
this.tile = tile;
return this;
}
public SteamBoiler setTicksPerCycle(int ticks) {
this.ticksPerCycle = ticks;
return this;
}
public SteamBoiler setEfficiencyModifier(double modifier) {
this.efficiencyModifier = modifier;
return this;
}
public SteamBoiler setMaxHeat(double maxHeat) {
this.maxHeat = maxHeat;
return this;
}
public double getMaxHeat() {
return maxHeat;
}
public double getHeatStep() {
if (fuelProvider != null)
return fuelProvider.getHeatStep();
return Steam.HEAT_STEP;
}
public void reset() {
heat = Steam.COLD_TEMP;
}
public double getHeat() {
return heat;
}
public void setHeat(double heat) {
this.heat = heat;
if (this.heat < Steam.COLD_TEMP)
this.heat = Steam.COLD_TEMP;
}
public double getHeatLevel() {
return heat / getMaxHeat();
}
public void increaseHeat(int numTanks) {
double max = getMaxHeat();
if (heat == max)
return;
double step = getHeatStep();
double change = step + (((max - heat) / max) * step * 3);
change /= numTanks;
heat += change;
heat = Math.min(heat, max);
}
public void reduceHeat(int numTanks) {
if (heat == Steam.COLD_TEMP)
return;
double step = Steam.HEAT_STEP;
double change = step + ((heat / getMaxHeat()) * step * 3);
change /= numTanks;
heat -= change;
heat = Math.max(heat, Steam.COLD_TEMP);
}
public boolean isBoiling() {
return getHeat() >= Steam.BOILING_POINT;
}
public boolean isSuperHeated() {
return getHeat() >= Steam.SUPER_HEATED;
}
public boolean isBurning() {
return isBurning;
}
public void setBurning(boolean isBurning) {
this.isBurning = isBurning;
}
public boolean hasFuel() {
return burnTime > 0;
}
public int getBurnProgressScaled(int i) {
if (!isBoiling())
return 0;
int scale = (int) ((burnTime / currentItemBurnTime) * i);
scale = Math.max(0, scale);
scale = Math.min(i, scale);
return scale;
}
private boolean addFuel() {
if (fuelProvider == null)
return false;
double fuel = fuelProvider.getMoreFuel();
if (fuel <= 0)
return false;
burnTime += fuel;
currentItemBurnTime = burnTime;
return true;
}
public double getFuelPerCycle(int numTanks) {
double fuel = Steam.FUEL_PER_BOILER_CYCLE;
fuel -= numTanks * Steam.FUEL_PER_BOILER_CYCLE * 0.0125F;
fuel += Steam.FUEL_HEAT_INEFFICIENCY * getHeatLevel();
fuel += Steam.FUEL_PRESSURE_INEFFICIENCY * (getMaxHeat() / Steam.MAX_HEAT_HIGH);
fuel *= numTanks;
fuel *= efficiencyModifier;
fuel *= RailcraftConfig.fuelPerSteamMultiplier();
return fuel;
}
public void tick(int numTanks) {
burnCycle++;
if (burnCycle >= ticksPerCycle) {
burnCycle = 0;
double fuelNeeded = getFuelPerCycle(numTanks);
while (burnTime < fuelNeeded) {
boolean addedFuel = addFuel();
if (!addedFuel)
break;
}
boolean wasBurning = isBurning;
isBurning = burnTime >= fuelNeeded;
if (isBurning)
burnTime -= fuelNeeded;
if (tile != null && isBurning != wasBurning)
tile.sendUpdateToClient();
convertSteam(numTanks);
}
if (isBurning)
increaseHeat(numTanks);
else
reduceHeat(numTanks);
}
public int convertSteam(int numTanks) {
if (!isBoiling())
return 0;
partialConversions += numTanks * getHeatLevel();
int waterCost = (int) partialConversions;
if (waterCost <= 0)
return 0;
partialConversions -= waterCost;
FluidStack water = tankWater.drain(waterCost, false);
if (water == null)
return 0;
waterCost = Math.min(waterCost, water.amount);
FluidStack steam = Fluids.STEAM.get(Steam.STEAM_PER_UNIT_WATER * waterCost);
if (steam == null)
return 0;
tankWater.drain(waterCost, true);
tankSteam.fill(steam, true);
return steam.amount;
}
public void writeToNBT(NBTTagCompound data) {
data.setFloat("heat", (float) heat);
data.setFloat("maxHeat", (float) maxHeat);
data.setFloat("burnTime", (float) burnTime);
data.setFloat("currentItemBurnTime", (float) currentItemBurnTime);
}
public void readFromNBT(NBTTagCompound data) {
heat = data.getFloat("heat");
maxHeat = data.getFloat("maxHeat");
burnTime = data.getFloat("burnTime");
currentItemBurnTime = data.getFloat("currentItemBurnTime");
}
public final IIndicatorController heatIndicator = new HeatIndicator();
private class HeatIndicator extends IndicatorController {
@Override
protected void refreshToolTip() {
tip.text = String.format("%.0f\u00B0C", getHeat());
}
@Override
public int getScaledLevel(int size) {
return (int) ((getHeat() - Steam.COLD_TEMP) * size / (getMaxHeat() - Steam.COLD_TEMP));
}
};
}