Merge pull request #214 from cabaletta/path-api

Pathing API
This commit is contained in:
Brady 2018-10-09 00:14:25 -05:00 committed by GitHub
commit 5da9347e2c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
32 changed files with 467 additions and 183 deletions

View File

@ -17,7 +17,10 @@
package baritone.api.behavior; package baritone.api.behavior;
import baritone.api.pathing.calc.IPathFinder;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.path.IPathExecutor;
import java.util.Optional; import java.util.Optional;
@ -65,4 +68,30 @@ public interface IPathingBehavior extends IBehavior {
* Cancels the pathing behavior or the current path calculation. * Cancels the pathing behavior or the current path calculation.
*/ */
void cancel(); void cancel();
/**
* Returns the current path, from the current path executor, if there is one.
*
* @return The current path
*/
default Optional<IPath> getPath() {
return Optional.ofNullable(getCurrent()).map(IPathExecutor::getPath);
}
/**
* @return The current path finder being executed
*/
Optional<IPathFinder> getPathFinder();
/**
* @return The current path executor
*/
IPathExecutor getCurrent();
/**
* Returns the next path executor, created when planning ahead.
*
* @return The next path executor
*/
IPathExecutor getNext();
} }

View File

@ -15,37 +15,35 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone.pathing.path; package baritone.api.pathing.calc;
import baritone.Baritone; import baritone.api.Settings;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.pathing.movement.Movement; import baritone.api.pathing.movement.IMovement;
import baritone.utils.Helper; import baritone.api.utils.BetterBlockPos;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.List; import java.util.List;
/** /**
* @author leijurv * @author leijurv, Brady
*/ */
public interface IPath extends Helper { public interface IPath {
/** /**
* Ordered list of movements to carry out. * Ordered list of movements to carry out.
* movements.get(i).getSrc() should equal positions.get(i) * movements.get(i).getSrc() should equal positions.get(i)
* movements.get(i).getDest() should equal positions.get(i+1) * movements.get(i).getDest() should equal positions.get(i+1)
* movements.size() should equal positions.size()-1 * movements.size() should equal positions.size()-1
*
* @return All of the movements to carry out
*/ */
List<Movement> movements(); List<IMovement> movements();
/** /**
* All positions along the way. * All positions along the way.
* Should begin with the same as getSrc and end with the same as getDest * Should begin with the same as getSrc and end with the same as getDest
*
* @return All of the positions along this path
*/ */
List<BetterBlockPos> positions(); List<BetterBlockPos> positions();
@ -53,10 +51,10 @@ public interface IPath extends Helper {
* This path is actually going to be executed in the world. Do whatever additional processing is required. * This path is actually going to be executed in the world. Do whatever additional processing is required.
* (as opposed to Path objects that are just constructed every frame for rendering) * (as opposed to Path objects that are just constructed every frame for rendering)
*/ */
default void postprocess() {} default void postProcess() {}
/** /**
* Number of positions in this path * Returns the number of positions in this path. Equivalent to {@code positions().size()}.
* *
* @return Number of positions in this path * @return Number of positions in this path
*/ */
@ -65,74 +63,74 @@ public interface IPath extends Helper {
} }
/** /**
* What goal was this path calculated towards? * @return The goal that this path was calculated towards
*
* @return
*/ */
Goal getGoal(); Goal getGoal();
default Tuple<Double, BlockPos> closestPathPos() { /**
double best = -1; * Returns the number of nodes that were considered during calculation before
BlockPos bestPos = null; * this path was found.
for (BlockPos pos : positions()) { *
double dist = Utils.playerDistanceToCenter(pos); * @return The number of nodes that were considered before finding this path
if (dist < best || best == -1) { */
best = dist; int getNumNodesConsidered();
bestPos = pos;
}
}
return new Tuple<>(best, bestPos);
}
/** /**
* Where does this path start * Returns the start position of this path. This is the first element in the
* {@link List} that is returned by {@link IPath#positions()}.
*
* @return The start position of this path
*/ */
default BetterBlockPos getSrc() { default BetterBlockPos getSrc() {
return positions().get(0); return positions().get(0);
} }
/** /**
* Where does this path end * Returns the end position of this path. This is the last element in the
* {@link List} that is returned by {@link IPath#positions()}.
*
* @return The end position of this path.
*/ */
default BetterBlockPos getDest() { default BetterBlockPos getDest() {
List<BetterBlockPos> pos = positions(); List<BetterBlockPos> pos = positions();
return pos.get(pos.size() - 1); return pos.get(pos.size() - 1);
} }
/**
* Returns the estimated number of ticks to complete the path from the given node index.
*
* @param pathPosition The index of the node we're calculating from
* @return The estimated number of ticks remaining frm the given position
*/
default double ticksRemainingFrom(int pathPosition) { default double ticksRemainingFrom(int pathPosition) {
double sum = 0; double sum = 0;
//this is fast because we aren't requesting recalculation, it's just cached //this is fast because we aren't requesting recalculation, it's just cached
for (int i = pathPosition; i < movements().size(); i++) { for (int i = pathPosition; i < movements().size(); i++) {
sum += movements().get(i).getCost(null); sum += movements().get(i).getCost();
} }
return sum; return sum;
} }
int getNumNodesConsidered(); /**
* Cuts off this path at the loaded chunk border, and returns the resulting path. Default
* implementation just returns this path, without the intended functionality.
*
* @return The result of this cut-off operation
*/
default IPath cutoffAtLoadedChunks() { default IPath cutoffAtLoadedChunks() {
for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i);
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
logDebug("Cutting off path at edge of loaded chunks");
logDebug("Length decreased by " + (positions().size() - i - 1));
return new CutoffPath(this, i);
}
}
logDebug("Path ends within loaded chunks");
return this; return this;
} }
/**
* Cuts off this path using the min length and cutoff factor settings, and returns the resulting path.
* Default implementation just returns this path, without the intended functionality.
*
* @see Settings#pathCutoffMinimumLength
* @see Settings#pathCutoffFactor
*
* @return The result of this cut-off operation
*/
default IPath staticCutoff(Goal destination) { default IPath staticCutoff(Goal destination) {
if (length() < Baritone.settings().pathCutoffMinimumLength.get()) { return this;
return this;
}
if (destination == null || destination.isInGoal(getDest())) {
return this;
}
double factor = Baritone.settings().pathCutoffFactor.get();
int newLength = (int) (length() * factor);
logDebug("Static cutoff " + length() + " to " + newLength);
return new CutoffPath(this, newLength);
} }
} }

