forked from RepoMirrors/baritone
Merge branch 'segment-calculation' into comms
This commit is contained in:
commit
81a9b71429
|
@ -63,7 +63,7 @@ BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAnd
|
|||
|
||||
# FAQ
|
||||
|
||||
## Can I use Baritone as a library in my hacked client?
|
||||
## Can I use Baritone as a library in my custom utility client?
|
||||
|
||||
Sure! (As long as usage is in compliance with the LGPL 3 License)
|
||||
|
||||
|
|
|
@ -247,14 +247,24 @@ public class Settings {
|
|||
public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* Pathing can never take longer than this
|
||||
* Pathing ends after this amount of time, if a path has been found
|
||||
*/
|
||||
public Setting<Long> pathTimeoutMS = new Setting<>(2000L);
|
||||
public Setting<Long> primaryTimeoutMS = new Setting<>(500L);
|
||||
|
||||
/**
|
||||
* Planning ahead while executing a segment can never take longer than this
|
||||
* Pathing can never take longer than this, even if that means failing to find any path at all
|
||||
*/
|
||||
public Setting<Long> planAheadTimeoutMS = new Setting<>(4000L);
|
||||
public Setting<Long> failureTimeoutMS = new Setting<>(2000L);
|
||||
|
||||
/**
|
||||
* Planning ahead while executing a segment ends after this amount of time, if a path has been found
|
||||
*/
|
||||
public Setting<Long> planAheadPrimaryTimeoutMS = new Setting<>(4000L);
|
||||
|
||||
/**
|
||||
* Planning ahead while executing a segment can never take longer than this, even if that means failing to find any path at all
|
||||
*/
|
||||
public Setting<Long> planAheadFailureTimeoutMS = new Setting<>(5000L);
|
||||
|
||||
/**
|
||||
* For debugging, consider nodes much much slower
|
||||
|
|
|
@ -94,7 +94,16 @@ public final class ChunkEvent {
|
|||
|
||||
/**
|
||||
* When the chunk is being populated with blocks, tile entities, etc.
|
||||
* <p>
|
||||
* And it's a full chunk
|
||||
*/
|
||||
POPULATE
|
||||
POPULATE_FULL,
|
||||
|
||||
/**
|
||||
* When the chunk is being populated with blocks, tile entities, etc.
|
||||
* <p>
|
||||
* And it's a partial chunk
|
||||
*/
|
||||
POPULATE_PARTIAL
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,9 +21,9 @@ import baritone.api.Settings;
|
|||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
|
@ -153,9 +153,10 @@ public interface IPath {
|
|||
if (path.size() != movements.size() + 1) {
|
||||
throw new IllegalStateException("Size of path array is unexpected");
|
||||
}
|
||||
HashSet<BetterBlockPos> seenSoFar = new HashSet<>();
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
BlockPos src = path.get(i);
|
||||
BlockPos dest = path.get(i + 1);
|
||||
BetterBlockPos src = path.get(i);
|
||||
BetterBlockPos dest = path.get(i + 1);
|
||||
IMovement movement = movements.get(i);
|
||||
if (!src.equals(movement.getSrc())) {
|
||||
throw new IllegalStateException("Path source is not equal to the movement source");
|
||||
|
@ -163,6 +164,10 @@ public interface IPath {
|
|||
if (!dest.equals(movement.getDest())) {
|
||||
throw new IllegalStateException("Path destination is not equal to the movement destination");
|
||||
}
|
||||
if (seenSoFar.contains(src)) {
|
||||
throw new IllegalStateException("Path doubles back on itself, making a loop");
|
||||
}
|
||||
seenSoFar.add(src);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -36,7 +36,7 @@ public interface IPathFinder {
|
|||
*
|
||||
* @return The final path
|
||||
*/
|
||||
PathCalculationResult calculate(long timeout);
|
||||
PathCalculationResult calculate(long primaryTimeout, long failureTimeout);
|
||||
|
||||
/**
|
||||
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
||||
|
|
|
@ -33,6 +33,9 @@ public class PathCalculationResult {
|
|||
public PathCalculationResult(Type type, IPath path) {
|
||||
this.path = path;
|
||||
this.type = type;
|
||||
if (type == null) {
|
||||
throw new IllegalArgumentException("come on");
|
||||
}
|
||||
}
|
||||
|
||||
public final Optional<IPath> getPath() {
|
||||
|
|
|
@ -0,0 +1,39 @@
|
|||
/*
|
||||
* 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.launch.mixins;
|
||||
|
||||
import baritone.utils.accessor.IChunkProviderClient;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(ChunkProviderClient.class)
|
||||
public class MixinChunkProviderClient implements IChunkProviderClient {
|
||||
|
||||
@Shadow
|
||||
@Final
|
||||
private Long2ObjectMap<Chunk> loadedChunks;
|
||||
|
||||
@Override
|
||||
public Long2ObjectMap<Chunk> loadedChunks() {
|
||||
return this.loadedChunks;
|
||||
}
|
||||
}
|
|
@ -49,7 +49,7 @@ public class MixinNetHandlerPlayClient {
|
|||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(
|
||||
EventState.PRE,
|
||||
ChunkEvent.Type.POPULATE,
|
||||
packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL,
|
||||
packetIn.getChunkX(),
|
||||
packetIn.getChunkZ()
|
||||
)
|
||||
|
@ -68,7 +68,7 @@ public class MixinNetHandlerPlayClient {
|
|||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(
|
||||
EventState.POST,
|
||||
ChunkEvent.Type.POPULATE,
|
||||
packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL,
|
||||
packetIn.getChunkX(),
|
||||
packetIn.getChunkZ()
|
||||
)
|
||||
|
|
|
@ -10,6 +10,7 @@
|
|||
"client": [
|
||||
"MixinAnvilChunkLoader",
|
||||
"MixinBlockPos",
|
||||
"MixinChunkProviderClient",
|
||||
"MixinChunkProviderServer",
|
||||
"MixinEntity",
|
||||
"MixinEntityLivingBase",
|
||||
|
|
|
@ -396,21 +396,27 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||
logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller
|
||||
return;
|
||||
}
|
||||
long timeout;
|
||||
long primaryTimeout;
|
||||
long failureTimeout;
|
||||
if (current == null) {
|
||||
timeout = Baritone.settings().pathTimeoutMS.<Long>get();
|
||||
primaryTimeout = Baritone.settings().primaryTimeoutMS.get();
|
||||
failureTimeout = Baritone.settings().failureTimeoutMS.get();
|
||||
} else {
|
||||
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
|
||||
primaryTimeout = Baritone.settings().planAheadPrimaryTimeoutMS.get();
|
||||
failureTimeout = Baritone.settings().planAheadFailureTimeoutMS.get();
|
||||
}
|
||||
CalculationContext context = new CalculationContext(baritone); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
|
||||
AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context);
|
||||
if (!Objects.equals(pathfinder.getGoal(), goal)) {
|
||||
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
}
|
||||
inProgress = pathfinder;
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
if (talkAboutIt) {
|
||||
logDebug("Starting to search for path from " + start + " to " + goal);
|
||||
}
|
||||
|
||||
PathCalculationResult calcResult = pathfinder.calculate(timeout);
|
||||
PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout);
|
||||
Optional<IPath> path = calcResult.getPath();
|
||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||
path = path.map(p -> {
|
||||
|
@ -474,12 +480,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
|||
});
|
||||
}
|
||||
|
||||
private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
public static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
Goal transformed = goal;
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
|
||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
if (context.world().getChunk(pos) instanceof EmptyChunk) {
|
||||
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
transformed = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
}
|
||||
|
|
|
@ -124,7 +124,7 @@ public final class ChunkPacker {
|
|||
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block.equals(Blocks.WATER)) {
|
||||
if (block.equals(Blocks.WATER) && !MovementHelper.isFlowing(state)) {
|
||||
// only water source blocks are plausibly usable, flowing water should be avoid
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
|
|
@ -70,7 +70,7 @@ public final class GameEventHandler implements IEventBus, Helper {
|
|||
ChunkEvent.Type type = event.getType();
|
||||
|
||||
boolean isPostPopulate = state == EventState.POST
|
||||
&& type == ChunkEvent.Type.POPULATE;
|
||||
&& (type == ChunkEvent.Type.POPULATE_FULL || type == ChunkEvent.Type.POPULATE_PARTIAL);
|
||||
|
||||
World world = baritone.getPlayerContext().world();
|
||||
|
||||
|
|
|
@ -49,7 +49,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
|||
}
|
||||
|
||||
@Override
|
||||
protected Optional<IPath> calculate0(long timeout) {
|
||||
protected Optional<IPath> calculate0(long primaryTimeout, long failureTimeout) {
|
||||
startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
|
||||
startNode.cost = 0;
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
|
@ -68,10 +68,11 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
|||
long startTime = System.nanoTime() / 1000000L;
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
if (slowPath) {
|
||||
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms");
|
||||
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms");
|
||||
}
|
||||
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout);
|
||||
//long lastPrintout = 0;
|
||||
long primaryTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : primaryTimeout);
|
||||
long failureTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : failureTimeout);
|
||||
boolean failing = true;
|
||||
int numNodes = 0;
|
||||
int numMovementsConsidered = 0;
|
||||
int numEmptyChunk = 0;
|
||||
|
@ -79,7 +80,11 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
|||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
|
||||
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) {
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
|
||||
break;
|
||||
}
|
||||
if (slowPath) {
|
||||
try {
|
||||
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
|
||||
|
@ -166,6 +171,9 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
|||
}
|
||||
bestHeuristicSoFar[i] = heuristic;
|
||||
bestSoFar[i] = neighbor;
|
||||
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
|
||||
failing = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -83,13 +83,14 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|||
cancelRequested = true;
|
||||
}
|
||||
|
||||
public synchronized PathCalculationResult calculate(long timeout) {
|
||||
@Override
|
||||
public synchronized PathCalculationResult calculate(long primaryTimeout, long failureTimeout) {
|
||||
if (isFinished) {
|
||||
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
||||
}
|
||||
this.cancelRequested = false;
|
||||
try {
|
||||
IPath path = calculate0(timeout).map(IPath::postProcess).orElse(null);
|
||||
IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null);
|
||||
isFinished = true;
|
||||
if (cancelRequested) {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
|
||||
|
@ -112,7 +113,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|||
}
|
||||
}
|
||||
|
||||
protected abstract Optional<IPath> calculate0(long timeout);
|
||||
protected abstract Optional<IPath> calculate0(long primaryTimeout, long failureTimeout);
|
||||
|
||||
/**
|
||||
* Determines the distance squared from the specified node to the start
|
||||
|
@ -157,7 +158,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|||
|
||||
@Override
|
||||
public Optional<IPath> bestPathSoFar() {
|
||||
if (startNode == null || bestSoFar == null || bestSoFar[0] == null) {
|
||||
if (startNode == null || bestSoFar == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
|
@ -165,12 +166,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
|||
continue;
|
||||
}
|
||||
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
try {
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
|
||||
} catch (IllegalStateException ex) {
|
||||
System.out.println("Unable to construct path to render");
|
||||
return Optional.empty();
|
||||
}
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
|
||||
}
|
||||
}
|
||||
// instead of returning bestSoFar[0], be less misleading
|
||||
|
|
|
@ -129,7 +129,7 @@ class Path extends PathBase {
|
|||
|
||||
private Movement runBackwards(BetterBlockPos src, BetterBlockPos dest, double cost) {
|
||||
for (Moves moves : Moves.values()) {
|
||||
Movement move = moves.apply0(context.getBaritone(), src);
|
||||
Movement move = moves.apply0(context, src);
|
||||
if (move.getDest().equals(dest)) {
|
||||
// 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);
|
||||
|
|
|
@ -86,7 +86,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||
// so the only remaining dynamic isPassables are snow and trapdoor
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (bsi.getWorld().getChunk(x >> 4, z >> 4) instanceof EmptyChunk) {
|
||||
if (!bsi.worldContainsLoadedChunk(x, z)) {
|
||||
return true;
|
||||
}
|
||||
if (snow) {
|
||||
|
@ -200,7 +200,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||
return true;
|
||||
}
|
||||
|
||||
return isHorizontalBlockPassable(gatePos, state, playerPos, BlockFenceGate.OPEN);
|
||||
return state.getValue(BlockFenceGate.OPEN);
|
||||
}
|
||||
|
||||
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) {
|
||||
|
@ -274,7 +274,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
|||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
|
||||
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
|
|
|
@ -17,7 +17,6 @@
|
|||
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
|
@ -31,8 +30,8 @@ import net.minecraft.util.EnumFacing;
|
|||
public enum Moves {
|
||||
DOWNWARD(0, -1, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementDownward(baritone, src, src.down());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDownward(context.getBaritone(), src, src.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -43,8 +42,8 @@ public enum Moves {
|
|||
|
||||
PILLAR(0, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementPillar(baritone, src, src.up());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementPillar(context.getBaritone(), src, src.up());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -55,8 +54,8 @@ public enum Moves {
|
|||
|
||||
TRAVERSE_NORTH(0, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementTraverse(baritone, src, src.north());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(context.getBaritone(), src, src.north());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -67,8 +66,8 @@ public enum Moves {
|
|||
|
||||
TRAVERSE_SOUTH(0, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementTraverse(baritone, src, src.south());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(context.getBaritone(), src, src.south());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -79,8 +78,8 @@ public enum Moves {
|
|||
|
||||
TRAVERSE_EAST(+1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementTraverse(baritone, src, src.east());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(context.getBaritone(), src, src.east());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -91,8 +90,8 @@ public enum Moves {
|
|||
|
||||
TRAVERSE_WEST(-1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementTraverse(baritone, src, src.west());
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementTraverse(context.getBaritone(), src, src.west());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -103,8 +102,8 @@ public enum Moves {
|
|||
|
||||
ASCEND_NORTH(0, +1, -1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementAscend(baritone, src, new BetterBlockPos(src.x, src.y + 1, src.z - 1));
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -115,8 +114,8 @@ public enum Moves {
|
|||
|
||||
ASCEND_SOUTH(0, +1, +1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementAscend(baritone, src, new BetterBlockPos(src.x, src.y + 1, src.z + 1));
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x, src.y + 1, src.z + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -127,8 +126,8 @@ public enum Moves {
|
|||
|
||||
ASCEND_EAST(+1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementAscend(baritone, src, new BetterBlockPos(src.x + 1, src.y + 1, src.z));
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x + 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -139,8 +138,8 @@ public enum Moves {
|
|||
|
||||
ASCEND_WEST(-1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementAscend(baritone, src, new BetterBlockPos(src.x - 1, src.y + 1, src.z));
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementAscend(context.getBaritone(), src, new BetterBlockPos(src.x - 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -151,13 +150,13 @@ public enum Moves {
|
|||
|
||||
DESCEND_EAST(+1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(baritone), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -169,13 +168,13 @@ public enum Moves {
|
|||
|
||||
DESCEND_WEST(-1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(baritone), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -187,13 +186,13 @@ public enum Moves {
|
|||
|
||||
DESCEND_NORTH(0, -1, -1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(baritone), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -205,13 +204,13 @@ public enum Moves {
|
|||
|
||||
DESCEND_SOUTH(0, -1, +1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(baritone), src.x, src.y, src.z, res);
|
||||
apply(context, src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementDescend(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(baritone, src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
return new MovementFall(context.getBaritone(), src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -223,8 +222,8 @@ public enum Moves {
|
|||
|
||||
DIAGONAL_NORTHEAST(+1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementDiagonal(baritone, src, EnumFacing.NORTH, EnumFacing.EAST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(context.getBaritone(), src, EnumFacing.NORTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -235,8 +234,8 @@ public enum Moves {
|
|||
|
||||
DIAGONAL_NORTHWEST(-1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementDiagonal(baritone, src, EnumFacing.NORTH, EnumFacing.WEST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(context.getBaritone(), src, EnumFacing.NORTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -247,8 +246,8 @@ public enum Moves {
|
|||
|
||||
DIAGONAL_SOUTHEAST(+1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementDiagonal(baritone, src, EnumFacing.SOUTH, EnumFacing.EAST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(context.getBaritone(), src, EnumFacing.SOUTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -259,8 +258,8 @@ public enum Moves {
|
|||
|
||||
DIAGONAL_SOUTHWEST(-1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return new MovementDiagonal(baritone, src, EnumFacing.SOUTH, EnumFacing.WEST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return new MovementDiagonal(context.getBaritone(), src, EnumFacing.SOUTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -271,8 +270,8 @@ public enum Moves {
|
|||
|
||||
PARKOUR_NORTH(0, 0, -4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return MovementParkour.cost(baritone, src, EnumFacing.NORTH);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.NORTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -283,8 +282,8 @@ public enum Moves {
|
|||
|
||||
PARKOUR_SOUTH(0, 0, +4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return MovementParkour.cost(baritone, src, EnumFacing.SOUTH);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.SOUTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -295,8 +294,8 @@ public enum Moves {
|
|||
|
||||
PARKOUR_EAST(+4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return MovementParkour.cost(baritone, src, EnumFacing.EAST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -307,8 +306,8 @@ public enum Moves {
|
|||
|
||||
PARKOUR_WEST(-4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(IBaritone baritone, BetterBlockPos src) {
|
||||
return MovementParkour.cost(baritone, src, EnumFacing.WEST);
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -336,7 +335,7 @@ public enum Moves {
|
|||
this(x, y, z, false, false);
|
||||
}
|
||||
|
||||
public abstract Movement apply0(IBaritone baritone, BetterBlockPos src);
|
||||
public abstract Movement apply0(CalculationContext context, BetterBlockPos src);
|
||||
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
if (dynamicXZ || dynamicY) {
|
||||
|
|
|
@ -211,6 +211,10 @@ public class MovementAscend extends Movement {
|
|||
return state;
|
||||
}
|
||||
|
||||
if (ctx.playerFeet().equals(src.up())) {
|
||||
return state; // no need to hit space if we're already jumping
|
||||
}
|
||||
|
||||
if (headBonkClear()) {
|
||||
return state.setInput(Input.JUMP, true);
|
||||
}
|
||||
|
|
|
@ -21,17 +21,22 @@ import baritone.Baritone;
|
|||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
|
@ -190,6 +195,18 @@ public class MovementDescend extends Movement {
|
|||
// System.out.println(player().posY + " " + playerFeet.getY() + " " + (player().posY - playerFeet.getY()));
|
||||
}*/
|
||||
}
|
||||
if (safeMode()) {
|
||||
double destX = (src.getX() + 0.5) * 0.19 + (dest.getX() + 0.5) * 0.81;
|
||||
double destZ = (src.getZ() + 0.5) * 0.19 + (dest.getZ() + 0.5) * 0.81;
|
||||
EntityPlayerSP player = ctx.player();
|
||||
state.setTarget(new MovementState.MovementTarget(
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F),
|
||||
new Vec3d(destX, dest.getY(), destZ),
|
||||
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
|
||||
false
|
||||
)).setInput(Input.MOVE_FORWARD, true);
|
||||
return state;
|
||||
}
|
||||
double diffX = ctx.player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = ctx.player().posZ - (dest.getZ() + 0.5);
|
||||
double ab = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
|
@ -210,4 +227,16 @@ public class MovementDescend extends Movement {
|
|||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
public boolean safeMode() {
|
||||
// (dest - src) + dest is offset 1 more in the same direction
|
||||
// so it's the block we'd need to worry about running into if we decide to sprint straight through this descend
|
||||
BlockPos into = dest.subtract(src.down()).add(dest);
|
||||
for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(ctx, into.up(y)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -33,6 +33,7 @@ import baritone.utils.BlockStateInterface;
|
|||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockStairs;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
@ -56,11 +57,11 @@ public class MovementParkour extends Movement {
|
|||
this.dist = dist;
|
||||
}
|
||||
|
||||
public static MovementParkour cost(IBaritone baritone, BetterBlockPos src, EnumFacing direction) {
|
||||
public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
cost(new CalculationContext(baritone), src.x, src.y, src.z, direction, res);
|
||||
cost(context, src.x, src.y, src.z, direction, res);
|
||||
int dist = Math.abs(res.x - src.x) + Math.abs(res.z - src.z);
|
||||
return new MovementParkour(baritone, src, dist, direction);
|
||||
return new MovementParkour(context.getBaritone(), src, dist, direction);
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
|
||||
|
@ -68,7 +69,7 @@ public class MovementParkour extends Movement {
|
|||
return;
|
||||
}
|
||||
IBlockState standingOn = context.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn)) {
|
||||
return;
|
||||
}
|
||||
int xDiff = dir.getXOffset();
|
||||
|
|
|
@ -194,12 +194,13 @@ public class MovementPillar extends Movement {
|
|||
}
|
||||
|
||||
|
||||
state.setInput(Input.SNEAK, ctx.player().posY > dest.getY()); // delay placement by 1 tick for ncp compatibility
|
||||
state.setInput(Input.SNEAK, ctx.player().posY > dest.getY() || ctx.player().posY < src.getY() + 0.2D); // delay placement by 1 tick for ncp compatibility
|
||||
// since (lower down) we only right click once player.isSneaking, and that happens the tick after we request to sneak
|
||||
|
||||
double diffX = ctx.player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = ctx.player().posZ - (dest.getZ() + 0.5);
|
||||
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
double flatMotion = Math.sqrt(ctx.player().motionX * ctx.player().motionX + ctx.player().motionZ * ctx.player().motionZ);
|
||||
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
|
||||
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
|
||||
//and 0.17 is reasonably less than 0.2
|
||||
|
@ -209,7 +210,7 @@ public class MovementPillar extends Movement {
|
|||
|
||||
// revise our target to both yaw and pitch if we're going to be moving forward
|
||||
state.setTarget(new MovementState.MovementTarget(rotation, true));
|
||||
} else {
|
||||
} else if (flatMotion < 0.05) {
|
||||
// If our Y coordinate is above our goal, stop jumping
|
||||
state.setInput(Input.JUMP, ctx.player().posY < dest.getY());
|
||||
}
|
||||
|
|
|
@ -226,7 +226,10 @@ public class MovementTraverse extends Movement {
|
|||
if (ctx.playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(ctx, ctx.playerFeet())) {
|
||||
BlockPos into = dest.subtract(src).add(dest);
|
||||
Block intoBelow = BlockStateInterface.get(ctx, into).getBlock();
|
||||
Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock();
|
||||
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !MovementHelper.avoidWalkingInto(intoBelow) && !MovementHelper.avoidWalkingInto(intoAbove)) {
|
||||
state.setInput(Input.SPRINT, true);
|
||||
}
|
||||
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();
|
||||
|
|
|
@ -378,16 +378,10 @@ public class PathExecutor implements IPathExecutor, Helper {
|
|||
IMovement current = path.movements().get(pathPosition);
|
||||
if (current instanceof MovementDescend && pathPosition < path.length() - 2) {
|
||||
|
||||
// (dest - src) + dest is offset 1 more in the same direction
|
||||
// so it's the block we'd need to worry about running into if we decide to sprint straight through this descend
|
||||
|
||||
BlockPos into = current.getDest().subtract(current.getSrc().down()).add(current.getDest());
|
||||
for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(ctx, into.up(y)))) {
|
||||
logDebug("Sprinting would be unsafe");
|
||||
ctx.player().setSprinting(false);
|
||||
return;
|
||||
}
|
||||
if (((MovementDescend) current).safeMode()) {
|
||||
logDebug("Sprinting would be unsafe");
|
||||
ctx.player().setSprinting(false);
|
||||
return;
|
||||
}
|
||||
|
||||
IMovement next = path.movements().get(pathPosition + 1);
|
||||
|
@ -464,7 +458,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
|||
if (next == null) {
|
||||
return cutIfTooLong();
|
||||
}
|
||||
return SplicedPath.trySplice(path, next.path).map(path -> {
|
||||
return SplicedPath.trySplice(path, next.path, false).map(path -> {
|
||||
if (!path.getDest().equals(next.getPath().getDest())) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
|
|
|
@ -62,7 +62,7 @@ public class SplicedPath extends PathBase {
|
|||
return numNodes;
|
||||
}
|
||||
|
||||
public static Optional<SplicedPath> trySplice(IPath first, IPath second) {
|
||||
public static Optional<SplicedPath> trySplice(IPath first, IPath second, boolean allowOverlapCutoff) {
|
||||
if (second == null || first == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
@ -72,18 +72,31 @@ public class SplicedPath extends PathBase {
|
|||
if (!first.getDest().equals(second.getSrc())) {
|
||||
return Optional.empty();
|
||||
}
|
||||
HashSet<BetterBlockPos> a = new HashSet<>(first.positions());
|
||||
for (int i = 1; i < second.length(); i++) {
|
||||
if (a.contains(second.positions().get(i))) {
|
||||
HashSet<BetterBlockPos> secondPos = new HashSet<>(second.positions());
|
||||
int firstPositionInSecond = -1;
|
||||
for (int i = 0; i < first.length() - 1; i++) { // overlap in the very last element is fine (and required) so only go up to first.length() - 1
|
||||
if (secondPos.contains(first.positions().get(i))) {
|
||||
firstPositionInSecond = i;
|
||||
}
|
||||
}
|
||||
if (firstPositionInSecond != -1) {
|
||||
if (!allowOverlapCutoff) {
|
||||
return Optional.empty();
|
||||
}
|
||||
} else {
|
||||
firstPositionInSecond = first.length() - 1;
|
||||
}
|
||||
int positionInSecond = second.positions().indexOf(first.positions().get(firstPositionInSecond));
|
||||
if (!allowOverlapCutoff && positionInSecond != 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
List<BetterBlockPos> positions = new ArrayList<>();
|
||||
List<IMovement> movements = new ArrayList<>();
|
||||
positions.addAll(first.positions());
|
||||
positions.addAll(second.positions().subList(1, second.length()));
|
||||
movements.addAll(first.movements());
|
||||
movements.addAll(second.movements());
|
||||
positions.addAll(first.positions().subList(0, firstPositionInSecond + 1));
|
||||
movements.addAll(first.movements().subList(0, firstPositionInSecond));
|
||||
|
||||
positions.addAll(second.positions().subList(positionInSecond + 1, second.length()));
|
||||
movements.addAll(second.movements().subList(positionInSecond, second.length() - 1));
|
||||
return Optional.of(new SplicedPath(positions, movements, first.getNumNodesConsidered() + second.getNumNodesConsidered(), first.getGoal()));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import baritone.api.pathing.goals.GoalGetToBlock;
|
|||
import baritone.api.process.IGetToBlockProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
@ -46,7 +47,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||
public void getToBlock(Block block) {
|
||||
gettingTo = block;
|
||||
knownLocations = null;
|
||||
rescan(new ArrayList<>());
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -57,7 +58,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (knownLocations == null) {
|
||||
rescan(new ArrayList<>());
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
}
|
||||
if (knownLocations.isEmpty()) {
|
||||
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
|
||||
|
@ -76,7 +77,8 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> current = new ArrayList<>(knownLocations);
|
||||
Baritone.getExecutor().execute(() -> rescan(current));
|
||||
CalculationContext context = new CalculationContext(baritone);
|
||||
Baritone.getExecutor().execute(() -> rescan(current, context));
|
||||
}
|
||||
Goal goal = new GoalComposite(knownLocations.stream().map(GoalGetToBlock::new).toArray(Goal[]::new));
|
||||
if (goal.isInGoal(ctx.playerFeet())) {
|
||||
|
@ -96,7 +98,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
|
|||
return "Get To Block " + gettingTo;
|
||||
}
|
||||
|
||||
private void rescan(List<BlockPos> known) {
|
||||
knownLocations = MineProcess.searchWorld(ctx, Collections.singletonList(gettingTo), 64, known);
|
||||
private void rescan(List<BlockPos> known, CalculationContext context) {
|
||||
knownLocations = MineProcess.searchWorld(context, Collections.singletonList(gettingTo), 64, known);
|
||||
}
|
||||
}
|
|
@ -27,6 +27,7 @@ import baritone.api.utils.RotationUtils;
|
|||
import baritone.cache.CachedChunk;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
|
@ -88,7 +89,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||
Baritone.getExecutor().execute(() -> rescan(curr));
|
||||
CalculationContext context = new CalculationContext(baritone);
|
||||
Baritone.getExecutor().execute(() -> rescan(curr, context));
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
addNearby();
|
||||
|
@ -116,7 +118,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
private Goal updateGoal() {
|
||||
List<BlockPos> locs = knownOreLocations;
|
||||
if (!locs.isEmpty()) {
|
||||
List<BlockPos> locs2 = prune(ctx, 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
|
||||
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new));
|
||||
knownOreLocations = locs2;
|
||||
|
@ -151,14 +153,14 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
return branchPointRunaway;
|
||||
}
|
||||
|
||||
private void rescan(List<BlockPos> already) {
|
||||
private void rescan(List<BlockPos> already, CalculationContext context) {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = searchWorld(ctx, mining, ORE_LOCATIONS_COUNT, already);
|
||||
List<BlockPos> locs = searchWorld(context, mining, ORE_LOCATIONS_COUNT, already);
|
||||
locs.addAll(droppedItemsScan(mining, ctx.world()));
|
||||
if (locs.isEmpty()) {
|
||||
logDebug("No locations for " + mining + " known, cancelling");
|
||||
|
@ -202,16 +204,13 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
return ret;
|
||||
}
|
||||
|
||||
/*public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
|
||||
|
||||
}*/
|
||||
public static List<BlockPos> searchWorld(IPlayerContext ctx, List<Block> mining, int max, List<BlockPos> alreadyKnown) {
|
||||
public static List<BlockPos> searchWorld(CalculationContext ctx, List<Block> mining, int max, List<BlockPos> alreadyKnown) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<Block> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
for (Block m : mining) {
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
|
||||
locs.addAll(ctx.worldData().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.playerFeet().getX(), ctx.playerFeet().getZ(), 1));
|
||||
locs.addAll(ctx.worldData().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 1));
|
||||
} else {
|
||||
uninteresting.add(m);
|
||||
}
|
||||
|
@ -222,7 +221,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
}
|
||||
if (!uninteresting.isEmpty()) {
|
||||
//long before = System.currentTimeMillis();
|
||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx, uninteresting, max, 10, 26));
|
||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx.getBaritone().getPlayerContext(), uninteresting, max, 10, 26));
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
locs.addAll(alreadyKnown);
|
||||
|
@ -232,35 +231,36 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
public void addNearby() {
|
||||
knownOreLocations.addAll(droppedItemsScan(mining, ctx.world()));
|
||||
BlockPos playerFeet = ctx.playerFeet();
|
||||
int searchDist = 4; // why four? idk
|
||||
BlockStateInterface bsi = new BlockStateInterface(ctx);
|
||||
int searchDist = 10;
|
||||
double fakedBlockReachDistance = 20; // at least 10 * sqrt(3) with some extra space to account for positioning within the block
|
||||
for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) {
|
||||
for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) {
|
||||
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
// crucial to only add blocks we can see because otherwise this
|
||||
// is an x-ray and it'll get caught
|
||||
if (mining.contains(BlockStateInterface.getBlock(ctx, pos)) && RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance()).isPresent()) {
|
||||
knownOreLocations.add(pos);
|
||||
if (mining.contains(bsi.get0(x, y, z).getBlock()) && RotationUtils.reachable(ctx.player(), new BlockPos(x, y, z), fakedBlockReachDistance).isPresent()) {
|
||||
knownOreLocations.add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
knownOreLocations = prune(ctx, knownOreLocations, mining, ORE_LOCATIONS_COUNT);
|
||||
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, mining, ORE_LOCATIONS_COUNT);
|
||||
}
|
||||
|
||||
public static List<BlockPos> prune(IPlayerContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
|
||||
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
|
||||
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world());
|
||||
List<BlockPos> locs = locs2
|
||||
.stream()
|
||||
.distinct()
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
.filter(pos -> ctx.world().getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.getBlock(ctx, pos)) || dropped.contains(pos))
|
||||
.filter(pos -> ctx.world().getChunk(pos) instanceof EmptyChunk || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
|
||||
|
||||
// remove any that are implausible to mine (encased in bedrock, or touching lava)
|
||||
.filter(pos -> MineProcess.plausibleToBreak(ctx, pos))
|
||||
.filter(pos -> MineProcess.plausibleToBreak(ctx.bsi(), pos))
|
||||
|
||||
.sorted(Comparator.comparingDouble(ctx.playerFeet()::distanceSq))
|
||||
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (locs.size() > max) {
|
||||
|
@ -269,12 +269,13 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
return locs;
|
||||
}
|
||||
|
||||
public static boolean plausibleToBreak(IPlayerContext ctx, BlockPos pos) {
|
||||
if (MovementHelper.avoidBreaking(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(ctx, pos))) {
|
||||
public static boolean plausibleToBreak(BlockStateInterface bsi, BlockPos pos) {
|
||||
if (MovementHelper.avoidBreaking(bsi, pos.getX(), pos.getY(), pos.getZ(), bsi.get0(pos))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// bedrock above and below makes it implausible, otherwise we're good
|
||||
return !(BlockStateInterface.getBlock(ctx, pos.up()) == Blocks.BEDROCK && BlockStateInterface.getBlock(ctx, pos.down()) == Blocks.BEDROCK);
|
||||
return !(bsi.get0(pos.up()).getBlock() == Blocks.BEDROCK && bsi.get0(pos.down()).getBlock() == Blocks.BEDROCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -289,6 +290,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
|||
this.knownOreLocations = new ArrayList<>();
|
||||
this.branchPoint = null;
|
||||
this.branchPointRunaway = null;
|
||||
rescan(new ArrayList<>());
|
||||
if (mining != null) {
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -21,10 +21,14 @@ import baritone.Baritone;
|
|||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.cache.CachedRegion;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.utils.accessor.IChunkProviderClient;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
|
@ -35,7 +39,7 @@ import net.minecraft.world.chunk.Chunk;
|
|||
*/
|
||||
public class BlockStateInterface {
|
||||
|
||||
private final World world;
|
||||
private final Long2ObjectMap<Chunk> loadedChunks;
|
||||
private final WorldData worldData;
|
||||
|
||||
private Chunk prev = null;
|
||||
|
@ -49,11 +53,14 @@ public class BlockStateInterface {
|
|||
|
||||
public BlockStateInterface(World world, WorldData worldData) {
|
||||
this.worldData = worldData;
|
||||
this.world = world;
|
||||
this.loadedChunks = ((IChunkProviderClient) world.getChunkProvider()).loadedChunks();
|
||||
if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
|
||||
public World getWorld() {
|
||||
return world;
|
||||
public boolean worldContainsLoadedChunk(int blockX, int blockZ) {
|
||||
return loadedChunks.containsKey(ChunkPos.asLong(blockX >> 4, blockZ >> 4));
|
||||
}
|
||||
|
||||
public static Block getBlock(IPlayerContext ctx, BlockPos pos) { // won't be called from the pathing thread because the pathing thread doesn't make a single blockpos pog
|
||||
|
@ -66,6 +73,10 @@ public class BlockStateInterface {
|
|||
// and toBreak and stuff fails when the movement is instantiated out of load range but it's not able to BlockStateInterface.get what it's going to walk on
|
||||
}
|
||||
|
||||
public IBlockState get0(BlockPos pos) {
|
||||
return get0(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
public IBlockState get0(int x, int y, int z) { // Mickey resigned
|
||||
|
||||
// Invalid vertical position
|
||||
|
@ -84,8 +95,9 @@ public class BlockStateInterface {
|
|||
if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) {
|
||||
return cached.getBlockState(x, y, z);
|
||||
}
|
||||
Chunk chunk = world.getChunk(x >> 4, z >> 4);
|
||||
if (chunk.isLoaded()) {
|
||||
Chunk chunk = loadedChunks.get(ChunkPos.asLong(x >> 4, z >> 4));
|
||||
|
||||
if (chunk != null && chunk.isLoaded()) {
|
||||
prev = chunk;
|
||||
return chunk.getBlockState(x, y, z);
|
||||
}
|
||||
|
@ -116,8 +128,8 @@ public class BlockStateInterface {
|
|||
if (prevChunk != null && prevChunk.x == x >> 4 && prevChunk.z == z >> 4) {
|
||||
return true;
|
||||
}
|
||||
prevChunk = world.getChunk(x >> 4, z >> 4);
|
||||
if (prevChunk.isLoaded()) {
|
||||
prevChunk = loadedChunks.get(ChunkPos.asLong(x >> 4, z >> 4));
|
||||
if (prevChunk != null && prevChunk.isLoaded()) {
|
||||
prev = prevChunk;
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -28,6 +28,7 @@ import baritone.behavior.Behavior;
|
|||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.process.CustomGoalProcess;
|
||||
|
@ -449,7 +450,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
|||
return true;
|
||||
}
|
||||
if (msg.equals("costs")) {
|
||||
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(baritone, ctx.playerFeet())).collect(Collectors.toCollection(ArrayList::new));
|
||||
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(new CalculationContext(baritone), ctx.playerFeet())).collect(Collectors.toCollection(ArrayList::new));
|
||||
while (moves.contains(null)) {
|
||||
moves.remove(null);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
/*
|
||||
* 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.accessor;
|
||||
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
public interface IChunkProviderClient {
|
||||
Long2ObjectMap<Chunk> loadedChunks();
|
||||
}
|
|
@ -0,0 +1,87 @@
|
|||
/*
|
||||
* 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.Baritone;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.path.SplicedPath;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Calculate and splice many path segments to reach a goal
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class SegmentedCalculator {
|
||||
private final BetterBlockPos start;
|
||||
private final Goal goal;
|
||||
private final CalculationContext context;
|
||||
|
||||
private SegmentedCalculator(BetterBlockPos start, Goal goal, CalculationContext context) {
|
||||
this.start = start;
|
||||
this.goal = goal;
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private Optional<IPath> doCalc() {
|
||||
Optional<IPath> soFar = Optional.empty();
|
||||
while (true) {
|
||||
PathCalculationResult result = segment(soFar);
|
||||
switch (result.getType()) {
|
||||
case SUCCESS_SEGMENT:
|
||||
break;
|
||||
case SUCCESS_TO_GOAL: // if we've gotten all the way to the goal, we're done
|
||||
case FAILURE: // if path calculation failed, we're done
|
||||
case EXCEPTION: // if path calculation threw an exception, we're done
|
||||
return soFar;
|
||||
default: // CANCELLATION and null should not be possible, nothing else has access to this, so it can't have been canceled
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
IPath segment = result.getPath().get(); // path calculation result type is SUCCESS_SEGMENT, so the path must be present
|
||||
IPath combined = soFar.map(previous -> (IPath) SplicedPath.trySplice(previous, segment, true).get()).orElse(segment);
|
||||
soFar = Optional.of(combined);
|
||||
}
|
||||
}
|
||||
|
||||
private PathCalculationResult segment(Optional<IPath> previous) {
|
||||
BetterBlockPos segmentStart = previous.map(IPath::getDest).orElse(start); // <-- e p i c
|
||||
AbstractNodeCostSearch search = PathingBehavior.createPathfinder(segmentStart, goal, previous.orElse(null), context);
|
||||
return search.calculate(Baritone.settings().primaryTimeoutMS.get(), Baritone.settings().failureTimeoutMS.get()); // use normal time settings, not the plan ahead settings, so as to not overwhelm the computer
|
||||
}
|
||||
|
||||
public static void calculateSegmentsThreaded(BetterBlockPos start, Goal goal, CalculationContext context, Consumer<Optional<IPath>> onCompletion) {
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
Optional<IPath> result;
|
||||
try {
|
||||
result = new SegmentedCalculator(start, goal, context).doCalc();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
result = Optional.empty();
|
||||
}
|
||||
onCompletion.accept(result);
|
||||
});
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue