use mutable move result to avoid instantianing ten million move result objects

This commit is contained in:
Leijurv 2018-10-05 12:24:52 -07:00
parent 6fff4c5254
commit cb589219d8
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
7 changed files with 144 additions and 108 deletions

View File

@ -26,7 +26,7 @@ import baritone.pathing.movement.Moves;
import baritone.pathing.path.IPath; import baritone.pathing.path.IPath;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.pathing.MoveResult; import baritone.utils.pathing.MutableMoveResult;
import java.util.HashSet; import java.util.HashSet;
import java.util.Optional; import java.util.Optional;
@ -60,6 +60,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
bestSoFar[i] = startNode; bestSoFar[i] = startNode;
} }
CalculationContext calcContext = new CalculationContext(); CalculationContext calcContext = new CalculationContext();
MutableMoveResult res = new MutableMoveResult();
HashSet<Long> favored = favoredPositions.orElse(null); HashSet<Long> favored = favoredPositions.orElse(null);
BlockStateInterface.clearCachedChunk(); BlockStateInterface.clearCachedChunk();
long startTime = System.nanoTime() / 1000000L; long startTime = System.nanoTime() / 1000000L;
@ -104,28 +105,29 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
continue; continue;
} }
} }
MoveResult res = moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z); res.reset();
moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res);
numMovementsConsidered++; numMovementsConsidered++;
double actionCost = res.cost; double actionCost = res.cost;
if (actionCost >= ActionCosts.COST_INF) { if (actionCost >= ActionCosts.COST_INF) {
continue; continue;
} }
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation // check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
if (!moves.dynamicXZ && (res.destX != newX || res.destZ != newZ)) { if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
throw new IllegalStateException(moves + " " + res.destX + " " + newX + " " + res.destZ + " " + newZ); throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
} }
if (!moves.dynamicY && res.destY != currentNode.y + moves.yOffset) { if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
throw new IllegalStateException(moves + " " + res.destX + " " + newX + " " + res.destZ + " " + newZ); throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
} }
if (actionCost <= 0) { if (actionCost <= 0) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
} }
long hashCode = posHash(res.destX, res.destY, res.destZ); long hashCode = posHash(res.x, res.y, res.z);
if (favoring && favored.contains(hashCode)) { if (favoring && favored.contains(hashCode)) {
// see issue #18 // see issue #18
actionCost *= favorCoeff; actionCost *= favorCoeff;
} }
PathNode neighbor = getNodeAtPosition(res.destX, res.destY, res.destZ, hashCode); PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost; double tentativeCost = currentNode.cost + actionCost;
if (tentativeCost < neighbor.cost) { if (tentativeCost < neighbor.cost) {
if (tentativeCost < 0) { if (tentativeCost < 0) {

View File

@ -139,6 +139,7 @@ class Path implements IPath {
for (Moves moves : Moves.values()) { for (Moves moves : Moves.values()) {
Movement move = moves.apply0(src); Movement move = moves.apply0(src);
if (move.getDest().equals(dest)) { if (move.getDest().equals(dest)) {
move.recalculateCost(); // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
return move; return move;
} }
} }

View File

@ -19,7 +19,7 @@ package baritone.pathing.movement;
import baritone.pathing.movement.movements.*; import baritone.pathing.movement.movements.*;
import baritone.utils.pathing.BetterBlockPos; import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
/** /**
@ -151,68 +151,72 @@ public enum Moves {
DESCEND_EAST(+1, 0, 0, false, true) { DESCEND_EAST(+1, 0, 0, false, true) {
@Override @Override
public Movement apply0(BetterBlockPos src) { public Movement apply0(BetterBlockPos src) {
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); MutableMoveResult res = new MutableMoveResult();
if (res.destY == src.y - 1) { apply(new CalculationContext(), src.x, src.y, src.z, res);
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); if (res.y == src.y - 1) {
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
} else { } else {
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
} }
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementDescend.cost(context, x, y, z, x + 1, z); MovementDescend.cost(context, x, y, z, x + 1, z, result);
} }
}, },
DESCEND_WEST(-1, 0, 0, false, true) { DESCEND_WEST(-1, 0, 0, false, true) {
@Override @Override
public Movement apply0(BetterBlockPos src) { public Movement apply0(BetterBlockPos src) {
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); MutableMoveResult res = new MutableMoveResult();
if (res.destY == src.y - 1) { apply(new CalculationContext(), src.x, src.y, src.z, res);
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); if (res.y == src.y - 1) {
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
} else { } else {
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
} }
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementDescend.cost(context, x, y, z, x - 1, z); MovementDescend.cost(context, x, y, z, x - 1, z, result);
} }
}, },
DESCEND_NORTH(0, 0, -1, false, true) { DESCEND_NORTH(0, 0, -1, false, true) {
@Override @Override
public Movement apply0(BetterBlockPos src) { public Movement apply0(BetterBlockPos src) {
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); MutableMoveResult res = new MutableMoveResult();
if (res.destY == src.y - 1) { apply(new CalculationContext(), src.x, src.y, src.z, res);
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); if (res.y == src.y - 1) {
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
} else { } else {
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
} }
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementDescend.cost(context, x, y, z, x, z - 1); MovementDescend.cost(context, x, y, z, x, z - 1, result);
} }
}, },
DESCEND_SOUTH(0, 0, +1, false, true) { DESCEND_SOUTH(0, 0, +1, false, true) {
@Override @Override
public Movement apply0(BetterBlockPos src) { public Movement apply0(BetterBlockPos src) {
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z); MutableMoveResult res = new MutableMoveResult();
if (res.destY == src.y - 1) { apply(new CalculationContext(), src.x, src.y, src.z, res);
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); if (res.y == src.y - 1) {
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
} else { } else {
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ)); return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
} }
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementDescend.cost(context, x, y, z, x, z + 1); MovementDescend.cost(context, x, y, z, x, z + 1, result);
} }
}, },
@ -271,8 +275,8 @@ public enum Moves {
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementParkour.cost(context, x, y, z, EnumFacing.NORTH); MovementParkour.cost(context, x, y, z, EnumFacing.NORTH, result);
} }
}, },
@ -283,8 +287,8 @@ public enum Moves {
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH); MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH, result);
} }
}, },
@ -295,8 +299,8 @@ public enum Moves {
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementParkour.cost(context, x, y, z, EnumFacing.EAST); MovementParkour.cost(context, x, y, z, EnumFacing.EAST, result);
} }
}, },
@ -307,8 +311,8 @@ public enum Moves {
} }
@Override @Override
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
return MovementParkour.cost(context, x, y, z, EnumFacing.WEST); MovementParkour.cost(context, x, y, z, EnumFacing.WEST, result);
} }
}; };
@ -333,11 +337,14 @@ public enum Moves {
public abstract Movement apply0(BetterBlockPos src); public abstract Movement apply0(BetterBlockPos src);
public MoveResult apply(CalculationContext context, int x, int y, int z) { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
if (dynamicXZ || dynamicY) { if (dynamicXZ || dynamicY) {
throw new UnsupportedOperationException(); throw new UnsupportedOperationException();
} }
return new MoveResult(x + xOffset, y + yOffset, z + zOffset, cost(context, x, y, z)); result.x = x + xOffset;
result.y = y + yOffset;
result.z = z + zOffset;
result.cost = cost(context, x, y, z);
} }
public double cost(CalculationContext context, int x, int y, int z) { public double cost(CalculationContext context, int x, int y, int z) {

View File

@ -26,15 +26,13 @@ import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.BetterBlockPos; import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling; import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import static baritone.utils.pathing.MoveResult.IMPOSSIBLE;
public class MovementDescend extends Movement { public class MovementDescend extends Movement {
private int numTicks = 0; private int numTicks = 0;
@ -51,32 +49,33 @@ public class MovementDescend extends Movement {
@Override @Override
protected double calculateCost(CalculationContext context) { protected double calculateCost(CalculationContext context) {
MoveResult result = cost(context, src.x, src.y, src.z, dest.x, dest.z); MutableMoveResult result = new MutableMoveResult();
if (result.destY != dest.y) { cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) {
return COST_INF; // doesn't apply to us, this position is a fall not a descend return COST_INF; // doesn't apply to us, this position is a fall not a descend
} }
return result.cost; return result.cost;
} }
public static MoveResult cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock(); Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) { if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
return IMPOSSIBLE; return;
} }
double totalCost = 0; double totalCost = 0;
IBlockState destDown = BlockStateInterface.get(destX, y - 1, destZ); IBlockState destDown = BlockStateInterface.get(destX, y - 1, destZ);
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, destDown, false); totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, destDown, false);
if (totalCost >= COST_INF) { if (totalCost >= COST_INF) {
return IMPOSSIBLE; return;
} }
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y, destZ, false); totalCost += MovementHelper.getMiningDurationTicks(context, destX, y, destZ, false);
if (totalCost >= COST_INF) { if (totalCost >= COST_INF) {
return IMPOSSIBLE; return;
} }
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, true); // only the top block in the 3 we need to mine needs to consider the falling blocks above totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, true); // only the top block in the 3 we need to mine needs to consider the falling blocks above
if (totalCost >= COST_INF) { if (totalCost >= COST_INF) {
return IMPOSSIBLE; return;
} }
// A // A
@ -91,11 +90,12 @@ public class MovementDescend extends Movement {
IBlockState below = BlockStateInterface.get(destX, y - 2, destZ); IBlockState below = BlockStateInterface.get(destX, y - 2, destZ);
if (!MovementHelper.canWalkOn(destX, y - 2, destZ, below)) { if (!MovementHelper.canWalkOn(destX, y - 2, destZ, below)) {
return dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below); dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
return;
} }
if (destDown.getBlock() == Blocks.LADDER || destDown.getBlock() == Blocks.VINE) { if (destDown.getBlock() == Blocks.LADDER || destDown.getBlock() == Blocks.VINE) {
return IMPOSSIBLE; return;
} }
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel) // we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
@ -105,25 +105,28 @@ public class MovementDescend extends Movement {
walk = WALK_ONE_OVER_SOUL_SAND_COST; walk = WALK_ONE_OVER_SOUL_SAND_COST;
} }
totalCost += walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST); totalCost += walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST);
return new MoveResult(destX, y - 1, destZ, totalCost); res.x = destX;
res.y = y - 1;
res.z = destZ;
res.cost = totalCost;
} }
public static MoveResult dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below) { public static void dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below, MutableMoveResult res) {
if (frontBreak != 0 && BlockStateInterface.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) { if (frontBreak != 0 && BlockStateInterface.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) {
// if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall // if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall
// but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column, // but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column,
// and potentially replace the water we're going to fall into // and potentially replace the water we're going to fall into
return IMPOSSIBLE; return;
} }
if (!MovementHelper.canWalkThrough(destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) { if (!MovementHelper.canWalkThrough(destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
return IMPOSSIBLE; return;
} }
for (int fallHeight = 3; true; fallHeight++) { for (int fallHeight = 3; true; fallHeight++) {
int newY = y - fallHeight; int newY = y - fallHeight;
if (newY < 0) { if (newY < 0) {
// when pathing in the end, where you could plausibly fall into the void // 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 // this check prevents it from getting the block at y=-1 and crashing
return IMPOSSIBLE; return;
} }
IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ); IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ);
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak; double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak;
@ -131,31 +134,43 @@ public class MovementDescend extends Movement {
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad // lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works) // however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
if (Baritone.settings().assumeWalkOnWater.get()) { if (Baritone.settings().assumeWalkOnWater.get()) {
return IMPOSSIBLE; // TODO fix return; // TODO fix
} }
// found a fall into water // found a fall into water
return new MoveResult(destX, newY, destZ, tentativeCost); // TODO incorporate water swim up cost? res.x = destX;
res.y = newY;
res.z = destZ;
res.cost = tentativeCost;// TODO incorporate water swim up cost?
return;
} }
if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) { if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) {
return IMPOSSIBLE; return;
} }
if (MovementHelper.canWalkThrough(destX, newY, destZ, ontoBlock)) { if (MovementHelper.canWalkThrough(destX, newY, destZ, ontoBlock)) {
continue; continue;
} }
if (!MovementHelper.canWalkOn(destX, newY, destZ, ontoBlock)) { if (!MovementHelper.canWalkOn(destX, newY, destZ, ontoBlock)) {
return IMPOSSIBLE; return;
} }
if (MovementHelper.isBottomSlab(ontoBlock)) { if (MovementHelper.isBottomSlab(ontoBlock)) {
return IMPOSSIBLE; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect return; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
} }
if (context.hasWaterBucket() && fallHeight <= context.maxFallHeightBucket() + 1) { if (context.hasWaterBucket() && fallHeight <= context.maxFallHeightBucket() + 1) {
return new MoveResult(destX, newY + 1, destZ, tentativeCost + context.placeBlockCost()); // this is the block we're falling onto, so dest is +1 res.x = destX;
res.y = newY + 1;// this is the block we're falling onto, so dest is +1
res.z = destZ;
res.cost = tentativeCost + context.placeBlockCost();
return;
} }
if (fallHeight <= context.maxFallHeightNoWater() + 1) { if (fallHeight <= context.maxFallHeightNoWater() + 1) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max // fallHeight = 4 means onto.up() is 3 blocks down, which is the max
return new MoveResult(destX, newY + 1, destZ, tentativeCost); res.x = destX;
res.y = newY + 1;
res.z = destZ;
res.cost = tentativeCost;
return;
} else { } else {
return IMPOSSIBLE; return;
} }
} }
} }

View File

@ -30,7 +30,7 @@ import baritone.utils.InputOverrideHandler;
import baritone.utils.RayTraceUtils; import baritone.utils.RayTraceUtils;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos; import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@ -49,8 +49,9 @@ public class MovementFall extends Movement {
@Override @Override
protected double calculateCost(CalculationContext context) { protected double calculateCost(CalculationContext context) {
MoveResult result = MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z); MutableMoveResult result = new MutableMoveResult();
if (result.destY != dest.y) { MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) {
return COST_INF; // doesn't apply to us, this position is a descend not a fall return COST_INF; // doesn't apply to us, this position is a descend not a fall
} }
return result.cost; return result.cost;

View File

@ -28,7 +28,7 @@ import baritone.utils.Helper;
import baritone.utils.InputOverrideHandler; import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils; import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos; import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -39,8 +39,6 @@ import net.minecraft.util.math.Vec3d;
import java.util.Objects; import java.util.Objects;
import static baritone.utils.pathing.MoveResult.IMPOSSIBLE;
public class MovementParkour extends Movement { 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};
@ -56,70 +54,75 @@ public class MovementParkour extends Movement {
} }
public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) { public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) {
MoveResult res = cost(context, src.x, src.y, src.z, direction); MutableMoveResult res = new MutableMoveResult();
int dist = Math.abs(res.destX - src.x) + Math.abs(res.destZ - src.z); 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(src, dist, direction); return new MovementParkour(src, dist, direction);
} }
public static MoveResult cost(CalculationContext context, int x, int y, int z, EnumFacing dir) { public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
if (!Baritone.settings().allowParkour.get()) { if (!Baritone.settings().allowParkour.get()) {
return IMPOSSIBLE; return;
} }
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z); IBlockState standingOn = BlockStateInterface.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 || MovementHelper.isBottomSlab(standingOn)) {
return IMPOSSIBLE; return;
} }
int xDiff = dir.getXOffset(); int xDiff = dir.getXOffset();
int zDiff = dir.getZOffset(); int zDiff = dir.getZOffset();
IBlockState adj = BlockStateInterface.get(x + xDiff, y - 1, z + zDiff); 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 if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks
return IMPOSSIBLE; return;
} }
if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
return IMPOSSIBLE; return;
} }
if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) { if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) {
return IMPOSSIBLE; return;
} }
if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) { if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) {
return IMPOSSIBLE; return;
} }
if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) { if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) {
return IMPOSSIBLE; return;
} }
if (!MovementHelper.fullyPassable(x, y + 2, z)) { if (!MovementHelper.fullyPassable(x, y + 2, z)) {
return IMPOSSIBLE; return;
} }
for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) { for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) {
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly? // TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
for (int y2 = 0; y2 < 4; y2++) { for (int y2 = 0; y2 < 4; y2++) {
if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) { if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) {
return IMPOSSIBLE; return;
} }
} }
if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) { if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) {
return new MoveResult(x + xDiff * i, y, z + zDiff * i, costFromJumpDistance(i)); res.x = x + xDiff * i;
res.y = y;
res.z = z + zDiff * i;
res.cost = costFromJumpDistance(i);
return;
} }
} }
if (!context.canSprint()) { if (!context.canSprint()) {
return IMPOSSIBLE; return;
} }
if (!Baritone.settings().allowParkourPlace.get()) { if (!Baritone.settings().allowParkourPlace.get()) {
return IMPOSSIBLE; return;
} }
if (!Baritone.settings().allowPlace.get()) { if (!Baritone.settings().allowPlace.get()) {
Helper.HELPER.logDirect("allowParkourPlace enabled but allowPlace disabled?"); Helper.HELPER.logDirect("allowParkourPlace enabled but allowPlace disabled?");
return IMPOSSIBLE; return;
} }
int destX = x + 4 * xDiff; int destX = x + 4 * xDiff;
int destZ = z + 4 * zDiff; int destZ = z + 4 * zDiff;
IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ); IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ);
if (!context.hasThrowaway()) { if (!context.hasThrowaway()) {
return IMPOSSIBLE; return;
} }
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) { if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
return IMPOSSIBLE; return;
} }
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset(); int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
@ -128,10 +131,13 @@ public class MovementParkour extends Movement {
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) { if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) {
return new MoveResult(destX, y, destZ, costFromJumpDistance(4) + context.placeBlockCost()); res.x = destX;
res.y = y;
res.z = destZ;
res.cost = costFromJumpDistance(4) + context.placeBlockCost();
return;
} }
} }
return IMPOSSIBLE;
} }
private static double costFromJumpDistance(int dist) { private static double costFromJumpDistance(int dist) {
@ -150,8 +156,9 @@ public class MovementParkour extends Movement {
@Override @Override
protected double calculateCost(CalculationContext context) { protected double calculateCost(CalculationContext context) {
MoveResult res = cost(context, src.x, src.y, src.z, direction); MutableMoveResult res = new MutableMoveResult();
if (res.destX != dest.x || res.destZ != dest.z) { cost(context, src.x, src.y, src.z, direction, res);
if (res.x != dest.x || res.z != dest.z) {
return COST_INF; return COST_INF;
} }
return res.cost; return res.cost;

View File

@ -17,24 +17,27 @@
package baritone.utils.pathing; package baritone.utils.pathing;
import static baritone.api.pathing.movement.ActionCosts.COST_INF; import baritone.api.pathing.movement.ActionCosts;
/** /**
* The result of a calculated movement, with destination x, y, z, and the cost of performing the movement * The result of a calculated movement, with destination x, y, z, and the cost of performing the movement
* *
* @author leijurv * @author leijurv
*/ */
public final class MoveResult { public final class MutableMoveResult {
public static final MoveResult IMPOSSIBLE = new MoveResult(0, 0, 0, COST_INF); public int x;
public final int destX; public int y;
public final int destY; public int z;
public final int destZ; public double cost;
public final double cost;
public MoveResult(int x, int y, int z, double cost) { public MutableMoveResult() {
this.destX = x; reset();
this.destY = y; }
this.destZ = z;
this.cost = cost; public final void reset() {
x = 0;
y = 0;
z = 0;
cost = ActionCosts.COST_INF;
} }
} }