Merge branch 'segment-calculation' into comms

This commit is contained in:
Leijurv 2018-11-23 10:36:56 -08:00
commit 81a9b71429
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
30 changed files with 406 additions and 156 deletions

View File

@ -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)

View File

@ -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

View File

@ -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
}
}

View File

@ -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);
}
}
}

View File

@ -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

View File

@ -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() {

View File

@ -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;
}
}

View File

@ -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()
)

View File

@ -10,6 +10,7 @@
"client": [
"MixinAnvilChunkLoader",
"MixinBlockPos",
"MixinChunkProviderClient",
"MixinChunkProviderServer",
"MixinEntity",
"MixinEntityLivingBase",

View File

@ -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());
}
}

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}
}
}
}

View File

@ -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

View File

@ -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);

View File

@ -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) {

View File

@ -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) {

View File

@ -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);
}

View File

@ -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;
}
}

View File

@ -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();

View File

@ -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());
}

View File

@ -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();

View File

@ -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();
}

View File

@ -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()));
}
}

View File

@ -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);
}
}

View File

@ -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));
}
}
}

View File

@ -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;
}

View File

@ -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);
}

View File

@ -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();
}

View File

@ -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);
});
}
}