Optimized drain algorithm to be based off distance
This commit is contained in:
parent
11b8227fea
commit
d91fdcf8fe
4 changed files with 94 additions and 61 deletions
|
@ -1,5 +1,6 @@
|
||||||
package resonantinduction.api.fluid;
|
package resonantinduction.api.fluid;
|
||||||
|
|
||||||
|
import java.util.List;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import net.minecraftforge.common.ForgeDirection;
|
import net.minecraftforge.common.ForgeDirection;
|
||||||
|
@ -17,8 +18,8 @@ import calclavia.lib.prefab.tile.IRotatable;
|
||||||
public interface IDrain extends IFluidHandler, IRotatable
|
public interface IDrain extends IFluidHandler, IRotatable
|
||||||
{
|
{
|
||||||
/** Gets the list of fillable blocks */
|
/** Gets the list of fillable blocks */
|
||||||
public Set<Vector3> getFillList();
|
public List<Vector3> getFillList();
|
||||||
|
|
||||||
/** Gets the list of drainable blocks */
|
/** Gets the list of drainable blocks */
|
||||||
public Set<Vector3> getDrainList();
|
public List<Vector3> getDrainList();
|
||||||
}
|
}
|
||||||
|
|
|
@ -2,6 +2,7 @@ package resonantinduction.mechanical.fluid.network;
|
||||||
|
|
||||||
import java.util.EnumSet;
|
import java.util.EnumSet;
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
|
import java.util.Iterator;
|
||||||
import java.util.Map.Entry;
|
import java.util.Map.Entry;
|
||||||
|
|
||||||
import net.minecraft.tileentity.TileEntity;
|
import net.minecraft.tileentity.TileEntity;
|
||||||
|
@ -36,8 +37,11 @@ public class PipeNetwork extends FluidNetwork
|
||||||
FluidStack stack = this.getTank().getFluid().copy();
|
FluidStack stack = this.getTank().getFluid().copy();
|
||||||
int count = this.sideMap.size();
|
int count = this.sideMap.size();
|
||||||
|
|
||||||
for (Entry<IFluidHandler, EnumSet<ForgeDirection>> entry : this.sideMap.entrySet())
|
Iterator<Entry<IFluidHandler, EnumSet<ForgeDirection>>> it = new HashMap<IFluidHandler, EnumSet<ForgeDirection>>(sideMap).entrySet().iterator();
|
||||||
|
|
||||||
|
while (it.hasNext())
|
||||||
{
|
{
|
||||||
|
Entry<IFluidHandler, EnumSet<ForgeDirection>> entry = it.next();
|
||||||
int sideCount = entry.getValue().size();
|
int sideCount = entry.getValue().size();
|
||||||
|
|
||||||
for (ForgeDirection dir : entry.getValue())
|
for (ForgeDirection dir : entry.getValue())
|
||||||
|
|
|
@ -28,6 +28,7 @@ public class LiquidPathFinder
|
||||||
public Set<Vector3> nodeList = new HashSet<Vector3>();
|
public Set<Vector3> nodeList = new HashSet<Vector3>();
|
||||||
/** List of all nodes that match the search parms */
|
/** List of all nodes that match the search parms */
|
||||||
public Set<Vector3> results = new HashSet<Vector3>();
|
public Set<Vector3> results = new HashSet<Vector3>();
|
||||||
|
public final List<Vector3> sortedResults = new ArrayList<Vector3>();
|
||||||
/** Are we looking for liquid fillable blocks */
|
/** Are we looking for liquid fillable blocks */
|
||||||
private boolean fill = false;
|
private boolean fill = false;
|
||||||
/** priority search direction either up or down only */
|
/** priority search direction either up or down only */
|
||||||
|
@ -143,15 +144,16 @@ public class LiquidPathFinder
|
||||||
public boolean find(ForgeDirection direction, Vector3 origin)
|
public boolean find(ForgeDirection direction, Vector3 origin)
|
||||||
{
|
{
|
||||||
this.runs++;
|
this.runs++;
|
||||||
Vector3 vec = origin.clone().modifyPositionFromSide(direction);
|
Vector3 vec = origin.clone().translate(direction);
|
||||||
double distance = vec.toVector2().distance(this.Start.toVector2());
|
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))
|
if (this.fill && FluidUtility.drainBlock(world, vec, false) != null || FluidUtility.isFillableFluid(world, vec))
|
||||||
{
|
{
|
||||||
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
|
for (ForgeDirection dir : ForgeDirection.VALID_DIRECTIONS)
|
||||||
{
|
{
|
||||||
Vector3 veb = vec.clone().modifyPositionFromSide(dir);
|
Vector3 veb = vec.clone().translate(dir);
|
||||||
if (FluidUtility.isFillableBlock(world, veb))
|
if (FluidUtility.isFillableBlock(world, veb))
|
||||||
{
|
{
|
||||||
this.addNode(veb);
|
this.addNode(veb);
|
||||||
|
@ -162,6 +164,7 @@ public class LiquidPathFinder
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (this.findNodes(vec))
|
if (this.findNodes(vec))
|
||||||
{
|
{
|
||||||
return true;
|
return true;
|
||||||
|
@ -183,6 +186,7 @@ public class LiquidPathFinder
|
||||||
{
|
{
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
return FluidUtility.drainBlock(world, pos, false) != null || FluidUtility.isFillableFluid(world, pos);
|
return FluidUtility.drainBlock(world, pos, false) != null || FluidUtility.isFillableFluid(world, pos);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -224,7 +228,7 @@ public class LiquidPathFinder
|
||||||
this.find(ForgeDirection.UNKNOWN, startNode);
|
this.find(ForgeDirection.UNKNOWN, startNode);
|
||||||
|
|
||||||
this.refresh();
|
this.refresh();
|
||||||
this.sortBlockList(Start, results, !fill, fill);
|
this.sortBlockList(Start, results, fill);
|
||||||
return this;
|
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
|
* Used to sort a list of vector3 locations using the vector3's distance from one point and
|
||||||
* elevation in the y axis
|
* 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 start - start location to measure distance from
|
||||||
* @param results2 - list of vectors to sort
|
* @param results2 - list of vectors to sort
|
||||||
* @param closest - sort closest distance to the top
|
* @param prioritizeHighest - sort highest y value to the top.
|
||||||
* @param highest - 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<Vector3> set, final boolean closest, final boolean highest)
|
public void sortBlockList(final Vector3 start, final Set<Vector3> set, final boolean prioritizeHighest)
|
||||||
{
|
{
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
List<Vector3> list = new ArrayList<Vector3>();
|
sortedResults.clear();
|
||||||
list.addAll(set);
|
sortedResults.addAll(set);
|
||||||
Collections.sort(list, new Comparator<Vector3>()
|
|
||||||
|
// 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<Vector3>()
|
||||||
{
|
{
|
||||||
@Override
|
@Override
|
||||||
public int compare(Vector3 vecA, Vector3 vecB)
|
public int compare(Vector3 vecA, Vector3 vecB)
|
||||||
{
|
{
|
||||||
// Though unlikely always return zero for equal vectors
|
return Double.compare(vecA.distance(optimalFluid), vecB.distance(optimalFluid));
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
set.clear();
|
|
||||||
set.addAll(list);
|
Collections.reverse(sortedResults);
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
|
|
|
@ -1,14 +1,11 @@
|
||||||
package resonantinduction.mechanical.fluid.pump;
|
package resonantinduction.mechanical.fluid.pump;
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.HashMap;
|
import java.util.Collections;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
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.common.ForgeDirection;
|
||||||
import net.minecraftforge.fluids.Fluid;
|
import net.minecraftforge.fluids.Fluid;
|
||||||
import net.minecraftforge.fluids.FluidContainerRegistry;
|
import net.minecraftforge.fluids.FluidContainerRegistry;
|
||||||
|
@ -23,8 +20,6 @@ import universalelectricity.core.net.NetworkTickHandler;
|
||||||
import calclavia.lib.prefab.tile.TileAdvanced;
|
import calclavia.lib.prefab.tile.TileAdvanced;
|
||||||
import calclavia.lib.utility.FluidUtility;
|
import calclavia.lib.utility.FluidUtility;
|
||||||
|
|
||||||
import com.builtbroken.common.Pair;
|
|
||||||
|
|
||||||
public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
||||||
{
|
{
|
||||||
public static final int MAX_FLUID_MODIFY_RATE = 50;
|
public static final int MAX_FLUID_MODIFY_RATE = 50;
|
||||||
|
@ -45,9 +40,9 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Vector3> getFillList()
|
public List<Vector3> getFillList()
|
||||||
{
|
{
|
||||||
return this.getFillFinder().refresh().results;
|
return this.getFillFinder().refresh().sortedResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
public LiquidPathFinder getDrainFinder()
|
public LiquidPathFinder getDrainFinder()
|
||||||
|
@ -60,9 +55,9 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Set<Vector3> getDrainList()
|
public List<Vector3> getDrainList()
|
||||||
{
|
{
|
||||||
return getDrainFinder().refresh().results;
|
return getDrainFinder().refresh().sortedResults;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -222,7 +217,7 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
||||||
doPathfinding();
|
doPathfinding();
|
||||||
}
|
}
|
||||||
|
|
||||||
Set<Vector3> drainList = getDrainList();
|
List<Vector3> drainList = getDrainList();
|
||||||
|
|
||||||
if (drainList != null && drainList.size() > 0)
|
if (drainList != null && drainList.size() > 0)
|
||||||
{
|
{
|
||||||
|
@ -257,7 +252,7 @@ public class TileGrate extends TileAdvanced implements IFluidHandler, IDrain
|
||||||
*/
|
*/
|
||||||
NetworkTickHandler.addNetwork(new IUpdate()
|
NetworkTickHandler.addNetwork(new IUpdate()
|
||||||
{
|
{
|
||||||
int wait = 60;
|
int wait = 20;
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void update()
|
public void update()
|
||||||
|
|
Loading…
Reference in a new issue