View File

@ -15,10 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone.pathing.calc; package baritone.api.pathing.calc;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.pathing.path.IPath;
import java.util.Optional; import java.util.Optional;

View File

@ -0,0 +1,67 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.movement;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import java.util.List;
/**
* @author Brady
* @since 10/8/2018
*/
public interface IMovement {
double getCost();
MovementStatus update();
/**
* Resets the current state status to {@link MovementStatus#PREPPING}
*/
void reset();
/**
* Resets the cache for special break, place, and walk into blocks
*/
void resetBlockCache();
/**
* @return Whether or not it is safe to cancel the current movement state
*/
boolean safeToCancel();
double recalculateCost();
double calculateCostWithoutCaching();
boolean calculatedWhileLoaded();
BetterBlockPos getSrc();
BetterBlockPos getDest();
BlockPos getDirection();
List<BlockPos> toBreak();
List<BlockPos> toPlace();
List<BlockPos> toWalkInto();
}

View File

@ -0,0 +1,74 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.movement;
/**
* @author Brady
* @since 10/8/2018
*/
public enum MovementStatus {
/**
* We are preparing the movement to be executed. This is when any blocks obstructing the destination are broken.
*/
PREPPING(false),
/**
* We are waiting for the movement to begin, after {@link MovementStatus#PREPPING}.
*/
WAITING(false),
/**
* The movement is currently in progress, after {@link MovementStatus#WAITING}
*/
RUNNING(false),
/**
* The movement has been completed and we are at our destination
*/
SUCCESS(true),
/**
* There was a change in state between calculation and actual
* movement execution, and the movement has now become impossible.
*/
UNREACHABLE(true),
/**
* Unused
*/
FAILED(true),
/**
* "Unused"
*/
CANCELED(true);
/**
* Whether or not this status indicates a complete movement.
*/
private final boolean complete;
MovementStatus(boolean complete) {
this.complete = complete;
}
public final boolean isComplete() {
return this.complete;
}
}

View File

@ -0,0 +1,29 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.path;
import baritone.api.pathing.calc.IPath;
/**
* @author Brady
* @since 10/8/2018
*/
public interface IPathExecutor {
IPath getPath();
}

View File

