Merge branch 'master' into mega-cancer-rendering

This commit is contained in:
Leijurv 2019-02-04 14:52:30 -08:00
commit a0c2935580
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
13 changed files with 113 additions and 77 deletions

View File

@ -28,6 +28,8 @@ Baritone is the pathfinding system used in [Impact](https://impactdevelopment.gi
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/), This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths). the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Have committed at least once a day for the last 6 months =D 🦀
Here are some links to help to get started: Here are some links to help to get started:
- [Features](FEATURES.md) - [Features](FEATURES.md)

View File

@ -65,7 +65,7 @@ $ gradlew build
![Image](https://i.imgur.com/PE6r9iN.png) ![Image](https://i.imgur.com/PE6r9iN.png)
- Right click on **build** and press **Run** - Double click on **build** to run it
## Artifacts ## Artifacts

View File

@ -298,8 +298,8 @@ public class ProguardTask extends BaritoneGradleTask {
.start(); .start();
// We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this // We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
this.printOutputLog(p.getInputStream()); this.printOutputLog(p.getInputStream(), System.out);
this.printOutputLog(p.getErrorStream()); this.printOutputLog(p.getErrorStream(), System.err);
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception // Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
int exitCode = p.waitFor(); int exitCode = p.waitFor();
@ -308,12 +308,12 @@ public class ProguardTask extends BaritoneGradleTask {
} }
} }
private void printOutputLog(InputStream stream) { private void printOutputLog(InputStream stream, PrintStream outerr) {
new Thread(() -> { new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
System.out.println(line); outerr.println(line);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -38,11 +38,24 @@ public interface IPathingBehavior extends IBehavior {
* @return The estimated remaining ticks in the current segment. * @return The estimated remaining ticks in the current segment.
*/ */
default Optional<Double> ticksRemainingInSegment() { default Optional<Double> ticksRemainingInSegment() {
return ticksRemainingInSegment(true);
}
/**
* Returns the estimated remaining ticks in the current pathing
* segment. Given that the return type is an optional, {@link Optional#empty()}
* will be returned in the case that there is no current segment being pathed.
*
* @param includeCurrentMovement whether or not to include the entirety of the cost of the currently executing movement in the total
* @return The estimated remaining ticks in the current segment.
*/
default Optional<Double> ticksRemainingInSegment(boolean includeCurrentMovement) {
IPathExecutor current = getCurrent(); IPathExecutor current = getCurrent();
if (current == null) { if (current == null) {
return Optional.empty(); return Optional.empty();
} }
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); int start = includeCurrentMovement ? current.getPosition() : current.getPosition() + 1;
return Optional.of(current.getPath().ticksRemainingFrom(start));
} }
/** /**

View File

@ -18,6 +18,7 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.behavior.IPathingBehavior; import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.ChatEvent; import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.PlayerUpdateEvent;
@ -100,8 +101,16 @@ public class MixinEntityPlayerSP {
) )
private boolean isKeyDown(KeyBinding keyBinding) { private boolean isKeyDown(KeyBinding keyBinding) {
SprintStateEvent event = new SprintStateEvent(); SprintStateEvent event = new SprintStateEvent();
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
return event.getState() == null ? keyBinding.isKeyDown() : event.getState(); baritone.getGameEventHandler().onPlayerSprintState(event);
if (event.getState() != null) {
return event.getState();
}
if (baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
// hitting control shouldn't make all bots sprint
return false;
}
return keyBinding.isKeyDown();
} }
@Inject( @Inject(

View File

@ -193,8 +193,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// and this path doesn't get us all the way there // and this path doesn't get us all the way there
return; return;
} }
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 7.5 seconds or less left // and this path has 7.5 seconds or less left
// don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up
// if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own
logDebug("Path almost over. Planning ahead..."); logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false); findPathInNewThread(current.getPath().getDest(), false);

View File

@ -124,12 +124,13 @@ public final class ChunkPacker {
private static PathingBlockType getPathingBlockType(IBlockState state) { private static PathingBlockType getPathingBlockType(IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) { if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && !MovementHelper.isFlowing(state)) {
// only water source blocks are plausibly usable, flowing water should be avoid // only water source blocks are plausibly usable, flowing water should be avoid
// FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
return PathingBlockType.WATER; return PathingBlockType.WATER;
} }
if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) { if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
return PathingBlockType.AVOID; return PathingBlockType.AVOID;
} }
// We used to do an AABB check here // We used to do an AABB check here

View File

@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder; import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring; import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
@ -37,7 +36,7 @@ import java.util.Optional;
* *
* @author leijurv * @author leijurv
*/ */
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper { public final class AStarPathFinder extends AbstractNodeCostSearch {
private final Favoring favoring; private final Favoring favoring;
private final CalculationContext calcContext; private final CalculationContext calcContext;
@ -55,14 +54,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
startNode.combinedCost = startNode.estimatedCostToGoal; startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet(); BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode); openSet.insert(startNode);
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];
for (int i = 0; i < bestHeuristicSoFar.length; i++) { for (int i = 0; i < bestHeuristicSoFar.length; i++) {
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal; bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode; bestSoFar[i] = startNode;
} }
MutableMoveResult res = new MutableMoveResult(); MutableMoveResult res = new MutableMoveResult();
Favoring favored = favoring;
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder()); BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.get(); boolean slowPath = Baritone.settings().slowPath.get();
@ -75,10 +72,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int numNodes = 0; int numNodes = 0;
int numMovementsConsidered = 0; int numMovementsConsidered = 0;
int numEmptyChunk = 0; int numEmptyChunk = 0;
boolean favoring = !favored.isEmpty(); boolean isFavoring = !favoring.isEmpty();
int timeCheckInterval = 1 << 6; int timeCheckInterval = 1 << 6;
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get(); double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0;
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) { while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond) if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds) long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
@ -136,21 +133,13 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset)); throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
} }
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z); long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (favoring) { if (isFavoring) {
// see issue #18 // see issue #18
actionCost *= favored.calculate(hashCode); actionCost *= favoring.calculate(hashCode);
} }
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode); PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost; double tentativeCost = currentNode.cost + actionCost;
if (tentativeCost < neighbor.cost) { if (neighbor.cost - tentativeCost > minimumImprovement) {
double improvementBy = neighbor.cost - tentativeCost;
// there are floating point errors caused by random combinations of traverse and diagonal over a flat area
// that means that sometimes there's a cost improvement of like 10 ^ -16
// it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
if (improvementBy < 0.01 && minimumImprovementRepropagation) {
// who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
continue;
}
neighbor.previous = currentNode; neighbor.previous = currentNode;
neighbor.cost = tentativeCost; neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
@ -159,15 +148,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} else { } else {
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
} }
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < COEFFICIENTS.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (heuristic < bestHeuristicSoFar[i]) { if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
continue;
}
bestHeuristicSoFar[i] = heuristic; bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor; bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) { if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false; failing = false;
} }
} }
@ -182,28 +168,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
System.out.println("Open set size: " + openSet.size()); System.out.println("Open set size: " + openSet.size());
System.out.println("PathNode map size: " + mapSize()); System.out.println("PathNode map size: " + mapSize());
System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second"); System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
double bestDist = 0; Optional<IPath> result = bestSoFar(true, numNodes);
for (int i = 0; i < bestSoFar.length; i++) { if (result.isPresent()) {
if (bestSoFar[i] == null) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
continue;
} }
double dist = getDistFromStartSq(bestSoFar[i]); return result;
if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, calcContext));
}
}
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
logDebug("No path found =(");
return Optional.empty();
} }
} }

