From a690e1eca4b46b896e532b75016e95c4e314fe19 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 14 Oct 2024 00:46:27 -0400 Subject: [PATCH 1/3] prepend feet to the path if start is adjacent to feet --- .../java/baritone/behavior/PathingBehavior.java | 13 ++++++++++--- .../java/baritone/pathing/calc/AStarPathFinder.java | 6 +++--- .../pathing/calc/AbstractNodeCostSearch.java | 8 +++++--- src/main/java/baritone/pathing/calc/Path.java | 12 ++++++++++-- 4 files changed, 28 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d3bd62d6b..d8df46681 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -265,7 +265,7 @@ public boolean secretInternalSetGoalAndPath(PathingCommand command) { if (goal == null) { return false; } - if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) { + if (goal.isInGoal(ctx.playerFeet())) { return false; } synchronized (pathPlanLock) { @@ -553,7 +553,7 @@ private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt }); } - private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) { + private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) { Goal transformed = goal; if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) { BlockPos pos = ((IGoalRenderPos) goal).getGoalPos(); @@ -562,7 +562,14 @@ private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal } } Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous, context); - return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context); + BetterBlockPos feet = ctx.playerFeet(); + var realStart = new BetterBlockPos(start); + var sub = feet.subtract(realStart); + if (feet.getY() == realStart.getY() && Math.abs(sub.getX()) <= 1 && Math.abs(sub.getZ()) <= 1) { + realStart = feet; + } + return new AStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context); + } @Override diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java index b37b598ff..0537eac5f 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java @@ -41,8 +41,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch { private final Favoring favoring; private final CalculationContext calcContext; - public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { - super(startX, startY, startZ, goal, context); + public AStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { + super(realStart, startX, startY, startZ, goal, context); this.favoring = favoring; this.calcContext = context; } @@ -96,7 +96,7 @@ protected Optional calculate0(long primaryTimeout, long failureTimeout) { numNodes++; if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered"); - return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext)); + return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext)); } for (Moves moves : allMoves) { int newX = currentNode.x + moves.xOffset; diff --git a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java index d20b519dc..0bfb6ac3f 100644 --- a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java @@ -36,6 +36,7 @@ */ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper { + protected final BetterBlockPos realStart; protected final int startX; protected final int startY; protected final int startZ; @@ -81,7 +82,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper { */ protected static final double MIN_IMPROVEMENT = 0.01; - AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) { + AbstractNodeCostSearch(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, CalculationContext context) { + this.realStart = realStart; this.startX = startX; this.startY = startY; this.startZ = startZ; @@ -177,7 +179,7 @@ protected PathNode getNodeAtPosition(int x, int y, int z, long hashCode) { @Override public Optional pathToMostRecentNodeConsidered() { - return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context)); + return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(realStart, startNode, node, 0, goal, context)); } @Override @@ -208,7 +210,7 @@ protected Optional bestSoFar(boolean logInfo, int numNodes) { System.out.println("Path goes for " + Math.sqrt(dist) + " blocks"); logDebug("A* cost coefficient " + COEFFICIENTS[i]); } - return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context)); + return Optional.of(new Path(realStart, startNode, bestSoFar[i], numNodes, goal, context)); } } // instead of returning bestSoFar[0], be less misleading diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index f7bfbaa24..0e176d5e1 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -68,8 +68,9 @@ class Path extends PathBase { private volatile boolean verified; - Path(PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { - this.start = new BetterBlockPos(start.x, start.y, start.z); + Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { + this.start = realStart; + var startNodePos = new BetterBlockPos(start.x, start.y, start.z); this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.movements = new ArrayList<>(); @@ -85,6 +86,13 @@ class Path extends PathBase { tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } + if (!realStart.equals(startNodePos)) { + PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); + fakeNode.cost = 0; + tempNodes.addFirst(fakeNode); + tempPath.addFirst(realStart); + } + // Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is // inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able // to performantly do that conversion since it knows the length. From 1e2ae34dbe452a1eebc12019ae632b2279210cad Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 15 Oct 2024 18:25:42 -0400 Subject: [PATCH 2/3] crucial performance optimization --- src/main/java/baritone/pathing/calc/Path.java | 25 ++++++++----------- 1 file changed, 11 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index 0e176d5e1..b749dff64 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -27,6 +27,7 @@ import baritone.pathing.movement.Moves; import baritone.pathing.path.CutoffPath; import baritone.utils.pathing.PathBase; +import com.google.common.collect.Lists; import java.util.ArrayList; import java.util.Collections; @@ -77,27 +78,23 @@ class Path extends PathBase { this.goal = goal; this.context = context; PathNode current = end; - LinkedList tempPath = new LinkedList<>(); - LinkedList tempNodes = new LinkedList<>(); - // Repeatedly inserting to the beginning of an arraylist is O(n^2) - // Instead, do it into a linked list, then convert at the end + List tempPath = new ArrayList<>(); + List tempNodes = new ArrayList<>(); while (current != null) { - tempNodes.addFirst(current); - tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z)); + tempNodes.add(current); + tempPath.add(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } + // If the position the player is at is different from the position we told A* to start from if (!realStart.equals(startNodePos)) { PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); fakeNode.cost = 0; - tempNodes.addFirst(fakeNode); - tempPath.addFirst(realStart); + tempNodes.add(fakeNode); + tempPath.add(realStart); } - - // Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is - // inserting into a LinkedList keeps track of length, then when we addall (which calls .toArray) it's able - // to performantly do that conversion since it knows the length. - this.path = new ArrayList<>(tempPath); - this.nodes = new ArrayList<>(tempNodes); + // Nodes are traversed last to first so we need to reverse the list + this.path = Lists.reverse(tempPath); + this.nodes = Lists.reverse(tempNodes); } @Override From d644c5b75401f6b7326caa99034e3363c24c8ae0 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 15 Oct 2024 18:56:46 -0400 Subject: [PATCH 3/3] a bit more elegant --- src/main/java/baritone/pathing/calc/Path.java | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index b749dff64..0c5dda00f 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -71,12 +71,21 @@ class Path extends PathBase { Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) { this.start = realStart; - var startNodePos = new BetterBlockPos(start.x, start.y, start.z); this.end = new BetterBlockPos(end.x, end.y, end.z); this.numNodes = numNodes; this.movements = new ArrayList<>(); this.goal = goal; this.context = context; + + // If the position the player is at is different from the position we told A* to start from + // see PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519 + var startNodePos = new BetterBlockPos(start.x, start.y, start.z); + if (!realStart.equals(startNodePos)) { + PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); + fakeNode.cost = 0; + start.previous = fakeNode; + } + PathNode current = end; List tempPath = new ArrayList<>(); List tempNodes = new ArrayList<>(); @@ -85,13 +94,6 @@ class Path extends PathBase { tempPath.add(new BetterBlockPos(current.x, current.y, current.z)); current = current.previous; } - // If the position the player is at is different from the position we told A* to start from - if (!realStart.equals(startNodePos)) { - PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal); - fakeNode.cost = 0; - tempNodes.add(fakeNode); - tempPath.add(realStart); - } // Nodes are traversed last to first so we need to reverse the list this.path = Lists.reverse(tempPath); this.nodes = Lists.reverse(tempNodes);