planning ahead

This commit is contained in:
Leijurv 2018-08-13 12:35:44 -07:00
parent 88c81a9635
commit 85fdc2df34
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
3 changed files with 114 additions and 23 deletions

View File

@ -49,16 +49,79 @@ public class PathingBehavior extends Behavior {
private Goal goal;
private volatile boolean isPathCalcInProgress;
private final Object pathCalcLock = new Object();
private final Object pathPlanLock = new Object();
@Override
public void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT || current == null) {
return;
}
current.onTick(event);
if (current.failed() || current.finished()) {
current = null;
if (!goal.isInGoal(playerFeet()))
findPathInNewThread(playerFeet(), true);
boolean safe = current.onTick(event);
synchronized (pathPlanLock) {
if (current.failed() || current.finished()) {
current = null;
if (next != null && !next.getPath().positions().contains(playerFeet())) {
// if the current path failed, we may not actually be on the next one, so make sure
displayChatMessageRaw("Discarding next path as it does not contain current position");
// for example if we had a nicely planned ahead path that starts where current ends
// that's all fine and good
// but if we fail in the middle of current
// we're nowhere close to our planned ahead path
// so need to discard it sadly.
next = null;
}
if (next != null) {
current = next;
next = null;
return;
}
if (goal.isInGoal(playerFeet())) {
return;
}
// at this point, current just ended, but we aren't in the goal and have no plan for the future
synchronized (pathCalcLock) {
if (isPathCalcInProgress) {
// if we aren't calculating right now
return;
}
findPathInNewThread(playerFeet(), true);
}
return;
}
// at this point, we know current is in progress
if (safe) {
// a movement just ended
if (next != null) {
if (next.getPath().positions().contains(playerFeet())) {
// jump directly onto the next path
current = next;
next = null;
return;
}
}
}
synchronized (pathCalcLock) {
if (isPathCalcInProgress) {
// if we aren't calculating right now
return;
}
if (next != null) {
// and we have no plan for what to do next
return;
}
if (goal.isInGoal(current.getPath().getDest())) {
// and this path dosen't get us all the way there
return;
}
if (current.getPath().ticksRemainingFrom(current.getPosition()) < 100) {
// and this path has 5 seconds or less left
displayChatMessageRaw("Path almost over; planning ahead");
findPathInNewThread(current.getPath().getDest(), true);
}
}
}
}
@ -136,12 +199,30 @@ public class PathingBehavior extends Behavior {
* @param talkAboutIt
*/
public void findPathInNewThread(final BlockPos start, final boolean talkAboutIt) {
synchronized (pathCalcLock) {
if (isPathCalcInProgress) {
throw new IllegalStateException("Already doing it");
}
isPathCalcInProgress = true;
}
new Thread(() -> {
if (talkAboutIt) {
displayChatMessageRaw("Starting to search for path from " + start + " to " + goal);
}
findPath(start).map(PathExecutor::new).ifPresent(path -> current = path);
findPath(start).map(PathExecutor::new).ifPresent(path -> {
synchronized (pathPlanLock) {
if (current == null) {
current = path;
} else {
if (next == null) {
next = path;
} else {
throw new IllegalStateException("I have no idea what to do with this path");
}
}
}
});
/*
isThereAnythingInProgress = false;
if (!currentPath.goal.isInGoal(currentPath.end)) {
@ -156,6 +237,9 @@ public class PathingBehavior extends Behavior {
if (talkAboutIt && current != null && current.getPath() != null) {
displayChatMessageRaw("Finished finding a path from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
}
synchronized (pathCalcLock) {
isPathCalcInProgress = false;
}
}).start();
}

View File

@ -17,7 +17,6 @@
package baritone.bot.pathing.path;
import baritone.bot.pathing.movement.CalculationContext;
import baritone.bot.pathing.movement.Movement;
import baritone.bot.utils.Utils;
import net.minecraft.util.Tuple;
@ -108,11 +107,11 @@ public interface IPath {
return pos.get(pos.size() - 1);
}
default double ticksRemaining(int pathPosition) {
default double ticksRemainingFrom(int pathPosition) {
double sum = 0;
CalculationContext ctx = new CalculationContext();
//this is fast because we aren't requesting recalculation, it's just cached
for (int i = pathPosition; i < movements().size(); i++) {
sum += movements().get(i).getCost(ctx);
sum += movements().get(i).getCost(null);
}
return sum;
}

View File

@ -18,12 +18,12 @@
package baritone.bot.pathing.path;
import baritone.bot.Baritone;
import baritone.bot.behavior.Behavior;
import baritone.bot.event.events.TickEvent;
import baritone.bot.pathing.movement.ActionCosts;
import baritone.bot.pathing.movement.Movement;
import baritone.bot.pathing.movement.MovementState;
import baritone.bot.utils.BlockStateInterface;
import baritone.bot.utils.Helper;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.init.Blocks;
import net.minecraft.util.Tuple;
@ -41,7 +41,7 @@ import static baritone.bot.pathing.movement.MovementState.MovementStatus.*;
*
* @author leijurv
*/
public class PathExecutor extends Behavior {
public class PathExecutor implements Helper {
private static final double MAX_DIST_FROM_PATH = 2;
private static final double MAX_TICKS_AWAY = 200; // ten seconds
private final IPath path;
@ -61,15 +61,21 @@ public class PathExecutor extends Behavior {
this.pathPosition = 0;
}
@Override
public void onTick(TickEvent event) {
/**
* Tick this executor
*
* @param event
* @return True if a movement just finished (and the player is therefore in a "stable" state, like,
* not sneaking out over lava), false otherwise
*/
public boolean onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
return;
throw new IllegalStateException();
}
if (pathPosition >= path.length()) {
//stop bugging me, I'm done
//TODO Baritone.INSTANCE.behaviors.remove(this)
return;
return true;
}
BlockPos whereShouldIBe = path.positions().get(pathPosition);
EntityPlayerSP thePlayer = mc.player;
@ -77,7 +83,7 @@ public class PathExecutor extends Behavior {
if (pathPosition == path.length() - 1) {
displayChatMessageRaw("On last position, ending this path.");
pathPosition++;
return;
return true;
}
if (!whereShouldIBe.equals(whereAmI)) {
System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
@ -86,7 +92,7 @@ public class PathExecutor extends Behavior {
if (whereAmI.equals(path.positions().get(i))) {
displayChatMessageRaw("Skipping back " + (pathPosition - i) + " steps, to " + i);
pathPosition = Math.max(i - 1, 0); // previous step might not actually be done
return;
return false;
}
}
for (int i = pathPosition + 2; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
@ -95,7 +101,7 @@ public class PathExecutor extends Behavior {
displayChatMessageRaw("Skipping forward " + (i - pathPosition) + " steps, to " + i);
}
pathPosition = i - 1;
return;
return false;
}
}
}
@ -111,7 +117,7 @@ public class PathExecutor extends Behavior {
pathPosition = path.length() + 3;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
failed = true;
return;
return false;
}
} else {
ticksAway = 0;
@ -194,7 +200,7 @@ public class PathExecutor extends Behavior {
pathPosition = path.length() + 3;
failed = true;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
return;
return true;
}
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
costEstimateIndex = pathPosition;
@ -206,7 +212,7 @@ public class PathExecutor extends Behavior {
pathPosition = path.length() + 3;
failed = true;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
return;
return true;
}
if (movementStatus == SUCCESS) {
System.out.println("Movement done, next path");
@ -214,6 +220,7 @@ public class PathExecutor extends Behavior {
ticksOnCurrent = 0;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
onTick(event);
return true;
} else {
ticksOnCurrent++;
if (ticksOnCurrent > currentMovementInitialCostEstimate + 100) {
@ -226,9 +233,10 @@ public class PathExecutor extends Behavior {
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
pathPosition = path.length() + 3;
failed = true;
return;
return true;
}
}
return false; // movement is in progress
}
public int getPosition() {