View File

@ -34,7 +34,7 @@ import java.util.Optional;
* *
* @author leijurv * @author leijurv
*/ */
public abstract class AbstractNodeCostSearch implements IPathFinder { public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
protected final int startX; protected final int startX;
protected final int startY; protected final int startY;
@ -53,7 +53,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
protected PathNode mostRecentConsidered; protected PathNode mostRecentConsidered;
protected PathNode[] bestSoFar; protected final PathNode[] bestSoFar = new PathNode[COEFFICIENTS.length];
private volatile boolean isFinished; private volatile boolean isFinished;
@ -63,13 +63,23 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so * This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts). * long it was easier as a Google Doc (because I could insert charts).
* *
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a> * @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">here</a>
*/ */
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10};
/** /**
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering. * If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
*/ */
protected final static double MIN_DIST_PATH = 5; protected static final double MIN_DIST_PATH = 5;
/**
* there are floating point errors caused by random combinations of traverse and diagonal over a flat area
* that means that sometimes there's a cost improvement of like 10 ^ -16
* it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
* <p>
* who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
*/
protected static final double MIN_IMPROVEMENT = 0.01;
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) { AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
this.startX = startX; this.startX = startX;
@ -170,25 +180,43 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context)); return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
} }
protected int mapSize() { @Override
return map.size(); public Optional<IPath> bestPathSoFar() {
return bestSoFar(false, 0);
} }
@Override protected Optional<IPath> bestSoFar(boolean logInfo, int numNodes) {
public Optional<IPath> bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder
if (startNode == null || bestSoFar == null) { if (startNode == null || bestSoFar == null) {
return Optional.empty(); return Optional.empty();
} }
for (int i = 0; i < bestSoFar.length; i++) { double bestDist = 0;
for (int i = 0; i < COEFFICIENTS.length; i++) {
if (bestSoFar[i] == null) { if (bestSoFar[i] == null) {
continue; continue;
} }
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared double dist = getDistFromStartSq(bestSoFar[i]);
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context)); if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
if (logInfo) {
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
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));
} }
} }
// instead of returning bestSoFar[0], be less misleading // instead of returning bestSoFar[0], be less misleading
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen // if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
if (logInfo) {
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
logDebug("No path found =(");
}
return Optional.empty(); return Optional.empty();
} }
@ -205,4 +233,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public BetterBlockPos getStart() { public BetterBlockPos getStart() {
return new BetterBlockPos(startX, startY, startZ); return new BetterBlockPos(startX, startY, startZ);
} }
protected int mapSize() {
return map.size();
}
} }

