diff --git a/src/api/java/baritone/api/BaritoneAPI.java b/src/api/java/baritone/api/BaritoneAPI.java index 0ffd1e98..b9dbcd04 100644 --- a/src/api/java/baritone/api/BaritoneAPI.java +++ b/src/api/java/baritone/api/BaritoneAPI.java @@ -17,10 +17,16 @@ package baritone.api; -import baritone.api.behavior.*; +import baritone.api.behavior.ILookBehavior; +import baritone.api.behavior.IMemoryBehavior; +import baritone.api.behavior.IPathingBehavior; import baritone.api.cache.IWorldProvider; import baritone.api.cache.IWorldScanner; import baritone.api.event.listener.IGameEventListener; +import baritone.api.process.ICustomGoalProcess; +import baritone.api.process.IFollowProcess; +import baritone.api.process.IGetToBlockProcess; +import baritone.api.process.IMineProcess; import baritone.api.utils.SettingsUtil; import java.util.Iterator; @@ -36,20 +42,20 @@ import java.util.ServiceLoader; */ public final class BaritoneAPI { - private static final IBaritoneProvider baritone; + private static final IBaritone baritone; private static final Settings settings; static { ServiceLoader baritoneLoader = ServiceLoader.load(IBaritoneProvider.class); Iterator instances = baritoneLoader.iterator(); - baritone = instances.next(); + baritone = instances.next().getBaritoneForPlayer(null); // PWNAGE settings = new Settings(); SettingsUtil.readAndApply(settings); } - public static IFollowBehavior getFollowBehavior() { - return baritone.getFollowBehavior(); + public static IFollowProcess getFollowProcess() { + return baritone.getFollowProcess(); } public static ILookBehavior getLookBehavior() { @@ -60,8 +66,8 @@ public final class BaritoneAPI { return baritone.getMemoryBehavior(); } - public static IMineBehavior getMineBehavior() { - return baritone.getMineBehavior(); + public static IMineProcess getMineProcess() { + return baritone.getMineProcess(); } public static IPathingBehavior getPathingBehavior() { @@ -80,6 +86,14 @@ public final class BaritoneAPI { return baritone.getWorldScanner(); } + public static ICustomGoalProcess getCustomGoalProcess() { + return baritone.getCustomGoalProcess(); + } + + public static IGetToBlockProcess getGetToBlockProcess() { + return baritone.getGetToBlockProcess(); + } + public static void registerEventListener(IGameEventListener listener) { baritone.registerEventListener(listener); } diff --git a/src/api/java/baritone/api/IBaritone.java b/src/api/java/baritone/api/IBaritone.java new file mode 100644 index 00000000..aee9dead --- /dev/null +++ b/src/api/java/baritone/api/IBaritone.java @@ -0,0 +1,89 @@ +/* + * 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.api; + +import baritone.api.behavior.ILookBehavior; +import baritone.api.behavior.IMemoryBehavior; +import baritone.api.behavior.IPathingBehavior; +import baritone.api.cache.IWorldProvider; +import baritone.api.cache.IWorldScanner; +import baritone.api.event.listener.IGameEventListener; +import baritone.api.process.ICustomGoalProcess; +import baritone.api.process.IFollowProcess; +import baritone.api.process.IGetToBlockProcess; +import baritone.api.process.IMineProcess; + +/** + * @author Brady + * @since 9/29/2018 + */ +public interface IBaritone { + + /** + * @return The {@link IFollowProcess} instance + * @see IFollowProcess + */ + IFollowProcess getFollowProcess(); + + /** + * @return The {@link ILookBehavior} instance + * @see ILookBehavior + */ + ILookBehavior getLookBehavior(); + + /** + * @return The {@link IMemoryBehavior} instance + * @see IMemoryBehavior + */ + IMemoryBehavior getMemoryBehavior(); + + /** + * @return The {@link IMineProcess} instance + * @see IMineProcess + */ + IMineProcess getMineProcess(); + + /** + * @return The {@link IPathingBehavior} instance + * @see IPathingBehavior + */ + IPathingBehavior getPathingBehavior(); + + /** + * @return The {@link IWorldProvider} instance + * @see IWorldProvider + */ + IWorldProvider getWorldProvider(); + + /** + * @return The {@link IWorldScanner} instance + * @see IWorldScanner + */ + IWorldScanner getWorldScanner(); + + ICustomGoalProcess getCustomGoalProcess(); + + IGetToBlockProcess getGetToBlockProcess(); + + /** + * Registers a {@link IGameEventListener} with Baritone's "event bus". + * + * @param listener The listener + */ + void registerEventListener(IGameEventListener listener); +} diff --git a/src/api/java/baritone/api/IBaritoneProvider.java b/src/api/java/baritone/api/IBaritoneProvider.java index 88c4adff..745842ce 100644 --- a/src/api/java/baritone/api/IBaritoneProvider.java +++ b/src/api/java/baritone/api/IBaritoneProvider.java @@ -17,70 +17,19 @@ package baritone.api; -import baritone.api.behavior.*; -import baritone.api.cache.IWorldProvider; -import baritone.api.cache.IWorldScanner; -import baritone.api.event.listener.IGameEventListener; +import net.minecraft.client.entity.EntityPlayerSP; /** - * @author Brady - * @since 9/29/2018 + * @author Leijurv */ public interface IBaritoneProvider { /** - * @see IFollowBehavior + * Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be + * replaced with {@code #getBaritoneForUser(IBaritoneUser)} when {@code bot-system} is merged. * - * @return The {@link IFollowBehavior} instance + * @param player The player + * @return The {@link IBaritone} instance. */ - IFollowBehavior getFollowBehavior(); - - /** - * @see ILookBehavior - * - * @return The {@link ILookBehavior} instance - */ - ILookBehavior getLookBehavior(); - - /** - * @see IMemoryBehavior - * - * @return The {@link IMemoryBehavior} instance - */ - IMemoryBehavior getMemoryBehavior(); - - /** - * @see IMineBehavior - * - * @return The {@link IMineBehavior} instance - */ - IMineBehavior getMineBehavior(); - - /** - * @see IPathingBehavior - * - * @return The {@link IPathingBehavior} instance - */ - IPathingBehavior getPathingBehavior(); - - /** - * @see IWorldProvider - * - * @return The {@link IWorldProvider} instance - */ - IWorldProvider getWorldProvider(); - - /** - * @see IWorldScanner - * - * @return The {@link IWorldScanner} instance - */ - IWorldScanner getWorldScanner(); - - /** - * Registers a {@link IGameEventListener} with Baritone's "event bus". - * - * @param listener The listener - */ - void registerEventListener(IGameEventListener listener); + IBaritone getBaritoneForPlayer(EntityPlayerSP player); } diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 9cd69f95..8cf6a845 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -383,6 +383,11 @@ public class Settings { */ public Setting mineGoalUpdateInterval = new Setting<>(5); + /** + * While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)? + */ + public Setting mineScanDroppedItems = new Setting<>(true); + /** * Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore. *

diff --git a/src/api/java/baritone/api/behavior/IBehavior.java b/src/api/java/baritone/api/behavior/IBehavior.java index aee144e2..248148e7 100644 --- a/src/api/java/baritone/api/behavior/IBehavior.java +++ b/src/api/java/baritone/api/behavior/IBehavior.java @@ -18,10 +18,9 @@ package baritone.api.behavior; import baritone.api.event.listener.AbstractGameEventListener; -import baritone.api.utils.interfaces.Toggleable; /** * @author Brady * @since 9/23/2018 */ -public interface IBehavior extends AbstractGameEventListener, Toggleable {} +public interface IBehavior extends AbstractGameEventListener {} diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java index b5b5d63b..058a5dd8 100644 --- a/src/api/java/baritone/api/behavior/ILookBehavior.java +++ b/src/api/java/baritone/api/behavior/ILookBehavior.java @@ -33,7 +33,7 @@ public interface ILookBehavior extends IBehavior { * otherwise, it should be {@code false}; * * @param rotation The target rotations - * @param force Whether or not to "force" the rotations + * @param force Whether or not to "force" the rotations */ void updateTarget(Rotation rotation, boolean force); } diff --git a/src/api/java/baritone/api/behavior/IPathingBehavior.java b/src/api/java/baritone/api/behavior/IPathingBehavior.java index 7d88ae59..e9ebe405 100644 --- a/src/api/java/baritone/api/behavior/IPathingBehavior.java +++ b/src/api/java/baritone/api/behavior/IPathingBehavior.java @@ -39,35 +39,25 @@ public interface IPathingBehavior extends IBehavior { */ Optional ticksRemainingInSegment(); - /** - * Sets the pathing goal. - * - * @param goal The pathing goal - */ - void setGoal(Goal goal); - /** * @return The current pathing goal */ Goal getGoal(); - /** - * Begins pathing. Calculation will start in a new thread, and once completed, - * movement will commence. Returns whether or not the operation was successful. - * - * @return Whether or not the operation was successful - */ - boolean path(); - /** * @return Whether or not a path is currently being executed. */ boolean isPathing(); /** - * Cancels the pathing behavior or the current path calculation. + * Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path. + *

+ * Basically, "MAKE IT STOP". + * + * @return Whether or not the pathing behavior was canceled. All processes are guaranteed to be canceled, but the + * PathingBehavior might be in the middle of an uncancelable action like a parkour jump */ - void cancel(); + boolean cancelEverything(); /** * Returns the current path, from the current path executor, if there is one. diff --git a/src/api/java/baritone/api/cache/ICachedRegion.java b/src/api/java/baritone/api/cache/ICachedRegion.java index 5f9199fa..6b9048a5 100644 --- a/src/api/java/baritone/api/cache/ICachedRegion.java +++ b/src/api/java/baritone/api/cache/ICachedRegion.java @@ -29,11 +29,10 @@ public interface ICachedRegion extends IBlockTypeAccess { * however, the block coordinates should in on a scale from 0 to 511 (inclusive) * because region sizes are 512x512 blocks. * - * @see ICachedWorld#isCached(int, int) - * * @param blockX The block X coordinate * @param blockZ The block Z coordinate * @return Whether or not the specified XZ location is cached + * @see ICachedWorld#isCached(int, int) */ boolean isCached(int blockX, int blockZ); diff --git a/src/api/java/baritone/api/cache/ICachedWorld.java b/src/api/java/baritone/api/cache/ICachedWorld.java index f8196ebb..5e06a475 100644 --- a/src/api/java/baritone/api/cache/ICachedWorld.java +++ b/src/api/java/baritone/api/cache/ICachedWorld.java @@ -61,8 +61,8 @@ public interface ICachedWorld { * information that is returned by this method may not be up to date, because * older cached chunks can contain data that is much more likely to have changed. * - * @param block The special block to search for - * @param maximum The maximum number of position results to receive + * @param block The special block to search for + * @param maximum The maximum number of position results to receive * @param maxRegionDistanceSq The maximum region distance, squared * @return The locations found that match the special block */ diff --git a/src/api/java/baritone/api/cache/IWaypointCollection.java b/src/api/java/baritone/api/cache/IWaypointCollection.java index 051b199e..4dd80a3e 100644 --- a/src/api/java/baritone/api/cache/IWaypointCollection.java +++ b/src/api/java/baritone/api/cache/IWaypointCollection.java @@ -50,19 +50,17 @@ public interface IWaypointCollection { /** * Gets all of the waypoints that have the specified tag * - * @see IWaypointCollection#getAllWaypoints() - * * @param tag The tag * @return All of the waypoints with the specified tag + * @see IWaypointCollection#getAllWaypoints() */ Set getByTag(IWaypoint.Tag tag); /** * Gets all of the waypoints in this collection, regardless of the tag. * - * @see IWaypointCollection#getByTag(IWaypoint.Tag) - * * @return All of the waypoints in this collection + * @see IWaypointCollection#getByTag(IWaypoint.Tag) */ Set getAllWaypoints(); } diff --git a/src/api/java/baritone/api/pathing/calc/IPath.java b/src/api/java/baritone/api/pathing/calc/IPath.java index c9d58818..fddc0232 100644 --- a/src/api/java/baritone/api/pathing/calc/IPath.java +++ b/src/api/java/baritone/api/pathing/calc/IPath.java @@ -125,10 +125,9 @@ public interface IPath { * Cuts off this path using the min length and cutoff factor settings, and returns the resulting path. * Default implementation just returns this path, without the intended functionality. * + * @return The result of this cut-off operation * @see Settings#pathCutoffMinimumLength * @see Settings#pathCutoffFactor - * - * @return The result of this cut-off operation */ default IPath staticCutoff(Goal destination) { return this; diff --git a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java index cb7a000e..d01f6eee 100644 --- a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java +++ b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java @@ -20,6 +20,7 @@ package baritone.api.pathing.goals; import net.minecraft.util.math.BlockPos; import java.util.Arrays; +import java.util.Optional; /** * Useful for automated combat (retreating specifically) @@ -32,16 +33,26 @@ public class GoalRunAway implements Goal { private final double distanceSq; + private final Optional maintainY; + public GoalRunAway(double distance, BlockPos... from) { + this(distance, Optional.empty(), from); + } + + public GoalRunAway(double distance, Optional maintainY, BlockPos... from) { if (from.length == 0) { throw new IllegalArgumentException(); } this.from = from; this.distanceSq = distance * distance; + this.maintainY = maintainY; } @Override public boolean isInGoal(int x, int y, int z) { + if (maintainY.isPresent() && maintainY.get() != y) { + return false; + } for (BlockPos p : from) { int diffX = x - p.getX(); int diffZ = z - p.getZ(); @@ -62,11 +73,19 @@ public class GoalRunAway implements Goal { min = h; } } - return -min; + min = -min; + if (maintainY.isPresent()) { + min += GoalYLevel.calculate(maintainY.get(), y); + } + return min; } @Override public String toString() { - return "GoalRunAwayFrom" + Arrays.asList(from); + if (maintainY.isPresent()) { + return "GoalRunAwayFromMaintainY y=" + maintainY.get() + ", " + Arrays.asList(from); + } else { + return "GoalRunAwayFrom" + Arrays.asList(from); + } } } diff --git a/src/api/java/baritone/api/process/IBaritoneProcess.java b/src/api/java/baritone/api/process/IBaritoneProcess.java new file mode 100644 index 00000000..db7588ab --- /dev/null +++ b/src/api/java/baritone/api/process/IBaritoneProcess.java @@ -0,0 +1,99 @@ +/* + * 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.api.process; + +import baritone.api.IBaritone; +import baritone.api.behavior.IPathingBehavior; +import baritone.api.event.events.PathEvent; + +/** + * A process that can control the PathingBehavior. + *

+ * Differences between a baritone process and a behavior: + * Only one baritone process can be active at a time + * PathingBehavior can only be controlled by a process + *

+ * That's it actually + * + * @author leijurv + */ +public interface IBaritoneProcess { + + /** + * Would this process like to be in control? + * + * @return Whether or not this process would like to be in contorl. + */ + boolean isActive(); + + /** + * Called when this process is in control of pathing; Returns what Baritone should do. + * + * @param calcFailed {@code true} if this specific process was in control last tick, + * and there was a {@link PathEvent#CALC_FAILED} event last tick + * @param isSafeToCancel {@code true} if a {@link PathingCommandType#REQUEST_PAUSE} would happen this tick, and + * {@link IPathingBehavior} wouldn't actually tick. {@code false} if the PathExecutor reported + * pausing would be unsafe at the end of the last tick. Effectively "could request cancel or + * pause and have it happen right away" + * @return What the {@link IPathingBehavior} should do + */ + PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel); + + /** + * Returns whether or not this process should be treated as "temporary". + *

+ * If a process is temporary, it doesn't call {@link #onLostControl} on the processes that aren't execute because of it. + *

+ * For example, {@code CombatPauserProcess} and {@code PauseForAutoEatProcess} should return {@code true} always, + * and should return {@link #isActive} {@code true} only if there's something in range this tick, or if the player would like + * to start eating this tick. {@code PauseForAutoEatProcess} should only actually right click once onTick is called with + * {@code isSafeToCancel} true though. + * + * @return Whethor or not if this control is temporary + */ + boolean isTemporary(); + + /** + * Called if {@link #isActive} returned {@code true}, but another non-temporary + * process has control. Effectively the same as cancel. You want control but you + * don't get it. + */ + void onLostControl(); + + /** + * Used to determine which Process gains control if multiple are reporting {@link #isActive()}. The one + * that returns the highest value will be given control. + * + * @return A double representing the priority + */ + double priority(); + + /** + * Returns which bot this process is associated with. (5000000iq forward thinking) + * + * @return The Bot associated with this process + */ + IBaritone associatedWith(); + + /** + * Returns a user-friendly name for this process. Suitable for a HUD. + * + * @return A display name that's suitable for a HUD + */ + String displayName(); +} diff --git a/src/api/java/baritone/api/utils/interfaces/Toggleable.java b/src/api/java/baritone/api/process/ICustomGoalProcess.java similarity index 54% rename from src/api/java/baritone/api/utils/interfaces/Toggleable.java rename to src/api/java/baritone/api/process/ICustomGoalProcess.java index 359d6ee1..5084aff2 100644 --- a/src/api/java/baritone/api/utils/interfaces/Toggleable.java +++ b/src/api/java/baritone/api/process/ICustomGoalProcess.java @@ -15,40 +15,36 @@ * along with Baritone. If not, see . */ -package baritone.api.utils.interfaces; +package baritone.api.process; -/** - * @author Brady - * @since 8/20/2018 - */ -public interface Toggleable { +import baritone.api.pathing.goals.Goal; + +public interface ICustomGoalProcess extends IBaritoneProcess { /** - * Toggles the enabled state of this {@link Toggleable}. + * Sets the pathing goal * - * @return The new state. + * @param goal The new goal */ - boolean toggle(); + void setGoal(Goal goal); /** - * Sets the enabled state of this {@link Toggleable}. + * Starts path calculation and execution. + */ + void path(); + + /** + * @return The current goal + */ + Goal getGoal(); + + /** + * Sets the goal and begins the path execution. * - * @return The new state. + * @param goal The new goal */ - boolean setEnabled(boolean enabled); - - /** - * @return Whether or not this {@link Toggleable} object is enabled - */ - boolean isEnabled(); - - /** - * Called when the state changes from disabled to enabled - */ - default void onEnable() {} - - /** - * Called when the state changes from enabled to disabled - */ - default void onDisable() {} + default void setGoalAndPath(Goal goal) { + this.setGoal(goal); + this.path(); + } } diff --git a/src/api/java/baritone/api/behavior/IFollowBehavior.java b/src/api/java/baritone/api/process/IFollowProcess.java similarity index 88% rename from src/api/java/baritone/api/behavior/IFollowBehavior.java rename to src/api/java/baritone/api/process/IFollowProcess.java index c960fab3..cb9ecde6 100644 --- a/src/api/java/baritone/api/behavior/IFollowBehavior.java +++ b/src/api/java/baritone/api/process/IFollowProcess.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.api.behavior; +package baritone.api.process; import net.minecraft.entity.Entity; @@ -23,7 +23,7 @@ import net.minecraft.entity.Entity; * @author Brady * @since 9/23/2018 */ -public interface IFollowBehavior extends IBehavior { +public interface IFollowProcess extends IBaritoneProcess { /** * Set the follow target to the specified entity; @@ -40,5 +40,7 @@ public interface IFollowBehavior extends IBehavior { /** * Cancels the follow behavior, this will clear the current follow target. */ - void cancel(); + default void cancel() { + onLostControl(); + } } diff --git a/src/api/java/baritone/api/process/IGetToBlockProcess.java b/src/api/java/baritone/api/process/IGetToBlockProcess.java new file mode 100644 index 00000000..ff3dc9b5 --- /dev/null +++ b/src/api/java/baritone/api/process/IGetToBlockProcess.java @@ -0,0 +1,28 @@ +/* + * 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.api.process; + +import net.minecraft.block.Block; + +/** + * but it rescans the world every once in a while so it doesn't get fooled by its cache + */ +public interface IGetToBlockProcess extends IBaritoneProcess { + + void getToBlock(Block block); +} diff --git a/src/api/java/baritone/api/behavior/IMineBehavior.java b/src/api/java/baritone/api/process/IMineProcess.java similarity index 81% rename from src/api/java/baritone/api/behavior/IMineBehavior.java rename to src/api/java/baritone/api/process/IMineProcess.java index 78ab6d6a..7ebabc9c 100644 --- a/src/api/java/baritone/api/behavior/IMineBehavior.java +++ b/src/api/java/baritone/api/process/IMineProcess.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.api.behavior; +package baritone.api.process; import net.minecraft.block.Block; @@ -23,7 +23,7 @@ import net.minecraft.block.Block; * @author Brady * @since 9/23/2018 */ -public interface IMineBehavior extends IBehavior { +public interface IMineProcess extends IBaritoneProcess { /** * Begin to search for and mine the specified blocks until @@ -31,9 +31,9 @@ public interface IMineBehavior extends IBehavior { * are mined. This is based on the first target block to mine. * * @param quantity The number of items to get from blocks mined - * @param blocks The blocks to mine + * @param blocks The blocks to mine */ - void mine(int quantity, String... blocks); + void mineByName(int quantity, String... blocks); /** * Begin to search for and mine the specified blocks until @@ -41,7 +41,7 @@ public interface IMineBehavior extends IBehavior { * are mined. This is based on the first target block to mine. * * @param quantity The number of items to get from blocks mined - * @param blocks The blocks to mine + * @param blocks The blocks to mine */ void mine(int quantity, Block... blocks); @@ -50,8 +50,8 @@ public interface IMineBehavior extends IBehavior { * * @param blocks The blocks to mine */ - default void mine(String... blocks) { - this.mine(0, blocks); + default void mineByName(String... blocks) { + mineByName(0, blocks); } /** @@ -60,11 +60,13 @@ public interface IMineBehavior extends IBehavior { * @param blocks The blocks to mine */ default void mine(Block... blocks) { - this.mine(0, blocks); + mine(0, blocks); } /** * Cancels the current mining task */ - void cancel(); + default void cancel() { + onLostControl(); + } } diff --git a/src/api/java/baritone/api/process/PathingCommand.java b/src/api/java/baritone/api/process/PathingCommand.java new file mode 100644 index 00000000..2caef158 --- /dev/null +++ b/src/api/java/baritone/api/process/PathingCommand.java @@ -0,0 +1,56 @@ +/* + * 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.api.process; + +import baritone.api.pathing.goals.Goal; + +import java.util.Objects; + +/** + * @author leijurv + */ +public class PathingCommand { + + /** + * The target goal, may be {@code null}. + */ + public final Goal goal; + + /** + * The command type. + * + * @see PathingCommandType + */ + public final PathingCommandType commandType; + + /** + * Create a new {@link PathingCommand}. + * + * @param goal The target goal, may be {@code null}. + * @param commandType The command type, cannot be {@code null}. + * @throws NullPointerException if {@code commandType} is {@code null}. + * @see Goal + * @see PathingCommandType + */ + public PathingCommand(Goal goal, PathingCommandType commandType) { + Objects.requireNonNull(commandType); + + this.goal = goal; + this.commandType = commandType; + } +} diff --git a/src/api/java/baritone/api/process/PathingCommandType.java b/src/api/java/baritone/api/process/PathingCommandType.java new file mode 100644 index 00000000..f2336d26 --- /dev/null +++ b/src/api/java/baritone/api/process/PathingCommandType.java @@ -0,0 +1,55 @@ +/* + * 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.api.process; + +import baritone.api.Settings; + +public enum PathingCommandType { + + /** + * Set the goal and path. + *

+ * If you use this alongside a {@code null} goal, it will continue along its current path and current goal. + */ + SET_GOAL_AND_PATH, + + /** + * Has no effect on the current goal or path, just requests a pause + */ + REQUEST_PAUSE, + + /** + * Set the goal (regardless of {@code null}), and request a cancel of the current path (when safe) + */ + CANCEL_AND_SET_GOAL, + + /** + * Set the goal and path. + *

+ * If {@link Settings#cancelOnGoalInvalidation} is {@code true}, revalidate the + * current goal, and cancel if it's no longer valid, or if the new goal is {@code 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 {@code null}. + */ + FORCE_REVALIDATE_GOAL_AND_PATH +} diff --git a/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java b/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java index 4ffb5abc..8b3ea0af 100644 --- a/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java +++ b/src/launch/java/baritone/launch/mixins/MixinAnvilChunkLoader.java @@ -32,7 +32,9 @@ import java.io.File; @Mixin(AnvilChunkLoader.class) public class MixinAnvilChunkLoader implements IAnvilChunkLoader { - @Shadow @Final private File chunkSaveLocation; + @Shadow + @Final + private File chunkSaveLocation; @Override public File getChunkSaveLocation() { diff --git a/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java b/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java index 246c368e..6d5a5421 100644 --- a/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java +++ b/src/launch/java/baritone/launch/mixins/MixinChunkProviderServer.java @@ -31,7 +31,9 @@ import org.spongepowered.asm.mixin.Shadow; @Mixin(ChunkProviderServer.class) public class MixinChunkProviderServer implements IChunkProviderServer { - @Shadow @Final private IChunkLoader chunkLoader; + @Shadow + @Final + private IChunkLoader chunkLoader; @Override public IChunkLoader getChunkLoader() { diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java index 6623e1c2..8ca1743f 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntity.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -37,7 +37,8 @@ import static org.spongepowered.asm.lib.Opcodes.GETFIELD; @Mixin(Entity.class) public class MixinEntity { - @Shadow public float rotationYaw; + @Shadow + public float rotationYaw; /** * Event called to override the movement direction when walking diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java index dd121ead..a180df5c 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java @@ -85,6 +85,6 @@ public class MixinEntityPlayerSP { ) private boolean isAllowFlying(PlayerCapabilities capabilities) { PathingBehavior pathingBehavior = Baritone.INSTANCE.getPathingBehavior(); - return (!pathingBehavior.isEnabled() || !pathingBehavior.isPathing()) && capabilities.allowFlying; + return !pathingBehavior.isPathing() && capabilities.allowFlying; } } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java b/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java index 0fc1b246..174b9e3c 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityRenderer.java @@ -33,7 +33,7 @@ public class MixinEntityRenderer { at = @At( value = "INVOKE_STRING", target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", - args = { "ldc=hand" } + args = {"ldc=hand"} ) ) private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index 30d4109b..3826f0d7 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -83,10 +83,9 @@ public class MixinMinecraft { ) ) private void runTick(CallbackInfo ci) { - Minecraft mc = (Minecraft) (Object) this; Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent( EventState.PRE, - (mc.player != null && mc.world != null) + (player != null && world != null) ? TickEvent.Type.IN : TickEvent.Type.OUT )); @@ -142,7 +141,7 @@ public class MixinMinecraft { ) ) private boolean isAllowUserInput(GuiScreen screen) { - return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && Baritone.INSTANCE.getPathingBehavior().isEnabled() && player != null) || screen.allowUserInput; + return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && player != null) || screen.allowUserInput; } @Inject( diff --git a/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java b/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java index 3f5f297b..bf15bfc3 100644 --- a/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java +++ b/src/launch/java/baritone/launch/mixins/MixinNetworkManager.java @@ -77,7 +77,8 @@ public class MixinNetworkManager { ) private void preProcessPacket(ChannelHandlerContext context, Packet packet, CallbackInfo ci) { if (this.direction == EnumPacketDirection.CLIENTBOUND) { - Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet));} + Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet)); + } } @Inject( diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index a0d5ba84..69dc1b2a 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -18,16 +18,24 @@ package baritone; import baritone.api.BaritoneAPI; -import baritone.api.IBaritoneProvider; +import baritone.api.IBaritone; import baritone.api.Settings; import baritone.api.event.listener.IGameEventListener; -import baritone.behavior.*; +import baritone.behavior.Behavior; +import baritone.behavior.LookBehavior; +import baritone.behavior.MemoryBehavior; +import baritone.behavior.PathingBehavior; import baritone.cache.WorldProvider; import baritone.cache.WorldScanner; import baritone.event.GameEventHandler; +import baritone.process.CustomGoalProcess; +import baritone.process.FollowProcess; +import baritone.process.GetToBlockProcess; +import baritone.process.MineProcess; import baritone.utils.BaritoneAutoTest; import baritone.utils.ExampleBaritoneControl; import baritone.utils.InputOverrideHandler; +import baritone.utils.PathingControlManager; import net.minecraft.client.Minecraft; import java.io.File; @@ -44,7 +52,7 @@ import java.util.concurrent.TimeUnit; * @author Brady * @since 7/31/2018 10:50 PM */ -public enum Baritone implements IBaritoneProvider { +public enum Baritone implements IBaritone { /** * Singleton instance of this class @@ -57,33 +65,33 @@ public enum Baritone implements IBaritoneProvider { private boolean initialized; private GameEventHandler gameEventHandler; - private InputOverrideHandler inputOverrideHandler; private Settings settings; private File dir; - private ThreadPoolExecutor threadPool; + private List behaviors; private PathingBehavior pathingBehavior; private LookBehavior lookBehavior; private MemoryBehavior memoryBehavior; - private FollowBehavior followBehavior; - private MineBehavior mineBehavior; + private InputOverrideHandler inputOverrideHandler; - /** - * Whether or not Baritone is active - */ - private boolean active; + private FollowProcess followProcess; + private MineProcess mineProcess; + private GetToBlockProcess getToBlockProcess; + private CustomGoalProcess customGoalProcess; + + private PathingControlManager pathingControlManager; + + private static ThreadPoolExecutor threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()); Baritone() { - this.gameEventHandler = new GameEventHandler(); + this.gameEventHandler = new GameEventHandler(this); } public synchronized void init() { if (initialized) { return; } - this.threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()); - this.inputOverrideHandler = new InputOverrideHandler(); // Acquire the "singleton" instance of the settings directly from the API // We might want to change this... @@ -95,10 +103,18 @@ public enum Baritone implements IBaritoneProvider { pathingBehavior = new PathingBehavior(this); lookBehavior = new LookBehavior(this); memoryBehavior = new MemoryBehavior(this); - followBehavior = new FollowBehavior(this); - mineBehavior = new MineBehavior(this); + inputOverrideHandler = new InputOverrideHandler(this); new ExampleBaritoneControl(this); } + + this.pathingControlManager = new PathingControlManager(this); + { + followProcess = new FollowProcess(this); + mineProcess = new MineProcess(this); + customGoalProcess = new CustomGoalProcess(this); // very high iq + getToBlockProcess = new GetToBlockProcess(this); + } + if (BaritoneAutoTest.ENABLE_AUTO_TEST) { registerEventListener(BaritoneAutoTest.INSTANCE); } @@ -109,10 +125,13 @@ public enum Baritone implements IBaritoneProvider { } catch (IOException ignored) {} } - this.active = true; this.initialized = true; } + public PathingControlManager getPathingControlManager() { + return pathingControlManager; + } + public boolean isInitialized() { return this.initialized; } @@ -129,7 +148,7 @@ public enum Baritone implements IBaritoneProvider { return this.behaviors; } - public Executor getExecutor() { + public static Executor getExecutor() { return threadPool; } @@ -139,8 +158,18 @@ public enum Baritone implements IBaritoneProvider { } @Override - public FollowBehavior getFollowBehavior() { - return followBehavior; + public CustomGoalProcess getCustomGoalProcess() { + return customGoalProcess; + } + + @Override + public GetToBlockProcess getGetToBlockProcess() { // very very high iq + return getToBlockProcess; + } + + @Override + public FollowProcess getFollowProcess() { + return followProcess; } @Override @@ -154,8 +183,8 @@ public enum Baritone implements IBaritoneProvider { } @Override - public MineBehavior getMineBehavior() { - return mineBehavior; + public MineProcess getMineProcess() { + return mineProcess; } @Override @@ -178,10 +207,6 @@ public enum Baritone implements IBaritoneProvider { this.gameEventHandler.registerEventListener(listener); } - public boolean isActive() { - return this.active; - } - public Settings getSettings() { return this.settings; } @@ -190,7 +215,7 @@ public enum Baritone implements IBaritoneProvider { return Baritone.INSTANCE.settings; // yolo } - public File getDir() { - return this.dir; + public static File getDir() { + return Baritone.INSTANCE.dir; // should be static I guess } } diff --git a/src/main/java/baritone/BaritoneProvider.java b/src/main/java/baritone/BaritoneProvider.java index 2e9b3b30..a80dfe5e 100644 --- a/src/main/java/baritone/BaritoneProvider.java +++ b/src/main/java/baritone/BaritoneProvider.java @@ -17,59 +17,17 @@ package baritone; +import baritone.api.IBaritone; import baritone.api.IBaritoneProvider; -import baritone.api.behavior.*; -import baritone.api.cache.IWorldProvider; -import baritone.api.cache.IWorldScanner; -import baritone.api.event.listener.IGameEventListener; -import baritone.cache.WorldProvider; -import baritone.cache.WorldScanner; +import net.minecraft.client.entity.EntityPlayerSP; /** - * todo fix this cancer - * * @author Brady * @since 9/29/2018 */ public final class BaritoneProvider implements IBaritoneProvider { - @Override - public IFollowBehavior getFollowBehavior() { - return Baritone.INSTANCE.getFollowBehavior(); - } - - @Override - public ILookBehavior getLookBehavior() { - return Baritone.INSTANCE.getLookBehavior(); - } - - @Override - public IMemoryBehavior getMemoryBehavior() { - return Baritone.INSTANCE.getMemoryBehavior(); - } - - @Override - public IMineBehavior getMineBehavior() { - return Baritone.INSTANCE.getMineBehavior(); - } - - @Override - public IPathingBehavior getPathingBehavior() { - return Baritone.INSTANCE.getPathingBehavior(); - } - - @Override - public IWorldProvider getWorldProvider() { - return WorldProvider.INSTANCE; - } - - @Override - public IWorldScanner getWorldScanner() { - return WorldScanner.INSTANCE; - } - - @Override - public void registerEventListener(IGameEventListener listener) { - Baritone.INSTANCE.registerEventListener(listener); + public IBaritone getBaritoneForPlayer(EntityPlayerSP player) { + return Baritone.INSTANCE; // pwnage } } diff --git a/src/main/java/baritone/behavior/Behavior.java b/src/main/java/baritone/behavior/Behavior.java index 713e98f0..154897d1 100644 --- a/src/main/java/baritone/behavior/Behavior.java +++ b/src/main/java/baritone/behavior/Behavior.java @@ -30,49 +30,8 @@ public class Behavior implements IBehavior { public final Baritone baritone; - /** - * Whether or not this behavior is enabled - */ - private boolean enabled = true; - protected Behavior(Baritone baritone) { this.baritone = baritone; baritone.registerBehavior(this); } - - /** - * Toggles the enabled state of this {@link Behavior}. - * - * @return The new state. - */ - @Override - public final boolean toggle() { - return this.setEnabled(!this.isEnabled()); - } - - /** - * Sets the enabled state of this {@link Behavior}. - * - * @return The new state. - */ - @Override - public final boolean setEnabled(boolean enabled) { - if (enabled == this.enabled) { - return this.enabled; - } - if (this.enabled = enabled) { - this.onEnable(); - } else { - this.onDisable(); - } - return this.enabled; - } - - /** - * @return Whether or not this {@link Behavior} is active. - */ - @Override - public final boolean isEnabled() { - return this.enabled; - } } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 7a3a16b7..77c9839d 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -52,6 +52,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, private Goal goal; + private boolean safeToCancel; + private boolean pauseRequestedLastTick; + private boolean calcFailedLastTick; + private volatile boolean isPathCalcInProgress; private final Object pathCalcLock = new Object(); @@ -72,8 +76,9 @@ 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); + baritone.getGameEventHandler().onPathEvent(event); } } @@ -81,7 +86,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, public void onTick(TickEvent event) { dispatchEvents(); if (event.getType() == TickEvent.Type.OUT) { - cancel(); + secretInternalSegmentCancel(); + baritone.getPathingControlManager().cancelEverything(); return; } tickPath(); @@ -89,10 +95,17 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } private void tickPath() { + baritone.getPathingControlManager().doTheThingWithTheStuff(); + if (pauseRequestedLastTick && safeToCancel) { + pauseRequestedLastTick = false; + baritone.getInputOverrideHandler().clearAllKeys(); + BlockBreakHelper.stopBreakingBlock(); + return; + } if (current == null) { return; } - boolean safe = current.onTick(); + safeToCancel = current.onTick(); synchronized (pathPlanLock) { if (current.failed() || current.finished()) { current = null; @@ -134,7 +147,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return; } // at this point, we know current is in progress - if (safe && next != null && next.snipsnapifpossible()) { + if (safeToCancel && next != null && next.snipsnapifpossible()) { // a movement just ended; jump directly onto the next path logDebug("Splicing into planned next path early..."); queuePathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY); @@ -191,14 +204,13 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); } - @Override - public void setGoal(Goal goal) { + public void secretInternalSetGoal(Goal goal) { this.goal = goal; } - public boolean setGoalAndPath(Goal goal) { - setGoal(goal); - return path(); + public boolean secretInternalSetGoalAndPath(Goal goal) { + secretInternalSetGoal(goal); + return secretInternalPath(); } @Override @@ -226,17 +238,49 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, return this.current != null; } + public boolean isSafeToCancel() { + return current == null || safeToCancel; + } + + public void requestPause() { + pauseRequestedLastTick = true; + } + + public boolean cancelSegmentIfSafe() { + if (isSafeToCancel()) { + secretInternalSegmentCancel(); + return true; + } + return false; + } + @Override - public void cancel() { + public boolean cancelEverything() { + boolean doIt = isSafeToCancel(); + if (doIt) { + secretInternalSegmentCancel(); + } + baritone.getPathingControlManager().cancelEverything(); + return doIt; + } + + public boolean calcFailedLastTick() { // NOT exposed on public api + return calcFailedLastTick; + } + + // just cancel the current path + public void secretInternalSegmentCancel() { queuePathEvent(PathEvent.CANCELED); current = null; next = null; - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); + baritone.getInputOverrideHandler().clearAllKeys(); AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel); BlockBreakHelper.stopBreakingBlock(); } public void forceCancel() { // NOT exposed on public api + cancelEverything(); + secretInternalSegmentCancel(); isPathCalcInProgress = false; } @@ -245,8 +289,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, * * @return true if this call started path calculation, false if it was already calculating or executing a path */ - @Override - public boolean path() { + public boolean secretInternalPath() { if (goal == null) { return false; } @@ -327,7 +370,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, isPathCalcInProgress = true; } CalculationContext context = new CalculationContext(); // not safe to create on the other thread, it looks up a lot of stuff in minecraft - Baritone.INSTANCE.getExecutor().execute(() -> { + Baritone.getExecutor().execute(() -> { if (talkAboutIt) { logDebug("Starting to search for path from " + start + " to " + goal); } @@ -435,31 +478,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } } - public void revalidateGoal() { - if (!Baritone.settings().cancelOnGoalInvalidation.get()) { - return; - } - synchronized (pathPlanLock) { - if (current == null || goal == null) { - return; - } - Goal intended = current.getPath().getGoal(); - BlockPos end = current.getPath().getDest(); - if (intended.isInGoal(end) && !goal.isInGoal(end)) { - // this path used to end in the goal - // but the goal has changed, so there's no reason to continue... - cancel(); - } - } - } - @Override public void onRenderPass(RenderEvent event) { PathRenderer.render(event, this); } - - @Override - public void onDisable() { - Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); - } } diff --git a/src/main/java/baritone/cache/CachedWorld.java b/src/main/java/baritone/cache/CachedWorld.java index a5641eea..b1fcd6fd 100644 --- a/src/main/java/baritone/cache/CachedWorld.java +++ b/src/main/java/baritone/cache/CachedWorld.java @@ -67,8 +67,8 @@ public final class CachedWorld implements ICachedWorld, Helper { System.out.println("Cached world directory: " + directory); // Insert an invalid region element cachedRegions.put(0, null); - Baritone.INSTANCE.getExecutor().execute(new PackerThread()); - Baritone.INSTANCE.getExecutor().execute(() -> { + Baritone.getExecutor().execute(new PackerThread()); + Baritone.getExecutor().execute(() -> { try { Thread.sleep(30000); while (true) { diff --git a/src/main/java/baritone/cache/Waypoint.java b/src/main/java/baritone/cache/Waypoint.java index 00f4410a..19e574f9 100644 --- a/src/main/java/baritone/cache/Waypoint.java +++ b/src/main/java/baritone/cache/Waypoint.java @@ -42,9 +42,9 @@ public class Waypoint implements IWaypoint { * Constructor called when a Waypoint is read from disk, adds the creationTimestamp * as a parameter so that it is reserved after a waypoint is wrote to the disk. * - * @param name The waypoint name - * @param tag The waypoint tag - * @param location The waypoint location + * @param name The waypoint name + * @param tag The waypoint tag + * @param location The waypoint location * @param creationTimestamp When the waypoint was created */ Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) { diff --git a/src/main/java/baritone/cache/WorldData.java b/src/main/java/baritone/cache/WorldData.java index b489d933..36a239fa 100644 --- a/src/main/java/baritone/cache/WorldData.java +++ b/src/main/java/baritone/cache/WorldData.java @@ -43,7 +43,7 @@ public class WorldData implements IWorldData { } public void onClose() { - Baritone.INSTANCE.getExecutor().execute(() -> { + Baritone.getExecutor().execute(() -> { System.out.println("Started saving the world in a new thread"); cache.save(); }); diff --git a/src/main/java/baritone/cache/WorldProvider.java b/src/main/java/baritone/cache/WorldProvider.java index 2aef54c6..e3a53bba 100644 --- a/src/main/java/baritone/cache/WorldProvider.java +++ b/src/main/java/baritone/cache/WorldProvider.java @@ -74,8 +74,8 @@ public enum WorldProvider implements IWorldProvider, Helper { } else { //remote - directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP); - readme = Baritone.INSTANCE.getDir(); + directory = new File(Baritone.getDir(), mc.getCurrentServerData().serverIP); + readme = Baritone.getDir(); } // lol wtf is this baritone folder in my minecraft save? try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) { diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index 61756e33..b42b3e06 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -21,16 +21,13 @@ import baritone.Baritone; import baritone.api.event.events.*; import baritone.api.event.events.type.EventState; import baritone.api.event.listener.IGameEventListener; -import baritone.api.utils.interfaces.Toggleable; import baritone.cache.WorldProvider; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; -import baritone.utils.InputOverrideHandler; -import net.minecraft.client.settings.KeyBinding; import net.minecraft.world.chunk.Chunk; -import org.lwjgl.input.Keyboard; import java.util.ArrayList; +import java.util.List; /** * @author Brady @@ -38,57 +35,32 @@ import java.util.ArrayList; */ public final class GameEventHandler implements IGameEventListener, Helper { - private final ArrayList listeners = new ArrayList<>(); + private final Baritone baritone; + + private final List listeners = new ArrayList<>(); + + public GameEventHandler(Baritone baritone) { + this.baritone = baritone; + } @Override public final void onTick(TickEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onTick(event); - } - }); + listeners.forEach(l -> l.onTick(event)); } @Override public final void onPlayerUpdate(PlayerUpdateEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onPlayerUpdate(event); - } - }); + listeners.forEach(l -> l.onPlayerUpdate(event)); } @Override public final void onProcessKeyBinds() { - InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler(); - - // Simulate the key being held down this tick - for (InputOverrideHandler.Input input : InputOverrideHandler.Input.values()) { - KeyBinding keyBinding = input.getKeyBinding(); - - if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) { - int keyCode = keyBinding.getKeyCode(); - - if (keyCode < Keyboard.KEYBOARD_SIZE) { - KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode); - } - } - } - - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onProcessKeyBinds(); - } - }); + listeners.forEach(IGameEventListener::onProcessKeyBinds); } @Override public final void onSendChatMessage(ChatEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onSendChatMessage(event); - } - }); + listeners.forEach(l -> l.onSendChatMessage(event)); } @Override @@ -114,20 +86,12 @@ public final class GameEventHandler implements IGameEventListener, Helper { } - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onChunkEvent(event); - } - }); + listeners.forEach(l -> l.onChunkEvent(event)); } @Override public final void onRenderPass(RenderEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onRenderPass(event); - } - }); + listeners.forEach(l -> l.onRenderPass(event)); } @Override @@ -143,72 +107,41 @@ public final class GameEventHandler implements IGameEventListener, Helper { } } - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onWorldEvent(event); - } - }); + listeners.forEach(l -> l.onWorldEvent(event)); } @Override public final void onSendPacket(PacketEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onSendPacket(event); - } - }); + listeners.forEach(l -> l.onSendPacket(event)); } @Override public final void onReceivePacket(PacketEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onReceivePacket(event); - } - }); + listeners.forEach(l -> l.onReceivePacket(event)); } @Override public void onPlayerRotationMove(RotationMoveEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onPlayerRotationMove(event); - } - }); + listeners.forEach(l -> l.onPlayerRotationMove(event)); } @Override public void onBlockInteract(BlockInteractEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onBlockInteract(event); - } - }); + listeners.forEach(l -> l.onBlockInteract(event)); } @Override public void onPlayerDeath() { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onPlayerDeath(); - } - }); + listeners.forEach(IGameEventListener::onPlayerDeath); } @Override public void onPathEvent(PathEvent event) { - listeners.forEach(l -> { - if (canDispatch(l)) { - l.onPathEvent(event); - } - }); + listeners.forEach(l -> l.onPathEvent(event)); } public final void registerEventListener(IGameEventListener listener) { this.listeners.add(listener); } - private boolean canDispatch(IGameEventListener listener) { - return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled(); - } } diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index aacd7f9f..fb316ed3 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -24,14 +24,12 @@ import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; import baritone.api.utils.VecUtils; -import baritone.utils.BlockBreakHelper; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; import baritone.utils.InputOverrideHandler; import net.minecraft.block.BlockLiquid; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.RayTraceResult; import net.minecraft.world.chunk.EmptyChunk; import java.util.ArrayList; @@ -115,52 +113,31 @@ public abstract class Movement implements IMovement, Helper, MovementHelper { @Override public MovementStatus update() { player().capabilities.isFlying = false; - MovementState latestState = updateState(currentState); + currentState = updateState(currentState); if (MovementHelper.isLiquid(playerFeet())) { - latestState.setInput(Input.JUMP, true); + currentState.setInput(Input.JUMP, true); } if (player().isEntityInsideOpaqueBlock()) { - latestState.setInput(Input.CLICK_LEFT, true); + currentState.setInput(Input.CLICK_LEFT, true); } // If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations - latestState.getTarget().getRotation().ifPresent(rotation -> + currentState.getTarget().getRotation().ifPresent(rotation -> Baritone.INSTANCE.getLookBehavior().updateTarget( rotation, - latestState.getTarget().hasToForceRotations())); + currentState.getTarget().hasToForceRotations())); // TODO: calculate movement inputs from latestState.getGoal().position // latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE - this.didBreakLastTick = false; - - latestState.getInputStates().forEach((input, forced) -> { - if (Baritone.settings().leftClickWorkaround.get()) { - RayTraceResult trace = mc.objectMouseOver; - boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK; - boolean isLeftClick = forced && input == Input.CLICK_LEFT; - - // If we're forcing left click, we're in a gui screen, and we're looking - // at a block, break the block without a direct game input manipulation. - if (mc.currentScreen != null && isLeftClick && isBlockTrace) { - BlockBreakHelper.tryBreakBlock(trace.getBlockPos(), trace.sideHit); - this.didBreakLastTick = true; - return; - } - } + currentState.getInputStates().forEach((input, forced) -> { Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced); }); - latestState.getInputStates().replaceAll((input, forced) -> false); - - if (!this.didBreakLastTick) { - BlockBreakHelper.stopBreakingBlock(); - } - - currentState = latestState; + currentState.getInputStates().replaceAll((input, forced) -> false); // If the current status indicates a completed movement if (currentState.getStatus().isComplete()) { - onFinish(latestState); + Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); } return currentState.getStatus(); @@ -218,20 +195,6 @@ public abstract class Movement implements IMovement, Helper, MovementHelper { return dest; } - /** - * Run cleanup on state finish and declare success. - */ - public void onFinish(MovementState state) { - state.getInputStates().replaceAll((input, forced) -> false); - state.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced)); - } - - public void cancel() { - currentState.getInputStates().replaceAll((input, forced) -> false); - currentState.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced)); - currentState.setStatus(MovementStatus.CANCELED); - } - @Override public void reset() { currentState = new MovementState().setStatus(MovementStatus.PREPPING); diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java new file mode 100644 index 00000000..98c700e3 --- /dev/null +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -0,0 +1,115 @@ +/* + * 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.process; + +import baritone.Baritone; +import baritone.api.pathing.goals.Goal; +import baritone.api.process.ICustomGoalProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; +import baritone.utils.BaritoneProcessHelper; + +import java.util.Objects; + +/** + * As set by ExampleBaritoneControl or something idk + * + * @author leijurv + */ +public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess { + + /** + * The current goal + */ + private Goal goal; + + /** + * The current process state. + * + * @see State + */ + private State state; + + public CustomGoalProcess(Baritone baritone) { + super(baritone, 3); + } + + @Override + public void setGoal(Goal goal) { + this.goal = goal; + this.state = State.GOAL_SET; + } + + @Override + public void path() { + this.state = State.PATH_REQUESTED; + } + + @Override + public Goal getGoal() { + return this.goal; + } + + @Override + public boolean isActive() { + return this.state != State.NONE; + } + + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + switch (this.state) { + case GOAL_SET: + if (!baritone.getPathingBehavior().isPathing() && Objects.equals(baritone.getPathingBehavior().getGoal(), this.goal)) { + this.state = State.NONE; + } + return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL); + case PATH_REQUESTED: + PathingCommand ret = new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); + this.state = State.EXECUTING; + return ret; + case EXECUTING: + if (calcFailed) { + onLostControl(); + } + if (this.goal == null || this.goal.isInGoal(playerFeet())) { + onLostControl(); // we're there xd + } + return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); + default: + throw new IllegalStateException(); + } + } + + @Override + public void onLostControl() { + this.state = State.NONE; + this.goal = null; + } + + @Override + public String displayName() { + return "Custom Goal " + this.goal; + } + + protected enum State { + NONE, + GOAL_SET, + PATH_REQUESTED, + EXECUTING + } +} diff --git a/src/main/java/baritone/behavior/FollowBehavior.java b/src/main/java/baritone/process/FollowProcess.java similarity index 65% rename from src/main/java/baritone/behavior/FollowBehavior.java rename to src/main/java/baritone/process/FollowProcess.java index 00fbe1c5..f662fa1d 100644 --- a/src/main/java/baritone/behavior/FollowBehavior.java +++ b/src/main/java/baritone/process/FollowProcess.java @@ -15,14 +15,15 @@ * along with Baritone. If not, see . */ -package baritone.behavior; +package baritone.process; import baritone.Baritone; -import baritone.api.behavior.IFollowBehavior; -import baritone.api.event.events.TickEvent; import baritone.api.pathing.goals.GoalNear; import baritone.api.pathing.goals.GoalXZ; -import baritone.utils.Helper; +import baritone.api.process.IFollowProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; +import baritone.utils.BaritoneProcessHelper; import net.minecraft.entity.Entity; import net.minecraft.util.math.BlockPos; @@ -31,23 +32,16 @@ import net.minecraft.util.math.BlockPos; * * @author leijurv */ -public final class FollowBehavior extends Behavior implements IFollowBehavior, Helper { +public final class FollowProcess extends BaritoneProcessHelper implements IFollowProcess { private Entity following; - public FollowBehavior(Baritone baritone) { - super(baritone); + public FollowProcess(Baritone baritone) { + super(baritone, 1); } @Override - public void onTick(TickEvent event) { - if (event.getType() == TickEvent.Type.OUT) { - following = null; - return; - } - if (following == null) { - return; - } + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { // lol this is trashy but it works BlockPos pos; if (Baritone.settings().followOffsetDistance.get() == 0) { @@ -56,9 +50,22 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get()); pos = new BlockPos(g.getX(), following.posY, g.getZ()); } - baritone.getPathingBehavior().setGoal(new GoalNear(pos, Baritone.settings().followRadius.get())); - ((PathingBehavior) baritone.getPathingBehavior()).revalidateGoal(); - baritone.getPathingBehavior().path(); + return new PathingCommand(new GoalNear(pos, Baritone.settings().followRadius.get()), PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH); + } + + @Override + public boolean isActive() { + return following != null; + } + + @Override + public void onLostControl() { + following = null; + } + + @Override + public String displayName() { + return "Follow " + following; } @Override @@ -70,10 +77,4 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H public Entity following() { return this.following; } - - @Override - public void cancel() { - baritone.getPathingBehavior().cancel(); - follow(null); - } } diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java new file mode 100644 index 00000000..94e02e03 --- /dev/null +++ b/src/main/java/baritone/process/GetToBlockProcess.java @@ -0,0 +1,99 @@ +/* + * 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.process; + +import baritone.Baritone; +import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalComposite; +import baritone.api.pathing.goals.GoalGetToBlock; +import baritone.api.process.IGetToBlockProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; +import baritone.utils.BaritoneProcessHelper; +import net.minecraft.block.Block; +import net.minecraft.util.math.BlockPos; + +import java.util.Collections; +import java.util.List; + +public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess { + private Block gettingTo; + private List knownLocations; + + private int tickCount = 0; + + public GetToBlockProcess(Baritone baritone) { + super(baritone, 2); + } + + @Override + public void getToBlock(Block block) { + gettingTo = block; + rescan(); + } + + @Override + public boolean isActive() { + return gettingTo != null; + } + + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + if (knownLocations == null) { + rescan(); + } + if (knownLocations.isEmpty()) { + 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 + Baritone.getExecutor().execute(this::rescan); + } + Goal goal = new GoalComposite(knownLocations.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)); + if (goal.isInGoal(playerFeet())) { + onLostControl(); + } + return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH); + } + + @Override + public void onLostControl() { + gettingTo = null; + knownLocations = null; + } + + @Override + public String displayName() { + return "Get To Block " + gettingTo; + } + + private void rescan() { + knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64, world()); + } +} \ No newline at end of file diff --git a/src/main/java/baritone/behavior/MineBehavior.java b/src/main/java/baritone/process/MineProcess.java similarity index 67% rename from src/main/java/baritone/behavior/MineBehavior.java rename to src/main/java/baritone/process/MineProcess.java index 4d37f5ff..bfceac75 100644 --- a/src/main/java/baritone/behavior/MineBehavior.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -15,25 +15,30 @@ * along with Baritone. If not, see . */ -package baritone.behavior; +package baritone.process; import baritone.Baritone; -import baritone.api.behavior.IMineBehavior; -import baritone.api.event.events.TickEvent; import baritone.api.pathing.goals.*; +import baritone.api.process.IMineProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; import baritone.api.utils.RotationUtils; import baritone.cache.CachedChunk; import baritone.cache.ChunkPacker; import baritone.cache.WorldProvider; import baritone.cache.WorldScanner; import baritone.pathing.movement.MovementHelper; +import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraft.world.chunk.EmptyChunk; import java.util.*; @@ -44,26 +49,27 @@ import java.util.stream.Collectors; * * @author leijurv */ -public final class MineBehavior extends Behavior implements IMineBehavior, Helper { +public final class MineProcess extends BaritoneProcessHelper implements IMineProcess { + + private static final int ORE_LOCATIONS_COUNT = 64; private List mining; private List knownOreLocations; private BlockPos branchPoint; private int desiredQuantity; + private int tickCount; - public MineBehavior(Baritone baritone) { - super(baritone); + public MineProcess(Baritone baritone) { + super(baritone, 0); } @Override - public void onTick(TickEvent event) { - if (event.getType() == TickEvent.Type.OUT) { - cancel(); - return; - } - if (mining == null) { - return; - } + public boolean isActive() { + return mining != null; + } + + @Override + 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(); @@ -71,35 +77,53 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe if (curr >= desiredQuantity) { logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1))); cancel(); - return; + 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 && event.getCount() % mineGoalUpdateInterval == 0) { - Baritone.INSTANCE.getExecutor().execute(this::rescan); + if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain + baritone.getExecutor().execute(this::rescan); } if (Baritone.settings().legitMine.get()) { addNearby(); } - updateGoal(); - baritone.getPathingBehavior().revalidateGoal(); + Goal goal = updateGoal(); + if (goal == null) { + // none in range + // maybe say something in chat? (ahem impact) + cancel(); + return null; + } + return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH); } - private void updateGoal() { - if (mining == null) { - return; - } + @Override + public void onLostControl() { + mine(0, (Block[]) null); + } + + @Override + public String displayName() { + return "Mine " + mining; + } + + private Goal updateGoal() { List locs = knownOreLocations; if (!locs.isEmpty()) { - List locs2 = prune(new ArrayList<>(locs), mining, 64); + List locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, world()); // 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 - baritone.getPathingBehavior().setGoalAndPath(new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new))); + Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new)); knownOreLocations = locs2; - return; + return goal; } // we don't know any ore locations at the moment if (!Baritone.settings().legitMine.get()) { - return; + return null; } // only in non-Xray mode (aka legit mode) do we do this if (branchPoint == null) { @@ -108,8 +132,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe // cool, path is over and we are at desired y branchPoint = playerFeet(); } else { - baritone.getPathingBehavior().setGoalAndPath(new GoalYLevel(y)); - return; + return new GoalYLevel(y); } } @@ -117,7 +140,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe // TODO mine 1x1 shafts to either side branchPoint = branchPoint.north(10); } - baritone.getPathingBehavior().setGoalAndPath(new GoalBlock(branchPoint)); + return new GoalBlock(branchPoint); } private void rescan() { @@ -127,10 +150,11 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe if (Baritone.settings().legitMine.get()) { return; } - List locs = searchWorld(mining, 64); + List locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world()); + locs.addAll(droppedItemsScan(mining, world())); if (locs.isEmpty()) { logDebug("No locations for " + mining + " known, cancelling"); - mine(0, (String[]) null); + cancel(); return; } knownOreLocations = locs; @@ -158,7 +182,30 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe } } - public List searchWorld(List mining, int max) { + public static List droppedItemsScan(List mining, World world) { + if (!Baritone.settings().mineScanDroppedItems.get()) { + return new ArrayList<>(); + } + Set searchingFor = new HashSet<>(); + for (Block block : mining) { + Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0); + Item ore = Item.getItemFromBlock(block); + searchingFor.add(drop); + searchingFor.add(ore); + } + List ret = new ArrayList<>(); + for (Entity entity : world.loadedEntityList) { + if (entity instanceof EntityItem) { + EntityItem ei = (EntityItem) entity; + if (searchingFor.contains(ei.getItem().getItem())) { + ret.add(new BlockPos(entity)); + } + } + } + return ret; + } + + public static List searchWorld(List mining, int max, World world) { List locs = new ArrayList<>(); List uninteresting = new ArrayList<>(); //long b = System.currentTimeMillis(); @@ -178,7 +225,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26)); //System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms"); } - return prune(locs, mining, max); + return prune(locs, mining, max, world); } public void addNearby() { @@ -194,18 +241,19 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe } } } - knownOreLocations = prune(knownOreLocations, mining, 64); + knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT, world()); } - public List prune(List locs2, List mining, int max) { + public static List prune(List locs2, List mining, int max, World world) { + List dropped = droppedItemsScan(mining, world); List locs = locs2 .stream() // remove any that are within loaded chunks that aren't actually what we want - .filter(pos -> world().getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock())) + .filter(pos -> world.getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()) || dropped.contains(pos)) // remove any that are implausible to mine (encased in bedrock, or touching lava) - .filter(MineBehavior::plausibleToBreak) + .filter(MineProcess::plausibleToBreak) .sorted(Comparator.comparingDouble(Helper.HELPER.playerFeet()::distanceSq)) .collect(Collectors.toList()); @@ -225,13 +273,8 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe } @Override - public void mine(int quantity, String... blocks) { - this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList()); - this.desiredQuantity = quantity; - this.knownOreLocations = new ArrayList<>(); - this.branchPoint = null; - rescan(); - updateGoal(); + public void mineByName(int quantity, String... blocks) { + mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).toArray(Block[]::new)); } @Override @@ -241,12 +284,5 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe this.knownOreLocations = new ArrayList<>(); this.branchPoint = null; rescan(); - updateGoal(); - } - - @Override - public void cancel() { - mine(0, (String[]) null); - baritone.getPathingBehavior().cancel(); } } diff --git a/src/main/java/baritone/utils/BaritoneAutoTest.java b/src/main/java/baritone/utils/BaritoneAutoTest.java index 70e1a70e..4aee4bd4 100644 --- a/src/main/java/baritone/utils/BaritoneAutoTest.java +++ b/src/main/java/baritone/utils/BaritoneAutoTest.java @@ -105,8 +105,7 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper { } // Setup Baritone's pathing goal and (if needed) begin pathing - Baritone.INSTANCE.getPathingBehavior().setGoal(GOAL); - Baritone.INSTANCE.getPathingBehavior().path(); + Baritone.INSTANCE.getCustomGoalProcess().setGoalAndPath(GOAL); // If we have reached our goal, print a message and safely close the game if (GOAL.isInGoal(playerFeet())) { diff --git a/src/main/java/baritone/utils/BaritoneProcessHelper.java b/src/main/java/baritone/utils/BaritoneProcessHelper.java new file mode 100644 index 00000000..d01e815d --- /dev/null +++ b/src/main/java/baritone/utils/BaritoneProcessHelper.java @@ -0,0 +1,53 @@ +/* + * 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.utils; + +import baritone.Baritone; +import baritone.api.process.IBaritoneProcess; + +public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper { + public static final double DEFAULT_PRIORITY = 0; + + protected final Baritone baritone; + private final double priority; + + public BaritoneProcessHelper(Baritone baritone) { + this(baritone, DEFAULT_PRIORITY); + } + + public BaritoneProcessHelper(Baritone baritone, double priority) { + this.baritone = baritone; + this.priority = priority; + baritone.getPathingControlManager().registerProcess(this); + } + + @Override + public Baritone associatedWith() { + return baritone; + } + + @Override + public boolean isTemporary() { + return false; + } + + @Override + public double priority() { + return priority; + } +} diff --git a/src/main/java/baritone/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java index 1bc4a44a..b1e9ae53 100644 --- a/src/main/java/baritone/utils/BlockBreakHelper.java +++ b/src/main/java/baritone/utils/BlockBreakHelper.java @@ -20,6 +20,7 @@ package baritone.utils; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.RayTraceResult; /** * @author Brady @@ -32,6 +33,7 @@ public final class BlockBreakHelper implements Helper { * between attempts, then we re-initialize the breaking process. */ private static BlockPos lastBlock; + private static boolean didBreakLastTick; private BlockBreakHelper() {} @@ -48,7 +50,23 @@ public final class BlockBreakHelper implements Helper { public static void stopBreakingBlock() { if (mc.playerController != null) { mc.playerController.resetBlockRemoving(); - } + } lastBlock = null; } + + public static boolean tick(boolean isLeftClick) { + RayTraceResult trace = mc.objectMouseOver; + boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK; + + // If we're forcing left click, we're in a gui screen, and we're looking + // at a block, break the block without a direct game input manipulation. + if (mc.currentScreen != null && isLeftClick && isBlockTrace) { + tryBreakBlock(trace.getBlockPos(), trace.sideHit); + didBreakLastTick = true; + } else if (didBreakLastTick) { + stopBreakingBlock(); + didBreakLastTick = false; + } + return !didBreakLastTick && isLeftClick; + } } diff --git a/src/main/java/baritone/utils/ExampleBaritoneControl.java b/src/main/java/baritone/utils/ExampleBaritoneControl.java index 77dbcef5..e908d1c4 100644 --- a/src/main/java/baritone/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/utils/ExampleBaritoneControl.java @@ -33,6 +33,7 @@ import baritone.cache.WorldProvider; import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.Movement; import baritone.pathing.movement.Moves; +import baritone.process.CustomGoalProcess; import net.minecraft.block.Block; import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.entity.Entity; @@ -73,7 +74,6 @@ public class ExampleBaritoneControl extends Behavior implements Helper { "sethome - Sets \"home\"\n" + "home - Paths towards \"home\" \n" + "costs - (debug) all movement costs from current location\n" + - "pause - Toggle pause\n" + "damn - Daniel "; public ExampleBaritoneControl(Baritone baritone) { @@ -100,6 +100,7 @@ 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(); + CustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); List> toggleable = Baritone.settings().getAllValuesByType(Boolean.class); for (Settings.Setting setting : toggleable) { if (msg.equalsIgnoreCase(setting.getName())) { @@ -187,21 +188,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper { logDirect("unable to parse integer " + ex); return true; } - pathingBehavior.setGoal(goal); + customGoalProcess.setGoal(goal); logDirect("Goal: " + goal); return true; } if (msg.equals("path")) { - if (!pathingBehavior.path()) { - if (pathingBehavior.getGoal() == null) { - logDirect("No goal."); - } else { - if (pathingBehavior.getGoal().isInGoal(playerFeet())) { - logDirect("Already in goal"); - } else { - logDirect("Currently executing a path. Please cancel it first."); - } - } + if (pathingBehavior.getGoal() == null) { + logDirect("No goal."); + } else if (pathingBehavior.getGoal().isInGoal(playerFeet())) { + logDirect("Already in goal"); + } else if (pathingBehavior.isPathing()) { + logDirect("Currently executing a path. Please cancel it first."); + } else { + customGoalProcess.setGoalAndPath(pathingBehavior.getGoal()); } return true; } @@ -223,21 +222,16 @@ public class ExampleBaritoneControl extends Behavior implements Helper { return true; } if (msg.equals("axis")) { - pathingBehavior.setGoal(new GoalAxis()); - pathingBehavior.path(); + customGoalProcess.setGoalAndPath(new GoalAxis()); return true; } if (msg.equals("cancel") || msg.equals("stop")) { - baritone.getMineBehavior().cancel(); - baritone.getFollowBehavior().cancel(); - pathingBehavior.cancel(); + pathingBehavior.cancelEverything(); logDirect("ok canceled"); return true; } if (msg.equals("forcecancel")) { - baritone.getMineBehavior().cancel(); - baritone.getFollowBehavior().cancel(); - pathingBehavior.cancel(); + pathingBehavior.cancelEverything(); AbstractNodeCostSearch.forceCancel(); pathingBehavior.forceCancel(); logDirect("ok force canceled"); @@ -260,15 +254,12 @@ public class ExampleBaritoneControl extends Behavior implements Helper { logDirect("Inverting goal of player feet"); runAwayFrom = playerFeet(); } - pathingBehavior.setGoal(new GoalRunAway(1, runAwayFrom) { + customGoalProcess.setGoalAndPath(new GoalRunAway(1, runAwayFrom) { @Override public boolean isInGoal(int x, int y, int z) { return false; } }); - if (!pathingBehavior.path()) { - logDirect("Currently executing a path. Please cancel it first."); - } return true; } if (msg.startsWith("follow")) { @@ -288,7 +279,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper { logDirect("Not found"); return true; } - baritone.getFollowBehavior().follow(toFollow.get()); + baritone.getFollowProcess().follow(toFollow.get()); logDirect("Following " + toFollow.get()); return true; } @@ -320,7 +311,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper { int quantity = Integer.parseInt(blockTypes[1]); Block block = ChunkPacker.stringToBlock(blockTypes[0]); Objects.requireNonNull(block); - baritone.getMineBehavior().mine(quantity, block); + baritone.getMineProcess().mine(quantity, block); logDirect("Will mine " + quantity + " " + blockTypes[0]); return true; } catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {} @@ -331,14 +322,14 @@ public class ExampleBaritoneControl extends Behavior implements Helper { } } - baritone.getMineBehavior().mine(0, blockTypes); + baritone.getMineProcess().mineByName(0, blockTypes); logDirect("Started mining blocks of type " + Arrays.toString(blockTypes)); return true; } if (msg.startsWith("thisway")) { try { Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim())); - pathingBehavior.setGoal(goal); + customGoalProcess.setGoal(goal); logDirect("Goal: " + goal); } catch (NumberFormatException ex) { logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double."); @@ -407,13 +398,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper { return true; } } else { - List locs = baritone.getMineBehavior().searchWorld(Collections.singletonList(block), 64); - if (locs.isEmpty()) { - logDirect("No locations for " + mining + " known, cancelling"); - return true; - } - pathingBehavior.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new))); - pathingBehavior.path(); + baritone.getGetToBlockProcess().getToBlock(block); return true; } } else { @@ -424,10 +409,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper { } } Goal goal = new GoalBlock(waypoint.getLocation()); - pathingBehavior.setGoal(goal); - if (!pathingBehavior.path() && !goal.isInGoal(playerFeet())) { - logDirect("Currently executing a path. Please cancel it first."); - } + customGoalProcess.setGoalAndPath(goal); return true; } if (msg.equals("spawn") || msg.equals("bed")) { @@ -437,10 +419,10 @@ public class ExampleBaritoneControl extends Behavior implements Helper { // for some reason the default spawnpoint is underground sometimes Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ()); logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal); - pathingBehavior.setGoal(goal); + customGoalProcess.setGoalAndPath(goal); } else { - Goal goal = new GoalBlock(waypoint.getLocation()); - pathingBehavior.setGoal(goal); + Goal goal = new GoalGetToBlock(waypoint.getLocation()); + customGoalProcess.setGoalAndPath(goal); logDirect("Set goal to most recent bed " + goal); } return true; @@ -456,8 +438,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper { logDirect("home not saved"); } else { Goal goal = new GoalBlock(waypoint.getLocation()); - pathingBehavior.setGoal(goal); - pathingBehavior.path(); + customGoalProcess.setGoalAndPath(goal); logDirect("Going to saved home " + goal); } return true; @@ -479,11 +460,6 @@ public class ExampleBaritoneControl extends Behavior implements Helper { } return true; } - if (msg.equals("pause")) { - boolean enabled = pathingBehavior.toggle(); - logDirect("Pathing Behavior has " + (enabled ? "resumed" : "paused") + "."); - return true; - } if (msg.equals("damn")) { logDirect("daniel"); } diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java index 9cf7d1da..b42b0ee1 100755 --- a/src/main/java/baritone/utils/InputOverrideHandler.java +++ b/src/main/java/baritone/utils/InputOverrideHandler.java @@ -17,7 +17,11 @@ package baritone.utils; +import baritone.Baritone; +import baritone.api.event.events.TickEvent; +import baritone.behavior.Behavior; import net.minecraft.client.settings.KeyBinding; +import org.lwjgl.input.Keyboard; import java.util.HashMap; import java.util.Map; @@ -30,7 +34,11 @@ import java.util.Map; * @author Brady * @since 7/31/2018 11:20 PM */ -public final class InputOverrideHandler implements Helper { +public final class InputOverrideHandler extends Behavior implements Helper { + + public InputOverrideHandler(Baritone baritone) { + super(baritone); + } /** * Maps keybinds to whether or not we are forcing their state down. @@ -61,6 +69,33 @@ public final class InputOverrideHandler implements Helper { inputForceStateMap.put(input.getKeyBinding(), forced); } + @Override + public final void onProcessKeyBinds() { + // Simulate the key being held down this tick + for (InputOverrideHandler.Input input : Input.values()) { + KeyBinding keyBinding = input.getKeyBinding(); + + if (isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) { + int keyCode = keyBinding.getKeyCode(); + + if (keyCode < Keyboard.KEYBOARD_SIZE) { + KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode); + } + } + } + } + + @Override + public final void onTick(TickEvent event) { + if (event.getType() == TickEvent.Type.OUT) { + return; + } + if (Baritone.settings().leftClickWorkaround.get()) { + boolean stillClick = BlockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT.keyBinding)); + setInputForceState(Input.CLICK_LEFT, stillClick); + } + } + /** * An {@link Enum} representing the possible inputs that we may want to force. */ diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java new file mode 100644 index 00000000..e75f7796 --- /dev/null +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -0,0 +1,146 @@ +/* + * 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.utils; + +import baritone.Baritone; +import baritone.api.pathing.goals.Goal; +import baritone.api.process.IBaritoneProcess; +import baritone.api.process.PathingCommand; +import baritone.behavior.PathingBehavior; +import baritone.pathing.path.PathExecutor; +import net.minecraft.util.math.BlockPos; + +import java.util.Comparator; +import java.util.HashSet; +import java.util.List; +import java.util.Objects; +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; + this.processes = new HashSet<>(); + } + + public void registerProcess(IBaritoneProcess process) { + process.onLostControl(); // make sure it's reset + processes.add(process); + } + + public void cancelEverything() { + for (IBaritoneProcess proc : processes) { + proc.onLostControl(); + if (proc.isActive() && !proc.isTemporary()) { // it's okay for a temporary thing (like combat pause) to maintain control even if you say to cancel + // but not for a non temporary thing + throw new IllegalStateException(proc.displayName()); + } + } + } + + public IBaritoneProcess inControlThisTick() { + return inControlThisTick; + } + + public void doTheThingWithTheStuff() { + inControlLastTick = inControlThisTick; + PathingCommand cmd = doTheStuff(); + if (cmd == null) { + return; + } + PathingBehavior p = baritone.getPathingBehavior(); + switch (cmd.commandType) { + case REQUEST_PAUSE: + p.requestPause(); + break; + case CANCEL_AND_SET_GOAL: + p.secretInternalSetGoal(cmd.goal); + p.cancelSegmentIfSafe(); + break; + case FORCE_REVALIDATE_GOAL_AND_PATH: + p.secretInternalSetGoalAndPath(cmd.goal); + if (cmd.goal == null || revalidateGoal(cmd.goal)) { + // pwnage + p.cancelSegmentIfSafe(); + } + break; + case REVALIDATE_GOAL_AND_PATH: + p.secretInternalSetGoalAndPath(cmd.goal); + if (Baritone.settings().cancelOnGoalInvalidation.get() && (cmd.goal == null || revalidateGoal(cmd.goal))) { + p.cancelSegmentIfSafe(); + } + break; + case SET_GOAL_AND_PATH: + // now this i can do + if (cmd.goal != null) { + baritone.getPathingBehavior().secretInternalSetGoalAndPath(cmd.goal); + } + break; + default: + throw new IllegalStateException(); + } + } + + public boolean revalidateGoal(Goal newGoal) { + PathExecutor current = baritone.getPathingBehavior().getCurrent(); + if (current != null) { + Goal intended = current.getPath().getGoal(); + BlockPos end = current.getPath().getDest(); + if (intended.isInGoal(end) && !newGoal.isInGoal(end)) { + // this path used to end in the goal + // but the goal has changed, so there's no reason to continue... + return true; + } + } + return false; + } + + + public PathingCommand doTheStuff() { + List inContention = processes.stream().filter(IBaritoneProcess::isActive).sorted(Comparator.comparingDouble(IBaritoneProcess::priority)).collect(Collectors.toList()); + boolean found = false; + boolean cancelOthers = false; + PathingCommand exec = null; + for (int i = inContention.size() - 1; i >= 0; i--) { // truly a gamer moment + IBaritoneProcess proc = inContention.get(i); + if (found) { + if (cancelOthers) { + proc.onLostControl(); + } + } else { + exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel()); + if (exec == null) { + if (proc.isActive()) { + throw new IllegalStateException(proc.displayName()); + } + proc.onLostControl(); + continue; + } + //System.out.println("Executing command " + exec.commandType + " " + exec.goal + " from " + proc.displayName()); + inControlThisTick = proc; + found = true; + cancelOthers = !proc.isTemporary(); + } + } + return exec; + } +}