fix tool set once and for all, fixes #136
This commit is contained in:
parent
2cf9a3a74b
commit
de84a49391
@ -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 <https://www.gnu.org/licenses/>.
|
|
||||||
*/
|
|
||||||
|
|
||||||
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();
|
|
||||||
}
|
|
||||||
}
|
|
@ -17,7 +17,6 @@
|
|||||||
"MixinGameSettings",
|
"MixinGameSettings",
|
||||||
"MixinGuiContainer",
|
"MixinGuiContainer",
|
||||||
"MixinGuiScreen",
|
"MixinGuiScreen",
|
||||||
"MixinInventoryPlayer",
|
|
||||||
"MixinKeyBinding",
|
"MixinKeyBinding",
|
||||||
"MixinMinecraft",
|
"MixinMinecraft",
|
||||||
"MixinNetHandlerPlayClient",
|
"MixinNetHandlerPlayClient",
|
||||||
|
@ -21,7 +21,6 @@ import baritone.api.event.GameEventHandler;
|
|||||||
import baritone.behavior.Behavior;
|
import baritone.behavior.Behavior;
|
||||||
import baritone.behavior.impl.*;
|
import baritone.behavior.impl.*;
|
||||||
import baritone.utils.InputOverrideHandler;
|
import baritone.utils.InputOverrideHandler;
|
||||||
import baritone.utils.ToolSet;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
@ -82,7 +81,6 @@ public enum Baritone {
|
|||||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||||
registerBehavior(FollowBehavior.INSTANCE);
|
registerBehavior(FollowBehavior.INSTANCE);
|
||||||
registerBehavior(MineBehavior.INSTANCE);
|
registerBehavior(MineBehavior.INSTANCE);
|
||||||
this.gameEventHandler.registerEventListener(ToolSet.INTERNAL_EVENT_LISTENER);
|
|
||||||
}
|
}
|
||||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||||
if (!Files.exists(dir.toPath())) {
|
if (!Files.exists(dir.toPath())) {
|
||||||
|
@ -83,6 +83,11 @@ public class Settings {
|
|||||||
*/
|
*/
|
||||||
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
|
||||||
|
*/
|
||||||
|
public Setting<Boolean> considerPotionEffects = new Setting<>(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This is the big A* setting.
|
* This is the big A* setting.
|
||||||
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
|
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
|
||||||
|
@ -159,11 +159,6 @@ public final class GameEventHandler implements IGameEventListener, Helper {
|
|||||||
dispatch(listener -> listener.onReceivePacket(event));
|
dispatch(listener -> listener.onReceivePacket(event));
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
|
||||||
public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
|
|
||||||
dispatch(listener -> listener.onQueryItemSlotForBlocks(event));
|
|
||||||
}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||||
dispatch(listener -> listener.onPlayerRelativeMove(event));
|
dispatch(listener -> listener.onPlayerRelativeMove(event));
|
||||||
|
@ -74,9 +74,6 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
|||||||
@Override
|
@Override
|
||||||
default void onReceivePacket(PacketEvent event) {}
|
default void onReceivePacket(PacketEvent event) {}
|
||||||
|
|
||||||
@Override
|
|
||||||
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
|
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
|
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
|
||||||
|
|
||||||
|
@ -36,7 +36,6 @@ package baritone.api.event.listener;
|
|||||||
|
|
||||||
import baritone.api.event.events.*;
|
import baritone.api.event.events.*;
|
||||||
import io.netty.util.concurrent.GenericFutureListener;
|
import io.netty.util.concurrent.GenericFutureListener;
|
||||||
import net.minecraft.block.state.IBlockState;
|
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.client.Minecraft;
|
||||||
import net.minecraft.client.entity.EntityPlayerSP;
|
import net.minecraft.client.entity.EntityPlayerSP;
|
||||||
import net.minecraft.client.gui.GuiGameOver;
|
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.renderer.EntityRenderer;
|
||||||
import net.minecraft.client.settings.GameSettings;
|
import net.minecraft.client.settings.GameSettings;
|
||||||
import net.minecraft.entity.Entity;
|
import net.minecraft.entity.Entity;
|
||||||
import net.minecraft.entity.player.InventoryPlayer;
|
|
||||||
import net.minecraft.network.NetworkManager;
|
import net.minecraft.network.NetworkManager;
|
||||||
import net.minecraft.network.Packet;
|
import net.minecraft.network.Packet;
|
||||||
import net.minecraft.util.text.ITextComponent;
|
import net.minecraft.util.text.ITextComponent;
|
||||||
@ -120,14 +118,6 @@ public interface IGameEventListener {
|
|||||||
*/
|
*/
|
||||||
void onReceivePacket(PacketEvent event);
|
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
|
* Run once per game tick from before and after the player's moveRelative method is called
|
||||||
*
|
*
|
||||||
|
@ -149,7 +149,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
|||||||
somethingInTheWay = true;
|
somethingInTheWay = true;
|
||||||
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
||||||
if (reachable.isPresent()) {
|
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);
|
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -261,7 +261,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||||||
return COST_INF;
|
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 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) {
|
if (includeFalling) {
|
||||||
BlockPos up = position.up();
|
BlockPos up = position.up();
|
||||||
IBlockState above = BlockStateInterface.get(up);
|
IBlockState above = BlockStateInterface.get(up);
|
||||||
|
@ -17,55 +17,24 @@
|
|||||||
|
|
||||||
package baritone.utils;
|
package baritone.utils;
|
||||||
|
|
||||||
import baritone.api.event.events.ItemSlotEvent;
|
import baritone.Baritone;
|
||||||
import baritone.api.event.listener.AbstractGameEventListener;
|
|
||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.block.state.IBlockState;
|
import net.minecraft.block.state.IBlockState;
|
||||||
import net.minecraft.client.Minecraft;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.client.entity.EntityPlayerSP;
|
import net.minecraft.init.Enchantments;
|
||||||
import net.minecraft.item.Item;
|
import net.minecraft.init.MobEffects;
|
||||||
import net.minecraft.item.ItemAir;
|
|
||||||
import net.minecraft.item.ItemStack;
|
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.HashMap;
|
||||||
import java.util.List;
|
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cached list of the best tools on the hotbar for any block
|
* 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 {
|
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<ItemTool> 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<Byte> 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<Block, Byte> slotCache = new HashMap<>();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* A cache mapping a {@link Block} to how long it will take to break
|
* A cache mapping a {@link Block} to how long it will take to break
|
||||||
* with this toolset, given the optimum tool is used.
|
* 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)
|
* Create a toolset from the current player's inventory (but don't calculate any hardness values just yet)
|
||||||
*/
|
*/
|
||||||
public ToolSet() {
|
public ToolSet() {}
|
||||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
|
||||||
NonNullList<ItemStack> 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)));
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate which tool on the hotbar is best for mining
|
* 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
|
* @param b the blockstate to be mined
|
||||||
* @return a byte indicating the index in the tools array that worked best
|
* @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;
|
byte best = 0;
|
||||||
float value = -1;
|
double value = -1;
|
||||||
for (byte i = 0; i < tools.size(); i++) {
|
for (byte i = 0; i < 9; i++) {
|
||||||
Item item = tools.get(i);
|
double v = calculateStrVsBlock(i, b);
|
||||||
if (item == null)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
float v = item.getDestroySpeed(new ItemStack(item), b);
|
|
||||||
if (v > value || value == -1) {
|
if (v > value || value == -1) {
|
||||||
value = v;
|
value = v;
|
||||||
best = i;
|
best = i;
|
||||||
@ -123,25 +65,14 @@ public class ToolSet implements Helper {
|
|||||||
return best;
|
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
|
* Using the best tool on the hotbar, how long would it take to mine this block
|
||||||
*
|
*
|
||||||
* @param state the blockstate to be mined
|
* @param state the blockstate to be mined
|
||||||
* @param pos the blockpos to be mined
|
|
||||||
* @return how long it would take in ticks
|
* @return how long it would take in ticks
|
||||||
*/
|
*/
|
||||||
public double getStrVsBlock(IBlockState state, BlockPos pos) {
|
public double getStrVsBlock(IBlockState state) {
|
||||||
return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(state, pos));
|
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.
|
* in this toolset is used.
|
||||||
*
|
*
|
||||||
* @param state the blockstate to be mined
|
* @param state the blockstate to be mined
|
||||||
* @param pos the blockpos to be mined
|
|
||||||
* @return how long it would take in ticks
|
* @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
|
// Calculate the slot with the best item
|
||||||
byte slot = this.getBestSlot(state);
|
ItemStack contents = player().inventory.getStackInSlot(slot);
|
||||||
|
|
||||||
INTERNAL_EVENT_LISTENER.setOverrideSlot(slot);
|
float blockHard = state.getBlockHardness(null, null);
|
||||||
|
if (blockHard < 0) {
|
||||||
// Calculate the relative hardness of the block to the player
|
return 0;
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
final void setOverrideSlot(int overrideSlot) {
|
float speed = contents.getDestroySpeed(state);
|
||||||
this.overrideSlot = overrideSlot;
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user