package micdoodle8.mods.galacticraft.planets.mars.tile; import micdoodle8.mods.galacticraft.api.prefab.world.gen.WorldProviderSpace; 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.world.IAtmosphericGas; import micdoodle8.mods.galacticraft.core.Constants; import micdoodle8.mods.galacticraft.core.GCBlocks; import micdoodle8.mods.galacticraft.core.GCItems; import micdoodle8.mods.galacticraft.core.energy.item.ItemElectricBase; import micdoodle8.mods.galacticraft.core.energy.tile.TileBaseElectricBlockWithInventory; import micdoodle8.mods.galacticraft.core.items.ItemCanisterGeneric; 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.AsteroidsItems; import micdoodle8.mods.galacticraft.planets.asteroids.items.ItemAtmosphericValve; import micdoodle8.mods.galacticraft.planets.mars.blocks.BlockMachineMarsT2; import micdoodle8.mods.miccore.Annotations.NetworkedField; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.inventory.ISidedInventory; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.IChatComponent; import net.minecraft.util.MathHelper; import net.minecraft.world.WorldProvider; import net.minecraftforge.fluids.*; import net.minecraftforge.fml.relauncher.Side; import java.util.ArrayList; public class TileEntityGasLiquefier extends TileBaseElectricBlockWithInventory implements ISidedInventory, IDisableableMachine, IFluidHandler, IOxygenReceiver { private final int tankCapacity = 2000; @NetworkedField(targetSide = Side.CLIENT) public FluidTank gasTank = new FluidTank(this.tankCapacity * 2); @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 = -10; private ItemStack[] containingItems = new ItemStack[4]; private int airProducts = -1; @NetworkedField(targetSide = Side.CLIENT) public int gasTankType = -1; @NetworkedField(targetSide = Side.CLIENT) public int fluidTankType = -1; @NetworkedField(targetSide = Side.CLIENT) public int fluidTank2Type = -1; public enum TankGases { METHANE(0, "methane", ConfigManagerCore.useOldFuelFluidID ? "fuelgc" : "fuel"), OXYGEN(1, "oxygen", "liquidoxygen"), NITROGEN(2, "nitrogen", "liquidnitrogen"), ARGON(3, "argon", "liquidargon"), AIR(4, "atmosphericgases", "xxyyzz"); int index; String gas; String liquid; TankGases(int id, String fluidname, String outputname) { this.index = id; this.gas = fluidname; this.liquid = outputname; } } public TileEntityGasLiquefier() { this.storage.setMaxExtract(ConfigManagerCore.hardMode ? 90 : 60); this.setTierGC(2); } @Override public void invalidate() { super.invalidate(); } @Override public void update() { super.update(); if (this.airProducts == -1) { this.airProducts = this.getAirProducts(); } if (!this.worldObj.isRemote) { FluidStack currentgas = this.gasTank.getFluid(); if (currentgas == null || currentgas.amount <= 0) { this.gasTankType = -1; } else { this.gasTankType = this.getIdFromName(currentgas.getFluid().getName()); } //If somehow it has air in an airless dimension, flush it out if (this.airProducts == 0 && this.gasTankType == TankGases.AIR.index) { this.gasTank.drain(this.gasTank.getFluidAmount(), true); } FluidStack currentLiquid = this.liquidTank.getFluid(); if (currentLiquid == null || currentLiquid.amount == 0) { this.fluidTankType = -1; } else { this.fluidTankType = this.getProductIdFromName(currentLiquid.getFluid().getName()); } currentLiquid = this.liquidTank2.getFluid(); if (currentLiquid == null || currentLiquid.amount == 0) { this.fluidTank2Type = -1; } else { this.fluidTank2Type = this.getProductIdFromName(currentLiquid.getFluid().getName()); } //First, see if any gas needs to be put into the gas storage ItemStack inputCanister = this.containingItems[1]; if (inputCanister != null) { if (inputCanister.getItem() instanceof ItemAtmosphericValve && this.airProducts > 0) { //Air -> Air tank if (this.gasTankType == -1 || (this.gasTankType == TankGases.AIR.index && this.gasTank.getFluid().amount < this.gasTank.getCapacity())) { Block blockAbove = this.worldObj.getBlockState(getPos().up()).getBlock(); if (blockAbove != null && blockAbove.getMaterial() == Material.air && blockAbove != GCBlocks.breatheableAir && blockAbove != GCBlocks.brightBreatheableAir) { FluidStack gcAtmosphere = FluidRegistry.getFluidStack(TankGases.AIR.gas, 4); this.gasTank.fill(gcAtmosphere, true); this.gasTankType = TankGases.AIR.index; } } } else if (inputCanister.getItem() instanceof ItemCanisterGeneric) { int amount = ItemCanisterGeneric.EMPTY - inputCanister.getItemDamage(); if (amount > 0) { Item canisterType = inputCanister.getItem(); FluidStack canisterGas = null; int factor = 1; if (this.gasTankType <= 0 && canisterType == AsteroidsItems.methaneCanister) { this.gasTankType = TankGases.METHANE.index; canisterGas = FluidRegistry.getFluidStack(TankGases.METHANE.gas, amount); } if ((this.gasTankType == TankGases.OXYGEN.index || this.gasTankType == -1) && canisterType == AsteroidsItems.canisterLOX) { this.gasTankType = TankGases.OXYGEN.index; canisterGas = FluidRegistry.getFluidStack(TankGases.OXYGEN.gas, amount * 2); factor = 2; } if ((this.gasTankType == TankGases.NITROGEN.index || this.gasTankType == -1) && canisterType == AsteroidsItems.canisterLN2) { this.gasTankType = TankGases.NITROGEN.index; canisterGas = FluidRegistry.getFluidStack(TankGases.NITROGEN.gas, amount * 2); factor = 2; } if (canisterGas != null) { int used = this.gasTank.fill(canisterGas, true) / factor; if (used == amount) { this.containingItems[1] = new ItemStack(GCItems.oilCanister, 1, ItemCanisterGeneric.EMPTY); } else { this.containingItems[1] = new ItemStack(canisterType, 1, ItemCanisterGeneric.EMPTY - amount + used); } } } } else { FluidStack liquid = FluidContainerRegistry.getFluidForFilledItem(inputCanister); if (liquid != null && liquid.amount > 0) { String inputName = FluidRegistry.getFluidName(liquid); //Methane -> Methane tank if (this.gasTankType <= 0 && inputName.contains("methane")) { if (currentgas == null || currentgas.amount + liquid.amount <= this.gasTank.getCapacity()) { FluidStack gcMethane = FluidRegistry.getFluidStack(TankGases.METHANE.gas, liquid.amount); this.gasTank.fill(gcMethane, true); this.gasTankType = 0; this.containingItems[1] = FluidUtil.getUsedContainer(inputCanister); } } else //Oxygen -> Oxygen tank if ((this.gasTankType == TankGases.OXYGEN.index || this.gasTankType == -1) && inputName.contains("oxygen")) { if (currentgas == null || currentgas.amount + liquid.amount * 2 <= this.gasTank.getCapacity()) { FluidStack gcgas = FluidRegistry.getFluidStack(TankGases.OXYGEN.gas, liquid.amount * (inputName.contains("liquid") ? 2 : 1)); this.gasTank.fill(gcgas, true); this.gasTankType = TankGases.OXYGEN.index; this.containingItems[1] = FluidUtil.getUsedContainer(inputCanister); } } else //Nitrogen -> Nitrogen tank if ((this.gasTankType == TankGases.NITROGEN.index || this.gasTankType == -1) && inputName.contains("nitrogen")) { if (currentgas == null || currentgas.amount + liquid.amount * 2 <= this.gasTank.getCapacity()) { FluidStack gcgas = FluidRegistry.getFluidStack(TankGases.NITROGEN.gas, liquid.amount * (inputName.contains("liquid") ? 2 : 1)); this.gasTank.fill(gcgas, true); this.gasTankType = TankGases.NITROGEN.index; this.containingItems[1] = FluidUtil.getUsedContainer(inputCanister); } } } } } //Now see if any liquids from the output tanks need to be put into the output slot 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.doLiquefaction(); this.processTicks = this.canProcess() ? this.processTimeRequired : 0; } } } else { if (this.processTicks > 0) { this.processTicks = 0; } else if (--this.processTicks <= -10) { this.processTicks = -10; } } } } private void checkFluidTankTransfer(int slot, FluidTank tank) { if (FluidUtil.isValidContainer(this.containingItems[slot])) { final FluidStack liquid = tank.getFluid(); if (liquid != null && liquid.amount > 0) { String liquidname = liquid.getFluid().getName(); if (liquidname.startsWith("fuel")) { FluidUtil.tryFillContainerFuel(tank, this.containingItems, slot); } else if (liquidname.equals(TankGases.OXYGEN.liquid)) { FluidUtil.tryFillContainer(tank, liquid, this.containingItems, slot, AsteroidsItems.canisterLOX); } else if (liquidname.equals(TankGases.NITROGEN.liquid)) { FluidUtil.tryFillContainer(tank, liquid, this.containingItems, slot, AsteroidsItems.canisterLN2); } } } else if (this.containingItems[slot] != null && this.containingItems[slot].getItem() instanceof ItemAtmosphericValve) { tank.drain(4, true); } } public int getIdFromName(String gasname) { for (TankGases type : TankGases.values()) { if (type.gas.equals(gasname)) { return type.index; } } return -1; } public int getProductIdFromName(String gasname) { for (TankGases type : TankGases.values()) { if (type.liquid.equals(gasname)) { return type.index; } } return -1; } public int getScaledGasLevel(int i) { return this.gasTank.getFluid() != null ? this.gasTank.getFluid().amount * i / this.gasTank.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.gasTank.getFluid() == null || this.gasTank.getFluid().amount <= 0 || this.getDisabled(0)) { return false; } if (this.fluidTankType == -1 || this.fluidTank2Type == -1) { return true; } boolean tank1HasSpace = this.liquidTank.getFluidAmount() < this.liquidTank.getCapacity(); boolean tank2HasSpace = this.liquidTank2.getFluidAmount() < this.liquidTank2.getCapacity(); if (this.gasTankType == TankGases.AIR.index) { int airProducts = this.airProducts; do { int thisProduct = (airProducts & 15) - 1; if ((thisProduct == this.fluidTankType && tank1HasSpace) || (thisProduct == this.fluidTank2Type && tank2HasSpace)) { return true; } airProducts = airProducts >> 4; } while (airProducts > 0); return false; } if ((this.gasTankType == this.fluidTankType && tank1HasSpace) || (this.gasTankType == this.fluidTank2Type && tank2HasSpace)) { return true; } return false; } public int getAirProducts() { WorldProvider WP = this.worldObj.provider; if (WP instanceof WorldProviderSpace) { int result = 0; ArrayList<IAtmosphericGas> atmos = ((WorldProviderSpace) WP).getCelestialBody().atmosphere.composition; if (atmos.size() > 0) { result = this.getIdFromName(atmos.get(0).name().toLowerCase()) + 1; } if (atmos.size() > 1) { result += 16 * (this.getIdFromName(atmos.get(1).name().toLowerCase()) + 1); } if (atmos.size() > 2) { result += 256 * (this.getIdFromName(atmos.get(2).name().toLowerCase()) + 1); } return result; } return 35; } public void doLiquefaction() { //Can't be called if the gasTank fluid is null final int gasAmount = this.gasTank.getFluid().amount; if (gasAmount == 0) { return; } if (this.gasTankType == TankGases.AIR.index) { int airProducts = this.airProducts; int amountToDrain = Math.min(gasAmount / 2, (airProducts > 15) ? 2 : 3); if (amountToDrain == 0) { amountToDrain = 1; } do { int thisProduct = (airProducts & 15) - 1; //-1 indicates a gas which can't be liquefied (e.g. Carbon Dioxide) if (thisProduct >= 0) { this.gasTank.drain(this.placeIntoFluidTanks(thisProduct, amountToDrain) * 2, true); } airProducts = airProducts >> 4; amountToDrain = amountToDrain >> 1; if (amountToDrain == 0) { amountToDrain = 1; } } while (airProducts > 0); } else { if (gasAmount == 1) { this.gasTank.drain(this.placeIntoFluidTanks(this.gasTankType, 1), true); } else { this.gasTank.drain(this.placeIntoFluidTanks(this.gasTankType, Math.min(gasAmount / 2, 3)) * 2, true); } } } private int placeIntoFluidTanks(int thisProduct, int amountToDrain) { final int fuelSpace = this.liquidTank.getCapacity() - this.liquidTank.getFluidAmount(); final int fuelSpace2 = this.liquidTank2.getCapacity() - this.liquidTank2.getFluidAmount(); if ((thisProduct == this.fluidTank2Type || this.fluidTank2Type == -1) && fuelSpace2 > 0) { if (amountToDrain > fuelSpace2) { amountToDrain = fuelSpace2; } this.liquidTank2.fill(FluidRegistry.getFluidStack(TankGases.values()[thisProduct].liquid, amountToDrain), true); this.fluidTank2Type = thisProduct; } else if ((thisProduct == this.fluidTankType || this.fluidTankType == -1) && fuelSpace > 0) { if (amountToDrain > fuelSpace) { amountToDrain = fuelSpace; } this.liquidTank.fill(FluidRegistry.getFluidStack(TankGases.values()[thisProduct].liquid, amountToDrain), true); this.fluidTankType = thisProduct; } else { amountToDrain = 0; } return amountToDrain; } @Override public void readFromNBT(NBTTagCompound nbt) { super.readFromNBT(nbt); this.processTicks = nbt.getInteger("smeltingTicks"); this.containingItems = this.readStandardItemsFromNBT(nbt); if (nbt.hasKey("gasTank")) { this.gasTank.readFromNBT(nbt.getCompoundTag("gasTank")); } if (nbt.hasKey("liquidTank")) { this.liquidTank.readFromNBT(nbt.getCompoundTag("liquidTank")); } if (nbt.hasKey("liquidTank2")) { this.liquidTank2.readFromNBT(nbt.getCompoundTag("liquidTank2")); } } @Override public void writeToNBT(NBTTagCompound nbt) { super.writeToNBT(nbt); nbt.setInteger("smeltingTicks", this.processTicks); this.writeStandardItemsToNBT(nbt); if (this.gasTank.getFluid() != null) { nbt.setTag("gasTank", this.gasTank.writeToNBT(new NBTTagCompound())); } if (this.liquidTank.getFluid() != null) { nbt.setTag("liquidTank", this.liquidTank.writeToNBT(new NBTTagCompound())); } if (this.liquidTank2.getFluid() != null) { nbt.setTag("liquidTank2", 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.4.name"); } // ISidedInventory Implementation: @Override public int[] getSlotsForFace(EnumFacing side) { if (side == EnumFacing.DOWN) { return new int[] { 0, 1, 2, 3 }; } if (side == EnumFacing.UP) { return new int[] { 0 }; } return new int[] { 1, 2, 3 }; } @Override public boolean canInsertItem(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 FluidUtil.isMethaneContainerAny(itemstack); case 2: return FluidUtil.isEmptyContainerFor(itemstack, this.liquidTank.getFluid()); case 3: return FluidUtil.isEmptyContainerFor(itemstack, this.liquidTank2.getFluid()); default: return false; } } return false; } @Override public boolean canExtractItem(int slotID, ItemStack itemstack, EnumFacing side) { switch (slotID) { case 0: return itemstack.getItem() instanceof ItemElectricBase && ((ItemElectricBase) itemstack.getItem()).getElectricityStored(itemstack) <= 0; case 1: return FluidUtil.isEmptyContainer(itemstack); case 2: return FluidUtil.isFullContainer(itemstack); case 3: return FluidUtil.isFullContainer(itemstack); default: return false; } } @Override public boolean isItemValidForSlot(int slotID, ItemStack itemstack) { switch (slotID) { case 0: return ItemElectricBase.isElectricItem(itemstack.getItem()); case 1: case 2: case 3: return FluidUtil.isValidContainer(itemstack); } 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 == getGasInputDirection().getOpposite()) { return this.liquidTank2.getFluid() != null && this.liquidTank2.getFluidAmount() > 0; } //2->5 3->4 4->2 5->3 if (getGasInputDirection().rotateY() == from) { return this.liquidTank.getFluid() != null && this.liquidTank.getFluidAmount() > 0; } return false; } @Override public FluidStack drain(EnumFacing from, FluidStack resource, boolean doDrain) { if (from == getGasInputDirection().getOpposite()) { if (resource != null && resource.isFluidEqual(this.liquidTank2.getFluid())) { return this.liquidTank2.drain(resource.amount, doDrain); } } //2->5 3->4 4->2 5->3 if (getGasInputDirection().rotateY() == from) { 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 == getGasInputDirection().getOpposite()) { return this.liquidTank2.drain(maxDrain, doDrain); } //2->5 3->4 4->2 5->3 if (getGasInputDirection().rotateY() == from) { return this.liquidTank.drain(maxDrain, doDrain); } return null; } @Override public boolean canFill(EnumFacing from, Fluid fluid) { if (from.equals(this.getGasInputDirection())) { //Can fill with gases return fluid == null || this.getIdFromName(fluid.getName()) > -1; } return false; } @Override public int fill(EnumFacing from, FluidStack resource, boolean doFill) { int used = 0; if (resource != null && this.canFill(from, resource.getFluid())) { int type = this.getIdFromName(FluidRegistry.getFluidName(resource)); if (this.gasTankType == -1 || (this.gasTankType == type && this.gasTank.getFluidAmount() < this.gasTank.getCapacity())) { if (type > 0) { float conversion = 2F * Constants.LOX_GAS_RATIO; FluidStack fluidToFill = new FluidStack(resource.getFluid(), (int) (resource.amount * conversion)); used = MathHelper.ceiling_float_int(this.gasTank.fill(fluidToFill, doFill) / conversion); } else { used = this.gasTank.fill(resource, doFill); } } } return used; } @Override public FluidTankInfo[] getTankInfo(EnumFacing from) { FluidTankInfo[] tankInfo = new FluidTankInfo[] {}; if (from == this.getGasInputDirection()) { tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.gasTank) }; } else if (from == this.getGasInputDirection().getOpposite()) { tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.liquidTank2) }; } if (getGasInputDirection().rotateY() == from) { tankInfo = new FluidTankInfo[] { new FluidTankInfo(this.liquidTank) }; } return tankInfo; } @Override public int getBlockMetadata() { return getBlockType().getMetaFromState(this.worldObj.getBlockState(getPos())) & 3; } @Override public boolean shouldPullOxygen() { return this.gasTankType == -1 || (this.gasTankType == 1 && this.gasTank.getFluidAmount() < this.gasTank.getCapacity()); } @Override public int receiveOxygen(EnumFacing from, int receive, boolean doReceive) { if (from == this.getGasInputDirection() && this.shouldPullOxygen()) { float conversion = 2F * Constants.LOX_GAS_RATIO; FluidStack fluidToFill = new FluidStack(AsteroidsModule.fluidOxygenGas, (int) (receive * conversion)); int used = MathHelper.ceiling_float_int(this.gasTank.fill(fluidToFill, doReceive) / conversion); return used; } return 0; } @Override public int provideOxygen(EnumFacing from, int request, boolean doProvide) { return 0; } @Override public int getOxygenRequest(EnumFacing direction) { return this.receiveOxygen(direction, 1000000, false); } @Override public int getOxygenProvide(EnumFacing direction) { return 0; } @Override public boolean canConnect(EnumFacing direction, NetworkType type) { if (direction == null) { return false; } if (type == NetworkType.FLUID) { return direction == getGasInputDirection() || direction == this.getGasInputDirection().getOpposite() || direction == this.getGasInputDirection().rotateY(); } if (type == NetworkType.POWER) { return direction == EnumFacing.DOWN; } return false; } @Override public IChatComponent getDisplayName() { return null; } @Override public EnumFacing getFront() { return this.worldObj.getBlockState(getPos()).getValue(BlockMachineMarsT2.FACING); } public EnumFacing getGasInputDirection() { return this.getFront().rotateY(); } }