From 83066fc57c1173aa6595375578751410fcc2cdcb Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 30 Jun 2023 20:42:03 -0500 Subject: [PATCH] Find jump off spot using INSANE custom CalculationContext --- .../api/process/PathingCommandType.java | 7 +- .../baritone/behavior/ElytraBehavior.java | 175 +++++++++--------- .../baritone/behavior/PathingBehavior.java | 2 +- .../pathing/movement/CalculationContext.java | 4 +- .../movement/movements/MovementDescend.java | 8 + .../baritone/utils/InputOverrideHandler.java | 2 +- .../java/baritone/utils/PathRenderer.java | 4 +- .../baritone/utils/PathingControlManager.java | 4 +- 8 files changed, 117 insertions(+), 89 deletions(-) diff --git a/src/api/java/baritone/api/process/PathingCommandType.java b/src/api/java/baritone/api/process/PathingCommandType.java index af25591af..cde38eaf2 100644 --- a/src/api/java/baritone/api/process/PathingCommandType.java +++ b/src/api/java/baritone/api/process/PathingCommandType.java @@ -56,5 +56,10 @@ public enum PathingCommandType { /** * Go and ask the next process what to do */ - DEFER + DEFER, + + /** + * Sets the goal and calculates a path, but pauses instead of immediately starting the path. + */ + SET_GOAL_AND_PAUSE } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3fbe06e44..c31624435 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -18,24 +18,28 @@ package baritone.behavior; import baritone.Baritone; +import baritone.api.IBaritone; import baritone.api.behavior.IElytraBehavior; import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.event.events.*; import baritone.api.pathing.goals.Goal; -import baritone.api.pathing.goals.GoalGetToBlock; +import baritone.api.pathing.goals.GoalYLevel; +import baritone.api.pathing.movement.IMovement; +import baritone.api.pathing.path.IPathExecutor; import baritone.api.process.IBaritoneProcess; import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.*; import baritone.api.utils.input.Input; -import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.NetherPath; import baritone.behavior.elytra.PathCalculationException; import baritone.behavior.elytra.UnpackedSegment; -import baritone.cache.FasterWorldScanner; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.movements.MovementFall; import baritone.utils.BlockStateInterface; +import baritone.utils.PathingCommandContext; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; @@ -54,6 +58,8 @@ import java.util.*; import java.util.concurrent.*; import java.util.function.UnaryOperator; +import static baritone.api.pathing.movement.ActionCosts.COST_INF; + public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { /** @@ -106,7 +112,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.context = new NetherPathfinderContext(NETHER_SEED); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); - this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); this.process = new ElytraProcess(); this.solverExecutor = Executors.newSingleThreadExecutor(); @@ -395,9 +400,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void cancel() { this.destination = null; - this.visiblePath = Collections.emptyList(); this.pathManager.clear(); - this.aimPos = null; this.remainingFireworkTicks = 0; this.remainingSetBackTicks = 0; if (this.solver != null) { @@ -446,12 +449,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Reset rendered elements this.clearLines.clear(); this.blockedLines.clear(); + this.visiblePath = null; this.simulationLine = null; this.aimPos = null; final List path = this.pathManager.getPath(); if (path.isEmpty()) { return; + } else if (this.destination == null) { + this.pathManager.clear(); + return; } this.bsi = new BlockStateInterface(ctx); @@ -1190,43 +1197,67 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (!Baritone.settings().elytraAutoJump.value) { - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + if (this.state == State.FLYING || this.state == State.START_FLYING) { + this.state = ctx.player().onGround && Baritone.settings().elytraAutoJump.value + ? State.LOCATE_JUMP + : State.START_FLYING; } - // We were flying, but we're not anymore, reset the state - if (this.state == State.FLYING) { - this.state = State.GET_TO_JUMP; + if (this.state == State.LOCATE_JUMP) { + if (this.goal == null) { + this.goal = new GoalYLevel(31); + } + this.state = State.VALIDATE_PATH; + return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new WalkOffCalculationContext(baritone)); + } + + if (this.state == State.VALIDATE_PATH) { + final IPathExecutor executor = baritone.getPathingBehavior().getCurrent(); + if (executor != null && executor.getPath().getGoal() == this.goal) { + final IMovement fall = executor.getPath().movements().stream() + .filter(movement -> movement instanceof MovementFall) + .findFirst().orElse(null); + + if (fall != null) { + ElytraBehavior.this.pathManager.pathToDestination(fall.getSrc()); + this.state = State.WAIT_ELYTRA_PATH; + } else { + onLostControl(); + logDirect("Jump off path didn't include a fall movement, canceling"); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + } + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + + // yucky + if (this.state == State.WAIT_ELYTRA_PATH) { + if (!ElytraBehavior.this.pathManager.getPath().isEmpty()) { + this.state = State.GET_TO_JUMP; + } + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } if (this.state == State.GET_TO_JUMP) { - if (this.goal == null) { - final BlockPos jumpOff = this.findJumpOffSpot(); - if (jumpOff == null) { - onLostControl(); - logDirect("Couldn't find a suitable spot to jump off of, canceling"); - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); - } - this.goal = new GoalGetToBlock(jumpOff); - ElytraBehavior.this.pathManager.pathToDestination(jumpOff.add(0, -4, 0)); - } - if (this.goal.isInGoal(ctx.playerFeet())) { + final IPathExecutor executor = baritone.getPathingBehavior().getCurrent(); + final boolean canStartFlying = ctx.player().fallDistance > 1.0f + && !isSafeToCancel + && executor != null + && executor.getPath().movements().get(executor.getPosition()) instanceof MovementFall; + + if (canStartFlying) { this.state = State.START_FLYING; } else { - return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); + return new PathingCommand(null, PathingCommandType.SET_GOAL_AND_PATH); } } - if (this.state == State.START_FLYING && isSafeToCancel && !ElytraBehavior.this.pathManager.getPath().isEmpty()) { - baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d( - ctx.playerHead(), - VecUtils.getBlockPosCenter(((IGoalRenderPos) this.goal).getGoalPos()), - ctx.playerRotations() - ), false); - baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true); - if (ctx.player().fallDistance > 0.0f) { - baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); + if (this.state == State.START_FLYING) { + if (!isSafeToCancel) { + // owned + baritone.getPathingBehavior().secretInternalSegmentCancel(); } + baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); } return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } @@ -1239,7 +1270,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void onLostControl() { this.goal = null; - this.state = State.GET_TO_JUMP; + this.state = State.START_FLYING; ElytraBehavior.this.cancel(); } @@ -1252,64 +1283,42 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public String displayName0() { return "Elytra"; } + } - // ok... now this.. is disgusting - // TODO: make less scuffed - private BlockPos findJumpOffSpot() { - BlockPos best = null; - final BetterBlockPos feet = ctx.playerFeet(); - final List nearby = FasterWorldScanner.getChunkRange(feet.x >> 4, feet.z >> 4, 3); - for (ChunkPos pos : nearby) { - final Chunk chunk = ctx.world().getChunk(pos.x, pos.z); - int[][] obstruction = new int[16][16]; - for (int y0 = 0; y0 < 8; y0++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - int y = feet.y - y0; - if (chunk.getBlockState(x, y, z).getMaterial() != Material.AIR) { - if (obstruction[x][z] == 0 || obstruction[x][z] > y0 + 1) { - obstruction[x][z] = y0 + 1; - } - } - } - } - } - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - if (obstruction[x][z] != 0) { - continue; - } + /** + * Custom calculation context which makes the player fall into lava + */ + private static final class WalkOffCalculationContext extends CalculationContext { - final int[] adjacent = new int[4]; - if (x > 0) adjacent[0] = obstruction[x - 1][z]; - if (z > 0) adjacent[1] = obstruction[x][z - 1]; - if (x < 15) adjacent[2] = obstruction[x + 1][z]; - if (z < 15) adjacent[3] = obstruction[x][z + 1]; - final OptionalInt minLevel = Arrays.stream(adjacent).filter(i -> i != 0).min(); + public WalkOffCalculationContext(IBaritone baritone) { + super(baritone, true); + this.allowFallIntoLava = true; + this.maxFallHeightNoWater = 10000; + } - if (minLevel.isPresent() && minLevel.getAsInt() <= 4) { - final int yActual = feet.y - minLevel.getAsInt() + 2; // lol - // The target spot itself is clear - if (chunk.getBlockState(x, yActual, z).getMaterial() != Material.AIR - || chunk.getBlockState(x, yActual + 1, z).getMaterial() != Material.AIR) { - continue; - } - // lessgooo - final BlockPos target = new BlockPos(chunk.x << 4 | x, yActual, chunk.z << 4 | z); - if (best == null || target.distanceSq(feet) < best.distanceSq(feet)) { - best = target; - } - } - } - } - } - return best; + @Override + public double costOfPlacingAt(int x, int y, int z, IBlockState current) { + return COST_INF; + } + + @Override + public double breakCostMultiplierAt(int x, int y, int z, IBlockState current) { + return COST_INF; + } + + @Override + public double placeBucketCost() { + return COST_INF; } } private enum State { + LOCATE_JUMP, + VALIDATE_PATH, + WAIT_ELYTRA_PATH, GET_TO_JUMP, START_FLYING, - FLYING + FLYING, + RESTART_FLYING, } } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 31a884622..9b1bd9187 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -352,7 +352,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } // just cancel the current path - private void secretInternalSegmentCancel() { + public void secretInternalSegmentCancel() { queuePathEvent(PathEvent.CANCELED); synchronized (pathPlanLock) { getInProgress().ifPresent(AbstractNodeCostSearch::cancel); diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 129f00e20..2e7db9946 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -66,11 +66,12 @@ public class CalculationContext { public final boolean allowJumpAt256; public final boolean allowParkourAscend; public final boolean assumeWalkOnWater; + public boolean allowFallIntoLava; public final int frostWalker; public final boolean allowDiagonalDescend; public final boolean allowDiagonalAscend; public final boolean allowDownward; - public final int maxFallHeightNoWater; + public int maxFallHeightNoWater; public final int maxFallHeightBucket; public final double waterWalkSpeed; public final double breakBlockAdditionalCost; @@ -105,6 +106,7 @@ public class CalculationContext { this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value; this.allowParkourAscend = Baritone.settings().allowParkourAscend.value; this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value; + this.allowFallIntoLava = false; // Super secret internal setting for ElytraBehavior this.frostWalker = EnchantmentHelper.getMaxEnchantmentLevel(Enchantments.FROST_WALKER, baritone.getPlayerContext().player()); this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value; this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 2d8180356..7dac6159d 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -178,6 +178,14 @@ public class MovementDescend extends Movement { res.cost = tentativeCost;// TODO incorporate water swim up cost? return false; } + if (context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { + // found a fall into lava + res.x = destX; + res.y = newY; + res.z = destZ; + res.cost = tentativeCost; + 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 diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java index f110b9ce1..fe232786b 100755 --- a/src/main/java/baritone/utils/InputOverrideHandler.java +++ b/src/main/java/baritone/utils/InputOverrideHandler.java @@ -107,7 +107,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri } private boolean inControl() { - for (Input input : new Input[]{Input.MOVE_FORWARD, Input.MOVE_BACK, Input.MOVE_LEFT, Input.MOVE_RIGHT, Input.SNEAK}) { + for (Input input : new Input[]{Input.MOVE_FORWARD, Input.MOVE_BACK, Input.MOVE_LEFT, Input.MOVE_RIGHT, Input.SNEAK, Input.JUMP}) { if (isInputForcedDown(input)) { return true; } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index d09567914..eb7615de8 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -104,7 +104,9 @@ public final class PathRenderer implements IRenderer { final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); - drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0, 0.0D); + if (elytra.visiblePath != null) { + drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0, 0.0D); + } if (elytra.aimPos != null) { drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN); } diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index 236e41cc6..a174c842b 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -99,6 +99,8 @@ public class PathingControlManager implements IPathingControlManager { // get rid of the in progress stuff from the last process } switch (command.commandType) { + case SET_GOAL_AND_PAUSE: + p.secretInternalSetGoalAndPath(command); case REQUEST_PAUSE: p.requestPause(); break; @@ -119,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager { case SET_GOAL_AND_PATH: // now this i can do if (command.goal != null) { - baritone.getPathingBehavior().secretInternalSetGoalAndPath(command); + p.secretInternalSetGoalAndPath(command); } break; default: