diff --git a/src/main/java/baritone/bot/Settings.java b/src/main/java/baritone/bot/Settings.java index bb12fcba..f63f5f23 100644 --- a/src/main/java/baritone/bot/Settings.java +++ b/src/main/java/baritone/bot/Settings.java @@ -31,6 +31,11 @@ import java.util.*; public class Settings { public Setting allowBreak = new Setting<>(true); public Setting allowPlaceThrowaway = new Setting<>(true); + /** + * It doesn't actually take twenty ticks to place a block, this cost is so high + * because we want to generally conserve blocks which might be limited + */ + public Setting blockPlacementPenalty = new Setting<>(20D); public Setting allowSprint = new Setting<>(true); public Setting costHeuristic = new Setting(4D); public Setting chuckCaching = new Setting<>(false); @@ -44,7 +49,7 @@ public class Settings { public Setting slowPath = new Setting<>(false); public Setting slowPathTimeDelayMS = new Setting<>(100L); public Setting slowPathTimeoutMS = new Setting<>(40000L); - public Setting> acceptableThrowAwayItems = new Setting<>(Arrays.asList( + public Setting> acceptableThrowawayItems = new Setting<>(Arrays.asList( Item.getItemFromBlock(Blocks.DIRT), Item.getItemFromBlock(Blocks.COBBLESTONE), Item.getItemFromBlock(Blocks.NETHERRACK) diff --git a/src/main/java/baritone/bot/pathing/goals/GoalBlock.java b/src/main/java/baritone/bot/pathing/goals/GoalBlock.java index 2f141444..12048681 100644 --- a/src/main/java/baritone/bot/pathing/goals/GoalBlock.java +++ b/src/main/java/baritone/bot/pathing/goals/GoalBlock.java @@ -68,9 +68,9 @@ public class GoalBlock implements Goal { @Override public double heuristic(BlockPos pos) { - double xDiff = pos.getX() - this.x; - double yDiff = pos.getY() - this.y; - double zDiff = pos.getZ() - this.z; + int xDiff = pos.getX() - this.x; + int yDiff = pos.getY() - this.y; + int zDiff = pos.getZ() - this.z; return calculate(xDiff, yDiff, zDiff); } @@ -86,25 +86,26 @@ public class GoalBlock implements Goal { return new BlockPos(x, y, z); } - public static double calculate(double xDiff, double yDiff, double zDiff) { + public static double calculate(double xDiff, int yDiff, double zDiff) { double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff); double heuristic = 0; - double baseline = (PLACE_ONE_BLOCK_COST + FALL_N_BLOCKS_COST[1]) * 32; if (pythaDist < MAX) {//if we are more than MAX away, ignore the Y coordinate. It really doesn't matter how far away your Y coordinate is if you X coordinate is 1000 blocks away. //as we get closer, slowly reintroduce the Y coordinate as a heuristic cost - double multiplier = pythaDist < MIN ? 1 : 1 - (pythaDist - MIN) / (MAX - MIN); - if (yDiff < 0) {//pos.getY()-this.y<0 therefore pos.getY() level) { + // need to descend + return FALL_N_BLOCKS_COST[pos.getY() - level]; + } + if (pos.getY() < level) { + // need to ascend + return (level - pos.getY()) * JUMP_ONE_BLOCK_COST; + } + return 0; } @Override diff --git a/src/main/java/baritone/bot/pathing/movement/ActionCosts.java b/src/main/java/baritone/bot/pathing/movement/ActionCosts.java index ee0eb907..3d9667f3 100644 --- a/src/main/java/baritone/bot/pathing/movement/ActionCosts.java +++ b/src/main/java/baritone/bot/pathing/movement/ActionCosts.java @@ -38,12 +38,6 @@ public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieI */ double CENTER_AFTER_FALL_COST = WALK_ONE_BLOCK_COST - WALK_OFF_BLOCK_COST; - /** - * It doesn't actually take ten ticks to place a block, this cost is so high - * because we want to generally conserve blocks which might be limited - */ - double PLACE_ONE_BLOCK_COST = 20; - /** * don't make this Double.MAX_VALUE because it's added to other things, maybe other COST_INFs, * and that would make it overflow to negative diff --git a/src/main/java/baritone/bot/pathing/movement/CalculationContext.java b/src/main/java/baritone/bot/pathing/movement/CalculationContext.java index 88a419bf..0f4026be 100644 --- a/src/main/java/baritone/bot/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/bot/pathing/movement/CalculationContext.java @@ -36,6 +36,8 @@ public class CalculationContext implements Helper { private final boolean hasWaterBucket; private final boolean hasThrowaway; private final boolean canSprint; + private final double placeBlockCost; + private final boolean allowBreak; public CalculationContext() { this(new ToolSet()); @@ -44,9 +46,14 @@ public class CalculationContext implements Helper { public CalculationContext(ToolSet toolSet) { player().setSprinting(true); this.toolSet = toolSet; - this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether(); this.hasThrowaway = Baritone.settings().allowPlaceThrowaway.get() && MovementHelper.throwaway(false); + this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether(); this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6; + this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get(); + this.allowBreak = Baritone.settings().allowBreak.get(); + // why cache these things here, why not let the movements just get directly from settings? + // because if some movements are calculated one way and others are calculated another way, + // then you get a wildly inconsistent path that isn't optimal for either scenario. } public ToolSet getToolSet() { @@ -64,4 +71,12 @@ public class CalculationContext implements Helper { public boolean canSprint() { return canSprint; } + + public double placeBlockCost() { + return placeBlockCost; + } + + public boolean allowBreak() { + return allowBreak; + } } diff --git a/src/main/java/baritone/bot/pathing/movement/Movement.java b/src/main/java/baritone/bot/pathing/movement/Movement.java index b1f8124b..da32c4f7 100644 --- a/src/main/java/baritone/bot/pathing/movement/Movement.java +++ b/src/main/java/baritone/bot/pathing/movement/Movement.java @@ -178,7 +178,7 @@ public abstract class Movement implements Helper, MovementHelper { } - public double getTotalHardnessOfBlocksToBreak(ToolSet ts) { + public double getTotalHardnessOfBlocksToBreak(CalculationContext ctx) { /* double sum = 0; HashSet toBreak = new HashSet(); @@ -209,7 +209,7 @@ public abstract class Movement implements Helper, MovementHelper { //^ the above implementation properly deals with falling blocks, TODO integrate double sum = 0; for (BlockPos pos : positionsToBreak) { - sum += MovementHelper.getMiningDurationTicks(ts, pos); + sum += MovementHelper.getMiningDurationTicks(ctx, pos); if (sum >= COST_INF) { return COST_INF; } diff --git a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java index 65a645ff..0931bc16 100644 --- a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java @@ -161,22 +161,22 @@ public interface MovementHelper extends ActionCosts, Helper { return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling; } - static double getMiningDurationTicks(ToolSet ts, BlockPos position) { + static double getMiningDurationTicks(CalculationContext context, BlockPos position) { IBlockState state = BlockStateInterface.get(position); - return getMiningDurationTicks(ts, position, state); + return getMiningDurationTicks(context, position, state); } - static double getMiningDurationTicks(ToolSet ts, BlockPos position, IBlockState state) { + static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state) { Block block = state.getBlock(); - if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { - if (!Baritone.settings().allowBreak.get()) { + if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough? + if (!context.allowBreak()) { return COST_INF; } if (avoidBreaking(position, state)) { return COST_INF; } - double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; - return m / ts.getStrVsBlock(state, position); + 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 + return m / context.getToolSet().getStrVsBlock(state, position); } return 0; } @@ -230,7 +230,12 @@ public interface MovementHelper extends ActionCosts, Helper { NonNullList inv = p.inventory.mainInventory; for (byte i = 0; i < 9; i++) { ItemStack item = inv.get(i); - if (Baritone.settings().acceptableThrowAwayItems.get().contains(item.getItem())) { + // this usage of settings() is okay because it's only called once during pathing + // (while creating the CalculationContext at the very beginning) + // and then it's called during execution + // since this function is never called during cost calculation, we don't need to migrate + // acceptableThrowawayItems to the CalculationContext + if (Baritone.settings().acceptableThrowawayItems.get().contains(item.getItem())) { if (select) { p.inventory.currentItem = i; } diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementAscend.java index 803c5d1c..19736ad3 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementAscend.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementAscend.java @@ -77,7 +77,7 @@ public class MovementAscend extends Movement { } for (BlockPos against1 : against) { if (BlockStateInterface.get(against1).isBlockNormalCube()) { - return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); } } return COST_INF; @@ -109,7 +109,7 @@ public class MovementAscend extends Movement { walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST; } // we hit space immediately on entering this action - return Math.max(JUMP_ONE_BLOCK_COST, walk) + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return Math.max(JUMP_ONE_BLOCK_COST, walk) + getTotalHardnessOfBlocksToBreak(context); } @Override diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java index 202e9f6f..d7b429a7 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementDescend.java @@ -51,7 +51,7 @@ public class MovementDescend extends Movement { // use this ratio to apply the soul sand speed penalty to our 0.8 block distance walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST; } - return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context); } int numTicks = 0; diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementDiagonal.java index c0d69b2e..468958f8 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementDiagonal.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementDiagonal.java @@ -93,8 +93,8 @@ public class MovementDiagonal extends Movement { if (BlockStateInterface.get(positionsToBreak[4].down()).getBlock() instanceof BlockMagma) { return COST_INF; } - double optionA = MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[1]); - double optionB = MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[2]) + MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[3]); + double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]); + double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3]); if (optionA != 0 && optionB != 0) { return COST_INF; } diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java index b8145e94..3f5b64ab 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java @@ -47,7 +47,7 @@ public class MovementDownward extends Movement { if (ladder) { return LADDER_DOWN_ONE_COST; } else { - return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context.getToolSet(), dest, d); + return FALL_N_BLOCKS_COST[1] + MovementHelper.getMiningDurationTicks(context, dest, d); } } diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java index 4b733284..2cda3b63 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementFall.java @@ -18,7 +18,10 @@ package baritone.bot.pathing.movement.movements; import baritone.bot.behavior.impl.LookBehaviorUtils; -import baritone.bot.pathing.movement.*; +import baritone.bot.pathing.movement.CalculationContext; +import baritone.bot.pathing.movement.Movement; +import baritone.bot.pathing.movement.MovementHelper; +import baritone.bot.pathing.movement.MovementState; import baritone.bot.pathing.movement.MovementState.MovementStatus; import baritone.bot.pathing.movement.MovementState.MovementTarget; import baritone.bot.utils.BlockStateInterface; @@ -52,9 +55,9 @@ public class MovementFall extends Movement { if (!context.hasWaterBucket()) { return COST_INF; } - placeBucketCost = ActionCosts.PLACE_ONE_BLOCK_COST; + placeBucketCost = context.placeBlockCost(); } - double frontTwo = MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[1]); + double frontTwo = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]); if (frontTwo >= COST_INF) { return COST_INF; } @@ -64,7 +67,7 @@ public class MovementFall extends Movement { // lilypads (i think?) are 0 ticks to mine, but they definitely cause fall damage // same thing for falling through water... we can't actually do that // and falling through signs is possible, but they do have a mining duration, right? - if (MovementHelper.getMiningDurationTicks(context.getToolSet(), positionsToBreak[i]) > 0) { + if (MovementHelper.getMiningDurationTicks(context, positionsToBreak[i]) > 0) { //can't break while falling return COST_INF; } diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java index 95a836c5..29463a69 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java @@ -56,7 +56,7 @@ public class MovementPillar extends Movement { return COST_INF; } } - double hardness = getTotalHardnessOfBlocksToBreak(context.getToolSet()); + double hardness = getTotalHardnessOfBlocksToBreak(context); if (hardness != 0) { Block tmp = BlockStateInterface.get(src.up(2)).getBlock(); if (tmp instanceof BlockLadder || tmp instanceof BlockVine) { @@ -78,7 +78,7 @@ public class MovementPillar extends Movement { if (ladder) { return LADDER_UP_ONE_COST + hardness; } else { - return JUMP_ONE_BLOCK_COST + PLACE_ONE_BLOCK_COST + hardness; + return JUMP_ONE_BLOCK_COST + context.placeBlockCost() + hardness; } } diff --git a/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java index b92a021c..52b8575e 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementTraverse.java @@ -94,7 +94,7 @@ public class MovementTraverse extends Movement { //double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]); //double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]); //Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")"); - return WC + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return WC + getTotalHardnessOfBlocksToBreak(context); } else {//this is a bridge, so we need to place a block Block srcDown = BlockStateInterface.get(src.down()).getBlock(); if (srcDown instanceof BlockLadder || srcDown instanceof BlockVine) { @@ -108,14 +108,14 @@ public class MovementTraverse extends Movement { double WC = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock()) ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST; for (BlockPos against1 : against) { if (BlockStateInterface.get(against1).isBlockNormalCube()) { - return WC + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); } } if (BlockStateInterface.get(src).getBlock().equals(Blocks.SOUL_SAND)) { return COST_INF; // can't sneak and backplace against soul sand =/ } WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking - return WC + PLACE_ONE_BLOCK_COST + getTotalHardnessOfBlocksToBreak(context.getToolSet()); + return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context); } return COST_INF; //Out.log("Can't walk on " + Baritone.get(positionsToPlace[0]).getBlock());