diff --git a/src/main/java/baritone/bot/behavior/PathExecution.java b/src/main/java/baritone/bot/behavior/PathExecution.java index 204f4aa7..08a9f011 100644 --- a/src/main/java/baritone/bot/behavior/PathExecution.java +++ b/src/main/java/baritone/bot/behavior/PathExecution.java @@ -1,34 +1,146 @@ package baritone.bot.behavior; import baritone.bot.pathing.calc.IPath; -import baritone.bot.utils.Helper; +import baritone.bot.pathing.movement.ActionCosts; +import baritone.bot.pathing.movement.Movement; +import baritone.bot.utils.BlockStateInterface; +import baritone.bot.utils.ToolSet; +import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.init.Blocks; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; /** - * @author Brady - * @since 8/1/2018 5:38 PM + * Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching + * or cutting (jumping onto the next path if it starts with a backtrack of this path's ending) + * + * @author leijurv */ public class PathExecution extends Behavior { private static final double MAX_DIST_FROM_PATH = 2; + private static final double MAX_TICKS_AWAY = 200; // ten seconds private final IPath path; + private int pathPosition; + private int ticksAway; + private int ticksOnCurrent; + private boolean failed; public PathExecution(IPath path) { this.path = path; + this.pathPosition = 0; } public void onTick() { - BlockPos playerFeet = playerFeet(); - // TODO copy logic from Path in resources - if (path.isInPath(playerFeet)) { - // TODO the old Path used to keep track of the index in the path - // and only increment it when the movement said it was done, not when it detected that the player feet had - // moved into the next position + if (pathPosition >= path.length()) { + //stop bugging me, I'm done + //TODO Baritone.INSTANCE.behaviors.remove(this) + return; + } + BlockPos whereShouldIBe = path.positions().get(pathPosition); + EntityPlayerSP thePlayer = mc.player; + BlockPos whereAmI = playerFeet(); + if (pathPosition == path.length() - 1) { + System.out.println("On last path position -- done!"); + return; + } + if (!whereShouldIBe.equals(whereAmI)) { + System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI); + if (!Blocks.AIR.equals(BlockStateInterface.getBlock(whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip + for (int i = 0; i < pathPosition - 2 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks + if (whereAmI.equals(path.positions().get(i))) { + System.out.println("Skipping back " + (pathPosition - i) + " steps, to " + i); + pathPosition = Math.max(i - 1, 0); // previous step might not actually be done + return; + } + } + 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) + if (whereAmI.equals(path.positions().get(i))) { + System.out.println("Skipping forward " + (i - pathPosition) + " steps, to " + i); + pathPosition = i - 1; + return; + } + } + } + } + Tuple status = path.closestPathPos(thePlayer.posX, thePlayer.posY, thePlayer.posZ); + double distanceFromPath = status.getFirst(); + if (distanceFromPath > MAX_DIST_FROM_PATH) { + ticksAway++; + System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + distanceFromPath + ". Threshold: " + MAX_DIST_FROM_PATH); + if (ticksAway > MAX_TICKS_AWAY) { + System.out.println("Too far away from path for too long, cancelling path"); + System.out.println("Too many ticks"); + pathPosition = path.length() + 3; + failed = true; + return; + } } else { - Tuple closest = path.closestPathPos(mc.player.posX, mc.player.posY, mc.player.posZ); - if (closest.getFirst() > MAX_DIST_FROM_PATH) { - // TODO how to indicate failure? Exception? + ticksAway = 0; + } + //this commented block is literally cursed. + /*Out.log(actions.get(pathPosition)); + if (pathPosition < actions.size() - 1) {//if there are two ActionBridges in a row and they are at right angles, walk diagonally. This makes it so you walk at 45 degrees along a zigzag path instead of doing inefficient zigging and zagging + if ((actions.get(pathPosition) instanceof ActionBridge) && (actions.get(pathPosition + 1) instanceof ActionBridge)) { + ActionBridge curr = (ActionBridge) actions.get(pathPosition); + ActionBridge next = (ActionBridge) actions.get(pathPosition + 1); + if (curr.dx() != next.dx() || curr.dz() != next.dz()) {//two movement are not parallel, so this is a right angle + if (curr.amIGood() && next.amIGood()) {//nothing in the way + BlockPos cornerToCut1 = new BlockPos(next.to.getX() - next.from.getX() + curr.from.getX(), next.to.getY(), next.to.getZ() - next.from.getZ() + curr.from.getZ()); + BlockPos cornerToCut2 = cornerToCut1.up(); + //Block corner1 = Baritone.get(cornerToCut1).getBlock(); + //Block corner2 = Baritone.get(cornerToCut2).getBlock(); + //Out.gui("Cutting conner " + cornerToCut1 + " " + corner1, Out.Mode.Debug); + if (!Action.avoidWalkingInto(cornerToCut1) && !Action.avoidWalkingInto(cornerToCut2)) { + double x = (next.from.getX() + next.to.getX() + 1.0D) * 0.5D; + double z = (next.from.getZ() + next.to.getZ() + 1.0D) * 0.5D; + MovementManager.clearMovement(); + if (!MovementManager.forward && curr.oneInTen != null && curr.oneInTen) { + MovementManager.clearMovement(); + MovementManager.forward = LookManager.lookAtCoords(x, 0, z, false); + } else { + MovementManager.moveTowardsCoords(x, 0, z); + } + if (MovementManager.forward && !MovementManager.backward) { + thePlayer.setSprinting(true); + } + return false; + } + } + } + } + }*/ + Movement movement = path.movements().get(pathPosition); + if (movement.calculateCost(new ToolSet()) >= ActionCosts.COST_INF) { + System.out.println("Something has changed in the world and this movement has become impossible. Cancelling."); + pathPosition = path.length() + 3; + failed = true; + return; + } + movement.onTick(); + if (movement.isFinished()) { + System.out.println("Movement done, next path"); + pathPosition++; + ticksOnCurrent = 0; + } else { + ticksOnCurrent++; + if (ticksOnCurrent > movement.calculateCost(new ToolSet()) + 100) { + System.out.println("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + movement.calculateCost(new ToolSet()) + "). Cancelling."); + pathPosition = path.length() + 3; + failed = true; + return; } } } + + public IPath getPath() { + return path; + } + + public boolean failed() { + return failed; + } + + public boolean finished() { + return pathPosition >= path.length(); + } } diff --git a/src/main/java/baritone/bot/pathing/calc/IPath.java b/src/main/java/baritone/bot/pathing/calc/IPath.java index 4d745d5e..91354b51 100644 --- a/src/main/java/baritone/bot/pathing/calc/IPath.java +++ b/src/main/java/baritone/bot/pathing/calc/IPath.java @@ -27,6 +27,15 @@ public interface IPath { */ List positions(); + /** + * Number of positions in this path + * + * @return Number of positions in this path + */ + default int length() { + return positions().size(); + } + /** * What's the next step *