blob: 82c837eda71f3de019e8d30cb7be66e2501d710c [file] [log] [blame] [raw]
package mekanism.common.tile;
import java.util.ArrayList;
import mekanism.api.ChemicalPair;
import mekanism.api.Coord4D;
import mekanism.api.gas.Gas;
import mekanism.api.gas.GasRegistry;
import mekanism.api.gas.GasStack;
import mekanism.api.gas.GasTank;
import mekanism.api.gas.GasTransmission;
import mekanism.api.gas.IGasHandler;
import mekanism.api.gas.IGasItem;
import mekanism.api.gas.ITubeConnection;
import mekanism.common.ISustainedTank;
import mekanism.common.Mekanism;
import mekanism.common.PacketHandler;
import mekanism.common.block.BlockMachine.MachineType;
import mekanism.common.network.PacketTileEntity;
import mekanism.common.recipe.RecipeHandler;
import mekanism.common.recipe.RecipeHandler.Recipe;
import mekanism.common.util.ChargeUtils;
import mekanism.common.util.InventoryUtils;
import mekanism.common.util.MekanismUtils;
import net.minecraft.item.ItemStack;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.tileentity.TileEntity;
import net.minecraftforge.common.util.ForgeDirection;
import net.minecraftforge.fluids.Fluid;
import net.minecraftforge.fluids.FluidContainerRegistry;
import net.minecraftforge.fluids.FluidRegistry;
import net.minecraftforge.fluids.FluidStack;
import net.minecraftforge.fluids.FluidTank;
import net.minecraftforge.fluids.FluidTankInfo;
import net.minecraftforge.fluids.IFluidHandler;
import com.google.common.io.ByteArrayDataInput;
import dan200.computercraft.api.peripheral.IComputerAccess;
import dan200.computercraft.api.lua.ILuaContext;
import dan200.computercraft.api.peripheral.IPeripheral;
public class TileEntityElectrolyticSeparator extends TileEntityElectricBlock implements IFluidHandler, IPeripheral, ITubeConnection, ISustainedTank, IGasHandler
{
/** This separator's water slot. */
public FluidTank fluidTank = new FluidTank(24000);
/** The maximum amount of gas this block can store. */
public int MAX_GAS = 2400;
/** The amount of oxygen this block is storing. */
public GasTank leftTank = new GasTank(MAX_GAS);
/** The amount of hydrogen this block is storing. */
public GasTank rightTank = new GasTank(MAX_GAS);
/** How fast this block can output gas. */
public int output = 16;
/** The type of gas this block is outputting. */
public boolean dumpLeft = false;
/** Type type of gas this block is dumping. */
public boolean dumpRight = false;
public boolean isActive = false;
public TileEntityElectrolyticSeparator()
{
super("ElectrolyticSeparator", MachineType.ELECTROLYTIC_SEPARATOR.baseEnergy);
inventory = new ItemStack[4];
}
@Override
public void onUpdate()
{
super.onUpdate();
if(!worldObj.isRemote)
{
ChargeUtils.discharge(3, this);
if(inventory[0] != null)
{
if(RecipeHandler.Recipe.ELECTROLYTIC_SEPARATOR.containsRecipe(inventory[0]))
{
FluidStack fluid = FluidContainerRegistry.getFluidForFilledItem(inventory[0]);
if(fluid != null && fluidTank.getFluid() == null || fluid.isFluidEqual(fluidTank.getFluid()) && fluidTank.getFluid().amount+fluid.amount <= fluidTank.getCapacity())
{
fluidTank.fill(fluid, true);
if(inventory[0].getItem().hasContainerItem())
{
inventory[0] = inventory[0].getItem().getContainerItem(inventory[0]);
}
else {
inventory[0].stackSize--;
}
if(inventory[0].stackSize == 0)
{
inventory[0] = null;
}
}
}
}
if(!worldObj.isRemote)
{
if(inventory[1] != null && leftTank.getStored() > 0)
{
leftTank.draw(GasTransmission.addGas(inventory[1], leftTank.getGas()), true);
MekanismUtils.saveChunk(this);
}
if(inventory[2] != null && rightTank.getStored() > 0)
{
rightTank.draw(GasTransmission.addGas(inventory[2], rightTank.getGas()), true);
MekanismUtils.saveChunk(this);
}
}
if(canOperate())
{
setActive(true);
fillTanks(RecipeHandler.getElectrolyticSeparatorOutput(fluidTank, true));
setEnergy(getEnergy() - Mekanism.FROM_H2*2);
}
else {
setActive(false);
}
if(leftTank.getGas() != null)
{
if(!dumpLeft)
{
GasStack toSend = new GasStack(leftTank.getGas().getGas(), Math.min(leftTank.getStored(), output));
leftTank.draw(GasTransmission.emitGasToNetwork(toSend, this, MekanismUtils.getLeft(facing)), true);
TileEntity tileEntity = Coord4D.get(this).getFromSide(MekanismUtils.getLeft(facing)).getTileEntity(worldObj);
if(tileEntity instanceof IGasHandler)
{
if(((IGasHandler)tileEntity).canReceiveGas(MekanismUtils.getLeft(facing).getOpposite(), leftTank.getGas().getGas()))
{
leftTank.draw(((IGasHandler)tileEntity).receiveGas(MekanismUtils.getLeft(facing).getOpposite(), toSend), true);
}
}
}
else {
leftTank.draw(8, true);
if(worldObj.rand.nextInt(3) == 2)
{
Mekanism.packetPipeline.sendToAllAround(new PacketTileEntity(Coord4D.get(this), getParticlePacket(0, new ArrayList())), Coord4D.get(this), 40D);
}
}
}
if(rightTank.getGas() != null)
{
if(!dumpRight)
{
GasStack toSend = new GasStack(rightTank.getGas().getGas(), Math.min(rightTank.getStored(), output));
rightTank.draw(GasTransmission.emitGasToNetwork(toSend, this, MekanismUtils.getRight(facing)), true);
TileEntity tileEntity = Coord4D.get(this).getFromSide(MekanismUtils.getRight(facing)).getTileEntity(worldObj);
if(tileEntity instanceof IGasHandler)
{
if(((IGasHandler)tileEntity).canReceiveGas(MekanismUtils.getRight(facing).getOpposite(), rightTank.getGas().getGas()))
{
rightTank.draw(((IGasHandler)tileEntity).receiveGas(MekanismUtils.getRight(facing).getOpposite(), toSend), true);
}
}
}
else {
rightTank.draw(8, true);
if(worldObj.rand.nextInt(3) == 2)
{
Mekanism.packetPipeline.sendToAllAround(new PacketTileEntity(Coord4D.get(this), getParticlePacket(1, new ArrayList())), Coord4D.get(this), 40D);
}
}
}
}
}
public boolean canOperate()
{
return canFillWithSwap(RecipeHandler.getElectrolyticSeparatorOutput(fluidTank, false)) && getEnergy() >= Mekanism.FROM_H2*2;
}
public boolean canFillWithSwap(ChemicalPair gases)
{
if(gases == null)
{
return false;
}
return canFill(gases) || canFill(gases.swap());
}
public boolean canFill(ChemicalPair gases)
{
return (leftTank.canReceive(gases.leftGas.getGas()) && leftTank.getNeeded() >= gases.leftGas.amount
&& rightTank.canReceive(gases.rightGas.getGas()) && rightTank.getNeeded() >= gases.rightGas.amount);
}
public void fillTanks(ChemicalPair gases)
{
if(gases == null) return;
if(canFill(gases))
{
leftTank.receive(gases.leftGas, true);
rightTank.receive(gases.rightGas, true);
}
else if(canFill(gases.swap()))
{
leftTank.receive(gases.rightGas, true);
rightTank.receive(gases.leftGas, true);
}
}
public void spawnParticle(int type)
{
if(type == 0)
{
ForgeDirection side = ForgeDirection.getOrientation(facing);
double x = xCoord + (side.offsetX == 0 ? 0.5 : Math.max(side.offsetX, 0));
double z = zCoord + (side.offsetZ == 0 ? 0.5 : Math.max(side.offsetZ, 0));
worldObj.spawnParticle("smoke", x, yCoord + 0.5, z, 0.0D, 0.0D, 0.0D);
}
else if(type == 1)
{
switch(facing)
{
case 3:
worldObj.spawnParticle("smoke", xCoord+0.9, yCoord+1, zCoord+0.75, 0.0D, 0.0D, 0.0D);
break;
case 4:
worldObj.spawnParticle("smoke", xCoord+0.25, yCoord+1, zCoord+0.9, 0.0D, 0.0D, 0.0D);
break;
case 2:
worldObj.spawnParticle("smoke", xCoord+0.1, yCoord+1, zCoord+0.25, 0.0D, 0.0D, 0.0D);
break;
case 5:
worldObj.spawnParticle("smoke", xCoord+0.75, yCoord+1, zCoord+0.1, 0.0D, 0.0D, 0.0D);
break;
}
}
}
@Override
public boolean canExtractItem(int slotID, ItemStack itemstack, int side)
{
if(slotID == 3)
{
return ChargeUtils.canBeOutputted(itemstack, false);
}
else if(slotID == 0)
{
return FluidContainerRegistry.isEmptyContainer(itemstack);
}
else if(slotID == 1 || slotID == 2)
{
return itemstack.getItem() instanceof IGasItem && ((IGasItem)itemstack.getItem()).getGas(itemstack) != null &&
((IGasItem)itemstack.getItem()).getGas(itemstack).amount == ((IGasItem)itemstack.getItem()).getMaxGas(itemstack);
}
return false;
}
@Override
public boolean isItemValidForSlot(int slotID, ItemStack itemstack)
{
if(slotID == 0)
{
return Recipe.ELECTROLYTIC_SEPARATOR.containsRecipe(itemstack);
}
else if(slotID == 1)
{
return itemstack.getItem() instanceof IGasItem && (((IGasItem)itemstack.getItem()).getGas(itemstack) == null || ((IGasItem)itemstack.getItem()).getGas(itemstack).getGas() == GasRegistry.getGas("hydrogen"));
}
else if(slotID == 2)
{
return itemstack.getItem() instanceof IGasItem && (((IGasItem)itemstack.getItem()).getGas(itemstack) == null || ((IGasItem)itemstack.getItem()).getGas(itemstack).getGas() == GasRegistry.getGas("oxygen"));
}
else if(slotID == 3)
{
return ChargeUtils.canBeDischarged(itemstack);
}
return true;
}
@Override
public int[] getAccessibleSlotsFromSide(int side)
{
if(ForgeDirection.getOrientation(side) == MekanismUtils.getRight(facing))
{
return new int[] {3};
}
else if(side == facing || ForgeDirection.getOrientation(side) == ForgeDirection.getOrientation(facing).getOpposite())
{
return new int[] {1, 2};
}
return InventoryUtils.EMPTY;
}
/**
* Gets the scaled hydrogen level for the GUI.
* @param i - multiplier
* @return
*/
public int getLeftScaledLevel(int i)
{
return leftTank.getStored()*i / MAX_GAS;
}
/**
* Gets the scaled oxygen level for the GUI.
* @param i - multiplier
* @return
*/
public int getRightScaledLevel(int i)
{
return rightTank.getStored()*i / MAX_GAS;
}
/**
* Gets the scaled water level for the GUI.
* @param i - multiplier
* @return
*/
public int getScaledFluidLevel(int i)
{
return fluidTank.getFluid() != null ? fluidTank.getFluid().amount*i / fluidTank.getCapacity() : 0;
}
/**
* Gets the scaled energy level for the GUI.
* @param i - multiplier
* @return
*/
public int getScaledEnergyLevel(int i)
{
return (int)(electricityStored*i / MAX_ELECTRICITY);
}
@Override
public void handlePacketData(ByteArrayDataInput dataStream)
{
if(!worldObj.isRemote)
{
byte type = dataStream.readByte();
if(type == 0)
{
dumpLeft ^= true;
}
else if(type == 1)
{
dumpRight ^= true;
}
return;
}
super.handlePacketData(dataStream);
int type = dataStream.readInt();
if(type == 0)
{
if(dataStream.readBoolean())
{
fluidTank.setFluid(new FluidStack(FluidRegistry.getFluid(dataStream.readInt()), dataStream.readInt()));
}
else {
fluidTank.setFluid(null);
}
if(dataStream.readBoolean())
{
leftTank.setGas(new GasStack(GasRegistry.getGas(dataStream.readInt()), dataStream.readInt()));
}
else {
leftTank.setGas(null);
}
if(dataStream.readBoolean())
{
rightTank.setGas(new GasStack(GasRegistry.getGas(dataStream.readInt()), dataStream.readInt()));
}
else {
rightTank.setGas(null);
}
dumpLeft = dataStream.readBoolean();
dumpRight = dataStream.readBoolean();
isActive = dataStream.readBoolean();
}
else if(type == 1)
{
spawnParticle(dataStream.readInt());
}
}
@Override
public ArrayList getNetworkedData(ArrayList data)
{
super.getNetworkedData(data);
data.add(0);
if(fluidTank.getFluid() != null)
{
data.add(true);
data.add(fluidTank.getFluid().getFluid().getID());
data.add(fluidTank.getFluidAmount());
}
else {
data.add(false);
}
if(leftTank.getGas() != null)
{
data.add(true);
data.add(leftTank.getGas().getGas().getID());
data.add(leftTank.getStored());
}
else {
data.add(false);
}
if(rightTank.getGas() != null)
{
data.add(true);
data.add(rightTank.getGas().getGas().getID());
data.add(rightTank.getStored());
}
else {
data.add(false);
}
data.add(dumpLeft);
data.add(dumpRight);
data.add(isActive);
return data;
}
public ArrayList getParticlePacket(int type, ArrayList data)
{
super.getNetworkedData(data);
data.add(1);
data.add(type);
return data;
}
@Override
public void readFromNBT(NBTTagCompound nbtTags)
{
super.readFromNBT(nbtTags);
if(nbtTags.hasKey("fluidTank"))
{
fluidTank.readFromNBT(nbtTags.getCompoundTag("fluidTank"));
}
leftTank.read(nbtTags.getCompoundTag("leftTank"));
rightTank.read(nbtTags.getCompoundTag("rightTank"));
dumpLeft = nbtTags.getBoolean("dumpLeft");
dumpRight = nbtTags.getBoolean("dumpRight");
}
@Override
public void writeToNBT(NBTTagCompound nbtTags)
{
super.writeToNBT(nbtTags);
if(fluidTank.getFluid() != null)
{
nbtTags.setTag("fluidTank", fluidTank.writeToNBT(new NBTTagCompound()));
}
nbtTags.setTag("leftTank", leftTank.write(new NBTTagCompound()));
nbtTags.setTag("rightTank", rightTank.write(new NBTTagCompound()));
nbtTags.setBoolean("dumpLeft", dumpLeft);
nbtTags.setBoolean("dumpRight", dumpRight);
}
@Override
public String getType()
{
return getInventoryName();
}
@Override
public String[] getMethodNames()
{
return new String[] {"getStored", "getOutput", "getMaxEnergy", "getEnergyNeeded", "getWater", "getWaterNeeded", "getHydrogen", "getHydrogenNeeded", "getOxygen", "getOxygenNeeded"};
}
@Override
public Object[] callMethod(IComputerAccess computer, ILuaContext context, int method, Object[] arguments) throws Exception
{
switch(method)
{
case 0:
return new Object[] {electricityStored};
case 1:
return new Object[] {output};
case 2:
return new Object[] {MAX_ELECTRICITY};
case 3:
return new Object[] {(MAX_ELECTRICITY-electricityStored)};
case 4:
return new Object[] {fluidTank.getFluid() != null ? fluidTank.getFluid().amount : 0};
case 5:
return new Object[] {fluidTank.getFluid() != null ? (fluidTank.getCapacity()- fluidTank.getFluid().amount) : 0};
case 6:
return new Object[] {leftTank.getStored()};
case 7:
return new Object[] {leftTank.getNeeded()};
case 8:
return new Object[] {rightTank.getStored()};
case 9:
return new Object[] {rightTank.getNeeded()};
default:
System.err.println("[Mekanism] Attempted to call unknown method with computer ID " + computer.getID());
return new Object[] {"Unknown command."};
}
}
@Override
public boolean equals(IPeripheral other)
{
return this == other;
}
@Override
public void attach(IComputerAccess computer) {}
@Override
public void detach(IComputerAccess computer) {}
@Override
public boolean canTubeConnect(ForgeDirection side)
{
return side == MekanismUtils.getLeft(facing) || side == MekanismUtils.getRight(facing);
}
@Override
public void setFluidStack(FluidStack fluidStack, Object... data)
{
fluidTank.setFluid(fluidStack);
}
@Override
public FluidStack getFluidStack(Object... data)
{
return fluidTank.getFluid();
}
@Override
public boolean hasTank(Object... data)
{
return true;
}
@Override
public FluidStack drain(ForgeDirection from, FluidStack resource, boolean doDrain)
{
return null;
}
@Override
public boolean canFill(ForgeDirection from, Fluid fluid)
{
return RecipeHandler.Recipe.ELECTROLYTIC_SEPARATOR.containsRecipe(fluid);
}
@Override
public boolean canDrain(ForgeDirection from, Fluid fluid)
{
return false;
}
@Override
public int fill(ForgeDirection from, FluidStack resource, boolean doFill)
{
if(RecipeHandler.Recipe.ELECTROLYTIC_SEPARATOR.containsRecipe(resource.getFluid()))
{
return fluidTank.fill(resource, doFill);
}
return 0;
}
@Override
public FluidStack drain(ForgeDirection from, int maxDrain, boolean doDrain)
{
return null;
}
@Override
public FluidTankInfo[] getTankInfo(ForgeDirection from)
{
return new FluidTankInfo[] {fluidTank.getInfo()};
}
@Override
public int receiveGas(ForgeDirection side, GasStack stack)
{
return 0;
}
@Override
public GasStack drawGas(ForgeDirection side, int amount)
{
if(side == MekanismUtils.getLeft(facing))
{
return leftTank.draw(amount, true);
}
else if(side == MekanismUtils.getRight(facing))
{
return rightTank.draw(amount, true);
}
return null;
}
@Override
public boolean canReceiveGas(ForgeDirection side, Gas type)
{
return false;
}
@Override
public boolean canDrawGas(ForgeDirection side, Gas type)
{
if(side == MekanismUtils.getLeft(facing))
{
return leftTank.getGas() != null && leftTank.getGas().getGas() == type;
}
else if(side == MekanismUtils.getRight(facing))
{
return rightTank.getGas() != null && rightTank.getGas().getGas() == type;
}
return false;
}
public void setActive(boolean active)
{
isActive = active;
}
}