Merge branch 'master' into mega-cancer-rendering
This commit is contained in:
commit
a0c2935580
@ -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/),
|
||||
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:
|
||||
|
||||
- [Features](FEATURES.md)
|
||||
|
2
SETUP.md
2
SETUP.md
@ -65,7 +65,7 @@ $ gradlew build
|
||||
|
||||
![Image](https://i.imgur.com/PE6r9iN.png)
|
||||
|
||||
- Right click on **build** and press **Run**
|
||||
- Double click on **build** to run it
|
||||
|
||||
## Artifacts
|
||||
|
||||
|
@ -298,8 +298,8 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
.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
|
||||
this.printOutputLog(p.getInputStream());
|
||||
this.printOutputLog(p.getErrorStream());
|
||||
this.printOutputLog(p.getInputStream(), System.out);
|
||||
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
|
||||
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(() -> {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
outerr.println(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
|
@ -38,11 +38,24 @@ public interface IPathingBehavior extends IBehavior {
|
||||
* @return The estimated remaining ticks in the current segment.
|
||||
*/
|
||||
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();
|
||||
if (current == null) {
|
||||
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));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -18,6 +18,7 @@
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.behavior.IPathingBehavior;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
@ -100,8 +101,16 @@ public class MixinEntityPlayerSP {
|
||||
)
|
||||
private boolean isKeyDown(KeyBinding keyBinding) {
|
||||
SprintStateEvent event = new SprintStateEvent();
|
||||
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event);
|
||||
return event.getState() == null ? keyBinding.isKeyDown() : event.getState();
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
|
||||
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(
|
||||
|
@ -193,8 +193,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
// and this path doesn't get us all the way there
|
||||
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
|
||||
// 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...");
|
||||
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
|
||||
findPathInNewThread(current.getPath().getDest(), false);
|
||||
|
@ -124,12 +124,13 @@ public final class ChunkPacker {
|
||||
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state) {
|
||||
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
|
||||
// FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) {
|
||||
if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
// We used to do an AABB check here
|
||||
|
@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import baritone.utils.pathing.Favoring;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
@ -37,7 +36,7 @@ import java.util.Optional;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
|
||||
private final Favoring favoring;
|
||||
private final CalculationContext calcContext;
|
||||
@ -55,14 +54,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
|
||||
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];
|
||||
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
|
||||
for (int i = 0; i < bestHeuristicSoFar.length; i++) {
|
||||
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
|
||||
bestSoFar[i] = startNode;
|
||||
}
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
Favoring favored = favoring;
|
||||
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
|
||||
long startTime = System.currentTimeMillis();
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
@ -75,10 +72,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
int numNodes = 0;
|
||||
int numMovementsConsidered = 0;
|
||||
int numEmptyChunk = 0;
|
||||
boolean favoring = !favored.isEmpty();
|
||||
boolean isFavoring = !favoring.isEmpty();
|
||||
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
|
||||
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
|
||||
double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0;
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
|
||||
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)
|
||||
@ -136,21 +133,13 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
|
||||
}
|
||||
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
|
||||
if (favoring) {
|
||||
if (isFavoring) {
|
||||
// see issue #18
|
||||
actionCost *= favored.calculate(hashCode);
|
||||
actionCost *= favoring.calculate(hashCode);
|
||||
}
|
||||
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
|
||||
double tentativeCost = currentNode.cost + actionCost;
|
||||
if (tentativeCost < neighbor.cost) {
|
||||
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;
|
||||
}
|
||||
if (neighbor.cost - tentativeCost > minimumImprovement) {
|
||||
neighbor.previous = currentNode;
|
||||
neighbor.cost = tentativeCost;
|
||||
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
|
||||
@ -159,15 +148,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
} else {
|
||||
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];
|
||||
if (heuristic < bestHeuristicSoFar[i]) {
|
||||
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
|
||||
continue;
|
||||
}
|
||||
if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
|
||||
bestHeuristicSoFar[i] = heuristic;
|
||||
bestSoFar[i] = neighbor;
|
||||
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
|
||||
if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
|
||||
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("PathNode map size: " + mapSize());
|
||||
System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
|
||||
double bestDist = 0;
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
if (bestSoFar[i] == null) {
|
||||
continue;
|
||||
Optional<IPath> result = bestSoFar(true, numNodes);
|
||||
if (result.isPresent()) {
|
||||
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
}
|
||||
double dist = getDistFromStartSq(bestSoFar[i]);
|
||||
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();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -34,7 +34,7 @@ import java.util.Optional;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
|
||||
protected final int startX;
|
||||
protected final int startY;
|
||||
@ -53,7 +53,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
protected PathNode mostRecentConsidered;
|
||||
|
||||
protected PathNode[] bestSoFar;
|
||||
protected final PathNode[] bestSoFar = new PathNode[COEFFICIENTS.length];
|
||||
|
||||
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
|
||||
* 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.
|
||||
*/
|
||||
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) {
|
||||
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));
|
||||
}
|
||||
|
||||
protected int mapSize() {
|
||||
return map.size();
|
||||
@Override
|
||||
public Optional<IPath> bestPathSoFar() {
|
||||
return bestSoFar(false, 0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<IPath> bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder
|
||||
protected Optional<IPath> bestSoFar(boolean logInfo, int numNodes) {
|
||||
if (startNode == null || bestSoFar == null) {
|
||||
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) {
|
||||
continue;
|
||||
}
|
||||
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
|
||||
double dist = getDistFromStartSq(bestSoFar[i]);
|
||||
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
|
||||
// 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();
|
||||
}
|
||||
|
||||
@ -205,4 +233,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
public BetterBlockPos getStart() {
|
||||
return new BetterBlockPos(startX, startY, startZ);
|
||||
}
|
||||
|
||||
protected int mapSize() {
|
||||
return map.size();
|
||||
}
|
||||
}
|
||||
|
@ -114,7 +114,7 @@ public class MovementDiagonal extends Movement {
|
||||
return;
|
||||
}
|
||||
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
|
||||
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
|
||||
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
|
||||
return;
|
||||
}
|
||||
|
@ -187,6 +187,11 @@ public class MovementParkour extends Movement {
|
||||
logDebug("Pausing parkour since hand is active");
|
||||
return state;
|
||||
}
|
||||
if (ctx.playerFeet().y < src.y) {
|
||||
// we have fallen
|
||||
logDebug("sorry");
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
if (dist >= 4) {
|
||||
state.setInput(Input.SPRINT, true);
|
||||
}
|
||||
|
@ -281,6 +281,8 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
return state;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
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
|
||||
|
@ -249,6 +249,8 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
return true;
|
||||
}
|
||||
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.");
|
||||
cancel();
|
||||
return true;
|
||||
@ -377,21 +379,21 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
}
|
||||
|
||||
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
|
||||
if (!new CalculationContext(behavior.baritone).canSprint) {
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
|
||||
return false;
|
||||
}
|
||||
|
||||
// if the movement requested sprinting, then we're done
|
||||
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) {
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
|
||||
if (requested) {
|
||||
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
|
||||
IMovement current = path.movements().get(pathPosition);
|
||||
if (current instanceof MovementDescend) {
|
||||
|
Loading…
Reference in New Issue
Block a user