From 9faa0ddc62ed10dc99fca669d1ace69490ae07f7 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 29 Jan 2019 15:22:48 -0800 Subject: [PATCH] huge number of fixes --- .../api/behavior/IPathingBehavior.java | 12 +++- .../api/pathing/path/IPathExecutor.java | 2 + .../baritone/behavior/PathingBehavior.java | 72 ++++++------------- .../pathing/calc/AbstractNodeCostSearch.java | 22 +++++- .../movement/movements/MovementDescend.java | 5 +- .../movement/movements/MovementFall.java | 7 +- .../baritone/pathing/path/PathExecutor.java | 1 + .../java/baritone/process/MineProcess.java | 15 ++-- .../java/baritone/utils/pathing/PathBase.java | 4 ++ 9 files changed, 72 insertions(+), 68 deletions(-) diff --git a/src/api/java/baritone/api/behavior/IPathingBehavior.java b/src/api/java/baritone/api/behavior/IPathingBehavior.java index 0f44f2ee..d28195ae 100644 --- a/src/api/java/baritone/api/behavior/IPathingBehavior.java +++ b/src/api/java/baritone/api/behavior/IPathingBehavior.java @@ -37,7 +37,13 @@ public interface IPathingBehavior extends IBehavior { * * @return The estimated remaining ticks in the current segment. */ - Optional ticksRemainingInSegment(); + default Optional ticksRemainingInSegment() { + IPathExecutor current = getCurrent(); + if (current == null) { + return Optional.empty(); + } + return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); + } /** * @return The current pathing goal @@ -47,7 +53,9 @@ public interface IPathingBehavior extends IBehavior { /** * @return Whether or not a path is currently being executed. */ - boolean isPathing(); + default boolean isPathing() { + return getCurrent() != null; + } /** * Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path. diff --git a/src/api/java/baritone/api/pathing/path/IPathExecutor.java b/src/api/java/baritone/api/pathing/path/IPathExecutor.java index f72060dc..a5c3108e 100644 --- a/src/api/java/baritone/api/pathing/path/IPathExecutor.java +++ b/src/api/java/baritone/api/pathing/path/IPathExecutor.java @@ -26,4 +26,6 @@ import baritone.api.pathing.calc.IPath; public interface IPathExecutor { IPath getPath(); + + int getPosition(); } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 74cc46ee..ea752082 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -30,7 +30,6 @@ import baritone.pathing.calc.AStarPathFinder; import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; -import baritone.pathing.path.CutoffPath; import baritone.pathing.path.PathExecutor; import baritone.utils.Helper; import baritone.utils.PathRenderer; @@ -125,7 +124,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, next = null; return; } - if (next != null && !next.getPath().positions().contains(ctx.playerFeet())) { + if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(pathStart())) { // can contain either one // if the current path failed, we may not actually be on the next one, so make sure logDebug("Discarding next path as it does not contain current position"); // for example if we had a nicely planned ahead path that starts where current ends @@ -141,16 +140,27 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT); current = next; next = null; - current.onTick(); + current.onTick(); // don't waste a tick doing nothing, get started right away return; } // at this point, current just ended, but we aren't in the goal and have no plan for the future synchronized (pathCalcLock) { if (inProgress != null) { - queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING); - // if we aren't calculating right now - return; + // we are calculating + // are we calculating the right thing though? 🤔 + BetterBlockPos calcFrom = inProgress.getStart(); + // if current just succeeded, we should be standing in calcFrom, so that's cool and good + // but if current just failed, we should discard this calculation since it doesn't start from where we're standing + if (calcFrom.equals(ctx.playerFeet()) || calcFrom.equals(pathStart())) { + // cool and good + queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING); + return; + } + // oh noes + inProgress.cancel(); // cancellation doesn't dispatch any events + inProgress = null; // this is safe since we hold both locks } + // we aren't calculating queuePathEvent(PathEvent.CALC_STARTED); findPathInNewThread(pathStart(), true); } @@ -180,11 +190,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return; } if (goal == null || goal.isInGoal(current.getPath().getDest())) { - // and this path dosen't get us all the way there + // and this path doesn't get us all the way there return; } if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { - // and this path has 5 seconds or less left + // and this path has 7.5 seconds or less left logDebug("Path almost over. Planning ahead..."); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); findPathInNewThread(current.getPath().getDest(), false); @@ -210,14 +220,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } } - @Override - public Optional ticksRemainingInSegment() { - if (current == null) { - return Optional.empty(); - } - return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); - } - public void secretInternalSetGoal(Goal goal) { this.goal = goal; } @@ -247,11 +249,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return Optional.ofNullable(inProgress); } - @Override - public boolean isPathing() { - return this.current != null; - } - public boolean isSafeToCancel() { return current == null || safeToCancel; } @@ -274,7 +271,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, if (doIt) { secretInternalSegmentCancel(); } - baritone.getPathingControlManager().cancelEverything(); + baritone.getPathingControlManager().cancelEverything(); // regardless of if we can stop the current segment, we can still stop the processes return doIt; } @@ -310,7 +307,9 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, public void forceCancel() { // NOT exposed on public api cancelEverything(); secretInternalSegmentCancel(); - inProgress = null; + synchronized (pathCalcLock) { + inProgress = null; + } } /** @@ -433,33 +432,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout); - Optional path = calcResult.getPath(); - if (Baritone.settings().cutoffAtLoadBoundary.get()) { - path = path.map(p -> { - IPath result = p.cutoffAtLoadedChunks(context.bsi); - - if (result instanceof CutoffPath) { - logDebug("Cutting off path at edge of loaded chunks"); - logDebug("Length decreased by " + (p.length() - result.length())); - } else { - logDebug("Path ends within loaded chunks"); - } - - return result; - }); - } - - Optional executor = path.map(p -> { - IPath result = p.staticCutoff(goal); - - if (result instanceof CutoffPath) { - logDebug("Static cutoff " + p.length() + " to " + result.length()); - } - - return result; - }).map(p -> new PathExecutor(this, p)); - synchronized (pathPlanLock) { + Optional executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p)); if (current == null) { if (executor.isPresent()) { queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING); diff --git a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java index 78710204..625e8e59 100644 --- a/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/pathing/calc/AbstractNodeCostSearch.java @@ -92,13 +92,25 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { cancelRequested = false; try { IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null); - isFinished = true; if (cancelRequested) { - return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path); + return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION); } if (path == null) { return new PathCalculationResult(PathCalculationResult.Type.FAILURE); } + int previousLength = path.length(); + path = path.cutoffAtLoadedChunks(context.bsi); + if (path.length() < previousLength) { + Helper.HELPER.logDebug("Cutting off path at edge of loaded chunks"); + Helper.HELPER.logDebug("Length decreased by " + (previousLength - path.length())); + } else { + Helper.HELPER.logDebug("Path ends within loaded chunks"); + } + previousLength = path.length(); + path = path.staticCutoff(goal); + if (path.length() < previousLength) { + Helper.HELPER.logDebug("Static cutoff " + previousLength + " to " + path.length()); + } if (goal.isInGoal(path.getDest())) { return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path); } else { @@ -163,7 +175,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { } @Override - public Optional bestPathSoFar() { + public Optional bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder if (startNode == null || bestSoFar == null) { return Optional.empty(); } @@ -189,4 +201,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { public final Goal getGoal() { return goal; } + + public BetterBlockPos getStart() { + return new BetterBlockPos(startX, startY, startZ); + } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index d54ffc51..aeb4e138 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -137,7 +137,7 @@ public class MovementDescend extends Movement { IBlockState ontoBlock = context.get(destX, newY, destZ); int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; - if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { + if ((ontoBlock.getBlock() == Blocks.WATER || ontoBlock.getBlock() == Blocks.FLOWING_WATER) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad // however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works) if (context.assumeWalkOnWater) { @@ -157,9 +157,6 @@ public class MovementDescend extends Movement { res.cost = tentativeCost;// TODO incorporate water swim up cost? return false; } - if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) { - return false; - } if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) { // if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know // this effectively "resets" our falling speed diff --git a/src/main/java/baritone/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/pathing/movement/movements/MovementFall.java index a82ad110..729a2f1d 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementFall.java @@ -81,7 +81,8 @@ public class MovementFall extends Movement { Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)); Rotation targetRotation = null; Block destBlock = ctx.world().getBlockState(dest).getBlock(); - if (destBlock != Blocks.WATER && destBlock != Blocks.FLOWING_WATER && willPlaceBucket() && !playerFeet.equals(dest)) { + boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER; + if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) { if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) { return state.setStatus(MovementStatus.UNREACHABLE); } @@ -102,8 +103,8 @@ public class MovementFall extends Movement { } else { state.setTarget(new MovementTarget(toDest, false)); } - if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || destBlock == Blocks.WATER)) { // 0.094 because lilypads - if (destBlock == Blocks.WATER) { // only match water, not flowing water (which we cannot pick up with a bucket) + if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || isWater)) { // 0.094 because lilypads + if (isWater) { // only match water, not flowing water (which we cannot pick up with a bucket) if (InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) { ctx.player().inventory.currentItem = ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY); if (ctx.player().motionY >= 0) { diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index 6f161cc0..a2c0e2ff 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -461,6 +461,7 @@ public class PathExecutor implements IPathExecutor, Helper { failed = true; } + @Override public int getPosition() { return pathPosition; } diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index d3883bbb..80677456 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -94,14 +94,14 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro if (Baritone.settings().legitMine.get()) { addNearby(); } - Goal goal = updateGoal(); - if (goal == null) { + PathingCommand command = updateGoal(); + if (command == null) { // none in range // maybe say something in chat? (ahem impact) cancel(); return null; } - return new PathingCommand(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH); + return command; } @Override @@ -114,17 +114,18 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro return "Mine " + mining; } - private Goal updateGoal() { + private PathingCommand updateGoal() { + boolean legit = Baritone.settings().legitMine.get(); List locs = knownOreLocations; if (!locs.isEmpty()) { List locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT); // can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new)); knownOreLocations = locs2; - return goal; + return new PathingCommand(goal, legit ? PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType.REVALIDATE_GOAL_AND_PATH); } // we don't know any ore locations at the moment - if (!Baritone.settings().legitMine.get()) { + if (!legit) { return null; } // only in non-Xray mode (aka legit mode) do we do this @@ -149,7 +150,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro } }; } - return branchPointRunaway; + return new PathingCommand(branchPointRunaway, PathingCommandType.REVALIDATE_GOAL_AND_PATH); } private void rescan(List already, CalculationContext context) { diff --git a/src/main/java/baritone/utils/pathing/PathBase.java b/src/main/java/baritone/utils/pathing/PathBase.java index 04fe9872..3acf80b4 100644 --- a/src/main/java/baritone/utils/pathing/PathBase.java +++ b/src/main/java/baritone/utils/pathing/PathBase.java @@ -17,6 +17,7 @@ package baritone.utils.pathing; +import baritone.Baritone; import baritone.api.BaritoneAPI; import baritone.api.pathing.calc.IPath; import baritone.api.pathing.goals.Goal; @@ -27,6 +28,9 @@ import net.minecraft.util.math.BlockPos; public abstract class PathBase implements IPath { @Override public PathBase cutoffAtLoadedChunks(Object bsi0) { // <-- cursed cursed cursed + if (!Baritone.settings().cutoffAtLoadBoundary.get()) { + return this; + } BlockStateInterface bsi = (BlockStateInterface) bsi0; for (int i = 0; i < positions().size(); i++) { BlockPos pos = positions().get(i);