diff --git a/.gitmessage b/.gitmessage new file mode 100644 index 000000000..259d0702f --- /dev/null +++ b/.gitmessage @@ -0,0 +1,31 @@ + (<ticket>) + +# 📝 Update README.md (WD-1234) +# ✅ Add unit test for inputs (WD-1234) + +# <emoji> can be: +# 🎨 :art: when improving structure of the code +# ⚡️ :zap: when improving performance +# 🔥 :fire: when removing code or files +# ✨ :sparkles: when introducing new features +# 🚧 :construction: when work in progress +# 🔨 :hammer: when refactoring code +# 📝 :memo: when writing docs +# 💄 :lipstick: when updating the UI and style files +# 📈 :chart_with_upwards_trend: when adding analytics or tracking code +# 🌐 :globe_with_meridians: when adding internationalization and localization +# ✏️ :pencil2: when fixing typos +# 🚚 :truck: when moving or renaming files +# ✅ :white_check_mark: when adding tests + +# 👌 :ok_hand: when updating code due to code review changes +# 🐛 :bug: when fixing a bug +# 🚑 :ambulance: when doing a critical hotfix +# 🚨 :rotating_light: when removing linter warnings + +# 🔀 :twisted_rightwards_arrows: when merging branches +# ⬆️ :arrow_up: when upgrading dependencies +# ⬇️ :arrow_down: when downgrading dependencies +# 🔧 :wrench: when changing configuration files +# 🔖 :bookmark: when releasing / version tagging +# 💚 :green_heart: when fixing the CI build diff --git a/README.md b/README.md index 26ff3b3b2..274dbe0f5 100644 --- a/README.md +++ b/README.md @@ -43,7 +43,7 @@ For 1.15.2, [click here](https://www.youtube.com/watch?v=j1qKtCZFURM) and see de This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/), the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2 through 1.15.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths). -Have committed at least once a day from Aug 1 2018 to Aug 1 2019. +Have committed at least once a day from Aug 1, 2018, to Aug 1, 2019. 1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2 @@ -71,7 +71,7 @@ The API is heavily documented, you can find the Javadocs for the latest release Please note that usage of anything located outside of the ``baritone.api`` package is not supported by the API release jar. -Below is an example of basic usage for changing some settings, and then pathing to a X/Z goal. +Below is an example of basic usage for changing some settings, and then pathing to an X/Z goal. ``` BaritoneAPI.getSettings().allowSprint.value = true; @@ -84,7 +84,7 @@ BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAnd ## Can I use Baritone as a library in my custom utility client? -That's what it's for, sure! (As long as usage is in compliance with the LGPL 3.0 License) +That's what it's for, sure! (As long as usage complies with the LGPL 3.0 License) ## How is it so fast? diff --git a/scripts/proguard.pro b/scripts/proguard.pro index 7e67a22ac..b4b1e021b 100644 --- a/scripts/proguard.pro +++ b/scripts/proguard.pro @@ -28,6 +28,13 @@ -keep class baritone.api.utils.MyChunkPos { *; } # even in standalone we need to keep this for gson reflect +# Keep any class or member annotated with @KeepName so we dont have to put everything in the script +-keep,allowobfuscation @interface baritone.KeepName +-keep @baritone.KeepName class * +-keepclassmembers class * { + @baritone.KeepName *; +} + # setting names are reflected from field names, so keep field names -keepclassmembers class baritone.api.Settings { public <fields>; diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 09fe85cf2..168d5a0f6 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -61,6 +61,19 @@ public final class Settings { */ public final Setting<Boolean> allowInventory = new Setting<>(false); + /** + * Disable baritone's auto-tool at runtime, but still assume that another mod will provide auto tool functionality + * <p> + * Specifically, path calculation will still assume that an auto tool wil run at execution time, even though + * Baritone itself will not do that. + */ + public final Setting<Boolean> assumeExternalAutoTool = new Setting<>(false); + + /** + * If this setting is on, no auto tool will occur at all, not at calculation time nor execution time + */ + public final Setting<Boolean> disableAutoTool = new Setting<>(false); + /** * It doesn't actually take twenty ticks to place a block, this cost is so high * because we want to generally conserve blocks which might be limited. @@ -1074,10 +1087,35 @@ public final class Settings { public final Setting<Boolean> renderSelectionCorners = new Setting<>(true); /** - * Desktop Notifications + * Desktop notifications */ public final Setting<Boolean> desktopNotifications = new Setting<>(false); + /** + * Desktop notification on path complete + */ + public final Setting<Boolean> notificationOnPathComplete = new Setting<>(true); + + /** + * Desktop notification on farm fail + */ + public final Setting<Boolean> notificationOnFarmFail = new Setting<>(true); + + /** + * Desktop notification on build finished + */ + public final Setting<Boolean> notificationOnBuildFinished = new Setting<>(true); + + /** + * Desktop notification on explore finished + */ + public final Setting<Boolean> notificationOnExploreFinished = new Setting<>(true); + + /** + * Desktop notification on mine fail + */ + public final Setting<Boolean> notificationOnMineFail = new Setting<>(true); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/KeepName.java b/src/main/java/baritone/KeepName.java new file mode 100644 index 000000000..20f08e7b8 --- /dev/null +++ b/src/main/java/baritone/KeepName.java @@ -0,0 +1,21 @@ +/* + * 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 <https://www.gnu.org/licenses/>. + */ + +package baritone; + +// Annotation for classes and class members that should not be renamed by proguard +public @interface KeepName { } diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index 4a04b9e09..1b024c3b8 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -79,7 +79,7 @@ public class ExecutionControlCommands { } } ); - pauseCommand = new Command(baritone, "pause") { + pauseCommand = new Command(baritone, "pause", "p") { @Override public void execute(String label, IArgConsumer args) throws CommandException { args.requireMax(0); @@ -112,7 +112,7 @@ public class ExecutionControlCommands { ); } }; - resumeCommand = new Command(baritone, "resume") { + resumeCommand = new Command(baritone, "resume", "r") { @Override public void execute(String label, IArgConsumer args) throws CommandException { args.requireMax(0); @@ -171,7 +171,7 @@ public class ExecutionControlCommands { ); } }; - cancelCommand = new Command(baritone, "cancel", "stop") { + cancelCommand = new Command(baritone, "cancel", "c", "stop") { @Override public void execute(String label, IArgConsumer args) throws CommandException { args.requireMax(0); diff --git a/src/main/java/baritone/command/defaults/FollowCommand.java b/src/main/java/baritone/command/defaults/FollowCommand.java index f74a4a064..3fd997ec8 100644 --- a/src/main/java/baritone/command/defaults/FollowCommand.java +++ b/src/main/java/baritone/command/defaults/FollowCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.KeepName; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.datatypes.EntityClassById; @@ -132,6 +133,7 @@ public class FollowCommand extends Command { ); } + @KeepName private enum FollowGroup { ENTITIES(LivingEntity.class::isInstance), PLAYERS(PlayerEntity.class::isInstance); /* , @@ -144,6 +146,7 @@ public class FollowCommand extends Command { } } + @KeepName private enum FollowList { ENTITY(EntityClassById.INSTANCE), PLAYER(NearbyPlayer.INSTANCE); diff --git a/src/main/java/baritone/command/defaults/GotoCommand.java b/src/main/java/baritone/command/defaults/GotoCommand.java index 28e768296..a6fe4e22b 100644 --- a/src/main/java/baritone/command/defaults/GotoCommand.java +++ b/src/main/java/baritone/command/defaults/GotoCommand.java @@ -72,7 +72,7 @@ public class GotoCommand extends Command { @Override public List<String> getLongDesc() { return Arrays.asList( - "The got command tells Baritone to head towards a given goal or block.", + "The goto command tells Baritone to head towards a given goal or block.", "", "Wherever a coordinate is expected, you can use ~ just like in regular Minecraft commands. Or, you can just use regular numbers.", "", diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 49851eebd..3c804067c 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -436,7 +436,9 @@ public interface MovementHelper extends ActionCosts, Helper { * @param ts previously calculated ToolSet */ static void switchToBestToolFor(IPlayerContext ctx, BlockState b, ToolSet ts, boolean preferSilkTouch) { - ctx.player().inventory.currentItem = ts.getBestSlot(b.getBlock(), preferSilkTouch); + if (!Baritone.settings().disableAutoTool.value && !Baritone.settings().assumeExternalAutoTool.value) { + ctx.player().inventory.currentItem = ts.getBestSlot(b.getBlock(), preferSilkTouch); + } } static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) { diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java index 417d25a20..f3e675c34 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java @@ -56,6 +56,14 @@ public class MovementDiagonal extends Movement { super(baritone, start, end, new BetterBlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}); } + @Override + protected boolean safeToCancel(MovementState state) { + return ctx.playerFeet().equals(src) || (( + MovementHelper.canWalkOn(ctx, new BlockPos(src.x, src.y - 1, dest.z)) + ) && + MovementHelper.canWalkOn(ctx, new BlockPos(dest.x, src.y - 1, src.z))); + } + @Override public double calculateCost(CalculationContext context) { MutableMoveResult result = new MutableMoveResult(); diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 62cee7bf9..c4b55b5c8 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -39,6 +39,7 @@ import baritone.pathing.movement.Movement; import baritone.pathing.movement.MovementHelper; import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; +import baritone.utils.NotificationHelper; import baritone.utils.PathingCommandContext; import baritone.utils.schematic.MapArtSchematic; import baritone.utils.schematic.SchematicSystem; @@ -424,6 +425,9 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil numRepeats++; if (repeat.equals(new Vector3i(0, 0, 0)) || (max != -1 && numRepeats >= max)) { logDirect("Done building"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnBuildFinished.value) { + NotificationHelper.notify("Done building", false); + } onLostControl(); return null; } diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java index b45c7d6f9..f925bec79 100644 --- a/src/main/java/baritone/process/CustomGoalProcess.java +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -23,6 +23,7 @@ import baritone.api.process.ICustomGoalProcess; import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.utils.BaritoneProcessHelper; +import baritone.utils.NotificationHelper; /** * As set by ExampleBaritoneControl or something idk @@ -93,6 +94,9 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC if (Baritone.settings().disconnectOnArrival.value) { ctx.world().sendQuittingDisconnectingPacket(); } + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnPathComplete.value) { + NotificationHelper.notify("Pathing complete", false); + } return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL); } return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); diff --git a/src/main/java/baritone/process/ExploreProcess.java b/src/main/java/baritone/process/ExploreProcess.java index 220ae3b12..c42ece0e5 100644 --- a/src/main/java/baritone/process/ExploreProcess.java +++ b/src/main/java/baritone/process/ExploreProcess.java @@ -29,6 +29,7 @@ import baritone.api.process.PathingCommandType; import baritone.api.utils.MyChunkPos; import baritone.cache.CachedWorld; import baritone.utils.BaritoneProcessHelper; +import baritone.utils.NotificationHelper; import com.google.gson.Gson; import com.google.gson.GsonBuilder; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; @@ -83,12 +84,18 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { if (calcFailed) { logDirect("Failed"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnExploreFinished.value) { + NotificationHelper.notify("Exploration failed", true); + } onLostControl(); return null; } IChunkFilter filter = calcFilter(); if (!Baritone.settings().disableCompletionCheck.value && filter.countRemain() == 0) { logDirect("Explored all chunks"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnExploreFinished.value) { + NotificationHelper.notify("Explored all chunks", false); + } onLostControl(); return null; } diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java index b8412de91..d2dc3c0f1 100644 --- a/src/main/java/baritone/process/FarmProcess.java +++ b/src/main/java/baritone/process/FarmProcess.java @@ -31,6 +31,7 @@ import baritone.api.utils.input.Input; import baritone.cache.WorldScanner; import baritone.pathing.movement.MovementHelper; import baritone.utils.BaritoneProcessHelper; +import baritone.utils.NotificationHelper; import net.minecraft.block.*; import net.minecraft.entity.Entity; import net.minecraft.entity.item.ItemEntity; @@ -254,6 +255,9 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro if (calcFailed) { logDirect("Farm failed"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnFarmFail.value) { + NotificationHelper.notify("Farm failed", true); + } onLostControl(); return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 108a0c780..3609827b7 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -30,6 +30,7 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; +import baritone.utils.NotificationHelper; import net.minecraft.block.*; import net.minecraft.client.world.ClientWorld; import net.minecraft.entity.Entity; @@ -85,10 +86,16 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro if (calcFailed) { if (!knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) { logDirect("Unable to find any path to " + filter + ", blacklisting presumably unreachable closest instance..."); - knownOreLocations.stream().min(Comparator.comparingDouble(ctx.playerFeet()::distanceSq)).ifPresent(blacklist::add); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) { + NotificationHelper.notify("Unable to find any path to " + filter + ", blacklisting presumably unreachable closest instance...", true); + } + knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::distanceSq)).ifPresent(blacklist::add); knownOreLocations.removeIf(blacklist::contains); } else { logDirect("Unable to find any path to " + filter + ", canceling mine"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) { + NotificationHelper.notify("Unable to find any path to " + filter + ", canceling mine", true); + } cancel(); return null; } @@ -219,6 +226,9 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro locs.addAll(dropped); if (locs.isEmpty()) { logDirect("No locations for " + filter + " known, cancelling"); + if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) { + NotificationHelper.notify("No locations for " + filter + " known, cancelling", true); + } cancel(); return; } diff --git a/src/main/java/baritone/utils/ToolSet.java b/src/main/java/baritone/utils/ToolSet.java index edd033061..811fd905d 100644 --- a/src/main/java/baritone/utils/ToolSet.java +++ b/src/main/java/baritone/utils/ToolSet.java @@ -89,12 +89,27 @@ public class ToolSet { } /** - * Calculate which tool on the hotbar is best for mining + * Calculate which tool on the hotbar is best for mining, depending on an override setting, + * related to auto tool movement cost, it will either return current selected slot, or the best slot. * * @param b the blockstate to be mined * @return An int containing the index in the tools array that worked best */ + public int getBestSlot(Block b, boolean preferSilkTouch) { + return getBestSlot(b, preferSilkTouch, false); + } + + public int getBestSlot(Block b, boolean preferSilkTouch, boolean pathingCalculation) { + + /* + If we actually want know what efficiency our held item has instead of the best one + possible, this lets us make pathing depend on the actual tool to be used (if auto tool is disabled) + */ + if (Baritone.settings().disableAutoTool.value && pathingCalculation) { + return player.inventory.currentItem; + } + int best = 0; double highestSpeed = Double.NEGATIVE_INFINITY; int lowestCost = Integer.MIN_VALUE; @@ -130,7 +145,7 @@ public class ToolSet { * @return A double containing the destruction ticks with the best tool */ private double getBestDestructionTime(Block b) { - ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b, false)); + ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b, false, true)); return calculateSpeedVsBlock(stack, b.getDefaultState()) * avoidanceMultiplier(b); }