Merge branch 'master' into builder

This commit is contained in:
Leijurv 2019-02-16 20:49:07 -08:00
commit ce73d34627
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
27 changed files with 406 additions and 141 deletions

View File

@ -11,6 +11,8 @@
[![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/) [![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/)
![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg) ![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg)
![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg) ![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg)
![](https://tokei.rs/b1/github/cabaletta/baritone?category=code)
![](https://tokei.rs/b1/github/cabaletta/baritone?category=files)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2) [![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2)
[![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/) [![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/)
[![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/) [![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/)
@ -30,6 +32,8 @@ the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone
Have committed at least once a day for the last 6 months =D 🦀 Have committed at least once a day for the last 6 months =D 🦀
1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2
Here are some links to help to get started: Here are some links to help to get started:
- [Features](FEATURES.md) - [Features](FEATURES.md)
@ -40,6 +44,8 @@ Here are some links to help to get started:
- [Javadocs](https://baritone.leijurv.com/) - [Javadocs](https://baritone.leijurv.com/)
- [Settings](https://baritone.leijurv.com/baritone/api/Settings.html#allowBreak)
# Chat control # Chat control
- [Baritone chat control usage](USAGE.md) - [Baritone chat control usage](USAGE.md)
@ -57,7 +63,7 @@ BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAnd
## Can I use Baritone as a library in my custom utility client? ## Can I use Baritone as a library in my custom utility client?
Sure! (As long as usage is in compliance with the LGPL 3 License) That's what it's for, sure! (As long as usage is in compliance with the LGPL 3 License)
## How is it so fast? ## How is it so fast?

View File

@ -43,7 +43,7 @@ Some common examples:
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java). For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java).
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/">here</a> and navigate to Settings in the left sidebar. All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#allowBreak">here</a>.
There are about a hundred settings, but here are some fun / interesting / important ones that you might want to look at changing in normal usage of Baritone. The documentation for each can be found at the above links. There are about a hundred settings, but here are some fun / interesting / important ones that you might want to look at changing in normal usage of Baritone. The documentation for each can be found at the above links.
- `allowBreak` - `allowBreak`

View File

@ -16,7 +16,7 @@
*/ */
group 'baritone' group 'baritone'
version '1.1.4' version '1.1.5'
buildscript { buildscript {
repositories { repositories {

View File

@ -17,8 +17,6 @@
package baritone.gradle.task; package baritone.gradle.task;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import java.io.File; import java.io.File;
@ -26,7 +24,6 @@ import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
/** /**
* @author Brady * @author Brady

View File

@ -164,6 +164,11 @@ public final class Settings {
*/ */
public final Setting<Boolean> considerPotionEffects = new Setting<>(true); public final Setting<Boolean> considerPotionEffects = new Setting<>(true);
/**
* Sprint and jump a block early on ascends wherever possible
*/
public final Setting<Boolean> sprintAscends = new Setting<>(true);
/** /**
* This is the big A* setting. * This is the big A* setting.
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path. * As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
@ -277,7 +282,7 @@ public final class Settings {
/** /**
* Start planning the next path once the remaining movements tick estimates sum up to less than this value * Start planning the next path once the remaining movements tick estimates sum up to less than this value
*/ */
public final Setting<Integer> planningTickLookAhead = new Setting<>(150); public final Setting<Integer> planningTickLookahead = new Setting<>(150);
/** /**
* Default size of the Long2ObjectOpenHashMap used in pathing * Default size of the Long2ObjectOpenHashMap used in pathing
@ -308,6 +313,8 @@ public final class Settings {
* Is it okay to sprint through a descend followed by a diagonal? * Is it okay to sprint through a descend followed by a diagonal?
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't * The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy. * lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
* <p>
* Note: this is *not* related to the allowDiagonalDescend setting, that is a completely different thing.
*/ */
public final Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true); public final Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
@ -378,6 +385,11 @@ public final class Settings {
*/ */
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false); public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
/**
* Cancel baritone on left click, as a form of "panic button"
*/
public final Setting<Boolean> clickCancel = new Setting<>(false);
/** /**
* Remember the contents of containers (chests, echests, furnaces) * Remember the contents of containers (chests, echests, furnaces)
* <p> * <p>
@ -388,7 +400,7 @@ public final class Settings {
/** /**
* Print all the debug messages to chat * Print all the debug messages to chat
*/ */
public final Setting<Boolean> chatDebug = new Setting<>(true); public final Setting<Boolean> chatDebug = new Setting<>(false);
/** /**
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in * Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
@ -467,7 +479,18 @@ public final class Settings {
public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false); public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
/** /**
* 😎 Render cached chunks as semitransparent. Doesn't work with OptiFine 😭 * Continue sprinting while in water
*/
public final Setting<Boolean> sprintInWater = new Setting<>(true);
/**
* When GetToBlockProcess fails to calculate a path, instead of just giving up, mark the closest instances
* of that block as "unreachable" and go towards the next closest
*/
public final Setting<Boolean> blacklistOnGetToBlockFailure = new Setting<>(true);
/**
* 😎 Render cached chunks as semitransparent. Doesn't work with OptiFine 😭 Rarely randomly crashes, see <a href="https://github.com/cabaletta/baritone/issues/327">this issue</a>.
* <p> * <p>
* Can be very useful on servers with low render distance. After enabling, you may need to reload the world in order for it to have an effect * Can be very useful on servers with low render distance. After enabling, you may need to reload the world in order for it to have an effect
* (e.g. disconnect and reconnect, enter then exit the nether, die and respawn, etc). This may literally kill your FPS and CPU because * (e.g. disconnect and reconnect, enter then exit the nether, die and respawn, etc). This may literally kill your FPS and CPU because
@ -558,6 +581,19 @@ public final class Settings {
*/ */
public final Setting<Integer> legitMineYLevel = new Setting<>(11); public final Setting<Integer> legitMineYLevel = new Setting<>(11);
/**
* Magically see ores that are separated diagonally from existing ores. Basically like mining around the ores that it finds
* in case there's one there touching it diagonally, except it checks it un-legit-ly without having the mine blocks to see it.
* You can decide whether this looks plausible or not.
* <p>
* This is disabled because it results in some weird behavior. For example, it can """see""" the top block of a vein of iron_ore
* through a lava lake. This isn't an issue normally since it won't consider anything touching lava, so it just ignores it.
* However, this setting expands that and allows it to see the entire vein so it'll mine under the lava lake to get the iron that
* it can reach without mining blocks adjacent to lava. This really defeats the purpose of legitMine since a player could never
* do that lol, so thats one reason why its disabled
*/
public final Setting<Boolean> legitMineIncludeDiagonals = new Setting<>(false);
/** /**
* When mining block of a certain type, try to mine two at once instead of one. * When mining block of a certain type, try to mine two at once instead of one.
* If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks * If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks

View File

@ -117,8 +117,12 @@ public class Rotation {
* @return are they really close * @return are they really close
*/ */
public boolean isReallyCloseTo(Rotation other) { public boolean isReallyCloseTo(Rotation other) {
float yawDiff = Math.abs(this.yaw - other.yaw); // you cant fool me return yawIsReallyClose(other) && Math.abs(this.pitch - other.pitch) < 0.01;
return (yawDiff < 0.01 || yawDiff > 359.9) && Math.abs(this.pitch - other.pitch) < 0.01; }
public boolean yawIsReallyClose(Rotation other) {
float yawDiff = Math.abs(normalizeYaw(yaw) - normalizeYaw(other.yaw)); // you cant fool me
return (yawDiff < 0.01 || yawDiff > 359.99);
} }
/** /**
@ -147,4 +151,9 @@ public class Rotation {
} }
return newYaw; return newYaw;
} }
@Override
public String toString() {
return "Yaw: " + yaw + ", Pitch: " + pitch;
}
} }

View File

@ -78,6 +78,9 @@ public final class RotationUtils {
* @return The wrapped angles * @return The wrapped angles
*/ */
public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) { public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) {
if (current.yawIsReallyClose(target)) {
return new Rotation(current.getYaw(), target.getPitch());
}
return target.subtract(current).normalize().add(current); return target.subtract(current).normalize().add(current);
} }
@ -102,7 +105,7 @@ public final class RotationUtils {
* @param dest The destination position * @param dest The destination position
* @return The rotation from the origin to the destination * @return The rotation from the origin to the destination
*/ */
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) { private static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z}; double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
double yaw = MathHelper.atan2(delta[0], -delta[2]); double yaw = MathHelper.atan2(delta[0], -delta[2]);
double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]); double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
@ -196,7 +199,7 @@ public final class RotationUtils {
* @return The optional rotation * @return The optional rotation
*/ */
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) { public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) {
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos); Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance); RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance);
//System.out.println(result); //System.out.println(result);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {

View File

@ -22,27 +22,31 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ChunkRenderContainer; import net.minecraft.client.renderer.ChunkRenderContainer;
import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.chunk.RenderChunk; import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL14; import org.lwjgl.opengl.GL14;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
@Mixin(ChunkRenderContainer.class) @Mixin(ChunkRenderContainer.class)
public class MixinChunkRenderContainer { public class MixinChunkRenderContainer {
@Inject( @Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "preRenderChunk", method = "preRenderChunk",
at = @At("HEAD") at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/RenderChunk.getPosition()Lnet/minecraft/util/math/BlockPos;"
) )
private void preRenderChunk(RenderChunk renderChunkIn, CallbackInfo ci) { )
private BlockPos getPosition(RenderChunk renderChunkIn) {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) { if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
GlStateManager.enableAlpha(); GlStateManager.enableAlpha();
GlStateManager.enableBlend(); GlStateManager.enableBlend();
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.get()); GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.get());
GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO); GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
} }
return renderChunkIn.getPosition();
} }
} }