@ -15,9 +15,8 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone.utils.pathing; package baritone.api.utils;
import baritone.pathing.calc.AbstractNodeCostSearch;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.MathHelper;
@ -54,11 +53,30 @@ public final class BetterBlockPos extends BlockPos {
@Override @Override
public int hashCode() { public int hashCode() {
return (int) AbstractNodeCostSearch.posHash(x, y, z); return (int) longHash(x, y, z);
} }
public static long longHash(BetterBlockPos pos) { public static long longHash(BetterBlockPos pos) {
return AbstractNodeCostSearch.posHash(pos.x, pos.y, pos.z); return longHash(pos.x, pos.y, pos.z);
}
public static long longHash(int x, int y, int z) {
/*
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
*
* 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
*/
long hash = 3241;
hash = 3457689L * hash + x;
hash = 8734625L * hash + y;
hash = 2873465L * hash + z;
return hash;
} }
@Override @Override

View File

@ -40,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture; import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/** /**

View File

@ -22,13 +22,13 @@ import baritone.api.behavior.IMineBehavior;
import baritone.api.event.events.PathEvent; import baritone.api.event.events.PathEvent;
import baritone.api.event.events.TickEvent; import baritone.api.event.events.TickEvent;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.cache.CachedChunk; import baritone.cache.CachedChunk;
import baritone.cache.ChunkPacker; import baritone.cache.ChunkPacker;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.cache.WorldScanner; import baritone.cache.WorldScanner;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.block.Block; import net.minecraft.block.Block;

View File

@ -25,18 +25,19 @@ import baritone.api.event.events.RenderEvent;
import baritone.api.event.events.TickEvent; import baritone.api.event.events.TickEvent;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ; import baritone.api.pathing.goals.GoalXZ;
import baritone.pathing.calc.CutoffPath;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.pathing.calc.AStarPathFinder; import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.calc.IPathFinder; import baritone.api.pathing.calc.IPathFinder;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.IPath;
import baritone.pathing.path.PathExecutor; import baritone.pathing.path.PathExecutor;
import baritone.utils.BlockBreakHelper; import baritone.utils.BlockBreakHelper;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.PathRenderer; import baritone.utils.PathRenderer;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk; import net.minecraft.world.chunk.EmptyChunk;
@ -190,19 +191,19 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return goal; return goal;
} }
@Override
public PathExecutor getCurrent() { public PathExecutor getCurrent() {
return current; return current;
} }
@Override
public PathExecutor getNext() { public PathExecutor getNext() {
return next; return next;
} }
// TODO: Expose this method in the API? @Override
// In order to do so, we'd need to move over IPath which has a whole lot of references to other public Optional<IPathFinder> getPathFinder() {
// things that may not need to be exposed necessarily, so we'll need to figure that out. return Optional.ofNullable(AbstractNodeCostSearch.currentlyRunning());
public Optional<IPath> getPath() {
return Optional.ofNullable(current).map(PathExecutor::getPath);
} }
@Override @Override
@ -283,9 +284,30 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Optional<IPath> path = findPath(start, previous); Optional<IPath> path = findPath(start, previous);
if (Baritone.settings().cutoffAtLoadBoundary.get()) { if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(IPath::cutoffAtLoadedChunks); path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks();
if (result instanceof CutoffPath) {
logDebug("Cutting off path at edge of loaded chunks");
logDebug("Length decreased by " + (p.length() - result.length()));
} else {
logDebug("Path ends within loaded chunks");
}
return result;
});
} }
Optional<PathExecutor> executor = path.map(p -> p.staticCutoff(goal)).map(PathExecutor::new);
Optional<PathExecutor> executor = path.map(p -> {
IPath result = p.staticCutoff(goal);
if (result instanceof CutoffPath) {
logDebug("Static cutoff " + p.length() + " to " + result.length());
}
return result;
}).map(PathExecutor::new);
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
if (current == null) { if (current == null) {
if (executor.isPresent()) { if (executor.isPresent()) {

View File

@ -20,10 +20,11 @@ package baritone.pathing.calc;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
import baritone.pathing.path.IPath;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
@ -47,7 +48,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
@Override @Override
protected Optional<IPath> calculate0(long timeout) { protected Optional<IPath> calculate0(long timeout) {
startNode = getNodeAtPosition(startX, startY, startZ, posHash(startX, startY, startZ)); startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
startNode.cost = 0; startNode.cost = 0;
startNode.combinedCost = startNode.estimatedCostToGoal; startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet(); BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
@ -122,7 +123,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
if (actionCost <= 0) { if (actionCost <= 0) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
} }
long hashCode = posHash(res.x, res.y, res.z); long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (favoring && favored.contains(hashCode)) { if (favoring && favored.contains(hashCode)) {
// see issue #18 // see issue #18
actionCost *= favorCoeff; actionCost *= favorCoeff;

View File

@ -18,8 +18,9 @@
package baritone.pathing.calc; package baritone.pathing.calc;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.calc.IPathFinder;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.pathing.path.IPath; import baritone.api.pathing.calc.IPath;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Optional; import java.util.Optional;
@ -88,7 +89,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
this.cancelRequested = false; this.cancelRequested = false;
try { try {
Optional<IPath> path = calculate0(timeout); Optional<IPath> path = calculate0(timeout);
path.ifPresent(IPath::postprocess); path.ifPresent(IPath::postProcess);
isFinished = true; isFinished = true;
return path; return path;
} finally { } finally {
@ -140,25 +141,6 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
return node; return node;
} }
public static long posHash(int x, int y, int z) {
/*
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
*
* 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
*/
long hash = 3241;
hash = 3457689L * hash + x;
hash = 8734625L * hash + y;
hash = 2873465L * hash + z;
return hash;
}
public static void forceCancel() { public static void forceCancel() {
currentlyRunning = null; currentlyRunning = null;
} }
@ -225,4 +207,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() { public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() {
return Optional.ofNullable(currentlyRunning); return Optional.ofNullable(currentlyRunning);
} }
public static AbstractNodeCostSearch currentlyRunning() {
return currentlyRunning;
}
} }

