package micdoodle8.mods.galacticraft.planets.mars.tile;
import mekanism.api.gas.Gas;
import mekanism.api.gas.GasStack;
import micdoodle8.mods.galacticraft.api.tile.IDisableableMachine;
import micdoodle8.mods.galacticraft.api.transmission.NetworkType;
import micdoodle8.mods.galacticraft.api.transmission.tile.IOxygenReceiver;
import micdoodle8.mods.galacticraft.api.transmission.tile.IOxygenStorage;
import micdoodle8.mods.galacticraft.api.vector.BlockVec3;
import micdoodle8.mods.galacticraft.core.GCFluids;
import micdoodle8.mods.galacticraft.core.energy.EnergyConfigHandler;
import micdoodle8.mods.galacticraft.core.energy.item.ItemElectricBase;
import micdoodle8.mods.galacticraft.core.energy.tile.TileBaseElectricBlockWithInventory;
import micdoodle8.mods.galacticraft.core.fluid.FluidNetwork;
import micdoodle8.mods.galacticraft.core.fluid.NetworkHelper;
import micdoodle8.mods.galacticraft.core.tile.TileEntityOxygenStorageModule;
import micdoodle8.mods.galacticraft.core.util.ConfigManagerCore;
import micdoodle8.mods.galacticraft.core.util.FluidUtil;
import micdoodle8.mods.galacticraft.core.util.GCCoreUtil;
import micdoodle8.mods.galacticraft.planets.asteroids.AsteroidsModule;
import micdoodle8.mods.galacticraft.planets.asteroids.items.ItemAtmosphericValve;
import micdoodle8.mods.galacticraft.planets.mars.blocks.BlockMachineMarsT2;
import micdoodle8.mods.miccore.Annotations;
import micdoodle8.mods.miccore.Annotations.NetworkedField;
import net.minecraft.init.Items;
import net.minecraft.inventory.ISidedInventory;
import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.IChatComponent;
import net.minecraftforge.fluids.*;
import net.minecraftforge.fml.relauncher.Side;
public class TileEntityElectrolyzer extends TileBaseElectricBlockWithInventory implements ISidedInventory, IDisableableMachine, IFluidHandler, IOxygenStorage, IOxygenReceiver
{
private final int tankCapacity = 4000;
@NetworkedField(targetSide = Side.CLIENT)
public FluidTank waterTank = new FluidTank(this.tankCapacity);
@NetworkedField(targetSide = Side.CLIENT)
public FluidTank liquidTank = new FluidTank(this.tankCapacity);
@NetworkedField(targetSide = Side.CLIENT)
public FluidTank liquidTank2 = new FluidTank(this.tankCapacity);
public int processTimeRequired = 3;
@NetworkedField(targetSide = Side.CLIENT)
public int processTicks = 0;
private ItemStack[] containingItems = new ItemStack[4];
public TileEntityElectrolyzer()
{
this.storage.setMaxExtract(ConfigManagerCore.hardMode ? 150 : 120);
this.setTierGC(2);
}
@Override
public void update()
{
super.update();
if (!this.worldObj.isRemote)
{
final FluidStack liquid = FluidUtil.getFluidContained(this.containingItems[1]);
if (FluidUtil.isFluidStrict(liquid, FluidRegistry.WATER.getName()))
{
FluidUtil.loadFromContainer(waterTank, FluidRegistry.WATER, containingItems, 1, liquid.amount);
}
//Only drain with atmospheric valve
checkFluidTankTransfer(2, this.liquidTank);
checkFluidTankTransfer(3, this.liquidTank2);
if (this.hasEnoughEnergyToRun && this.canProcess())
{
//50% extra speed boost for Tier 2 machine if powered by Tier 2 power
if (this.tierGC == 2)
{
this.processTimeRequired = Math.max(1, 4 - this.poweredByTierGC);
}
if (this.processTicks == 0)
{
this.processTicks = this.processTimeRequired;
}
else
{
if (--this.processTicks <= 0)
{
this.doElectrolysis();
this.processTicks = this.canProcess() ? this.processTimeRequired : 0;
}
}
}
else
{
this.processTicks = 0;
}
this.produceOxygen(this.getOxygenOutputDirection());
this.produceHydrogen(this.getHydrogenOutputDirection());
}
}
private void doElectrolysis()
{
//Can't be called if the gasTank fluid is null
final int waterAmount = this.waterTank.getFluid().amount;
if (waterAmount == 0)
{
return;
}
this.placeIntoFluidTanks(2);
this.waterTank.drain(1, true);
}
private int placeIntoFluidTanks(int amountToDrain)
{
final int fuelSpace = this.liquidTank.getCapacity() - this.liquidTank.getFluidAmount();
final int fuelSpace2 = this.liquidTank2.getCapacity() - this.liquidTank2.getFluidAmount();
int amountToDrain2 = amountToDrain * 2;
if (amountToDrain > fuelSpace)
{
amountToDrain = fuelSpace;
}
this.liquidTank.fill(FluidRegistry.getFluidStack("oxygen", amountToDrain), true);
if (amountToDrain2 > fuelSpace2)
{
amountToDrain2 = fuelSpace2;
}
this.liquidTank2.fill(FluidRegistry.getFluidStack("hydrogen", amountToDrain2), true);
return amountToDrain;
}
private void checkFluidTankTransfer(int slot, FluidTank tank)
{
if (this.containingItems[slot] != null && this.containingItems[slot].getItem() instanceof ItemAtmosphericValve)
{
tank.drain(4, true);
}
}
public int getScaledGasLevel(int i)
{
return this.waterTank.getFluid() != null ? this.waterTank.getFluid().amount * i / this.waterTank.getCapacity() : 0;
}
public int getScaledFuelLevel(int i)
{
return this.liquidTank.getFluid() != null ? this.liquidTank.getFluid().amount * i / this.liquidTank.getCapacity() : 0;
}
public int getScaledFuelLevel2(int i)
{
return this.liquidTank2.getFluid() != null ? this.liquidTank2.getFluid().amount * i / this.liquidTank2.getCapacity() : 0;
}
public boolean canProcess()
{
if (this.waterTank.getFluid() == null || this.waterTank.getFluid().amount <= 0 || this.getDisabled(0))
{
return false;
}
boolean tank1HasSpace = this.liquidTank.getFluidAmount() < this.liquidTank.getCapacity();
boolean tank2HasSpace = this.liquidTank2.getFluidAmount() < this.liquidTank2.getCapacity();
return tank1HasSpace || tank2HasSpace;
}
@Override
public void readFromNBT(NBTTagCompound nbt)
{
super.readFromNBT(nbt);
this.processTicks = nbt.getInteger("processTicks");
this.containingItems = this.readStandardItemsFromNBT(nbt);
if (nbt.hasKey("waterTank"))
{
this.waterTank.readFromNBT(nbt.getCompoundTag("waterTank"));
}
if (nbt.hasKey("gasTank"))
{
this.liquidTank.readFromNBT(nbt.getCompoundTag("gasTank"));
}
if (nbt.hasKey("gasTank2"))
{
this.liquidTank2.readFromNBT(nbt.getCompoundTag("gasTank2"));
}
}
@Override
public void writeToNBT(NBTTagCompound nbt)
{
super.writeToNBT(nbt);
nbt.setInteger("processTicks", this.processTicks);
this.writeStandardItemsToNBT(nbt);
if (this.waterTank.getFluid() != null)
{
nbt.setTag("waterTank", this.waterTank.writeToNBT(new NBTTagCompound()));
}
if (this.liquidTank.getFluid() != null)
{
nbt.setTag("gasTank", this.liquidTank.writeToNBT(new NBTTagCompound()));
}
if (this.liquidTank2.getFluid() != null)
{
nbt.setTag("gasTank2", this.liquidTank2.writeToNBT(new NBTTagCompound()));
}
}
@Override
protected ItemStack[] getContainingItems()
{
return this.containingItems;
}
@Override
public boolean hasCustomName()
{
return true;
}
@Override
public String getName()
{
return GCCoreUtil.translate("tile.mars_machine.6.name");
}
// ISidedInventory Implementation:
@Override
public int[] getSlotsForFace(EnumFacing side)
{
return new int[] { 0, 1 };
}
@Override
public boolean canInsertItem(int slotID, ItemStack itemstack, EnumFacing side)
{
if (this.isItemValidForSlot(slotID, itemstack))
{
switch (slotID)
{
case 0:
return ItemElectricBase.isElectricItem(itemstack.getItem());
case 1:
return itemstack.getItem() == Items.water_bucket;
default:
return false;
}
}
return false;
}
@Override
public boolean canExtractItem(int slotID, ItemStack itemstack, EnumFacing side)
{
if (this.isItemValidForSlot(slotID, itemstack))
{
switch (slotID)
{
case 0:
return itemstack.getItem() instanceof ItemElectricBase && ((ItemElectricBase) itemstack.getItem()).getElectricityStored(itemstack) <= 0;
case 1:
return itemstack.getItem() == Items.bucket;
default:
return false;
}
}
return false;
}
@Override
public boolean isItemValidForSlot(int slotID, ItemStack itemstack)
{
Item item = itemstack.getItem();
switch (slotID)
{
case 0:
return ItemElectricBase.isElectricItem(item);
case 1:
return item == Items.bucket || item == Items.water_bucket;
}
return false;
}
@Override
public boolean shouldUseEnergy()
{
return this.canProcess();
}
@Override
public double getPacketRange()
{
return 320.0D;
}
@Override
public EnumFacing getElectricInputDirection()
{
return EnumFacing.DOWN;
}
@Override
public boolean canDrain(EnumFacing from, Fluid fluid)
{
if (from == this.getHydrogenOutputDirection())
{
return this.liquidTank2.getFluid() != null && this.liquidTank2.getFluidAmount() > 0;
}
if (from == this.getOxygenOutputDirection())
{
return this.liquidTank.getFluid() != null && this.liquidTank.getFluidAmount() > 0;
}
return false;
}
@Override
public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain)
{
if (from == this.getHydrogenOutputDirection())
{
if (resource != null && resource.isFluidEqual(this.liquidTank2.getFluid()))
{
return this.liquidTank2.drain(resource.amount, doDrain);
}
}
if (from == this.getOxygenOutputDirection())
{
if (resource != null && resource.isFluidEqual(this.liquidTank.getFluid()))
{
return this.liquidTank.drain(resource.amount, doDrain);
}
}
return null;
}
@Override
public FluidStack drain(EnumFacing from, int maxDrain, boolean doDrain)
{
if (from == this.getHydrogenOutputDirection())
{
return this.liquidTank2.drain(maxDrain, doDrain);
}
if (from == this.getOxygenOutputDirection())
{
return this.liquidTank.drain(maxDrain, doDrain);
}
return null;
}
@Override
public boolean canFill(EnumFacing from, Fluid fluid)
{
if (from == this.getFront().rotateY())
{
//Can fill with water
return fluid == null || fluid.getName().equals(FluidRegistry.WATER.getName());
}
return false;
}
@Override
public int fill(EnumFacing from, FluidStack resource, boolean doFill)
{
int used = 0;
if (resource != null && this.canFill(from, resource.getFluid()))
{
used = this.waterTank.fill(resource, doFill);
}
return used;
}
@Override
public FluidTankInfo[] getTankInfo(EnumFacing from)
{
FluidTankInfo[] tankInfo = new FluidTankInfo[] {};
if (from == this.getFront().rotateY())
{
tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.waterTank) };
}
else if (from == this.getHydrogenOutputDirection())
{
tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.liquidTank2) };
}
else if (from == this.getOxygenOutputDirection())
{
tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.liquidTank) };
}
return tankInfo;
}
@Override
public int getBlockMetadata()
{
return getBlockType().getMetaFromState(this.worldObj.getBlockState(getPos()));
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public int receiveGas(EnumFacing side, GasStack stack, boolean doTransfer)
{
return 0;
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public int receiveGas(EnumFacing side, GasStack stack)
{
return 0;
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public GasStack drawGas(EnumFacing from, int amount, boolean doTransfer)
{
if (from == this.getHydrogenOutputDirection() && this.liquidTank2.getFluid() != null)
{
int amountH = Math.min(8, this.liquidTank2.getFluidAmount());
amountH = this.liquidTank2.drain(amountH, doTransfer).amount;
return new GasStack((Gas) EnergyConfigHandler.gasHydrogen, amountH);
}
else if (from == this.getOxygenOutputDirection() && this.liquidTank.getFluid() != null)
{
int amountO = Math.min(8, this.liquidTank.getFluidAmount());
amountO = this.liquidTank.drain(amountO, doTransfer).amount;
return new GasStack((Gas) EnergyConfigHandler.gasOxygen, amountO);
}
return null;
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public GasStack drawGas(EnumFacing from, int amount)
{
return this.drawGas(from, amount, true);
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public boolean canReceiveGas(EnumFacing side, Gas type)
{
return false;
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.IGasHandler", modID = "Mekanism")
public boolean canDrawGas(EnumFacing from, Gas type)
{
if (from == this.getHydrogenOutputDirection())
{
return type.getName().equals("hydrogen");
}
else if (from == this.getOxygenOutputDirection())
{
return type.getName().equals("oxygen");
}
return false;
}
@Annotations.RuntimeInterface(clazz = "mekanism.api.gas.ITubeConnection", modID = "Mekanism")
public boolean canTubeConnect(EnumFacing from)
{
if (from == this.getHydrogenOutputDirection())
{
return true;
}
else if (from == this.getOxygenOutputDirection())
{
return true;
}
return false;
}
@Override
public void setOxygenStored(int amount)
{
this.liquidTank.setFluid(new FluidStack(AsteroidsModule.fluidOxygenGas, (int) amount));
}
@Override
public int getOxygenStored()
{
return this.liquidTank.getFluidAmount();
}
public int getHydrogenStored()
{
return this.liquidTank2.getFluidAmount();
}
@Override
public int getMaxOxygenStored()
{
return this.liquidTank.getCapacity();
}
private EnumFacing getOxygenOutputDirection()
{
return this.getFront().getOpposite();
}
private EnumFacing getHydrogenOutputDirection()
{
return this.getFront().rotateYCCW();
}
private boolean produceOxygen(EnumFacing outputDirection)
{
int provide = this.getOxygenProvide(outputDirection);
if (provide > 0)
{
TileEntity outputTile = new BlockVec3(this).modifyPositionFromSide(outputDirection).getTileEntity(this.worldObj);
FluidNetwork outputNetwork = NetworkHelper.getFluidNetworkFromTile(outputTile, outputDirection);
if (outputNetwork != null)
{
int gasRequested = outputNetwork.getRequest();
if (gasRequested > 0)
{
int usedGas = outputNetwork.emitToBuffer(new FluidStack(GCFluids.fluidOxygenGas, Math.min(gasRequested, provide)), true);
this.drawOxygen(usedGas, true);
return true;
}
}
else if (outputTile instanceof IOxygenReceiver)
{
float requestedOxygen = ((IOxygenReceiver) outputTile).getOxygenRequest(outputDirection.getOpposite());
if (requestedOxygen > 0)
{
int toSend = Math.min(this.getOxygenStored(), provide);
int acceptedOxygen = ((IOxygenReceiver) outputTile).receiveOxygen(outputDirection.getOpposite(), toSend, true);
this.drawOxygen(acceptedOxygen, true);
return true;
}
}
// else if (EnergyConfigHandler.isMekanismLoaded())
// {
// //TODO Oxygen item handling - internal tank (IGasItem)
// //int acceptedOxygen = GasTransmission.addGas(itemStack, type, amount);
// //this.drawOxygen(acceptedOxygen, true);
//
// if (outputTile instanceof IGasHandler && ((IGasHandler) outputTile).canReceiveGas(outputDirection.getOpposite(), (Gas) EnergyConfigHandler.gasOxygen))
// {
// GasStack toSend = new GasStack((Gas) EnergyConfigHandler.gasOxygen, (int) Math.floor(Math.min(this.getOxygenStored(), provide)));
// int acceptedOxygen = 0;
// try {
// acceptedOxygen = ((IGasHandler) outputTile).receiveGas(outputDirection.getOpposite(), toSend);
// } catch (Exception e) { }
// this.drawOxygen(acceptedOxygen, true);
// return true;
// }
// }
}
return false;
}
private boolean produceHydrogen(EnumFacing outputDirection)
{
int provide = this.getHydrogenProvide(outputDirection);
if (provide > 0)
{
TileEntity outputTile = new BlockVec3(this).modifyPositionFromSide(outputDirection).getTileEntity(this.worldObj);
FluidNetwork outputNetwork = NetworkHelper.getFluidNetworkFromTile(outputTile, outputDirection);
if (outputNetwork != null)
{
int gasRequested = outputNetwork.getRequest();
if (gasRequested > 0)
{
int usedGas = outputNetwork.emitToBuffer(new FluidStack(FluidRegistry.getFluid("hydrogen"), Math.min(gasRequested, provide)), true);
this.drawHydrogen(usedGas, true);
return true;
}
}
else if (outputTile instanceof TileEntityMethaneSynthesizer)
{
float requestedHydrogen = ((TileEntityMethaneSynthesizer) outputTile).getHydrogenRequest(outputDirection.getOpposite());
if (requestedHydrogen > 0)
{
int toSend = Math.min(this.getHydrogenStored(), provide);
int acceptedHydrogen = ((TileEntityMethaneSynthesizer) outputTile).receiveHydrogen(outputDirection.getOpposite(), toSend, true);
this.drawHydrogen(acceptedHydrogen, true);
return true;
}
}
// else if (EnergyConfigHandler.isMekanismLoaded())
// {
// //TODO Gas item handling - internal tank (IGasItem)
// //int acceptedHydrogen = GasTransmission.addGas(itemStack, type, amount);
// //this.drawHydrogen(acceptedHydrogen, true);
//
// if (outputTile instanceof IGasHandler && ((IGasHandler) outputTile).canReceiveGas(outputDirection.getOpposite(), (Gas) EnergyConfigHandler.gasHydrogen))
// {
// GasStack toSend = new GasStack((Gas) EnergyConfigHandler.gasHydrogen, (int) Math.floor(Math.min(this.getHydrogenStored(), provide)));
// int acceptedHydrogen = 0;
// try {
// acceptedHydrogen = ((IGasHandler) outputTile).receiveGas(outputDirection.getOpposite(), toSend);
// } catch (Exception e) { }
// this.drawHydrogen(acceptedHydrogen, true);
// return true;
// }
// }
}
return false;
}
@Override
public int provideOxygen(EnumFacing from, int request, boolean doProvide)
{
if (this.getOxygenOutputDirection() == from)
{
return this.drawOxygen(request, doProvide);
}
return 0;
}
public int drawOxygen(int request, boolean doProvide)
{
if (request > 0)
{
int requestedOxygen = Math.min(request, this.liquidTank.getFluidAmount());
if (doProvide)
{
this.setOxygenStored(this.liquidTank.getFluidAmount() - requestedOxygen);
}
return requestedOxygen;
}
return 0;
}
public int drawHydrogen(int request, boolean doProvide)
{
if (request > 0)
{
int currentHydrogen = this.liquidTank2.getFluidAmount();
int requestedHydrogen = Math.min(request, currentHydrogen);
if (doProvide)
{
this.liquidTank2.setFluid(new FluidStack(FluidRegistry.getFluid("hydrogen"), currentHydrogen - requestedHydrogen));
}
return requestedHydrogen;
}
return 0;
}
@Override
public int getOxygenProvide(EnumFacing direction)
{
return this.getOxygenOutputDirection() == direction ? Math.min(TileEntityOxygenStorageModule.OUTPUT_PER_TICK, this.getOxygenStored()) : 0;
}
public int getHydrogenProvide(EnumFacing direction)
{
return this.getHydrogenOutputDirection() == direction ? Math.min(TileEntityOxygenStorageModule.OUTPUT_PER_TICK, this.getHydrogenStored()) : 0;
}
@Override
public boolean shouldPullOxygen()
{
return false;
}
@Override
public int receiveOxygen(EnumFacing from, int receive, boolean doReceive)
{
return 0;
}
@Override
public int getOxygenRequest(EnumFacing direction)
{
return 0;
}
@Override
public boolean canConnect(EnumFacing direction, NetworkType type)
{
if (direction == null)
{
return false;
}
if (type == NetworkType.FLUID)
{
return this.getOxygenOutputDirection() == direction || this.getHydrogenOutputDirection() == direction || direction == this.getFront().rotateY();
}
if (type == NetworkType.POWER)
{
return direction == this.getElectricInputDirection();
}
return false;
}
@Override
public IChatComponent getDisplayName()
{
return null;
}
@Override
public EnumFacing getFront()
{
return this.worldObj.getBlockState(getPos()).getValue(BlockMachineMarsT2.FACING);
}
}