This commit is contained in:
Leijurv 2018-09-23 12:24:07 -07:00
parent a05d3269a3
commit 59b4e1a993
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
5 changed files with 116 additions and 141 deletions

View File

@ -102,7 +102,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
}
}
MoveResult res = moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z);
if (res.destX != newX || res.destZ != newZ) {
if (!moves.dynamicXZ && (res.destX != newX || res.destZ != newZ)) {
throw new IllegalStateException(moves + " " + res.destX + " " + newX + " " + res.destZ + " " + newZ);
}
numMovementsConsidered++;

View File

@ -264,19 +264,76 @@ public enum Moves {
return new MoveResult(x - 1, y, z + 1, MovementDiagonal.cost(context, x, y, z, x - 1, z + 1));
}
},
// TODO parkour
;
PARKOUR_NORTH(0, -4, true) {
@Override
protected Movement apply0(BetterBlockPos src) {
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.NORTH);
}
@Override
public MoveResult apply(CalculationContext context, int x, int y, int z) {
Tuple<Tuple<Integer, Integer>, Double> res = MovementParkour.cost(context, x, y, z, EnumFacing.NORTH);
return new MoveResult(res.getFirst().getFirst(), y, res.getFirst().getSecond(), res.getSecond());
}
},
PARKOUR_SOUTH(0, +4, true) {
@Override
protected Movement apply0(BetterBlockPos src) {
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.SOUTH);
}
@Override
public MoveResult apply(CalculationContext context, int x, int y, int z) {
Tuple<Tuple<Integer, Integer>, Double> res = MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH);
return new MoveResult(res.getFirst().getFirst(), y, res.getFirst().getSecond(), res.getSecond());
}
},
PARKOUR_EAST(+4, 0, true) {
@Override
protected Movement apply0(BetterBlockPos src) {
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.EAST);
}
@Override
public MoveResult apply(CalculationContext context, int x, int y, int z) {
Tuple<Tuple<Integer, Integer>, Double> res = MovementParkour.cost(context, x, y, z, EnumFacing.EAST);
return new MoveResult(res.getFirst().getFirst(), y, res.getFirst().getSecond(), res.getSecond());
}
},
PARKOUR_WEST(-4, 0, true) {
@Override
protected Movement apply0(BetterBlockPos src) {
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.WEST);
}
@Override
public MoveResult apply(CalculationContext context, int x, int y, int z) {
Tuple<Tuple<Integer, Integer>, Double> res = MovementParkour.cost(context, x, y, z, EnumFacing.WEST);
return new MoveResult(res.getFirst().getFirst(), y, res.getFirst().getSecond(), res.getSecond());
}
};
protected abstract Movement apply0(BetterBlockPos src);
public abstract MoveResult apply(CalculationContext context, int x, int y, int z);
public final boolean dynamicXZ;
public final int xOffset;
public final int zOffset;
Moves(int x, int z) {
Moves(int x, int z, boolean dynamicXZ) {
this.xOffset = x;
this.zOffset = z;
this.dynamicXZ = dynamicXZ;
}
Moves(int x, int z) {
this(x, z, false);
}
}

View File

