betterblockpos

This commit is contained in:
Leijurv 2018-08-14 10:47:31 -07:00
parent 46593fc1a4
commit 60d246ecc9
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
10 changed files with 159 additions and 62 deletions

View File

@ -33,6 +33,7 @@ public class Settings {
public boolean chatDebug = true; public boolean chatDebug = true;
public boolean chatControl = true; public boolean chatControl = true;
public boolean fadePath = true; public boolean fadePath = true;
public boolean slowPath = false;
Settings() { Settings() {

View File

@ -46,6 +46,7 @@ import baritone.bot.pathing.movement.MovementHelper;
import baritone.bot.pathing.movement.movements.*; import baritone.bot.pathing.movement.movements.*;
import baritone.bot.pathing.path.IPath; import baritone.bot.pathing.path.IPath;
import baritone.bot.utils.Helper; import baritone.bot.utils.Helper;
import baritone.bot.utils.pathing.BetterBlockPos;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -61,8 +62,6 @@ import java.util.Random;
*/ */
public class AStarPathFinder extends AbstractNodeCostSearch implements Helper { public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
public static boolean slowPath = false;
public AStarPathFinder(BlockPos start, Goal goal) { public AStarPathFinder(BlockPos start, Goal goal) {
super(start, goal); super(start, goal);
} }
@ -82,14 +81,14 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
} }
currentlyRunning = this; currentlyRunning = this;
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
long timeoutTime = startTime + (slowPath ? 40000 : 4000); long timeoutTime = startTime + (Baritone.settings().slowPath ? 40000 : 4000);
long lastPrintout = 0; long lastPrintout = 0;
int numNodes = 0; int numNodes = 0;
CalculationContext calcContext = new CalculationContext(); CalculationContext calcContext = new CalculationContext();
int numEmptyChunk = 0; int numEmptyChunk = 0;
boolean cache = Baritone.settings().chuckCaching; boolean cache = Baritone.settings().chuckCaching;
while (!openSet.isEmpty() && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) { while (!openSet.isEmpty() && numEmptyChunk < 50 && System.currentTimeMillis() < timeoutTime) {
if (slowPath) { if (Baritone.settings().slowPath) {
try { try {
Thread.sleep(100); Thread.sleep(100);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
@ -98,7 +97,7 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
PathNode currentNode = openSet.removeLowest(); PathNode currentNode = openSet.removeLowest();
currentNode.isOpen = false; currentNode.isOpen = false;
mostRecentConsidered = currentNode; mostRecentConsidered = currentNode;
BlockPos currentNodePos = currentNode.pos; BetterBlockPos currentNodePos = currentNode.pos;
numNodes++; numNodes++;
if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second
System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far"); 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) { if (actionCost <= 0) {
throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " calculated implausible cost " + actionCost); 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; double tentativeCost = currentNode.cost + actionCost;
if (tentativeCost < neighbor.cost) { if (tentativeCost < neighbor.cost) {
if (tentativeCost < 0) { 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 x = pos.getX();
int y = pos.getY(); int y = pos.getY();
int z = pos.getZ(); 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[]{ return new Movement[]{
new MovementTraverse(pos, new BlockPos(x + 1, y, z)), new MovementTraverse(pos, east),
new MovementTraverse(pos, new BlockPos(x - 1, y, z)), new MovementTraverse(pos, west),
new MovementTraverse(pos, new BlockPos(x, y, z + 1)), new MovementTraverse(pos, north),
new MovementTraverse(pos, new BlockPos(x, y, z - 1)), new MovementTraverse(pos, south),
new MovementAscend(pos, new BlockPos(x + 1, y + 1, z)), new MovementAscend(pos, new BetterBlockPos(x + 1, y + 1, z)),
new MovementAscend(pos, new BlockPos(x - 1, y + 1, z)), new MovementAscend(pos, new BetterBlockPos(x - 1, y + 1, z)),
new MovementAscend(pos, new BlockPos(x, y + 1, z + 1)), new MovementAscend(pos, new BetterBlockPos(x, y + 1, z + 1)),
new MovementAscend(pos, new BlockPos(x, y + 1, z - 1)), new MovementAscend(pos, new BetterBlockPos(x, y + 1, z - 1)),
MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.NORTH, calcContext), MovementHelper.generateMovementFallOrDescend(pos, east, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.SOUTH, calcContext), MovementHelper.generateMovementFallOrDescend(pos, west, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.EAST, calcContext), MovementHelper.generateMovementFallOrDescend(pos, north, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, EnumFacing.WEST, calcContext), MovementHelper.generateMovementFallOrDescend(pos, south, calcContext),
new MovementDownward(pos), new MovementDownward(pos, new BetterBlockPos(x, y - 1, z)),
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST), new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST),
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST), new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST),
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST), new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST),
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST), new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST),
new MovementPillar(pos) new MovementPillar(pos, new BetterBlockPos(x, y + 1, z))
}; };
} }

View File

