diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index d8df46681..df2f0cfbc 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -28,12 +28,11 @@ import baritone.api.utils.Helper; import baritone.api.utils.PathCalculationResult; import baritone.api.utils.interfaces.IGoalRenderPos; -import baritone.pathing.calc.AStarPathFinder; +import baritone.pathing.calc.ThetaStarPathFinder; import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.PathExecutor; -import baritone.process.ElytraProcess; import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.pathing.Favoring; @@ -568,7 +567,7 @@ private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath if (feet.getY() == realStart.getY() && Math.abs(sub.getX()) <= 1 && Math.abs(sub.getZ()) <= 1) { realStart = feet; } - return new AStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context); + return new ThetaStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context); } diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index eba408058..d05ca0ac9 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -19,6 +19,7 @@ import baritone.api.pathing.calc.IPath; import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.IMovement; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Helper; @@ -31,7 +32,6 @@ import java.util.ArrayList; import java.util.Collections; -import java.util.LinkedList; import java.util.List; /** @@ -128,12 +128,13 @@ private boolean assembleMovements() { private Movement runBackwards(BetterBlockPos src, BetterBlockPos dest, double cost) { for (Moves moves : Moves.values()) { - Movement move = moves.apply0(context, src); - if (move.getDest().equals(dest)) { + double newCost = moves.cost(context, src.x, src.y, src.z, dest.x, dest.y, dest.z); + if (newCost != ActionCosts.COST_INF) { // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution // however, taking into account possible favoring that could skew the node cost, we really want the stricter limit of the two // so we take the minimum of the path node cost difference, and the calculated cost - move.override(Math.min(move.calculateCost(context), cost)); + Movement move = moves.apply0(context, src, dest); + move.override(Math.min(newCost, cost)); return move; } } diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/ThetaStarPathFinder.java similarity index 53% rename from src/main/java/baritone/pathing/calc/AStarPathFinder.java rename to src/main/java/baritone/pathing/calc/ThetaStarPathFinder.java index 1c58cbf20..2103b6f5a 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/ThetaStarPathFinder.java @@ -22,27 +22,30 @@ import baritone.api.pathing.goals.Goal; import baritone.api.pathing.movement.ActionCosts; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Pair; import baritone.api.utils.SettingsUtil; import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.Moves; +import baritone.pathing.movement.Offset; import baritone.utils.pathing.BetterWorldBorder; import baritone.utils.pathing.Favoring; -import baritone.utils.pathing.MutableMoveResult; import java.util.Optional; /** - * The actual A* pathfinding + * Theta* pathfinding - an any-angle variant of A* that creates more optimal paths + * by using line-of-sight checks to skip intermediate nodes when possible * - * @author leijurv + * @author leijurv (original A*), modified to Theta* */ -public final class AStarPathFinder extends AbstractNodeCostSearch { +public final class ThetaStarPathFinder extends AbstractNodeCostSearch { private final Favoring favoring; private final CalculationContext calcContext; - public AStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { + public ThetaStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) { super(realStart, startX, startY, startZ, goal, context); this.favoring = favoring; this.calcContext = context; @@ -62,7 +65,6 @@ protected Optional calculate0(long primaryTimeout, long failureTimeout) { bestHeuristicSoFar[i] = startNode.estimatedCostToGoal; bestSoFar[i] = startNode; } - MutableMoveResult res = new MutableMoveResult(); BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder()); long startTime = System.currentTimeMillis(); boolean slowPath = Baritone.settings().slowPath.value; @@ -95,108 +97,106 @@ protected Optional calculate0(long primaryTimeout, long failureTimeout) { PathNode currentNode = openSet.removeLowest(); mostRecentConsidered = currentNode; numNodes++; + if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered"); return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext)); } - for (Moves moves : allMoves) { - int newX = currentNode.x + moves.xOffset; - int newZ = currentNode.z + moves.zOffset; - if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) { - // only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement - if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed + + for (Moves move : allMoves) { + for (Pair offsetAndCost : move.offsets(calcContext, currentNode.x, currentNode.y, currentNode.z)) { + int newX = currentNode.x + offsetAndCost.first().x(); + int newY = currentNode.y + offsetAndCost.first().y(); + int newZ = currentNode.z + offsetAndCost.first().z(); + + if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) { numEmptyChunk++; + continue; } - continue; - } - if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) { - continue; - } - if (currentNode.y + moves.yOffset > height || currentNode.y + moves.yOffset < minY) { - continue; - } - res.reset(); - moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res); - numMovementsConsidered++; - double actionCost = res.cost; - if (actionCost >= ActionCosts.COST_INF) { - continue; - } - if (actionCost <= 0 || Double.isNaN(actionCost)) { - throw new IllegalStateException(String.format( - "%s from %s %s %s calculated implausible cost %s", - moves, - SettingsUtil.maybeCensor(currentNode.x), - SettingsUtil.maybeCensor(currentNode.y), - SettingsUtil.maybeCensor(currentNode.z), - actionCost)); - } - // check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination - if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218 - continue; - } - if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) { - throw new IllegalStateException(String.format( - "%s from %s %s %s ended at x z %s %s instead of %s %s", - moves, - SettingsUtil.maybeCensor(currentNode.x), - SettingsUtil.maybeCensor(currentNode.y), - SettingsUtil.maybeCensor(currentNode.z), - SettingsUtil.maybeCensor(res.x), - SettingsUtil.maybeCensor(res.z), - SettingsUtil.maybeCensor(newX), - SettingsUtil.maybeCensor(newZ))); - } - if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) { - throw new IllegalStateException(String.format( - "%s from %s %s %s ended at y %s instead of %s", - moves, - SettingsUtil.maybeCensor(currentNode.x), - SettingsUtil.maybeCensor(currentNode.y), - SettingsUtil.maybeCensor(currentNode.z), - SettingsUtil.maybeCensor(res.y), - SettingsUtil.maybeCensor(currentNode.y + moves.yOffset))); - } - long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z); - if (isFavoring) { - // see issue #18 - actionCost *= favoring.calculate(hashCode); - } - PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode); - double tentativeCost = currentNode.cost + actionCost; - if (neighbor.cost - tentativeCost > minimumImprovement) { - neighbor.previous = currentNode; - neighbor.cost = tentativeCost; - neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; - if (neighbor.isOpen()) { - openSet.update(neighbor); + if (!worldBorder.entirelyContains(newX, newZ)) { + continue; + } + if (newY > height || newY < minY) { + continue; + } + + numMovementsConsidered++; + double actionCost = offsetAndCost.second(); + if (actionCost >= ActionCosts.COST_INF) { + continue; + } + if (actionCost <= 0 || Double.isNaN(actionCost)) { + throw new IllegalStateException(String.format( + "%s from %s %s %s calculated implausible cost %s", + move, + SettingsUtil.maybeCensor(currentNode.x), + SettingsUtil.maybeCensor(currentNode.y), + SettingsUtil.maybeCensor(currentNode.z), + actionCost)); + } + + long hashCode = BetterBlockPos.longHash(newX, newY, newZ); + + PathNode neighbor = getNodeAtPosition(newX, newY, newZ, hashCode); + + PathNode parentNode = currentNode.previous; + double tentativeCost; + + double shortcutCost; + + if (parentNode != null && (shortcutCost = move.cost(calcContext, parentNode.x, parentNode.y, parentNode.z, newX, newY, newZ)) <= currentNode.cost + actionCost) { + // Theta Star + actionCost = shortcutCost; + tentativeCost = parentNode.cost; } else { - openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there + parentNode = currentNode; + tentativeCost = currentNode.cost; + } + + if (isFavoring) { + actionCost *= favoring.calculate(hashCode); } - for (int i = 0; i < COEFFICIENTS.length; i++) { - double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; - if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) { - bestHeuristicSoFar[i] = heuristic; - bestSoFar[i] = neighbor; - if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) { - failing = false; + tentativeCost += actionCost; + + if (neighbor.cost - tentativeCost > minimumImprovement) { + neighbor.previous = parentNode; + neighbor.cost = tentativeCost; + neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; + + if (neighbor.isOpen()) { + openSet.update(neighbor); + } else { + openSet.insert(neighbor); //don't double count, don't insert into the open set if it's already there + } + + for (int i = 0; i < COEFFICIENTS.length; i++) { + double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; + if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) { + bestHeuristicSoFar[i] = heuristic; + bestSoFar[i] = neighbor; + if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) { + failing = false; + } } } } } } } + if (cancelRequested) { return Optional.empty(); } + System.out.println(numMovementsConsidered + " movements considered"); 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"); + Optional result = bestSoFar(true, numNodes); if (result.isPresent()) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered"); } return result; } -} +} \ No newline at end of file diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index 739c8ee89..d17eab347 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -26,6 +26,8 @@ import baritone.behavior.PathingBehavior; import baritone.utils.BlockStateInterface; import java.util.*; +import java.util.function.Supplier; + import net.minecraft.core.BlockPos; import net.minecraft.core.Direction; import net.minecraft.world.entity.item.FallingBlockEntity; @@ -52,7 +54,7 @@ public abstract class Movement implements IMovement, MovementHelper { /** * The position where we need to place a block before this movement can ensue */ - protected final BetterBlockPos positionToPlace; + protected final BetterBlockPos[] positionsToPlace; private Double cost; @@ -64,13 +66,13 @@ public abstract class Movement implements IMovement, MovementHelper { private Boolean calculatedWhileLoaded; - protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos toPlace) { + protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos[] toPlace) { this.baritone = baritone; this.ctx = baritone.getPlayerContext(); this.src = src; this.dest = dest; this.positionsToBreak = toBreak; - this.positionToPlace = toPlace; + this.positionsToPlace = toPlace; } protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak) { @@ -276,8 +278,12 @@ public List toPlace(BlockStateInterface bsi) { return toPlaceCached; } List result = new ArrayList<>(); - if (positionToPlace != null && !MovementHelper.canWalkOn(bsi, positionToPlace.x, positionToPlace.y, positionToPlace.z)) { - result.add(positionToPlace); + if (positionsToPlace != null) { + for (BetterBlockPos position : positionsToPlace) { + if (!MovementHelper.canWalkOn(bsi, position.x, position.y, position.z)) { + result.add(position); + } + } } toPlaceCached = result; return result; diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 914a806ae..48ebf7b14 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -49,6 +49,7 @@ import net.minecraft.world.phys.BlockHitResult; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; +import org.apache.logging.log4j.util.TriConsumer; import java.util.ArrayList; import java.util.List; @@ -204,6 +205,7 @@ static boolean canWalkThroughPosition(BlockStateInterface bsi, int x, int y, int if (!bsi.worldContainsLoadedChunk(x, z)) { return true; } + // TODO We should actually be checking the block's height, not just snow specifically // the check in BlockSnow.isPassable is layers < 5 // while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling if (state.getValue(SnowLayerBlock.LAYERS) >= 3) { @@ -652,9 +654,9 @@ static void switchToBestToolFor(IPlayerContext ctx, BlockState b, ToolSet ts, bo static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) { state.setTarget(new MovementTarget( - RotationUtils.calcRotationFromVec3d(ctx.playerHead(), - VecUtils.getBlockPosCenter(pos), - ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()), + RotationUtils.calcRotationFromVec3d( + ctx.playerHead(), VecUtils.getBlockPosCenter(pos), ctx.playerRotations() + ).withPitch(ctx.playerRotations().getPitch()), false )).setInput(Input.MOVE_FORWARD, true); } @@ -819,4 +821,57 @@ static List steppingOnBlocks(IPlayerContext ctx) { } return blocks; } + + /** + * Amanatides & Woo algorithm to traverse voxels along a ray. + */ + static void pathPositions(int currentX, int currentY, int currentZ, int endX, int endY, int endZ, TriConsumer voxelCallback) { + // Direction vector + int dx = endX - currentX; + int dy = endY - currentY; + int dz = endZ - currentZ; + + // Step direction: -1, 0, or 1 + int stepX = Integer.signum(dx); + int stepY = Integer.signum(dy); + int stepZ = Integer.signum(dz); + + // tDelta: how far along the ray we must move for the horizontal/vertical/depth + // component to equal the width/height/depth of a voxel + double tDeltaX = (stepX != 0) ? 1.0 / Math.abs(dx) : Double.MAX_VALUE; + double tDeltaY = (stepY != 0) ? 1.0 / Math.abs(dy) : Double.MAX_VALUE; + double tDeltaZ = (stepZ != 0) ? 1.0 / Math.abs(dz) : Double.MAX_VALUE; + + // tMax: the value of t at which the ray crosses the first voxel boundary + double tMaxX = (stepX != 0) ? tDeltaX * 0.5 : Double.MAX_VALUE; + double tMaxY = (stepY != 0) ? tDeltaY * 0.5 : Double.MAX_VALUE; + double tMaxZ = (stepZ != 0) ? tDeltaZ * 0.5 : Double.MAX_VALUE; + + // Add the starting voxel + voxelCallback.accept(currentX, currentY, currentZ); + + // Traverse until we reach the end voxel + while (currentX != endX || currentY != endY || currentZ != endZ) { + // Step to the next voxel by moving along the axis with the smallest tMax + if (tMaxX < tMaxY) { + if (tMaxX < tMaxZ) { + currentX += stepX; + tMaxX += tDeltaX; + } else { + currentZ += stepZ; + tMaxZ += tDeltaZ; + } + } else { + if (tMaxY < tMaxZ) { + currentY += stepY; + tMaxY += tDeltaY; + } else { + currentZ += stepZ; + tMaxZ += tDeltaZ; + } + } + + voxelCallback.accept(currentX, currentY, currentZ); + } + } } diff --git a/src/main/java/baritone/pathing/movement/Moves.java b/src/main/java/baritone/pathing/movement/Moves.java index 312c8957c..e00395501 100644 --- a/src/main/java/baritone/pathing/movement/Moves.java +++ b/src/main/java/baritone/pathing/movement/Moves.java @@ -18,9 +18,10 @@ package baritone.pathing.movement; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Pair; import baritone.pathing.movement.movements.*; -import baritone.utils.pathing.MutableMoveResult; -import net.minecraft.core.Direction; + +import java.util.List; /** * An enum of all possible movements attached to all possible directions they could be taken in @@ -28,334 +29,331 @@ * @author leijurv */ public enum Moves { - DOWNWARD(0, -1, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementDownward(context.getBaritone(), src, src.below()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementDownward.cost(context, x, y, z); - } - }, - - PILLAR(0, +1, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementPillar(context.getBaritone(), src, src.above()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementPillar.cost(context, x, y, z); - } - }, - - TRAVERSE_NORTH(0, 0, -1) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementTraverse(context.getBaritone(), src, src.north()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementTraverse.cost(context, x, y, z, x, z - 1); - } - }, - - TRAVERSE_SOUTH(0, 0, +1) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementTraverse(context.getBaritone(), src, src.south()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementTraverse.cost(context, x, y, z, x, z + 1); - } - }, - - TRAVERSE_EAST(+1, 0, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementTraverse(context.getBaritone(), src, src.east()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementTraverse.cost(context, x, y, z, x + 1, z); - } - }, - - TRAVERSE_WEST(-1, 0, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementTraverse(context.getBaritone(), src, src.west()); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementTraverse.cost(context, x, y, z, x - 1, z); - } - }, - - ASCEND_NORTH(0, +1, -1) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z - 1)); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementAscend.cost(context, x, y, z, x, z - 1); - } - }, - - ASCEND_SOUTH(0, +1, +1) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z + 1)); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementAscend.cost(context, x, y, z, x, z + 1); - } - }, - - ASCEND_EAST(+1, +1, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x + 1, src.y + 1, src.z)); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementAscend.cost(context, x, y, z, x + 1, z); - } - }, - - ASCEND_WEST(-1, +1, 0) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x - 1, src.y + 1, src.z)); - } - - @Override - public double cost(CalculationContext context, int x, int y, int z) { - return MovementAscend.cost(context, x, y, z, x - 1, z); - } - }, - - DESCEND_EAST(+1, -1, 0, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - if (res.y == src.y - 1) { - return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } else { - return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDescend.cost(context, x, y, z, x + 1, z, result); - } - }, - - DESCEND_WEST(-1, -1, 0, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - if (res.y == src.y - 1) { - return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } else { - return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDescend.cost(context, x, y, z, x - 1, z, result); - } - }, - - DESCEND_NORTH(0, -1, -1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - if (res.y == src.y - 1) { - return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } else { - return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDescend.cost(context, x, y, z, x, z - 1, result); - } - }, - - DESCEND_SOUTH(0, -1, +1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - if (res.y == src.y - 1) { - return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } else { - return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); - } - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDescend.cost(context, x, y, z, x, z + 1, result); - } - }, - - DIAGONAL_NORTHEAST(+1, 0, -1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - return new MovementDiagonal(context.getBaritone(), src, Direction.NORTH, Direction.EAST, res.y - src.y); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDiagonal.cost(context, x, y, z, x + 1, z - 1, result); - } - }, - - DIAGONAL_NORTHWEST(-1, 0, -1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - return new MovementDiagonal(context.getBaritone(), src, Direction.NORTH, Direction.WEST, res.y - src.y); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDiagonal.cost(context, x, y, z, x - 1, z - 1, result); - } - }, - - DIAGONAL_SOUTHEAST(+1, 0, +1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - return new MovementDiagonal(context.getBaritone(), src, Direction.SOUTH, Direction.EAST, res.y - src.y); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDiagonal.cost(context, x, y, z, x + 1, z + 1, result); - } - }, - - DIAGONAL_SOUTHWEST(-1, 0, +1, false, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - MutableMoveResult res = new MutableMoveResult(); - apply(context, src.x, src.y, src.z, res); - return new MovementDiagonal(context.getBaritone(), src, Direction.SOUTH, Direction.WEST, res.y - src.y); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementDiagonal.cost(context, x, y, z, x - 1, z + 1, result); - } - }, - - PARKOUR_NORTH(0, 0, -4, true, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return MovementParkour.cost(context, src, Direction.NORTH); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementParkour.cost(context, x, y, z, Direction.NORTH, result); - } - }, - - PARKOUR_SOUTH(0, 0, +4, true, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return MovementParkour.cost(context, src, Direction.SOUTH); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementParkour.cost(context, x, y, z, Direction.SOUTH, result); - } - }, - - PARKOUR_EAST(+4, 0, 0, true, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return MovementParkour.cost(context, src, Direction.EAST); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementParkour.cost(context, x, y, z, Direction.EAST, result); - } - }, - - PARKOUR_WEST(-4, 0, 0, true, true) { - @Override - public Movement apply0(CalculationContext context, BetterBlockPos src) { - return MovementParkour.cost(context, src, Direction.WEST); - } - - @Override - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - MovementParkour.cost(context, x, y, z, Direction.WEST, result); +// DOWNWARD(0, -1, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementDownward(context.getBaritone(), src, src.below()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementDownward.cost(context, x, y, z); +// } +// }, +// +// PILLAR(0, +1, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementPillar(context.getBaritone(), src, src.above()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementPillar.cost(context, x, y, z); +// } +// }, +// +// TRAVERSE_NORTH(0, 0, -1) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementTraverse(context.getBaritone(), src, src.north()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementTraverse.cost(context, x, y, z, x, z - 1); +// } +// }, +// +// TRAVERSE_SOUTH(0, 0, +1) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementTraverse(context.getBaritone(), src, src.south()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementTraverse.cost(context, x, y, z, x, z + 1); +// } +// }, +// +// TRAVERSE_EAST(+1, 0, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementTraverse(context.getBaritone(), src, src.east()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementTraverse.cost(context, x, y, z, x + 1, z); +// } +// }, +// +// TRAVERSE_WEST(-1, 0, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementTraverse(context.getBaritone(), src, src.west()); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementTraverse.cost(context, x, y, z, x - 1, z); +// } +// }, +// +// ASCEND_NORTH(0, +1, -1) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z - 1)); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementAscend.cost(context, x, y, z, x, z - 1); +// } +// }, +// +// ASCEND_SOUTH(0, +1, +1) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z + 1)); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementAscend.cost(context, x, y, z, x, z + 1); +// } +// }, +// +// ASCEND_EAST(+1, +1, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x + 1, src.y + 1, src.z)); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementAscend.cost(context, x, y, z, x + 1, z); +// } +// }, +// +// ASCEND_WEST(-1, +1, 0) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x - 1, src.y + 1, src.z)); +// } +// +// @Override +// public double cost(CalculationContext context, int x, int y, int z) { +// return MovementAscend.cost(context, x, y, z, x - 1, z); +// } +// }, +// +// DESCEND_EAST(+1, -1, 0, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// if (res.y == src.y - 1) { +// return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } else { +// return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDescend.cost(context, x, y, z, x + 1, z, result); +// } +// }, +// +// DESCEND_WEST(-1, -1, 0, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// if (res.y == src.y - 1) { +// return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } else { +// return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDescend.cost(context, x, y, z, x - 1, z, result); +// } +// }, +// +// DESCEND_NORTH(0, -1, -1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// if (res.y == src.y - 1) { +// return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } else { +// return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDescend.cost(context, x, y, z, x, z - 1, result); +// } +// }, +// +// DESCEND_SOUTH(0, -1, +1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// if (res.y == src.y - 1) { +// return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } else { +// return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z)); +// } +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDescend.cost(context, x, y, z, x, z + 1, result); +// } +// }, +// +// DIAGONAL_NORTHEAST(+1, 0, -1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// return new MovementDiagonal(context.getBaritone(), src, Direction.NORTH, Direction.EAST, res.y - src.y); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDiagonal.cost(context, x, y, z, x + 1, z - 1, result); +// } +// }, +// +// DIAGONAL_NORTHWEST(-1, 0, -1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// return new MovementDiagonal(context.getBaritone(), src, Direction.NORTH, Direction.WEST, res.y - src.y); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDiagonal.cost(context, x, y, z, x - 1, z - 1, result); +// } +// }, +// +// DIAGONAL_SOUTHEAST(+1, 0, +1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// return new MovementDiagonal(context.getBaritone(), src, Direction.SOUTH, Direction.EAST, res.y - src.y); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDiagonal.cost(context, x, y, z, x + 1, z + 1, result); +// } +// }, +// +// DIAGONAL_SOUTHWEST(-1, 0, +1, false, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// MutableMoveResult res = new MutableMoveResult(); +// apply(context, src.x, src.y, src.z, res); +// return new MovementDiagonal(context.getBaritone(), src, Direction.SOUTH, Direction.WEST, res.y - src.y); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementDiagonal.cost(context, x, y, z, x - 1, z + 1, result); +// } +// }, +// +// PARKOUR_NORTH(0, 0, -4, true, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return MovementParkour.cost(context, src, Direction.NORTH); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementParkour.cost(context, x, y, z, Direction.NORTH, result); +// } +// }, +// +// PARKOUR_SOUTH(0, 0, +4, true, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return MovementParkour.cost(context, src, Direction.SOUTH); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementParkour.cost(context, x, y, z, Direction.SOUTH, result); +// } +// }, +// +// PARKOUR_EAST(+4, 0, 0, true, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return MovementParkour.cost(context, src, Direction.EAST); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementParkour.cost(context, x, y, z, Direction.EAST, result); +// } +// }, +// +// PARKOUR_WEST(-4, 0, 0, true, true) { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src) { +// return MovementParkour.cost(context, src, Direction.WEST); +// } +// +// @Override +// public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { +// MovementParkour.cost(context, x, y, z, Direction.WEST, result); +// } +// }; + + TRAVERSE { + @Override + public Movement apply0(CalculationContext context, BetterBlockPos src, BetterBlockPos dest) { + return MovementTraverse.create(context.getBaritone(), src, dest); + } + + public List> offsets(CalculationContext context, int x, int y, int z) { + return MovementTraverse.cost(context, x, y, z); + } + + public double cost(CalculationContext context, int srcX, int srcY, int srcZ, int destX, int destY, int destZ) { + return MovementTraverse.cost(context, srcX, srcY, srcZ, destX, destY, destZ); } }; - - public final boolean dynamicXZ; - public final boolean dynamicY; - - public final int xOffset; - public final int yOffset; - public final int zOffset; - - Moves(int x, int y, int z, boolean dynamicXZ, boolean dynamicY) { - this.xOffset = x; - this.yOffset = y; - this.zOffset = z; - this.dynamicXZ = dynamicXZ; - this.dynamicY = dynamicY; - } - - Moves(int x, int y, int z) { - this(x, y, z, false, false); - } - - public abstract Movement apply0(CalculationContext context, BetterBlockPos src); - - public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { - if (dynamicXZ || dynamicY) { - throw new UnsupportedOperationException("Movements with dynamic offset must override `apply`"); - } - result.x = x + xOffset; - result.y = y + yOffset; - result.z = z + zOffset; - result.cost = cost(context, x, y, z); - } - - public double cost(CalculationContext context, int x, int y, int z) { - throw new UnsupportedOperationException("Movements must override `cost` or `apply`"); - } +// PARKOUR { +// @Override +// public Movement apply0(CalculationContext context, BetterBlockPos src, BetterBlockPos dest) { +// return new MovementParkour(context.getBaritone(), src, dest); +// } +// +// @Override +// public List> cost(CalculationContext context, int x, int y, int z) { +// return MovementParkour.cost(context, x, y, z); +// } +// }; + + public abstract Movement apply0(CalculationContext context, BetterBlockPos src, BetterBlockPos dest); + + public abstract List> offsets(CalculationContext context, int x, int y, int z); + + public abstract double cost(CalculationContext context, int srcX, int srcY, int srcZ, int destX, int destY, int destZ); } diff --git a/src/main/java/baritone/pathing/movement/Offset.java b/src/main/java/baritone/pathing/movement/Offset.java new file mode 100644 index 000000000..119ec561b --- /dev/null +++ b/src/main/java/baritone/pathing/movement/Offset.java @@ -0,0 +1,20 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.pathing.movement; + +public record Offset(int x, int y, int z) {} diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 2ecd9d723..dd5d78c95 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -39,7 +39,7 @@ public class MovementAscend extends Movement { private int ticksWithoutPlacement = 0; public MovementAscend(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest) { - super(baritone, src, dest, new BetterBlockPos[]{dest, src.above(2), dest.above()}, dest.below()); + super(baritone, src, dest, new BetterBlockPos[]{dest, src.above(2), dest.above()}, new BetterBlockPos[] {dest.below()}); } @Override @@ -173,8 +173,8 @@ public MovementState updateState(MovementState state) { return state.setStatus(MovementStatus.SUCCESS); } - BlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace); - if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) { + BlockState jumpingOnto = BlockStateInterface.get(ctx, positionsToPlace[0]); // TODO add in the multiple positions to place functionality + if (!MovementHelper.canWalkOn(ctx, positionsToPlace[0], jumpingOnto)) { // TODO add in the multiple positions to place functionality ticksWithoutPlacement++; if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), false, true) == PlaceResult.READY_TO_PLACE) { state.setInput(Input.SNEAK, true); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 3e860e301..afcf06a8f 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -45,7 +45,7 @@ public class MovementDescend extends Movement { public boolean forceSafeMode = false; public MovementDescend(IBaritone baritone, BetterBlockPos start, BetterBlockPos end) { - super(baritone, start, end, new BetterBlockPos[]{end.above(2), end.above(), end}, end.below()); + super(baritone, start, end, new BetterBlockPos[]{end.above(2), end.above(), end}, new BetterBlockPos[]{end.below()}); } @Override diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index 5ea1e4dcc..926c246b7 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -21,182 +21,185 @@ import baritone.api.IBaritone; import baritone.api.pathing.movement.MovementStatus; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Pair; import baritone.api.utils.input.Input; -import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.MovementState; +import baritone.pathing.movement.*; import baritone.utils.BlockStateInterface; import baritone.utils.pathing.MutableMoveResult; -import net.minecraft.core.Direction; -import net.minecraft.world.level.block.Block; import net.minecraft.world.level.block.Blocks; import net.minecraft.world.level.block.StairBlock; import net.minecraft.world.level.block.state.BlockState; import net.minecraft.world.level.material.WaterFluid; +import java.util.ArrayList; import java.util.HashSet; +import java.util.List; import java.util.Set; public class MovementParkour extends Movement { private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{}; + private final BetterBlockPos dest; - private final Direction direction; - private final int dist; - private final boolean ascend; - - private MovementParkour(IBaritone baritone, BetterBlockPos src, int dist, Direction dir, boolean ascend) { - super(baritone, src, src.relative(dir, dist).above(ascend ? 1 : 0), EMPTY, src.relative(dir, dist).below(ascend ? 0 : 1)); - this.direction = dir; - this.dist = dist; - this.ascend = ascend; - } - - public static MovementParkour cost(CalculationContext context, BetterBlockPos src, Direction direction) { - MutableMoveResult res = new MutableMoveResult(); - cost(context, src.x, src.y, src.z, direction, res); - int dist = Math.abs(res.x - src.x) + Math.abs(res.z - src.z); - return new MovementParkour(context.getBaritone(), src, dist, direction, res.y > src.y); + public MovementParkour(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest) { + super(baritone, src, dest, EMPTY, new BetterBlockPos[] {dest}); + this.dest = dest; } - public static void cost(CalculationContext context, int x, int y, int z, Direction dir, MutableMoveResult res) { + public static List> cost(CalculationContext context, int x, int y, int z) { + List> costs = new ArrayList<>(); if (!context.allowParkour) { - return; + return costs; } if (!context.allowJumpAtBuildLimit && y >= context.world.getMaxBuildHeight()) { - return; - } - int xDiff = dir.getStepX(); - int zDiff = dir.getStepZ(); - if (!MovementHelper.fullyPassable(context, x + xDiff, y, z + zDiff)) { - // most common case at the top -- the adjacent block isn't air - return; - } - BlockState adj = context.get(x + xDiff, y - 1, z + zDiff); - if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) - // second most common case -- we could just traverse not parkour - return; - } - if (MovementHelper.avoidWalkingInto(adj) && !(adj.getFluidState().getType() instanceof WaterFluid)) { // magma sucks - return; - } - if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) { - return; - } - if (!MovementHelper.fullyPassable(context, x + xDiff, y + 2, z + zDiff)) { - return; + return costs; } if (!MovementHelper.fullyPassable(context, x, y + 2, z)) { - return; + return costs; } BlockState standingOn = context.get(x, y - 1, z); if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof StairBlock || MovementHelper.isBottomSlab(standingOn)) { - return; + return costs; } // we can't jump from (frozen) water with assumeWalkOnWater because we can't be sure it will be frozen if (context.assumeWalkOnWater && !standingOn.getFluidState().isEmpty()) { - return; + return costs; } if (!context.get(x, y, z).getFluidState().isEmpty()) { - return; // can't jump out of water + return costs; // can't jump out of water } - int maxJump; - if (context.allowWalkOnMagmaBlocks && standingOn.is(Blocks.MAGMA_BLOCK)) { - maxJump = 2; - } else if (standingOn.getBlock() == Blocks.SOUL_SAND) { - maxJump = 2; // 1 block gap - } else if (context.canSprint) { - maxJump = 4; - } else { - maxJump = 3; - } - - // check parkour jumps from smallest to largest for obstacles/walls and landing positions - int verifiedMaxJump = 1; // i - 1 (when i = 2) - for (int i = 2; i <= maxJump; i++) { - int destX = x + xDiff * i; - int destZ = z + zDiff * i; - - // check head/feet - if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) { - break; - } - if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) { - break; - } + int maxJump = getMaxJump(context, x, y, z, standingOn); - // check for ascend landing position - BlockState destInto = context.bsi.get0(destX, y, destZ); - if (!MovementHelper.fullyPassable(context, destX, y, destZ, destInto)) { - if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { - res.x = destX; - res.y = y + 1; - res.z = destZ; - res.cost = i * SPRINT_ONE_BLOCK_COST + context.jumpPenalty; - return; + // check parkour jumps from largest to smallest for obstacles/walls and landing positions + for (int xJump = -maxJump; xJump <= maxJump; xJump++) { + for (int zJump = -maxJump; zJump <= maxJump; zJump++) { + if (xJump != 0 || zJump != 0) { + double cost = cost(context, x, y, z, x + xJump, y, z + zJump); + if (cost < COST_INF) { + costs.add(new Pair<>(new Offset(xJump, 0, zJump), cost)); + } + // TODO ascending } - break; } + } + return costs; - // check for flat landing position - BlockState landingOn = context.bsi.get0(destX, y - 1, destZ); - // farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha - // frostwalker works here because we can't jump from possibly unfrozen water - if ((landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn)) - || (Math.min(16, context.frostWalker + 2) >= i && MovementHelper.canUseFrostWalker(context, landingOn)) - ) { - if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { - res.x = destX; - res.y = y; - res.z = destZ; - res.cost = costFromJumpDistance(i) + context.jumpPenalty; - return; - } - break; - } + // parkour place starts here +// if (!context.allowParkourPlace) { +// return ret; +// } +// // check parkour jumps from largest to smallest for positions to place blocks +// for (int i = verifiedMaxJump; i >= 2; i--) { +// int destX = x + i * xDiff; +// int destZ = z + i * zDiff; +// BlockState toReplace = context.get(destX, y - 1, destZ); +// double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, toReplace); +// if (placeCost >= COST_INF) { +// continue; +// } +// if (!MovementHelper.isReplaceable(destX, y - 1, destZ, toReplace, context.bsi)) { +// continue; +// } +// if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { +// continue; +// } +// for (Direction direction : HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP) { +// int againstX = destX + direction.getStepX(); +// int againstY = y - 1 + direction.getStepY(); +// int againstZ = destZ + direction.getStepZ(); +// if (againstX == destX - xDiff && againstZ == destZ - zDiff) { // we can't turn around that fast +// continue; +// } +// if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { +// res.x = destX; +// res.y = y; +// res.z = destZ; +// res.cost = costFromJumpDistance(i) + placeCost + context.jumpPenalty; +// return; +// } +// } +// } + } - if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) { - break; - } + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destY, int destZ) { + int maxJump = getMaxJump(context, x, y, z, context.get(x, y - 1, z)); + if (destX - x > maxJump || destZ - z > maxJump) { + return COST_INF; + } + if (!MovementHelper.fullyPassable(context, destX, y, destZ)) { // TODO needed check? + // most common case at the top -- the adjacent block isn't air + return COST_INF; + } + BlockState adj = context.get(destX, y - 1, destZ); +// if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) +// // second most common case -- we could just traverse not parkour +// return; +// } + if (MovementHelper.avoidWalkingInto(adj) && !(adj.getFluidState().getType() instanceof WaterFluid)) { // magma sucks + return COST_INF; + } + if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) { + return COST_INF; + } + if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) { + return COST_INF; + } - verifiedMaxJump = i; + // check head/feet + if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) { + return COST_INF; + } + if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) { + return COST_INF; } - // parkour place starts here - if (!context.allowParkourPlace) { - return; + BlockState destInto = context.bsi.get0(destX, y, destZ); + if (!MovementHelper.fullyPassable(context, destX, y, destZ, destInto)) { + return COST_INF; } - // check parkour jumps from largest to smallest for positions to place blocks - for (int i = verifiedMaxJump; i > 1; i--) { - int destX = x + i * xDiff; - int destZ = z + i * zDiff; - BlockState toReplace = context.get(destX, y - 1, destZ); - double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, toReplace); - if (placeCost >= COST_INF) { - continue; - } - if (!MovementHelper.isReplaceable(destX, y - 1, destZ, toReplace, context.bsi)) { - continue; - } - if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) { - continue; - } - for (int j = 0; j < 5; j++) { - int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepX(); - int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepY(); - int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepZ(); - if (againstX == destX - xDiff && againstZ == destZ - zDiff) { // we can't turn around that fast - continue; - } - if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { - res.x = destX; - res.y = y; - res.z = destZ; - res.cost = costFromJumpDistance(i) + placeCost + context.jumpPenalty; - return; - } - } + + BlockState landingOn = context.bsi.get0(destX, y - 1, destZ); + if (!MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn)) { + return COST_INF; + } + +// // check for ascend landing position +// BlockState destInto = context.bsi.get0(destX, y, destZ); +// if (!MovementHelper.fullyPassable(context, destX, y, destZ, destInto)) { +// if (maxJump <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) { +// res.x = destX; +// res.y = y + 1; +// res.z = destZ; +// res.cost = i * SPRINT_ONE_BLOCK_COST + context.jumpPenalty; +// return; +// } else { +// return COST_INF; +// } +// } + // check for flat landing position +// BlockState landingOn = context.bsi.get0(destX, y - 1, destZ); +// // farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha +// // frostwalker works here because we can't jump from possibly unfrozen water +// if ((landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn)) +// || (Math.min(16, context.frostWalker + 2) >= i && MovementHelper.canUseFrostWalker(context, landingOn)) +// ) { +// if (checkOvershootSafety(context.bsi, destX, destY, destZ)) { +// return costFromJumpDistance((int)Mth.sqrt((x - destX) * (x - destX) + (z - destZ) * (z - destZ))) + context.jumpPenalty; // TODO cost calculation changes for diag jumps +// } +// return COST_INF; +// } + return costFromJumpDistance(maxJump); + } + + private static int getMaxJump(CalculationContext context, int x, int y, int z, BlockState standingOn) { + if (context.allowWalkOnMagmaBlocks && standingOn.is(Blocks.MAGMA_BLOCK)) { + return 2; + } else if (standingOn.getBlock() == Blocks.SOUL_SAND) { + return 2; // 1 block gap + } else if (context.canSprint) { + return 4; + } else { + return 3; } } @@ -206,35 +209,31 @@ private static boolean checkOvershootSafety(BlockStateInterface bsi, int x, int } private static double costFromJumpDistance(int dist) { - switch (dist) { - case 2: - return WALK_ONE_BLOCK_COST * 2; // IDK LOL - case 3: - return WALK_ONE_BLOCK_COST * 3; - case 4: - return SPRINT_ONE_BLOCK_COST * 4; - default: - throw new IllegalStateException("LOL " + dist); - } + // TODO calculate jump costs + return switch (dist) { + case 2 -> WALK_ONE_BLOCK_COST * 2 / 2; // IDK LOL + case 3 -> WALK_ONE_BLOCK_COST * 3 / 2; + case 4 -> SPRINT_ONE_BLOCK_COST * 4 / 2; + default -> throw new IllegalStateException("LOL " + dist); + }; } @Override public double calculateCost(CalculationContext context) { - MutableMoveResult res = new MutableMoveResult(); - cost(context, src.x, src.y, src.z, direction, res); - if (res.x != dest.x || res.y != dest.y || res.z != dest.z) { - return COST_INF; - } - return res.cost; + return cost(context, src.x, src.y, src.z, dest.x, dest.y, dest.z); } @Override protected Set calculateValidPositions() { Set set = new HashSet<>(); - for (int i = 0; i <= dist; i++) { - for (int y = 0; y < 2; y++) { - set.add(src.relative(direction, i).above(y)); + int xDist = Math.abs(src.x - dest.x); + int zDist = Math.abs(src.z - dest.z); + for (int x = -xDist; x <= xDist; x++) { + for (int z = -zDist; z <= zDist; z++) { + if ((src.x != x || src.z != z) && x * x + z * z < 20) { + set.add(new BetterBlockPos(src.x + x, src.y, src.z + z)); + } } } return set; @@ -250,6 +249,7 @@ public boolean safeToCancel(MovementState state) { @Override public MovementState updateState(MovementState state) { + System.out.println("sdlpihsdf"); super.updateState(state); if (state.getStatus() != MovementStatus.RUNNING) { return state; @@ -259,55 +259,57 @@ public MovementState updateState(MovementState state) { logDebug("sorry"); return state.setStatus(MovementStatus.UNREACHABLE); } - if (dist >= 4 || ascend) { - state.setInput(Input.SPRINT, true); - } +// if (dist >= 4 || ascend) { +// state.setInput(Input.SPRINT, true); +// } + state.setInput(Input.SPRINT, true); if (Baritone.settings().allowWalkOnMagmaBlocks.value && ctx.world().getBlockState(ctx.playerFeet().below()).is(Blocks.MAGMA_BLOCK)) { state.setInput(Input.SNEAK, true); } - MovementHelper.moveTowards(ctx, state, dest); + if (Math.abs(ctx.playerFeetAsVec().x() - dest.getCenter().x()) > ctx.playerMotion().x() && + Math.abs(ctx.playerFeetAsVec().z() - dest.getCenter().z()) > ctx.playerMotion().z()) { + MovementHelper.moveTowards(ctx, state, dest); + } if (ctx.playerFeet().equals(dest)) { - Block d = BlockStateInterface.getBlock(ctx, dest); - if (d == Blocks.VINE || d == Blocks.LADDER) { - // it physically hurt me to add support for parkour jumping onto a vine - // but i did it anyway - return state.setStatus(MovementStatus.SUCCESS); - } - if (ctx.player().position().y - ctx.playerFeet().getY() < 0.094) { // lilypads + if (ctx.player().isOnGround()) { state.setStatus(MovementStatus.SUCCESS); } - } else if (!ctx.playerFeet().equals(src)) { - if (ctx.playerFeet().equals(src.relative(direction)) || ctx.player().position().y - src.y > 0.0001) { - if (Baritone.settings().allowPlace.value // see PR #3775 - && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway() - && !MovementHelper.canWalkOn(ctx, dest.below()) - && !ctx.player().isOnGround() - && MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false) == PlaceResult.READY_TO_PLACE - ) { - // go in the opposite order to check DOWN before all horizontals -- down is preferable because you don't have to look to the side while in midair, which could mess up the trajectory - state.setInput(Input.CLICK_RIGHT, true); - } - // prevent jumping too late by checking for ascend - if (dist == 3 && !ascend) { // this is a 2 block gap, dest = src + direction * 3 - double xDiff = (src.x + 0.5) - ctx.player().position().x; - double zDiff = (src.z + 0.5) - ctx.player().position().z; - double distFromStart = Math.max(Math.abs(xDiff), Math.abs(zDiff)); - if (distFromStart < 0.7) { - return state; - } - } - - state.setInput(Input.JUMP, true); - } else if (!ctx.playerFeet().equals(dest.relative(direction, -1))) { - state.setInput(Input.SPRINT, false); - if (ctx.playerFeet().equals(src.relative(direction, -1))) { - MovementHelper.moveTowards(ctx, state, src); - } else { - MovementHelper.moveTowards(ctx, state, src.relative(direction, -1)); - } - } + } else if (ctx.playerFeet().distanceSq(dest) > 2) { + state.setInput(Input.JUMP, true); } + MovementHelper.moveTowards(ctx, state, dest); +// } else if (!ctx.playerFeet().equals(src)) { +// if (ctx.playerFeet().equals(src.relative(direction)) || ctx.player().position().y - src.y > 0.0001) { +// if (Baritone.settings().allowPlace.value // see PR #3775 +// && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway() +// && !MovementHelper.canWalkOn(ctx, dest.below()) +// && !ctx.player().isOnGround() +// && MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false) == PlaceResult.READY_TO_PLACE +// ) { +// // go in the opposite order to check DOWN before all horizontals -- down is preferable because you don't have to look to the side while in midair, which could mess up the trajectory +// state.setInput(Input.CLICK_RIGHT, true); +// } +// // prevent jumping too late by checking for ascend +// if (dist == 3 && !ascend) { // this is a 2 block gap, dest = src + direction * 3 +// double xDiff = (src.x + 0.5) - ctx.player().position().x; +// double zDiff = (src.z + 0.5) - ctx.player().position().z; +// double distFromStart = Math.max(Math.abs(xDiff), Math.abs(zDiff)); +// if (distFromStart < 0.7) { +// return state; +// } +// } +// +// state.setInput(Input.JUMP, true); +// } else if (!ctx.playerFeet().equals(dest.relative(direction, -1))) { +// state.setInput(Input.SPRINT, false); +// if (ctx.playerFeet().equals(src.relative(direction, -1))) { +// MovementHelper.moveTowards(ctx, state, src); +// } else { +// MovementHelper.moveTowards(ctx, state, src.relative(direction, -1)); +// } +// } +// } return state; } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index 8007eb767..d0cd5fe90 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -49,7 +49,7 @@ public class MovementPillar extends Movement { public MovementPillar(IBaritone baritone, BetterBlockPos start, BetterBlockPos end) { - super(baritone, start, end, new BetterBlockPos[]{start.above(2)}, start); + super(baritone, start, end, new BetterBlockPos[]{start.above(2)}, new BetterBlockPos[]{start}); } @Override @@ -195,7 +195,7 @@ public MovementState updateState(MovementState state) { boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE; boolean vine = fromDown.getBlock() == Blocks.VINE; Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), - VecUtils.getBlockPosCenter(positionToPlace), + VecUtils.getBlockPosCenter(positionsToPlace[0]), // TODO add in the multiple positions to place functionality ctx.playerRotations()); if (!ladder) { state.setTarget(new MovementState.MovementTarget(ctx.playerRotations().withPitch(rotation.getPitch()), true)); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index b500eb8e4..0d3ada28f 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -20,15 +20,9 @@ import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.pathing.movement.MovementStatus; -import baritone.api.utils.BetterBlockPos; -import baritone.api.utils.Rotation; -import baritone.api.utils.RotationUtils; -import baritone.api.utils.VecUtils; +import baritone.api.utils.*; import baritone.api.utils.input.Input; -import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.Movement; -import baritone.pathing.movement.MovementHelper; -import baritone.pathing.movement.MovementState; +import baritone.pathing.movement.*; import baritone.utils.BlockStateInterface; import com.google.common.collect.ImmutableSet; import net.minecraft.core.BlockPos; @@ -44,18 +38,37 @@ import net.minecraft.world.level.block.state.properties.SlabType; import net.minecraft.world.phys.Vec3; +import java.util.ArrayList; +import java.util.List; import java.util.Optional; import java.util.Set; public class MovementTraverse extends Movement { + private static final Offset[] offsets = { + new Offset(-1, 0, 0), + new Offset(+1, 0, 0), + new Offset(0, 0, -1), + new Offset(0, 0, +1), + }; /** * Did we have to place a bridge block or was it always there */ private boolean wasTheBridgeBlockAlwaysThere = true; - public MovementTraverse(IBaritone baritone, BetterBlockPos from, BetterBlockPos to) { - super(baritone, from, to, new BetterBlockPos[]{to.above(), to}, to.below()); + private MovementTraverse(IBaritone baritone, BetterBlockPos from, BetterBlockPos to, BetterBlockPos[] toBreak, BetterBlockPos[] toPlace) { + super(baritone, from, to, toBreak, toPlace); + } + + public static MovementTraverse create(IBaritone baritone, BetterBlockPos from, BetterBlockPos to) { // This method exists since you can't put stuff behind `super` before Java 22. + List toBreak = new ArrayList<>(32); + List toPlace = new ArrayList<>(16); + MovementHelper.pathPositions(from.x, from.y, from.z, to.x, to.y, to.z, (x, y, z) -> { + toBreak.add(new BetterBlockPos(x, y, z)); + toBreak.add(new BetterBlockPos(x, y + 1, z)); + toPlace.add(new BetterBlockPos(x, y - 1, z)); + }); + return new MovementTraverse(baritone, from, to, toBreak.toArray(BetterBlockPos[]::new), toPlace.toArray(BetterBlockPos[]::new)); } @Override @@ -66,7 +79,7 @@ public void reset() { @Override public double calculateCost(CalculationContext context) { - return cost(context, src.x, src.y, src.z, dest.x, dest.z); + return cost(context, src.x, src.y, src.z, dest.x, dest.y, dest.z); } @Override @@ -74,109 +87,139 @@ protected Set calculateValidPositions() { return ImmutableSet.of(src, dest); // src.above means that we don't get caught in an infinite loop in water } - public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { - BlockState pb0 = context.get(destX, y + 1, destZ); - BlockState pb1 = context.get(destX, y, destZ); - BlockState destOn = context.get(destX, y - 1, destZ); - BlockState srcDown = context.get(x, y - 1, z); - Block srcDownBlock = srcDown.getBlock(); - boolean standingOnABlock = MovementHelper.mustBeSolidToWalkOn(context, x, y - 1, z, srcDown); - boolean frostWalker = standingOnABlock && !context.assumeWalkOnWater && MovementHelper.canUseFrostWalker(context, destOn); - if (frostWalker || MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) { //this is a walk, not a bridge - double WC = WALK_ONE_BLOCK_COST; - boolean water = false; - boolean sneaking = false; - if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) { - WC = context.waterWalkSpeed; - water = true; - } else { - if (destOn.getBlock() == Blocks.SOUL_SAND) { - WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; - } else if (frostWalker) { - // with frostwalker we can walk on water without the penalty, if we are sure we won't be using jesus - } else if (destOn.getBlock() == Blocks.WATER) { - WC += context.walkOnWaterOnePenalty; - } - if (srcDownBlock == Blocks.SOUL_SAND) { - WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; - } else if (context.allowWalkOnMagmaBlocks && srcDownBlock.equals(Blocks.MAGMA_BLOCK)) { - sneaking = true; - WC += (SNEAK_ONE_BLOCK_COST - WALK_ONE_BLOCK_COST) / 2; - } - } - double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); - if (hardness1 >= COST_INF) { - return COST_INF; - } - double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break - if (hardness1 == 0 && hardness2 == 0) { - if (!water && !sneaking && context.canSprint) { - // If there's nothing in the way, and this isn't water, and we aren't sneak placing - // We can sprint =D - // Don't check for soul sand, since we can sprint on that too - WC *= SPRINT_MULTIPLIER; - } - return WC; - } - if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) { - hardness1 *= 5; - hardness2 *= 5; - } - return WC + hardness1 + hardness2; - } else {//this is a bridge, so we need to place a block - if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) { - return COST_INF; - } - if (MovementHelper.isReplaceable(destX, y - 1, destZ, destOn, context.bsi)) { - boolean throughWater = MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1); - if (MovementHelper.isWater(destOn) && throughWater) { - // this happens when assume walk on water is true and this is a traverse in water, which isn't allowed - return COST_INF; - } - double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, destOn); - if (placeCost >= COST_INF) { - return COST_INF; - } - double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); - if (hardness1 >= COST_INF) { - return COST_INF; - } - double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break - double WC = throughWater ? context.waterWalkSpeed : WALK_ONE_BLOCK_COST; - for (int i = 0; i < 5; i++) { - int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepX(); - int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepY(); - int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepZ(); - if (againstX == x && againstZ == z) { // this would be a backplace - continue; - } - if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option - return WC + placeCost + hardness1 + hardness2; - } - } - // now that we've checked all possible directions to side place, we actually need to backplace - if (srcDownBlock == Blocks.SOUL_SAND || (srcDownBlock instanceof SlabBlock && srcDown.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)) { - return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/ - } - if (!standingOnABlock) { // standing on water / swimming - return COST_INF; // this is obviously impossible - } - Block blockSrc = context.getBlock(x, y, z); - if ((blockSrc == Blocks.LILY_PAD || blockSrc instanceof CarpetBlock) && !srcDown.getFluidState().isEmpty()) { - return COST_INF; // we can stand on these but can't place against them - } - WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol - return WC + placeCost + hardness1 + hardness2; + public static List> cost(CalculationContext context, int x, int y, int z) { + List> costs = new ArrayList<>(); + for (Offset offset : offsets) { + double cost = cost(context, x, y, z, x + offset.x(), y + offset.y(), z + offset.z()); + if (cost < COST_INF) { + costs.add(new Pair<>(offset, cost)); } + } + return costs; + } + + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destY, int destZ) { + if (y != destY) { return COST_INF; } + + int offsetX = destX - x; + int offsetZ = destZ - z; + + double[] cost = {Math.sqrt(offsetX * offsetX + offsetZ * offsetZ) * WALK_ONE_BLOCK_COST}; + MovementHelper.pathPositions(x, y, z, destX, destY, destZ, (blockX, blockY, blockZ) -> { + cost[0] += MovementHelper.getMiningDurationTicks(context, blockX, blockY, blockZ, false) + + MovementHelper.getMiningDurationTicks(context, blockX, blockY, blockZ, true); + if (cost[0] >= COST_INF) { + HELPER.logDebug(new BetterBlockPos(blockX, blockY, blockZ).toString()); + } + }); + if (context.canSprint) { + cost[0] *= SPRINT_MULTIPLIER; + } + return cost[0]; + +// BlockState pb0 = context.get(destX, destY + 1, destZ); +// BlockState pb1 = context.get(destX, destY, destZ); +// BlockState destOn = context.get(destX, destY - 1, destZ); +// BlockState srcDown = context.get(x, y - 1, z); +// Block srcDownBlock = srcDown.getBlock(); +// boolean standingOnABlock = MovementHelper.mustBeSolidToWalkOn(context, x, y - 1, z, srcDown); +// boolean frostWalker = standingOnABlock && !context.assumeWalkOnWater && MovementHelper.canUseFrostWalker(context, destOn); +// if (frostWalker || MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) { //this is a walk, not a bridge +// double WC = WALK_ONE_BLOCK_COST; +// boolean water = false; +// boolean sneaking = false; +// if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) { +// WC = context.waterWalkSpeed; +// water = true; +// } else { +// if (destOn.getBlock() == Blocks.SOUL_SAND) { +// WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; +// } else if (frostWalker) { +// // with frostwalker we can walk on water without the penalty, if we are sure we won't be using jesus +// } else if (destOn.getBlock() == Blocks.WATER) { +// WC += context.walkOnWaterOnePenalty; +// } +// if (srcDownBlock == Blocks.SOUL_SAND) { +// WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; +// } else if (context.allowWalkOnMagmaBlocks && srcDownBlock.equals(Blocks.MAGMA_BLOCK)) { +// sneaking = true; +// WC += (SNEAK_ONE_BLOCK_COST - WALK_ONE_BLOCK_COST) / 2; +// } +// } +// double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); +// if (hardness1 >= COST_INF) { +// return COST_INF; +// } +// double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break +// if (hardness1 == 0 && hardness2 == 0) { +// if (!water && !sneaking && context.canSprint) { +// // If there's nothing in the way, and this isn't water, and we aren't sneak placing +// // We can sprint =D +// // Don't check for soul sand, since we can sprint on that too +// WC *= SPRINT_MULTIPLIER; +// } +// return WC; +// } +// if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) { +// hardness1 *= 5; +// hardness2 *= 5; +// } +// +// return WC + hardness1 + hardness2; +// } else {//this is a bridge, so we need to place a block +// if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) { +// return COST_INF; +// } +// if (MovementHelper.isReplaceable(destX, y - 1, destZ, destOn, context.bsi)) { +// boolean throughWater = MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1); +// if (MovementHelper.isWater(destOn) && throughWater) { +// // this happens when assume walk on water is true and this is a traverse in water, which isn't allowed +// return COST_INF; +// } +// double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, destOn); +// if (placeCost >= COST_INF) { +// return COST_INF; +// } +// double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); +// if (hardness1 >= COST_INF) { +// return COST_INF; +// } +// double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break +// double WC = throughWater ? context.waterWalkSpeed : WALK_ONE_BLOCK_COST; +// for (int i = 0; i < 5; i++) { +// int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepX(); +// int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepY(); +// int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepZ(); +// if (againstX == x && againstZ == z) { // this would be a backplace +// continue; +// } +// if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option +// return WC + placeCost + hardness1 + hardness2; +// } +// } +// // now that we've checked all possible directions to side place, we actually need to backplace +// if (srcDownBlock == Blocks.SOUL_SAND || (srcDownBlock instanceof SlabBlock && srcDown.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)) { +// return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/ +// } +// if (!standingOnABlock) { // standing on water / swimming +// return COST_INF; // this is obviously impossible +// } +// Block blockSrc = context.getBlock(x, y, z); +// if ((blockSrc == Blocks.LILY_PAD || blockSrc instanceof CarpetBlock) && !srcDown.getFluidState().isEmpty()) { +// return COST_INF; // we can stand on these but can't place against them +// } +// WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol +// return WC + placeCost + hardness1 + hardness2; +// } +// return COST_INF; +// } } @Override public MovementState updateState(MovementState state) { super.updateState(state); - BlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]); - BlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]); if (state.getStatus() != MovementStatus.RUNNING) { // if the setting is enabled if (!Baritone.settings().walkWhileBreaking.value) { @@ -187,179 +230,216 @@ public MovementState updateState(MovementState state) { return state; } // and if it's fine to walk into the blocks in front - if (MovementHelper.avoidWalkingInto(pb0)) { - return state; - } - if (MovementHelper.avoidWalkingInto(pb1)) { - return state; - } - // and we aren't already pressed up against the block - double dist = Math.max(Math.abs(ctx.player().position().x - (dest.getX() + 0.5D)), Math.abs(ctx.player().position().z - (dest.getZ() + 0.5D))); - if (dist < 0.83) { - return state; - } - if (!state.getTarget().getRotation().isPresent()) { +// if (MovementHelper.avoidWalkingInto(pb0)) { +// return state; +// } +// if (MovementHelper.avoidWalkingInto(pb1)) { +// return state; +// } + + if (state.getTarget().getRotation().isEmpty()) { // this can happen rarely when the server lags and doesn't send the falling sand entity until you've already walked through the block and are now mining the next one return state; } - // combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break - // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest), ctx.playerRotations()).getYaw(); float pitchToBreak = state.getTarget().getRotation().get().getPitch(); - if ((MovementHelper.isBlockNormalCube(pb0) || pb0.getBlock() instanceof AirBlock && (MovementHelper.isBlockNormalCube(pb1) || pb1.getBlock() instanceof AirBlock))) { - // in the meantime, before we're right up against the block, we can break efficiently at this angle - pitchToBreak = 26; - } - - return state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)) - .setInput(Input.MOVE_FORWARD, true) - .setInput(Input.SPRINT, true); - } - - Block fd = BlockStateInterface.get(ctx, src.below()).getBlock(); - boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE; - //sneak may have been set to true in the PREPPING state while mining an adjacent block, but we still want it to be true if the player is about to go on magma - state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK))); - - if (pb0.getBlock() instanceof DoorBlock || pb1.getBlock() instanceof DoorBlock) { - boolean notPassable = pb0.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, src, dest) || pb1.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, dest, src); - boolean canOpen = !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock())); - - if (notPassable && canOpen) { - return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true)) - .setInput(Input.CLICK_RIGHT, true); - } - } - - if (pb0.getBlock() instanceof FenceGateBlock || pb1.getBlock() instanceof FenceGateBlock) { - BlockPos blocked = !MovementHelper.isGatePassable(ctx, positionsToBreak[0], src.above()) ? positionsToBreak[0] - : !MovementHelper.isGatePassable(ctx, positionsToBreak[1], src) ? positionsToBreak[1] - : null; - if (blocked != null) { - Optional rotation = RotationUtils.reachable(ctx, blocked); - if (rotation.isPresent()) { - return state.setTarget(new MovementState.MovementTarget(rotation.get(), true)).setInput(Input.CLICK_RIGHT, true); - } - } - } - - boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(ctx, positionToPlace) || ladder || MovementHelper.canUseFrostWalker(ctx, positionToPlace); - BlockPos feet = ctx.playerFeet(); - if (feet.getY() != dest.getY() && !ladder) { - logDebug("Wrong Y coordinate"); - if (feet.getY() < dest.getY()) { - System.out.println("In movement traverse"); - return state.setInput(Input.JUMP, true); - } - return state; - } - - if (isTheBridgeBlockThere) { - if (feet.equals(dest)) { - return state.setStatus(MovementStatus.SUCCESS); - } - if (Baritone.settings().overshootTraverse.value && (feet.equals(dest.offset(getDirection())) || feet.equals(dest.offset(getDirection()).offset(getDirection())))) { - return state.setStatus(MovementStatus.SUCCESS); - } - Block low = BlockStateInterface.get(ctx, src).getBlock(); - Block high = BlockStateInterface.get(ctx, src.above()).getBlock(); - if (ctx.player().position().y > src.y + 0.1D && !ctx.player().isOnGround() && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) { - // hitting W could cause us to climb the ladder instead of going forward - // wait until we're on the ground - return state; - } - BlockPos into = dest.subtract(src).offset(dest); - BlockState intoBelow = BlockStateInterface.get(ctx, into); - BlockState intoAbove = BlockStateInterface.get(ctx, into.above()); - if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, feet) || Baritone.settings().sprintInWater.value) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) { - state.setInput(Input.SPRINT, true); - } - - BlockState destDown = BlockStateInterface.get(ctx, dest.below()); - BlockPos against = positionsToBreak[0]; - if (feet.getY() != dest.getY() && ladder && (destDown.getBlock() == Blocks.VINE || destDown.getBlock() == Blocks.LADDER)) { - against = destDown.getBlock() == Blocks.VINE ? MovementPillar.getAgainst(new CalculationContext(baritone), dest.below()) : dest.relative(destDown.getValue(LadderBlock.FACING).getOpposite()); - if (against == null) { - logDirect("Unable to climb vines. Consider disabling allowVines."); - return state.setStatus(MovementStatus.UNREACHABLE); - } - } - MovementHelper.moveTowards(ctx, state, against); - return state; + state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)); } else { - wasTheBridgeBlockAlwaysThere = false; - Block standingOn = BlockStateInterface.get(ctx, feet.below()).getBlock(); - if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof SlabBlock) { // see issue #118 - double dist = Math.max(Math.abs(dest.getX() + 0.5 - ctx.player().position().x), Math.abs(dest.getZ() + 0.5 - ctx.player().position().z)); - if (dist < 0.85) { // 0.5 + 0.3 + epsilon - MovementHelper.moveTowards(ctx, state, dest); - return state.setInput(Input.MOVE_FORWARD, false) - .setInput(Input.MOVE_BACK, true); - } - } - double dist1 = Math.max(Math.abs(ctx.player().position().x - (dest.getX() + 0.5D)), Math.abs(ctx.player().position().z - (dest.getZ() + 0.5D))); - PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), false, !Baritone.settings().assumeSafeWalk.value); - if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.value) { - state.setInput(Input.SNEAK, true); - } - switch (p) { - case READY_TO_PLACE: { - if (ctx.player().isCrouching() || Baritone.settings().assumeSafeWalk.value) { - state.setInput(Input.CLICK_RIGHT, true); - } - return state; - } - case ATTEMPTING: { - if (dist1 > 0.83) { - // might need to go forward a bit - float yaw = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()).getYaw(); - if (Math.abs(state.getTarget().rotation.getYaw() - yaw) < 0.1) { - // but only if our attempted place is straight ahead - return state.setInput(Input.MOVE_FORWARD, true); - } - } else if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) { - // well i guess theres something in the way - return state.setInput(Input.CLICK_LEFT, true); - } - return state; - } - default: - break; - } - if (feet.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 - // Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI); - double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D; - double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D; - double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D; - // faceX, faceY, faceZ is the middle of the face between from and to - BlockPos goalLook = src.below(); // this is the block we were just standing on, and the one we want to place against - - Rotation backToFace = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3(faceX, faceY, faceZ), ctx.playerRotations()); - float pitch = backToFace.getPitch(); - double dist2 = Math.max(Math.abs(ctx.player().position().x - faceX), Math.abs(ctx.player().position().z - faceZ)); - if (dist2 < 0.29) { // see issue #208 - float yaw = RotationUtils.calcRotationFromVec3d(VecUtils.getBlockPosCenter(dest), ctx.playerHead(), ctx.playerRotations()).getYaw(); - state.setTarget(new MovementState.MovementTarget(new Rotation(yaw, pitch), true)); - state.setInput(Input.MOVE_BACK, true); - } else { - state.setTarget(new MovementState.MovementTarget(backToFace, true)); - } - if (ctx.isLookingAt(goalLook)) { - return state.setInput(Input.CLICK_RIGHT, true); // wait to right click until we are able to place - } - // Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt()); - if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) { - state.setInput(Input.CLICK_LEFT, true); - } - return state; - } - MovementHelper.moveTowards(ctx, state, positionsToBreak[0]); - return state; - // TODO MovementManager.moveTowardsBlock(to); // move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block + state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d( + ctx.playerHead(), + VecUtils.calculateBlockCenter(ctx.world(), dest), + ctx.playerRotations() + ).withPitch(ctx.playerRotations().getPitch()), true)); } + return state.setInput(Input.MOVE_FORWARD, true) + .setInput(Input.SPRINT, true); +// BlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]); +// BlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]); +// if (state.getStatus() != MovementStatus.RUNNING) { +// // if the setting is enabled +// if (!Baritone.settings().walkWhileBreaking.value) { +// return state; +// } +// // and if we're prepping (aka mining the block in front) +// if (state.getStatus() != MovementStatus.PREPPING) { +// return state; +// } +// // and if it's fine to walk into the blocks in front +// if (MovementHelper.avoidWalkingInto(pb0)) { +// return state; +// } +// if (MovementHelper.avoidWalkingInto(pb1)) { +// return state; +// } +// // and we aren't already pressed up against the block +// double dist = Math.max(Math.abs(ctx.player().position().x - (dest.getX() + 0.5D)), Math.abs(ctx.player().position().z - (dest.getZ() + 0.5D))); +// if (dist < 0.83) { +// return state; +// } +// if (!state.getTarget().getRotation().isPresent()) { +// // this can happen rarely when the server lags and doesn't send the falling sand entity until you've already walked through the block and are now mining the next one +// return state; +// } +// +// // combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break +// // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw +// float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest), ctx.playerRotations()).getYaw(); +// float pitchToBreak = state.getTarget().getRotation().get().getPitch(); +// if ((MovementHelper.isBlockNormalCube(pb0) || pb0.getBlock() instanceof AirBlock && (MovementHelper.isBlockNormalCube(pb1) || pb1.getBlock() instanceof AirBlock))) { +// // in the meantime, before we're right up against the block, we can break efficiently at this angle +// pitchToBreak = 26; +// } +// +// return state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)) +// .setInput(Input.MOVE_FORWARD, true) +// .setInput(Input.SPRINT, true); +// } +// +// Block fd = BlockStateInterface.get(ctx, src.below()).getBlock(); +// boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE; +// +// //sneak may have been set to true in the PREPPING state while mining an adjacent block, but we still want it to be true if the player is about to go on magma +// state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK))); +// +// if (pb0.getBlock() instanceof DoorBlock || pb1.getBlock() instanceof DoorBlock) { +// boolean notPassable = pb0.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, src, dest) || pb1.getBlock() instanceof DoorBlock && !MovementHelper.isDoorPassable(ctx, dest, src); +// boolean canOpen = !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock())); +// +// if (notPassable && canOpen) { +// return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true)) +// .setInput(Input.CLICK_RIGHT, true); +// } +// } +// +// if (pb0.getBlock() instanceof FenceGateBlock || pb1.getBlock() instanceof FenceGateBlock) { +// BlockPos blocked = !MovementHelper.isGatePassable(ctx, positionsToBreak[0], src.above()) ? positionsToBreak[0] +// : !MovementHelper.isGatePassable(ctx, positionsToBreak[1], src) ? positionsToBreak[1] +// : null; +// if (blocked != null) { +// Optional rotation = RotationUtils.reachable(ctx, blocked); +// if (rotation.isPresent()) { +// return state.setTarget(new MovementState.MovementTarget(rotation.get(), true)).setInput(Input.CLICK_RIGHT, true); +// } +// } +// } +// +// boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(ctx, positionToPlace) || ladder || MovementHelper.canUseFrostWalker(ctx, positionToPlace); +// BlockPos feet = ctx.playerFeet(); +// if (feet.getY() != dest.getY() && !ladder) { +// logDebug("Wrong Y coordinate"); +// if (feet.getY() < dest.getY()) { +// System.out.println("In movement traverse"); +// return state.setInput(Input.JUMP, true); +// } +// return state; +// } +// +// if (isTheBridgeBlockThere) { +// if (feet.equals(dest)) { +// return state.setStatus(MovementStatus.SUCCESS); +// } +// if (Baritone.settings().overshootTraverse.value && (feet.equals(dest.offset(getDirection())) || feet.equals(dest.offset(getDirection()).offset(getDirection())))) { +// return state.setStatus(MovementStatus.SUCCESS); +// } +// Block low = BlockStateInterface.get(ctx, src).getBlock(); +// Block high = BlockStateInterface.get(ctx, src.above()).getBlock(); +// if (ctx.player().position().y > src.y + 0.1D && !ctx.player().isOnGround() && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) { +// // hitting W could cause us to climb the ladder instead of going forward +// // wait until we're on the ground +// return state; +// } +// BlockPos into = dest.subtract(src).offset(dest); +// BlockState intoBelow = BlockStateInterface.get(ctx, into); +// BlockState intoAbove = BlockStateInterface.get(ctx, into.above()); +// if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, feet) || Baritone.settings().sprintInWater.value) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) { +// state.setInput(Input.SPRINT, true); +// } +// +// BlockState destDown = BlockStateInterface.get(ctx, dest.below()); +// BlockPos against = positionsToBreak[0]; +// if (feet.getY() != dest.getY() && ladder && (destDown.getBlock() == Blocks.VINE || destDown.getBlock() == Blocks.LADDER)) { +// against = destDown.getBlock() == Blocks.VINE ? MovementPillar.getAgainst(new CalculationContext(baritone), dest.below()) : dest.relative(destDown.getValue(LadderBlock.FACING).getOpposite()); +// if (against == null) { +// logDirect("Unable to climb vines. Consider disabling allowVines."); +// return state.setStatus(MovementStatus.UNREACHABLE); +// } +// } +// MovementHelper.moveTowards(ctx, state, against); +// return state; +// } else { +// wasTheBridgeBlockAlwaysThere = false; +// Block standingOn = BlockStateInterface.get(ctx, feet.below()).getBlock(); +// if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof SlabBlock) { // see issue #118 +// double dist = Math.max(Math.abs(dest.getX() + 0.5 - ctx.player().position().x), Math.abs(dest.getZ() + 0.5 - ctx.player().position().z)); +// if (dist < 0.85) { // 0.5 + 0.3 + epsilon +// MovementHelper.moveTowards(ctx, state, dest); +// return state.setInput(Input.MOVE_FORWARD, false) +// .setInput(Input.MOVE_BACK, true); +// } +// } +// double dist1 = Math.max(Math.abs(ctx.player().position().x - (dest.getX() + 0.5D)), Math.abs(ctx.player().position().z - (dest.getZ() + 0.5D))); +// PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), false, !Baritone.settings().assumeSafeWalk.value); +// if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.value) { +// state.setInput(Input.SNEAK, true); +// } +// switch (p) { +// case READY_TO_PLACE: { +// if (ctx.player().isCrouching() || Baritone.settings().assumeSafeWalk.value) { +// state.setInput(Input.CLICK_RIGHT, true); +// } +// return state; +// } +// case ATTEMPTING: { +// if (dist1 > 0.83) { +// // might need to go forward a bit +// float yaw = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()).getYaw(); +// if (Math.abs(state.getTarget().rotation.getYaw() - yaw) < 0.1) { +// // but only if our attempted place is straight ahead +// return state.setInput(Input.MOVE_FORWARD, true); +// } +// } else if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) { +// // well i guess theres something in the way +// return state.setInput(Input.CLICK_LEFT, true); +// } +// return state; +// } +// default: +// break; +// } +// if (feet.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 +// // Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI); +// double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D; +// double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D; +// double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D; +// // faceX, faceY, faceZ is the middle of the face between from and to +// BlockPos goalLook = src.below(); // this is the block we were just standing on, and the one we want to place against +// +// Rotation backToFace = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3(faceX, faceY, faceZ), ctx.playerRotations()); +// float pitch = backToFace.getPitch(); +// double dist2 = Math.max(Math.abs(ctx.player().position().x - faceX), Math.abs(ctx.player().position().z - faceZ)); +// if (dist2 < 0.29) { // see issue #208 +// float yaw = RotationUtils.calcRotationFromVec3d(VecUtils.getBlockPosCenter(dest), ctx.playerHead(), ctx.playerRotations()).getYaw(); +// state.setTarget(new MovementState.MovementTarget(new Rotation(yaw, pitch), true)); +// state.setInput(Input.MOVE_BACK, true); +// } else { +// state.setTarget(new MovementState.MovementTarget(backToFace, true)); +// } +// if (ctx.isLookingAt(goalLook)) { +// return state.setInput(Input.CLICK_RIGHT, true); // wait to right click until we are able to place +// } +// // Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt()); +// if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) { +// state.setInput(Input.CLICK_LEFT, true); +// } +// return state; +// } +// MovementHelper.moveTowards(ctx, state, positionsToBreak[0]); +// return state; +// // TODO MovementManager.moveTowardsBlock(to); // move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block +// } } @Override diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 96d105208..9fbde0687 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -125,23 +125,6 @@ public boolean onTick() { } } } - Tuple status = closestPathPos(path); - if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) { - ticksAway++; - System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getA() + ". Threshold: " + MAX_DIST_FROM_PATH); - if (ticksAway > MAX_TICKS_AWAY) { - logDebug("Too far away from path for too long, cancelling path"); - cancel(); - return false; - } - } else { - ticksAway = 0; - } - if (possiblyOffPath(status, MAX_MAX_DIST_FROM_PATH)) { // ok, stop right away, we're way too far. - logDebug("too far from path"); - cancel(); - return false; - } //long start = System.nanoTime() / 1000000L; BlockStateInterface bsi = new BlockStateInterface(ctx); for (int i = pathPosition - 10; i < pathPosition + 10; i++) {