View File

@ -20,6 +20,7 @@ package baritone.launch.mixins;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow; import org.spongepowered.asm.mixin.Shadow;
@ -61,6 +62,11 @@ public class MixinKeyBinding {
private void isPressed(CallbackInfoReturnable<Boolean> cir) { private void isPressed(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys // only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this); Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (pressTime > 0 && (KeyBinding) (Object) this == Minecraft.getMinecraft().gameSettings.keyBindAttack && Baritone.settings().clickCancel.get() && BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().isPathing()) {
Helper.HELPER.logDirect("Cancelling path on left click since the clickCancel setting is enabled!");
BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().cancelEverything();
return;
}
if (force != null && !force && Baritone.settings().suppressClicks.get()) { // <-- cursed if (force != null && !force && Baritone.settings().suppressClicks.get()) { // <-- cursed
if (pressTime > 0) { if (pressTime > 0) {
Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you."); Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you.");

View File

@ -22,25 +22,25 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderList; import net.minecraft.client.renderer.RenderList;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
@Mixin(RenderList.class) @Mixin(RenderList.class)
public class MixinRenderList { public class MixinRenderList {
@Inject( @Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer", method = "renderChunkLayer",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V" target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
) )
) )
private void renderChunkLayer(CallbackInfo info) { private void popMatrix() {
if (Baritone.settings().renderCachedChunks.get()) { if (Baritone.settings().renderCachedChunks.get()) {
// reset the blend func to normal (not dependent on constant alpha) // reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
} }
GlStateManager.popMatrix();
} }
} }

View File

@ -22,25 +22,25 @@ import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.VboRenderList; import net.minecraft.client.renderer.VboRenderList;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*; import static org.lwjgl.opengl.GL11.*;
@Mixin(VboRenderList.class) @Mixin(VboRenderList.class)
public class MixinVboRenderList { public class MixinVboRenderList {
@Inject( @Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer", method = "renderChunkLayer",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V" target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
) )
) )
private void renderChunkLayer(CallbackInfo info) { private void popMatrix() {
if (Baritone.settings().renderCachedChunks.get()) { if (Baritone.settings().renderCachedChunks.get()) {
// reset the blend func to normal (not dependent on constant alpha) // reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO); GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
} }
GlStateManager.popMatrix();
} }
} }