@ -19,6 +19,7 @@ package baritone.bot.pathing.calc;
import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.goals.Goal;
import baritone.bot.pathing.path.IPath; import baritone.bot.pathing.path.IPath;
import baritone.bot.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.HashMap; import java.util.HashMap;
@ -37,11 +38,11 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
*/ */
protected static AbstractNodeCostSearch currentlyRunning = null; protected static AbstractNodeCostSearch currentlyRunning = null;
protected final BlockPos start; protected final BetterBlockPos start;
protected final Goal goal; protected final Goal goal;
protected final Map<BlockPos, PathNode> map; protected final Map<BetterBlockPos, PathNode> map;
protected PathNode startNode; protected PathNode startNode;
@ -64,14 +65,14 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
protected final static double MIN_DIST_PATH = 5; protected final static double MIN_DIST_PATH = 5;
AbstractNodeCostSearch(BlockPos start, Goal goal) { AbstractNodeCostSearch(BlockPos start, Goal goal) {
this.start = start; this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
this.goal = goal; this.goal = goal;
this.map = new HashMap<>(); this.map = new HashMap<>();
} }
public synchronized Optional<IPath> calculate() { public synchronized Optional<IPath> calculate() {
if (isFinished) { 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<IPath> path = calculate0(); Optional<IPath> path = calculate0();
isFinished = true; isFinished = true;
@ -114,7 +115,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* @param pos The pos to lookup * @param pos The pos to lookup
* @return The associated node * @return The associated node
*/ */
protected PathNode getNodeAtPosition(BlockPos pos) { protected PathNode getNodeAtPosition(BetterBlockPos pos) {
return map.computeIfAbsent(pos, p -> new PathNode(p, goal)); return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
} }

View File

@ -19,7 +19,7 @@ package baritone.bot.pathing.calc;
import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.goals.Goal;
import baritone.bot.pathing.movement.Movement; 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. * 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 * The position of this node
*/ */
final BlockPos pos; final BetterBlockPos pos;
/** /**
* The goal it's going towards * The goal it's going towards
@ -78,9 +78,7 @@ public class PathNode {
*/ */
public int heapPosition; public int heapPosition;
public final int hashCode; public PathNode(BetterBlockPos pos, Goal goal) {
public PathNode(BlockPos pos, Goal goal) {
this.pos = pos; this.pos = pos;
this.previous = null; this.previous = null;
this.cost = Short.MAX_VALUE; this.cost = Short.MAX_VALUE;
@ -88,7 +86,6 @@ public class PathNode {
this.estimatedCostToGoal = goal.heuristic(pos); this.estimatedCostToGoal = goal.heuristic(pos);
this.previousMovement = null; this.previousMovement = null;
this.isOpen = false; this.isOpen = false;
this.hashCode = calcHashCode();
} }
/** /**
@ -101,25 +98,6 @@ public class PathNode {
throw new IllegalStateException(); 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 @Override
public boolean equals(Object obj) { public boolean equals(Object obj) {
// GOTTA GO FAST // GOTTA GO FAST

View File

@ -21,7 +21,9 @@ import baritone.bot.Baritone;
import baritone.bot.behavior.impl.LookBehavior; import baritone.bot.behavior.impl.LookBehavior;
import baritone.bot.behavior.impl.LookBehaviorUtils; import baritone.bot.behavior.impl.LookBehaviorUtils;
import baritone.bot.pathing.movement.MovementState.MovementStatus; 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.BlockStateInterface;
import baritone.bot.utils.Helper; import baritone.bot.utils.Helper;
import baritone.bot.utils.Rotation; import baritone.bot.utils.Rotation;
@ -77,7 +79,7 @@ public abstract class Movement implements Helper, MovementHelper {
return cost; return cost;
} }
private double calculateCost0(CalculationContext context){ private double calculateCost0(CalculationContext context) {
if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) { if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) {
Block fromDown = BlockStateInterface.get(src.down()).getBlock(); Block fromDown = BlockStateInterface.get(src.down()).getBlock();
if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) { if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) {

View File

@ -32,7 +32,6 @@ import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
@ -219,8 +218,7 @@ public interface MovementHelper extends ActionCosts, Helper {
).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); ).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
} }
static Movement generateMovementFallOrDescend(BlockPos pos, EnumFacing direction, CalculationContext calcContext) { static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
BlockPos dest = pos.offset(direction);
// A // A
//SA //SA
// B // B

View File

@ -31,8 +31,8 @@ public class MovementDownward extends Movement {
private int numTicks = 0; private int numTicks = 0;
public MovementDownward(BlockPos start) { public MovementDownward(BlockPos start, BlockPos end) {
super(start, start.down(), new BlockPos[]{start.down()}, new BlockPos[0]); super(start, end, new BlockPos[]{end}, new BlockPos[0]);
} }
@Override @Override

View File

@ -34,8 +34,8 @@ import net.minecraft.util.math.BlockPos;
public class MovementPillar extends Movement { public class MovementPillar extends Movement {
private int numTicks = 0; private int numTicks = 0;
public MovementPillar(BlockPos start) { public MovementPillar(BlockPos start, BlockPos end) {
super(start, start.up(), new BlockPos[]{start.up(2)}, new BlockPos[]{start}); super(start, end, new BlockPos[]{start.up(2)}, new BlockPos[]{start});
} }
@Override @Override

View File

@ -21,7 +21,6 @@ import baritone.bot.Baritone;
import baritone.bot.behavior.Behavior; import baritone.bot.behavior.Behavior;
import baritone.bot.behavior.impl.PathingBehavior; import baritone.bot.behavior.impl.PathingBehavior;
import baritone.bot.event.events.ChatEvent; import baritone.bot.event.events.ChatEvent;
import baritone.bot.pathing.calc.AStarPathFinder;
import baritone.bot.pathing.goals.Goal; import baritone.bot.pathing.goals.Goal;
import baritone.bot.pathing.goals.GoalBlock; import baritone.bot.pathing.goals.GoalBlock;
import baritone.bot.pathing.goals.GoalXZ; import baritone.bot.pathing.goals.GoalXZ;
@ -84,7 +83,7 @@ public class ExampleBaritoneControl extends Behavior {
return; return;
} }
if (msg.toLowerCase().equals("slowpath")) { if (msg.toLowerCase().equals("slowpath")) {
AStarPathFinder.slowPath ^= true; Baritone.settings().slowPath ^= true;
event.cancel(); event.cancel();
return; return;
} }

View File

@ -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 <https://www.gnu.org/licenses/>.
*/
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());
}
}