2018-08-03 04:50:45 +00:00
|
|
|
package baritone.bot.pathing.calc;
|
|
|
|
|
|
|
|
import baritone.bot.pathing.goals.Goal;
|
2018-08-05 03:25:05 +00:00
|
|
|
import baritone.bot.pathing.path.IPath;
|
2018-08-03 04:50:45 +00:00
|
|
|
import net.minecraft.util.math.BlockPos;
|
|
|
|
|
|
|
|
import java.util.HashMap;
|
2018-08-03 07:51:10 +00:00
|
|
|
import java.util.Map;
|
2018-08-03 04:50:45 +00:00
|
|
|
|
2018-08-03 13:55:17 +00:00
|
|
|
/**
|
|
|
|
* Any pathfinding algorithm that keeps track of nodes recursively by their cost (e.g. A*, dijkstra)
|
|
|
|
*
|
|
|
|
* @author leijurv
|
|
|
|
*/
|
2018-08-03 04:50:45 +00:00
|
|
|
public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|
|
|
|
2018-08-03 07:51:10 +00:00
|
|
|
/**
|
|
|
|
* The currently running search task
|
2018-08-03 13:55:17 +00:00
|
|
|
* <p>
|
2018-08-03 07:51:10 +00:00
|
|
|
* TODO: This shouldn't be necessary, investigate old purpose of this field and determine necessity.
|
|
|
|
*/
|
2018-08-03 04:50:45 +00:00
|
|
|
public static AbstractNodeCostSearch currentlyRunning = null;
|
|
|
|
|
|
|
|
protected final BlockPos start;
|
2018-08-03 07:51:10 +00:00
|
|
|
|
2018-08-03 04:50:45 +00:00
|
|
|
protected final Goal goal;
|
2018-08-03 07:51:10 +00:00
|
|
|
|
|
|
|
protected final Map<BlockPos, PathNode> map;
|
|
|
|
|
2018-08-03 04:50:45 +00:00
|
|
|
protected PathNode startNode;
|
2018-08-03 07:51:10 +00:00
|
|
|
|
2018-08-03 04:50:45 +00:00
|
|
|
protected PathNode mostRecentConsidered;
|
2018-08-03 07:51:10 +00:00
|
|
|
|
2018-08-03 04:50:45 +00:00
|
|
|
protected PathNode[] bestSoFar;
|
2018-08-03 07:51:10 +00:00
|
|
|
|
2018-08-03 04:50:45 +00:00
|
|
|
private volatile boolean isFinished;
|
|
|
|
|
|
|
|
/**
|
|
|
|
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
|
|
|
|
* long it was easier as a Google Doc (because I could insert charts).
|
2018-08-03 04:55:53 +00:00
|
|
|
*
|
2018-08-03 05:06:06 +00:00
|
|
|
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a>
|
2018-08-03 04:50:45 +00:00
|
|
|
*/
|
|
|
|
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10};
|
2018-08-03 05:06:49 +00:00
|
|
|
/**
|
|
|
|
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
|
|
|
|
*/
|
|
|
|
protected final static double MIN_DIST_PATH = 5;
|
2018-08-03 04:50:45 +00:00
|
|
|
|
2018-08-03 05:06:49 +00:00
|
|
|
AbstractNodeCostSearch(BlockPos start, Goal goal) {
|
2018-08-03 04:50:45 +00:00
|
|
|
this.start = start;
|
|
|
|
this.goal = goal;
|
|
|
|
this.map = new HashMap<>();
|
|
|
|
}
|
|
|
|
|
2018-08-03 07:51:10 +00:00
|
|
|
public synchronized IPath calculate() {
|
2018-08-03 04:50:45 +00:00
|
|
|
if (isFinished) {
|
2018-08-03 07:51:10 +00:00
|
|
|
throw new IllegalStateException("Path Finder is currently in use! Wait until complete to reuse!");
|
2018-08-03 04:50:45 +00:00
|
|
|
}
|
2018-08-03 07:51:10 +00:00
|
|
|
IPath path = calculate0();
|
2018-08-03 04:50:45 +00:00
|
|
|
isFinished = true;
|
|
|
|
return path;
|
|
|
|
}
|
|
|
|
|
2018-08-03 07:51:10 +00:00
|
|
|
protected abstract IPath calculate0();
|
2018-08-03 04:50:45 +00:00
|
|
|
|
2018-08-03 07:51:10 +00:00
|
|
|
/**
|
|
|
|
* Determines the distance squared from the specified node to the start
|
|
|
|
* node. Intended for use in distance comparison, rather than anything that
|
|
|
|
* considers the real distance value, hence the "sq".
|
|
|
|
*
|
|
|
|
* @param n A node
|
|
|
|
* @return The distance, squared
|
2018-08-03 13:55:17 +00:00
|
|
|
* @see AbstractNodeCostSearch#getDistFromStart(PathNode)
|
2018-08-03 07:51:10 +00:00
|
|
|
*/
|
|
|
|
protected double getDistFromStartSq(PathNode n) {
|
2018-08-03 05:06:49 +00:00
|
|
|
int xDiff = n.pos.getX() - start.getX();
|
|
|
|
int yDiff = n.pos.getY() - start.getY();
|
|
|
|
int zDiff = n.pos.getZ() - start.getZ();
|
2018-08-03 07:51:10 +00:00
|
|
|
return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
|
2018-08-03 04:50:45 +00:00
|
|
|
}
|
|
|
|
|
2018-08-03 07:51:10 +00:00
|
|
|
/**
|
|
|
|
* Determines the distance from the specified node to this the node.
|
|
|
|
*
|
|
|
|
* @param n A node
|
|
|
|
* @return The distance
|
|
|
|
*/
|
|
|
|
protected double getDistFromStart(PathNode n) {
|
|
|
|
return Math.sqrt(getDistFromStartSq(n));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Attempts to search the {@link BlockPos} to {@link PathNode} map
|
|
|
|
* for the node mapped to the specified pos. If no node is found,
|
|
|
|
* a new node is created.
|
|
|
|
*
|
|
|
|
* @param pos The pos to lookup
|
|
|
|
* @return The associated node
|
|
|
|
*/
|
2018-08-03 05:06:49 +00:00
|
|
|
protected PathNode getNodeAtPosition(BlockPos pos) {
|
2018-08-03 07:51:10 +00:00
|
|
|
return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
|
2018-08-03 04:50:45 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-08-03 07:51:10 +00:00
|
|
|
public IPath bestPathSoFar() {
|
2018-08-03 04:50:45 +00:00
|
|
|
if (startNode == null || bestSoFar[0] == null) {
|
|
|
|
return null;
|
|
|
|
}
|
|
|
|
return new Path(startNode, bestSoFar[0], goal);
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
2018-08-03 07:51:10 +00:00
|
|
|
public IPath pathToMostRecentNodeConsidered() {
|
2018-08-03 04:50:45 +00:00
|
|
|
return mostRecentConsidered == null ? null : new Path(startNode, mostRecentConsidered, goal);
|
|
|
|
}
|
2018-08-03 05:06:49 +00:00
|
|
|
|
|
|
|
@Override
|
|
|
|
public final boolean isFinished() {
|
|
|
|
return isFinished;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final Goal getGoal() {
|
|
|
|
return goal;
|
|
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
|
|
public final BlockPos getStart() {
|
|
|
|
return start;
|
|
|
|
}
|
2018-08-03 04:50:45 +00:00
|
|
|
}
|