mirror of https://github.com/cabaletta/baritone
Find jump off spot using INSANE custom CalculationContext
This commit is contained in:
parent
d32f1b2a16
commit
83066fc57c
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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<BetterBlockPos> 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<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;
|
||||
}
|
||||
/**
|
||||
* 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,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
Loading…
Reference in New Issue