View File

@ -122,11 +122,27 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
cancelRequested = false; cancelRequested = false;
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
} }
synchronized (pathPlanLock) {
synchronized (pathCalcLock) {
if (inProgress != null) {
// we are calculating
// are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
Optional<IPath> currentBest = inProgress.bestPathSoFar();
if ((current == null || !current.getPath().getDest().equals(calcFrom)) // if current ends in inProgress's start, then we're ok
&& !calcFrom.equals(ctx.playerFeet()) && !calcFrom.equals(expectedSegmentStart) // if current starts in our playerFeet or pathStart, then we're ok
&& (!currentBest.isPresent() || (!currentBest.get().positions().contains(ctx.playerFeet()) && !currentBest.get().positions().contains(expectedSegmentStart))) // if
) {
// when it was *just* started, currentBest will be empty so we need to also check calcFrom since that's always present
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
}
}
}
if (current == null) { if (current == null) {
return; return;
} }
safeToCancel = current.onTick(); safeToCancel = current.onTick();
synchronized (pathPlanLock) {
if (current.failed() || current.finished()) { if (current.failed() || current.finished()) {
current = null; current = null;
if (goal == null || goal.isInGoal(ctx.playerFeet())) { if (goal == null || goal.isInGoal(ctx.playerFeet())) {
@ -135,7 +151,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
next = null; next = null;
return; return;
} }
if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(pathStart())) { // can contain either one if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(expectedSegmentStart)) { // can contain either one
// if the current path failed, we may not actually be on the next one, so make sure // if the current path failed, we may not actually be on the next one, so make sure
logDebug("Discarding next path as it does not contain current position"); logDebug("Discarding next path as it does not contain current position");
// for example if we had a nicely planned ahead path that starts where current ends // for example if we had a nicely planned ahead path that starts where current ends
@ -157,23 +173,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// at this point, current just ended, but we aren't in the goal and have no plan for the future // at this point, current just ended, but we aren't in the goal and have no plan for the future
synchronized (pathCalcLock) { synchronized (pathCalcLock) {
if (inProgress != null) { if (inProgress != null) {
// we are calculating
// are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing
if (calcFrom.equals(ctx.playerFeet()) || calcFrom.equals(pathStart())) {
// cool and good
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING); queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
return; return;
} }
// oh noes
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
}
// we aren't calculating // we aren't calculating
queuePathEvent(PathEvent.CALC_STARTED); queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true, context); findPathInNewThread(expectedSegmentStart, true, context);
} }
return; return;
} }
@ -204,7 +209,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// and this path doesn't get us all the way there // and this path doesn't get us all the way there
return; return;
} }
if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookAhead.get()) { if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookahead.get()) {
// and this path has 7.5 seconds or less left // and this path has 7.5 seconds or less left
// don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up // don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up
// if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own // if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own
@ -247,8 +252,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (goal == null) { if (goal == null) {
return false; return false;
} }
BlockPos pathStart = pathStart(); if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) {
if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(pathStart)) {
return false; return false;
} }
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
@ -260,7 +264,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return false; return false;
} }
queuePathEvent(PathEvent.CALC_STARTED); queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart, true, context); findPathInNewThread(expectedSegmentStart, true, context);
return true; return true;
} }
} }
@ -333,13 +337,15 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public void secretInternalSegmentCancel() { public void secretInternalSegmentCancel() {
queuePathEvent(PathEvent.CANCELED); queuePathEvent(PathEvent.CANCELED);
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
if (current != null) {
current = null; current = null;
next = null; next = null;
}
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
getInProgress().ifPresent(AbstractNodeCostSearch::cancel); getInProgress().ifPresent(AbstractNodeCostSearch::cancel);
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock(); baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock();
} }
}
}
public void forceCancel() { // NOT exposed on public api public void forceCancel() { // NOT exposed on public api
cancelEverything(); cancelEverything();
@ -448,7 +454,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p)); Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p));
if (current == null) { if (current == null) {
if (executor.isPresent()) { if (executor.isPresent()) {
if (executor.get().getPath().getSrc().equals(expectedSegmentStart)) { if (executor.get().getPath().positions().contains(expectedSegmentStart)) {
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING); queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
current = executor.get(); current = executor.get();
} else { } else {
@ -463,8 +469,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} else { } else {
if (next == null) { if (next == null) {
if (executor.isPresent()) { if (executor.isPresent()) {
if (executor.get().getPath().getSrc().equals(current.getPath().getDest())) {
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
next = executor.get(); next = executor.get();
} else {
logDebug("Warning: discarding orphan next segment with incorrect start");
}
} else { } else {
queuePathEvent(PathEvent.NEXT_CALC_FAILED); queuePathEvent(PathEvent.NEXT_CALC_FAILED);
} }

View File

@ -50,7 +50,9 @@ public final class GameEventHandler implements IEventBus, Helper {
if (event.getType() == TickEvent.Type.IN) { if (event.getType() == TickEvent.Type.IN) {
try { try {
baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true); baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true);
} catch (Exception ex) {} } catch (Exception ex) {
baritone.bsi = null;
}
} else { } else {
baritone.bsi = null; baritone.bsi = null;
} }

View File

@ -160,7 +160,7 @@ public abstract class Movement implements IMovement, MovementHelper {
//i dont care if theres snow in the way!!!!!!! //i dont care if theres snow in the way!!!!!!!
//you dont own me!!!! //you dont own me!!!!
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(blockPos)), true) VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true)
); );
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block // don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
state.setInput(Input.CLICK_LEFT, true); state.setInput(Input.CLICK_LEFT, true);

View File

@ -407,11 +407,10 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) { static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) {
EntityPlayerSP player = ctx.player();
state.setTarget(new MovementTarget( state.setTarget(new MovementTarget(
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F), new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(pos), VecUtils.getBlockPosCenter(pos),
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch), ctx.playerRotations()).getYaw(), ctx.player().rotationPitch),
false false
)).setInput(Input.MOVE_FORWARD, true); )).setInput(Input.MOVE_FORWARD, true);
} }

