@@ -377,6 +377,16 @@ public class Settings {
 | 
			
		||||
     */
 | 
			
		||||
    public Setting<Boolean> walkWhileBreaking = new Setting<>(true);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If we are more than 500 movements into the current path, discard the oldest segments, as they are no longer useful
 | 
			
		||||
     */
 | 
			
		||||
    public Setting<Integer> maxPathHistoryLength = new Setting<>(500);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * If the current path is too long, cut off this many movements from the beginning.
 | 
			
		||||
     */
 | 
			
		||||
    public Setting<Integer> pathHistoryCutoffAmount = new Setting<>(100);
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Rescan for the goal once every 5 ticks.
 | 
			
		||||
     * Set to 0 to disable.
 | 
			
		||||
 
 | 
			
		||||
@@ -21,6 +21,7 @@ import baritone.api.Settings;
 | 
			
		||||
import baritone.api.pathing.goals.Goal;
 | 
			
		||||
import baritone.api.pathing.movement.IMovement;
 | 
			
		||||
import baritone.api.utils.BetterBlockPos;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
 | 
			
		||||
import java.util.List;
 | 
			
		||||
 | 
			
		||||
@@ -132,4 +133,33 @@ public interface IPath {
 | 
			
		||||
    default IPath staticCutoff(Goal destination) {
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs a series of checks to ensure that the assembly of the path went as expected.
 | 
			
		||||
     */
 | 
			
		||||
    default void sanityCheck() {
 | 
			
		||||
        List<BetterBlockPos> path = positions();
 | 
			
		||||
        List<IMovement> movements = movements();
 | 
			
		||||
        if (!getSrc().equals(path.get(0))) {
 | 
			
		||||
            throw new IllegalStateException("Start node does not equal first path element");
 | 
			
		||||
        }
 | 
			
		||||
        if (!getDest().equals(path.get(path.size() - 1))) {
 | 
			
		||||
            throw new IllegalStateException("End node does not equal last path element");
 | 
			
		||||
        }
 | 
			
		||||
        if (path.size() != movements.size() + 1) {
 | 
			
		||||
            throw new IllegalStateException("Size of path array is unexpected");
 | 
			
		||||
        }
 | 
			
		||||
        for (int i = 0; i < path.size() - 1; i++) {
 | 
			
		||||
            BlockPos src = path.get(i);
 | 
			
		||||
            BlockPos dest = path.get(i + 1);
 | 
			
		||||
            IMovement movement = movements.get(i);
 | 
			
		||||
            if (!src.equals(movement.getSrc())) {
 | 
			
		||||
                throw new IllegalStateException("Path source is not equal to the movement source");
 | 
			
		||||
            }
 | 
			
		||||
            if (!dest.equals(movement.getDest())) {
 | 
			
		||||
                throw new IllegalStateException("Path destination is not equal to the movement destination");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
 
 | 
			
		||||
@@ -31,9 +31,9 @@ import baritone.api.utils.BetterBlockPos;
 | 
			
		||||
import baritone.api.utils.interfaces.IGoalRenderPos;
 | 
			
		||||
import baritone.pathing.calc.AStarPathFinder;
 | 
			
		||||
import baritone.pathing.calc.AbstractNodeCostSearch;
 | 
			
		||||
import baritone.pathing.calc.CutoffPath;
 | 
			
		||||
import baritone.pathing.movement.CalculationContext;
 | 
			
		||||
import baritone.pathing.movement.MovementHelper;
 | 
			
		||||
import baritone.pathing.path.CutoffPath;
 | 
			
		||||
import baritone.pathing.path.PathExecutor;
 | 
			
		||||
import baritone.utils.BlockBreakHelper;
 | 
			
		||||
import baritone.utils.Helper;
 | 
			
		||||
@@ -156,6 +156,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
 | 
			
		||||
                current.onTick();
 | 
			
		||||
                return;
 | 
			
		||||
            }
 | 
			
		||||
            current = current.trySplice(next);
 | 
			
		||||
            if (next != null && current.getPath().getDest().equals(next.getPath().getDest())) {
 | 
			
		||||
                next = null;
 | 
			
		||||
            }
 | 
			
		||||
            synchronized (pathCalcLock) {
 | 
			
		||||
                if (isPathCalcInProgress) {
 | 
			
		||||
                    // if we aren't calculating right now
 | 
			
		||||
 
 | 
			
		||||
@@ -24,6 +24,7 @@ import baritone.api.pathing.movement.IMovement;
 | 
			
		||||
import baritone.api.utils.BetterBlockPos;
 | 
			
		||||
import baritone.pathing.movement.Movement;
 | 
			
		||||
import baritone.pathing.movement.Moves;
 | 
			
		||||
import baritone.pathing.path.CutoffPath;
 | 
			
		||||
import net.minecraft.client.Minecraft;
 | 
			
		||||
import net.minecraft.util.math.BlockPos;
 | 
			
		||||
import net.minecraft.world.chunk.EmptyChunk;
 | 
			
		||||
@@ -104,32 +105,6 @@ class Path implements IPath {
 | 
			
		||||
        path.addAll(tempPath);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    /**
 | 
			
		||||
     * Performs a series of checks to ensure that the assembly of the path went as expected.
 | 
			
		||||
     */
 | 
			
		||||
    private void sanityCheck() {
 | 
			
		||||
        if (!start.equals(path.get(0))) {
 | 
			
		||||
            throw new IllegalStateException("Start node does not equal first path element");
 | 
			
		||||
        }
 | 
			
		||||
        if (!end.equals(path.get(path.size() - 1))) {
 | 
			
		||||
            throw new IllegalStateException("End node does not equal last path element");
 | 
			
		||||
        }
 | 
			
		||||
        if (path.size() != movements.size() + 1) {
 | 
			
		||||
            throw new IllegalStateException("Size of path array is unexpected");
 | 
			
		||||
        }
 | 
			
		||||
        for (int i = 0; i < path.size() - 1; i++) {
 | 
			
		||||
            BlockPos src = path.get(i);
 | 
			
		||||
            BlockPos dest = path.get(i + 1);
 | 
			
		||||
            Movement movement = movements.get(i);
 | 
			
		||||
            if (!src.equals(movement.getSrc())) {
 | 
			
		||||
                throw new IllegalStateException("Path source is not equal to the movement source");
 | 
			
		||||
            }
 | 
			
		||||
            if (!dest.equals(movement.getDest())) {
 | 
			
		||||
                throw new IllegalStateException("Path destination is not equal to the movement destination");
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private void assembleMovements() {
 | 
			
		||||
        if (path.isEmpty() || !movements.isEmpty()) {
 | 
			
		||||
            throw new IllegalStateException();
 | 
			
		||||
 
 | 
			
		||||
@@ -15,7 +15,7 @@
 | 
			
		||||
 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package baritone.pathing.calc;
 | 
			
		||||
package baritone.pathing.path;
 | 
			
		||||
 | 
			
		||||
import baritone.api.pathing.calc.IPath;
 | 
			
		||||
import baritone.api.pathing.goals.Goal;
 | 
			
		||||
@@ -35,11 +35,16 @@ public class CutoffPath implements IPath {
 | 
			
		||||
 | 
			
		||||
    private final Goal goal;
 | 
			
		||||
 | 
			
		||||
    CutoffPath(IPath prev, int lastPositionToInclude) {
 | 
			
		||||
        path = prev.positions().subList(0, lastPositionToInclude + 1);
 | 
			
		||||
        movements = prev.movements().subList(0, lastPositionToInclude + 1);
 | 
			
		||||
    public CutoffPath(IPath prev, int firstPositionToInclude, int lastPositionToInclude) {
 | 
			
		||||
        path = prev.positions().subList(firstPositionToInclude, lastPositionToInclude + 1);
 | 
			
		||||
        movements = prev.movements().subList(firstPositionToInclude, lastPositionToInclude);
 | 
			
		||||
        numNodes = prev.getNumNodesConsidered();
 | 
			
		||||
        goal = prev.getGoal();
 | 
			
		||||
        sanityCheck();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public CutoffPath(IPath prev, int lastPositionToInclude) {
 | 
			
		||||
        this(prev, 0, lastPositionToInclude);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
@@ -454,6 +454,43 @@ public class PathExecutor implements IPathExecutor, Helper {
 | 
			
		||||
        return pathPosition;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public PathExecutor trySplice(PathExecutor next) {
 | 
			
		||||
        if (next == null) {
 | 
			
		||||
            return cutIfTooLong();
 | 
			
		||||
        }
 | 
			
		||||
        return SplicedPath.trySplice(path, next.path).map(path -> {
 | 
			
		||||
            if (!path.getDest().equals(next.getPath().getDest())) {
 | 
			
		||||
                throw new IllegalStateException();
 | 
			
		||||
            }
 | 
			
		||||
            PathExecutor ret = new PathExecutor(path);
 | 
			
		||||
            ret.pathPosition = pathPosition;
 | 
			
		||||
            ret.currentMovementOriginalCostEstimate = currentMovementOriginalCostEstimate;
 | 
			
		||||
            ret.costEstimateIndex = costEstimateIndex;
 | 
			
		||||
            ret.ticksOnCurrent = ticksOnCurrent;
 | 
			
		||||
            return ret;
 | 
			
		||||
        }).orElse(cutIfTooLong());
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    private PathExecutor cutIfTooLong() {
 | 
			
		||||
        if (pathPosition > Baritone.settings().maxPathHistoryLength.get()) {
 | 
			
		||||
            int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.get();
 | 
			
		||||
            CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1);
 | 
			
		||||
            if (!newPath.getDest().equals(path.getDest())) {
 | 
			
		||||
                throw new IllegalStateException();
 | 
			
		||||
            }
 | 
			
		||||
            logDebug("Discarding earliest segment movements, length cut from " + path.length() + " to " + newPath.length());
 | 
			
		||||
            PathExecutor ret = new PathExecutor(newPath);
 | 
			
		||||
            ret.pathPosition = pathPosition - cutoffAmt;
 | 
			
		||||
            ret.currentMovementOriginalCostEstimate = currentMovementOriginalCostEstimate;
 | 
			
		||||
            if (costEstimateIndex != null) {
 | 
			
		||||
                ret.costEstimateIndex = costEstimateIndex - cutoffAmt;
 | 
			
		||||
            }
 | 
			
		||||
            ret.ticksOnCurrent = ticksOnCurrent;
 | 
			
		||||
            return ret;
 | 
			
		||||
        }
 | 
			
		||||
        return this;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public IPath getPath() {
 | 
			
		||||
        return path;
 | 
			
		||||
 
 | 
			
		||||
							
								
								
									
										88
									
								
								src/main/java/baritone/pathing/path/SplicedPath.java
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										88
									
								
								src/main/java/baritone/pathing/path/SplicedPath.java
									
									
									
									
									
										Normal file
									
								
							@@ -0,0 +1,88 @@
 | 
			
		||||
/*
 | 
			
		||||
 * This file is part of Baritone.
 | 
			
		||||
 *
 | 
			
		||||
 * Baritone is free software: you can redistribute it and/or modify
 | 
			
		||||
 * it under the terms of the GNU Lesser General Public License as published by
 | 
			
		||||
 * the Free Software Foundation, either version 3 of the License, or
 | 
			
		||||
 * (at your option) any later version.
 | 
			
		||||
 *
 | 
			
		||||
 * Baritone is distributed in the hope that it will be useful,
 | 
			
		||||
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
			
		||||
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
			
		||||
 * GNU Lesser General Public License for more details.
 | 
			
		||||
 *
 | 
			
		||||
 * You should have received a copy of the GNU Lesser General Public License
 | 
			
		||||
 * along with Baritone.  If not, see <https://www.gnu.org/licenses/>.
 | 
			
		||||
 */
 | 
			
		||||
 | 
			
		||||
package baritone.pathing.path;
 | 
			
		||||
 | 
			
		||||
import baritone.api.pathing.calc.IPath;
 | 
			
		||||
import baritone.api.pathing.goals.Goal;
 | 
			
		||||
import baritone.api.pathing.movement.IMovement;
 | 
			
		||||
import baritone.api.utils.BetterBlockPos;
 | 
			
		||||
 | 
			
		||||
import java.util.*;
 | 
			
		||||
 | 
			
		||||
public class SplicedPath implements IPath {
 | 
			
		||||
    private final List<BetterBlockPos> path;
 | 
			
		||||
 | 
			
		||||
    private final List<IMovement> movements;
 | 
			
		||||
 | 
			
		||||
    private final int numNodes;
 | 
			
		||||
 | 
			
		||||
    private final Goal goal;
 | 
			
		||||
 | 
			
		||||
    private SplicedPath(List<BetterBlockPos> path, List<IMovement> movements, int numNodesConsidered, Goal goal) {
 | 
			
		||||
        this.path = path;
 | 
			
		||||
        this.movements = movements;
 | 
			
		||||
        this.numNodes = numNodesConsidered;
 | 
			
		||||
        this.goal = goal;
 | 
			
		||||
        sanityCheck();
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public Goal getGoal() {
 | 
			
		||||
        return goal;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<IMovement> movements() {
 | 
			
		||||
        return Collections.unmodifiableList(movements);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public List<BetterBlockPos> positions() {
 | 
			
		||||
        return Collections.unmodifiableList(path);
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    @Override
 | 
			
		||||
    public int getNumNodesConsidered() {
 | 
			
		||||
        return numNodes;
 | 
			
		||||
    }
 | 
			
		||||
 | 
			
		||||
    public static Optional<SplicedPath> trySplice(IPath first, IPath second) {
 | 
			
		||||
        if (second == null || first == null) {
 | 
			
		||||
            return Optional.empty();
 | 
			
		||||
        }
 | 
			
		||||
        if (!Objects.equals(first.getGoal(), second.getGoal())) {
 | 
			
		||||
            return Optional.empty();
 | 
			
		||||
        }
 | 
			
		||||
        if (!first.getDest().equals(second.getSrc())) {
 | 
			
		||||
            return Optional.empty();
 | 
			
		||||
        }
 | 
			
		||||
        HashSet<BetterBlockPos> a = new HashSet<>(first.positions());
 | 
			
		||||
        for (int i = 1; i < second.length(); i++) {
 | 
			
		||||
            if (a.contains(second.positions().get(i))) {
 | 
			
		||||
                return Optional.empty();
 | 
			
		||||
            }
 | 
			
		||||
        }
 | 
			
		||||
        List<BetterBlockPos> positions = new ArrayList<>();
 | 
			
		||||
        List<IMovement> movements = new ArrayList<>();
 | 
			
		||||
        positions.addAll(first.positions());
 | 
			
		||||
        positions.addAll(second.positions().subList(1, second.length()));
 | 
			
		||||
        movements.addAll(first.movements());
 | 
			
		||||
        movements.addAll(second.movements());
 | 
			
		||||
        return Optional.of(new SplicedPath(positions, movements, first.getNumNodesConsidered() + second.getNumNodesConsidered(), first.getGoal()));
 | 
			
		||||
    }
 | 
			
		||||
}
 | 
			
		||||
		Reference in New Issue
	
	Block a user