Find jump off spot using INSANE custom CalculationContext

This commit is contained in:
Brady 2023-06-30 20:42:03 -05:00
parent d32f1b2a16
commit 83066fc57c
No known key found for this signature in database
GPG Key ID: 73A788379A197567
8 changed files with 117 additions and 89 deletions

View File

@ -56,5 +56,10 @@ public enum PathingCommandType {
/** /**
* Go and ask the next process what to do * 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
} }

View File

@ -18,24 +18,28 @@
package baritone.behavior; package baritone.behavior;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.behavior.IElytraBehavior; import baritone.api.behavior.IElytraBehavior;
import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.IAimProcessor;
import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor;
import baritone.api.event.events.*; import baritone.api.event.events.*;
import baritone.api.pathing.goals.Goal; 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.IBaritoneProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
import baritone.api.utils.*; import baritone.api.utils.*;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.NetherPathfinderContext;
import baritone.behavior.elytra.NetherPath; import baritone.behavior.elytra.NetherPath;
import baritone.behavior.elytra.PathCalculationException; import baritone.behavior.elytra.PathCalculationException;
import baritone.behavior.elytra.UnpackedSegment; 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.BlockStateInterface;
import baritone.utils.PathingCommandContext;
import baritone.utils.accessor.IEntityFireworkRocket; import baritone.utils.accessor.IEntityFireworkRocket;
import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatArrayList;
import it.unimi.dsi.fastutil.floats.FloatIterator; import it.unimi.dsi.fastutil.floats.FloatIterator;
@ -54,6 +58,8 @@ import java.util.*;
import java.util.concurrent.*; import java.util.concurrent.*;
import java.util.function.UnaryOperator; import java.util.function.UnaryOperator;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { 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.context = new NetherPathfinderContext(NETHER_SEED);
this.clearLines = new CopyOnWriteArrayList<>(); this.clearLines = new CopyOnWriteArrayList<>();
this.blockedLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>();
this.visiblePath = Collections.emptyList();
this.pathManager = this.new PathManager(); this.pathManager = this.new PathManager();
this.process = new ElytraProcess(); this.process = new ElytraProcess();
this.solverExecutor = Executors.newSingleThreadExecutor(); this.solverExecutor = Executors.newSingleThreadExecutor();
@ -395,9 +400,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H
@Override @Override
public void cancel() { public void cancel() {
this.destination = null; this.destination = null;
this.visiblePath = Collections.emptyList();
this.pathManager.clear(); this.pathManager.clear();
this.aimPos = null;
this.remainingFireworkTicks = 0; this.remainingFireworkTicks = 0;
this.remainingSetBackTicks = 0; this.remainingSetBackTicks = 0;
if (this.solver != null) { if (this.solver != null) {
@ -446,12 +449,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H
// Reset rendered elements // Reset rendered elements
this.clearLines.clear(); this.clearLines.clear();
this.blockedLines.clear(); this.blockedLines.clear();
this.visiblePath = null;
this.simulationLine = null; this.simulationLine = null;
this.aimPos = null; this.aimPos = null;
final List<BetterBlockPos> path = this.pathManager.getPath(); final List<BetterBlockPos> path = this.pathManager.getPath();
if (path.isEmpty()) { if (path.isEmpty()) {
return; return;
} else if (this.destination == null) {
this.pathManager.clear();
return;
} }
this.bsi = new BlockStateInterface(ctx); 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); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
if (!Baritone.settings().elytraAutoJump.value) { if (this.state == State.FLYING || this.state == State.START_FLYING) {
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); 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.LOCATE_JUMP) {
if (this.state == State.FLYING) { if (this.goal == null) {
this.state = State.GET_TO_JUMP; 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.state == State.GET_TO_JUMP) {
if (this.goal == null) { final IPathExecutor executor = baritone.getPathingBehavior().getCurrent();
final BlockPos jumpOff = this.findJumpOffSpot(); final boolean canStartFlying = ctx.player().fallDistance > 1.0f
if (jumpOff == null) { && !isSafeToCancel
onLostControl(); && executor != null
logDirect("Couldn't find a suitable spot to jump off of, canceling"); && executor.getPath().movements().get(executor.getPosition()) instanceof MovementFall;
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} if (canStartFlying) {
this.goal = new GoalGetToBlock(jumpOff);
ElytraBehavior.this.pathManager.pathToDestination(jumpOff.add(0, -4, 0));
}
if (this.goal.isInGoal(ctx.playerFeet())) {
this.state = State.START_FLYING; this.state = State.START_FLYING;
} else { } 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()) { if (this.state == State.START_FLYING) {
baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d( if (!isSafeToCancel) {
ctx.playerHead(), // owned
VecUtils.getBlockPosCenter(((IGoalRenderPos) this.goal).getGoalPos()), baritone.getPathingBehavior().secretInternalSegmentCancel();
ctx.playerRotations()
), false);
baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
if (ctx.player().fallDistance > 0.0f) {
baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true);
} }
baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true);
} }
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
@ -1239,7 +1270,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H
@Override @Override
public void onLostControl() { public void onLostControl() {
this.goal = null; this.goal = null;
this.state = State.GET_TO_JUMP; this.state = State.START_FLYING;
ElytraBehavior.this.cancel(); ElytraBehavior.this.cancel();
} }
@ -1252,64 +1283,42 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H
public String displayName0() { public String displayName0() {
return "Elytra"; return "Elytra";
} }
}
// ok... now this.. is disgusting /**
// TODO: make less scuffed * Custom calculation context which makes the player fall into lava
private BlockPos findJumpOffSpot() { */
BlockPos best = null; private static final class WalkOffCalculationContext extends CalculationContext {
final BetterBlockPos feet = ctx.playerFeet();
final List<ChunkPos> 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;
}
final int[] adjacent = new int[4]; public WalkOffCalculationContext(IBaritone baritone) {
if (x > 0) adjacent[0] = obstruction[x - 1][z]; super(baritone, true);
if (z > 0) adjacent[1] = obstruction[x][z - 1]; this.allowFallIntoLava = true;
if (x < 15) adjacent[2] = obstruction[x + 1][z]; this.maxFallHeightNoWater = 10000;
if (z < 15) adjacent[3] = obstruction[x][z + 1]; }
final OptionalInt minLevel = Arrays.stream(adjacent).filter(i -> i != 0).min();
if (minLevel.isPresent() && minLevel.getAsInt() <= 4) { @Override
final int yActual = feet.y - minLevel.getAsInt() + 2; // lol public double costOfPlacingAt(int x, int y, int z, IBlockState current) {
// The target spot itself is clear return COST_INF;
if (chunk.getBlockState(x, yActual, z).getMaterial() != Material.AIR }
|| chunk.getBlockState(x, yActual + 1, z).getMaterial() != Material.AIR) {
continue; @Override
} public double breakCostMultiplierAt(int x, int y, int z, IBlockState current) {
// lessgooo return COST_INF;
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; @Override
} public double placeBucketCost() {
} return COST_INF;
}
}
}
return best;
} }
} }
private enum State { private enum State {
LOCATE_JUMP,
VALIDATE_PATH,
WAIT_ELYTRA_PATH,
GET_TO_JUMP, GET_TO_JUMP,
START_FLYING, START_FLYING,
FLYING FLYING,
RESTART_FLYING,
} }
} }

