Merge branch 'master' into bot-system
This commit is contained in:
@@ -7,11 +7,13 @@
|
|||||||
[](https://github.com/cabaletta/baritone/issues)
|
[](https://github.com/cabaletta/baritone/issues)
|
||||||
[](https://minecraft.gamepedia.com/1.12.2)
|
[](https://minecraft.gamepedia.com/1.12.2)
|
||||||
|
|
||||||
A Minecraft pathfinder bot. This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
A Minecraft pathfinder bot.
|
||||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
|
||||||
|
|
||||||
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
|
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
|
||||||
|
|
||||||
|
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
||||||
|
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||||
|
|
||||||
Here are some links to help to get started:
|
Here are some links to help to get started:
|
||||||
|
|
||||||
- [Features](FEATURES.md)
|
- [Features](FEATURES.md)
|
||||||
|
|||||||
@@ -411,7 +411,7 @@ public class Settings {
|
|||||||
* <p>
|
* <p>
|
||||||
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
|
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
|
||||||
*/
|
*/
|
||||||
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(false);
|
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
|
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
|
||||||
|
|||||||
@@ -52,7 +52,9 @@ public interface IPath {
|
|||||||
* 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 IPath postProcess() {
|
||||||
|
throw new UnsupportedOperationException();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Returns the number of positions in this path. Equivalent to {@code positions().size()}.
|
* Returns the number of positions in this path. Equivalent to {@code positions().size()}.
|
||||||
@@ -119,7 +121,7 @@ public interface IPath {
|
|||||||
* @return The result of this cut-off operation
|
* @return The result of this cut-off operation
|
||||||
*/
|
*/
|
||||||
default IPath cutoffAtLoadedChunks() {
|
default IPath cutoffAtLoadedChunks() {
|
||||||
return this;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -131,7 +133,7 @@ public interface IPath {
|
|||||||
* @see Settings#pathCutoffFactor
|
* @see Settings#pathCutoffFactor
|
||||||
*/
|
*/
|
||||||
default IPath staticCutoff(Goal destination) {
|
default IPath staticCutoff(Goal destination) {
|
||||||
return this;
|
throw new UnsupportedOperationException();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -18,6 +18,7 @@
|
|||||||
package baritone.api.pathing.calc;
|
package baritone.api.pathing.calc;
|
||||||
|
|
||||||
import baritone.api.pathing.goals.Goal;
|
import baritone.api.pathing.goals.Goal;
|
||||||
|
import baritone.api.utils.PathCalculationResult;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
|
|
||||||
@@ -35,7 +36,7 @@ public interface IPathFinder {
|
|||||||
*
|
*
|
||||||
* @return The final path
|
* @return The final path
|
||||||
*/
|
*/
|
||||||
Optional<IPath> calculate(long timeout);
|
PathCalculationResult calculate(long timeout);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ public enum PathingCommandType {
|
|||||||
/**
|
/**
|
||||||
* Set the goal and path.
|
* Set the goal and path.
|
||||||
* <p>
|
* <p>
|
||||||
* Revalidate the current goal, and cancel if it's no longer valid, or if the new goal is {@code null}.
|
* Cancel the current path if the goals are not equal
|
||||||
*/
|
*/
|
||||||
FORCE_REVALIDATE_GOAL_AND_PATH
|
FORCE_REVALIDATE_GOAL_AND_PATH
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,41 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils;
|
||||||
|
|
||||||
|
import baritone.api.pathing.calc.IPath;
|
||||||
|
|
||||||
|
import java.util.Optional;
|
||||||
|
|
||||||
|
public class PathCalculationResult {
|
||||||
|
|
||||||
|
public final Optional<IPath> path;
|
||||||
|
public final Type type;
|
||||||
|
|
||||||
|
public PathCalculationResult(Type type, Optional<IPath> path) {
|
||||||
|
this.path = path;
|
||||||
|
this.type = type;
|
||||||
|
}
|
||||||
|
|
||||||
|
public enum Type {
|
||||||
|
SUCCESS_TO_GOAL,
|
||||||
|
SUCCESS_SEGMENT,
|
||||||
|
FAILURE,
|
||||||
|
CANCELLATION,
|
||||||
|
EXCEPTION,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -28,6 +28,7 @@ import baritone.api.pathing.calc.IPathFinder;
|
|||||||
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.api.utils.BetterBlockPos;
|
import baritone.api.utils.BetterBlockPos;
|
||||||
|
import baritone.api.utils.PathCalculationResult;
|
||||||
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;
|
||||||
@@ -379,7 +380,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||||||
logDebug("Starting to search for path from " + start + " to " + goal);
|
logDebug("Starting to search for path from " + start + " to " + goal);
|
||||||
}
|
}
|
||||||
|
|
||||||
Optional<IPath> path = findPath(start, previous, context);
|
PathCalculationResult calcResult = findPath(start, previous, context);
|
||||||
|
Optional<IPath> path = calcResult.path;
|
||||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||||
path = path.map(p -> {
|
path = path.map(p -> {
|
||||||
IPath result = p.cutoffAtLoadedChunks();
|
IPath result = p.cutoffAtLoadedChunks();
|
||||||
@@ -411,7 +413,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||||||
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||||
current = executor.get();
|
current = executor.get();
|
||||||
} else {
|
} else {
|
||||||
queuePathEvent(PathEvent.CALC_FAILED);
|
if (calcResult.type != PathCalculationResult.Type.CANCELLATION && calcResult.type != PathCalculationResult.Type.EXCEPTION) {
|
||||||
|
// don't dispatch CALC_FAILED on cancellation
|
||||||
|
queuePathEvent(PathEvent.CALC_FAILED);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (next == null) {
|
if (next == null) {
|
||||||
@@ -425,18 +430,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||||||
throw new IllegalStateException("I have no idea what to do with this path");
|
throw new IllegalStateException("I have no idea what to do with this path");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
if (talkAboutIt && current != null && current.getPath() != null) {
|
||||||
|
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
||||||
if (talkAboutIt && current != null && current.getPath() != null) {
|
logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||||
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
} else {
|
||||||
logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||||
} else {
|
}
|
||||||
logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
}
|
||||||
|
synchronized (pathCalcLock) {
|
||||||
|
isPathCalcInProgress = false;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
synchronized (pathCalcLock) {
|
|
||||||
isPathCalcInProgress = false;
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -447,11 +450,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||||||
* @param start
|
* @param start
|
||||||
* @return
|
* @return
|
||||||
*/
|
*/
|
||||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
|
private PathCalculationResult findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
|
||||||
Goal goal = this.goal;
|
Goal goal = this.goal;
|
||||||
if (goal == null) {
|
if (goal == null) {
|
||||||
logDebug("no goal");
|
logDebug("no goal");
|
||||||
return Optional.empty();
|
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, Optional.empty());
|
||||||
}
|
}
|
||||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
|
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
|
||||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||||
@@ -478,7 +481,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||||||
} catch (Exception e) {
|
} catch (Exception e) {
|
||||||
logDebug("Pathing exception: " + e);
|
logDebug("Pathing exception: " + e);
|
||||||
e.printStackTrace();
|
e.printStackTrace();
|
||||||
return Optional.empty();
|
return new PathCalculationResult(PathCalculationResult.Type.EXCEPTION, Optional.empty());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,6 +21,7 @@ import baritone.Baritone;
|
|||||||
import baritone.api.pathing.calc.IPath;
|
import baritone.api.pathing.calc.IPath;
|
||||||
import baritone.api.pathing.calc.IPathFinder;
|
import baritone.api.pathing.calc.IPathFinder;
|
||||||
import baritone.api.pathing.goals.Goal;
|
import baritone.api.pathing.goals.Goal;
|
||||||
|
import baritone.api.utils.PathCalculationResult;
|
||||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||||
|
|
||||||
import java.util.Optional;
|
import java.util.Optional;
|
||||||
@@ -82,16 +83,26 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|||||||
cancelRequested = true;
|
cancelRequested = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized Optional<IPath> calculate(long timeout) {
|
public synchronized PathCalculationResult calculate(long timeout) {
|
||||||
if (isFinished) {
|
if (isFinished) {
|
||||||
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
||||||
}
|
}
|
||||||
this.cancelRequested = false;
|
this.cancelRequested = false;
|
||||||
try {
|
try {
|
||||||
Optional<IPath> path = calculate0(timeout);
|
Optional<IPath> path = calculate0(timeout);
|
||||||
path.ifPresent(IPath::postProcess);
|
path = path.map(IPath::postProcess);
|
||||||
isFinished = true;
|
isFinished = true;
|
||||||
return path;
|
if (cancelRequested) {
|
||||||
|
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
|
||||||
|
}
|
||||||
|
if (!path.isPresent()) {
|
||||||
|
return new PathCalculationResult(PathCalculationResult.Type.FAILURE, path);
|
||||||
|
}
|
||||||
|
if (goal.isInGoal(path.get().getDest())) {
|
||||||
|
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path);
|
||||||
|
} else {
|
||||||
|
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_SEGMENT, path);
|
||||||
|
}
|
||||||
} finally {
|
} finally {
|
||||||
// this is run regardless of what exception may or may not be raised by calculate0
|
// this is run regardless of what exception may or may not be raised by calculate0
|
||||||
currentlyRunning = null;
|
currentlyRunning = null;
|
||||||
|
|||||||
@@ -17,7 +17,6 @@
|
|||||||
|
|
||||||
package baritone.pathing.calc;
|
package baritone.pathing.calc;
|
||||||
|
|
||||||
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;
|
||||||
import baritone.api.pathing.movement.IMovement;
|
import baritone.api.pathing.movement.IMovement;
|
||||||
@@ -25,9 +24,8 @@ 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.CutoffPath;
|
import baritone.pathing.path.CutoffPath;
|
||||||
import net.minecraft.client.Minecraft;
|
import baritone.utils.Helper;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import baritone.utils.pathing.PathBase;
|
||||||
import net.minecraft.world.chunk.EmptyChunk;
|
|
||||||
|
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
@@ -39,7 +37,7 @@ import java.util.List;
|
|||||||
*
|
*
|
||||||
* @author leijurv
|
* @author leijurv
|
||||||
*/
|
*/
|
||||||
class Path implements IPath {
|
class Path extends PathBase {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The start position of this path
|
* The start position of this path
|
||||||
@@ -59,6 +57,8 @@ class Path implements IPath {
|
|||||||
|
|
||||||
private final List<Movement> movements;
|
private final List<Movement> movements;
|
||||||
|
|
||||||
|
private final List<PathNode> nodes;
|
||||||
|
|
||||||
private final Goal goal;
|
private final Goal goal;
|
||||||
|
|
||||||
private final int numNodes;
|
private final int numNodes;
|
||||||
@@ -71,8 +71,9 @@ class Path implements IPath {
|
|||||||
this.numNodes = numNodes;
|
this.numNodes = numNodes;
|
||||||
this.path = new ArrayList<>();
|
this.path = new ArrayList<>();
|
||||||
this.movements = new ArrayList<>();
|
this.movements = new ArrayList<>();
|
||||||
|
this.nodes = new ArrayList<>();
|
||||||
this.goal = goal;
|
this.goal = goal;
|
||||||
assemblePath(start, end);
|
assemblePath(end);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -81,62 +82,80 @@ class Path implements IPath {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assembles this path given the start and end nodes.
|
* Assembles this path given the end node.
|
||||||
*
|
*
|
||||||
* @param start The start node
|
* @param end The end node
|
||||||
* @param end The end node
|
|
||||||
*/
|
*/
|
||||||
private void assemblePath(PathNode start, PathNode end) {
|
private void assemblePath(PathNode end) {
|
||||||
if (!path.isEmpty() || !movements.isEmpty()) {
|
if (!path.isEmpty() || !movements.isEmpty()) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
PathNode current = end;
|
PathNode current = end;
|
||||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||||
|
LinkedList<PathNode> tempNodes = new LinkedList();
|
||||||
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||||
// Instead, do it into a linked list, then convert at the end
|
// Instead, do it into a linked list, then convert at the end
|
||||||
while (!current.equals(start)) {
|
while (current != null) {
|
||||||
|
tempNodes.addFirst(current);
|
||||||
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
|
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
|
||||||
current = current.previous;
|
current = current.previous;
|
||||||
}
|
}
|
||||||
tempPath.addFirst(this.start);
|
|
||||||
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
|
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
|
||||||
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
||||||
// to performantly do that conversion since it knows the length.
|
// to performantly do that conversion since it knows the length.
|
||||||
path.addAll(tempPath);
|
path.addAll(tempPath);
|
||||||
|
nodes.addAll(tempNodes);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void assembleMovements() {
|
private boolean assembleMovements() {
|
||||||
if (path.isEmpty() || !movements.isEmpty()) {
|
if (path.isEmpty() || !movements.isEmpty()) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
for (int i = 0; i < path.size() - 1; i++) {
|
for (int i = 0; i < path.size() - 1; i++) {
|
||||||
movements.add(runBackwards(path.get(i), path.get(i + 1)));
|
double cost = nodes.get(i + 1).cost - nodes.get(i).cost;
|
||||||
|
Movement move = runBackwards(path.get(i), path.get(i + 1), cost);
|
||||||
|
if (move == null) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
movements.add(move);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static Movement runBackwards(BetterBlockPos src, BetterBlockPos dest) { // TODO this is horrifying
|
private static Movement runBackwards(BetterBlockPos src, BetterBlockPos dest, double cost) {
|
||||||
for (Moves moves : Moves.values()) {
|
for (Moves moves : Moves.values()) {
|
||||||
Movement move = moves.apply0(src);
|
Movement move = moves.apply0(src);
|
||||||
if (move.getDest().equals(dest)) {
|
if (move.getDest().equals(dest)) {
|
||||||
// TODO instead of recalculating here, could we take pathNode.cost - pathNode.prevNode.cost to get the cost as-calculated?
|
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
|
||||||
move.recalculateCost(); // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
|
move.override(cost);
|
||||||
return move;
|
return move;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// this is no longer called from bestPathSoFar, now it's in postprocessing
|
// this is no longer called from bestPathSoFar, now it's in postprocessing
|
||||||
throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
Helper.HELPER.logDebug("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
||||||
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void postProcess() {
|
public IPath postProcess() {
|
||||||
if (verified) {
|
if (verified) {
|
||||||
throw new IllegalStateException();
|
throw new IllegalStateException();
|
||||||
}
|
}
|
||||||
verified = true;
|
verified = true;
|
||||||
assembleMovements();
|
boolean failed = assembleMovements();
|
||||||
// more post processing here
|
|
||||||
movements.forEach(Movement::checkLoadedChunk);
|
movements.forEach(Movement::checkLoadedChunk);
|
||||||
|
|
||||||
|
if (failed) { // at least one movement became impossible during calculation
|
||||||
|
CutoffPath res = new CutoffPath(this, movements().size());
|
||||||
|
if (res.movements().size() != movements.size()) {
|
||||||
|
throw new IllegalStateException();
|
||||||
|
}
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
// more post processing here
|
||||||
sanityCheck();
|
sanityCheck();
|
||||||
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -166,28 +185,4 @@ 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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -95,7 +95,7 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
|
|||||||
return getCost();
|
return getCost();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void override(double cost) {
|
public void override(double cost) {
|
||||||
this.cost = cost;
|
this.cost = cost;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -21,11 +21,12 @@ import baritone.api.pathing.calc.IPath;
|
|||||||
import baritone.api.pathing.goals.Goal;
|
import baritone.api.pathing.goals.Goal;
|
||||||
import baritone.api.pathing.movement.IMovement;
|
import baritone.api.pathing.movement.IMovement;
|
||||||
import baritone.api.utils.BetterBlockPos;
|
import baritone.api.utils.BetterBlockPos;
|
||||||
|
import baritone.utils.pathing.PathBase;
|
||||||
|
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
public class CutoffPath implements IPath {
|
public class CutoffPath extends PathBase {
|
||||||
|
|
||||||
private final List<BetterBlockPos> path;
|
private final List<BetterBlockPos> path;
|
||||||
|
|
||||||
|
|||||||
@@ -21,10 +21,11 @@ import baritone.api.pathing.calc.IPath;
|
|||||||
import baritone.api.pathing.goals.Goal;
|
import baritone.api.pathing.goals.Goal;
|
||||||
import baritone.api.pathing.movement.IMovement;
|
import baritone.api.pathing.movement.IMovement;
|
||||||
import baritone.api.utils.BetterBlockPos;
|
import baritone.api.utils.BetterBlockPos;
|
||||||
|
import baritone.utils.pathing.PathBase;
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
|
|
||||||
public class SplicedPath implements IPath {
|
public class SplicedPath extends PathBase {
|
||||||
private final List<BetterBlockPos> path;
|
private final List<BetterBlockPos> path;
|
||||||
|
|
||||||
private final List<IMovement> movements;
|
private final List<IMovement> movements;
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ import baritone.utils.BaritoneProcessHelper;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
import net.minecraft.util.math.BlockPos;
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||||||
@Override
|
@Override
|
||||||
public void getToBlock(Block block) {
|
public void getToBlock(Block block) {
|
||||||
gettingTo = block;
|
gettingTo = block;
|
||||||
rescan();
|
knownLocations = null;
|
||||||
|
rescan(new ArrayList<>());
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -55,7 +57,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||||||
@Override
|
@Override
|
||||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||||
if (knownLocations == null) {
|
if (knownLocations == null) {
|
||||||
rescan();
|
rescan(new ArrayList<>());
|
||||||
}
|
}
|
||||||
if (knownLocations.isEmpty()) {
|
if (knownLocations.isEmpty()) {
|
||||||
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
|
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
|
||||||
@@ -73,7 +75,8 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||||||
}
|
}
|
||||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||||
Baritone.getExecutor().execute(this::rescan);
|
List<BlockPos> current = new ArrayList<>(knownLocations);
|
||||||
|
Baritone.getExecutor().execute(() -> rescan(current));
|
||||||
}
|
}
|
||||||
Goal goal = new GoalComposite(knownLocations.stream().map(GoalGetToBlock::new).toArray(Goal[]::new));
|
Goal goal = new GoalComposite(knownLocations.stream().map(GoalGetToBlock::new).toArray(Goal[]::new));
|
||||||
if (goal.isInGoal(playerFeet())) {
|
if (goal.isInGoal(playerFeet())) {
|
||||||
@@ -93,7 +96,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||||||
return "Get To Block " + gettingTo;
|
return "Get To Block " + gettingTo;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rescan() {
|
private void rescan(List<BlockPos> known) {
|
||||||
knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64, world());
|
knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64, world(), known);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -56,6 +56,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
private List<Block> mining;
|
private List<Block> mining;
|
||||||
private List<BlockPos> knownOreLocations;
|
private List<BlockPos> knownOreLocations;
|
||||||
private BlockPos branchPoint;
|
private BlockPos branchPoint;
|
||||||
|
private GoalRunAway branchPointRunaway;
|
||||||
private int desiredQuantity;
|
private int desiredQuantity;
|
||||||
private int tickCount;
|
private int tickCount;
|
||||||
|
|
||||||
@@ -87,7 +88,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
}
|
}
|
||||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||||
baritone.getExecutor().execute(this::rescan);
|
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||||
|
baritone.getExecutor().execute(() -> rescan(curr));
|
||||||
}
|
}
|
||||||
if (Baritone.settings().legitMine.get()) {
|
if (Baritone.settings().legitMine.get()) {
|
||||||
addNearby();
|
addNearby();
|
||||||
@@ -99,7 +101,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
cancel();
|
cancel();
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
return new PathingCommand(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
@@ -126,31 +128,37 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
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
|
||||||
|
int y = Baritone.settings().legitMineYLevel.get();
|
||||||
if (branchPoint == null) {
|
if (branchPoint == null) {
|
||||||
int y = Baritone.settings().legitMineYLevel.get();
|
|
||||||
if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
||||||
// cool, path is over and we are at desired y
|
// cool, path is over and we are at desired y
|
||||||
branchPoint = playerFeet();
|
branchPoint = playerFeet();
|
||||||
|
branchPointRunaway = null;
|
||||||
} else {
|
} else {
|
||||||
return new GoalYLevel(y);
|
return new GoalYLevel(y);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
// TODO shaft mode, mine 1x1 shafts to either side
|
||||||
if (playerFeet().equals(branchPoint)) {
|
// TODO also, see if the GoalRunAway with maintain Y at 11 works even from the surface
|
||||||
// TODO mine 1x1 shafts to either side
|
if (branchPointRunaway == null) {
|
||||||
branchPoint = branchPoint.north(10);
|
branchPointRunaway = new GoalRunAway(1, Optional.of(y), branchPoint) {
|
||||||
|
@Override
|
||||||
|
public boolean isInGoal(int x, int y, int z) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
};
|
||||||
}
|
}
|
||||||
return new GoalBlock(branchPoint);
|
return branchPointRunaway;
|
||||||
}
|
}
|
||||||
|
|
||||||
private void rescan() {
|
private void rescan(List<BlockPos> already) {
|
||||||
if (mining == null) {
|
if (mining == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (Baritone.settings().legitMine.get()) {
|
if (Baritone.settings().legitMine.get()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<BlockPos> locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world());
|
List<BlockPos> locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world(), already);
|
||||||
locs.addAll(droppedItemsScan(mining, world()));
|
locs.addAll(droppedItemsScan(mining, world()));
|
||||||
if (locs.isEmpty()) {
|
if (locs.isEmpty()) {
|
||||||
logDebug("No locations for " + mining + " known, cancelling");
|
logDebug("No locations for " + mining + " known, cancelling");
|
||||||
@@ -205,7 +213,10 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
|
/*public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
|
||||||
|
|
||||||
|
}*/
|
||||||
|
public static List<BlockPos> searchWorld(List<Block> mining, int max, World world, List<BlockPos> alreadyKnown) {
|
||||||
List<BlockPos> locs = new ArrayList<>();
|
List<BlockPos> locs = new ArrayList<>();
|
||||||
List<Block> uninteresting = new ArrayList<>();
|
List<Block> uninteresting = new ArrayList<>();
|
||||||
//long b = System.currentTimeMillis();
|
//long b = System.currentTimeMillis();
|
||||||
@@ -225,6 +236,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26));
|
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26));
|
||||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||||
}
|
}
|
||||||
|
locs.addAll(alreadyKnown);
|
||||||
return prune(locs, mining, max, world);
|
return prune(locs, mining, max, world);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -283,6 +295,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||||||
this.desiredQuantity = quantity;
|
this.desiredQuantity = quantity;
|
||||||
this.knownOreLocations = new ArrayList<>();
|
this.knownOreLocations = new ArrayList<>();
|
||||||
this.branchPoint = null;
|
this.branchPoint = null;
|
||||||
rescan();
|
this.branchPointRunaway = null;
|
||||||
|
rescan(new ArrayList<>());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -78,7 +78,7 @@ public class PathingControlManager {
|
|||||||
break;
|
break;
|
||||||
case FORCE_REVALIDATE_GOAL_AND_PATH:
|
case FORCE_REVALIDATE_GOAL_AND_PATH:
|
||||||
p.secretInternalSetGoalAndPath(cmd.goal);
|
p.secretInternalSetGoalAndPath(cmd.goal);
|
||||||
if (cmd.goal == null || revalidateGoal(cmd.goal)) {
|
if (cmd.goal == null || forceRevalidate(cmd.goal) || revalidateGoal(cmd.goal)) {
|
||||||
// pwnage
|
// pwnage
|
||||||
p.cancelSegmentIfSafe();
|
p.cancelSegmentIfSafe();
|
||||||
}
|
}
|
||||||
@@ -100,6 +100,17 @@ public class PathingControlManager {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public boolean forceRevalidate(Goal newGoal) {
|
||||||
|
PathExecutor current = baritone.getPathingBehavior().getCurrent();
|
||||||
|
if (current != null) {
|
||||||
|
if (newGoal.isInGoal(current.getPath().getDest())) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
return !newGoal.toString().equals(current.getPath().getGoal().toString());
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
public boolean revalidateGoal(Goal newGoal) {
|
public boolean revalidateGoal(Goal newGoal) {
|
||||||
PathExecutor current = baritone.getPathingBehavior().getCurrent();
|
PathExecutor current = baritone.getPathingBehavior().getCurrent();
|
||||||
if (current != null) {
|
if (current != null) {
|
||||||
|
|||||||
@@ -0,0 +1,52 @@
|
|||||||
|
/*
|
||||||
|
* 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.utils.pathing;
|
||||||
|
|
||||||
|
import baritone.api.BaritoneAPI;
|
||||||
|
import baritone.api.pathing.calc.IPath;
|
||||||
|
import baritone.api.pathing.goals.Goal;
|
||||||
|
import baritone.pathing.path.CutoffPath;
|
||||||
|
import net.minecraft.client.Minecraft;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.chunk.EmptyChunk;
|
||||||
|
|
||||||
|
public abstract class PathBase implements IPath {
|
||||||
|
@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() - 1) * factor);
|
||||||
|
return new CutoffPath(this, newLength);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user