@ -20,8 +20,6 @@ package baritone.pathing.movement;
import baritone.Baritone;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.pathing.movement.movements.MovementDescend;
import baritone.pathing.movement.movements.MovementFall;
import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*;
@ -142,6 +140,10 @@ public interface MovementHelper extends ActionCosts, Helper {
return fullyPassable(BlockStateInterface.get(pos));
}
static boolean fullyPassable(int x, int y, int z) {
return fullyPassable(BlockStateInterface.get(x, y, z));
}
static boolean fullyPassable(IBlockState state) {
Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case
@ -463,48 +465,4 @@ public interface MovementHelper extends ActionCosts, Helper {
false
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
}
static Movement generateMovementFallOrDescend(BetterBlockPos pos, BetterBlockPos dest, CalculationContext calcContext) {
int x = dest.x;
int y = dest.y;
int z = dest.z;
if (!canWalkThrough(x, y - 2, z)) {
//if B in the diagram aren't air
//have to do a descend, because fall is impossible
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
// we can't cost shortcut descend because !canWalkThrough doesn't mean canWalkOn
}
// we're clear for a fall 2
// let's see how far we can fall
for (int fallHeight = 3; true; fallHeight++) {
int newY = y - fallHeight;
if (newY < 0) {
// when pathing in the end, where you could plausibly fall into the void
// this check prevents it from getting the block at y=-1 and crashing
break;
}
IBlockState ontoBlock = BlockStateInterface.get(x, newY, z);
if (ontoBlock.getBlock() == Blocks.WATER) {
return new MovementFall(pos, new BetterBlockPos(x, newY, z));
}
if (canWalkThrough(x, newY, z, ontoBlock)) {
continue;
}
if (!canWalkOn(x, newY, z, ontoBlock)) {
break;
}
if ((calcContext.hasWaterBucket() && fallHeight <= calcContext.maxFallHeightBucket() + 1) || fallHeight <= calcContext.maxFallHeightNoWater() + 1) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
return new MovementFall(pos, new BetterBlockPos(x, newY + 1, z));
} else {
return null;
}
}
return null;
}
}

View File