View File

@ -199,7 +199,7 @@ public class MovementAscend extends Movement {
return state.setInput(Input.JUMP, true); return state.setInput(Input.JUMP, true);
} }
private boolean headBonkClear() { public boolean headBonkClear() {
BetterBlockPos startUp = src.up(2); BetterBlockPos startUp = src.up(2);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
BetterBlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i)); BetterBlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i));

View File

@ -245,7 +245,7 @@ public class MovementDescend extends Movement {
// (dest - src) + dest is offset 1 more in the same direction // (dest - src) + dest is offset 1 more in the same direction
// so it's the block we'd need to worry about running into if we decide to sprint straight through this descend // so it's the block we'd need to worry about running into if we decide to sprint straight through this descend
BlockPos into = dest.subtract(src.down()).add(dest); BlockPos into = dest.subtract(src.down()).add(dest);
if (!MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into)) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up()) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up(2))) { if (skipToAscend()) {
// if dest extends into can't walk through, but the two above are can walk through, then we can overshoot and glitch in that weird way // if dest extends into can't walk through, but the two above are can walk through, then we can overshoot and glitch in that weird way
return true; return true;
} }
@ -256,4 +256,9 @@ public class MovementDescend extends Movement {
} }
return false; return false;
} }
public boolean skipToAscend() {
BlockPos into = dest.subtract(src.down()).add(dest);
return !MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into)) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up()) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up(2));
}
} }

View File

@ -17,6 +17,7 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.pathing.movement.MovementStatus; import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
@ -181,7 +182,7 @@ public class MovementDiagonal extends Movement {
} }
public boolean sprint() { public boolean sprint() {
if (MovementHelper.isLiquid(ctx, ctx.playerFeet())) { if (MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !Baritone.settings().sprintInWater.get()) {
return false; return false;
} }
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {

View File

@ -78,7 +78,7 @@ public class MovementFall extends Movement {
} }
BlockPos playerFeet = ctx.playerFeet(); BlockPos playerFeet = ctx.playerFeet();
Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)); Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest),ctx.playerRotations());
Rotation targetRotation = null; Rotation targetRotation = null;
Block destBlock = ctx.world().getBlockState(dest).getBlock(); Block destBlock = ctx.world().getBlockState(dest).getBlock();
boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER; boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER;
@ -141,7 +141,7 @@ public class MovementFall extends Movement {
} }
if (targetRotation == null) { if (targetRotation == null) {
Vec3d destCenterOffset = new Vec3d(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ()); 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)); state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset,ctx.playerRotations()), false));
} }
return state; return state;
} }

View File

