diff --git a/archaic/src/main/scala/resonantinduction/archaic/fluid/tank/TankNetwork.java b/archaic/src/main/scala/resonantinduction/archaic/fluid/tank/TankNetwork.java index 8b2d1ae1..ac0e8af5 100644 --- a/archaic/src/main/scala/resonantinduction/archaic/fluid/tank/TankNetwork.java +++ b/archaic/src/main/scala/resonantinduction/archaic/fluid/tank/TankNetwork.java @@ -1,10 +1,13 @@ package resonantinduction.archaic.fluid.tank; +import java.util.Comparator; import java.util.HashMap; import java.util.LinkedList; +import java.util.PriorityQueue; import net.minecraft.tileentity.TileEntity; import net.minecraftforge.fluids.FluidStack; +import resonant.lib.utility.FluidUtility; import resonantinduction.core.grid.fluid.FluidDistributionetwork; import resonantinduction.core.grid.fluid.IFluidDistribution; @@ -22,119 +25,97 @@ public class TankNetwork extends FluidDistributionetwork @Override public void update() { - final FluidStack networkTankFluid = getTank().getFluid(); - int lowestY = 255; - int highestY = 0; - int connectorCount; - int totalFluid = networkTankFluid != null ? networkTankFluid.amount : 0; + final FluidStack networkTankFluid = getTank().getFluid(); + int lowestY = 255, highestY = 0; - //If we only have one tank only fill one tank + if (getConnectors().size() > 0) + { + int totalFluid = networkTankFluid != null ? networkTankFluid.amount : 0; - if (getConnectors().size() > 0) - { - IFluidDistribution tank = ((IFluidDistribution) getConnectors().toArray()[0]); - if (getConnectors().size() == 1) - { - tank.getInternalTank().setFluid(networkTankFluid); - tank.onFluidChanged(); - needsUpdate = false; - return; - } - if (networkTankFluid != null) - { - //If fluid is gaseous fill all tanks equally - if (networkTankFluid.getFluid().isGaseous()) - { - connectorCount = this.getConnectors().size(); - for (IFluidDistribution connector : this.getConnectors()) - { - FluidStack input = networkTankFluid.copy(); - input.amount = (totalFluid / connectorCount) + (totalFluid % connectorCount); - connector.getInternalTank().setFluid(null); - totalFluid -= connector.getInternalTank().fill(input, true); - connector.onFluidChanged(); + HashMap heightCount = new HashMap(); + PriorityQueue heightPriorityQueue = new PriorityQueue(1024, new Comparator() + { + @Override + public int compare(Object a, Object b) + { + if (networkTankFluid != null && networkTankFluid.getFluid().isGaseous()) + return 0; - if (connectorCount > 0) - connectorCount--; - } - } - else - { - HashMap> heightMap = new HashMap(); + TileEntity wa = (TileEntity) a; + TileEntity wb = (TileEntity) b; + return wa.yCoord - wb.yCoord; + } + }); - //Build map of all tanks by their y level - for (IFluidDistribution connector : this.getConnectors()) - { - if (connector instanceof TileEntity) - { - LinkedList list = new LinkedList(); - int yCoord = ((TileEntity) connector).yCoord; + for (IFluidDistribution connector : this.getConnectors()) + { + if (connector instanceof TileEntity) + { + int yCoord = ((TileEntity) connector).yCoord; - if (yCoord < lowestY) - { - lowestY = yCoord; - } + if (yCoord < lowestY) + { + lowestY = yCoord; + } - if (yCoord > highestY) - { - highestY = yCoord; - } + if (yCoord > highestY) + { + highestY = yCoord; + } - if (heightMap.containsKey(yCoord)) - { - list = heightMap.get(yCoord); - } - list.add(connector); - heightMap.put(yCoord, list); - } - } + heightPriorityQueue.add(connector); + heightCount.put(yCoord, heightCount.containsKey(yCoord) ? heightCount.get(yCoord) + 1 : 1); + } + } - //Loop threw levels - for (int yLevel = lowestY; yLevel <= highestY; yLevel++) - { - if (heightMap.containsKey(yLevel)) - { - connectorCount = heightMap.get(yLevel).size(); + boolean didChange = false; - if (connectorCount <= 0) - continue; - //Loop threw tanks in each level - for (IFluidDistribution connector : heightMap.get(yLevel)) - { - //If tank is empty clear internal and move on - if (totalFluid <= 0) - { - connector.getInternalTank().setFluid(null); - connector.onFluidChanged(); - continue; - } + while (!heightPriorityQueue.isEmpty()) + { + IFluidDistribution distributeNode = heightPriorityQueue.poll(); + int yCoord = ((TileEntity) distributeNode).yCoord; + int connectorCount = heightCount.get(yCoord); - FluidStack input = networkTankFluid.copy(); - input.amount = (totalFluid / connectorCount) + (totalFluid % connectorCount); - connector.getInternalTank().setFluid(null); - totalFluid -= connector.getInternalTank().fill(input, true); - connector.onFluidChanged(); + if (totalFluid <= 0) + { + distributeNode.getInternalTank().setFluid(null); + distributeNode.onFluidChanged(); + continue; + } - if (connectorCount > 1) - connectorCount--; + int fluidPer = totalFluid / connectorCount; + int deltaFluidAmount = fluidPer - distributeNode.getInternalTank().getFluidAmount(); - } - } - } - } - } - else - { - //In the cases the tank is empty just clear all tanks - //instead of doing additional logic that is wasting ticks - for (IFluidDistribution connector : this.getConnectors()) - { - connector.getInternalTank().setFluid(null); - connector.onFluidChanged(); - } - } - } - needsUpdate = false; + int current = distributeNode.getInternalTank().getFluidAmount(); + + if (deltaFluidAmount > 0) + { + int filled = distributeNode.getInternalTank().fill(FluidUtility.getStack(networkTankFluid, deltaFluidAmount), false); + distributeNode.getInternalTank().fill(FluidUtility.getStack(networkTankFluid, deltaFluidAmount / 10), true); + totalFluid -= current + filled; + } + else + { + FluidStack drain = distributeNode.getInternalTank().drain(Math.abs(deltaFluidAmount), false); + distributeNode.getInternalTank().drain(Math.abs(deltaFluidAmount / 10), true); + + if (drain != null) + totalFluid -= current - drain.amount; + } + + if (deltaFluidAmount != 0) + didChange = true; + + if (connectorCount > 1) + connectorCount--; + + heightCount.put(yCoord, connectorCount); + distributeNode.onFluidChanged(); + } + + if (!didChange) + needsUpdate = false; + } } @Override