View File

@ -352,7 +352,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} }
// just cancel the current path // just cancel the current path
private void secretInternalSegmentCancel() { public void secretInternalSegmentCancel() {
queuePathEvent(PathEvent.CANCELED); queuePathEvent(PathEvent.CANCELED);
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
getInProgress().ifPresent(AbstractNodeCostSearch::cancel); getInProgress().ifPresent(AbstractNodeCostSearch::cancel);

View File

@ -66,11 +66,12 @@ public class CalculationContext {
public final boolean allowJumpAt256; public final boolean allowJumpAt256;
public final boolean allowParkourAscend; public final boolean allowParkourAscend;
public final boolean assumeWalkOnWater; public final boolean assumeWalkOnWater;
public boolean allowFallIntoLava;
public final int frostWalker; public final int frostWalker;
public final boolean allowDiagonalDescend; public final boolean allowDiagonalDescend;
public final boolean allowDiagonalAscend; public final boolean allowDiagonalAscend;
public final boolean allowDownward; public final boolean allowDownward;
public final int maxFallHeightNoWater; public int maxFallHeightNoWater;
public final int maxFallHeightBucket; public final int maxFallHeightBucket;
public final double waterWalkSpeed; public final double waterWalkSpeed;
public final double breakBlockAdditionalCost; public final double breakBlockAdditionalCost;
@ -105,6 +106,7 @@ public class CalculationContext {
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value; this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
this.allowParkourAscend = Baritone.settings().allowParkourAscend.value; this.allowParkourAscend = Baritone.settings().allowParkourAscend.value;
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.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.frostWalker = EnchantmentHelper.getMaxEnchantmentLevel(Enchantments.FROST_WALKER, baritone.getPlayerContext().player());
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value; this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value;
this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value; this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value;

View File

@ -178,6 +178,14 @@ public class MovementDescend extends Movement {
res.cost = tentativeCost;// TODO incorporate water swim up cost? res.cost = tentativeCost;// TODO incorporate water swim up cost?
return false; 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 (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 // 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 // this effectively "resets" our falling speed

View File

@ -107,7 +107,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
} }
private boolean inControl() { 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)) { if (isInputForcedDown(input)) {
return true; return true;
} }

View File

@ -104,7 +104,9 @@ public final class PathRenderer implements IRenderer {
final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); 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) { if (elytra.aimPos != null) {
drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN); drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN);
} }

View File

@ -99,6 +99,8 @@ public class PathingControlManager implements IPathingControlManager {
// get rid of the in progress stuff from the last process // get rid of the in progress stuff from the last process
} }
switch (command.commandType) { switch (command.commandType) {
case SET_GOAL_AND_PAUSE:
p.secretInternalSetGoalAndPath(command);
case REQUEST_PAUSE: case REQUEST_PAUSE:
p.requestPause(); p.requestPause();
break; break;
@ -119,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager {
case SET_GOAL_AND_PATH: case SET_GOAL_AND_PATH:
// now this i can do // now this i can do
if (command.goal != null) { if (command.goal != null) {
baritone.getPathingBehavior().secretInternalSetGoalAndPath(command); p.secretInternalSetGoalAndPath(command);
} }
break; break;
default: default: