diff --git a/src/main/java/baritone/bot/Baritone.java b/src/main/java/baritone/bot/Baritone.java index d776edb8..29e1a5d0 100755 --- a/src/main/java/baritone/bot/Baritone.java +++ b/src/main/java/baritone/bot/Baritone.java @@ -67,9 +67,11 @@ public enum Baritone { this.inputOverrideHandler = new InputOverrideHandler(); this.settings = new Settings(); this.behaviors = new ArrayList<>(); - behaviors.add(PathingBehavior.INSTANCE); - behaviors.add(LookBehavior.INSTANCE); - behaviors.add(MemoryBehavior.INSTANCE); + { + registerBehavior(PathingBehavior.INSTANCE); + registerBehavior(LookBehavior.INSTANCE); + registerBehavior(MemoryBehavior.INSTANCE); + } this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone"); if (!Files.exists(dir.toPath())) { @@ -100,6 +102,7 @@ public enum Baritone { public void registerBehavior(Behavior behavior) { this.behaviors.add(behavior); + this.gameEventHandler.registerEventListener(behavior); } public final boolean isActive() { diff --git a/src/main/java/baritone/bot/Settings.java b/src/main/java/baritone/bot/Settings.java index 4fb954a7..32b4920f 100644 --- a/src/main/java/baritone/bot/Settings.java +++ b/src/main/java/baritone/bot/Settings.java @@ -65,6 +65,12 @@ public class Settings { Item.getItemFromBlock(Blocks.NETHERRACK) )); + /** + * Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real + * pathing scenarios. And they can cause Baritone to get trapped indefinitely in a strange scenario. + */ + public Setting allowVines = new Setting<>(false); + /** * This is the big A* setting. * As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path. @@ -122,6 +128,18 @@ public class Settings { */ public Setting planningTickLookAhead = new Setting<>(100); + /** + * How far are you allowed to fall onto solid ground (without a water bucket)? + * 3 won't deal any damage. But if you just want to get down the mountain quickly and you have + * Feather Falling IV, you might set it a bit higher, like 4 or 5. + */ + public Setting maxFallHeight = new Setting<>(3); + + /** + * If a movement takes this many ticks more than its initial cost estimate, cancel it + */ + public Setting movementTimeoutTicks = new Setting<>(100); + /** * Pathing can never take longer than this */ diff --git a/src/main/java/baritone/bot/behavior/Behavior.java b/src/main/java/baritone/bot/behavior/Behavior.java index 198dfb8a..87104246 100644 --- a/src/main/java/baritone/bot/behavior/Behavior.java +++ b/src/main/java/baritone/bot/behavior/Behavior.java @@ -19,6 +19,7 @@ package baritone.bot.behavior; import baritone.bot.event.listener.AbstractGameEventListener; import baritone.bot.utils.Helper; +import baritone.bot.utils.interfaces.Toggleable; /** * A generic bot behavior. @@ -26,7 +27,7 @@ import baritone.bot.utils.Helper; * @author Brady * @since 8/1/2018 6:29 PM */ -public class Behavior implements AbstractGameEventListener, Helper { +public class Behavior implements AbstractGameEventListener, Toggleable, Helper { /** * Whether or not this behavior is enabled @@ -38,6 +39,7 @@ public class Behavior implements AbstractGameEventListener, Helper { * * @return The new state. */ + @Override public final boolean toggle() { return this.setEnabled(!this.enabled); } @@ -47,6 +49,7 @@ public class Behavior implements AbstractGameEventListener, Helper { * * @return The new state. */ + @Override public final boolean setEnabled(boolean enabled) { boolean newState = getNewState(this.enabled, enabled); if (newState == this.enabled) @@ -79,6 +82,7 @@ public class Behavior implements AbstractGameEventListener, Helper { /** * @return Whether or not this {@link Behavior} is active. */ + @Override public final boolean isEnabled() { return this.enabled; } diff --git a/src/main/java/baritone/bot/event/GameEventHandler.java b/src/main/java/baritone/bot/event/GameEventHandler.java index 32bcde8c..7beeb3d6 100644 --- a/src/main/java/baritone/bot/event/GameEventHandler.java +++ b/src/main/java/baritone/bot/event/GameEventHandler.java @@ -35,7 +35,6 @@ package baritone.bot.event; import baritone.bot.Baritone; -import baritone.bot.behavior.Behavior; import baritone.bot.chunk.CachedWorld; import baritone.bot.chunk.CachedWorldProvider; import baritone.bot.chunk.ChunkPacker; @@ -44,6 +43,7 @@ import baritone.bot.event.events.type.EventState; import baritone.bot.event.listener.IGameEventListener; import baritone.bot.utils.Helper; import baritone.bot.utils.InputOverrideHandler; +import baritone.bot.utils.interfaces.Toggleable; import net.minecraft.client.renderer.BufferBuilder; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.Tessellator; @@ -51,6 +51,8 @@ import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.client.settings.KeyBinding; import org.lwjgl.input.Keyboard; +import java.util.ArrayList; +import java.util.List; import java.util.function.Consumer; /** @@ -59,18 +61,20 @@ import java.util.function.Consumer; */ public final class GameEventHandler implements IGameEventListener, Helper { + private final List listeners = new ArrayList<>(); + @Override public final void onTick(TickEvent event) { - dispatch(behavior -> behavior.onTick(event)); + dispatch(listener -> listener.onTick(event)); } @Override - public void onPlayerUpdate() { - dispatch(Behavior::onPlayerUpdate); + public final void onPlayerUpdate() { + dispatch(IGameEventListener::onPlayerUpdate); } @Override - public void onProcessKeyBinds() { + public final void onProcessKeyBinds() { InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler(); // Simulate the key being held down this tick @@ -85,16 +89,16 @@ public final class GameEventHandler implements IGameEventListener, Helper { } } - dispatch(Behavior::onProcessKeyBinds); + dispatch(IGameEventListener::onProcessKeyBinds); } @Override - public void onSendChatMessage(ChatEvent event) { - dispatch(behavior -> behavior.onSendChatMessage(event)); + public final void onSendChatMessage(ChatEvent event) { + dispatch(listener -> listener.onSendChatMessage(event)); } @Override - public void onChunkEvent(ChunkEvent event) { + public final void onChunkEvent(ChunkEvent event) { EventState state = event.getState(); ChunkEvent.Type type = event.getType(); @@ -116,22 +120,22 @@ public final class GameEventHandler implements IGameEventListener, Helper { } } - dispatch(behavior -> behavior.onChunkEvent(event)); + dispatch(listener -> listener.onChunkEvent(event)); } @Override - public void onRenderPass(RenderEvent event) { + public final void onRenderPass(RenderEvent event) { /* CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> { drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks()); }))); */ - dispatch(behavior -> behavior.onRenderPass(event)); + dispatch(listener -> listener.onRenderPass(event)); } @Override - public void onWorldEvent(WorldEvent event) { + public final void onWorldEvent(WorldEvent event) { if (Baritone.settings().chuckCaching.get()) { CachedWorldProvider cache = CachedWorldProvider.INSTANCE; @@ -147,21 +151,34 @@ public final class GameEventHandler implements IGameEventListener, Helper { } } - dispatch(behavior -> behavior.onWorldEvent(event)); + dispatch(listener -> listener.onWorldEvent(event)); } @Override - public void onSendPacket(PacketEvent event) { + public final void onSendPacket(PacketEvent event) { dispatch(behavior -> behavior.onSendPacket(event)); } @Override - public void onReceivePacket(PacketEvent event) { + public final void onReceivePacket(PacketEvent event) { dispatch(behavior -> behavior.onReceivePacket(event)); } - private void dispatch(Consumer dispatchFunction) { - Baritone.INSTANCE.getBehaviors().stream().filter(Behavior::isEnabled).forEach(dispatchFunction); + @Override + public final void onQueryItemSlotForBlocks(ItemSlotEvent event) { + dispatch(behavior -> behavior.onQueryItemSlotForBlocks(event)); + } + + public final void registerEventListener(IGameEventListener listener) { + this.listeners.add(listener); + } + + private void dispatch(Consumer dispatchFunction) { + this.listeners.stream().filter(this::canDispatch).forEach(dispatchFunction); + } + + private boolean canDispatch(IGameEventListener listener) { + return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled(); } private void drawChunkLine(int posX, int posZ, float partialTicks) { diff --git a/src/main/java/baritone/bot/event/events/ItemSlotEvent.java b/src/main/java/baritone/bot/event/events/ItemSlotEvent.java new file mode 100644 index 00000000..3362e780 --- /dev/null +++ b/src/main/java/baritone/bot/event/events/ItemSlotEvent.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 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Baritone. If not, see . + */ + +package baritone.bot.event.events; + +import baritone.bot.event.listener.IGameEventListener; + +/** + * Called in some cases where a player's inventory has it's current slot queried. + *

+ * @see IGameEventListener#onQueryItemSlotForBlocks() + * + * @author Brady + * @since 8/20/2018 + */ +public final class ItemSlotEvent { + + /** + * The current slot index + */ + private int slot; + + public ItemSlotEvent(int slot) { + this.slot = slot; + } + + /** + * Sets the new slot index that will be used + * + * @param slot The slot index + */ + public final void setSlot(int slot) { + this.slot = slot; + } + + /** + * @return The current slot index + */ + public final int getSlot() { + return this.slot; + } +} diff --git a/src/main/java/baritone/bot/event/listener/AbstractGameEventListener.java b/src/main/java/baritone/bot/event/listener/AbstractGameEventListener.java index 23fd18ab..a3e4251d 100644 --- a/src/main/java/baritone/bot/event/listener/AbstractGameEventListener.java +++ b/src/main/java/baritone/bot/event/listener/AbstractGameEventListener.java @@ -74,4 +74,7 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onReceivePacket(PacketEvent event) {} + + @Override + default void onQueryItemSlotForBlocks(ItemSlotEvent event) {} } diff --git a/src/main/java/baritone/bot/event/listener/IGameEventListener.java b/src/main/java/baritone/bot/event/listener/IGameEventListener.java index d418519d..d2b0cd28 100644 --- a/src/main/java/baritone/bot/event/listener/IGameEventListener.java +++ b/src/main/java/baritone/bot/event/listener/IGameEventListener.java @@ -36,11 +36,13 @@ package baritone.bot.event.listener; import baritone.bot.event.events.*; import io.netty.util.concurrent.GenericFutureListener; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.settings.GameSettings; +import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; @@ -114,5 +116,11 @@ public interface IGameEventListener { */ void onReceivePacket(PacketEvent event); - + /** + * Run when a query is made for a player's inventory current slot in the context of blocks + * + * @see InventoryPlayer#getDestroySpeed(IBlockState) + * @see InventoryPlayer#canHarvestBlock(IBlockState) + */ + void onQueryItemSlotForBlocks(ItemSlotEvent event); } diff --git a/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java index b5106235..5089dfc4 100644 --- a/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java @@ -115,10 +115,20 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { @Override public Optional bestPathSoFar() { - if (startNode == null || bestSoFar[0] == null) + if (startNode == null || bestSoFar[0] == null) { return Optional.empty(); - - return Optional.of(new Path(startNode, bestSoFar[0], 0)); + } + for (int i = 0; i < bestSoFar.length; i++) { + if (bestSoFar[i] == null) { + continue; + } + if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared + return Optional.of(new Path(startNode, bestSoFar[i], 0)); + } + } + // instead of returning bestSoFar[0], be less misleading + // if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen + return Optional.empty(); } @Override diff --git a/src/main/java/baritone/bot/pathing/movement/CalculationContext.java b/src/main/java/baritone/bot/pathing/movement/CalculationContext.java index 2d65e789..03d4aba7 100644 --- a/src/main/java/baritone/bot/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/bot/pathing/movement/CalculationContext.java @@ -38,6 +38,7 @@ public class CalculationContext implements Helper { private final boolean canSprint; private final double placeBlockCost; private final boolean allowBreak; + private final int maxFallHeight; public CalculationContext() { this(new ToolSet()); @@ -51,6 +52,7 @@ public class CalculationContext implements Helper { this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6; this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get(); this.allowBreak = Baritone.settings().allowBreak.get(); + this.maxFallHeight = Baritone.settings().maxFallHeight.get(); // why cache these things here, why not let the movements just get directly from settings? // because if some movements are calculated one way and others are calculated another way, // then you get a wildly inconsistent path that isn't optimal for either scenario. @@ -79,4 +81,8 @@ public class CalculationContext implements Helper { public boolean allowBreak() { return allowBreak; } + + public int maxFallHeight(){ + return maxFallHeight; + } } diff --git a/src/main/java/baritone/bot/pathing/movement/Movement.java b/src/main/java/baritone/bot/pathing/movement/Movement.java index 8905d061..84540a75 100644 --- a/src/main/java/baritone/bot/pathing/movement/Movement.java +++ b/src/main/java/baritone/bot/pathing/movement/Movement.java @@ -24,10 +24,7 @@ import baritone.bot.pathing.movement.MovementState.MovementStatus; import baritone.bot.pathing.movement.movements.MovementDownward; import baritone.bot.pathing.movement.movements.MovementPillar; import baritone.bot.pathing.movement.movements.MovementTraverse; -import baritone.bot.utils.BlockStateInterface; -import baritone.bot.utils.Helper; -import baritone.bot.utils.Rotation; -import baritone.bot.utils.ToolSet; +import baritone.bot.utils.*; import net.minecraft.block.Block; import net.minecraft.block.BlockLadder; import net.minecraft.block.BlockVine; @@ -137,6 +134,14 @@ public abstract class Movement implements Helper, MovementHelper { state.setTarget(new MovementState.MovementTarget(reachable.get())).setInput(Input.CLICK_LEFT, true); return false; } + //get rekt minecraft + //i'm doing it anyway + //i dont care if theres snow in the way!!!!!!! + //you dont own me!!!! + state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), + Utils.getBlockPosCenter(blockPos))) + ).setInput(InputOverrideHandler.Input.CLICK_LEFT, true); + return false; } } if (somethingInTheWay) { @@ -168,7 +173,6 @@ public abstract class Movement implements Helper, MovementHelper { public void onFinish(MovementState state) { state.getInputStates().replaceAll((input, forced) -> false); state.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced)); - state.setStatus(MovementStatus.SUCCESS); } public void cancel() { diff --git a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java index 90e4c4c8..aef088e1 100644 --- a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java @@ -69,14 +69,14 @@ public interface MovementHelper extends ActionCosts, Helper { static boolean canWalkThrough(BlockPos pos, IBlockState state) { Block block = state.getBlock(); - if (block instanceof BlockLilyPad - || block instanceof BlockFire + if (block instanceof BlockFire || block instanceof BlockTripWire || block instanceof BlockWeb || block instanceof BlockEndPortal) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire return false; } - if (BlockStateInterface.isFlowing(state) || BlockStateInterface.isLiquid(pos.up())) { + IBlockState up = BlockStateInterface.get(pos.up()); + if (BlockStateInterface.isFlowing(state) || up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { return false; // Don't walk through flowing liquids } if (block instanceof BlockDoor && !Blocks.IRON_DOOR.equals(block)) { @@ -140,7 +140,7 @@ public interface MovementHelper extends ActionCosts, Helper { */ static boolean canWalkOn(BlockPos pos, IBlockState state) { Block block = state.getBlock(); - if (block instanceof BlockLadder || block instanceof BlockVine) { // TODO reconsider this + if (block instanceof BlockLadder || (Baritone.settings().allowVines.get() && block instanceof BlockVine)) { // TODO reconsider this return true; } if (block instanceof BlockGlass || block instanceof BlockStainedGlass) { @@ -153,7 +153,8 @@ public interface MovementHelper extends ActionCosts, Helper { return false; } if (BlockStateInterface.isWater(block)) { - return BlockStateInterface.isWater(pos.up()); // You can only walk on water if there is water above it + Block up = BlockStateInterface.get(pos.up()).getBlock(); + return BlockStateInterface.isWater(up) || up instanceof BlockLilyPad; // You can only walk on water if there is water above it } if (Blocks.MAGMA.equals(block)) { return false; @@ -284,6 +285,8 @@ public interface MovementHelper extends ActionCosts, Helper { for (int fallHeight = 3; true; fallHeight++) { BlockPos onto = dest.down(fallHeight); if (onto.getY() < 0) { + // when pathing in the end, where you could plausibly fall into the void + // this check prevents it from getting the block at y=-1 and crashing break; } IBlockState ontoBlock = BlockStateInterface.get(onto); diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java index d7b429a7..b852318d 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java @@ -69,7 +69,7 @@ public class MovementDescend extends Movement { } BlockPos playerFeet = playerFeet(); if (playerFeet.equals(dest)) { - if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.01) { + if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads // Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately state.setStatus(MovementStatus.SUCCESS); return state; diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java index 2cda3b63..fe7dde7b 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java @@ -17,6 +17,7 @@ package baritone.bot.pathing.movement.movements; +import baritone.bot.Baritone; import baritone.bot.behavior.impl.LookBehaviorUtils; import baritone.bot.pathing.movement.CalculationContext; import baritone.bot.pathing.movement.Movement; @@ -51,7 +52,7 @@ public class MovementFall extends Movement { return COST_INF; } double placeBucketCost = 0.0; - if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > 3) { + if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeight()) { if (!context.hasWaterBucket()) { return COST_INF; } @@ -88,7 +89,7 @@ public class MovementFall extends Movement { } BlockPos playerFeet = playerFeet(); Optional targetRotation = Optional.empty(); - if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > 3 && !playerFeet.equals(dest)) { + if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeight.get() && !playerFeet.equals(dest)) { if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) { // TODO check if water bucket is on hotbar or main inventory state.setStatus(MovementStatus.UNREACHABLE); return state; @@ -104,7 +105,7 @@ public class MovementFall extends Movement { } else { state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)))); } - if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.01 + if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads || BlockStateInterface.isWater(dest))) { if (BlockStateInterface.isWater(dest) && player().inventory.hasItemStack(STACK_BUCKET_EMPTY)) { player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY); diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java index 44182a97..2ca97995 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java @@ -83,7 +83,7 @@ public class MovementTraverse extends Movement { WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; } } - if (MovementHelper.canWalkThrough(positionsToBreak[0]) && MovementHelper.canWalkThrough(positionsToBreak[1])) { + if (MovementHelper.canWalkThrough(positionsToBreak[0], pb0) && MovementHelper.canWalkThrough(positionsToBreak[1], pb1)) { if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) { // if there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing // we can sprint =D diff --git a/src/main/java/baritone/bot/pathing/path/PathExecutor.java b/src/main/java/baritone/bot/pathing/path/PathExecutor.java index ae14d3d8..3c3fd929 100644 --- a/src/main/java/baritone/bot/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/bot/pathing/path/PathExecutor.java @@ -85,7 +85,7 @@ public class PathExecutor implements Helper { return true; } if (!whereShouldIBe.equals(whereAmI)) { - System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI); + //System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI); if (!Blocks.AIR.equals(BlockStateInterface.getBlock(whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip for (int i = 0; i < pathPosition - 2 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks if (whereAmI.equals(path.positions().get(i))) { @@ -100,6 +100,7 @@ public class PathExecutor implements Helper { if (i - pathPosition > 2) { displayChatMessageRaw("Skipping forward " + (i - pathPosition) + " steps, to " + i); } + System.out.println("Double skip sundae"); pathPosition = i - 1; Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); return false; @@ -216,7 +217,7 @@ public class PathExecutor implements Helper { return true; } if (movementStatus == SUCCESS) { - System.out.println("Movement done, next path"); + //System.out.println("Movement done, next path"); pathPosition++; ticksOnCurrent = 0; Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); @@ -224,12 +225,12 @@ public class PathExecutor implements Helper { return true; } else { ticksOnCurrent++; - if (ticksOnCurrent > currentMovementInitialCostEstimate + 100) { + if (ticksOnCurrent > currentMovementInitialCostEstimate + Baritone.settings().movementTimeoutTicks.get()) { // only fail if the total time has exceeded the initial estimate // as you break the blocks required, the remaining cost goes down, to the point where - // ticksOnCurrent is greater than recalculateCost + 1000 + // ticksOnCurrent is greater than recalculateCost + 100 // this is why we cache cost at the beginning, and don't recalculate for this comparison every tick - displayChatMessageRaw("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + movement.getCost(null) + "). Cancelling."); + displayChatMessageRaw("This movement has taken too long (" + ticksOnCurrent + " ticks, expected " + currentMovementInitialCostEstimate + "). Cancelling."); movement.cancel(); Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys(); pathPosition = path.length() + 3; diff --git a/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java b/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java index 68fb0b53..9c2c88d1 100644 --- a/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java @@ -23,10 +23,7 @@ import baritone.bot.behavior.Behavior; import baritone.bot.behavior.impl.PathingBehavior; import baritone.bot.event.events.ChatEvent; import baritone.bot.pathing.calc.AStarPathFinder; -import baritone.bot.pathing.goals.Goal; -import baritone.bot.pathing.goals.GoalBlock; -import baritone.bot.pathing.goals.GoalXZ; -import baritone.bot.pathing.goals.GoalYLevel; +import baritone.bot.pathing.goals.*; import baritone.bot.pathing.movement.ActionCosts; import baritone.bot.pathing.movement.CalculationContext; import baritone.bot.pathing.movement.Movement; @@ -114,6 +111,15 @@ public class ExampleBaritoneControl extends Behavior { event.cancel(); return; } + if (msg.toLowerCase().equals("spawn")) { + BlockPos spawnPoint = player().getBedLocation(); + // for some reason the default spawnpoint is underground sometimes + Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getY()); + PathingBehavior.INSTANCE.setGoal(goal); + displayChatMessageRaw("Goal: " + goal); + event.cancel(); + return; + } if (msg.toLowerCase().equals("costs")) { Movement[] movements = AStarPathFinder.getConnectedPositions(new BetterBlockPos(playerFeet()), new CalculationContext()); ArrayList moves = new ArrayList<>(Arrays.asList(movements)); diff --git a/src/main/java/baritone/bot/utils/ToolSet.java b/src/main/java/baritone/bot/utils/ToolSet.java index 575605d1..935e157f 100644 --- a/src/main/java/baritone/bot/utils/ToolSet.java +++ b/src/main/java/baritone/bot/utils/ToolSet.java @@ -17,6 +17,9 @@ package baritone.bot.utils; +import baritone.bot.Baritone; +import baritone.bot.event.events.ItemSlotEvent; +import baritone.bot.event.listener.AbstractGameEventListener; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.Minecraft; @@ -36,10 +39,19 @@ import java.util.Map; /** * A cached list of the best tools on the hotbar for any block * - * @author avecowa + * @author avecowa, Brady */ public class ToolSet implements Helper { + /** + * Instance of the internal event listener used to hook into Baritone's event bus + */ + private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener(); + + static { + Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER); + } + /** * A list of tools on the hotbar that should be considered. * Note that if there are no tools on the hotbar this list will still have one (null) entry. @@ -131,18 +143,29 @@ public class ToolSet implements Helper { // Calculate the slot with the best item byte slot = this.getBestSlot(state); - // Save the old current slot - int oldSlot = player().inventory.currentItem; - - // Set the best slot - player().inventory.currentItem = slot; + INTERNAL_EVENT_LISTENER.setOverrideSlot(slot); // Calculate the relative hardness of the block to the player float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos); // Restore the old slot - player().inventory.currentItem = oldSlot; + INTERNAL_EVENT_LISTENER.setOverrideSlot(-1); return hardness; } + + private static final class InternalEventListener implements AbstractGameEventListener { + + private int overrideSlot; + + @Override + public void onQueryItemSlotForBlocks(ItemSlotEvent event) { + if (this.overrideSlot >= 0) + event.setSlot(this.overrideSlot); + } + + public final void setOverrideSlot(int overrideSlot) { + this.overrideSlot = overrideSlot; + } + } } diff --git a/src/main/java/baritone/bot/utils/interfaces/Toggleable.java b/src/main/java/baritone/bot/utils/interfaces/Toggleable.java new file mode 100644 index 00000000..e0d42958 --- /dev/null +++ b/src/main/java/baritone/bot/utils/interfaces/Toggleable.java @@ -0,0 +1,44 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Baritone. If not, see . + */ + +package baritone.bot.utils.interfaces; + +/** + * @author Brady + * @since 8/20/2018 + */ +public interface Toggleable { + + /** + * Toggles the enabled state of this {@link Toggleable}. + * + * @return The new state. + */ + boolean toggle(); + + /** + * Sets the enabled state of this {@link Toggleable}. + * + * @return The new state. + */ + boolean setEnabled(boolean enabled); + + /** + * @return Whether or not this {@link Toggleable} object is enabled + */ + boolean isEnabled(); +} diff --git a/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java b/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java new file mode 100644 index 00000000..8e1b908b --- /dev/null +++ b/src/main/java/baritone/launch/mixins/MixinInventoryPlayer.java @@ -0,0 +1,62 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU 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 General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Baritone. If not, see . + */ + +package baritone.launch.mixins; + +import baritone.bot.Baritone; +import baritone.bot.event.events.ItemSlotEvent; +import net.minecraft.entity.player.InventoryPlayer; +import org.spongepowered.asm.lib.Opcodes; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.injection.At; +import org.spongepowered.asm.mixin.injection.Redirect; + +/** + * @author Brady + * @since 8/20/2018 + */ +@Mixin(InventoryPlayer.class) +public class MixinInventoryPlayer { + + @Redirect( + method = "getDestroySpeed", + at = @At( + value = "FIELD", + opcode = Opcodes.GETFIELD, + target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I" + ) + ) + private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) { + ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem); + Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event); + return event.getSlot(); + } + + @Redirect( + method = "canHarvestBlock", + at = @At( + value = "FIELD", + opcode = Opcodes.GETFIELD, + target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I" + ) + ) + private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) { + ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem); + Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event); + return event.getSlot(); + } +} diff --git a/src/main/resources/mixins.baritone.json b/src/main/resources/mixins.baritone.json index 21196347..72f7d4dc 100755 --- a/src/main/resources/mixins.baritone.json +++ b/src/main/resources/mixins.baritone.json @@ -10,6 +10,7 @@ "MixinGameSettings", "MixinGuiContainer", "MixinGuiScreen", + "MixinInventoryPlayer", "MixinKeyBinding", "MixinMain", "MixinMinecraft",