Allow `autoTool` to pull tools from the inventory

This commit is contained in:
Brady 2023-07-05 21:44:31 -07:00
parent 827ce7e2a8
commit bc18f0eabd
No known key found for this signature in database
GPG Key ID: 73A788379A197567
3 changed files with 60 additions and 56 deletions

View File

@ -23,7 +23,8 @@ import baritone.api.utils.Helper;
import baritone.api.utils.InventorySlot;
import baritone.api.utils.Pair;
import baritone.utils.ToolSet;
import it.unimi.dsi.fastutil.objects.Reference2ReferenceOpenHashMap;
import it.unimi.dsi.fastutil.objects.Reference2BooleanMap;
import it.unimi.dsi.fastutil.objects.Reference2BooleanOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.EntityPlayer;
@ -140,6 +141,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
}
private InventorySlot bestToolAgainst(final Block against, final Class<? extends ItemTool> cla$$) {
// TODO: Replace with ToolSet.getBestSlot
return this.findBestSlotMatching(
Comparator.comparingDouble(stack -> ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState())),
stack -> {
@ -189,11 +191,11 @@ public final class InventoryBehavior extends Behavior implements Helper {
}
public boolean canSelectItem(Predicate<? super ItemStack> desired) {
return this.resolveSelectionStrategy(desired) != null;
return this.resolveSelectionStrategy(this.findSlotMatching(desired)) != null;
}
public boolean trySelectItem(Predicate<? super ItemStack> desired) {
final SelectionStrategy strategy = this.resolveSelectionStrategy(desired);
final SelectionStrategy strategy = this.resolveSelectionStrategy(this.findSlotMatching(desired));
if (strategy != null) {
strategy.run();
// TODO: Consider cases where returning the SelectionType is needed/useful to the caller
@ -202,8 +204,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
return false;
}
public SelectionStrategy resolveSelectionStrategy(Predicate<? super ItemStack> desired) {
final InventorySlot slot = this.findSlotMatching(desired);
public SelectionStrategy resolveSelectionStrategy(final InventorySlot slot) {
if (slot != null) {
switch (slot.getType()) {
case HOTBAR:
@ -232,6 +233,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
if (this.canAccessInventory()) {
return SelectionStrategy.of(SelectionType.ENQUEUED, () -> {
// TODO: Determine if hotbar swap can be immediate, and return type accordingly
// Also don't only swap into slot 7 that's silly
requestSwapWithHotBar(slot.getInventoryIndex(), 7);
ctx.player().inventory.currentItem = 7;
});
@ -244,6 +246,14 @@ public final class InventoryBehavior extends Behavior implements Helper {
return null;
}
public InventorySlot findBestAccessibleMatching(final Comparator<? super ItemStack> comparator,
final Predicate<? super ItemStack> filter) {
final Stream<Pair<InventorySlot, ItemStack>> accessible = this.canAccessInventory()
? ctx.inventory().allSlots()
: Stream.concat(ctx.inventory().hotbarSlots(), Stream.of(ctx.inventory().offhand()));
return this.findBestMatching0(accessible, comparator, filter);
}
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> filter) {
return this.findBestSlotMatching(null, filter);
}
@ -320,7 +330,7 @@ public final class InventoryBehavior extends Behavior implements Helper {
private static final class ItemInteractionHelper {
private static final Map<Class<? extends Item>, Boolean> CACHE = new Reference2ReferenceOpenHashMap<>();
private static final Reference2BooleanMap<Class<? extends Item>> CACHE = new Reference2BooleanOpenHashMap<>();
public static boolean couldInteract(final ItemStack stack) {
if (stack.isEmpty()) {

View File

@ -18,12 +18,12 @@
package baritone.pathing.movement;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.behavior.InventoryBehavior;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.pathing.precompute.Ternary;
import baritone.utils.BlockStateInterface;
@ -592,8 +592,13 @@ public interface MovementHelper extends ActionCosts, Helper {
* @param ts Previously calculated ToolSet
*/
static void switchToBestToolFor(IPlayerContext ctx, IBlockState state, ToolSet ts, boolean preferSilkTouch) {
if (Baritone.settings().autoTool.value && !Baritone.settings().assumeExternalAutoTool.value) {
ctx.player().inventory.currentItem = ts.getBestSlot(state, preferSilkTouch, false);
if (ToolSet.isAutoTool()) {
// TODO: Submit through InventoryBehavior, instead of executing the strategy here
final InventorySlot slot = ts.getBestSlot(state, preferSilkTouch);
final InventoryBehavior.SelectionStrategy strategy = ((Baritone) ctx.baritone()).getInventoryBehavior().resolveSelectionStrategy(slot);
if (strategy != null) {
strategy.run();
}
}
}

View File

@ -20,6 +20,7 @@ package baritone.utils;
import baritone.Baritone;
import baritone.PerformanceCritical;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.InventorySlot;
import baritone.utils.accessor.IItemTool;
import it.unimi.dsi.fastutil.HashCommon;
import it.unimi.dsi.fastutil.objects.Reference2DoubleOpenHashMap;
@ -27,11 +28,13 @@ import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Enchantments;
import net.minecraft.init.Items;
import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemSword;
import net.minecraft.item.ItemTool;
import java.util.Comparator;
import java.util.function.ToDoubleFunction;
/**
@ -84,7 +87,9 @@ public final class ToolSet {
* @return A double containing the destruction speed with the best tool
*/
private double getBestDestructionSpeed(IBlockState state) {
final ItemStack stack = ctx.player().inventory.getStackInSlot(this.getBestSlot(state, false, true));
final ItemStack stack = isAutoTool()
? ctx.inventory().itemAt(this.getBestSlot(state, false))
: ctx.player().getHeldItemMainhand();
return calculateSpeedVsBlock(stack, state) * avoidanceMultiplier(state.getBlock());
}
@ -93,13 +98,12 @@ public final class ToolSet {
* harvest level order; there is a chance for multiple at the same with modded tools
* but in that case we don't really care.
*
* @param itemStack a possibly empty ItemStack
* @param stack a possibly empty ItemStack
* @return The tool's harvest level, or {@code -1} if the stack isn't a tool
*/
private static int getMaterialCost(ItemStack itemStack) {
if (itemStack.getItem() instanceof ItemTool) {
ItemTool tool = (ItemTool) itemStack.getItem();
return ((IItemTool) tool).getHarvestLevel();
private static int getMaterialCost(ItemStack stack) {
if (stack.getItem() instanceof IItemTool) {
return ((IItemTool) stack.getItem()).getHarvestLevel();
} else {
return -1;
}
@ -111,51 +115,36 @@ public final class ToolSet {
*
* @param state the blockstate to be mined
* @param preferSilkTouch whether to prefer silk touch tools
* @param pathingCalculation whether the call to this method is for pathing calculation
* @return An int containing the index in the tools array that worked best
*/
public int getBestSlot(IBlockState state, boolean preferSilkTouch, boolean pathingCalculation) {
public InventorySlot getBestSlot(IBlockState state, boolean preferSilkTouch) {
final Comparator<ItemStack> compare = Comparator
// Prioritize mining speed over everything
.<ItemStack>comparingDouble(stack -> calculateSpeedVsBlock(stack, state))
// Prioritize silk touch tools, if preferSilkTouch is true, over reduced material cost
.thenComparing(ToolSet::hasSilkTouch, (a, b) -> preferSilkTouch ? Boolean.compare(a, b) : 0)
// Minimize material cost
.thenComparing(Comparator.comparingInt(ToolSet::getMaterialCost).reversed());
/*
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().autoTool.value && pathingCalculation) {
return ctx.player().inventory.currentItem;
}
int best = 0;
double highestSpeed = Double.NEGATIVE_INFINITY;
int lowestCost = Integer.MIN_VALUE;
boolean bestSilkTouch = false;
for (int i = 0; i < 9; i++) {
ItemStack itemStack = ctx.player().inventory.getStackInSlot(i);
if (!Baritone.settings().useSwordToMine.value && itemStack.getItem() instanceof ItemSword) {
continue;
}
if (Baritone.settings().itemSaver.value && (itemStack.getItemDamage() + Baritone.settings().itemSaverThreshold.value) >= itemStack.getMaxDamage() && itemStack.getMaxDamage() > 1) {
continue;
}
double speed = calculateSpeedVsBlock(itemStack, state);
boolean silkTouch = hasSilkTouch(itemStack);
if (speed > highestSpeed) {
highestSpeed = speed;
best = i;
lowestCost = getMaterialCost(itemStack);
bestSilkTouch = silkTouch;
} else if (speed == highestSpeed) {
int cost = getMaterialCost(itemStack);
if ((cost < lowestCost && (silkTouch || !bestSilkTouch)) ||
(preferSilkTouch && !bestSilkTouch && silkTouch)) {
highestSpeed = speed;
best = i;
lowestCost = cost;
bestSilkTouch = silkTouch;
return ((Baritone) ctx.baritone()).getInventoryBehavior().findBestAccessibleMatching(
compare,
stack -> {
if (!Baritone.settings().useSwordToMine.value && stack.getItem() instanceof ItemSword) {
return false;
}
if (Baritone.settings().itemSaver.value
&& stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value >= stack.getMaxDamage()
&& stack.getMaxDamage() > 1
) {
return false;
}
return true;
}
}
}
return best;
);
}
public static boolean isAutoTool() {
return Baritone.settings().autoTool.value && !Baritone.settings().assumeExternalAutoTool.value;
}
/**