View File

@ -15,11 +15,12 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone.pathing.path; package baritone.pathing.calc;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.pathing.movement.Movement; import baritone.api.pathing.movement.IMovement;
import baritone.utils.pathing.BetterBlockPos; import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -28,13 +29,13 @@ public class CutoffPath implements IPath {
private final List<BetterBlockPos> path; private final List<BetterBlockPos> path;
private final List<Movement> movements; private final List<IMovement> movements;
private final int numNodes; private final int numNodes;
private final Goal goal; private final Goal goal;
public CutoffPath(IPath prev, int lastPositionToInclude) { CutoffPath(IPath prev, int lastPositionToInclude) {
path = prev.positions().subList(0, lastPositionToInclude + 1); path = prev.positions().subList(0, lastPositionToInclude + 1);
movements = prev.movements().subList(0, lastPositionToInclude + 1); movements = prev.movements().subList(0, lastPositionToInclude + 1);
numNodes = prev.getNumNodesConsidered(); numNodes = prev.getNumNodesConsidered();
@ -47,7 +48,7 @@ public class CutoffPath implements IPath {
} }
@Override @Override
public List<Movement> movements() { public List<IMovement> movements() {
return Collections.unmodifiableList(movements); return Collections.unmodifiableList(movements);
} }

View File

@ -17,12 +17,16 @@
package baritone.pathing.calc; package baritone.pathing.calc;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
import baritone.pathing.path.IPath; import net.minecraft.client.Minecraft;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
@ -149,7 +153,7 @@ class Path implements IPath {
} }
@Override @Override
public void postprocess() { public void postProcess() {
if (verified) { if (verified) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -161,7 +165,7 @@ class Path implements IPath {
} }
@Override @Override
public List<Movement> movements() { public List<IMovement> movements() {
if (!verified) { if (!verified) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@ -187,4 +191,28 @@ class Path implements IPath {
public BetterBlockPos getDest() { public BetterBlockPos getDest() {
return end; return end;
} }
@Override
public IPath cutoffAtLoadedChunks() {
for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i);
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
return new CutoffPath(this, i);
}
}
return this;
}
@Override
public IPath staticCutoff(Goal destination) {
if (length() < BaritoneAPI.getSettings().pathCutoffMinimumLength.get()) {
return this;
}
if (destination == null || destination.isInGoal(getDest())) {
return this;
}
double factor = BaritoneAPI.getSettings().pathCutoffFactor.get();
int newLength = (int) (length() * factor);
return new CutoffPath(this, newLength);
}
} }

View File

@ -19,6 +19,7 @@ package baritone.pathing.calc;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.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.
@ -85,7 +86,7 @@ public final class PathNode {
*/ */
@Override @Override
public int hashCode() { public int hashCode() {
return (int) AbstractNodeCostSearch.posHash(x, y, z); return (int) BetterBlockPos.longHash(x, y, z);
} }
@Override @Override

View File

@ -18,12 +18,13 @@
package baritone.pathing.movement; package baritone.pathing.movement;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.behavior.LookBehavior; import baritone.behavior.LookBehavior;
import baritone.behavior.LookBehaviorUtils; import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.*; import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockLiquid; import net.minecraft.block.BlockLiquid;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@ -36,7 +37,7 @@ import java.util.Optional;
import static baritone.utils.InputOverrideHandler.Input; import static baritone.utils.InputOverrideHandler.Input;
public abstract class Movement implements Helper, MovementHelper { public abstract class Movement implements IMovement, Helper, MovementHelper {
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST}; protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
@ -77,24 +78,27 @@ public abstract class Movement implements Helper, MovementHelper {
this(src, dest, toBreak, null); this(src, dest, toBreak, null);
} }
public double getCost(CalculationContext context) { @Override
public double getCost() {
if (cost == null) { if (cost == null) {
cost = calculateCost(context != null ? context : new CalculationContext()); cost = calculateCost(new CalculationContext());
} }
return cost; return cost;
} }
protected abstract double calculateCost(CalculationContext context); protected abstract double calculateCost(CalculationContext context);
@Override
public double recalculateCost() { public double recalculateCost() {
cost = null; cost = null;
return getCost(null); return getCost();
} }
protected void override(double cost) { protected void override(double cost) {
this.cost = cost; this.cost = cost;
} }
@Override
public double calculateCostWithoutCaching() { public double calculateCostWithoutCaching() {
return calculateCost(new CalculationContext()); return calculateCost(new CalculationContext());
} }
@ -105,6 +109,7 @@ public abstract class Movement implements Helper, MovementHelper {
* *
* @return Status * @return Status
*/ */
@Override
public MovementStatus update() { public MovementStatus update() {
player().capabilities.allowFlying = false; player().capabilities.allowFlying = false;
MovementState latestState = updateState(currentState); MovementState latestState = updateState(currentState);
@ -147,7 +152,8 @@ public abstract class Movement implements Helper, MovementHelper {
currentState = latestState; currentState = latestState;
if (isFinished()) { // If the current status indicates a completed movement
if (currentState.getStatus().isComplete()) {
onFinish(latestState); onFinish(latestState);
} }
@ -187,6 +193,7 @@ public abstract class Movement implements Helper, MovementHelper {
return true; return true;
} }
@Override
public boolean safeToCancel() { public boolean safeToCancel() {
return safeToCancel(currentState); return safeToCancel(currentState);
} }
@ -195,16 +202,12 @@ public abstract class Movement implements Helper, MovementHelper {
return true; return true;
} }
public boolean isFinished() { @Override
return (currentState.getStatus() != MovementStatus.RUNNING
&& currentState.getStatus() != MovementStatus.PREPPING
&& currentState.getStatus() != MovementStatus.WAITING);
}
public BetterBlockPos getSrc() { public BetterBlockPos getSrc() {
return src; return src;
} }
@Override
public BetterBlockPos getDest() { public BetterBlockPos getDest() {
return dest; return dest;
} }
@ -223,6 +226,7 @@ public abstract class Movement implements Helper, MovementHelper {
currentState.setStatus(MovementStatus.CANCELED); currentState.setStatus(MovementStatus.CANCELED);
} }
@Override
public void reset() { public void reset() {
currentState = new MovementState().setStatus(MovementStatus.PREPPING); currentState = new MovementState().setStatus(MovementStatus.PREPPING);
} }
@ -247,6 +251,7 @@ public abstract class Movement implements Helper, MovementHelper {
return state; return state;
} }
@Override
public BlockPos getDirection() { public BlockPos getDirection() {
return getDest().subtract(getSrc()); return getDest().subtract(getSrc());
} }
@ -255,10 +260,19 @@ public abstract class Movement implements Helper, MovementHelper {
calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk); calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk);
} }
@Override
public boolean calculatedWhileLoaded() { public boolean calculatedWhileLoaded() {
return calculatedWhileLoaded; return calculatedWhileLoaded;
} }
@Override
public void resetBlockCache() {
toBreakCached = null;
toPlaceCached = null;
toWalkIntoCached = null;
}
@Override
public List<BlockPos> toBreak() { public List<BlockPos> toBreak() {
if (toBreakCached != null) { if (toBreakCached != null) {
return toBreakCached; return toBreakCached;
@ -273,6 +287,7 @@ public abstract class Movement implements Helper, MovementHelper {
return result; return result;
} }
@Override
public List<BlockPos> toPlace() { public List<BlockPos> toPlace() {
if (toPlaceCached != null) { if (toPlaceCached != null) {
return toPlaceCached; return toPlaceCached;
@ -285,6 +300,7 @@ public abstract class Movement implements Helper, MovementHelper {
return result; return result;
} }
@Override
public List<BlockPos> toWalkInto() { // overridden by movementdiagonal public List<BlockPos> toWalkInto() { // overridden by movementdiagonal
if (toWalkIntoCached == null) { if (toWalkIntoCached == null) {
toWalkIntoCached = new ArrayList<>(); toWalkIntoCached = new ArrayList<>();

View File

@ -19,11 +19,11 @@ package baritone.pathing.movement;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils; import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementTarget; import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.*; import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.properties.PropertyBool; import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;

View File

@ -17,6 +17,7 @@
package baritone.pathing.movement; package baritone.pathing.movement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.utils.InputOverrideHandler.Input; import baritone.utils.InputOverrideHandler.Input;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@ -72,10 +73,6 @@ public class MovementState {
return this.inputState; return this.inputState;
} }
public enum MovementStatus {
PREPPING, WAITING, RUNNING, SUCCESS, UNREACHABLE, FAILED, CANCELED
}
public static class MovementTarget { public static class MovementTarget {
/** /**

View File

@ -17,8 +17,8 @@
package baritone.pathing.movement; package baritone.pathing.movement;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.movements.*; import baritone.pathing.movement.movements.*;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;

View File

@ -18,16 +18,16 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.behavior.LookBehaviorUtils; import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockFalling; import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;

View File

@ -18,14 +18,14 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling; import net.minecraft.block.BlockFalling;

View File

@ -17,13 +17,14 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.BetterBlockPos;
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.init.Blocks; import net.minecraft.init.Blocks;
@ -140,12 +141,12 @@ public class MovementDiagonal extends Movement {
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
return state; return state;
} }
if (playerFeet().equals(dest)) { if (playerFeet().equals(dest)) {
state.setStatus(MovementState.MovementStatus.SUCCESS); state.setStatus(MovementStatus.SUCCESS);
return state; return state;
} }
if (!BlockStateInterface.isLiquid(playerFeet())) { if (!BlockStateInterface.isLiquid(playerFeet())) {

View File

@ -17,12 +17,13 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.BetterBlockPos;
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.init.Blocks; import net.minecraft.init.Blocks;
@ -64,12 +65,12 @@ public class MovementDownward extends Movement {
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
return state; return state;
} }
if (playerFeet().equals(dest)) { if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
double diffX = player().posX - (dest.getX() + 0.5); double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5); double diffZ = player().posZ - (dest.getZ() + 0.5);

View File

@ -18,18 +18,18 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.pathing.movement.MovementState.MovementTarget; import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.RayTraceUtils; import baritone.utils.RayTraceUtils;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Items; import net.minecraft.init.Items;

View File

@ -18,6 +18,8 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils; import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
@ -25,7 +27,6 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.utils.*; import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
@ -168,13 +169,13 @@ public class MovementParkour extends Movement {
// once this movement is instantiated, the state is default to PREPPING // once this movement is instantiated, the state is default to PREPPING
// but once it's ticked for the first time it changes to RUNNING // but once it's ticked for the first time it changes to RUNNING
// since we don't really know anything about momentum, it suffices to say Parkour can only be canceled on the 0th tick // since we don't really know anything about momentum, it suffices to say Parkour can only be canceled on the 0th tick
return state.getStatus() != MovementState.MovementStatus.RUNNING; return state.getStatus() != MovementStatus.RUNNING;
} }
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
return state; return state;
} }
if (dist >= 4) { if (dist >= 4) {
@ -186,10 +187,10 @@ public class MovementParkour extends Movement {
if (d == Blocks.VINE || d == Blocks.LADDER) { if (d == Blocks.VINE || d == Blocks.LADDER) {
// it physically hurt me to add support for parkour jumping onto a vine // it physically hurt me to add support for parkour jumping onto a vine
// but i did it anyway // but i did it anyway
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
if (player().posY - playerFeet().getY() < 0.094) { // lilypads if (player().posY - playerFeet().getY() < 0.094) { // lilypads
state.setStatus(MovementState.MovementStatus.SUCCESS); state.setStatus(MovementStatus.SUCCESS);
} }
} else if (!playerFeet().equals(src)) { } else if (!playerFeet().equals(src)) {
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) { if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
@ -203,7 +204,7 @@ public class MovementParkour extends Movement {
} }
if (MovementHelper.canPlaceAgainst(against1)) { if (MovementHelper.canPlaceAgainst(against1)) {
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
return state.setStatus(MovementState.MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D; double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D; double faceY = (dest.getY() + against1.getY()) * 0.5D;

View File

@ -17,6 +17,8 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
@ -25,7 +27,6 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -148,7 +149,7 @@ public class MovementPillar extends Movement {
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
return state; return state;
} }
@ -161,7 +162,7 @@ public class MovementPillar extends Movement {
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true); state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
} }
if (playerFeet().equals(dest)) { if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
return state; return state;
} }
@ -178,11 +179,11 @@ public class MovementPillar extends Movement {
BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite()); BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
if (against == null) { if (against == null) {
logDebug("Unable to climb vines"); logDebug("Unable to climb vines");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) { if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
if (MovementHelper.isBottomSlab(src.down())) { if (MovementHelper.isBottomSlab(src.down())) {
state.setInput(InputOverrideHandler.Input.JUMP, true); state.setInput(InputOverrideHandler.Input.JUMP, true);
@ -198,7 +199,7 @@ public class MovementPillar extends Movement {
} else { } else {
// Get ready to place a throwaway block // Get ready to place a throwaway block
if (!MovementHelper.throwaway(true)) { if (!MovementHelper.throwaway(true)) {
return state.setStatus(MovementState.MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
numTicks++; numTicks++;
@ -233,7 +234,7 @@ public class MovementPillar extends Movement {
// If we are at our goal and the block below us is placed // If we are at our goal and the block below us is placed
if (playerFeet().equals(dest) && blockIsThere) { if (playerFeet().equals(dest) && blockIsThere) {
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
return state; return state;

View File

@ -18,6 +18,8 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils; import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
@ -27,7 +29,6 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -144,13 +145,13 @@ public class MovementTraverse extends Movement {
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
// if the setting is enabled // if the setting is enabled
if (!Baritone.settings().walkWhileBreaking.get()) { if (!Baritone.settings().walkWhileBreaking.get()) {
return state; return state;
} }
// and if we're prepping (aka mining the block in front) // and if we're prepping (aka mining the block in front)
if (state.getStatus() != MovementState.MovementStatus.PREPPING) { if (state.getStatus() != MovementStatus.PREPPING) {
return state; return state;
} }
// and if it's fine to walk into the blocks in front // and if it's fine to walk into the blocks in front
@ -225,7 +226,7 @@ public class MovementTraverse extends Movement {
if (isTheBridgeBlockThere) { if (isTheBridgeBlockThere) {
if (playerFeet().equals(dest)) { if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) { if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true); state.setInput(InputOverrideHandler.Input.SPRINT, true);
@ -248,7 +249,7 @@ public class MovementTraverse extends Movement {
if (MovementHelper.canPlaceAgainst(against1)) { if (MovementHelper.canPlaceAgainst(against1)) {
if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble"); logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
if (!Baritone.settings().assumeSafeWalk.get()) { if (!Baritone.settings().assumeSafeWalk.get()) {
state.setInput(InputOverrideHandler.Input.SNEAK, true); state.setInput(InputOverrideHandler.Input.SNEAK, true);
@ -287,7 +288,7 @@ public class MovementTraverse extends Movement {
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI); // Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble"); logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D; double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D; double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D;
@ -324,7 +325,7 @@ public class MovementTraverse extends Movement {
// if we're in the process of breaking blocks before walking forwards // if we're in the process of breaking blocks before walking forwards
// or if this isn't a sneak place (the block is already there) // or if this isn't a sneak place (the block is already there)
// then it's safe to cancel this // then it's safe to cancel this
return state.getStatus() != MovementState.MovementStatus.RUNNING || MovementHelper.canWalkOn(dest.down()); return state.getStatus() != MovementStatus.RUNNING || MovementHelper.canWalkOn(dest.down());
} }
@Override @Override

View File

@ -20,21 +20,23 @@ package baritone.pathing.path;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.event.events.TickEvent; import baritone.api.event.events.TickEvent;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.path.IPathExecutor;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.movements.*; import baritone.pathing.movement.movements.*;
import baritone.utils.*; import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.*; import java.util.*;
import static baritone.pathing.movement.MovementState.MovementStatus.*; import static baritone.api.pathing.movement.MovementStatus.*;
/** /**
* Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching * Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching
@ -42,7 +44,7 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*;
* *
* @author leijurv * @author leijurv
*/ */
public class PathExecutor implements Helper { public class PathExecutor implements IPathExecutor, Helper {
private static final double MAX_MAX_DIST_FROM_PATH = 3; private static final double MAX_MAX_DIST_FROM_PATH = 3;
private static final double MAX_DIST_FROM_PATH = 2; private static final double MAX_DIST_FROM_PATH = 2;
@ -128,7 +130,7 @@ public class PathExecutor implements Helper {
} }
} }
} }
Tuple<Double, BlockPos> status = path.closestPathPos(); Tuple<Double, BlockPos> status = closestPathPos(path);
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) { if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
ticksAway++; ticksAway++;
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH); System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH);
@ -182,13 +184,11 @@ public class PathExecutor implements Helper {
if (i < 0 || i >= path.movements().size()) { if (i < 0 || i >= path.movements().size()) {
continue; continue;
} }
Movement m = path.movements().get(i); IMovement m = path.movements().get(i);
HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak()); HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak());
HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace()); HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace());
HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto()); HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto());
m.toBreakCached = null; m.resetBlockCache();
m.toPlaceCached = null;
m.toWalkIntoCached = null;
if (!prevBreak.equals(new HashSet<>(m.toBreak()))) { if (!prevBreak.equals(new HashSet<>(m.toBreak()))) {
recalcBP = true; recalcBP = true;
} }
@ -217,12 +217,12 @@ public class PathExecutor implements Helper {
if (end - start > 0) { if (end - start > 0) {
System.out.println("Recalculating break and place took " + (end - start) + "ms"); System.out.println("Recalculating break and place took " + (end - start) + "ms");
}*/ }*/
Movement movement = path.movements().get(pathPosition); IMovement movement = path.movements().get(pathPosition);
boolean canCancel = movement.safeToCancel(); boolean canCancel = movement.safeToCancel();
if (costEstimateIndex == null || costEstimateIndex != pathPosition) { if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
costEstimateIndex = pathPosition; costEstimateIndex = pathPosition;
// do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now // do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now
currentMovementOriginalCostEstimate = movement.getCost(null); currentMovementOriginalCostEstimate = movement.getCost();
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) { for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF && canCancel) { if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF && canCancel) {
logDebug("Something has changed in the world and a future movement has become impossible. Cancelling."); logDebug("Something has changed in the world and a future movement has become impossible. Cancelling.");
@ -246,7 +246,7 @@ public class PathExecutor implements Helper {
logDebug("Pausing since current best path is a backtrack"); logDebug("Pausing since current best path is a backtrack");
return true; return true;
} }
MovementState.MovementStatus movementStatus = movement.update(); MovementStatus movementStatus = movement.update();
if (movementStatus == UNREACHABLE || movementStatus == FAILED) { if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
logDebug("Movement returns status " + movementStatus); logDebug("Movement returns status " + movementStatus);
cancel(); cancel();
@ -274,6 +274,19 @@ public class PathExecutor implements Helper {
return false; // movement is in progress return false; // movement is in progress
} }
private Tuple<Double, BlockPos> closestPathPos(IPath path) {
double best = -1;
BlockPos bestPos = null;
for (BlockPos pos : path.positions()) {
double dist = Utils.playerDistanceToCenter(pos);
if (dist < best || best == -1) {
best = dist;
bestPos = pos;
}
}
return new Tuple<>(best, bestPos);
}
private boolean shouldPause() { private boolean shouldPause() {
Optional<AbstractNodeCostSearch> current = AbstractNodeCostSearch.getCurrentlyRunning(); Optional<AbstractNodeCostSearch> current = AbstractNodeCostSearch.getCurrentlyRunning();
if (!current.isPresent()) { if (!current.isPresent()) {
@ -346,7 +359,7 @@ public class PathExecutor implements Helper {
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT,false); Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT,false);
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it // however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
Movement current = path.movements().get(pathPosition); IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend && pathPosition < path.length() - 2) { if (current instanceof MovementDescend && pathPosition < path.length() - 2) {
// (dest - src) + dest is offset 1 more in the same direction // (dest - src) + dest is offset 1 more in the same direction
@ -361,7 +374,7 @@ public class PathExecutor implements Helper {
} }
} }
Movement next = path.movements().get(pathPosition + 1); IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) { if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction // a descend then an ascend in the same direction
if (!player().isSprinting()) { if (!player().isSprinting()) {
@ -385,7 +398,7 @@ public class PathExecutor implements Helper {
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection())); //logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
} }
if (current instanceof MovementAscend && pathPosition != 0) { if (current instanceof MovementAscend && pathPosition != 0) {
Movement prev = path.movements().get(pathPosition - 1); IMovement prev = path.movements().get(pathPosition - 1);
if (prev instanceof MovementDescend && prev.getDirection().up().equals(current.getDirection().down())) { if (prev instanceof MovementDescend && prev.getDirection().up().equals(current.getDirection().down())) {
BlockPos center = current.getSrc().up(); BlockPos center = current.getSrc().up();
if (player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand if (player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand
@ -400,7 +413,7 @@ public class PathExecutor implements Helper {
player().setSprinting(false); player().setSprinting(false);
} }
private static boolean canSprintInto(Movement current, Movement next) { private static boolean canSprintInto(IMovement current, IMovement next) {
if (next instanceof MovementDescend) { if (next instanceof MovementDescend) {
if (next.getDirection().equals(current.getDirection())) { if (next.getDirection().equals(current.getDirection())) {
return true; return true;
@ -438,6 +451,7 @@ public class PathExecutor implements Helper {
return pathPosition; return pathPosition;
} }
@Override
public IPath getPath() { public IPath getPath() {
return path; return path;
} }

View File

@ -32,7 +32,6 @@ import baritone.cache.ChunkPacker;
import baritone.cache.Waypoint; import baritone.cache.Waypoint;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement; import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
@ -470,10 +469,10 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
while (moves.contains(null)) { while (moves.contains(null)) {
moves.remove(null); moves.remove(null);
} }
moves.sort(Comparator.comparingDouble(movement -> movement.getCost(new CalculationContext()))); moves.sort(Comparator.comparingDouble(Movement::getCost));
for (Movement move : moves) { for (Movement move : moves) {
String[] parts = move.getClass().toString().split("\\."); String[] parts = move.getClass().toString().split("\\.");
double cost = move.getCost(new CalculationContext()); double cost = move.getCost();
String strCost = cost + ""; String strCost = cost + "";
if (cost >= ActionCosts.COST_INF) { if (cost >= ActionCosts.COST_INF) {
strCost = "IMPOSSIBLE"; strCost = "IMPOSSIBLE";

View File

@ -18,8 +18,8 @@
package baritone.utils; package baritone.utils;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockSlab; import net.minecraft.block.BlockSlab;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;

View File

@ -23,12 +23,12 @@ import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalComposite; import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks; import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.pathing.goals.GoalXZ; import baritone.api.pathing.goals.GoalXZ;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.behavior.PathingBehavior; import baritone.behavior.PathingBehavior;
import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.path.IPath;
import baritone.pathing.path.PathExecutor; import baritone.pathing.path.PathExecutor;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.state.IBlockState; 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;

View File

@ -17,6 +17,7 @@
package baritone.utils.pathing; package baritone.utils.pathing;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import org.junit.Test; import org.junit.Test;