diff --git a/src/api/java/baritone/api/pathing/calc/IPath.java b/src/api/java/baritone/api/pathing/calc/IPath.java index 0844ab90..133de5ef 100644 --- a/src/api/java/baritone/api/pathing/calc/IPath.java +++ b/src/api/java/baritone/api/pathing/calc/IPath.java @@ -21,9 +21,9 @@ import baritone.api.Settings; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.movement.IMovement; import baritone.api.utils.BetterBlockPos; -import net.minecraft.util.math.BlockPos; import net.minecraft.world.World; +import java.util.HashSet; import java.util.List; /** @@ -153,9 +153,10 @@ public interface IPath { if (path.size() != movements.size() + 1) { throw new IllegalStateException("Size of path array is unexpected"); } + HashSet seenSoFar = new HashSet<>(); for (int i = 0; i < path.size() - 1; i++) { - BlockPos src = path.get(i); - BlockPos dest = path.get(i + 1); + BetterBlockPos src = path.get(i); + BetterBlockPos dest = path.get(i + 1); IMovement movement = movements.get(i); if (!src.equals(movement.getSrc())) { throw new IllegalStateException("Path source is not equal to the movement source"); @@ -163,6 +164,10 @@ public interface IPath { if (!dest.equals(movement.getDest())) { throw new IllegalStateException("Path destination is not equal to the movement destination"); } + if (seenSoFar.contains(src)) { + throw new IllegalStateException("Path doubles back on itself, making a loop"); + } + seenSoFar.add(src); } } } diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index af0fe142..171dd769 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -458,7 +458,7 @@ public class PathExecutor implements IPathExecutor, Helper { if (next == null) { return cutIfTooLong(); } - return SplicedPath.trySplice(path, next.path).map(path -> { + return SplicedPath.trySplice(path, next.path, false).map(path -> { if (!path.getDest().equals(next.getPath().getDest())) { throw new IllegalStateException(); } diff --git a/src/main/java/baritone/pathing/path/SplicedPath.java b/src/main/java/baritone/pathing/path/SplicedPath.java index 5048a84a..92610c86 100644 --- a/src/main/java/baritone/pathing/path/SplicedPath.java +++ b/src/main/java/baritone/pathing/path/SplicedPath.java @@ -62,7 +62,7 @@ public class SplicedPath extends PathBase { return numNodes; } - public static Optional trySplice(IPath first, IPath second) { + public static Optional trySplice(IPath first, IPath second, boolean allowOverlapCutoff) { if (second == null || first == null) { return Optional.empty(); } @@ -72,18 +72,31 @@ public class SplicedPath extends PathBase { if (!first.getDest().equals(second.getSrc())) { return Optional.empty(); } - HashSet a = new HashSet<>(first.positions()); - for (int i = 1; i < second.length(); i++) { - if (a.contains(second.positions().get(i))) { + HashSet secondPos = new HashSet<>(second.positions()); + int firstPositionInSecond = -1; + for (int i = 0; i < first.length() - 1; i++) { // overlap in the very last element is fine (and required) so only go up to first.length() - 1 + if (secondPos.contains(first.positions().get(i))) { + firstPositionInSecond = i; + } + } + if (firstPositionInSecond != -1) { + if (!allowOverlapCutoff) { return Optional.empty(); } + } else { + firstPositionInSecond = first.length() - 1; + } + int positionInSecond = second.positions().indexOf(first.positions().get(firstPositionInSecond)); + if (!allowOverlapCutoff && positionInSecond != 0) { + throw new IllegalStateException(); } List positions = new ArrayList<>(); List movements = new ArrayList<>(); - positions.addAll(first.positions()); - positions.addAll(second.positions().subList(1, second.length())); - movements.addAll(first.movements()); - movements.addAll(second.movements()); + positions.addAll(first.positions().subList(0, firstPositionInSecond + 1)); + movements.addAll(first.movements().subList(0, firstPositionInSecond)); + + positions.addAll(second.positions().subList(positionInSecond + 1, second.length())); + movements.addAll(second.movements().subList(positionInSecond, second.length() - 1)); return Optional.of(new SplicedPath(positions, movements, first.getNumNodesConsidered() + second.getNumNodesConsidered(), first.getGoal())); } }