@ -27,19 +27,20 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
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.EnumFacing;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.Objects;
public class MovementParkour extends Movement {
private static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN_SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
private static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{};
private static final Tuple<Tuple<Integer, Integer>, Double> IMPOSSIBLE = new Tuple<>(new Tuple<>(0, 0), COST_INF);
private final EnumFacing direction;
private final int dist;
@ -48,79 +49,81 @@ public class MovementParkour extends Movement {
super(src, src.offset(dir, dist), EMPTY);
this.direction = dir;
this.dist = dist;
super.override(costFromJumpDistance(dist));
}
public static MovementParkour generate(BetterBlockPos src, EnumFacing dir, CalculationContext context) {
// MUST BE KEPT IN SYNC WITH calculateCost
public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) {
Tuple<Tuple<Integer, Integer>, Double> res = cost(context, src.x, src.y, src.z, direction);
int dist = Math.abs(res.getFirst().getFirst() - src.x) + Math.abs(res.getFirst().getSecond() - src.z);
return new MovementParkour(src, dist, direction);
}
public static Tuple<Tuple<Integer, Integer>, Double> cost(CalculationContext context, int x, int y, int z, EnumFacing dir) {
if (!Baritone.settings().allowParkour.get()) {
return null;
return IMPOSSIBLE;
}
IBlockState standingOn = BlockStateInterface.get(src.down());
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z);
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
return null;
return IMPOSSIBLE;
}
BetterBlockPos adjBlock = src.down().offset(dir);
IBlockState adj = BlockStateInterface.get(adjBlock);
int xDiff = dir.getXOffset();
int zDiff = dir.getZOffset();
IBlockState adj = BlockStateInterface.get(x + xDiff, y - 1, z + zDiff);
if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks
return null;
return IMPOSSIBLE;
}
if (MovementHelper.canWalkOn(adjBlock, adj)) { // don't parkour if we could just traverse (for now)
return null;
if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
return IMPOSSIBLE;
}
if (!MovementHelper.fullyPassable(src.offset(dir))) {
return null;
if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) {
return IMPOSSIBLE;
}
if (!MovementHelper.fullyPassable(src.up().offset(dir))) {
return null;
if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) {
return IMPOSSIBLE;
}
if (!MovementHelper.fullyPassable(src.up(2).offset(dir))) {
return null;
if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) {
return IMPOSSIBLE;
}
if (!MovementHelper.fullyPassable(src.up(2))) {
return null;
if (!MovementHelper.fullyPassable(x, y + 2, z)) {
return IMPOSSIBLE;
}
for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) {
BetterBlockPos dest = src.offset(dir, i);
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
for (int y = 0; y < 4; y++) {
if (!MovementHelper.fullyPassable(dest.up(y))) {
return null;
for (int y2 = 0; y2 < 4; y2++) {
if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) {
return IMPOSSIBLE;
}
}
if (MovementHelper.canWalkOn(dest.down())) {
return new MovementParkour(src, i, dir);
if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) {
return new Tuple<>(new Tuple<>(x + xDiff * i, z + zDiff * i), costFromJumpDistance(i));
}
}
if (!context.canSprint()) {
return null;
return IMPOSSIBLE;
}
if (!Baritone.settings().allowParkourPlace.get()) {
return null;
return IMPOSSIBLE;
}
BlockPos dest = src.offset(dir, 4);
BlockPos positionToPlace = dest.down();
IBlockState toPlace = BlockStateInterface.get(positionToPlace);
int destX = x + 4 * xDiff;
int destZ = z + 4 * zDiff;
IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ);
if (!context.hasThrowaway()) {
return null;
return IMPOSSIBLE;
}
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) {
return null;
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
return IMPOSSIBLE;
}
for (int i = 0; i < 5; i++) {
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN_SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (against1.up().equals(src.offset(dir, 3))) { // we can't turn around that fast
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
continue;
}
if (MovementHelper.canPlaceAgainst(against1)) {
// holy jesus we gonna do it
MovementParkour ret = new MovementParkour(src, 4, dir);
ret.override(costFromJumpDistance(4) + context.placeBlockCost());
return ret;
if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) {
return new Tuple<>(new Tuple<>(destX, destZ), costFromJumpDistance(i) + context.placeBlockCost());
}
}
return null;
return IMPOSSIBLE;
}
private static double costFromJumpDistance(int dist) {
@ -139,54 +142,11 @@ public class MovementParkour extends Movement {
@Override
protected double calculateCost(CalculationContext context) {
// MUST BE KEPT IN SYNC WITH generate
if (!context.canSprint() && dist >= 4) {
Tuple<Tuple<Integer, Integer>, Double> res = cost(context, src.x, src.y, src.z, direction);
if (res.getFirst().getFirst() != dest.x || res.getFirst().getSecond() != dest.z) {
return COST_INF;
}
boolean placing = false;
if (!MovementHelper.canWalkOn(dest.down())) {
if (dist != 4) {
return COST_INF;
}
if (!Baritone.settings().allowParkourPlace.get()) {
return COST_INF;
}
BlockPos positionToPlace = dest.down();
IBlockState toPlace = BlockStateInterface.get(positionToPlace);
if (!context.hasThrowaway()) {
return COST_INF;
}
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) {
return COST_INF;
}
for (int i = 0; i < 5; i++) {
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN_SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (against1.up().equals(src.offset(direction, 3))) { // we can't turn around that fast
continue;
}
if (MovementHelper.canPlaceAgainst(against1)) {
// holy jesus we gonna do it
placing = true;
break;
}
}
}
Block walkOff = BlockStateInterface.get(src.down().offset(direction)).getBlock();
if (MovementHelper.avoidWalkingInto(walkOff) && walkOff != Blocks.WATER && walkOff != Blocks.FLOWING_WATER) {
return COST_INF;
}
for (int i = 1; i <= 4; i++) {
BlockPos d = src.offset(direction, i);
for (int y = 0; y < (i == 1 ? 3 : 4); y++) {
if (!MovementHelper.fullyPassable(d.up(y))) {
return COST_INF;
}
}
if (d.equals(dest)) {
return costFromJumpDistance(i) + (placing ? context.placeBlockCost() : 0);
}
}
throw new IllegalStateException("invalid jump distance?");
return res.getSecond();
}
@Override
@ -209,7 +169,7 @@ public class MovementParkour extends Movement {
if (!MovementHelper.canWalkOn(dest.down())) {
BlockPos positionToPlace = dest.down();
for (int i = 0; i < 5; i++) {
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN_SO_EVERY_DIRECTION_EXCEPT_UP[i]);
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (against1.up().equals(src.offset(direction, 3))) { // we can't turn around that fast
continue;
}

View File

@ -83,7 +83,7 @@ public class OpenSetsTest {
assertTrue(set.isEmpty());
}
// generate the pathnodes that we'll be testing the sets on
// cost the pathnodes that we'll be testing the sets on
PathNode[] toInsert = new PathNode[size];
for (int i = 0; i < size; i++) {
// can't use an existing goal