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;
}
}
}