@ -160,7 +160,7 @@ public class MovementPillar extends Movement {
IBlockState fromDown = BlockStateInterface.get(ctx, src); IBlockState fromDown = BlockStateInterface.get(ctx, src);
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(ctx, dest)) { if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(ctx, dest)) {
// stay centered while swimming up a water column // stay centered while swimming up a water column
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)), false)); state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest),ctx.playerRotations()), false));
Vec3d destCenter = VecUtils.getBlockPosCenter(dest); Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
if (Math.abs(ctx.player().posX - destCenter.x) > 0.2 || Math.abs(ctx.player().posZ - destCenter.z) > 0.2) { if (Math.abs(ctx.player().posX - destCenter.x) > 0.2 || Math.abs(ctx.player().posZ - destCenter.z) > 0.2) {
state.setInput(Input.MOVE_FORWARD, true); state.setInput(Input.MOVE_FORWARD, true);

View File

@ -175,7 +175,7 @@ public class MovementTraverse extends Movement {
// combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break // combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break
// it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw
float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest)).getYaw(); float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest), ctx.playerRotations()).getYaw();
float pitchToBreak = state.getTarget().getRotation().get().getPitch(); float pitchToBreak = state.getTarget().getRotation().get().getPitch();
state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)); state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true));
@ -199,7 +199,7 @@ public class MovementTraverse extends Movement {
isDoorActuallyBlockingUs = true; isDoorActuallyBlockingUs = true;
} }
if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) { if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0])), true)) return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true); .setInput(Input.CLICK_RIGHT, true);
} }
} }
@ -213,7 +213,7 @@ public class MovementTraverse extends Movement {
} }
if (blocked != null) { if (blocked != null) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked)), true)) return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true); .setInput(Input.CLICK_RIGHT, true);
} }
} }
@ -235,7 +235,7 @@ public class MovementTraverse extends Movement {
BlockPos into = dest.subtract(src).add(dest); BlockPos into = dest.subtract(src).add(dest);
Block intoBelow = BlockStateInterface.get(ctx, into).getBlock(); Block intoBelow = BlockStateInterface.get(ctx, into).getBlock();
Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock(); Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock();
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !MovementHelper.avoidWalkingInto(intoBelow) && !MovementHelper.avoidWalkingInto(intoAbove)) { if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, ctx.playerFeet()) || Baritone.settings().sprintInWater.get()) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock(); Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();

View File

