huge number of fixes

This commit is contained in:
Leijurv 2019-01-29 15:22:48 -08:00
parent 8f2b23f8f9
commit 9faa0ddc62
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
9 changed files with 72 additions and 68 deletions

View File

@ -37,7 +37,13 @@ public interface IPathingBehavior extends IBehavior {
* *
* @return The estimated remaining ticks in the current segment. * @return The estimated remaining ticks in the current segment.
*/ */
Optional<Double> ticksRemainingInSegment(); default Optional<Double> ticksRemainingInSegment() {
IPathExecutor current = getCurrent();
if (current == null) {
return Optional.empty();
}
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
}
/** /**
* @return The current pathing goal * @return The current pathing goal
@ -47,7 +53,9 @@ public interface IPathingBehavior extends IBehavior {
/** /**
* @return Whether or not a path is currently being executed. * @return Whether or not a path is currently being executed.
*/ */
boolean isPathing(); default boolean isPathing() {
return getCurrent() != null;
}
/** /**
* Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path. * Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path.

View File

@ -26,4 +26,6 @@ import baritone.api.pathing.calc.IPath;
public interface IPathExecutor { public interface IPathExecutor {
IPath getPath(); IPath getPath();
int getPosition();
} }

View File

@ -30,7 +30,6 @@ import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.CutoffPath;
import baritone.pathing.path.PathExecutor; import baritone.pathing.path.PathExecutor;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.PathRenderer; import baritone.utils.PathRenderer;
@ -125,7 +124,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
next = null; next = null;
return; return;
} }
if (next != null && !next.getPath().positions().contains(ctx.playerFeet())) { if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(pathStart())) { // can contain either one
// if the current path failed, we may not actually be on the next one, so make sure // if the current path failed, we may not actually be on the next one, so make sure
logDebug("Discarding next path as it does not contain current position"); logDebug("Discarding next path as it does not contain current position");
// for example if we had a nicely planned ahead path that starts where current ends // for example if we had a nicely planned ahead path that starts where current ends
@ -141,16 +140,27 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT); queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
current = next; current = next;
next = null; next = null;
current.onTick(); current.onTick(); // don't waste a tick doing nothing, get started right away
return; return;
} }
// at this point, current just ended, but we aren't in the goal and have no plan for the future // at this point, current just ended, but we aren't in the goal and have no plan for the future
synchronized (pathCalcLock) { synchronized (pathCalcLock) {
if (inProgress != null) { if (inProgress != null) {
// we are calculating
// are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing
if (calcFrom.equals(ctx.playerFeet()) || calcFrom.equals(pathStart())) {
// cool and good
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING); queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
// if we aren't calculating right now
return; return;
} }
// oh noes
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
}
// we aren't calculating
queuePathEvent(PathEvent.CALC_STARTED); queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true); findPathInNewThread(pathStart(), true);
} }
@ -180,11 +190,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return; return;
} }
if (goal == null || goal.isInGoal(current.getPath().getDest())) { if (goal == null || goal.isInGoal(current.getPath().getDest())) {
// and this path dosen't get us all the way there // and this path doesn't get us all the way there
return; return;
} }
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 5 seconds or less left // and this path has 7.5 seconds or less left
logDebug("Path almost over. Planning ahead..."); logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false); findPathInNewThread(current.getPath().getDest(), false);
@ -210,14 +220,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} }
} }
@Override
public Optional<Double> ticksRemainingInSegment() {
if (current == null) {
return Optional.empty();
}
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
}
public void secretInternalSetGoal(Goal goal) { public void secretInternalSetGoal(Goal goal) {
this.goal = goal; this.goal = goal;
} }
@ -247,11 +249,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return Optional.ofNullable(inProgress); return Optional.ofNullable(inProgress);
} }
@Override
public boolean isPathing() {
return this.current != null;
}
public boolean isSafeToCancel() { public boolean isSafeToCancel() {
return current == null || safeToCancel; return current == null || safeToCancel;
} }
@ -274,7 +271,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (doIt) { if (doIt) {
secretInternalSegmentCancel(); secretInternalSegmentCancel();
} }
baritone.getPathingControlManager().cancelEverything(); baritone.getPathingControlManager().cancelEverything(); // regardless of if we can stop the current segment, we can still stop the processes
return doIt; return doIt;
} }
@ -310,8 +307,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public void forceCancel() { // NOT exposed on public api public void forceCancel() { // NOT exposed on public api
cancelEverything(); cancelEverything();
secretInternalSegmentCancel(); secretInternalSegmentCancel();
synchronized (pathCalcLock) {
inProgress = null; inProgress = null;
} }
}
/** /**
* Start calculating a path if we aren't already * Start calculating a path if we aren't already
@ -433,33 +432,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} }
PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout); PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout);
Optional<IPath> path = calcResult.getPath();
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks(context.bsi);
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 -> {
IPath result = p.staticCutoff(goal);
if (result instanceof CutoffPath) {
logDebug("Static cutoff " + p.length() + " to " + result.length());
}
return result;
}).map(p -> new PathExecutor(this, p));
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p));
if (current == null) { if (current == null) {
if (executor.isPresent()) { if (executor.isPresent()) {
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING); queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);

View File

@ -92,13 +92,25 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
cancelRequested = false; cancelRequested = false;
try { try {
IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null); IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null);
isFinished = true;
if (cancelRequested) { if (cancelRequested) {
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path); return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION);
} }
if (path == null) { if (path == null) {
return new PathCalculationResult(PathCalculationResult.Type.FAILURE); return new PathCalculationResult(PathCalculationResult.Type.FAILURE);
} }
int previousLength = path.length();
path = path.cutoffAtLoadedChunks(context.bsi);
if (path.length() < previousLength) {
Helper.HELPER.logDebug("Cutting off path at edge of loaded chunks");
Helper.HELPER.logDebug("Length decreased by " + (previousLength - path.length()));
} else {
Helper.HELPER.logDebug("Path ends within loaded chunks");
}
previousLength = path.length();
path = path.staticCutoff(goal);
if (path.length() < previousLength) {
Helper.HELPER.logDebug("Static cutoff " + previousLength + " to " + path.length());
}
if (goal.isInGoal(path.getDest())) { if (goal.isInGoal(path.getDest())) {
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path); return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path);
} else { } else {
@ -163,7 +175,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
} }
@Override @Override
public Optional<IPath> bestPathSoFar() { public Optional<IPath> bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder
if (startNode == null || bestSoFar == null) { if (startNode == null || bestSoFar == null) {
return Optional.empty(); return Optional.empty();
} }
@ -189,4 +201,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public final Goal getGoal() { public final Goal getGoal() {
return goal; return goal;
} }
public BetterBlockPos getStart() {
return new BetterBlockPos(startX, startY, startZ);
}
} }

View File

@ -137,7 +137,7 @@ public class MovementDescend extends Movement {
IBlockState ontoBlock = context.get(destX, newY, destZ); IBlockState ontoBlock = context.get(destX, newY, destZ);
int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar;
if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { if ((ontoBlock.getBlock() == Blocks.WATER || ontoBlock.getBlock() == Blocks.FLOWING_WATER) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) {
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad // lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works) // however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
if (context.assumeWalkOnWater) { if (context.assumeWalkOnWater) {
@ -157,9 +157,6 @@ public class MovementDescend extends Movement {
res.cost = tentativeCost;// TODO incorporate water swim up cost? res.cost = tentativeCost;// TODO incorporate water swim up cost?
return false; return false;
} }
if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) {
return false;
}
if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) { if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) {
// if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know // if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know
// this effectively "resets" our falling speed // this effectively "resets" our falling speed

View File

@ -81,7 +81,8 @@ public class MovementFall extends Movement {
Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)); Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest));
Rotation targetRotation = null; Rotation targetRotation = null;
Block destBlock = ctx.world().getBlockState(dest).getBlock(); Block destBlock = ctx.world().getBlockState(dest).getBlock();
if (destBlock != Blocks.WATER && destBlock != Blocks.FLOWING_WATER && willPlaceBucket() && !playerFeet.equals(dest)) { boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER;
if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) {
if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) { if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) {
return state.setStatus(MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
@ -102,8 +103,8 @@ public class MovementFall extends Movement {
} else { } else {
state.setTarget(new MovementTarget(toDest, false)); state.setTarget(new MovementTarget(toDest, false));
} }
if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || destBlock == Blocks.WATER)) { // 0.094 because lilypads if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || isWater)) { // 0.094 because lilypads
if (destBlock == Blocks.WATER) { // only match water, not flowing water (which we cannot pick up with a bucket) if (isWater) { // only match water, not flowing water (which we cannot pick up with a bucket)
if (InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) { if (InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
ctx.player().inventory.currentItem = ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY); ctx.player().inventory.currentItem = ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
if (ctx.player().motionY >= 0) { if (ctx.player().motionY >= 0) {

View File

@ -461,6 +461,7 @@ public class PathExecutor implements IPathExecutor, Helper {
failed = true; failed = true;
} }
@Override
public int getPosition() { public int getPosition() {
return pathPosition; return pathPosition;
} }

View File

@ -94,14 +94,14 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
if (Baritone.settings().legitMine.get()) { if (Baritone.settings().legitMine.get()) {
addNearby(); addNearby();
} }
Goal goal = updateGoal(); PathingCommand command = updateGoal();
if (goal == null) { if (command == null) {
// none in range // none in range
// maybe say something in chat? (ahem impact) // maybe say something in chat? (ahem impact)
cancel(); cancel();
return null; return null;
} }
return new PathingCommand(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH); return command;
} }
@Override @Override
@ -114,17 +114,18 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return "Mine " + mining; return "Mine " + mining;
} }
private Goal updateGoal() { private PathingCommand updateGoal() {
boolean legit = Baritone.settings().legitMine.get();
List<BlockPos> locs = knownOreLocations; List<BlockPos> locs = knownOreLocations;
if (!locs.isEmpty()) { if (!locs.isEmpty()) {
List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT); List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT);
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final // can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new)); Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new));
knownOreLocations = locs2; knownOreLocations = locs2;
return goal; return new PathingCommand(goal, legit ? PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType.REVALIDATE_GOAL_AND_PATH);
} }
// we don't know any ore locations at the moment // we don't know any ore locations at the moment
if (!Baritone.settings().legitMine.get()) { if (!legit) {
return null; return null;
} }
// only in non-Xray mode (aka legit mode) do we do this // only in non-Xray mode (aka legit mode) do we do this
@ -149,7 +150,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
} }
}; };
} }
return branchPointRunaway; return new PathingCommand(branchPointRunaway, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
} }
private void rescan(List<BlockPos> already, CalculationContext context) { private void rescan(List<BlockPos> already, CalculationContext context) {

View File

@ -17,6 +17,7 @@
package baritone.utils.pathing; package baritone.utils.pathing;
import baritone.Baritone;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.pathing.calc.IPath; import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
@ -27,6 +28,9 @@ import net.minecraft.util.math.BlockPos;
public abstract class PathBase implements IPath { public abstract class PathBase implements IPath {
@Override @Override
public PathBase cutoffAtLoadedChunks(Object bsi0) { // <-- cursed cursed cursed public PathBase cutoffAtLoadedChunks(Object bsi0) { // <-- cursed cursed cursed
if (!Baritone.settings().cutoffAtLoadBoundary.get()) {
return this;
}
BlockStateInterface bsi = (BlockStateInterface) bsi0; BlockStateInterface bsi = (BlockStateInterface) bsi0;
for (int i = 0; i < positions().size(); i++) { for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i); BlockPos pos = positions().get(i);