View File

@ -114,7 +114,7 @@ public class MovementDiagonal extends Movement {
return; return;
} }
IBlockState pb3 = context.get(destX, y + 1, z); IBlockState pb3 = context.get(destX, y + 1, z);
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) { if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3.getBlock()))) {
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction // at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
return; return;
} }
@ -123,7 +123,7 @@ public class MovementDiagonal extends Movement {
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible // and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
return; return;
} }
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) { if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1.getBlock()))) {
// and now that option B is fully calculated, see if we can edge around that way // and now that option B is fully calculated, see if we can edge around that way
return; return;
} }

View File

@ -187,6 +187,11 @@ public class MovementParkour extends Movement {
logDebug("Pausing parkour since hand is active"); logDebug("Pausing parkour since hand is active");
return state; return state;
} }
if (ctx.playerFeet().y < src.y) {
// we have fallen
logDebug("sorry");
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (dist >= 4) { if (dist >= 4) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }

View File

@ -281,6 +281,8 @@ public class MovementTraverse extends Movement {
} }
return state; return state;
} }
default:
break;
} }
if (whereAmI.equals(dest)) { if (whereAmI.equals(dest)) {
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of // If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of

View File

@ -249,6 +249,8 @@ public class PathExecutor implements IPathExecutor, Helper {
return true; return true;
} }
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) { if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) {
// don't do this if the movement was calculated while loaded
// that means that this isn't a cache error, it's just part of the path interfering with a later part
logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling."); logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling.");
cancel(); cancel();
return true; return true;
@ -377,21 +379,21 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
private boolean shouldSprintNextTick() { private boolean shouldSprintNextTick() {
boolean requested = behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT);
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint // first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint) { if (!new CalculationContext(behavior.baritone).canSprint) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return false; return false;
} }
// if the movement requested sprinting, then we're done // if the movement requested sprinting, then we're done
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) { if (requested) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return true; return true;
} }
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it // however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
IMovement current = path.movements().get(pathPosition); IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend) { if (current instanceof MovementDescend) {