diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index 75c93dca..6907c426 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -30,9 +30,7 @@ import net.minecraft.util.EnumFacing; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; -import java.util.ArrayList; -import java.util.List; -import java.util.Optional; +import java.util.*; public abstract class Movement implements IMovement, MovementHelper { @@ -63,6 +61,8 @@ public abstract class Movement implements IMovement, MovementHelper { public List toPlaceCached = null; public List toWalkIntoCached = null; + private Set validPositionsCached = null; + private Boolean calculatedWhileLoaded; protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos toPlace) { @@ -100,6 +100,16 @@ public abstract class Movement implements IMovement, MovementHelper { this.cost = cost; } + protected abstract Set calculateValidPositions(); + + public Set getValidPositions() { + if (validPositionsCached == null) { + validPositionsCached = calculateValidPositions(); + Objects.requireNonNull(validPositionsCached); + } + return validPositionsCached; + } + /** * Handles the execution of the latest Movement * State, and offers a Status to the calling class. diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java index 6d5ecd85..24fe2285 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java @@ -27,11 +27,14 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.BlockFalling; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; +import java.util.Set; + public class MovementAscend extends Movement { private int ticksWithoutPlacement = 0; @@ -51,6 +54,17 @@ public class MovementAscend extends Movement { return cost(context, src.x, src.y, src.z, dest.x, dest.z); } + @Override + protected Set calculateValidPositions() { + BetterBlockPos prior = new BetterBlockPos(src.subtract(getDirection()).up()); // sometimes we back up to place the block, also sprint ascends, also skip descend to straight ascend + return ImmutableSet.of(src, + src.up(), + dest, + prior, + prior.up() + ); + } + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { IBlockState toPlace = context.get(destX, y, destZ); double additionalPlacementCost = 0; @@ -143,6 +157,10 @@ public class MovementAscend extends Movement { @Override public MovementState updateState(MovementState state) { + if (ctx.playerFeet().y < src.y) { + // this check should run even when in preparing state (breaking blocks) + return state.setStatus(MovementStatus.UNREACHABLE); + } super.updateState(state); // TODO incorporate some behavior from ActionClimb (specifically how it waited until it was at most 1.2 blocks away before starting to jump // for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly) @@ -154,10 +172,6 @@ public class MovementAscend extends Movement { return state.setStatus(MovementStatus.SUCCESS); } - if (ctx.playerFeet().y < src.y) { - return state.setStatus(MovementStatus.UNREACHABLE); - } - IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace); if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) { ticksWithoutPlacement++; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index a73ed4fb..67b7cd95 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -29,6 +29,7 @@ import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; import baritone.utils.pathing.MutableMoveResult; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.Block; import net.minecraft.block.BlockFalling; import net.minecraft.block.state.IBlockState; @@ -37,6 +38,8 @@ import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import java.util.Set; + public class MovementDescend extends Movement { private int numTicks = 0; @@ -61,6 +64,11 @@ public class MovementDescend extends Movement { return result.cost; } + @Override + protected Set calculateValidPositions() { + return ImmutableSet.of(src, dest.up(), dest); + } + public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) { double totalCost = 0; IBlockState destDown = context.get(destX, y - 1, destZ); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index 9761f617..878c9cff 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -28,6 +28,7 @@ import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; import baritone.utils.pathing.MutableMoveResult; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; @@ -36,6 +37,7 @@ import net.minecraft.util.math.BlockPos; import java.util.ArrayList; import java.util.List; +import java.util.Set; public class MovementDiagonal extends Movement { @@ -64,6 +66,16 @@ public class MovementDiagonal extends Movement { return result.cost; } + @Override + protected Set calculateValidPositions() { + BetterBlockPos diagA = new BetterBlockPos(src.x, src.y, dest.z); + BetterBlockPos diagB = new BetterBlockPos(dest.x, src.y, src.z); + if (dest.y != src.y) { // only if allowDiagonalDescend + return ImmutableSet.of(src, dest.up(), diagA, diagB, dest, diagA.down(), diagB.down()); + } + return ImmutableSet.of(src, dest, diagA, diagB); + } + public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) { IBlockState destInto = context.get(destX, y, destZ); if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) { @@ -171,8 +183,9 @@ public class MovementDiagonal extends Movement { } if (ctx.playerFeet().equals(dest)) { - state.setStatus(MovementStatus.SUCCESS); - return state; + return state.setStatus(MovementStatus.SUCCESS); + } else if (!getValidPositions().contains(ctx.playerFeet())) { + return state.setStatus(MovementStatus.UNREACHABLE); } if (sprint()) { state.setInput(Input.SPRINT, true); @@ -181,7 +194,7 @@ public class MovementDiagonal extends Movement { return state; } - public boolean sprint() { + private boolean sprint() { if (MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !Baritone.settings().sprintInWater.value) { return false; } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java index 47ed9580..250f3471 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDownward.java @@ -24,10 +24,13 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; +import java.util.Set; + public class MovementDownward extends Movement { private int numTicks = 0; @@ -47,6 +50,11 @@ public class MovementDownward extends Movement { return cost(context, src.x, src.y, src.z); } + @Override + protected Set calculateValidPositions() { + return ImmutableSet.of(src, dest); + } + public static double cost(CalculationContext context, int x, int y, int z) { if (!context.allowDownward) { return COST_INF; @@ -73,6 +81,8 @@ public class MovementDownward extends Movement { if (ctx.playerFeet().equals(dest)) { return state.setStatus(MovementStatus.SUCCESS); + } else if (!getValidPositions().contains(ctx.playerFeet())) { + return state.setStatus(MovementStatus.UNREACHABLE); } double diffX = ctx.player().posX - (dest.getX() + 0.5); double diffZ = ctx.player().posZ - (dest.getZ() + 0.5); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/pathing/movement/movements/MovementFall.java index 0a4c38c7..b777b0a6 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementFall.java @@ -42,7 +42,9 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3i; +import java.util.HashSet; import java.util.Optional; +import java.util.Set; public class MovementFall extends Movement { @@ -63,6 +65,16 @@ public class MovementFall extends Movement { return result.cost; } + @Override + protected Set calculateValidPositions() { + Set set = new HashSet<>(); + set.add(src); + for (int y = src.y - dest.y; y >= 0; y--) { + set.add(dest.up(y)); + } + return set; + } + private boolean willPlaceBucket() { CalculationContext context = new CalculationContext(baritone); MutableMoveResult result = new MutableMoveResult(); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java index dfa43a05..b9f02c1a 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java @@ -34,6 +34,9 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; +import java.util.HashSet; +import java.util.Set; + public class MovementParkour extends Movement { private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{}; @@ -174,6 +177,17 @@ public class MovementParkour extends Movement { return res.cost; } + @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.offset(direction, i).up(y)); + } + } + return set; + } + @Override public boolean safeToCancel(MovementState state) { // once this movement is instantiated, the state is default to PREPPING diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java index 5e4a409f..c444422e 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java @@ -30,6 +30,7 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; @@ -37,6 +38,7 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import java.util.Objects; +import java.util.Set; public class MovementPillar extends Movement { @@ -49,6 +51,11 @@ public class MovementPillar extends Movement { return cost(context, src.x, src.y, src.z); } + @Override + protected Set calculateValidPositions() { + return ImmutableSet.of(src, dest); + } + public static double cost(CalculationContext context, int x, int y, int z) { Block from = context.get(x, y, z).getBlock(); boolean ladder = from == Blocks.LADDER || from == Blocks.VINE; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java index b621632c..03f81e76 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java @@ -30,12 +30,15 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementState; import baritone.utils.BlockStateInterface; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.*; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import java.util.Set; + public class MovementTraverse extends Movement { /** @@ -58,6 +61,11 @@ public class MovementTraverse extends Movement { return cost(context, src.x, src.y, src.z, dest.x, dest.z); } + @Override + protected Set calculateValidPositions() { + return ImmutableSet.of(src, dest); + } + public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { IBlockState pb0 = context.get(destX, y + 1, destZ); IBlockState pb1 = context.get(destX, y, destZ); @@ -205,8 +213,8 @@ public class MovementTraverse extends Movement { if (pb0.getBlock() instanceof BlockFenceGate || pb1.getBlock() instanceof BlockFenceGate) { BlockPos blocked = !MovementHelper.isGatePassable(ctx, positionsToBreak[0], src.up()) ? positionsToBreak[0] - : !MovementHelper.isGatePassable(ctx, positionsToBreak[1], src) ? positionsToBreak[1] - : null; + : !MovementHelper.isGatePassable(ctx, positionsToBreak[1], src) ? positionsToBreak[1] + : null; if (blocked != null) { return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked), ctx.playerRotations()), true)) .setInput(Input.CLICK_RIGHT, true); diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 7b9ba9ee..e92d3273 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -33,7 +33,6 @@ import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.movements.*; import baritone.utils.BlockStateInterface; import net.minecraft.block.BlockLiquid; -import net.minecraft.init.Blocks; import net.minecraft.util.Tuple; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -100,14 +99,13 @@ public class PathExecutor implements IPathExecutor, Helper { if (pathPosition >= path.length()) { return true; // stop bugging me, I'm done } - BetterBlockPos whereShouldIBe = path.positions().get(pathPosition); + Movement movement = (Movement) path.movements().get(pathPosition); BetterBlockPos whereAmI = ctx.playerFeet(); - if (!whereShouldIBe.equals(whereAmI) && !Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip - for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks - if (whereAmI.equals(path.positions().get(i))) { - logDebug("Skipping back " + (pathPosition - i) + " steps, to " + i); + if (!movement.getValidPositions().contains(whereAmI)) { + for (int i = 0; i < pathPosition && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks + if (((Movement) path.movements().get(i)).getValidPositions().contains(whereAmI)) { int previousPos = pathPosition; - pathPosition = Math.max(i - 1, 0); // previous step might not actually be done + pathPosition = i; for (int j = pathPosition; j <= previousPos; j++) { path.movements().get(j).reset(); } @@ -173,10 +171,10 @@ public class PathExecutor implements IPathExecutor, Helper { HashSet newPlace = new HashSet<>(); HashSet newWalkInto = new HashSet<>(); for (int i = pathPosition; i < path.movements().size(); i++) { - Movement movement = (Movement) path.movements().get(i); - newBreak.addAll(movement.toBreak(bsi)); - newPlace.addAll(movement.toPlace(bsi)); - newWalkInto.addAll(movement.toWalkInto(bsi)); + Movement m = (Movement) path.movements().get(i); + newBreak.addAll(m.toBreak(bsi)); + newPlace.addAll(m.toPlace(bsi)); + newWalkInto.addAll(m.toWalkInto(bsi)); } toBreak = newBreak; toPlace = newPlace; @@ -187,11 +185,13 @@ public class PathExecutor implements IPathExecutor, Helper { if (end - start > 0) { System.out.println("Recalculating break and place took " + (end - start) + "ms"); }*/ - IMovement movement = path.movements().get(pathPosition); - if (!behavior.baritone.bsi.worldContainsLoadedChunk(movement.getDest().x, movement.getDest().z)) { - logDebug("Pausing since destination is at edge of loaded chunks"); - clearKeys(); - return true; + if (pathPosition < path.movements().size() - 1) { + IMovement next = path.movements().get(pathPosition + 1); + if (!behavior.baritone.bsi.worldContainsLoadedChunk(next.getDest().x, next.getDest().z)) { + logDebug("Pausing since destination is at edge of loaded chunks"); + clearKeys(); + return true; + } } boolean canCancel = movement.safeToCancel(); if (costEstimateIndex == null || costEstimateIndex != pathPosition) { @@ -206,7 +206,7 @@ public class PathExecutor implements IPathExecutor, Helper { } } } - double currentCost = ((Movement) movement).recalculateCost(behavior.secretInternalGetCalculationContext()); + double currentCost = movement.recalculateCost(behavior.secretInternalGetCalculationContext()); if (currentCost >= ActionCosts.COST_INF && canCancel) { logDebug("Something has changed in the world and this movement has become impossible. Cancelling."); cancel(); @@ -258,11 +258,13 @@ public class PathExecutor implements IPathExecutor, Helper { private Tuple closestPathPos(IPath path) { double best = -1; BlockPos bestPos = null; - for (BlockPos pos : path.positions()) { - double dist = VecUtils.entityDistanceToCenter(ctx.player(), pos); - if (dist < best || best == -1) { - best = dist; - bestPos = pos; + for (IMovement movement : path.movements()) { + for (BlockPos pos : ((Movement) movement).getValidPositions()) { + double dist = VecUtils.entityDistanceToCenter(ctx.player(), pos); + if (dist < best || best == -1) { + best = dist; + bestPos = pos; + } } } return new Tuple<>(best, bestPos);