better path splicing
This commit is contained in:
parent
399fa003dd
commit
e0f2159276
@ -35,17 +35,22 @@ public class Settings {
|
|||||||
public Setting<Boolean> chuckCaching = new Setting<>(false);
|
public Setting<Boolean> chuckCaching = new Setting<>(false);
|
||||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||||
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
|
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
|
||||||
public Setting<Boolean> renderPath = new Setting<>(true);
|
|
||||||
public Setting<Boolean> chatDebug = new Setting<>(true);
|
public Setting<Boolean> chatDebug = new Setting<>(true);
|
||||||
public Setting<Boolean> chatControl = new Setting<>(true); // probably false in impact
|
public Setting<Boolean> chatControl = new Setting<>(true); // probably false in impact
|
||||||
|
public Setting<Boolean> renderPath = new Setting<>(true);
|
||||||
public Setting<Boolean> fadePath = new Setting<>(false); // give this a better name in the UI, like "better path fps" idk
|
public Setting<Boolean> fadePath = new Setting<>(false); // give this a better name in the UI, like "better path fps" idk
|
||||||
|
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
|
||||||
public Setting<Boolean> slowPath = new Setting<>(false);
|
public Setting<Boolean> slowPath = new Setting<>(false);
|
||||||
|
public Setting<Number> slowPathTimeDelayMS = new Setting<>(100L);
|
||||||
|
public Setting<Number> slowPathTimeoutMS = new Setting<>(40000L);
|
||||||
public Setting<List<Item>> acceptableThrowAwayItems = new Setting<>(Arrays.asList(
|
public Setting<List<Item>> acceptableThrowAwayItems = new Setting<>(Arrays.asList(
|
||||||
Item.getItemFromBlock(Blocks.DIRT),
|
Item.getItemFromBlock(Blocks.DIRT),
|
||||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||||
));
|
));
|
||||||
public Setting<Boolean> renderGoal = new Setting<>(true);
|
public Setting<Boolean> renderGoal = new Setting<>(true);
|
||||||
|
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
|
||||||
|
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9);
|
||||||
|
|
||||||
public final Map<String, Setting<?>> byName;
|
public final Map<String, Setting<?>> byName;
|
||||||
public final List<Setting<?>> allSettings;
|
public final List<Setting<?>> allSettings;
|
||||||
@ -63,8 +68,8 @@ public class Settings {
|
|||||||
this.klass = (Class<T>) value.getClass();
|
this.klass = (Class<T>) value.getClass();
|
||||||
}
|
}
|
||||||
|
|
||||||
public final T get() {
|
public final <K extends T> K get() {
|
||||||
return value;
|
return (K) value;
|
||||||
}
|
}
|
||||||
|
|
||||||
public final String getName() {
|
public final String getName() {
|
||||||
|
@ -93,7 +93,7 @@ public class PathingBehavior extends Behavior {
|
|||||||
// if we aren't calculating right now
|
// if we aren't calculating right now
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
findPathInNewThread(playerFeet(), true);
|
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -126,7 +126,7 @@ public class PathingBehavior extends Behavior {
|
|||||||
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
|
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
|
||||||
// and this path has 5 seconds or less left
|
// and this path has 5 seconds or less left
|
||||||
displayChatMessageRaw("Path almost over. Planning ahead...");
|
displayChatMessageRaw("Path almost over. Planning ahead...");
|
||||||
findPathInNewThread(current.getPath().getDest(), false);
|
findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -160,11 +160,17 @@ public class PathingBehavior extends Behavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void path() {
|
public void path() {
|
||||||
|
synchronized (pathPlanLock) {
|
||||||
|
if (current != null) {
|
||||||
|
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
synchronized (pathCalcLock) {
|
synchronized (pathCalcLock) {
|
||||||
if (isPathCalcInProgress) {
|
if (isPathCalcInProgress) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
findPathInNewThread(playerFeet(), true);
|
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -174,7 +180,7 @@ public class PathingBehavior extends Behavior {
|
|||||||
* @param start
|
* @param start
|
||||||
* @param talkAboutIt
|
* @param talkAboutIt
|
||||||
*/
|
*/
|
||||||
private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt) {
|
private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt, final Optional<IPath> previous) {
|
||||||
synchronized (pathCalcLock) {
|
synchronized (pathCalcLock) {
|
||||||
if (isPathCalcInProgress) {
|
if (isPathCalcInProgress) {
|
||||||
throw new IllegalStateException("Already doing it");
|
throw new IllegalStateException("Already doing it");
|
||||||
@ -186,7 +192,7 @@ public class PathingBehavior extends Behavior {
|
|||||||
displayChatMessageRaw("Starting to search for path from " + start + " to " + goal);
|
displayChatMessageRaw("Starting to search for path from " + start + " to " + goal);
|
||||||
}
|
}
|
||||||
|
|
||||||
findPath(start).map(IPath::cutoffAtLoadedChunks).map(PathExecutor::new).ifPresent(path -> {
|
findPath(start, previous).map(IPath::cutoffAtLoadedChunks).map(PathExecutor::new).ifPresent(path -> {
|
||||||
synchronized (pathPlanLock) {
|
synchronized (pathPlanLock) {
|
||||||
if (current == null) {
|
if (current == null) {
|
||||||
current = path;
|
current = path;
|
||||||
@ -219,13 +225,13 @@ public class PathingBehavior extends Behavior {
|
|||||||
* @param start
|
* @param start
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Optional<IPath> findPath(BlockPos start) {
|
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
|
||||||
if (goal == null) {
|
if (goal == null) {
|
||||||
displayChatMessageRaw("no goal");
|
displayChatMessageRaw("no goal");
|
||||||
return Optional.empty();
|
return Optional.empty();
|
||||||
}
|
}
|
||||||
try {
|
try {
|
||||||
IPathFinder pf = new AStarPathFinder(start, goal);
|
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
|
||||||
return pf.calculate();
|
return pf.calculate();
|
||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
@ -251,6 +257,7 @@ public class PathingBehavior extends Behavior {
|
|||||||
PathExecutor current = this.current; // this should prevent most race conditions?
|
PathExecutor current = this.current; // this should prevent most race conditions?
|
||||||
PathExecutor next = this.next; // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
|
PathExecutor next = this.next; // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
|
||||||
// TODO is this enough, or do we need to acquire a lock here?
|
// TODO is this enough, or do we need to acquire a lock here?
|
||||||
|
// TODO benchmark synchronized in render loop
|
||||||
|
|
||||||
// Render the current path, if there is one
|
// Render the current path, if there is one
|
||||||
if (current != null && current.getPath() != null) {
|
if (current != null && current.getPath() != null) {
|
||||||
|
@ -52,6 +52,8 @@ import net.minecraft.util.EnumFacing;
|
|||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
import net.minecraft.world.chunk.EmptyChunk;
|
import net.minecraft.world.chunk.EmptyChunk;
|
||||||
|
|
||||||
|
import java.util.Collection;
|
||||||
|
import java.util.HashSet;
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
import java.util.Random;
|
import java.util.Random;
|
||||||
|
|
||||||
@ -62,8 +64,11 @@ import java.util.Random;
|
|||||||
*/
|
*/
|
||||||
public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||||
|
|
||||||
public AStarPathFinder(BlockPos start, Goal goal) {
|
private final Optional<HashSet<BetterBlockPos>> favoredPositions;
|
||||||
|
|
||||||
|
public AStarPathFinder(BlockPos start, Goal goal, Optional<Collection<BetterBlockPos>> favoredPositions) {
|
||||||
super(start, goal);
|
super(start, goal);
|
||||||
|
this.favoredPositions = favoredPositions.map(HashSet::new); // <-- okay this is epic
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@ -72,26 +77,30 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
|||||||
startNode.cost = 0;
|
startNode.cost = 0;
|
||||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||||
IOpenSet openSet = new BinaryHeapOpenSet();
|
IOpenSet openSet = new BinaryHeapOpenSet();
|
||||||
startNode.isOpen = true;
|
|
||||||
openSet.insert(startNode);
|
openSet.insert(startNode);
|
||||||
|
startNode.isOpen = true;
|
||||||
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
|
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];
|
||||||
for (int i = 0; i < bestHeuristicSoFar.length; i++) {
|
for (int i = 0; i < bestHeuristicSoFar.length; i++) {
|
||||||
bestHeuristicSoFar[i] = Double.MAX_VALUE;
|
bestHeuristicSoFar[i] = Double.MAX_VALUE;
|
||||||
}
|
}
|
||||||
|
CalculationContext calcContext = new CalculationContext();
|
||||||
|
HashSet<BetterBlockPos> favored = favoredPositions.orElse(null);
|
||||||
currentlyRunning = this;
|
currentlyRunning = this;
|
||||||
long startTime = System.currentTimeMillis();
|
long startTime = System.currentTimeMillis();
|
||||||
boolean slowPath = Baritone.settings().slowPath.get();
|
boolean slowPath = Baritone.settings().slowPath.get();
|
||||||
long timeoutTime = startTime + (slowPath ? 40000 : 4000);
|
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS : Baritone.settings().pathTimeoutMS).<Long>get();
|
||||||
long lastPrintout = 0;
|
long lastPrintout = 0;
|
||||||
int numNodes = 0;
|
int numNodes = 0;
|
||||||
CalculationContext calcContext = new CalculationContext();
|
|
||||||
int numEmptyChunk = 0;
|
int numEmptyChunk = 0;
|
||||||
|
boolean favoring = favoredPositions.isPresent(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||||
boolean cache = Baritone.settings().chuckCaching.get();
|
boolean cache = Baritone.settings().chuckCaching.get();
|
||||||
while (!openSet.isEmpty() && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) {
|
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get();
|
||||||
|
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
|
||||||
|
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.currentTimeMillis() < timeoutTime) {
|
||||||
if (slowPath) {
|
if (slowPath) {
|
||||||
try {
|
try {
|
||||||
Thread.sleep(100);
|
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
|
||||||
} catch (InterruptedException ex) {
|
} catch (InterruptedException ex) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -109,7 +118,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
|||||||
return Optional.of(new Path(startNode, currentNode, numNodes));
|
return Optional.of(new Path(startNode, currentNode, numNodes));
|
||||||
}
|
}
|
||||||
//long constructStart = System.nanoTime();
|
//long constructStart = System.nanoTime();
|
||||||
Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at myPos, in random order
|
Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at currentNodePos, in random order
|
||||||
shuffle(possibleMovements);
|
shuffle(possibleMovements);
|
||||||
//long constructEnd = System.nanoTime();
|
//long constructEnd = System.nanoTime();
|
||||||
//System.out.println(constructEnd - constructStart);
|
//System.out.println(constructEnd - constructStart);
|
||||||
@ -117,16 +126,16 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
|||||||
if (movementToGetToNeighbor == null) {
|
if (movementToGetToNeighbor == null) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest();
|
||||||
boolean isPositionCached = false;
|
boolean isPositionCached = false;
|
||||||
if (cache) {
|
if (cache) {
|
||||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld() != null) {
|
if (CachedWorldProvider.INSTANCE.getCurrentWorld() != null) {
|
||||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld().getBlockType(movementToGetToNeighbor.getDest()) != null) {
|
if (CachedWorldProvider.INSTANCE.getCurrentWorld().getBlockType(dest) != null) {
|
||||||
isPositionCached = true;
|
isPositionCached = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(movementToGetToNeighbor.getDest()) instanceof EmptyChunk) {
|
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(dest) instanceof EmptyChunk) {
|
||||||
numEmptyChunk++;
|
numEmptyChunk++;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -141,7 +150,10 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
|||||||
if (actionCost <= 0) {
|
if (actionCost <= 0) {
|
||||||
throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " calculated implausible cost " + actionCost);
|
throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " calculated implausible cost " + actionCost);
|
||||||
}
|
}
|
||||||
PathNode neighbor = getNodeAtPosition((BetterBlockPos) movementToGetToNeighbor.getDest());
|
if (favoring && favored.contains(dest)) {
|
||||||
|
actionCost *= favorCoeff;
|
||||||
|
}
|
||||||
|
PathNode neighbor = getNodeAtPosition(dest);
|
||||||
double tentativeCost = currentNode.cost + actionCost;
|
double tentativeCost = currentNode.cost + actionCost;
|
||||||
if (tentativeCost < neighbor.cost) {
|
if (tentativeCost < neighbor.cost) {
|
||||||
if (tentativeCost < 0) {
|
if (tentativeCost < 0) {
|
||||||
|
@ -20,6 +20,7 @@ package baritone.bot.pathing.path;
|
|||||||
import baritone.bot.pathing.movement.Movement;
|
import baritone.bot.pathing.movement.Movement;
|
||||||
import baritone.bot.utils.Helper;
|
import baritone.bot.utils.Helper;
|
||||||
import baritone.bot.utils.Utils;
|
import baritone.bot.utils.Utils;
|
||||||
|
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.util.Tuple;
|
import net.minecraft.util.Tuple;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
@ -44,7 +45,7 @@ public interface IPath extends Helper {
|
|||||||
* All positions along the way.
|
* All positions along the way.
|
||||||
* Should begin with the same as getSrc and end with the same as getDest
|
* Should begin with the same as getSrc and end with the same as getDest
|
||||||
*/
|
*/
|
||||||
List<BlockPos> positions();
|
List<BetterBlockPos> positions();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Number of positions in this path
|
* Number of positions in this path
|
||||||
@ -62,7 +63,7 @@ public interface IPath extends Helper {
|
|||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
default Movement subsequentMovement(BlockPos currentPosition) {
|
default Movement subsequentMovement(BlockPos currentPosition) {
|
||||||
List<BlockPos> pos = positions();
|
List<BetterBlockPos> pos = positions();
|
||||||
List<Movement> movements = movements();
|
List<Movement> movements = movements();
|
||||||
for (int i = 0; i < pos.size(); i++) {
|
for (int i = 0; i < pos.size(); i++) {
|
||||||
if (currentPosition.equals(pos.get(i))) {
|
if (currentPosition.equals(pos.get(i))) {
|
||||||
@ -98,15 +99,15 @@ public interface IPath extends Helper {
|
|||||||
/**
|
/**
|
||||||
* Where does this path start
|
* Where does this path start
|
||||||
*/
|
*/
|
||||||
default BlockPos getSrc() {
|
default BetterBlockPos getSrc() {
|
||||||
return positions().get(0);
|
return positions().get(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Where does this path end
|
* Where does this path end
|
||||||
*/
|
*/
|
||||||
default BlockPos getDest() {
|
default BetterBlockPos getDest() {
|
||||||
List<BlockPos> pos = positions();
|
List<BetterBlockPos> pos = positions();
|
||||||
return pos.get(pos.size() - 1);
|
return pos.get(pos.size() - 1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user