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/),
|
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)
|
||||||
|
2
SETUP.md
2
SETUP.md
@ -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
|
||||||
|
|
||||||
|
@ -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();
|
||||||
|
@ -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));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -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(
|
||||||
|
@ -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);
|
||||||
|
@ -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
|
||||||
|
@ -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]);
|
|
||||||
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");
|
return result;
|
||||||
logDebug("No path found =(");
|
|
||||||
return Optional.empty();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -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();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -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;
|
||||||
}
|
}
|
||||||
|
@ -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);
|
||||||
}
|
}
|
||||||
|
@ -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
|
||||||
|
@ -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) {
|
||||||
|
Loading…
Reference in New Issue
Block a user