tool set, fixes #227
This commit is contained in:
parent
b55d96169f
commit
9a1aecc002
@ -400,7 +400,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||||||
* @param ts previously calculated ToolSet
|
* @param ts previously calculated ToolSet
|
||||||
*/
|
*/
|
||||||
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
||||||
mc.player.inventory.currentItem = ts.getBestSlot(b);
|
mc.player.inventory.currentItem = ts.getBestSlot(b.getBlock());
|
||||||
}
|
}
|
||||||
|
|
||||||
static boolean throwaway(boolean select) {
|
static boolean throwaway(boolean select) {
|
||||||
|
@ -23,42 +23,42 @@ import net.minecraft.block.state.IBlockState;
|
|||||||
import net.minecraft.enchantment.EnchantmentHelper;
|
import net.minecraft.enchantment.EnchantmentHelper;
|
||||||
import net.minecraft.init.Enchantments;
|
import net.minecraft.init.Enchantments;
|
||||||
import net.minecraft.init.MobEffects;
|
import net.minecraft.init.MobEffects;
|
||||||
|
import net.minecraft.item.Item.ToolMaterial;
|
||||||
import net.minecraft.item.ItemStack;
|
import net.minecraft.item.ItemStack;
|
||||||
|
import net.minecraft.item.ItemTool;
|
||||||
|
|
||||||
import java.util.HashMap;
|
import java.util.HashMap;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
import java.util.function.Function;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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, leijurv
|
* @author Avery, Brady, leijurv
|
||||||
*/
|
*/
|
||||||
public class ToolSet implements Helper {
|
public class ToolSet implements Helper {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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.
|
||||||
*/
|
*/
|
||||||
private Map<Block, Double> breakStrengthCache = new HashMap<>();
|
private final Map<Block, Double> breakStrengthCache;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Calculate which tool on the hotbar is best for mining
|
* My buddy leijurv owned me so we have this to not create a new lambda instance.
|
||||||
*
|
|
||||||
* @param b the blockstate to be mined
|
|
||||||
* @return a byte indicating the index in the tools array that worked best
|
|
||||||
*/
|
*/
|
||||||
public byte getBestSlot(IBlockState b) {
|
private final Function<Block, Double> backendCalculation;
|
||||||
byte best = 0;
|
|
||||||
double value = -1;
|
public ToolSet() {
|
||||||
for (byte i = 0; i < 9; i++) {
|
breakStrengthCache = new HashMap<>();
|
||||||
double v = calculateStrVsBlock(i, b);
|
|
||||||
if (v > value || value == -1) {
|
if (Baritone.settings().considerPotionEffects.get()) {
|
||||||
value = v;
|
double amplifier = potionAmplifier();
|
||||||
best = i;
|
Function<Double, Double> amplify = x -> amplifier * x;
|
||||||
|
backendCalculation = amplify.compose(this::getBestDestructionTime);
|
||||||
|
} else {
|
||||||
|
backendCalculation = this::getBestDestructionTime;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return best;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* 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
|
||||||
@ -67,14 +67,64 @@ public class ToolSet implements Helper {
|
|||||||
* @return how long it would take in ticks
|
* @return how long it would take in ticks
|
||||||
*/
|
*/
|
||||||
public double getStrVsBlock(IBlockState state) {
|
public double getStrVsBlock(IBlockState state) {
|
||||||
Double strength = this.breakStrengthCache.get(state.getBlock());
|
return breakStrengthCache.computeIfAbsent(state.getBlock(), backendCalculation);
|
||||||
if (strength != null) {
|
|
||||||
// the function will take this path >99% of the time
|
|
||||||
return strength;
|
|
||||||
}
|
}
|
||||||
double str = calculateStrVsBlock(getBestSlot(state), state);
|
|
||||||
this.breakStrengthCache.put(state.getBlock(), str);
|
/**
|
||||||
return str;
|
* Evaluate the material cost of a possible tool. The priority matches the
|
||||||
|
* listed order in the Item.ToolMaterial enum.
|
||||||
|
*
|
||||||
|
* @param itemStack a possibly empty ItemStack
|
||||||
|
* @return values range from -1 to 4
|
||||||
|
*/
|
||||||
|
private int getMaterialCost(ItemStack itemStack) {
|
||||||
|
if (itemStack.getItem() instanceof ItemTool) {
|
||||||
|
ItemTool tool = (ItemTool) itemStack.getItem();
|
||||||
|
return ToolMaterial.valueOf(tool.getToolMaterialName()).ordinal();
|
||||||
|
} else {
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate which tool on the hotbar is best for mining
|
||||||
|
*
|
||||||
|
* @param b the blockstate to be mined
|
||||||
|
* @return A byte containing the index in the tools array that worked best
|
||||||
|
*/
|
||||||
|
public byte getBestSlot(Block b) {
|
||||||
|
byte best = 0;
|
||||||
|
double value = Double.NEGATIVE_INFINITY;
|
||||||
|
int materialCost = Integer.MIN_VALUE;
|
||||||
|
IBlockState blockState = b.getDefaultState();
|
||||||
|
for (byte i = 0; i < 9; i++) {
|
||||||
|
ItemStack itemStack = player().inventory.getStackInSlot(i);
|
||||||
|
double v = calculateStrVsBlock(itemStack, blockState);
|
||||||
|
if (v > value) {
|
||||||
|
value = v;
|
||||||
|
best = i;
|
||||||
|
materialCost = getMaterialCost(itemStack);
|
||||||
|
} else if (v == value) {
|
||||||
|
int c = getMaterialCost(itemStack);
|
||||||
|
if (c < materialCost) {
|
||||||
|
value = v;
|
||||||
|
best = i;
|
||||||
|
materialCost = c;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return best;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculate how effectively a block can be destroyed
|
||||||
|
*
|
||||||
|
* @param b the blockstate to be mined
|
||||||
|
* @return A double containing the destruction ticks with the best tool
|
||||||
|
*/
|
||||||
|
private double getBestDestructionTime(Block b) {
|
||||||
|
ItemStack stack = player().inventory.getStackInSlot(getBestSlot(b));
|
||||||
|
return calculateStrVsBlock(stack, b.getDefaultState());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -84,24 +134,36 @@ public class ToolSet implements Helper {
|
|||||||
* @param state the blockstate to be mined
|
* @param state the blockstate to be mined
|
||||||
* @return how long it would take in ticks
|
* @return how long it would take in ticks
|
||||||
*/
|
*/
|
||||||
private double calculateStrVsBlock(byte slot, IBlockState state) {
|
private double calculateStrVsBlock(ItemStack item, IBlockState state) {
|
||||||
// Calculate the slot with the best item
|
float hardness = state.getBlockHardness(null, null);
|
||||||
ItemStack contents = player().inventory.getStackInSlot(slot);
|
if (hardness < 0) {
|
||||||
|
|
||||||
float blockHard = state.getBlockHardness(null, null);
|
|
||||||
if (blockHard < 0) {
|
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
float speed = contents.getDestroySpeed(state);
|
float speed = item.getDestroySpeed(state);
|
||||||
if (speed > 1) {
|
if (speed > 1) {
|
||||||
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents);
|
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, item);
|
||||||
if (effLevel > 0 && !contents.isEmpty()) {
|
if (effLevel > 0 && !item.isEmpty()) {
|
||||||
speed += effLevel * effLevel + 1;
|
speed += effLevel * effLevel + 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (Baritone.settings().considerPotionEffects.get()) {
|
speed /= hardness;
|
||||||
|
if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) {
|
||||||
|
speed /= 30;
|
||||||
|
} else {
|
||||||
|
speed /= 100;
|
||||||
|
}
|
||||||
|
return speed;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Calculates any modifier to breaking time based on status effects.
|
||||||
|
*
|
||||||
|
* @return a double to scale block breaking speed.
|
||||||
|
*/
|
||||||
|
private double potionAmplifier() {
|
||||||
|
double speed = 1;
|
||||||
if (player().isPotionActive(MobEffects.HASTE)) {
|
if (player().isPotionActive(MobEffects.HASTE)) {
|
||||||
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||||
}
|
}
|
||||||
@ -121,12 +183,6 @@ public class ToolSet implements Helper {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
return speed;
|
||||||
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