From 60d246ecc9aee8a8df409865bb39643bdce81b5b Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 14 Aug 2018 10:47:31 -0700 Subject: [PATCH] betterblockpos --- src/main/java/baritone/bot/Settings.java | 1 + .../bot/pathing/calc/AStarPathFinder.java | 45 +++---- .../pathing/calc/AbstractNodeCostSearch.java | 11 +- .../baritone/bot/pathing/calc/PathNode.java | 28 +---- .../bot/pathing/movement/Movement.java | 6 +- .../bot/pathing/movement/MovementHelper.java | 4 +- .../movement/movements/MovementDownward.java | 4 +- .../movement/movements/MovementPillar.java | 4 +- .../bot/utils/ExampleBaritoneControl.java | 3 +- .../bot/utils/pathing/BetterBlockPos.java | 115 ++++++++++++++++++ 10 files changed, 159 insertions(+), 62 deletions(-) create mode 100644 src/main/java/baritone/bot/utils/pathing/BetterBlockPos.java diff --git a/src/main/java/baritone/bot/Settings.java b/src/main/java/baritone/bot/Settings.java index d6d1d170..ad93d7fe 100644 --- a/src/main/java/baritone/bot/Settings.java +++ b/src/main/java/baritone/bot/Settings.java @@ -33,6 +33,7 @@ public class Settings { public boolean chatDebug = true; public boolean chatControl = true; public boolean fadePath = true; + public boolean slowPath = false; Settings() { diff --git a/src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java index 3de70552..552aeb4b 100644 --- a/src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/bot/pathing/calc/AStarPathFinder.java @@ -46,6 +46,7 @@ import baritone.bot.pathing.movement.MovementHelper; import baritone.bot.pathing.movement.movements.*; import baritone.bot.pathing.path.IPath; import baritone.bot.utils.Helper; +import baritone.bot.utils.pathing.BetterBlockPos; import net.minecraft.client.Minecraft; import net.minecraft.util.EnumFacing; import net.minecraft.util.math.BlockPos; @@ -61,8 +62,6 @@ import java.util.Random; */ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { - public static boolean slowPath = false; - public AStarPathFinder(BlockPos start, Goal goal) { super(start, goal); } @@ -82,14 +81,14 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { } currentlyRunning = this; long startTime = System.currentTimeMillis(); - long timeoutTime = startTime + (slowPath ? 40000 : 4000); + long timeoutTime = startTime + (Baritone.settings().slowPath ? 40000 : 4000); long lastPrintout = 0; int numNodes = 0; CalculationContext calcContext = new CalculationContext(); int numEmptyChunk = 0; boolean cache = Baritone.settings().chuckCaching; while (!openSet.isEmpty() && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) { - if (slowPath) { + if (Baritone.settings().slowPath) { try { Thread.sleep(100); } catch (InterruptedException ex) { @@ -98,7 +97,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { PathNode currentNode = openSet.removeLowest(); currentNode.isOpen = false; mostRecentConsidered = currentNode; - BlockPos currentNodePos = currentNode.pos; + BetterBlockPos currentNodePos = currentNode.pos; numNodes++; if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far"); @@ -141,7 +140,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { if (actionCost <= 0) { throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " calculated implausible cost " + actionCost); } - PathNode neighbor = getNodeAtPosition(movementToGetToNeighbor.getDest()); + PathNode neighbor = getNodeAtPosition((BetterBlockPos) movementToGetToNeighbor.getDest()); double tentativeCost = currentNode.cost + actionCost; if (tentativeCost < neighbor.cost) { if (tentativeCost < 0) { @@ -195,29 +194,33 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { } - private static Movement[] getConnectedPositions(BlockPos pos, CalculationContext calcContext) { + private static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) { int x = pos.getX(); int y = pos.getY(); int z = pos.getZ(); + BetterBlockPos east = new BetterBlockPos(x + 1, y, z); + BetterBlockPos west = new BetterBlockPos(x - 1, y, z); + BetterBlockPos south = new BetterBlockPos(x, y, z + 1); + BetterBlockPos north = new BetterBlockPos(x, y, z - 1); return new Movement[]{ - new MovementTraverse(pos, new BlockPos(x + 1, y, z)), - new MovementTraverse(pos, new BlockPos(x - 1, y, z)), - new MovementTraverse(pos, new BlockPos(x, y, z + 1)), - new MovementTraverse(pos, new BlockPos(x, y, z - 1)), - new MovementAscend(pos, new BlockPos(x + 1, y + 1, z)), - new MovementAscend(pos, new BlockPos(x - 1, y + 1, z)), - new MovementAscend(pos, new BlockPos(x, y + 1, z + 1)), - new MovementAscend(pos, new BlockPos(x, y + 1, z - 1)), - MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.NORTH, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.SOUTH, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.EAST, calcContext), - MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.WEST, calcContext), - new MovementDownward(pos), + new MovementTraverse(pos, east), + new MovementTraverse(pos, west), + new MovementTraverse(pos, north), + new MovementTraverse(pos, south), + new MovementAscend(pos, new BetterBlockPos(x + 1, y + 1, z)), + new MovementAscend(pos, new BetterBlockPos(x - 1, y + 1, z)), + new MovementAscend(pos, new BetterBlockPos(x, y + 1, z + 1)), + new MovementAscend(pos, new BetterBlockPos(x, y + 1, z - 1)), + MovementHelper.generateMovementFallOrDescend(pos, east, calcContext), + MovementHelper.generateMovementFallOrDescend(pos, west, calcContext), + MovementHelper.generateMovementFallOrDescend(pos, north, calcContext), + MovementHelper.generateMovementFallOrDescend(pos, south, calcContext), + new MovementDownward(pos, new BetterBlockPos(x, y - 1, z)), new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST), new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST), new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST), new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST), - new MovementPillar(pos) + new MovementPillar(pos, new BetterBlockPos(x, y + 1, z)) }; } diff --git a/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java b/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java index 5a1523bd..50a624bc 100644 --- a/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java +++ b/src/main/java/baritone/bot/pathing/calc/AbstractNodeCostSearch.java @@ -19,6 +19,7 @@ package baritone.bot.pathing.calc; import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.path.IPath; +import baritone.bot.utils.pathing.BetterBlockPos; import net.minecraft.util.math.BlockPos; import java.util.HashMap; @@ -37,11 +38,11 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { */ protected static AbstractNodeCostSearch currentlyRunning = null; - protected final BlockPos start; + protected final BetterBlockPos start; protected final Goal goal; - protected final Map map; + protected final Map map; protected PathNode startNode; @@ -64,14 +65,14 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { protected final static double MIN_DIST_PATH = 5; AbstractNodeCostSearch(BlockPos start, Goal goal) { - this.start = start; + this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ()); this.goal = goal; this.map = new HashMap<>(); } public synchronized Optional calculate() { if (isFinished) { - throw new IllegalStateException("Path Finder is currently in use! Wait until complete to reuse!"); + throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!"); } Optional path = calculate0(); isFinished = true; @@ -114,7 +115,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder { * @param pos The pos to lookup * @return The associated node */ - protected PathNode getNodeAtPosition(BlockPos pos) { + protected PathNode getNodeAtPosition(BetterBlockPos pos) { return map.computeIfAbsent(pos, p -> new PathNode(p, goal)); } diff --git a/src/main/java/baritone/bot/pathing/calc/PathNode.java b/src/main/java/baritone/bot/pathing/calc/PathNode.java index 1b872972..fd561320 100644 --- a/src/main/java/baritone/bot/pathing/calc/PathNode.java +++ b/src/main/java/baritone/bot/pathing/calc/PathNode.java @@ -19,7 +19,7 @@ package baritone.bot.pathing.calc; import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.movement.Movement; -import net.minecraft.util.math.BlockPos; +import baritone.bot.utils.pathing.BetterBlockPos; /** * A node in the path, containing the cost and steps to get to it. @@ -31,7 +31,7 @@ public class PathNode { /** * The position of this node */ - final BlockPos pos; + final BetterBlockPos pos; /** * The goal it's going towards @@ -78,9 +78,7 @@ public class PathNode { */ public int heapPosition; - public final int hashCode; - - public PathNode(BlockPos pos, Goal goal) { + public PathNode(BetterBlockPos pos, Goal goal) { this.pos = pos; this.previous = null; this.cost = Short.MAX_VALUE; @@ -88,7 +86,6 @@ public class PathNode { this.estimatedCostToGoal = goal.heuristic(pos); this.previousMovement = null; this.isOpen = false; - this.hashCode = calcHashCode(); } /** @@ -101,25 +98,6 @@ public class PathNode { throw new IllegalStateException(); } - private final int calcHashCode() { - /* - * This is the hashcode implementation of Vec3i, the superclass of BlockPos - * - * public int hashCode() { - * return (this.getY() + this.getZ() * 31) * 31 + this.getX(); - * } - * - * That is terrible and has tons of collisions and makes the HashMap terribly inefficient. - * - * That's why we grab out the X, Y, Z and calculate our own hashcode - */ - int hash = 3241; - hash = 3457689 * hash + this.pos.getX(); - hash = 8734625 * hash + this.pos.getY(); - hash = 2873465 * hash + this.pos.getZ(); - return hash; - } - @Override public boolean equals(Object obj) { // GOTTA GO FAST diff --git a/src/main/java/baritone/bot/pathing/movement/Movement.java b/src/main/java/baritone/bot/pathing/movement/Movement.java index edcca086..9db706b7 100644 --- a/src/main/java/baritone/bot/pathing/movement/Movement.java +++ b/src/main/java/baritone/bot/pathing/movement/Movement.java @@ -21,7 +21,9 @@ import baritone.bot.Baritone; import baritone.bot.behavior.impl.LookBehavior; import baritone.bot.behavior.impl.LookBehaviorUtils; import baritone.bot.pathing.movement.MovementState.MovementStatus; -import baritone.bot.pathing.movement.movements.*; +import baritone.bot.pathing.movement.movements.MovementDownward; +import baritone.bot.pathing.movement.movements.MovementPillar; +import baritone.bot.pathing.movement.movements.MovementTraverse; import baritone.bot.utils.BlockStateInterface; import baritone.bot.utils.Helper; import baritone.bot.utils.Rotation; @@ -77,7 +79,7 @@ public abstract class Movement implements Helper, MovementHelper { return cost; } - private double calculateCost0(CalculationContext context){ + private double calculateCost0(CalculationContext context) { if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) { Block fromDown = BlockStateInterface.get(src.down()).getBlock(); if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) { diff --git a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java index 78b3a4b5..427cf4cb 100644 --- a/src/main/java/baritone/bot/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/bot/pathing/movement/MovementHelper.java @@ -32,7 +32,6 @@ import net.minecraft.entity.Entity; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; -import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.RayTraceResult; @@ -219,8 +218,7 @@ public interface MovementHelper extends ActionCosts, Helper { ).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); } - static Movement generateMovementFallOrDescend(BlockPos pos, EnumFacing direction, CalculationContext calcContext) { - BlockPos dest = pos.offset(direction); + static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) { // A //SA // B 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 bc68e2bc..10c84c5e 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementDownward.java @@ -31,8 +31,8 @@ public class MovementDownward extends Movement { private int numTicks = 0; - public MovementDownward(BlockPos start) { - super(start, start.down(), new BlockPos[]{start.down()}, new BlockPos[0]); + public MovementDownward(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{end}, new BlockPos[0]); } @Override 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 f994c6b1..eace641e 100644 --- a/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java +++ b/src/main/java/baritone/bot/pathing/movement/movements/MovementPillar.java @@ -34,8 +34,8 @@ import net.minecraft.util.math.BlockPos; public class MovementPillar extends Movement { private int numTicks = 0; - public MovementPillar(BlockPos start) { - super(start, start.up(), new BlockPos[]{start.up(2)}, new BlockPos[]{start}); + public MovementPillar(BlockPos start, BlockPos end) { + super(start, end, new BlockPos[]{start.up(2)}, new BlockPos[]{start}); } @Override diff --git a/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java b/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java index fd441000..d4865449 100644 --- a/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java +++ b/src/main/java/baritone/bot/utils/ExampleBaritoneControl.java @@ -21,7 +21,6 @@ import baritone.bot.Baritone; import baritone.bot.behavior.Behavior; import baritone.bot.behavior.impl.PathingBehavior; import baritone.bot.event.events.ChatEvent; -import baritone.bot.pathing.calc.AStarPathFinder; import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.goals.GoalBlock; import baritone.bot.pathing.goals.GoalXZ; @@ -84,7 +83,7 @@ public class ExampleBaritoneControl extends Behavior { return; } if (msg.toLowerCase().equals("slowpath")) { - AStarPathFinder.slowPath ^= true; + Baritone.settings().slowPath ^= true; event.cancel(); return; } diff --git a/src/main/java/baritone/bot/utils/pathing/BetterBlockPos.java b/src/main/java/baritone/bot/utils/pathing/BetterBlockPos.java new file mode 100644 index 00000000..6f010571 --- /dev/null +++ b/src/main/java/baritone/bot/utils/pathing/BetterBlockPos.java @@ -0,0 +1,115 @@ +/* + * 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.bot.utils.pathing; + +import net.minecraft.util.EnumFacing; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3i; + +/** + * A better BlockPos that has fewer hash collisions (and slightly more performant offsets) + * + * @author leijurv + */ +public class BetterBlockPos extends BlockPos { + private final int x; + private final int y; + private final int z; + private final int hashCode; + + public BetterBlockPos(int x, int y, int z) { + super(x, y, z); + this.x = x; + this.y = y; + this.z = z; + /* + * This is the hashcode implementation of Vec3i, the superclass of BlockPos + * + * public int hashCode() { + * return (this.getY() + this.getZ() * 31) * 31 + this.getX(); + * } + * + * That is terrible and has tons of collisions and makes the HashMap terribly inefficient. + * + * That's why we grab out the X, Y, Z and calculate our own hashcode + */ + int hash = 3241; + hash = 3457689 * hash + x; + hash = 8734625 * hash + y; + hash = 2873465 * hash + z; + this.hashCode = hash; + } + + @Override + public int hashCode() { + return hashCode; + } + + @Override + public boolean equals(Object o) { + if (o instanceof BetterBlockPos) { + BetterBlockPos oth = (BetterBlockPos) o; + if (oth.hashCode != hashCode) { + return false; + } + return oth.x == x && oth.y == y && oth.z == z; + } + // during path execution, like "if (whereShouldIBe.equals(whereAmI)) {" + // sometimes we compare a BlockPos to a BetterBlockPos + BlockPos oth = (BlockPos) o; + return oth.getX() == x && oth.getY() == y && oth.getZ() == z; + } + + @Override + public BlockPos up() { + // this is unimaginably faster than blockpos.up + // that literally calls + // this.up(1) + // which calls this.offset(EnumFacing.UP, 1) + // which does return n == 0 ? this : new BlockPos(this.getX() + facing.getXOffset() * n, this.getY() + facing.getYOffset() * n, this.getZ() + facing.getZOffset() * n); + + // how many function calls is that? up(), up(int), offset(EnumFacing, int), new BlockPos, getX, getXOffset, getY, getYOffset, getZ, getZOffset + // that's ten. + // this is one function call. + return new BetterBlockPos(x, y + 1, z); + } + + @Override + public BlockPos up(int amt) { + // see comment in up() + return new BetterBlockPos(x, y + amt, z); + } + + @Override + public BlockPos down() { + // see comment in up() + return new BetterBlockPos(x, y - 1, z); + } + + @Override + public BlockPos down(int amt) { + // see comment in up() + return new BetterBlockPos(x, y - amt, z); + } + + @Override + public BlockPos offset(EnumFacing dir) { + Vec3i vec = dir.getDirectionVec(); + return new BetterBlockPos(x + vec.getX(), y + vec.getY(), z + vec.getZ()); + } +}