cool vine and ladder descending, fixes #159
This commit is contained in:
		| @@ -121,7 +121,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel | ||||
|                 if (actionCost >= ActionCosts.COST_INF) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 if (actionCost <= 0) { | ||||
|                 if (actionCost <= 0 || Double.isNaN(actionCost)) { | ||||
|                     throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); | ||||
|                 } | ||||
|                 if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218 | ||||
|   | ||||
| @@ -73,6 +73,9 @@ public final class PathNode { | ||||
|         this.previous = null; | ||||
|         this.cost = ActionCosts.COST_INF; | ||||
|         this.estimatedCostToGoal = goal.heuristic(x, y, z); | ||||
|         if (Double.isNaN(estimatedCostToGoal)) { | ||||
|             throw new IllegalStateException(goal + " calculated implausible heuristic"); | ||||
|         } | ||||
|         this.isOpen = false; | ||||
|         this.x = x; | ||||
|         this.y = y; | ||||
|   | ||||
| @@ -115,66 +115,84 @@ public class MovementDescend extends Movement { | ||||
|         res.cost = totalCost; | ||||
|     } | ||||
|  | ||||
|     public static void dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below, MutableMoveResult res) { | ||||
|     public static boolean dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below, MutableMoveResult res) { | ||||
|         if (frontBreak != 0 && context.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 | ||||
|             // 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 | ||||
|             return; | ||||
|             return false; | ||||
|         } | ||||
|         if (!MovementHelper.canWalkThrough(context.bsi(), destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) { | ||||
|             return; | ||||
|             return false; | ||||
|         } | ||||
|         double costSoFar = 0; | ||||
|         int effectiveStartHeight = y; | ||||
|         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 | ||||
|                 return; | ||||
|                 return false; | ||||
|             } | ||||
|             IBlockState ontoBlock = context.get(destX, newY, destZ); | ||||
|             double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak; | ||||
|             if (ontoBlock.getBlock() == Blocks.WATER && !MovementHelper.isFlowing(ontoBlock) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here? | ||||
|             int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY | ||||
|             double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; | ||||
|             if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { | ||||
|                 // 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) | ||||
|                 if (context.assumeWalkOnWater()) { | ||||
|                     return; // TODO fix | ||||
|                     return false; // TODO fix | ||||
|                 } | ||||
|                 if (MovementHelper.isFlowing(ontoBlock)) { | ||||
|                     return false; // TODO flowing check required here? | ||||
|                 } | ||||
|                 if (!MovementHelper.canWalkOn(context.bsi(), destX, newY - 1, destZ)) { | ||||
|                     // we could punch right through the water into something else | ||||
|                     return false; | ||||
|                 } | ||||
|                 // found a fall into water | ||||
|                 res.x = destX; | ||||
|                 res.y = newY; | ||||
|                 res.z = destZ; | ||||
|                 res.cost = tentativeCost;// TODO incorporate water swim up cost? | ||||
|                 return; | ||||
|                 return false; | ||||
|             } | ||||
|             if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) { | ||||
|                 return; | ||||
|                 return false; | ||||
|             } | ||||
|             if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) { | ||||
|                 // if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know | ||||
|                 // this effectively "resets" our falling speed | ||||
|                 costSoFar += FALL_N_BLOCKS_COST[unprotectedFallHeight - 1];// we fall until the top of this block (not including this block) | ||||
|                 costSoFar += LADDER_DOWN_ONE_COST; | ||||
|                 effectiveStartHeight = newY; | ||||
|                 continue; | ||||
|             } | ||||
|             if (MovementHelper.canWalkThrough(context.bsi(), destX, newY, destZ, ontoBlock)) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (!MovementHelper.canWalkOn(context.bsi(), destX, newY, destZ, ontoBlock)) { | ||||
|                 return; | ||||
|                 return false; | ||||
|             } | ||||
|             if (MovementHelper.isBottomSlab(ontoBlock)) { | ||||
|                 return; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect | ||||
|                 return false; // 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() && unprotectedFallHeight <= context.maxFallHeightBucket() + 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; | ||||
|                 return true; | ||||
|             } | ||||
|             if (fallHeight <= context.maxFallHeightNoWater() + 1) { | ||||
|             if (unprotectedFallHeight <= context.maxFallHeightNoWater() + 1) { | ||||
|                 // fallHeight = 4 means onto.up() is 3 blocks down, which is the max | ||||
|                 res.x = destX; | ||||
|                 res.y = newY + 1; | ||||
|                 res.z = destZ; | ||||
|                 res.cost = tentativeCost; | ||||
|                 return; | ||||
|                 return false; | ||||
|             } else { | ||||
|                 return; | ||||
|                 return false; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|   | ||||
| @@ -17,7 +17,6 @@ | ||||
|  | ||||
| package baritone.pathing.movement.movements; | ||||
|  | ||||
| import baritone.Baritone; | ||||
| import baritone.api.IBaritone; | ||||
| import baritone.api.pathing.movement.MovementStatus; | ||||
| import baritone.api.utils.BetterBlockPos; | ||||
| @@ -31,12 +30,19 @@ import baritone.pathing.movement.MovementHelper; | ||||
| import baritone.pathing.movement.MovementState; | ||||
| import baritone.pathing.movement.MovementState.MovementTarget; | ||||
| import baritone.utils.pathing.MutableMoveResult; | ||||
| import net.minecraft.block.BlockLadder; | ||||
| import net.minecraft.block.state.IBlockState; | ||||
| import net.minecraft.entity.player.InventoryPlayer; | ||||
| import net.minecraft.init.Blocks; | ||||
| import net.minecraft.init.Items; | ||||
| import net.minecraft.item.ItemStack; | ||||
| import net.minecraft.util.EnumFacing; | ||||
| import net.minecraft.util.math.BlockPos; | ||||
| import net.minecraft.util.math.RayTraceResult; | ||||
| import net.minecraft.util.math.Vec3d; | ||||
| import net.minecraft.util.math.Vec3i; | ||||
|  | ||||
| import java.util.Optional; | ||||
|  | ||||
| public class MovementFall extends Movement { | ||||
|  | ||||
| @@ -57,6 +63,12 @@ public class MovementFall extends Movement { | ||||
|         return result.cost; | ||||
|     } | ||||
|  | ||||
|     private boolean willPlaceBucket() { | ||||
|         CalculationContext context = new CalculationContext(baritone); | ||||
|         MutableMoveResult result = new MutableMoveResult(); | ||||
|         return MovementDescend.dynamicFallCost(context, src.x, src.y, src.z, dest.x, dest.z, 0, context.get(dest.x, src.y - 2, dest.z), result); | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public MovementState updateState(MovementState state) { | ||||
|         super.updateState(state); | ||||
| @@ -67,7 +79,7 @@ public class MovementFall extends Movement { | ||||
|         BlockPos playerFeet = ctx.playerFeet(); | ||||
|         Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)); | ||||
|         Rotation targetRotation = null; | ||||
|         if (!MovementHelper.isWater(ctx, dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) { | ||||
|         if (!MovementHelper.isWater(ctx, dest) && willPlaceBucket() && !playerFeet.equals(dest)) { | ||||
|             if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) { | ||||
|                 return state.setStatus(MovementStatus.UNREACHABLE); | ||||
|             } | ||||
| @@ -78,7 +90,7 @@ public class MovementFall extends Movement { | ||||
|                 targetRotation = new Rotation(toDest.getYaw(), 90.0F); | ||||
|  | ||||
|                 RayTraceResult trace = ctx.objectMouseOver(); | ||||
|                 if (trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK && ctx.player().rotationPitch > 89.0F) { | ||||
|                 if (trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK && (trace.getBlockPos().equals(dest) || trace.getBlockPos().equals(dest.down()))) { | ||||
|                     state.setInput(Input.CLICK_RIGHT, true); | ||||
|                 } | ||||
|             } | ||||
| @@ -107,12 +119,40 @@ public class MovementFall extends Movement { | ||||
|             } | ||||
|         } | ||||
|         Vec3d destCenter = VecUtils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder) | ||||
|         if (Math.abs(ctx.player().posX - destCenter.x) > 0.15 || Math.abs(ctx.player().posZ - destCenter.z) > 0.15) { | ||||
|         if (Math.abs(ctx.player().posX + ctx.player().motionX - destCenter.x) > 0.1 || Math.abs(ctx.player().posZ + ctx.player().motionZ - destCenter.z) > 0.1) { | ||||
|             if (!ctx.player().onGround && Math.abs(ctx.player().motionY) > 0.4) { | ||||
|                 state.setInput(Input.SNEAK, true); | ||||
|             } | ||||
|             state.setInput(Input.MOVE_FORWARD, true); | ||||
|         } | ||||
|         Vec3i avoid = Optional.ofNullable(avoid()).map(EnumFacing::getDirectionVec).orElse(null); | ||||
|         if (avoid == null) { | ||||
|             avoid = src.subtract(dest); | ||||
|         } else { | ||||
|             double dist = Math.abs(avoid.getX() * (destCenter.x - avoid.getX() / 2.0 - ctx.player().posX)) + Math.abs(avoid.getZ() * (destCenter.z - avoid.getZ() / 2.0 - ctx.player().posZ)); | ||||
|             if (dist < 0.6) { | ||||
|                 state.setInput(Input.MOVE_FORWARD, true); | ||||
|             } else { | ||||
|                 state.setInput(Input.SNEAK, false); | ||||
|             } | ||||
|         } | ||||
|         if (targetRotation == null) { | ||||
|             Vec3d destCenterOffset = new Vec3d(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ()); | ||||
|             state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset), false)); | ||||
|         } | ||||
|         return state; | ||||
|     } | ||||
|  | ||||
|     private EnumFacing avoid() { | ||||
|         for (int i = 0; i < 15; i++) { | ||||
|             IBlockState state = ctx.world().getBlockState(ctx.playerFeet().down(i)); | ||||
|             if (state.getBlock() == Blocks.LADDER) { | ||||
|                 return state.getValue(BlockLadder.FACING); | ||||
|             } | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     @Override | ||||
|     public boolean safeToCancel(MovementState state) { | ||||
|         // if we haven't started walking off the edge yet, or if we're in the process of breaking blocks before doing the fall | ||||
|   | ||||
		Reference in New Issue
	
	Block a user