add a secondary failure cutoff
This commit is contained in:
		@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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
 | 
			
		||||
 
 | 
			
		||||
@@ -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 -> {
 | 
			
		||||
 
 | 
			
		||||
@@ -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;
 | 
			
		||||
                            }
 | 
			
		||||
                        }
 | 
			
		||||
                    }
 | 
			
		||||
                }
 | 
			
		||||
 
 | 
			
		||||
@@ -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();
 | 
			
		||||
                }
 | 
			
		||||
                return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        // instead of returning bestSoFar[0], be less misleading
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user