diff --git a/src/main/java/resonantinduction/api/fluid/IDrain.java b/src/main/java/resonantinduction/api/fluid/IDrain.java index 1ecc67e2..5463e97e 100644 --- a/src/main/java/resonantinduction/api/fluid/IDrain.java +++ b/src/main/java/resonantinduction/api/fluid/IDrain.java @@ -1,5 +1,6 @@ package resonantinduction.api.fluid; +import java.util.List; import java.util.Set; import net.minecraftforge.common.ForgeDirection; @@ -17,8 +18,8 @@ import calclavia.lib.prefab.tile.IRotatable; public interface IDrain extends IFluidHandler, IRotatable { /** Gets the list of fillable blocks */ - public Set getFillList(); + public List getFillList(); /** Gets the list of drainable blocks */ - public Set getDrainList(); + public List getDrainList(); } diff --git a/src/main/java/resonantinduction/mechanical/fluid/network/PipeNetwork.java b/src/main/java/resonantinduction/mechanical/fluid/network/PipeNetwork.java index 2f3e64ab..dbff4f0f 100644 --- a/src/main/java/resonantinduction/mechanical/fluid/network/PipeNetwork.java +++ b/src/main/java/resonantinduction/mechanical/fluid/network/PipeNetwork.java @@ -2,6 +2,7 @@ package resonantinduction.mechanical.fluid.network; import java.util.EnumSet; import java.util.HashMap; +import java.util.Iterator; import java.util.Map.Entry; import net.minecraft.tileentity.TileEntity; @@ -36,8 +37,11 @@ public class PipeNetwork extends FluidNetwork FluidStack stack = this.getTank().getFluid().copy(); int count = this.sideMap.size(); - for (Entry> entry : this.sideMap.entrySet()) + Iterator>> it = new HashMap>(sideMap).entrySet().iterator(); + + while (it.hasNext()) { + Entry> entry = it.next(); int sideCount = entry.getValue().size(); for (ForgeDirection dir : entry.getValue()) @@ -54,7 +58,7 @@ public class PipeNetwork extends FluidNetwork { stack.amount -= handler.fill(dir, FluidUtility.getStack(stack, Math.min(volPerSide, this.maxFlowRate)), true); } - + if (sideCount > 1) --sideCount; if (volPer <= 0) diff --git a/src/main/java/resonantinduction/mechanical/fluid/pump/LiquidPathFinder.java b/src/main/java/resonantinduction/mechanical/fluid/pump/LiquidPathFinder.java index 7c94db5a..4c5f6431 100644 --- a/src/main/java/resonantinduction/mechanical/fluid/pump/LiquidPathFinder.java +++ b/src/main/java/resonantinduction/mechanical/fluid/pump/LiquidPathFinder.java @@ -28,6 +28,7 @@ public class LiquidPathFinder public Set nodeList = new HashSet(); /** List of all nodes that match the search parms */ public Set results = new HashSet(); + public final List sortedResults = new ArrayList(); /** Are we looking for liquid fillable blocks */ private boolean fill = false; /** priority search direction either up or down only */ @@ -143,15 +144,16 @@ public class LiquidPathFinder public boolean find(ForgeDirection direction, Vector3 origin) { this.runs++; - Vector3 vec = origin.clone().modifyPositionFromSide(direction); + Vector3 vec = origin.clone().translate(direction); double distance = vec.toVector2().distance(this.Start.toVector2()); - if (distance <= this.range && this.isValidNode(vec)) + + if (distance <= this.range && isValidNode(vec)) { if (this.fill && FluidUtility.drainBlock(world, vec, false) != null || FluidUtility.isFillableFluid(world, vec)) { for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS) { - Vector3 veb = vec.clone().modifyPositionFromSide(dir); + Vector3 veb = vec.clone().translate(dir); if (FluidUtility.isFillableBlock(world, veb)) { this.addNode(veb); @@ -162,6 +164,7 @@ public class LiquidPathFinder } } } + if (this.findNodes(vec)) { return true; @@ -183,6 +186,7 @@ public class LiquidPathFinder { return false; } + return FluidUtility.drainBlock(world, pos, false) != null || FluidUtility.isFillableFluid(world, pos); } @@ -224,7 +228,7 @@ public class LiquidPathFinder this.find(ForgeDirection.UNKNOWN, startNode); this.refresh(); - this.sortBlockList(Start, results, !fill, fill); + this.sortBlockList(Start, results, fill); return this; } @@ -270,60 +274,89 @@ public class LiquidPathFinder * Used to sort a list of vector3 locations using the vector3's distance from one point and * elevation in the y axis * + * Sorting is ordered from the highest-furthest block and consequently will have its adjacent + * blocks as the "next blocks" to make sure the fluid can easily remove infinite fluids like + * water. + * * @param start - start location to measure distance from * @param results2 - list of vectors to sort - * @param closest - sort closest distance to the top - * @param highest - sort highest y value to the top. + * @param prioritizeHighest - sort highest y value to the top. * - * Note: highest takes priority over closest + * Note: Height takes priority over distance. */ - public void sortBlockList(final Vector3 start, final Set set, final boolean closest, final boolean highest) + public void sortBlockList(final Vector3 start, final Set set, final boolean prioritizeHighest) { try { - List list = new ArrayList(); - list.addAll(set); - Collections.sort(list, new Comparator() + sortedResults.clear(); + sortedResults.addAll(set); + + // The highest and furthest fluid block for drain. Closest fluid block for fill. + Vector3 bestFluid = null; + + for (Vector3 checkPos : set) + { + if (bestFluid == null) + { + bestFluid = checkPos; + } + + if (fill) + { + /** + * We're filling, so we want the closest lowest block first. + */ + if (prioritizeHighest) + { + if (checkPos.y < bestFluid.y) + { + bestFluid = checkPos; + } + else if (checkPos.y == bestFluid.y && start.distance(checkPos) < start.distance(bestFluid)) + { + bestFluid = checkPos; + } + } + else if (start.distance(checkPos) < start.distance(bestFluid)) + { + bestFluid = checkPos; + } + } + else + { + /** + * We're draining, so we want the highest furthest block first. + */ + if (prioritizeHighest) + { + if (checkPos.y > bestFluid.y) + { + bestFluid = checkPos; + } + else if (checkPos.y == bestFluid.y && start.distance(checkPos) > start.distance(bestFluid)) + { + bestFluid = checkPos; + } + } + else if (start.distance(checkPos) > start.distance(bestFluid)) + { + bestFluid = checkPos; + } + } + } + + final Vector3 optimalFluid = bestFluid; + + Collections.sort(sortedResults, new Comparator() { @Override public int compare(Vector3 vecA, Vector3 vecB) { - // Though unlikely always return zero for equal vectors - if (vecA.equals(vecB)) - { - return 0; - } - // Check y value fist as this is the primary search area - if (Integer.compare(vecA.intY(), vecB.intY()) != 0) - { - if (highest) - { - return vecA.intY() > vecB.intY() ? -1 : 1; - } - else - { - return vecA.intY() > vecB.intY() ? 1 : -1; - } - } - // Check distance after that - double distanceA = Vector2.distance(vecA.toVector2(), start.toVector2()); - double distanceB = Vector2.distance(vecB.toVector2(), start.toVector2()); - if (Double.compare(distanceA, distanceB) != 0) - { - if (closest) - { - return distanceA > distanceB ? 1 : -1; - } - else - { - return distanceA > distanceB ? -1 : 1; - } - } - return Double.compare(distanceA, distanceB); + return Double.compare(vecA.distance(optimalFluid), vecB.distance(optimalFluid)); } }); - set.clear(); - set.addAll(list); + + Collections.reverse(sortedResults); } catch (Exception e) { diff --git a/src/main/java/resonantinduction/mechanical/fluid/pump/TileGrate.java b/src/main/java/resonantinduction/mechanical/fluid/pump/TileGrate.java index c0c9dc86..82e8d571 100644 --- a/src/main/java/resonantinduction/mechanical/fluid/pump/TileGrate.java +++ b/src/main/java/resonantinduction/mechanical/fluid/pump/TileGrate.java @@ -1,14 +1,11 @@ package resonantinduction.mechanical.fluid.pump; import java.util.ArrayList; -import java.util.HashMap; +import java.util.Collections; import java.util.Iterator; import java.util.List; import java.util.Set; -import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.tileentity.TileEntity; -import net.minecraft.world.World; import net.minecraftforge.common.ForgeDirection; import net.minecraftforge.fluids.Fluid; import net.minecraftforge.fluids.FluidContainerRegistry; @@ -23,8 +20,6 @@ import universalelectricity.core.net.NetworkTickHandler; import calclavia.lib.prefab.tile.TileAdvanced; import calclavia.lib.utility.FluidUtility; -import com.builtbroken.common.Pair; - public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain { public static final int MAX_FLUID_MODIFY_RATE = 50; @@ -45,9 +40,9 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain } @Override - public Set getFillList() + public List getFillList() { - return this.getFillFinder().refresh().results; + return this.getFillFinder().refresh().sortedResults; } public LiquidPathFinder getDrainFinder() @@ -60,9 +55,9 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain } @Override - public Set getDrainList() + public List getDrainList() { - return getDrainFinder().refresh().results; + return getDrainFinder().refresh().sortedResults; } @Override @@ -222,7 +217,7 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain doPathfinding(); } - Set drainList = getDrainList(); + List drainList = getDrainList(); if (drainList != null && drainList.size() > 0) { @@ -257,7 +252,7 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain */ NetworkTickHandler.addNetwork(new IUpdate() { - int wait = 60; + int wait = 20; @Override public void update()