diff --git a/src/launch/java/baritone/launch/mixins/MixinInventoryPlayer.java b/src/launch/java/baritone/launch/mixins/MixinInventoryPlayer.java deleted file mode 100644 index dfaa4b19..00000000 --- a/src/launch/java/baritone/launch/mixins/MixinInventoryPlayer.java +++ /dev/null @@ -1,62 +0,0 @@ -/* - * 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.Baritone; -import baritone.api.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/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index 7f9bda48..b1a8ed31 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -17,7 +17,6 @@ "MixinGameSettings", "MixinGuiContainer", "MixinGuiScreen", - "MixinInventoryPlayer", "MixinKeyBinding", "MixinMinecraft", "MixinNetHandlerPlayClient", diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 0b571264..5baacec8 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -21,7 +21,6 @@ import baritone.api.event.GameEventHandler; import baritone.behavior.Behavior; import baritone.behavior.impl.*; import baritone.utils.InputOverrideHandler; -import baritone.utils.ToolSet; import net.minecraft.client.Minecraft; import java.io.File; @@ -82,7 +81,6 @@ public enum Baritone { registerBehavior(LocationTrackingBehavior.INSTANCE); registerBehavior(FollowBehavior.INSTANCE); registerBehavior(MineBehavior.INSTANCE); - this.gameEventHandler.registerEventListener(ToolSet.INTERNAL_EVENT_LISTENER); } this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone"); if (!Files.exists(dir.toPath())) { diff --git a/src/main/java/baritone/Settings.java b/src/main/java/baritone/Settings.java index 2e6f0e39..1eed4333 100644 --- a/src/main/java/baritone/Settings.java +++ b/src/main/java/baritone/Settings.java @@ -83,6 +83,11 @@ public class Settings { */ public Setting allowWalkOnBottomSlab = new Setting<>(true); + /** + * For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly. + */ + public Setting considerPotionEffects = new Setting<>(true); + /** * This is the big A* setting. * As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path. diff --git a/src/main/java/baritone/api/event/GameEventHandler.java b/src/main/java/baritone/api/event/GameEventHandler.java index 45e86885..1ec2d834 100644 --- a/src/main/java/baritone/api/event/GameEventHandler.java +++ b/src/main/java/baritone/api/event/GameEventHandler.java @@ -159,11 +159,6 @@ public final class GameEventHandler implements IGameEventListener, Helper { dispatch(listener -> listener.onReceivePacket(event)); } - @Override - public final void onQueryItemSlotForBlocks(ItemSlotEvent event) { - dispatch(listener -> listener.onQueryItemSlotForBlocks(event)); - } - @Override public void onPlayerRelativeMove(RelativeMoveEvent event) { dispatch(listener -> listener.onPlayerRelativeMove(event)); diff --git a/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java index b47468bd..3b228e9d 100644 --- a/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/main/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -74,9 +74,6 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onReceivePacket(PacketEvent event) {} - @Override - default void onQueryItemSlotForBlocks(ItemSlotEvent event) {} - @Override default void onPlayerRelativeMove(RelativeMoveEvent event) {} diff --git a/src/main/java/baritone/api/event/listener/IGameEventListener.java b/src/main/java/baritone/api/event/listener/IGameEventListener.java index 9be19aab..81f91774 100644 --- a/src/main/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/main/java/baritone/api/event/listener/IGameEventListener.java @@ -36,7 +36,6 @@ package baritone.api.event.listener; import baritone.api.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.gui.GuiGameOver; @@ -44,7 +43,6 @@ import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.settings.GameSettings; import net.minecraft.entity.Entity; -import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.network.NetworkManager; import net.minecraft.network.Packet; import net.minecraft.util.text.ITextComponent; @@ -120,14 +118,6 @@ 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); - /** * Run once per game tick from before and after the player's moveRelative method is called * diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java index 9d2f5869..5eba39ab 100644 --- a/src/main/java/baritone/pathing/movement/Movement.java +++ b/src/main/java/baritone/pathing/movement/Movement.java @@ -149,7 +149,7 @@ public abstract class Movement implements Helper, MovementHelper { somethingInTheWay = true; Optional reachable = LookBehaviorUtils.reachable(blockPos); if (reachable.isPresent()) { - player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos)); + MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos)); state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true); return false; } diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index 82b20c41..06c880d8 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -261,7 +261,7 @@ public interface MovementHelper extends ActionCosts, Helper { return COST_INF; } double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table - double result = m / context.getToolSet().getStrVsBlock(state, position); + double result = m / context.getToolSet().getStrVsBlock(state); if (includeFalling) { BlockPos up = position.up(); IBlockState above = BlockStateInterface.get(up); diff --git a/src/main/java/baritone/utils/ToolSet.java b/src/main/java/baritone/utils/ToolSet.java index e8243ba6..8a97980c 100644 --- a/src/main/java/baritone/utils/ToolSet.java +++ b/src/main/java/baritone/utils/ToolSet.java @@ -17,55 +17,24 @@ package baritone.utils; -import baritone.api.event.events.ItemSlotEvent; -import baritone.api.event.listener.AbstractGameEventListener; +import baritone.Baritone; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; -import net.minecraft.client.Minecraft; -import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.item.Item; -import net.minecraft.item.ItemAir; +import net.minecraft.enchantment.EnchantmentHelper; +import net.minecraft.init.Enchantments; +import net.minecraft.init.MobEffects; import net.minecraft.item.ItemStack; -import net.minecraft.item.ItemTool; -import net.minecraft.util.NonNullList; -import net.minecraft.util.math.BlockPos; -import java.util.ArrayList; import java.util.HashMap; -import java.util.List; import java.util.Map; /** * A cached list of the best tools on the hotbar for any block * - * @author avecowa, Brady + * @author avecowa, Brady, leijurv */ public class ToolSet implements Helper { - /** - * Instance of the internal event listener used to hook into Baritone's event bus - */ - public static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener(); - - /** - * 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. - */ - private List tools; - - /** - * A mapping from the tools array to what hotbar slots the tool is actually in. - * tools.get(i) will be on your hotbar in slot slots.get(i) - */ - private List slots; - - /** - * A mapping from a block to which tool index is best for it. - * The values in this map are *not* hotbar slots indexes, they need to be looked up in slots - * in order to be converted into hotbar slots. - */ - private Map slotCache = new HashMap<>(); - /** * A cache mapping a {@link Block} to how long it will take to break * with this toolset, given the optimum tool is used. @@ -75,30 +44,7 @@ public class ToolSet implements Helper { /** * Create a toolset from the current player's inventory (but don't calculate any hardness values just yet) */ - public ToolSet() { - EntityPlayerSP p = Minecraft.getMinecraft().player; - NonNullList inv = p.inventory.mainInventory; - tools = new ArrayList<>(); - slots = new ArrayList<>(); - boolean fnull = false; - for (byte i = 0; i < 9; i++) { - if (!fnull || ((!(inv.get(i).getItem() instanceof ItemAir)) && inv.get(i).getItem() instanceof ItemTool)) { - tools.add(inv.get(i).getItem() instanceof ItemTool ? (ItemTool) inv.get(i).getItem() : null); - slots.add(i); - fnull |= (inv.get(i).getItem() instanceof ItemAir) || (!inv.get(i).getItem().isDamageable()); - } - } - } - - /** - * A caching wrapper around getBestToolIndex - * - * @param state the blockstate to be mined - * @return get which tool on the hotbar is best for mining it - */ - public Item getBestTool(IBlockState state) { - return tools.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state))); - } + public ToolSet() {} /** * Calculate which tool on the hotbar is best for mining @@ -106,15 +52,11 @@ public class ToolSet implements Helper { * @param b the blockstate to be mined * @return a byte indicating the index in the tools array that worked best */ - private byte getBestToolIndex(IBlockState b) { + public byte getBestSlot(IBlockState b) { byte best = 0; - float value = -1; - for (byte i = 0; i < tools.size(); i++) { - Item item = tools.get(i); - if (item == null) - continue; - - float v = item.getDestroySpeed(new ItemStack(item), b); + double value = -1; + for (byte i = 0; i < 9; i++) { + double v = calculateStrVsBlock(i, b); if (v > value || value == -1) { value = v; best = i; @@ -123,25 +65,14 @@ public class ToolSet implements Helper { return best; } - /** - * Get which hotbar slot should be selected for fastest mining - * - * @param state the blockstate to be mined - * @return a byte indicating which hotbar slot worked best - */ - public byte getBestSlot(IBlockState state) { - return slots.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state))); - } - /** * Using the best tool on the hotbar, how long would it take to mine this block * * @param state the blockstate to be mined - * @param pos the blockpos to be mined * @return how long it would take in ticks */ - public double getStrVsBlock(IBlockState state, BlockPos pos) { - return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(state, pos)); + public double getStrVsBlock(IBlockState state) { + return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(getBestSlot(state), state)); } /** @@ -149,36 +80,51 @@ public class ToolSet implements Helper { * in this toolset is used. * * @param state the blockstate to be mined - * @param pos the blockpos to be mined * @return how long it would take in ticks */ - private double calculateStrVsBlock(IBlockState state, BlockPos pos) { + private double calculateStrVsBlock(byte slot, IBlockState state) { // Calculate the slot with the best item - byte slot = this.getBestSlot(state); + ItemStack contents = player().inventory.getStackInSlot(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 - 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); + float blockHard = state.getBlockHardness(null, null); + if (blockHard < 0) { + return 0; } - final void setOverrideSlot(int overrideSlot) { - this.overrideSlot = overrideSlot; + float speed = contents.getDestroySpeed(state); + if (speed > 1) { + int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents); + if (effLevel > 0 && !contents.isEmpty()) { + speed += effLevel * effLevel + 1; + } + } + + if (Baritone.settings().considerPotionEffects.get()) { + if (player().isPotionActive(MobEffects.HASTE)) { + speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2; + } + if (player().isPotionActive(MobEffects.MINING_FATIGUE)) { + switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) { + case 0: + speed *= 0.3; + break; + case 1: + speed *= 0.09; + break; + case 2: + speed *= 0.0027; + break; + default: + speed *= 0.00081; + break; + } + } + } + speed /= blockHard; + if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) { + return speed / 30; + } else { + return speed / 100; } } }