Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
154 changes: 75 additions & 79 deletions src/main/java/baritone/pathing/calc/AStarPathFinder.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,13 +22,14 @@
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Pair;
import baritone.api.utils.SettingsUtil;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves;
import baritone.pathing.movement.Offset;
import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult;

import java.util.Optional;

Expand Down Expand Up @@ -62,7 +63,6 @@ protected Optional<IPath> calculate0(long primaryTimeout, long failureTimeout) {
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode;
}
MutableMoveResult res = new MutableMoveResult();
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.value;
Expand Down Expand Up @@ -100,86 +100,82 @@ protected Optional<IPath> calculate0(long primaryTimeout, long failureTimeout) {
return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext));
}
for (Moves moves : allMoves) {
int newX = currentNode.x + moves.xOffset;
int newZ = currentNode.z + moves.zOffset;
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) {
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
for (Pair<Offset, Double> offsetAndCost : moves.cost(calcContext, currentNode.x, currentNode.y, currentNode.z)) {
int newX = currentNode.x + offsetAndCost.first().x();
int newY = currentNode.y + offsetAndCost.first().y();
int newZ = currentNode.z + offsetAndCost.first().z();
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) {
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
numEmptyChunk++;
continue;
}
continue;
}
if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) {
continue;
}
if (currentNode.y + moves.yOffset > height || currentNode.y + moves.yOffset < minY) {
continue;
}
res.reset();
moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res);
numMovementsConsidered++;
double actionCost = res.cost;
if (actionCost >= ActionCosts.COST_INF) {
continue;
}
if (actionCost <= 0 || Double.isNaN(actionCost)) {
throw new IllegalStateException(String.format(
"%s from %s %s %s calculated implausible cost %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
actionCost));
}
// check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
continue;
}
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
throw new IllegalStateException(String.format(
"%s from %s %s %s ended at x z %s %s instead of %s %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
SettingsUtil.maybeCensor(res.x),
SettingsUtil.maybeCensor(res.z),
SettingsUtil.maybeCensor(newX),
SettingsUtil.maybeCensor(newZ)));
}
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
throw new IllegalStateException(String.format(
"%s from %s %s %s ended at y %s instead of %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
SettingsUtil.maybeCensor(res.y),
SettingsUtil.maybeCensor(currentNode.y + moves.yOffset)));
}
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (isFavoring) {
// see issue #18
actionCost *= favoring.calculate(hashCode);
}
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost;
if (neighbor.cost - tentativeCost > minimumImprovement) {
neighbor.previous = currentNode;
neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
if (neighbor.isOpen()) {
openSet.update(neighbor);
} else {
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
if (!worldBorder.entirelyContains(newX, newZ)) {
continue;
}
if (newY > height || newY < minY) {
continue;
}
numMovementsConsidered++;
double actionCost = offsetAndCost.second();
if (actionCost >= ActionCosts.COST_INF) {
continue;
}
for (int i = 0; i < COEFFICIENTS.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false;
if (actionCost <= 0 || Double.isNaN(actionCost)) {
throw new IllegalStateException(String.format(
"%s from %s %s %s calculated implausible cost %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
actionCost));
}
// check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination
// if (res.x != newX || res.z != newZ) {
// throw new IllegalStateException(String.format(
// "%s from %s %s %s ended at x z %s %s instead of %s %s",
// moves,
// SettingsUtil.maybeCensor(currentNode.x),
// SettingsUtil.maybeCensor(currentNode.y),
// SettingsUtil.maybeCensor(currentNode.z),
// SettingsUtil.maybeCensor(res.x),
// SettingsUtil.maybeCensor(res.z),
// SettingsUtil.maybeCensor(newX),
// SettingsUtil.maybeCensor(newZ)));
// }
// if (res.y != currentNode.y + offsetAndCost.first().y()) {
// throw new IllegalStateException(String.format(
// "%s from %s %s %s ended at y %s instead of %s",
// moves,
// SettingsUtil.maybeCensor(currentNode.x),
// SettingsUtil.maybeCensor(currentNode.y),
// SettingsUtil.maybeCensor(currentNode.z),
// SettingsUtil.maybeCensor(res.y),
// SettingsUtil.maybeCensor(currentNode.y + offsetAndCost.first().y())));
// }
long hashCode = BetterBlockPos.longHash(newX, newY, newZ);
if (isFavoring) {
// see issue #18
actionCost *= favoring.calculate(hashCode);
}
PathNode neighbor = getNodeAtPosition(newX, newY, newZ, hashCode);
double tentativeCost = currentNode.cost + actionCost;
if (neighbor.cost - tentativeCost > minimumImprovement) {
neighbor.previous = currentNode;
neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
if (neighbor.isOpen()) {
openSet.update(neighbor);
} else {
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
}
for (int i = 0; i < COEFFICIENTS.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false;
}
}
}
}
Expand Down
19 changes: 12 additions & 7 deletions src/main/java/baritone/pathing/calc/Path.java
Original file line number Diff line number Diff line change
Expand Up @@ -22,9 +22,11 @@
import baritone.api.pathing.movement.IMovement;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Helper;
import baritone.api.utils.Pair;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.Moves;
import baritone.pathing.movement.Offset;
import baritone.pathing.path.CutoffPath;
import baritone.utils.pathing.PathBase;
import com.google.common.collect.Lists;
Expand Down Expand Up @@ -128,13 +130,16 @@ private boolean assembleMovements() {

private Movement runBackwards(BetterBlockPos src, BetterBlockPos dest, double cost) {
for (Moves moves : Moves.values()) {
Movement move = moves.apply0(context, src);
if (move.getDest().equals(dest)) {
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
// however, taking into account possible favoring that could skew the node cost, we really want the stricter limit of the two
// so we take the minimum of the path node cost difference, and the calculated cost
move.override(Math.min(move.calculateCost(context), cost));
return move;
List<Pair<Offset, Double>> costs = moves.cost(context, src.x, src.y, src.z);
for (Pair<Offset, Double> offset : costs) {
if (src.x + offset.first().x() == dest.x && src.y + offset.first().y() == dest.y && src.z + offset.first().z() == dest.z) {
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
// however, taking into account possible favoring that could skew the node cost, we really want the stricter limit of the two
// so we take the minimum of the path node cost difference, and the calculated cost
Movement move = moves.apply0(context, src, dest);
move.override(Math.min(offset.second(), cost));
return move;
}
}
}
// this is no longer called from bestPathSoFar, now it's in postprocessing
Expand Down
6 changes: 3 additions & 3 deletions src/main/java/baritone/pathing/movement/MovementHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -652,9 +652,9 @@ static void switchToBestToolFor(IPlayerContext ctx, BlockState b, ToolSet ts, bo

static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) {
state.setTarget(new MovementTarget(
RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(pos),
ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()),
RotationUtils.calcRotationFromVec3d(
ctx.playerHead(), VecUtils.getBlockPosCenter(pos), ctx.playerRotations()
).withPitch(ctx.playerRotations().getPitch()),
false
)).setInput(Input.MOVE_FORWARD, true);
}
Expand Down
Loading