@ -25,6 +25,7 @@ import baritone.api.pathing.movement.MovementStatus;
import baritone.api.pathing.path.IPathExecutor; import baritone.api.pathing.path.IPathExecutor;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.VecUtils; import baritone.api.utils.VecUtils;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.behavior.PathingBehavior; import baritone.behavior.PathingBehavior;
@ -39,6 +40,8 @@ import net.minecraft.block.BlockLiquid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import java.util.*; import java.util.*;
@ -104,14 +107,6 @@ public class PathExecutor implements IPathExecutor, Helper {
BetterBlockPos whereShouldIBe = path.positions().get(pathPosition); BetterBlockPos whereShouldIBe = path.positions().get(pathPosition);
BetterBlockPos whereAmI = ctx.playerFeet(); BetterBlockPos whereAmI = ctx.playerFeet();
if (!whereShouldIBe.equals(whereAmI)) { if (!whereShouldIBe.equals(whereAmI)) {
if (pathPosition == 0 && whereAmI.equals(whereShouldIBe.up()) && Math.abs(ctx.player().motionY) < 0.1 && !(path.movements().get(0) instanceof MovementAscend) && !(path.movements().get(0) instanceof MovementPillar)) {
// avoid the Wrong Y coordinate bug
// TODO add a timer here
new MovementDownward(behavior.baritone, whereAmI, whereShouldIBe).update();
return false;
}
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
if (whereAmI.equals(path.positions().get(i))) { if (whereAmI.equals(path.positions().get(i))) {
@ -122,6 +117,7 @@ public class PathExecutor implements IPathExecutor, Helper {
path.movements().get(j).reset(); path.movements().get(j).reset();
} }
onChangeInPathPosition(); onChangeInPathPosition();
onTick();
return false; return false;
} }
} }
@ -134,6 +130,7 @@ public class PathExecutor implements IPathExecutor, Helper {
//System.out.println("Double skip sundae"); //System.out.println("Double skip sundae");
pathPosition = i - 1; pathPosition = i - 1;
onChangeInPathPosition(); onChangeInPathPosition();
onTick();
return false; return false;
} }
} }
@ -195,17 +192,17 @@ public class PathExecutor implements IPathExecutor, Helper {
continue; continue;
} }
Movement m = (Movement) path.movements().get(i); Movement m = (Movement) path.movements().get(i);
HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak(bsi)); List<BlockPos> prevBreak = m.toBreak(bsi);
HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace(bsi)); List<BlockPos> prevPlace = m.toPlace(bsi);
HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto(bsi)); List<BlockPos> prevWalkInto = m.toWalkInto(bsi);
m.resetBlockCache(); m.resetBlockCache();
if (!prevBreak.equals(new HashSet<>(m.toBreak(bsi)))) { if (!prevBreak.equals(m.toBreak(bsi))) {
recalcBP = true; recalcBP = true;
} }
if (!prevPlace.equals(new HashSet<>(m.toPlace(bsi)))) { if (!prevPlace.equals(m.toPlace(bsi))) {
recalcBP = true; recalcBP = true;
} }
if (!prevWalkInto.equals(new HashSet<>(m.toWalkInto(bsi)))) { if (!prevWalkInto.equals(m.toWalkInto(bsi))) {
recalcBP = true; recalcBP = true;
} }
} }
@ -388,17 +385,34 @@ public class PathExecutor implements IPathExecutor, Helper {
if (!new CalculationContext(behavior.baritone).canSprint) { if (!new CalculationContext(behavior.baritone).canSprint) {
return false; return false;
} }
IMovement current = path.movements().get(pathPosition);
// traverse requests sprinting, so we need to do this check first
if (current instanceof MovementTraverse && pathPosition < path.length() - 3) {
IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && sprintableAscend(ctx, (MovementTraverse) current, (MovementAscend) next, path.movements().get(pathPosition + 2))) {
if (skipNow(ctx, current, next)) {
logDebug("Skipping traverse to straight ascend");
pathPosition++;
onChangeInPathPosition();
onTick();
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true);
return true;
} else {
logDebug("Too far to the side to safely sprint ascend");
}
}
}
// if the movement requested sprinting, then we're done // if the movement requested sprinting, then we're done
if (requested) { if (requested) {
return true; return true;
} }
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it // however, descend and ascend don't request sprinting, because they don't know the context of what movement comes after it
IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend) { if (current instanceof MovementDescend) {
if (((MovementDescend) current).safeMode()) { if (((MovementDescend) current).safeMode() && !((MovementDescend) current).skipToAscend()) {
logDebug("Sprinting would be unsafe"); logDebug("Sprinting would be unsafe");
return false; return false;
} }
@ -408,11 +422,13 @@ public class PathExecutor implements IPathExecutor, Helper {
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) { if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction // a descend then an ascend in the same direction
pathPosition++; pathPosition++;
onChangeInPathPosition();
onTick();
// okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric // okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric
logDebug("Skipping descend to straight ascend"); logDebug("Skipping descend to straight ascend");
return true; return true;
} }
if (canSprintInto(ctx, current, next)) { if (canSprintFromDescendInto(ctx, current, next)) {
if (ctx.playerFeet().equals(current.getDest())) { if (ctx.playerFeet().equals(current.getDest())) {
pathPosition++; pathPosition++;
onChangeInPathPosition(); onChangeInPathPosition();
@ -432,11 +448,117 @@ public class PathExecutor implements IPathExecutor, Helper {
return true; return true;
} }
} }
if (pathPosition < path.length() - 2 && prev instanceof MovementTraverse && sprintableAscend(ctx, (MovementTraverse) prev, (MovementAscend) current, path.movements().get(pathPosition + 1))) {
return true;
}
}
if (current instanceof MovementFall) {
Tuple<Vec3d, BlockPos> data = overrideFall((MovementFall) current);
if (data != null) {
BlockPos fallDest = data.getSecond();
if (!path.positions().contains(fallDest)) {
throw new IllegalStateException();
}
if (ctx.playerFeet().equals(fallDest)) {
pathPosition = path.positions().indexOf(fallDest);
onChangeInPathPosition();
onTick();
return true;
}
clearKeys();
behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getFirst(), ctx.playerRotations()), false);
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
return true;
}
} }
return false; return false;
} }
private static boolean canSprintInto(IPlayerContext ctx, IMovement current, IMovement next) { private Tuple<Vec3d, BlockPos> overrideFall(MovementFall movement) {
Vec3i dir = movement.getDirection();
if (dir.getY() < -3) {
return null;
}
Vec3i flatDir = new Vec3i(dir.getX(), 0, dir.getZ());
int i;
outer:
for (i = pathPosition + 1; i < path.length() - 1 && i < pathPosition + 3; i++) {
IMovement next = path.movements().get(i);
if (!(next instanceof MovementTraverse)) {
break;
}
if (!flatDir.equals(next.getDirection())) {
break;
}
for (int y = next.getDest().y; y <= movement.getSrc().y + 1; y++) {
BlockPos chk = new BlockPos(next.getDest().x, y, next.getDest().z);
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) {
break outer;
}
}
if (!MovementHelper.canWalkOn(ctx, next.getDest().down())) {
break;
}
}
i--;
if (i == pathPosition) {
return null; // no valid extension exists
}
double len = i - pathPosition - 0.4;
return new Tuple<>(
new Vec3d(flatDir.getX() * len + movement.getDest().x + 0.5, movement.getDest().y, flatDir.getZ() * len + movement.getDest().z + 0.5),
movement.getDest().add(flatDir.getX() * (i - pathPosition), 0, flatDir.getZ() * (i - pathPosition)));
}
private static boolean skipNow(IPlayerContext ctx, IMovement current, IMovement next) {
double offTarget = Math.abs(current.getDirection().getX() * (current.getSrc().z + 0.5D - ctx.player().posZ)) + Math.abs(current.getDirection().getZ() * (current.getSrc().x + 0.5D - ctx.player().posX));
if (offTarget > 0.1) {
return false;
}
// we are centered
BlockPos headBonk = current.getSrc().subtract(current.getDirection()).up(2);
if (MovementHelper.fullyPassable(ctx.world().getBlockState(headBonk))) {
return true;
}
// wait 0.3
double flatDist = Math.abs(current.getDirection().getX() * (headBonk.getX() + 0.5D - ctx.player().posX)) + Math.abs(current.getDirection().getZ() * (headBonk.getZ() + 0.5 - ctx.player().posZ));
return flatDist > 0.8;
}
private static boolean sprintableAscend(IPlayerContext ctx, MovementTraverse current, MovementAscend next, IMovement nextnext) {
if (!Baritone.settings().sprintAscends.get()) {
return false;
}
if (!current.getDirection().equals(next.getDirection().down())) {
return false;
}
if (nextnext.getDirection().getX() != next.getDirection().getX() || nextnext.getDirection().getZ() != next.getDirection().getZ()) {
return false;
}
if (!MovementHelper.canWalkOn(ctx, current.getDest().down())) {
return false;
}
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 3; y++) {
BlockPos chk = current.getSrc().up(y);
if (x == 1) {
chk = chk.add(current.getDirection());
}
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) {
return false;
}
}
}
if (MovementHelper.avoidWalkingInto(ctx.world().getBlockState(current.getSrc().up(3)).getBlock())) {
return false;
}
if (MovementHelper.avoidWalkingInto(ctx.world().getBlockState(next.getDest().up(2)).getBlock())) {
return false;
}
return true;
}
private static boolean canSprintFromDescendInto(IPlayerContext ctx, IMovement current, IMovement next) {
if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) { if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) {
return true; return true;
} }

