add a secondary failure cutoff

This commit is contained in:
Leijurv 2018-11-22 09:39:54 -08:00 committed by Brady
parent 5aa78cd478
commit 7632d667c9
5 changed files with 48 additions and 25 deletions

View File

@ -247,14 +247,24 @@ public class Settings {
public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
/**
* Pathing can never take longer than this
* Pathing ends after this amount of time, if a path has been found
*/
public Setting<Long> pathTimeoutMS = new Setting<>(2000L);
public Setting<Long> primaryTimeoutMS = new Setting<>(500L);
/**
* Planning ahead while executing a segment can never take longer than this
* Pathing can never take longer than this, even if that means failing to find any path at all
*/
public Setting<Long> planAheadTimeoutMS = new Setting<>(4000L);
public Setting<Long> failureTimeoutMS = new Setting<>(2000L);
/**
* Planning ahead while executing a segment ends after this amount of time, if a path has been found
*/
public Setting<Long> planAheadPrimaryTimeoutMS = new Setting<>(4000L);
/**
* Planning ahead while executing a segment can never take longer than this, even if that means failing to find any path at all
*/
public Setting<Long> planAheadFailureTimeoutMS = new Setting<>(5000L);
/**
* For debugging, consider nodes much much slower

View File

@ -36,7 +36,7 @@ public interface IPathFinder {
*
* @return The final path
*/
PathCalculationResult calculate(long timeout);
PathCalculationResult calculate(long primaryTimeout, long failureTimeout);
/**
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet

View File

@ -40,7 +40,10 @@ import baritone.utils.PathRenderer;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.*;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.stream.Collectors;
@ -396,11 +399,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller
return;
}
long timeout;
long primaryTimeout;
long failureTimeout;
if (current == null) {
timeout = Baritone.settings().pathTimeoutMS.<Long>get();
primaryTimeout = Baritone.settings().primaryTimeoutMS.get();
failureTimeout = Baritone.settings().failureTimeoutMS.get();
} else {
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
primaryTimeout = Baritone.settings().planAheadPrimaryTimeoutMS.get();
failureTimeout = Baritone.settings().planAheadFailureTimeoutMS.get();
}
CalculationContext context = new CalculationContext(baritone); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context);
@ -410,7 +416,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
logDebug("Starting to search for path from " + start + " to " + goal);
}
PathCalculationResult calcResult = pathfinder.calculate(timeout);
PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout);
Optional<IPath> path = calcResult.getPath();
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> {

View File

@ -49,7 +49,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
}
@Override
protected Optional<IPath> calculate0(long timeout) {
protected Optional<IPath> calculate0(long primaryTimeout, long failureTimeout) {
startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
startNode.cost = 0;
startNode.combinedCost = startNode.estimatedCostToGoal;
@ -68,10 +68,11 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
long startTime = System.nanoTime() / 1000000L;
boolean slowPath = Baritone.settings().slowPath.get();
if (slowPath) {
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms");
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms");
}
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout);
//long lastPrintout = 0;
long primaryTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : primaryTimeout);
long failureTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : failureTimeout);
boolean failing = true;
int numNodes = 0;
int numMovementsConsidered = 0;
int numEmptyChunk = 0;
@ -79,7 +80,14 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) {
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
long now = System.nanoTime() / 1000000L;
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
break;
}
if (failing == bestPathSoFar().isPresent()) {
throw new IllegalStateException();
}
if (slowPath) {
try {
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
@ -166,6 +174,9 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
}
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false;
}
}
}
}

View File

@ -83,13 +83,14 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
cancelRequested = true;
}
public synchronized PathCalculationResult calculate(long timeout) {
@Override
public synchronized PathCalculationResult calculate(long primaryTimeout, long failureTimeout) {
if (isFinished) {
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
}
cancelRequested = false;
try {
IPath path = calculate0(timeout).map(IPath::postProcess).orElse(null);
IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null);
isFinished = true;
if (cancelRequested) {
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
@ -112,7 +113,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
}
}
protected abstract Optional<IPath> calculate0(long timeout);
protected abstract Optional<IPath> calculate0(long primaryTimeout, long failureTimeout);
/**
* Determines the distance squared from the specified node to the start
@ -157,7 +158,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
@Override
public Optional<IPath> bestPathSoFar() {
if (startNode == null || bestSoFar == null || bestSoFar[0] == null) {
if (startNode == null || bestSoFar == null) {
return Optional.empty();
}
for (int i = 0; i < bestSoFar.length; i++) {
@ -165,12 +166,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
continue;
}
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
try {
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
} catch (IllegalStateException ex) {
System.out.println("Unable to construct path to render");
return Optional.empty();
}
}
}
// instead of returning bestSoFar[0], be less misleading