diff --git a/src/api/java/baritone/api/process/IBaritoneProcess.java b/src/api/java/baritone/api/process/IBaritoneProcess.java index 9eef16fc..3f907c3d 100644 --- a/src/api/java/baritone/api/process/IBaritoneProcess.java +++ b/src/api/java/baritone/api/process/IBaritoneProcess.java @@ -31,19 +31,58 @@ import baritone.api.IBaritone; * @author leijurv */ public interface IBaritoneProcess { - // javadocs small brain, // comment large brain + /** + * Would this process like to be in control? + * + * @return + */ + boolean isActive(); - boolean isActive(); // would you like to be in control? + /** + * This process is in control of pathing. What should Baritone do? + * + * @param calcFailed true if this specific process was in control last tick, and there was a CALC_FAILED event last tick + * @param isSafeToCancel true if a REQUEST_PAUSE would happen this tick, and PathingBehavior wouldn't actually tick. + * false if the PathExecutor reported pausing would be unsafe at the end of the last tick + * @return what the PathingBehavior should do + */ + PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel); - PathingCommand onTick(); // you're in control, what should baritone do? + /** + * Is this control temporary? + * If a process is temporary, it doesn't call onLostControl on the processes that aren't execute because of it + * For example, CombatPauserProcess and PauseForAutoEatProcess should return isTemporary true always, + * and should return isActive true only if there's something in range this tick, or if the player would like to start eating this tick. + * PauseForAutoEatProcess should only actually right click once onTick is called with isSafeToCancel true though. + * + * @return + */ + boolean isTemporary(); - boolean isTemporary(); // CombatPauserProcess should return isTemporary true always, and isActive true only when something is in range + /** + * Called if isActive returned true, but another non-temporary process has control. Effectively the same as cancel. + * You want control but you don't get it. + */ + void onLostControl(); - void onLostControl(); // called if isActive returned true, but another non-temporary process has control. effectively the same as cancel. + /** + * How to decide which Process gets control if they all report isActive? It's the one with the highest priority. + * + * @return + */ + double priority(); - double priority(); // tenor be like - - IBaritone associatedWith(); // which bot is this associated with (5000000iq forward thinking) + /** + * which bot is this associated with (5000000iq forward thinking) + * + * @return + */ + IBaritone associatedWith(); + /** + * What this process should be displayed to the user as (maybe in a HUD? hint hint) + * + * @return + */ String displayName(); } diff --git a/src/api/java/baritone/api/process/PathingCommandType.java b/src/api/java/baritone/api/process/PathingCommandType.java index d4f7af44..98517ba5 100644 --- a/src/api/java/baritone/api/process/PathingCommandType.java +++ b/src/api/java/baritone/api/process/PathingCommandType.java @@ -18,12 +18,34 @@ package baritone.api.process; public enum PathingCommandType { - SET_GOAL_AND_PATH, // self explanatory, if you do this one with a null goal it should continue + /** + * Set the goal and path. + *

+ * If you use this alongside a null goal, it will continue along its current path and current goal. + */ + SET_GOAL_AND_PATH, - REQUEST_PAUSE, // this one just pauses. it doesn't change the goal. + /** + * Has no effect on the current goal or path, just requests a pause + */ + REQUEST_PAUSE, - CANCEL_AND_SET_GOAL, // cancel the current path, and set the goal (regardless of if it's null) + /** + * Set the goal (regardless of null), and request a cancel of the current path (when safe) + */ + CANCEL_AND_SET_GOAL, - REVALIDATE_GOAL_AND_PATH, // set the goal, revalidate if cancelOnGoalInvalidation is true, then path. if the goal is null, it will cancel (but only if that setting is true) - FORCE_REVALIDATE_GOAL_AND_PATH // set the goal, revalidate current goal (cancel if no longer valid), cancel if the provided goal is null + /** + * Set the goal and path. + *

+ * If cancelOnGoalInvalidation is true, revalidate the current goal, and cancel if it's no longer valid, or if the new goal is null. + */ + REVALIDATE_GOAL_AND_PATH, + + /** + * Set the goal and path. + *

+ * Revalidate the current goal, and cancel if it's no longer valid, or if the new goal is null. + */ + FORCE_REVALIDATE_GOAL_AND_PATH, } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 15dffae8..03641ac5 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -54,6 +54,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, private boolean safeToCancel; private boolean pauseRequestedLastTick; + private boolean calcFailedLastTick; private volatile boolean isPathCalcInProgress; private final Object pathCalcLock = new Object(); @@ -75,6 +76,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, private void dispatchEvents() { ArrayList curr = new ArrayList<>(); toDispatch.drainTo(curr); + calcFailedLastTick = curr.contains(PathEvent.CALC_FAILED); for (PathEvent event : curr) { Baritone.INSTANCE.getGameEventHandler().onPathEvent(event); } @@ -257,6 +259,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, baritone.getPathingControlManager().cancelEverything(); } + public boolean calcFailedLastTick() { // NOT exposed on public api + return calcFailedLastTick; + } + // just cancel the current path public void secretInternalSegmentCancel() { queuePathEvent(PathEvent.CANCELED); diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java index e402edf8..52769f25 100644 --- a/src/main/java/baritone/process/CustomGoalProcess.java +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -22,7 +22,6 @@ import baritone.api.pathing.goals.Goal; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; -import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.utils.BaritoneProcessHelper; import java.util.Objects; @@ -35,7 +34,6 @@ import java.util.Objects; public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess { private Goal goal; private State state; - private int ticksExecuting; public CustomGoalProcess(Baritone baritone) { super(baritone, 3); @@ -69,7 +67,7 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG } @Override - public PathingCommand onTick() { + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { switch (state) { case GOAL_SET: if (!baritone.getPathingBehavior().isPathing() && Objects.equals(baritone.getPathingBehavior().getGoal(), goal)) { @@ -79,12 +77,14 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG case PATH_REQUESTED: PathingCommand ret = new PathingCommand(goal, PathingCommandType.SET_GOAL_AND_PATH); state = State.EXECUTING; - ticksExecuting = 0; return ret; case EXECUTING: - if (ticksExecuting++ > 2 && !baritone.getPathingBehavior().isPathing() && !AbstractNodeCostSearch.getCurrentlyRunning().isPresent()) { + if (calcFailed) { onLostControl(); } + if (goal.isInGoal(playerFeet())) { + onLostControl(); // we're there xd + } return new PathingCommand(goal, PathingCommandType.SET_GOAL_AND_PATH); default: throw new IllegalStateException(); @@ -95,7 +95,6 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG public void onLostControl() { state = State.NONE; goal = null; - ticksExecuting = 0; } @Override diff --git a/src/main/java/baritone/process/FollowProcess.java b/src/main/java/baritone/process/FollowProcess.java index bfccdda7..f662fa1d 100644 --- a/src/main/java/baritone/process/FollowProcess.java +++ b/src/main/java/baritone/process/FollowProcess.java @@ -41,7 +41,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo } @Override - public PathingCommand onTick() { + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { // lol this is trashy but it works BlockPos pos; if (Baritone.settings().followOffsetDistance.get() == 0) { diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java index b2fd1363..8dd07560 100644 --- a/src/main/java/baritone/process/GetToBlockProcess.java +++ b/src/main/java/baritone/process/GetToBlockProcess.java @@ -32,10 +32,10 @@ import java.util.Collections; import java.util.List; public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess { - Block gettingTo; - List knownLocations; + private Block gettingTo; + private List knownLocations; - int tickCount = 0; + private int tickCount = 0; public GetToBlockProcess(Baritone baritone) { super(baritone, 2); @@ -53,14 +53,23 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl } @Override - public PathingCommand onTick() { + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { if (knownLocations == null) { rescan(); } if (knownLocations.isEmpty()) { - logDirect("No known locations of " + gettingTo); - onLostControl(); - return null; + logDirect("No known locations of " + gettingTo + ", canceling GetToBlock"); + if (isSafeToCancel) { + onLostControl(); + } + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + if (calcFailed) { + logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock"); + if (isSafeToCancel) { + onLostControl(); + } + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 823f2091..2efeca03 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -66,7 +66,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro } @Override - public PathingCommand onTick() { + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { if (desiredQuantity > 0) { Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0); int curr = player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum(); @@ -77,6 +77,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro return null; } } + if (calcFailed) { + logDirect("Unable to find any path to " + mining + ", canceling Mine"); + cancel(); + return null; + } int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain baritone.getExecutor().execute(this::rescan); diff --git a/src/main/java/baritone/utils/ExampleBaritoneControl.java b/src/main/java/baritone/utils/ExampleBaritoneControl.java index d7c1cf89..74c17d60 100644 --- a/src/main/java/baritone/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/utils/ExampleBaritoneControl.java @@ -100,7 +100,6 @@ public class ExampleBaritoneControl extends Behavior implements Helper { public boolean runCommand(String msg0) { String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL PathingBehavior pathingBehavior = baritone.getPathingBehavior(); - PathingControlManager pathControl = baritone.getPathingControlManager(); CustomGoalProcess CGPgrey = baritone.getCustomGoalProcess(); List> toggleable = Baritone.settings().getAllValuesByType(Boolean.class); for (Settings.Setting setting : toggleable) { diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index 8165f1a1..bfb84d3c 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -33,6 +33,8 @@ import java.util.stream.Collectors; public class PathingControlManager { private final Baritone baritone; private final HashSet processes; // unGh + private IBaritoneProcess inControlLastTick; + private IBaritoneProcess inControlThisTick; public PathingControlManager(Baritone baritone) { this.baritone = baritone; @@ -54,7 +56,12 @@ public class PathingControlManager { } } + public IBaritoneProcess inControlThisTick() { + return inControlThisTick; + } + public void doTheThingWithTheStuff() { + inControlLastTick = inControlThisTick; PathingCommand cmd = doTheStuff(); if (cmd == null) { return; @@ -119,7 +126,7 @@ public class PathingControlManager { proc.onLostControl(); } } else { - exec = proc.onTick(); + exec = proc.onTick(proc == inControlLastTick && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel()); if (exec == null) { if (proc.isActive()) { throw new IllegalStateException(proc.displayName()); @@ -128,6 +135,7 @@ public class PathingControlManager { continue; } System.out.println("Executing command " + exec.commandType + " " + exec.goal + " from " + proc.displayName()); + inControlThisTick = proc; found = true; cancelOthers = !proc.isTemporary(); }