View File

@ -202,7 +202,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x); double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x);
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y); double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z); double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z);
Rotation rot = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(placeX, placeY, placeZ)); Rotation rot = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(placeX, placeY, placeZ), ctx.playerRotations());
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance()); RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance());
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) { if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot); OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);

View File

@ -32,15 +32,13 @@ import net.minecraft.init.Blocks;
import net.minecraft.inventory.ContainerPlayer; import net.minecraft.inventory.ContainerPlayer;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess { public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
private Block gettingTo; private Block gettingTo;
private List<BlockPos> knownLocations; private List<BlockPos> knownLocations;
private List<BlockPos> blacklist; // locations we failed to calc to
private BlockPos start; private BlockPos start;
private int tickCount = 0; private int tickCount = 0;
@ -54,6 +52,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
onLostControl(); onLostControl();
gettingTo = block; gettingTo = block;
start = ctx.playerFeet(); start = ctx.playerFeet();
blacklist = new ArrayList<>();
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
@ -63,12 +62,12 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
@Override @Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { public synchronized PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (knownLocations == null) { if (knownLocations == null) {
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
if (knownLocations.isEmpty()) { if (knownLocations.isEmpty()) {
if (Baritone.settings().exploreForBlocks.get()) { if (Baritone.settings().exploreForBlocks.get() && !calcFailed) {
return new PathingCommand(new GoalRunAway(1, start) { return new PathingCommand(new GoalRunAway(1, start) {
@Override @Override
public boolean isInGoal(int x, int y, int z) { public boolean isInGoal(int x, int y, int z) {
@ -82,12 +81,19 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
Goal goal = new GoalComposite(knownLocations.stream().map(this::createGoal).toArray(Goal[]::new));
if (calcFailed) { if (calcFailed) {
if (Baritone.settings().blacklistOnGetToBlockFailure.get()) {
logDirect("Unable to find any path to " + gettingTo + ", blacklisting presumably unreachable closest instances");
blacklistClosest();
return onTick(false, isSafeToCancel); // gamer moment
} else {
logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock"); logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock");
if (isSafeToCancel) { if (isSafeToCancel) {
onLostControl(); onLostControl();
} }
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); return new PathingCommand(goal, PathingCommandType.CANCEL_AND_SET_GOAL);
}
} }
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
@ -95,25 +101,58 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
CalculationContext context = new CalculationContext(baritone, true); CalculationContext context = new CalculationContext(baritone, true);
Baritone.getExecutor().execute(() -> rescan(current, context)); Baritone.getExecutor().execute(() -> rescan(current, context));
} }
Goal goal = new GoalComposite(knownLocations.stream().map(this::createGoal).toArray(Goal[]::new));
if (goal.isInGoal(ctx.playerFeet()) && isSafeToCancel) { if (goal.isInGoal(ctx.playerFeet()) && isSafeToCancel) {
// we're there // we're there
if (rightClickOnArrival(gettingTo)) { if (rightClickOnArrival(gettingTo)) {
if (rightClick()) { if (rightClick()) {
onLostControl(); onLostControl();
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
} else { } else {
onLostControl(); onLostControl();
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
} }
return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH); return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
} }
// blacklist the closest block and its adjacent blocks
public synchronized void blacklistClosest() {
List<BlockPos> newBlacklist = new ArrayList<>();
knownLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(newBlacklist::add);
outer:
while (true) {
for (BlockPos known : knownLocations) {
for (BlockPos blacklist : newBlacklist) {
if (areAdjacent(known, blacklist)) { // directly adjacent
newBlacklist.add(known);
knownLocations.remove(known);
continue outer;
}
}
}
if (true) {
break; // codacy gets mad if i just end on a break LOL
}
}
logDebug("Blacklisting unreachable locations " + newBlacklist);
blacklist.addAll(newBlacklist);
}
// safer than direct double comparison from distanceSq
private boolean areAdjacent(BlockPos posA, BlockPos posB) {
int diffX = Math.abs(posA.getX() - posB.getX());
int diffY = Math.abs(posA.getY() - posB.getY());
int diffZ = Math.abs(posA.getZ() - posB.getZ());
return (diffX + diffY + diffZ) == 1;
}
@Override @Override
public void onLostControl() { public synchronized void onLostControl() {
gettingTo = null; gettingTo = null;
knownLocations = null; knownLocations = null;
start = null; start = null;
blacklist = null;
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
} }
@ -122,8 +161,10 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
return "Get To Block " + gettingTo; return "Get To Block " + gettingTo;
} }
private void rescan(List<BlockPos> known, CalculationContext context) { private synchronized void rescan(List<BlockPos> known, CalculationContext context) {
knownLocations = MineProcess.searchWorld(context, Collections.singletonList(gettingTo), 64, known); List<BlockPos> positions = MineProcess.searchWorld(context, Collections.singletonList(gettingTo), 64, known);
positions.removeIf(blacklist::contains);
knownLocations = positions;
} }
private Goal createGoal(BlockPos pos) { private Goal createGoal(BlockPos pos) {

View File

@ -228,7 +228,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return prune(ctx, locs, mining, max); return prune(ctx, locs, mining, max);
} }
public void addNearby() { private void addNearby() {
knownOreLocations.addAll(droppedItemsScan(mining, ctx.world())); knownOreLocations.addAll(droppedItemsScan(mining, ctx.world()));
BlockPos playerFeet = ctx.playerFeet(); BlockPos playerFeet = ctx.playerFeet();
BlockStateInterface bsi = new BlockStateInterface(ctx); BlockStateInterface bsi = new BlockStateInterface(ctx);
@ -239,8 +239,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) { for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
// crucial to only add blocks we can see because otherwise this // crucial to only add blocks we can see because otherwise this
// is an x-ray and it'll get caught // is an x-ray and it'll get caught
if (mining.contains(bsi.get0(x, y, z).getBlock()) && RotationUtils.reachable(ctx.player(), new BlockPos(x, y, z), fakedBlockReachDistance).isPresent()) { if (mining.contains(bsi.get0(x, y, z).getBlock())) {
knownOreLocations.add(new BlockPos(x, y, z)); BlockPos pos = new BlockPos(x, y, z);
if ((Baritone.settings().legitMineIncludeDiagonals.get() && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx.player(), pos, fakedBlockReachDistance).isPresent()) {
knownOreLocations.add(pos);
}
} }
} }
} }
@ -250,12 +253,19 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) { public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world); List<BlockPos> dropped = droppedItemsScan(mining, ctx.world);
dropped.removeIf(drop -> {
for (BlockPos pos : locs2) {
if (pos.distanceSq(drop) <= 9 && mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx.bsi, pos)) { // TODO maybe drop also has to be supported? no lava below?
return true;
}
}
return false;
});
List<BlockPos> locs = locs2 List<BlockPos> locs = locs2
.stream() .stream()
.distinct() .distinct()
// remove any that are within loaded chunks that aren't actually what we want // remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos)) .filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
// remove any that are implausible to mine (encased in bedrock, or touching lava) // remove any that are implausible to mine (encased in bedrock, or touching lava)

View File

@ -164,36 +164,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
if (msg.startsWith("goal")) { if (msg.startsWith("goal")) {
String[] params = msg.substring(4).trim().split(" "); String rest = msg.substring(4).trim();
Goal goal;
if (rest.equals("clear") || rest.equals("none")) {
goal = null;
} else {
String[] params = rest.split(" ");
if (params[0].equals("")) { if (params[0].equals("")) {
params = new String[]{}; params = new String[]{};
} }
Goal goal; goal = parseGoal(params);
try { if (goal == null) {
switch (params.length) {
case 0:
goal = new GoalBlock(ctx.playerFeet());
break;
case 1:
if (params[0].equals("clear") || params[0].equals("none")) {
goal = null;
} else {
goal = new GoalYLevel(Integer.parseInt(params[0]));
}
break;
case 2:
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
break;
case 3:
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
break;
default:
logDirect("unable to understand lol");
return true; return true;
} }
} catch (NumberFormatException ex) {
logDirect("unable to parse integer " + ex);
return true;
} }
customGoalProcess.setGoal(goal); customGoalProcess.setGoal(goal);
logDirect("Goal: " + goal); logDirect("Goal: " + goal);
@ -270,7 +253,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect(success ? "Loaded" : "Unable to load"); logDirect(success ? "Loaded" : "Unable to load");
return true; return true;
} }
if (msg.equals("axis")) { if (msg.equals("axis") || msg.equals("highway")) {
customGoalProcess.setGoalAndPath(new GoalAxis()); customGoalProcess.setGoalAndPath(new GoalAxis());
return true; return true;
} }
@ -516,7 +499,11 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
if (block == null) { if (block == null) {
waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null); waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
if (waypoint == null) { if (waypoint == null) {
logDirect("No locations for " + mining + " known, cancelling"); Goal goal = parseGoal(waypointType.split(" "));
if (goal != null) {
logDirect("Going to " + goal);
customGoalProcess.setGoalAndPath(goal);
}
return true; return true;
} }
} else { } else {
@ -595,4 +582,31 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
} }
} }
private Goal parseGoal(String[] params) {
Goal goal;
try {
switch (params.length) {
case 0:
goal = new GoalBlock(ctx.playerFeet());
break;
case 1:
goal = new GoalYLevel(Integer.parseInt(params[0]));
break;
case 2:
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
break;
case 3:
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
break;
default:
logDirect("unable to understand lol");
return null;
}
} catch (NumberFormatException ex) {
logDirect("unable to parse integer " + ex);
return null;
}
return goal;
}
} }

View File

@ -115,7 +115,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
ctx.player().movementInput = new PlayerMovementInput(this); ctx.player().movementInput = new PlayerMovementInput(this);
} }
} else { } else {
if (ctx.player().movementInput.getClass() == PlayerMovementInput.class) { if (ctx.player().movementInput.getClass() == PlayerMovementInput.class) { // allow other movement inputs that aren't this one, e.g. for a freecam
ctx.player().movementInput = new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings); ctx.player().movementInput = new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
} }
} }