From 705a5a0712ccadac53ac6e132128bce48f6e29e0 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 00:33:35 -0700 Subject: [PATCH 001/276] elytra prototype mvp --- src/api/java/baritone/api/Settings.java | 4 + src/main/java/baritone/Baritone.java | 2 + src/main/java/baritone/Elytra.java | 274 ++++++++++++++++++ .../java/baritone/utils/PathRenderer.java | 22 +- 4 files changed, 293 insertions(+), 9 deletions(-) create mode 100644 src/main/java/baritone/Elytra.java diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index b7a4e41a4..5463f3163 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -48,6 +48,10 @@ import java.util.function.Consumer; */ public final class Settings { + public final Setting elytraSimulationTicks = new Setting<>(20); + public final Setting elytraPitchRange = new Setting<>(25); + public final Setting elytraFireworkSpeed = new Setting<>(0.425); + /** * Allow Baritone to break blocks */ diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 61db54211..a85155bcf 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -88,6 +88,7 @@ public class Baritone implements IBaritone { private IPlayerContext playerContext; private WorldProvider worldProvider; + public Elytra elytra; public BlockStateInterface bsi; @@ -100,6 +101,7 @@ public class Baritone implements IBaritone { { // the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist pathingBehavior = new PathingBehavior(this); + elytra = new Elytra(this); lookBehavior = new LookBehavior(this); inventoryBehavior = new InventoryBehavior(this); inputOverrideHandler = new InputOverrideHandler(this); diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java new file mode 100644 index 000000000..ac253868b --- /dev/null +++ b/src/main/java/baritone/Elytra.java @@ -0,0 +1,274 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone; + +import baritone.api.event.events.TickEvent; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Helper; +import baritone.api.utils.Rotation; +import baritone.api.utils.RotationUtils; +import baritone.behavior.Behavior; +import baritone.utils.BlockStateInterface; +import net.minecraft.block.material.Material; +import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.util.EnumHand; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.RayTraceResult; +import net.minecraft.util.math.Vec3d; + +import java.io.DataInputStream; +import java.io.File; +import java.io.FileInputStream; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +public class Elytra extends Behavior implements Helper { + + public static List path = new ArrayList<>(); + + static { + + try { + DataInputStream in = new DataInputStream(new FileInputStream(new File("/Users/leijurv/Dropbox/nether-pathfinder/build/test"))); + int count = in.readInt(); + System.out.println("Count: " + count); + for (int i = 0; i < count; i++) { + path.add(new BetterBlockPos((int) in.readDouble(), (int) in.readDouble(), (int) in.readDouble())); + } + removeBacktracks(); + } catch (Exception e) { + throw new RuntimeException(e); + } + } + + public int playerNear; + public int goingTo; + public int sinceFirework; + public BlockPos goal; + + protected Elytra(Baritone baritone) { + super(baritone); + } + + + @Override + public void onTick(TickEvent event) { + if (event.getType() == TickEvent.Type.OUT) { + return; + } + fixNearPlayer(); + baritone.getInputOverrideHandler().clearAllKeys(); + + if (ctx.player().isElytraFlying()) { + Vec3d start = ctx.playerFeetAsVec(); + boolean firework = firework(); + sinceFirework++; + if (!firework + && sinceFirework > 10 + && ctx.player().posY < path.get(goingTo).y + 5 // don't firework if trying to descend + && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x, ctx.player().posY, path.get(goingTo).z)) > 5) // UGH!!!!!!! + && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending + ) { + logDirect("firework"); + ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); + sinceFirework = 0; + } + long t = System.currentTimeMillis(); + for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) + int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + boolean requireClear = relaxation == 0; + int steps = relaxation < 2 ? Baritone.settings().elytraSimulationTicks.value : 3; + int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps + for (int dy : heights) { + for (int i = Math.min(playerNear + 20, path.size()); i >= playerNear; i--) { + Vec3d dest = new Vec3d(path.get(i)).add(0, dy, 0); + if (dy != 0 && (i + lookahead >= path.size() || (!clearView(dest, new Vec3d(path.get(i + lookahead)).add(0, dy, 0)) || !clearView(dest, new Vec3d(path.get(i + lookahead)))))) { + // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position + continue; + } + if (requireClear ? isClear(start, dest) : clearView(start, dest)) { + Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); + ctx.player().rotationYaw = rot.getYaw(); + long a = System.currentTimeMillis(); + Float pitch = solvePitch(dest.subtract(start), steps); + if (pitch == null) { + continue; + } + long b = System.currentTimeMillis(); + ctx.player().rotationPitch = pitch; + System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); + goingTo = i; + goal = path.get(i).add(0, dy, 0); + return; + } + } + } + } + logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); + } + } + + private boolean firework() { + return ctx.world().loadedEntityList.stream().anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); + } + + private boolean isClear(Vec3d start, Vec3d dest) { + Vec3d perpendicular = dest.subtract(start).crossProduct(new Vec3d(0, 1, 0)).normalize(); + return clearView(start, dest) + && clearView(start.add(0, 2, 0), dest.add(0, 2, 0)) + && clearView(start.add(0, -2, 0), dest.add(0, -2, 0)) + && clearView(start.add(perpendicular), dest.add(perpendicular)) + && clearView(start.subtract(perpendicular), dest.subtract(perpendicular)); + } + + private boolean clearView(Vec3d start, Vec3d dest) { + RayTraceResult result = ctx.world().rayTraceBlocks(start, dest, true, false, true); + return result == null || result.typeOfHit == RayTraceResult.Type.MISS; + } + + private Float solvePitch(Vec3d goalDirection, int steps) { + // we are at a certain velocity, but we have a target velocity + // what pitch would get us closest to our target velocity? + // yaw is easy so we only care about pitch + + goalDirection = goalDirection.normalize(); + Rotation good = RotationUtils.calcRotationFromVec3d(new Vec3d(0, 0, 0), goalDirection, ctx.playerRotations()); // lazy lol + + boolean firework = firework(); + Float bestPitch = null; + double bestDot = Double.NEGATIVE_INFINITY; + Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); + BlockStateInterface bsi = new BlockStateInterface(ctx); + outer: + for (float pitch = Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); pitch < Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); pitch++) { + Vec3d stepped = motion; + Vec3d totalMotion = new Vec3d(0, 0, 0); + for (int i = 0; i < steps; i++) { + stepped = step(stepped, pitch, good.getYaw(), firework); + totalMotion = totalMotion.add(stepped); + + Vec3d actualPosition = ctx.playerFeetAsVec().add(totalMotion); + if (bsi.get0(MathHelper.floor(actualPosition.x), MathHelper.floor(actualPosition.y), MathHelper.floor(actualPosition.z)).getMaterial() != Material.AIR) { + continue outer; + } + if (bsi.get0(MathHelper.floor(actualPosition.x), MathHelper.floor(actualPosition.y) + 1, MathHelper.floor(actualPosition.z)).getMaterial() != Material.AIR) { + continue outer; + } + } + double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); + // tried to incorporate a "speedGoodness" but it kept making it do stupid stuff (aka always losing altitude) + double goodness = directionalGoodness; + if (goodness > bestDot) { + bestDot = goodness; + bestPitch = pitch; + } + } + return bestPitch; + } + + public static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { + double motionX = motion.x; + double motionY = motion.y; + double motionZ = motion.z; + float flatZ = MathHelper.cos(-rotationYaw * 0.017453292F - (float) Math.PI); // 0.174... is Math.PI / 180 + float flatX = MathHelper.sin(-rotationYaw * 0.017453292F - (float) Math.PI); + float pitchBase = -MathHelper.cos(-rotationPitch * 0.017453292F); + float pitchHeight = MathHelper.sin(-rotationPitch * 0.017453292F); + Vec3d lookDirection = new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); + float pitchRadians = rotationPitch * 0.017453292F; + double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); + double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); + double thisIsAlwaysOne = lookDirection.length(); + float pitchBase3 = MathHelper.cos(pitchRadians); + //System.out.println("always the same lol " + -pitchBase + " " + pitchBase3); + //System.out.println("always the same lol " + Math.abs(pitchBase3) + " " + pitchBase2); + //System.out.println("always 1 lol " + thisIsAlwaysOne); + pitchBase3 = (float) ((double) pitchBase3 * (double) pitchBase3 * Math.min(1, thisIsAlwaysOne / 0.4)); + motionY += -0.08 + (double) pitchBase3 * 0.06; + if (motionY < 0 && pitchBase2 > 0) { + double speedModifier = motionY * -0.1 * (double) pitchBase3; + motionY += speedModifier; + motionX += lookDirection.x * speedModifier / pitchBase2; + motionZ += lookDirection.z * speedModifier / pitchBase2; + } + if (pitchRadians < 0) { // if you are looking down (below level) + double anotherSpeedModifier = flatMotion * (double) (-MathHelper.sin(pitchRadians)) * 0.04; + motionY += anotherSpeedModifier * 3.2; + motionX -= lookDirection.x * anotherSpeedModifier / pitchBase2; + motionZ -= lookDirection.z * anotherSpeedModifier / pitchBase2; + } + if (pitchBase2 > 0) { // this is always true unless you are looking literally straight up (let's just say the bot will never do that) + motionX += (lookDirection.x / pitchBase2 * flatMotion - motionX) * 0.1; + motionZ += (lookDirection.z / pitchBase2 * flatMotion - motionZ) * 0.1; + } + motionX *= 0.99; + motionY *= 0.98; + motionZ *= 0.99; + //System.out.println(motionX + " " + motionY + " " + motionZ); + if (firework) { + motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; + motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; + motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; + } + return new Vec3d(motionX, motionY, motionZ); + } + + public void fixNearPlayer() { + BetterBlockPos pos = ctx.playerFeet(); + for (int i = playerNear; i >= Math.max(playerNear - 1000, 0); i -= 10) { + if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { + playerNear = i; // intentional: this changes the bound of the loop + } + } + for (int i = playerNear; i < Math.min(playerNear + 1000, path.size()); i += 10) { + if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { + playerNear = i; // intentional: this changes the bound of the loop + } + } + for (int i = playerNear; i >= Math.max(playerNear - 50, 0); i--) { + if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { + playerNear = i; // intentional: this changes the bound of the loop + } + } + for (int i = playerNear; i < Math.min(playerNear + 50, path.size()); i++) { + if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { + playerNear = i; // intentional: this changes the bound of the loop + } + } + //System.out.println(playerNear); + } + + public static void removeBacktracks() { + Map positionFirstSeen = new HashMap<>(); + for (int i = 0; i < path.size(); i++) { + BetterBlockPos pos = path.get(i); + if (positionFirstSeen.containsKey(pos)) { + int j = positionFirstSeen.get(pos); + while (i > j) { + path.remove(i); + i--; + } + } else { + positionFirstSeen.put(pos, i); + } + } + } +} diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 2fe224706..828479a5d 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -17,9 +17,9 @@ package baritone.utils; +import baritone.Elytra; import baritone.api.BaritoneAPI; import baritone.api.event.events.RenderEvent; -import baritone.api.pathing.calc.IPath; import baritone.api.pathing.goals.*; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Helper; @@ -96,33 +96,37 @@ public final class PathRenderer implements IRenderer { // Render the current path, if there is one if (current != null && current.getPath() != null) { int renderBegin = Math.max(current.getPosition() - 3, 0); - drawPath(current.getPath(), renderBegin, settings.colorCurrentPath.value, settings.fadePath.value, 10, 20); + drawPath(current.getPath().positions(), renderBegin, settings.colorCurrentPath.value, settings.fadePath.value, 10, 20); } if (next != null && next.getPath() != null) { - drawPath(next.getPath(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); + drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); + } + + drawPath(Elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, Elytra.path.size())), 0, Color.RED, false, 0, 0); + if (behavior.baritone.elytra.goal != null) { + drawDankLitGoalBox(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); } // If there is a path calculation currently running, render the path calculation process behavior.getInProgress().ifPresent(currentlyRunning -> { currentlyRunning.bestPathSoFar().ifPresent(p -> { - drawPath(p, 0, settings.colorBestPathSoFar.value, settings.fadePath.value, 10, 20); + drawPath(p.positions(), 0, settings.colorBestPathSoFar.value, settings.fadePath.value, 10, 20); }); currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> { - drawPath(mr, 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20); + drawPath(mr.positions(), 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20); drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value); }); }); } - public static void drawPath(IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { + public static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); int fadeStart = fadeStart0 + startIndex; int fadeEnd = fadeEnd0 + startIndex; - List positions = path.positions(); for (int i = startIndex, next; i < positions.size() - 1; i = next) { BetterBlockPos start = positions.get(i); BetterBlockPos end = positions.get(next = i + 1); @@ -131,12 +135,12 @@ public final class PathRenderer implements IRenderer { int dirY = end.y - start.y; int dirZ = end.z - start.z; - while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && + /*while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && (dirX == positions.get(next + 1).x - end.x && dirY == positions.get(next + 1).y - end.y && dirZ == positions.get(next + 1).z - end.z)) { end = positions.get(++next); - } + }*/ if (fadeOut) { float alpha; From a602863426c32ace17de343c3c2306d5757bed81 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 12:49:31 -0700 Subject: [PATCH 002/276] better elytra --- src/main/java/baritone/Elytra.java | 56 +++++++++++++++++++++--------- 1 file changed, 40 insertions(+), 16 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index ac253868b..e50a098e6 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -78,6 +78,12 @@ public class Elytra extends Behavior implements Helper { baritone.getInputOverrideHandler().clearAllKeys(); if (ctx.player().isElytraFlying()) { + if (ctx.player().collidedHorizontally) { + logDirect("hbonk"); + } + if (ctx.player().collidedVertically) { + logDirect("vbonk"); + } Vec3d start = ctx.playerFeetAsVec(); boolean firework = firework(); sinceFirework++; @@ -97,12 +103,26 @@ public class Elytra extends Behavior implements Helper { boolean requireClear = relaxation == 0; int steps = relaxation < 2 ? Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps - for (int dy : heights) { - for (int i = Math.min(playerNear + 20, path.size()); i >= playerNear; i--) { + //int minStep = Math.max(0, playerNear - relaxation); + int minStep = playerNear; + for (int i = Math.min(playerNear + 20, path.size()); i >= minStep; i--) { + for (int dy : heights) { Vec3d dest = new Vec3d(path.get(i)).add(0, dy, 0); - if (dy != 0 && (i + lookahead >= path.size() || (!clearView(dest, new Vec3d(path.get(i + lookahead)).add(0, dy, 0)) || !clearView(dest, new Vec3d(path.get(i + lookahead)))))) { - // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position - continue; + if (dy != 0) { + if (i + lookahead >= path.size()) { + continue; + } + if (start.distanceTo(dest) < 40) { + if (!clearView(dest, new Vec3d(path.get(i + lookahead)).add(0, dy, 0)) || !clearView(dest, new Vec3d(path.get(i + lookahead)))) { + // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position + continue; + } + } else { + // but if it's far away, allow gaining altitude if we could lose it again by the time we get there + if (!clearView(dest, new Vec3d(path.get(i)))) { + continue; + } + } } if (requireClear ? isClear(start, dest) : clearView(start, dest)) { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); @@ -163,14 +183,17 @@ public class Elytra extends Behavior implements Helper { Vec3d totalMotion = new Vec3d(0, 0, 0); for (int i = 0; i < steps; i++) { stepped = step(stepped, pitch, good.getYaw(), firework); + Vec3d actualPositionPrevTick = ctx.playerFeetAsVec().add(totalMotion); totalMotion = totalMotion.add(stepped); - Vec3d actualPosition = ctx.playerFeetAsVec().add(totalMotion); - if (bsi.get0(MathHelper.floor(actualPosition.x), MathHelper.floor(actualPosition.y), MathHelper.floor(actualPosition.z)).getMaterial() != Material.AIR) { - continue outer; - } - if (bsi.get0(MathHelper.floor(actualPosition.x), MathHelper.floor(actualPosition.y) + 1, MathHelper.floor(actualPosition.z)).getMaterial() != Material.AIR) { - continue outer; + for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { + for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 0.8; y++) { + for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { + if (bsi.get0(x, y, z).getMaterial() != Material.AIR) { + continue outer; + } + } + } } } double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); @@ -193,6 +216,11 @@ public class Elytra extends Behavior implements Helper { float pitchBase = -MathHelper.cos(-rotationPitch * 0.017453292F); float pitchHeight = MathHelper.sin(-rotationPitch * 0.017453292F); Vec3d lookDirection = new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); + if (firework) { + motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; + motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; + motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; + } float pitchRadians = rotationPitch * 0.017453292F; double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); @@ -223,11 +251,7 @@ public class Elytra extends Behavior implements Helper { motionY *= 0.98; motionZ *= 0.99; //System.out.println(motionX + " " + motionY + " " + motionZ); - if (firework) { - motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; - motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; - motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; - } + return new Vec3d(motionX, motionY, motionZ); } From c48c2aa45cc0904ae8c994064ad226a4527ad163 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 13:57:21 -0700 Subject: [PATCH 003/276] allow even more desperate motion --- src/main/java/baritone/Elytra.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index e50a098e6..1534b211d 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -128,7 +128,7 @@ public class Elytra extends Behavior implements Helper { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); ctx.player().rotationYaw = rot.getYaw(); long a = System.currentTimeMillis(); - Float pitch = solvePitch(dest.subtract(start), steps); + Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); if (pitch == null) { continue; } @@ -164,7 +164,7 @@ public class Elytra extends Behavior implements Helper { return result == null || result.typeOfHit == RayTraceResult.Type.MISS; } - private Float solvePitch(Vec3d goalDirection, int steps) { + private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -177,8 +177,10 @@ public class Elytra extends Behavior implements Helper { double bestDot = Double.NEGATIVE_INFINITY; Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); BlockStateInterface bsi = new BlockStateInterface(ctx); + float minPitch = desperate ? -90 : Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); + float maxPitch = desperate ? 90 : Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); outer: - for (float pitch = Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); pitch < Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); pitch++) { + for (float pitch = minPitch; pitch <= maxPitch; pitch++) { Vec3d stepped = motion; Vec3d totalMotion = new Vec3d(0, 0, 0); for (int i = 0; i < steps; i++) { From 35a996e2b0406b9689bd1be4ee87464c3dd600aa Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 20:59:28 -0700 Subject: [PATCH 004/276] firework more often --- src/api/java/baritone/api/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 5463f3163..4fe0c6281 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -50,7 +50,7 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); - public final Setting elytraFireworkSpeed = new Setting<>(0.425); + public final Setting elytraFireworkSpeed = new Setting<>(0.6); /** * Allow Baritone to break blocks From b9054cdfc9cd8a043ae32c71a9d414f1b025f536 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 22:22:01 -0700 Subject: [PATCH 005/276] use more fireworks --- src/api/java/baritone/api/Settings.java | 2 ++ src/main/java/baritone/Elytra.java | 11 ++++++++--- src/main/java/baritone/utils/PathRenderer.java | 15 +++++++++++++++ 3 files changed, 25 insertions(+), 3 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 4fe0c6281..343fe823a 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -51,6 +51,8 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); public final Setting elytraFireworkSpeed = new Setting<>(0.6); + public final Setting wasteFireworks = new Setting<>(false); + public final Setting renderRaytraces = new Setting<>(false); /** * Allow Baritone to break blocks diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 1534b211d..2be7932ea 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -24,6 +24,7 @@ import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; +import com.mojang.realmsclient.util.Pair; import net.minecraft.block.material.Material; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.util.EnumHand; @@ -64,6 +65,9 @@ public class Elytra extends Behavior implements Helper { public int sinceFirework; public BlockPos goal; + + public List> lines = new ArrayList<>(); + protected Elytra(Baritone baritone) { super(baritone); } @@ -76,7 +80,7 @@ public class Elytra extends Behavior implements Helper { } fixNearPlayer(); baritone.getInputOverrideHandler().clearAllKeys(); - + lines.clear(); if (ctx.player().isElytraFlying()) { if (ctx.player().collidedHorizontally) { logDirect("hbonk"); @@ -89,7 +93,7 @@ public class Elytra extends Behavior implements Helper { sinceFirework++; if (!firework && sinceFirework > 10 - && ctx.player().posY < path.get(goingTo).y + 5 // don't firework if trying to descend + && (Baritone.settings().wasteFireworks.value && ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x, ctx.player().posY, path.get(goingTo).z)) > 5) // UGH!!!!!!! && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending ) { @@ -101,7 +105,7 @@ public class Elytra extends Behavior implements Helper { for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost boolean requireClear = relaxation == 0; - int steps = relaxation < 2 ? Baritone.settings().elytraSimulationTicks.value : 3; + int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; @@ -160,6 +164,7 @@ public class Elytra extends Behavior implements Helper { } private boolean clearView(Vec3d start, Vec3d dest) { + lines.add(Pair.of(start, dest)); RayTraceResult result = ctx.world().rayTraceBlocks(start, dest, true, false, true); return result == null || result.typeOfHit == RayTraceResult.Type.MISS; } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 828479a5d..f4e9317b3 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -17,6 +17,7 @@ package baritone.utils; +import baritone.Baritone; import baritone.Elytra; import baritone.api.BaritoneAPI; import baritone.api.event.events.RenderEvent; @@ -26,6 +27,7 @@ import baritone.api.utils.Helper; import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; +import com.mojang.realmsclient.util.Pair; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer; @@ -35,6 +37,7 @@ import net.minecraft.init.Blocks; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import java.awt.*; import java.util.Collection; @@ -107,6 +110,18 @@ public final class PathRenderer implements IRenderer { if (behavior.baritone.elytra.goal != null) { drawDankLitGoalBox(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); } + if (!behavior.baritone.elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { + IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + boolean orig = settings.renderPathAsLine.value; + settings.renderPathAsLine.value = true; + for (Pair line : behavior.baritone.elytra.lines) { + drawLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); + tessellator.draw(); + } + settings.renderPathAsLine.value = orig; + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } + // If there is a path calculation currently running, render the path calculation process behavior.getInProgress().ifPresent(currentlyRunning -> { From 4148b9818707841d1383c00d7e45a2a3de8e907c Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 22:22:49 -0700 Subject: [PATCH 006/276] typo --- src/main/java/baritone/Elytra.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 2be7932ea..14b64e547 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -93,7 +93,7 @@ public class Elytra extends Behavior implements Helper { sinceFirework++; if (!firework && sinceFirework > 10 - && (Baritone.settings().wasteFireworks.value && ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend + && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x, ctx.player().posY, path.get(goingTo).z)) > 5) // UGH!!!!!!! && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending ) { From 410cfcf21a664a7e23fbd08923de3cbbc320117d Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 11 Jun 2023 22:40:35 -0700 Subject: [PATCH 007/276] typo, fix crash at end of path --- src/main/java/baritone/Elytra.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 14b64e547..708f6621d 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -109,7 +109,7 @@ public class Elytra extends Behavior implements Helper { int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; - for (int i = Math.min(playerNear + 20, path.size()); i >= minStep; i--) { + for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { Vec3d dest = new Vec3d(path.get(i)).add(0, dy, 0); if (dy != 0) { From 44cd5dcd415bc01151797b97bbd5f591de46ac5f Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 12 Jun 2023 21:43:10 -0700 Subject: [PATCH 008/276] go around glowstone and nether fortresses --- src/main/java/baritone/Elytra.java | 154 +++++++++++++++++++++++++++-- 1 file changed, 145 insertions(+), 9 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 708f6621d..9607fbcdb 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -26,6 +26,7 @@ import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; import net.minecraft.block.material.Material; +import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; @@ -36,10 +37,7 @@ import net.minecraft.util.math.Vec3d; import java.io.DataInputStream; import java.io.File; import java.io.FileInputStream; -import java.util.ArrayList; -import java.util.HashMap; -import java.util.List; -import java.util.Map; +import java.util.*; public class Elytra extends Behavior implements Helper { @@ -65,6 +63,139 @@ public class Elytra extends Behavior implements Helper { public int sinceFirework; public BlockPos goal; + private void pathfindAroundObstacles() { + outer: + while (true) { + int rangeStartIncl = playerNear; + int rangeEndExcl = playerNear; + while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { + rangeEndExcl++; + } + if (rangeStartIncl >= rangeEndExcl) { + // not loaded yet? + return; + } + if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { + // we're in a wall + return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: + } + for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { + if (!clearView(pathAt(i), pathAt(i + 1))) { + // obstacle. where do we return to pathing? + // find the next valid segment + for (int j = i + 1; j < rangeEndExcl - 1; j++) { + if (clearView(pathAt(j), pathAt(j + 1))) { + // found it + // path from i to j + List newPath = simplePathfind(path.get(i), path.get(j)); + if (newPath == null) { + logDirect("no path"); + return; + } + path.subList(i + 1, j).clear(); + for (int k = newPath.size() - 1; k >= 0; k--) { + path.add(i + 1, newPath.get(k)); + } + logDirect("replaced path starting at " + path.get(i)); + removeBacktracks(); + break outer; // eventually "continue outer" + } + } + } + } + break; + } + } + + private int manhattanDist(BlockPos start, BlockPos dest) { + return Math.abs(start.getX() - dest.getX()) + Math.abs(start.getY() - dest.getY()) + Math.abs(start.getZ() - dest.getZ()); + } + + private class SearchNode { + BetterBlockPos pos; + int dist; + int heuristic; + SearchNode prev; + boolean canceled; + + public SearchNode(BetterBlockPos pos, int dist, int heuristic, SearchNode prev) { + this.pos = pos; + this.dist = dist; + this.heuristic = heuristic; + this.prev = prev; + } + } + + private List simplePathfind(BetterBlockPos start, BetterBlockPos dest) { + Map map = new HashMap<>(); + PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(node -> node.dist + node.heuristic)); + SearchNode origin = new SearchNode(start, 0, manhattanDist(start, dest) * 10, null); + map.put(start, origin); + queue.add(origin); + int count = 0; + while (!queue.isEmpty()) { + if (count++ > 10000) { + logDirect("oopsie"); + return null; + } + SearchNode node = queue.poll(); + if (node.canceled) { + continue; + } + if (node.pos.equals(dest)) { + List path = new ArrayList<>(); + while (node != null) { + path.add(node.pos); + node = node.prev; + } + Collections.reverse(path); + return simplify(path); + } + BetterBlockPos[] adjs = new BetterBlockPos[]{node.pos.up(), node.pos.down(), node.pos.north(), node.pos.south(), node.pos.east(), node.pos.west()}; + boolean nearAWall = false; + for (BetterBlockPos adj : adjs) { + if (!passable(ctx.world().getBlockState(adj))) { + nearAWall = true; + break; + } + } + for (BetterBlockPos adj : adjs) { + if (!passable(ctx.world().getBlockState(adj))) { + continue; + } + int cost = node.dist + (nearAWall ? 11 : 10); + if (map.containsKey(adj)) { + if (map.get(adj).dist <= cost) { + continue; + } + map.get(adj).canceled = true; + } + map.put(adj, new SearchNode(adj, cost, manhattanDist(adj, dest) * 10, node)); + queue.add(map.get(adj)); + } + } + return null; + } + + private List simplify(List path) { + List simplified = new ArrayList<>(path); + for (int i = 0; i < simplified.size() - 2; i++) { + BlockPos dir = simplified.get(i + 1).subtract(simplified.get(i)); + while (i + 2 < simplified.size()) { + if (simplified.get(i + 2).subtract(simplified.get(i + 1)).equals(dir)) { + simplified.remove(i + 1); + } else { + break; + } + } + } + return simplified; + } + + private Vec3d pathAt(int i) { + return new Vec3d(path.get(i).x + 0.5, path.get(i).y + 0.5, path.get(i).z + 0.5); + } + public List> lines = new ArrayList<>(); @@ -81,6 +212,7 @@ public class Elytra extends Behavior implements Helper { fixNearPlayer(); baritone.getInputOverrideHandler().clearAllKeys(); lines.clear(); + pathfindAroundObstacles(); if (ctx.player().isElytraFlying()) { if (ctx.player().collidedHorizontally) { logDirect("hbonk"); @@ -94,7 +226,7 @@ public class Elytra extends Behavior implements Helper { if (!firework && sinceFirework > 10 && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend - && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x, ctx.player().posY, path.get(goingTo).z)) > 5) // UGH!!!!!!! + && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending ) { logDirect("firework"); @@ -111,19 +243,19 @@ public class Elytra extends Behavior implements Helper { int minStep = playerNear; for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { - Vec3d dest = new Vec3d(path.get(i)).add(0, dy, 0); + Vec3d dest = pathAt(i).add(0, dy, 0); if (dy != 0) { if (i + lookahead >= path.size()) { continue; } if (start.distanceTo(dest) < 40) { - if (!clearView(dest, new Vec3d(path.get(i + lookahead)).add(0, dy, 0)) || !clearView(dest, new Vec3d(path.get(i + lookahead)))) { + if (!clearView(dest, pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, pathAt(i + lookahead))) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, new Vec3d(path.get(i)))) { + if (!clearView(dest, pathAt(i))) { continue; } } @@ -196,7 +328,7 @@ public class Elytra extends Behavior implements Helper { for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 0.8; y++) { for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { - if (bsi.get0(x, y, z).getMaterial() != Material.AIR) { + if (!passable(bsi.get0(x, y, z))) { continue outer; } } @@ -214,6 +346,10 @@ public class Elytra extends Behavior implements Helper { return bestPitch; } + private static boolean passable(IBlockState state) { + return state.getMaterial() == Material.AIR; + } + public static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { double motionX = motion.x; double motionY = motion.y; From 92509f07e9e3ec042ecbe3d93602f86645952694 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 12 Jun 2023 22:00:23 -0700 Subject: [PATCH 009/276] normal raytracer skips flowing lava (aka lavafalls) which is no good --- src/main/java/baritone/Elytra.java | 98 +++++++++++++++++++++++++++++- 1 file changed, 97 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 9607fbcdb..2f724c692 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -28,6 +28,8 @@ import com.mojang.realmsclient.util.Pair; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.init.Blocks; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -297,7 +299,7 @@ public class Elytra extends Behavior implements Helper { private boolean clearView(Vec3d start, Vec3d dest) { lines.add(Pair.of(start, dest)); - RayTraceResult result = ctx.world().rayTraceBlocks(start, dest, true, false, true); + RayTraceResult result = rayTraceBlocks(start, dest); return result == null || result.typeOfHit == RayTraceResult.Type.MISS; } @@ -438,4 +440,98 @@ public class Elytra extends Behavior implements Helper { } } } + + public RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { + int x1 = MathHelper.floor(end.x); + int y1 = MathHelper.floor(end.y); + int z1 = MathHelper.floor(end.z); + int x2 = MathHelper.floor(start.x); + int y2 = MathHelper.floor(start.y); + int z2 = MathHelper.floor(start.z); + BlockPos blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate)) { + return Blocks.DIRT.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + } + int steps = 200; + while (steps-- >= 0) { + if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { + return null; + } + if (x2 == x1 && y2 == y1 && z2 == z1) { + return null; + } + boolean hitX = true; + boolean hitY = true; + boolean hitZ = true; + double nextX = 999.0D; + double nextY = 999.0D; + double nextZ = 999.0D; + if (x1 > x2) { + nextX = (double) x2 + 1.0D; + } else if (x1 < x2) { + nextX = (double) x2 + 0.0D; + } else { + hitX = false; + } + if (y1 > y2) { + nextY = (double) y2 + 1.0D; + } else if (y1 < y2) { + nextY = (double) y2 + 0.0D; + } else { + hitY = false; + } + if (z1 > z2) { + nextZ = (double) z2 + 1.0D; + } else if (z1 < z2) { + nextZ = (double) z2 + 0.0D; + } else { + hitZ = false; + } + double stepX = 999.0D; + double stepY = 999.0D; + double stepZ = 999.0D; + double dirX = end.x - start.x; + double dirY = end.y - start.y; + double dirZ = end.z - start.z; + if (hitX) { + stepX = (nextX - start.x) / dirX; + } + if (hitY) { + stepY = (nextY - start.y) / dirY; + } + if (hitZ) { + stepZ = (nextZ - start.z) / dirZ; + } + if (stepX == -0.0D) { + stepX = -1.0E-4D; + } + if (stepY == -0.0D) { + stepY = -1.0E-4D; + } + if (stepZ == -0.0D) { + stepZ = -1.0E-4D; + } + EnumFacing dir; + if (stepX < stepY && stepX < stepZ) { + dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; + start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); + } else if (stepY < stepZ) { + dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; + start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); + } else { + dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; + start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); + } + x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); + y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); + z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); + blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate1)) { + return Blocks.DIRT.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + } + } + return null; + } } From 9672bd2c6d83bc9ae24ea607650e84804fd68c06 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 14 Jun 2023 16:08:34 -0500 Subject: [PATCH 010/276] Fix compile --- src/main/java/baritone/utils/PathRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 13a14f6dc..bec8937a4 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -108,14 +108,14 @@ public final class PathRenderer implements IRenderer { drawPath(Elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, Elytra.path.size())), 0, Color.RED, false, 0, 0); if (behavior.baritone.elytra.goal != null) { - drawDankLitGoalBox(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); + drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); } if (!behavior.baritone.elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); boolean orig = settings.renderPathAsLine.value; settings.renderPathAsLine.value = true; for (Pair line : behavior.baritone.elytra.lines) { - drawLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); + emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); tessellator.draw(); } settings.renderPathAsLine.value = orig; From bde0c620ad6270cbd363140ab6be8aa49370644d Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 14 Jun 2023 16:11:11 -0500 Subject: [PATCH 011/276] Allow freeLook when using elytra --- .../api/event/events/RotationMoveEvent.java | 38 ++++++++- .../launch/mixins/MixinEntityLivingBase.java | 85 +++++++++++++++---- .../launch/mixins/MixinEntityPlayerSP.java | 16 ---- .../launch/mixins/MixinMinecraft.java | 15 ++++ src/main/java/baritone/Elytra.java | 6 +- .../java/baritone/behavior/LookBehavior.java | 1 + 6 files changed, 121 insertions(+), 40 deletions(-) diff --git a/src/api/java/baritone/api/event/events/RotationMoveEvent.java b/src/api/java/baritone/api/event/events/RotationMoveEvent.java index 109061c7e..a2ab17ed6 100644 --- a/src/api/java/baritone/api/event/events/RotationMoveEvent.java +++ b/src/api/java/baritone/api/event/events/RotationMoveEvent.java @@ -17,6 +17,7 @@ package baritone.api.event.events; +import baritone.api.utils.Rotation; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -31,14 +32,27 @@ public final class RotationMoveEvent { */ private final Type type; + private final Rotation original; + /** * The yaw rotation */ private float yaw; - public RotationMoveEvent(Type type, float yaw) { + /** + * The pitch rotation + */ + private float pitch; + + public RotationMoveEvent(Type type, float yaw, float pitch) { this.type = type; + this.original = new Rotation(yaw, pitch); this.yaw = yaw; + this.pitch = pitch; + } + + public Rotation getOriginal() { + return this.original; } /** @@ -46,21 +60,37 @@ public final class RotationMoveEvent { * * @param yaw Yaw rotation */ - public final void setYaw(float yaw) { + public void setYaw(float yaw) { this.yaw = yaw; } /** * @return The yaw rotation */ - public final float getYaw() { + public float getYaw() { return this.yaw; } + /** + * Set the pitch movement rotation + * + * @param pitch Pitch rotation + */ + public void setPitch(float pitch) { + this.pitch = pitch; + } + + /** + * @return The pitch rotation + */ + public float getPitch() { + return pitch; + } + /** * @return The type of the event */ - public final Type getType() { + public Type getType() { return this.type; } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index 0fd2436c9..f8544dd2f 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -25,11 +25,14 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; 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 java.util.Optional; + import static org.spongepowered.asm.lib.Opcodes.GETFIELD; /** @@ -42,11 +45,14 @@ public abstract class MixinEntityLivingBase extends Entity { /** * Event called to override the movement direction when jumping */ + @Unique private RotationMoveEvent jumpRotationEvent; - public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) { + @Unique + private RotationMoveEvent elytraRotationEvent; + + public MixinEntityLivingBase(World worldIn) { super(worldIn); - this.jumpRotationEvent = jumpRotationEvent; } @Inject( @@ -54,14 +60,10 @@ public abstract class MixinEntityLivingBase extends Entity { at = @At("HEAD") ) private void preMoveRelative(CallbackInfo ci) { - // noinspection ConstantConditions - if (EntityPlayerSP.class.isInstance(this)) { - IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this); - if (baritone != null) { - this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw); - baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent); - } - } + this.getBaritone().ifPresent(baritone -> { + this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw, this.rotationPitch); + baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent); + }); } @Redirect( @@ -79,6 +81,38 @@ public abstract class MixinEntityLivingBase extends Entity { return self.rotationYaw; } + @Inject( + method = "travel", + at = @At( + value = "INVOKE", + target = "net/minecraft/entity/EntityLivingBase.getLookVec()Lnet/minecraft/util/math/Vec3d;" + ) + ) + private void onPreElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) { + this.getBaritone().ifPresent(baritone -> { + this.elytraRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch); + baritone.getGameEventHandler().onPlayerRotationMove(this.elytraRotationEvent); + this.rotationYaw = this.elytraRotationEvent.getYaw(); + this.rotationPitch = this.elytraRotationEvent.getPitch(); + }); + } + + @Inject( + method = "travel", + at = @At( + value = "INVOKE", + target = "net/minecraft/entity/EntityLivingBase.move(Lnet/minecraft/entity/MoverType;DDD)V", + shift = At.Shift.AFTER + ) + ) + private void onPostElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) { + if (this.elytraRotationEvent != null) { + this.rotationYaw = this.elytraRotationEvent.getOriginal().getYaw(); + this.rotationPitch = this.elytraRotationEvent.getOriginal().getPitch(); + this.elytraRotationEvent = null; + } + } + @Redirect( method = "travel", at = @At( @@ -86,17 +120,32 @@ public abstract class MixinEntityLivingBase extends Entity { target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V" ) ) - private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) { - // noinspection ConstantConditions - if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) { + private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) { + Optional baritone = this.getBaritone(); + if (!baritone.isPresent()) { moveRelative(strafe, up, forward, friction); return; } - RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw); - BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent); - float originalYaw = this.rotationYaw; - this.rotationYaw = motionUpdateRotationEvent.getYaw(); + + RotationMoveEvent event = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch); + baritone.get().getGameEventHandler().onPlayerRotationMove(event); + + this.rotationYaw = event.getYaw(); + this.rotationPitch = event.getPitch(); + this.moveRelative(strafe, up, forward, friction); - this.rotationYaw = originalYaw; + + this.rotationYaw = event.getOriginal().getYaw(); + this.rotationPitch = event.getOriginal().getPitch(); + } + + @Unique + private Optional getBaritone() { + // noinspection ConstantConditions + if (EntityPlayerSP.class.isInstance(this)) { + return Optional.ofNullable(BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this)); + } else { + return Optional.empty(); + } } } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java index 7c1225b9b..3f34c0e77 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java @@ -73,22 +73,6 @@ public class MixinEntityPlayerSP { } } - @Inject( - method = "onUpdate", - at = @At( - value = "INVOKE", - target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V", - shift = At.Shift.BY, - by = 2 - ) - ) - private void onPostUpdate(CallbackInfo ci) { - IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this); - if (baritone != null) { - baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST)); - } - } - @Redirect( method = "onLivingUpdate", at = @At( diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index 097c72905..edc1e3fcc 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -20,6 +20,7 @@ package baritone.launch.mixins; import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.event.events.BlockInteractEvent; +import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.TickEvent; import baritone.api.event.events.WorldEvent; import baritone.api.event.events.type.EventState; @@ -84,7 +85,21 @@ public class MixinMinecraft { baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type)); } + } + @Inject( + method = "runTick", + at = @At( + value = "INVOKE", + target = "net/minecraft/client/multiplayer/WorldClient.updateEntities()V", + shift = At.Shift.AFTER + ) + ) + private void postUpdateEntities(CallbackInfo ci) { + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(this.player); + if (baritone != null) { + baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST)); + } } @Inject( diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 2f724c692..35ea70b95 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -264,17 +264,19 @@ public class Elytra extends Behavior implements Helper { } if (requireClear ? isClear(start, dest) : clearView(start, dest)) { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); - ctx.player().rotationYaw = rot.getYaw(); +// ctx.player().rotationYaw = rot.getYaw(); long a = System.currentTimeMillis(); Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); if (pitch == null) { + baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), ctx.playerRotations().getPitch()), false); continue; } long b = System.currentTimeMillis(); - ctx.player().rotationPitch = pitch; +// ctx.player().rotationPitch = pitch; System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); goingTo = i; goal = path.get(i).add(0, dy, 0); + baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); return; } } diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 99e496e6f..d9a06b086 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -149,6 +149,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null) { event.setYaw(this.target.rotation.getYaw()); + event.setPitch(this.target.rotation.getPitch()); } } From 91bf7d726b30add13deaf14094a15b58f93c8b70 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 14 Jun 2023 16:32:56 -0500 Subject: [PATCH 012/276] Un-scuff and add setting --- src/api/java/baritone/api/Settings.java | 1 + .../java/baritone/launch/mixins/MixinMinecraft.java | 2 ++ src/main/java/baritone/Elytra.java | 4 +--- src/main/java/baritone/behavior/LookBehavior.java | 12 ++++++++---- 4 files changed, 12 insertions(+), 7 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 30506fd08..f5cf3c77a 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -53,6 +53,7 @@ public final class Settings { public final Setting elytraFireworkSpeed = new Setting<>(0.6); public final Setting wasteFireworks = new Setting<>(false); public final Setting renderRaytraces = new Setting<>(false); + public final Setting elytraFreeLook = new Setting<>(false); /** * Allow Baritone to break blocks diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index edc1e3fcc..19d4741ca 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -98,6 +98,8 @@ public class MixinMinecraft { private void postUpdateEntities(CallbackInfo ci) { IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(this.player); if (baritone != null) { + // Intentionally call this after all entities have been updated. That way, any modification to rotations + // can be recognized by other entity code. (Fireworks and Pigs, for example) baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST)); } } diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 35ea70b95..b8a05010b 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -48,7 +48,7 @@ public class Elytra extends Behavior implements Helper { static { try { - DataInputStream in = new DataInputStream(new FileInputStream(new File("/Users/leijurv/Dropbox/nether-pathfinder/build/test"))); + DataInputStream in = new DataInputStream(new FileInputStream(new File("E:/Brady/Documents/Java/baritone/test"))); int count = in.readInt(); System.out.println("Count: " + count); for (int i = 0; i < count; i++) { @@ -264,7 +264,6 @@ public class Elytra extends Behavior implements Helper { } if (requireClear ? isClear(start, dest) : clearView(start, dest)) { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); -// ctx.player().rotationYaw = rot.getYaw(); long a = System.currentTimeMillis(); Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); if (pitch == null) { @@ -272,7 +271,6 @@ public class Elytra extends Behavior implements Helper { continue; } long b = System.currentTimeMillis(); -// ctx.player().rotationPitch = pitch; System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); goingTo = i; goal = path.get(i).add(0, dy, 0); diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index d9a06b086..1b85ac7e3 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -56,7 +56,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { @Override public void updateTarget(Rotation rotation, boolean blockInteract) { - this.target = new Target(rotation, blockInteract); + this.target = new Target(rotation, Target.Mode.resolve(ctx, blockInteract)); } @Override @@ -186,9 +186,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior { public final Rotation rotation; public final Mode mode; - public Target(Rotation rotation, boolean blockInteract) { + public Target(Rotation rotation, Mode mode) { this.rotation = rotation; - this.mode = Mode.resolve(blockInteract); + this.mode = mode; } enum Mode { @@ -207,12 +207,16 @@ public final class LookBehavior extends Behavior implements ILookBehavior { */ NONE; - static Mode resolve(boolean blockInteract) { + static Mode resolve(IPlayerContext ctx, boolean blockInteract) { final Settings settings = Baritone.settings(); final boolean antiCheat = settings.antiCheatCompatibility.value; final boolean blockFreeLook = settings.blockFreeLook.value; final boolean freeLook = settings.freeLook.value; + if (ctx.player().isElytraFlying()) { + return settings.elytraFreeLook.value ? SERVER : CLIENT; + } + if (!freeLook && !blockFreeLook) return CLIENT; if (!blockFreeLook && blockInteract) return CLIENT; From 06d11c187417374103a6e4b0ed162e1dfbfe4083 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 14 Jun 2023 16:59:03 -0500 Subject: [PATCH 013/276] Revert file path --- src/main/java/baritone/Elytra.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index b8a05010b..6d12e9f0d 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -48,7 +48,7 @@ public class Elytra extends Behavior implements Helper { static { try { - DataInputStream in = new DataInputStream(new FileInputStream(new File("E:/Brady/Documents/Java/baritone/test"))); + DataInputStream in = new DataInputStream(new FileInputStream(new File("/Users/leijurv/Dropbox/nether-pathfinder/build/test"))); int count = in.readInt(); System.out.println("Count: " + count); for (int i = 0; i < count; i++) { From 8df67786415d5f0eb8f4fb6802bf0b8a385d20c9 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 15 Jun 2023 00:32:26 -0700 Subject: [PATCH 014/276] sort of integrated nether pathfinder --- build.gradle | 18 +++--- src/main/java/baritone/Elytra.java | 28 +++------ .../command/defaults/DefaultCommands.java | 3 +- .../command/defaults/ElytraCommand.java | 61 +++++++++++++++++++ .../java/baritone/utils/PathRenderer.java | 3 +- 5 files changed, 84 insertions(+), 29 deletions(-) create mode 100644 src/main/java/baritone/command/defaults/ElytraCommand.java diff --git a/build.gradle b/build.gradle index 0ce05058c..7909911be 100755 --- a/build.gradle +++ b/build.gradle @@ -100,7 +100,9 @@ dependencies { exclude module: 'commons-io' exclude module: 'log4j-core' } + runtime launchCompile('dev.babbaj:nether-pathfinder:1.3') testImplementation 'junit:junit:4.12' + implementation 'dev.babbaj:nether-pathfinder:1.3' } mixin { @@ -153,16 +155,16 @@ install { def jarSAForgeName = String.format("%s-standalone-forge-%s", rootProject.name, version.toString()) artifacts { - archives file("$buildDir/libs/"+jarApiName+".jar") - archives file("$buildDir/libs/"+jarApiForgeName+".jar") - archives file("$buildDir/libs/"+jarSAName+".jar") - archives file("$buildDir/libs/"+jarSAForgeName+".jar") + archives file("$buildDir/libs/" + jarApiName + ".jar") + archives file("$buildDir/libs/" + jarApiForgeName + ".jar") + archives file("$buildDir/libs/" + jarSAName + ".jar") + archives file("$buildDir/libs/" + jarSAForgeName + ".jar") } repositories.mavenInstaller { - addFilter('api') { artifact, file -> artifact.name == "baritone-api" } - addFilter('api-forge') { artifact, file -> artifact.name == "baritone-api-forge" } - addFilter('standalone') { artifact, file -> artifact.name == "baritone-standalone" } - addFilter('standalone-forge') { artifact, file -> artifact.name == "baritone-standalone-forge" } + addFilter('api') { artifact, file -> artifact.name == "baritone-api" } + addFilter('api-forge') { artifact, file -> artifact.name == "baritone-api-forge" } + addFilter('standalone') { artifact, file -> artifact.name == "baritone-standalone" } + addFilter('standalone-forge') { artifact, file -> artifact.name == "baritone-standalone-forge" } } } diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 2f724c692..5a8cae634 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -25,6 +25,7 @@ import baritone.api.utils.RotationUtils; import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; +import dev.babbaj.pathfinder.NetherPathfinder; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -36,28 +37,16 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import java.io.DataInputStream; -import java.io.File; -import java.io.FileInputStream; import java.util.*; +import java.util.stream.Collectors; public class Elytra extends Behavior implements Helper { - public static List path = new ArrayList<>(); + public List path = new ArrayList<>(); - static { - - try { - DataInputStream in = new DataInputStream(new FileInputStream(new File("/Users/leijurv/Dropbox/nether-pathfinder/build/test"))); - int count = in.readInt(); - System.out.println("Count: " + count); - for (int i = 0; i < count; i++) { - path.add(new BetterBlockPos((int) in.readDouble(), (int) in.readDouble(), (int) in.readDouble())); - } - removeBacktracks(); - } catch (Exception e) { - throw new RuntimeException(e); - } + public void path(BlockPos destination) { + path = Arrays.stream(NetherPathfinder.pathFind(146008555100680L, false, false, ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, destination.getX(), destination.getY(), destination.getZ())).mapToObj(BlockPos::fromLong).map(BetterBlockPos::new).collect(Collectors.toList()); + removeBacktracks(); } public int playerNear; @@ -211,6 +200,9 @@ public class Elytra extends Behavior implements Helper { if (event.getType() == TickEvent.Type.OUT) { return; } + if (path.isEmpty()) { + return; + } fixNearPlayer(); baritone.getInputOverrideHandler().clearAllKeys(); lines.clear(); @@ -425,7 +417,7 @@ public class Elytra extends Behavior implements Helper { //System.out.println(playerNear); } - public static void removeBacktracks() { + public void removeBacktracks() { Map positionFirstSeen = new HashMap<>(); for (int i = 0; i < path.size(); i++) { BetterBlockPos pos = path.get(i); diff --git a/src/main/java/baritone/command/defaults/DefaultCommands.java b/src/main/java/baritone/command/defaults/DefaultCommands.java index 901fda713..b8e3c924b 100644 --- a/src/main/java/baritone/command/defaults/DefaultCommands.java +++ b/src/main/java/baritone/command/defaults/DefaultCommands.java @@ -66,7 +66,8 @@ public final class DefaultCommands { new WaypointsCommand(baritone), new CommandAlias(baritone, "sethome", "Sets your home waypoint", "waypoints save home"), new CommandAlias(baritone, "home", "Path to your home waypoint", "waypoints goto home"), - new SelCommand(baritone) + new SelCommand(baritone), + new ElytraCommand(baritone) )); ExecutionControlCommands prc = new ExecutionControlCommands(baritone); commands.add(prc.pauseCommand); diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java new file mode 100644 index 000000000..2d2e3f0ee --- /dev/null +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -0,0 +1,61 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.command.defaults; + +import baritone.Baritone; +import baritone.api.IBaritone; +import baritone.api.command.Command; +import baritone.api.command.argument.IArgConsumer; +import baritone.api.command.exception.CommandException; +import baritone.api.pathing.goals.GoalXZ; +import baritone.api.process.ICustomGoalProcess; +import net.minecraft.util.math.BlockPos; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Stream; + +public class ElytraCommand extends Command { + + public ElytraCommand(IBaritone baritone) { + super(baritone, "elytra"); + } + + @Override + public void execute(String label, IArgConsumer args) throws CommandException { + ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); + args.requireMax(0); + GoalXZ goal = (GoalXZ) customGoalProcess.getGoal(); + ((Baritone) baritone).elytra.path(new BlockPos(goal.getX(), 64, goal.getZ())); + } + + @Override + public Stream tabComplete(String label, IArgConsumer args) throws CommandException { + return Stream.empty(); + } + + @Override + public String getShortDesc() { + return "elytra time"; + } + + @Override + public List getLongDesc() { + return Arrays.asList(); + } +} diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index bec8937a4..df0d5b0ca 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -18,7 +18,6 @@ package baritone.utils; import baritone.Baritone; -import baritone.Elytra; import baritone.api.BaritoneAPI; import baritone.api.event.events.RenderEvent; import baritone.api.pathing.goals.*; @@ -106,7 +105,7 @@ public final class PathRenderer implements IRenderer { drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); } - drawPath(Elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, Elytra.path.size())), 0, Color.RED, false, 0, 0); + drawPath(behavior.baritone.elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, behavior.baritone.elytra.path.size())), 0, Color.RED, false, 0, 0); if (behavior.baritone.elytra.goal != null) { drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); } From fe8ec19b6d8e321a08d0300be5b7a25ab4be7226 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 15 Jun 2023 22:07:44 -0500 Subject: [PATCH 015/276] Fix `renderRaytraces` crash --- src/main/java/baritone/utils/PathRenderer.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index df0d5b0ca..15ae73696 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -115,7 +115,6 @@ public final class PathRenderer implements IRenderer { settings.renderPathAsLine.value = true; for (Pair line : behavior.baritone.elytra.lines) { emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); - tessellator.draw(); } settings.renderPathAsLine.value = orig; IRenderer.endLines(settings.renderPathIgnoreDepth.value); From a9e9cd978df262403c3a7571ca15187aa0a21bbe Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 15 Jun 2023 22:59:01 -0500 Subject: [PATCH 016/276] cancel lol --- src/main/java/baritone/Elytra.java | 8 ++++++++ .../command/defaults/ExecutionControlCommands.java | 2 ++ .../baritone/command/defaults/ForceCancelCommand.java | 2 ++ 3 files changed, 12 insertions(+) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 082344f6c..f2d28b0f2 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -54,6 +54,14 @@ public class Elytra extends Behavior implements Helper { public int sinceFirework; public BlockPos goal; + public void cancel() { + this.path.clear(); + this.goal = null; + this.playerNear = 0; + this.goingTo = 0; + this.sinceFirework = 0; + } + private void pathfindAroundObstacles() { outer: while (true) { diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index 6f6293ccd..66b2d156d 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; @@ -180,6 +181,7 @@ public class ExecutionControlCommands { paused[0] = false; } baritone.getPathingBehavior().cancelEverything(); + ((Baritone) baritone).elytra.cancel(); logDirect("ok canceled"); } diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index 513d61bcb..3a54ce69e 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.behavior.IPathingBehavior; import baritone.api.command.Command; @@ -39,6 +40,7 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); + ((Baritone) baritone).elytra.cancel(); logDirect("ok force canceled"); } From e01093eb9aa19cff9bed1094f0f9305a82310de3 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Thu, 15 Jun 2023 20:59:08 -0700 Subject: [PATCH 017/276] build with pathfinder --- .../baritone/gradle/task/ProguardTask.java | 30 +++++++++++-------- .../baritone/gradle/util/Determinizer.java | 15 ++++++---- scripts/proguard.pro | 2 +- src/main/java/baritone/Elytra.java | 2 ++ 4 files changed, 31 insertions(+), 18 deletions(-) diff --git a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java index 1789435f7..1c329ee2c 100644 --- a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java +++ b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java @@ -68,17 +68,18 @@ public class ProguardTask extends BaritoneGradleTask { private List requiredLibraries; private File mixin; + private File pathfinder; @TaskAction protected void exec() throws Exception { super.verifyArtifacts(); // "Haha brady why don't you make separate tasks" - processArtifact(); downloadProguard(); extractProguard(); generateConfigs(); acquireDependencies(); + processArtifact(); proguardApi(); proguardStandalone(); cleanup(); @@ -89,7 +90,7 @@ public class ProguardTask extends BaritoneGradleTask { Files.delete(this.artifactUnoptimizedPath); } - Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Optional.empty()); + Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Arrays.asList(pathfinder), false); } private void downloadProguard() throws Exception { @@ -114,8 +115,7 @@ public class ProguardTask extends BaritoneGradleTask { try { path = findJavaPathByGradleConfig(); if (path != null) return path; - } - catch (Exception ex) { + } catch (Exception ex) { System.err.println("Unable to find java by javaCompile options"); ex.printStackTrace(); } @@ -123,8 +123,7 @@ public class ProguardTask extends BaritoneGradleTask { try { path = findJavaByJavaHome(); if (path != null) return path; - } - catch(Exception ex) { + } catch (Exception ex) { System.err.println("Unable to find java by JAVA_HOME"); ex.printStackTrace(); } @@ -132,7 +131,7 @@ public class ProguardTask extends BaritoneGradleTask { path = findJavaByGradleCurrentRuntime(); if (path != null) return path; - + throw new Exception("Unable to find java to determine ProGuard libraryjars. Please specify forkOptions.executable in javaCompile," + " JAVA_HOME environment variable, or make sure to run Gradle with the correct JDK (a v1.8 only)"); } @@ -281,6 +280,9 @@ public class ProguardTask extends BaritoneGradleTask { if (lib.contains("mixin")) { mixin = file; } + if (lib.contains("nether-pathfinder")) { + pathfinder = file; + } Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING); } } @@ -288,6 +290,9 @@ public class ProguardTask extends BaritoneGradleTask { if (mixin == null) { throw new IllegalStateException("Unable to find mixin jar"); } + if (pathfinder == null) { + throw new IllegalStateException("Unable to find pathfinder jar"); + } } // a bunch of epic stuff to get the path to the cached jar @@ -375,14 +380,14 @@ public class ProguardTask extends BaritoneGradleTask { private void proguardApi() throws Exception { runProguard(getTemporaryFile(PROGUARD_API_CONFIG)); - Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Optional.empty()); - Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Optional.of(mixin)); + Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Arrays.asList(pathfinder), false); + Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Arrays.asList(pathfinder, mixin), true); } private void proguardStandalone() throws Exception { runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG)); - Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Optional.empty()); - Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Optional.of(mixin)); + Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Arrays.asList(pathfinder), false); + Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Arrays.asList(pathfinder, mixin), true); } private void cleanup() { @@ -409,7 +414,7 @@ public class ProguardTask extends BaritoneGradleTask { Path workingDirectory = getTemporaryFile(""); Path proguardJar = workingDirectory.relativize(getTemporaryFile(PROGUARD_JAR)); config = workingDirectory.relativize(config); - + // Honestly, if you still have spaces in your path at this point, you're SOL. Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString()) @@ -423,6 +428,7 @@ public class ProguardTask extends BaritoneGradleTask { // Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception int exitCode = p.waitFor(); if (exitCode != 0) { + Thread.sleep(1000); throw new IllegalStateException("Proguard exited with code " + exitCode); } } diff --git a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java index d9f475a5c..40d17ef03 100644 --- a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java +++ b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java @@ -22,7 +22,10 @@ import com.google.gson.stream.JsonReader; import com.google.gson.stream.JsonWriter; import java.io.*; -import java.util.*; +import java.util.ArrayList; +import java.util.Comparator; +import java.util.List; +import java.util.Map; import java.util.jar.JarEntry; import java.util.jar.JarFile; import java.util.jar.JarOutputStream; @@ -36,10 +39,11 @@ import java.util.stream.Collectors; */ public class Determinizer { - public static void determinize(String inputPath, String outputPath, Optional toInclude) throws IOException { + public static void determinize(String inputPath, String outputPath, List toInclude, boolean doForgeReplacementOfMetaInf) throws IOException { System.out.println("Running Determinizer"); System.out.println(" Input path: " + inputPath); System.out.println(" Output path: " + outputPath); + System.out.println(" Shade: " + toInclude); try ( JarFile jarFile = new JarFile(new File(inputPath)); @@ -63,7 +67,7 @@ public class Determinizer { if (entry.getName().endsWith(".refmap.json")) { JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject(); jos.write(writeSorted(object).getBytes()); - } else if (entry.getName().equals("META-INF/MANIFEST.MF") && toInclude.isPresent()) { // only replace for forge jar + } else if (entry.getName().equals("META-INF/MANIFEST.MF") && doForgeReplacementOfMetaInf) { // only replace for forge jar ByteArrayOutputStream cancer = new ByteArrayOutputStream(); copy(jarFile.getInputStream(entry), cancer); String manifest = new String(cancer.toByteArray()); @@ -76,8 +80,8 @@ public class Determinizer { copy(jarFile.getInputStream(entry), jos); } } - if (toInclude.isPresent()) { - try (JarFile mixin = new JarFile(toInclude.get())) { + for (File file : toInclude) { + try (JarFile mixin = new JarFile(file)) { for (JarEntry entry : mixin.stream().sorted(Comparator.comparing(JarEntry::getName)).collect(Collectors.toList())) { if (entry.getName().startsWith("META-INF") && !entry.getName().startsWith("META-INF/services")) { continue; @@ -89,6 +93,7 @@ public class Determinizer { } jos.finish(); } + System.out.println("Done with determinizer"); } private static void copy(InputStream is, OutputStream os) throws IOException { diff --git a/scripts/proguard.pro b/scripts/proguard.pro index cc3130081..858494778 100644 --- a/scripts/proguard.pro +++ b/scripts/proguard.pro @@ -94,7 +94,7 @@ -libraryjars 'tempLibraries/mixin-0.7.11-SNAPSHOT.jar' -libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist? - +-libraryjars 'tempLibraries/nether-pathfinder-.jar' # Keep - Applications. Keep all application classes, along with their 'main' diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index f2d28b0f2..caa819fb4 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -45,6 +45,8 @@ public class Elytra extends Behavior implements Helper { public List path = new ArrayList<>(); public void path(BlockPos destination) { + playerNear = 0; + goingTo = 0; path = Arrays.stream(NetherPathfinder.pathFind(146008555100680L, false, false, ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, destination.getX(), destination.getY(), destination.getZ())).mapToObj(BlockPos::fromLong).map(BetterBlockPos::new).collect(Collectors.toList()); removeBacktracks(); } From 8c124163483755aa2ad350e2822558077a51590d Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 18:59:57 -0500 Subject: [PATCH 018/276] Use new nether-pathfinder API Doesn't stitch segments, just partially functional --- build.gradle | 9 +++- src/main/java/baritone/Elytra.java | 44 +++++++++++++++++-- .../command/defaults/ElytraCommand.java | 2 +- 3 files changed, 48 insertions(+), 7 deletions(-) diff --git a/build.gradle b/build.gradle index 7909911be..8e952df73 100755 --- a/build.gradle +++ b/build.gradle @@ -88,6 +88,11 @@ repositories { name = 'impactdevelopment-repo' url = 'https://impactdevelopment.github.io/maven/' } + + maven { + name = 'babbaj-repo' + url = 'https://babbaj.github.io/maven/' + } } dependencies { @@ -100,9 +105,9 @@ dependencies { exclude module: 'commons-io' exclude module: 'log4j-core' } - runtime launchCompile('dev.babbaj:nether-pathfinder:1.3') + runtime launchCompile('dev.babbaj:nether-pathfinder:0.2') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:1.3' + implementation 'dev.babbaj:nether-pathfinder:0.2' } mixin { diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index caa819fb4..69fee5450 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -26,6 +26,7 @@ import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; import dev.babbaj.pathfinder.NetherPathfinder; +import dev.babbaj.pathfinder.PathSegment; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -44,13 +45,48 @@ public class Elytra extends Behavior implements Helper { public List path = new ArrayList<>(); - public void path(BlockPos destination) { - playerNear = 0; - goingTo = 0; - path = Arrays.stream(NetherPathfinder.pathFind(146008555100680L, false, false, ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, destination.getX(), destination.getY(), destination.getZ())).mapToObj(BlockPos::fromLong).map(BetterBlockPos::new).collect(Collectors.toList()); + private long context; + private Long seed; + + public void path(long seed, BlockPos destination) { + this.setupContext(seed); + + this.playerNear = 0; + this.goingTo = 0; + + final PathSegment segment = NetherPathfinder.pathFind( + this.context, + ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, + destination.getX(), destination.getY(), destination.getZ() + ); + + this.path = Arrays.stream(segment.packed) + .mapToObj(BlockPos::fromLong) + .map(BetterBlockPos::new) + .collect(Collectors.toList()); + + if (!segment.finished) { + logDirect("segment not finished. path incomplete"); + } + removeBacktracks(); } + private void setupContext(long seed) { + if (!Objects.equals(this.seed, seed)) { + this.freeContext(); + this.context = NetherPathfinder.newContext(seed); + } + this.seed = seed; + } + + private void freeContext() { + if (this.context != 0) { + NetherPathfinder.freeContext(this.context); + } + this.context = 0; + } + public int playerNear; public int goingTo; public int sinceFirework; diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 2d2e3f0ee..99ddaa8e4 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -41,7 +41,7 @@ public class ElytraCommand extends Command { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); GoalXZ goal = (GoalXZ) customGoalProcess.getGoal(); - ((Baritone) baritone).elytra.path(new BlockPos(goal.getX(), 64, goal.getZ())); + ((Baritone) baritone).elytra.path(146008555100680L, new BlockPos(goal.getX(), 64, goal.getZ())); } @Override From 53a0069704b115657bfd470940d443544c61ca03 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 19:54:37 -0500 Subject: [PATCH 019/276] Remove Java pathfinder in preparation for `insertChunkData` --- src/main/java/baritone/Elytra.java | 166 ++++------------------------- 1 file changed, 18 insertions(+), 148 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 69fee5450..77a09f369 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -48,6 +48,16 @@ public class Elytra extends Behavior implements Helper { private long context; private Long seed; + public int playerNear; + public int goingTo; + public int sinceFirework; + public BlockPos goal; + public List> lines = new ArrayList<>(); + + protected Elytra(Baritone baritone) { + super(baritone); + } + public void path(long seed, BlockPos destination) { this.setupContext(seed); @@ -87,11 +97,6 @@ public class Elytra extends Behavior implements Helper { this.context = 0; } - public int playerNear; - public int goingTo; - public int sinceFirework; - public BlockPos goal; - public void cancel() { this.path.clear(); this.goal = null; @@ -100,147 +105,10 @@ public class Elytra extends Behavior implements Helper { this.sinceFirework = 0; } - private void pathfindAroundObstacles() { - outer: - while (true) { - int rangeStartIncl = playerNear; - int rangeEndExcl = playerNear; - while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { - rangeEndExcl++; - } - if (rangeStartIncl >= rangeEndExcl) { - // not loaded yet? - return; - } - if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { - // we're in a wall - return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: - } - for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!clearView(pathAt(i), pathAt(i + 1))) { - // obstacle. where do we return to pathing? - // find the next valid segment - for (int j = i + 1; j < rangeEndExcl - 1; j++) { - if (clearView(pathAt(j), pathAt(j + 1))) { - // found it - // path from i to j - List newPath = simplePathfind(path.get(i), path.get(j)); - if (newPath == null) { - logDirect("no path"); - return; - } - path.subList(i + 1, j).clear(); - for (int k = newPath.size() - 1; k >= 0; k--) { - path.add(i + 1, newPath.get(k)); - } - logDirect("replaced path starting at " + path.get(i)); - removeBacktracks(); - break outer; // eventually "continue outer" - } - } - } - } - break; - } - } - - private int manhattanDist(BlockPos start, BlockPos dest) { - return Math.abs(start.getX() - dest.getX()) + Math.abs(start.getY() - dest.getY()) + Math.abs(start.getZ() - dest.getZ()); - } - - private class SearchNode { - BetterBlockPos pos; - int dist; - int heuristic; - SearchNode prev; - boolean canceled; - - public SearchNode(BetterBlockPos pos, int dist, int heuristic, SearchNode prev) { - this.pos = pos; - this.dist = dist; - this.heuristic = heuristic; - this.prev = prev; - } - } - - private List simplePathfind(BetterBlockPos start, BetterBlockPos dest) { - Map map = new HashMap<>(); - PriorityQueue queue = new PriorityQueue<>(Comparator.comparingInt(node -> node.dist + node.heuristic)); - SearchNode origin = new SearchNode(start, 0, manhattanDist(start, dest) * 10, null); - map.put(start, origin); - queue.add(origin); - int count = 0; - while (!queue.isEmpty()) { - if (count++ > 10000) { - logDirect("oopsie"); - return null; - } - SearchNode node = queue.poll(); - if (node.canceled) { - continue; - } - if (node.pos.equals(dest)) { - List path = new ArrayList<>(); - while (node != null) { - path.add(node.pos); - node = node.prev; - } - Collections.reverse(path); - return simplify(path); - } - BetterBlockPos[] adjs = new BetterBlockPos[]{node.pos.up(), node.pos.down(), node.pos.north(), node.pos.south(), node.pos.east(), node.pos.west()}; - boolean nearAWall = false; - for (BetterBlockPos adj : adjs) { - if (!passable(ctx.world().getBlockState(adj))) { - nearAWall = true; - break; - } - } - for (BetterBlockPos adj : adjs) { - if (!passable(ctx.world().getBlockState(adj))) { - continue; - } - int cost = node.dist + (nearAWall ? 11 : 10); - if (map.containsKey(adj)) { - if (map.get(adj).dist <= cost) { - continue; - } - map.get(adj).canceled = true; - } - map.put(adj, new SearchNode(adj, cost, manhattanDist(adj, dest) * 10, node)); - queue.add(map.get(adj)); - } - } - return null; - } - - private List simplify(List path) { - List simplified = new ArrayList<>(path); - for (int i = 0; i < simplified.size() - 2; i++) { - BlockPos dir = simplified.get(i + 1).subtract(simplified.get(i)); - while (i + 2 < simplified.size()) { - if (simplified.get(i + 2).subtract(simplified.get(i + 1)).equals(dir)) { - simplified.remove(i + 1); - } else { - break; - } - } - } - return simplified; - } - private Vec3d pathAt(int i) { return new Vec3d(path.get(i).x + 0.5, path.get(i).y + 0.5, path.get(i).z + 0.5); } - - public List> lines = new ArrayList<>(); - - protected Elytra(Baritone baritone) { - super(baritone); - } - - @Override public void onTick(TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { @@ -252,7 +120,6 @@ public class Elytra extends Behavior implements Helper { fixNearPlayer(); baritone.getInputOverrideHandler().clearAllKeys(); lines.clear(); - pathfindAroundObstacles(); if (ctx.player().isElytraFlying()) { if (ctx.player().collidedHorizontally) { logDirect("hbonk"); @@ -323,7 +190,9 @@ public class Elytra extends Behavior implements Helper { } private boolean firework() { - return ctx.world().loadedEntityList.stream().anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); + // TODO: Validate that the EntityFireworkRocket is attached to ctx.player() + return ctx.world().loadedEntityList.stream() + .anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); } private boolean isClear(Vec3d start, Vec3d dest) { @@ -390,7 +259,7 @@ public class Elytra extends Behavior implements Helper { return state.getMaterial() == Material.AIR; } - public static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { + private static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { double motionX = motion.x; double motionY = motion.y; double motionZ = motion.z; @@ -438,7 +307,7 @@ public class Elytra extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - public void fixNearPlayer() { + private void fixNearPlayer() { BetterBlockPos pos = ctx.playerFeet(); for (int i = playerNear; i >= Math.max(playerNear - 1000, 0); i -= 10) { if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { @@ -463,7 +332,7 @@ public class Elytra extends Behavior implements Helper { //System.out.println(playerNear); } - public void removeBacktracks() { + private void removeBacktracks() { Map positionFirstSeen = new HashMap<>(); for (int i = 0; i < path.size(); i++) { BetterBlockPos pos = path.get(i); @@ -479,7 +348,8 @@ public class Elytra extends Behavior implements Helper { } } - public RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { + // TODO: Use the optimized version from builder-2 + private RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { int x1 = MathHelper.floor(end.x); int y1 = MathHelper.floor(end.y); int z1 = MathHelper.floor(end.z); From 5b39eb5041e60f0aad6cf6284836ab78954864ae Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 20:38:29 -0500 Subject: [PATCH 020/276] clean up --- src/main/java/baritone/Elytra.java | 139 +++++++++++++++-------------- 1 file changed, 74 insertions(+), 65 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 77a09f369..5b748403e 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -43,16 +43,18 @@ import java.util.stream.Collectors; public class Elytra extends Behavior implements Helper { + // Used exclusively for PathRenderer + public List> lines = new ArrayList<>(); + public BlockPos goal; + public List path = new ArrayList<>(); private long context; private Long seed; public int playerNear; - public int goingTo; - public int sinceFirework; - public BlockPos goal; - public List> lines = new ArrayList<>(); + private int goingTo; + private int sinceFirework; protected Elytra(Baritone baritone) { super(baritone); @@ -117,79 +119,83 @@ public class Elytra extends Behavior implements Helper { if (path.isEmpty()) { return; } + fixNearPlayer(); - baritone.getInputOverrideHandler().clearAllKeys(); + baritone.getInputOverrideHandler().clearAllKeys(); // FIXME: This breaks the regular path-finder lines.clear(); - if (ctx.player().isElytraFlying()) { - if (ctx.player().collidedHorizontally) { - logDirect("hbonk"); - } - if (ctx.player().collidedVertically) { - logDirect("vbonk"); - } - Vec3d start = ctx.playerFeetAsVec(); - boolean firework = firework(); - sinceFirework++; - if (!firework - && sinceFirework > 10 - && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend - && (ctx.player().posY < path.get(goingTo).y - 5 || ctx.playerFeetAsVec().distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! - && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending - ) { - logDirect("firework"); - ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); - sinceFirework = 0; - } - long t = System.currentTimeMillis(); - for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) - int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost - boolean requireClear = relaxation == 0; - int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; - int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps - //int minStep = Math.max(0, playerNear - relaxation); - int minStep = playerNear; - for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { - for (int dy : heights) { - Vec3d dest = pathAt(i).add(0, dy, 0); - if (dy != 0) { - if (i + lookahead >= path.size()) { + + if (!ctx.player().isElytraFlying()) { + return; + } + if (ctx.player().collidedHorizontally) { + logDirect("hbonk"); + } + if (ctx.player().collidedVertically) { + logDirect("vbonk"); + } + + Vec3d start = ctx.playerFeetAsVec(); + boolean firework = isFireworkActive(); + sinceFirework++; + if (!firework + && sinceFirework > 10 + && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend + && (ctx.player().posY < path.get(goingTo).y - 5 || start.distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! + && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending + ) { + logDirect("firework"); + ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); + sinceFirework = 0; + } + final long t = System.currentTimeMillis(); + for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) + int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + boolean requireClear = relaxation == 0; + int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps + //int minStep = Math.max(0, playerNear - relaxation); + int minStep = playerNear; + for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { + for (int dy : heights) { + Vec3d dest = pathAt(i).add(0, dy, 0); + if (dy != 0) { + if (i + lookahead >= path.size()) { + continue; + } + if (start.distanceTo(dest) < 40) { + if (!clearView(dest, pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, pathAt(i + lookahead))) { + // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } - if (start.distanceTo(dest) < 40) { - if (!clearView(dest, pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, pathAt(i + lookahead))) { - // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position - continue; - } - } else { - // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, pathAt(i))) { - continue; - } - } - } - if (requireClear ? isClear(start, dest) : clearView(start, dest)) { - Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); - long a = System.currentTimeMillis(); - Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); - if (pitch == null) { - baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), ctx.playerRotations().getPitch()), false); + } else { + // but if it's far away, allow gaining altitude if we could lose it again by the time we get there + if (!clearView(dest, pathAt(i))) { continue; } - long b = System.currentTimeMillis(); - System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); - goingTo = i; - goal = path.get(i).add(0, dy, 0); - baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); - return; } } + if (requireClear ? isClear(start, dest) : clearView(start, dest)) { + Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); + long a = System.currentTimeMillis(); + Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); + if (pitch == null) { + baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), ctx.playerRotations().getPitch()), false); + continue; + } + long b = System.currentTimeMillis(); + System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); + goingTo = i; + goal = path.get(i).add(0, dy, 0); + baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); + return; + } } } - logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); } + logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); } - private boolean firework() { + private boolean isFireworkActive() { // TODO: Validate that the EntityFireworkRocket is attached to ctx.player() return ctx.world().loadedEntityList.stream() .anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); @@ -218,7 +224,7 @@ public class Elytra extends Behavior implements Helper { goalDirection = goalDirection.normalize(); Rotation good = RotationUtils.calcRotationFromVec3d(new Vec3d(0, 0, 0), goalDirection, ctx.playerRotations()); // lazy lol - boolean firework = firework(); + boolean firework = isFireworkActive(); Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); @@ -268,11 +274,14 @@ public class Elytra extends Behavior implements Helper { float pitchBase = -MathHelper.cos(-rotationPitch * 0.017453292F); float pitchHeight = MathHelper.sin(-rotationPitch * 0.017453292F); Vec3d lookDirection = new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); + if (firework) { + // See EntityFireworkRocket motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; } + float pitchRadians = rotationPitch * 0.017453292F; double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); From 800cb2e747a487fb7cb035764fc7cffb308dc562 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 20:53:53 -0500 Subject: [PATCH 021/276] Replace sublist troll in PathRenderer with `visiblePath` --- src/main/java/baritone/Elytra.java | 49 ++++++++++++------- .../java/baritone/utils/PathRenderer.java | 2 +- 2 files changed, 31 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 5b748403e..e8e83c5b7 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -44,20 +44,25 @@ import java.util.stream.Collectors; public class Elytra extends Behavior implements Helper { // Used exclusively for PathRenderer - public List> lines = new ArrayList<>(); + public List> lines; public BlockPos goal; + public List visiblePath; - public List path = new ArrayList<>(); - + // NetherPathfinder stuff private long context; private Long seed; + // yay! + private List path; public int playerNear; private int goingTo; private int sinceFirework; protected Elytra(Baritone baritone) { super(baritone); + this.lines = new ArrayList<>(); + this.visiblePath = Collections.emptyList(); + this.path = new ArrayList<>(); } public void path(long seed, BlockPos destination) { @@ -100,6 +105,7 @@ public class Elytra extends Behavior implements Helper { } public void cancel() { + this.visiblePath = Collections.emptyList(); this.path.clear(); this.goal = null; this.playerNear = 0; @@ -120,7 +126,12 @@ public class Elytra extends Behavior implements Helper { return; } - fixNearPlayer(); + playerNear = fixNearPlayer(playerNear); + visiblePath = path.subList( + Math.max(playerNear - 30, 0), + Math.min(playerNear + 30, path.size()) + ); + baritone.getInputOverrideHandler().clearAllKeys(); // FIXME: This breaks the regular path-finder lines.clear(); @@ -316,29 +327,29 @@ public class Elytra extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - private void fixNearPlayer() { - BetterBlockPos pos = ctx.playerFeet(); - for (int i = playerNear; i >= Math.max(playerNear - 1000, 0); i -= 10) { - if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { - playerNear = i; // intentional: this changes the bound of the loop + private int fixNearPlayer(int index) { + final BetterBlockPos pos = ctx.playerFeet(); + for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop } } - for (int i = playerNear; i < Math.min(playerNear + 1000, path.size()); i += 10) { - if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { - playerNear = i; // intentional: this changes the bound of the loop + for (int i = index; i < Math.min(index + 1000, path.size()); i += 10) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop } } - for (int i = playerNear; i >= Math.max(playerNear - 50, 0); i--) { - if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { - playerNear = i; // intentional: this changes the bound of the loop + for (int i = index; i >= Math.max(index - 50, 0); i--) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop } } - for (int i = playerNear; i < Math.min(playerNear + 50, path.size()); i++) { - if (path.get(i).distanceSq(pos) < path.get(playerNear).distanceSq(pos)) { - playerNear = i; // intentional: this changes the bound of the loop + for (int i = index; i < Math.min(index + 50, path.size()); i++) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop } } - //System.out.println(playerNear); + return index; } private void removeBacktracks() { diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 15ae73696..934375c4c 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -105,7 +105,7 @@ public final class PathRenderer implements IRenderer { drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); } - drawPath(behavior.baritone.elytra.path.subList(Math.max(behavior.baritone.elytra.playerNear - 30, 0), Math.min(behavior.baritone.elytra.playerNear + 30, behavior.baritone.elytra.path.size())), 0, Color.RED, false, 0, 0); + drawPath(behavior.baritone.elytra.visiblePath, 0, Color.RED, false, 0, 0); if (behavior.baritone.elytra.goal != null) { drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); } From cb7c2d71710caa43a352675e566b43374eb2ed55 Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Fri, 16 Jun 2023 21:59:06 -0400 Subject: [PATCH 022/276] 1.12.2 build script overhaul. - Updated to ForgeGradle 4.0, MixinGradle 0.7 and Gradle 6.9.4 - Added a hack to run the game on arm64 on Mac OS X natively. --- .gitignore | 2 + build.gradle | 138 +++++++---- buildSrc/build.gradle | 4 +- .../baritone/gradle/task/ProguardTask.java | 228 +++++++----------- .../baritone/gradle/util/MappingType.java | 29 --- .../baritone/gradle/util/ReobfWrapper.java | 63 ----- gradle/wrapper/gradle-wrapper.jar | Bin 54706 -> 59536 bytes gradle/wrapper/gradle-wrapper.properties | 3 +- gradlew | 55 +++-- gradlew.bat | 43 ++-- hacks.gradle | 161 +++++++++++++ scripts/proguard.pro | 2 +- 12 files changed, 406 insertions(+), 322 deletions(-) delete mode 100644 buildSrc/src/main/java/baritone/gradle/util/MappingType.java delete mode 100644 buildSrc/src/main/java/baritone/gradle/util/ReobfWrapper.java create mode 100644 hacks.gradle diff --git a/.gitignore b/.gitignore index d4c25ad90..5b420a0e4 100644 --- a/.gitignore +++ b/.gitignore @@ -30,3 +30,5 @@ baritone_Client.launch .vscode/launch.json +libs/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar +libs/java-objc-bridge-1.1.jar diff --git a/build.gradle b/build.gradle index 8e952df73..70f8a7adf 100755 --- a/build.gradle +++ b/build.gradle @@ -22,7 +22,7 @@ buildscript { repositories { maven { name = 'forge' - url = 'http://files.minecraftforge.net/maven' + url = 'https://files.minecraftforge.net/maven' } maven { name = 'SpongePowered' @@ -32,18 +32,19 @@ buildscript { } dependencies { - classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' - classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT' + classpath 'net.minecraftforge.gradle:ForgeGradle:4.+' // TODO: 5.+. `doHackyStuff` relies on 4.x internals. + classpath 'org.spongepowered:mixingradle:0.7-SNAPSHOT' } } - import baritone.gradle.task.CreateDistTask import baritone.gradle.task.ProguardTask apply plugin: 'java' -apply plugin: 'maven' -apply plugin: 'net.minecraftforge.gradle.tweaker-client' +apply plugin: 'maven-publish' +apply plugin: 'net.minecraftforge.gradle' +apply from: 'hacks.gradle' +ext.doHackyStuff(Class.forName('net.minecraftforge.gradle.mcp.task.GenerateSRG')) // TODO: fg 5.0 - `ext.doHackyStuff(Class.forName('net.minecraftforge.gradle.mcp.tasks.GenerateSRG'))` apply plugin: 'org.spongepowered.mixin' sourceCompatibility = targetCompatibility = '1.8' @@ -53,8 +54,19 @@ compileJava { } sourceSets { + api { + compileClasspath += main.compileClasspath + } + main { + compileClasspath += api.output + } + test { + compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output + runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output + } launch { compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output + runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output } schematica_api { @@ -67,13 +79,26 @@ sourceSets { } minecraft { - version = '1.12.2' - mappings = 'stable_39' - tweakClass = 'baritone.launch.BaritoneTweaker' - runDir = 'run' + mappings channel: 'stable', version: '39-1.12' + runs { + def nativesOutput = extractNatives.output // TODO: fg 5.0 - `def nativesOutput = extractNatives.output.get()` + println("[Baritoe] Detected natives: ${nativesOutput}") + client { + workingDirectory project.file('run') + source sourceSets.launch - // The sources jar should use SRG names not MCP to ensure compatibility with all mappings - makeObfSourceJar = true + main 'net.minecraft.launchwrapper.Launch' + + args '--gameDir', '.' + args '--version', '1.12.2' + args '--assetsDir', downloadAssets.output + args '--assetIndex', '{asset_index}' + args '--accessToken', 'INVALID' + + args '--tweakClass', 'baritone.launch.BaritoneTweaker' + jvmArgs "-Dorg.lwjgl.librarypath=${nativesOutput}" + } + } } repositories { @@ -95,23 +120,66 @@ repositories { } } -dependencies { - runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2') - runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') { - // Mixin includes a lot of dependencies that are too up-to-date - exclude module: 'launchwrapper' - exclude module: 'guava' - exclude module: 'gson' - exclude module: 'commons-io' - exclude module: 'log4j-core' +// fix forge gradle 4+ bug with 1.12.2 +afterEvaluate { + configurations.minecraft { + exclude group: 'net.minecraftforge', module: 'mergetool' } - runtime launchCompile('dev.babbaj:nether-pathfinder:0.2') +} + +// lwjgl2 hack for running game on arm64 mac os +afterEvaluate { + def os = org.gradle.internal.os.OperatingSystem.current() + if (os.isMacOsX()) { + def arch = System.getProperty("os.arch").toLowerCase() + println("Detected Mac OS X running on ${arch}") + if (arch == "aarch64") { + println("Configurating aarch64 dependencies.") + + configurations.minecraft { + exclude group: 'ca.weblite', module: 'java-objc-bridge' + } + + dependencies { + // https://github.com/MinecraftMachina/lwjgl/releases/download/2.9.4-20150209-mmachina.2/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar + minecraft files("libs/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar") // TODO: use prism launcher maven + // https://github.com/MinecraftMachina/Java-Objective-C-Bridge/releases/download/1.1.0-mmachina.1/java-objc-bridge-1.1.jar + minecraft files("libs/java-objc-bridge-1.1.jar") // TODO: use prism launcher maven + minecraft(group: 'net.java.dev.jna', name: 'jna') { + version { + strictly '5.12.1' + } + } + } + } + } +} + +dependencies { + minecraft group: 'net.minecraft', name: 'joined', version: '1.12.2' + implementation(group: 'net.minecraft', name: 'launchwrapper', version: '1.12') { + transitive = false + } + + def asmVersion = '9.5' + implementation group: 'org.ow2.asm', name: 'asm', version: asmVersion + implementation group: 'org.ow2.asm', name: 'asm-tree', version: asmVersion + implementation group: 'org.ow2.asm', name: 'asm-commons', version: asmVersion + implementation group: 'org.ow2.asm', name: 'asm-analysis', version: asmVersion + implementation group: 'org.ow2.asm', name: 'asm-util', version: asmVersion + + launchImplementation('com.github.ImpactDevelopment:SimpleTweaker:1.2') + launchImplementation('org.spongepowered:mixin:0.7.11-SNAPSHOT') { + // Mixin includes a lot of dependencies that are too up-to-date + transitive = false + } + launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' + launchImplementation('dev.babbaj:nether-pathfinder:0.2') testImplementation 'junit:junit:4.12' implementation 'dev.babbaj:nether-pathfinder:0.2' } mixin { - defaultObfuscationEnv searge add sourceSets.launch, 'mixins.baritone.refmap.json' } @@ -137,7 +205,7 @@ jar { manifest { attributes( 'MixinConfigs': 'mixins.baritone.json', - + 'TweakClass': 'baritone.launch.BaritoneTweaker', 'Implementation-Title': 'Baritone', 'Implementation-Version': version ) @@ -152,25 +220,3 @@ task proguard(type: ProguardTask) { task createDist(type: CreateDistTask, dependsOn: proguard) build.finalizedBy(createDist) - -install { - def jarApiName = String.format("%s-api-%s", rootProject.name, version.toString()) - def jarApiForgeName = String.format("%s-api-forge-%s", rootProject.name, version.toString()) - def jarSAName = String.format("%s-standalone-%s", rootProject.name, version.toString()) - def jarSAForgeName = String.format("%s-standalone-forge-%s", rootProject.name, version.toString()) - - artifacts { - archives file("$buildDir/libs/" + jarApiName + ".jar") - archives file("$buildDir/libs/" + jarApiForgeName + ".jar") - archives file("$buildDir/libs/" + jarSAName + ".jar") - archives file("$buildDir/libs/" + jarSAForgeName + ".jar") - } - repositories.mavenInstaller { - addFilter('api') { artifact, file -> artifact.name == "baritone-api" } - addFilter('api-forge') { artifact, file -> artifact.name == "baritone-api-forge" } - addFilter('standalone') { artifact, file -> artifact.name == "baritone-standalone" } - addFilter('standalone-forge') { artifact, file -> artifact.name == "baritone-standalone-forge" } - } -} - -install.dependsOn(build) diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle index 2ac49af0f..8ab0f7014 100644 --- a/buildSrc/build.gradle +++ b/buildSrc/build.gradle @@ -20,6 +20,6 @@ repositories { } dependencies { - compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5' - compile group: 'commons-io', name: 'commons-io', version: '2.6' + implementation group: 'com.google.code.gson', name: 'gson', version: '2.8.5' + implementation group: 'commons-io', name: 'commons-io', version: '2.6' } \ No newline at end of file diff --git a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java index 1c329ee2c..435eabcf3 100644 --- a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java +++ b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java @@ -18,39 +18,33 @@ package baritone.gradle.task; import baritone.gradle.util.Determinizer; -import baritone.gradle.util.MappingType; -import baritone.gradle.util.ReobfWrapper; import org.apache.commons.io.IOUtils; -import org.gradle.api.JavaVersion; -import org.gradle.api.NamedDomainObjectContainer; +import org.gradle.api.Project; import org.gradle.api.artifacts.Configuration; import org.gradle.api.artifacts.Dependency; -import org.gradle.api.internal.file.IdentityFileResolver; -import org.gradle.api.internal.plugins.DefaultConvention; import org.gradle.api.tasks.Input; import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskCollection; import org.gradle.api.tasks.compile.ForkOptions; import org.gradle.api.tasks.compile.JavaCompile; -import org.gradle.internal.Pair; import org.gradle.internal.jvm.Jvm; -import org.gradle.internal.jvm.inspection.DefaultJvmVersionDetector; -import org.gradle.process.internal.DefaultExecActionFactory; + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Method; +import java.nio.file.Path; +import java.nio.file.StandardCopyOption; +import java.util.Objects; import java.io.*; -import java.lang.reflect.Field; import java.net.URL; import java.nio.file.Files; -import java.nio.file.Path; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; -import java.util.stream.Collectors; import java.util.zip.ZipEntry; import java.util.zip.ZipFile; -import static java.nio.file.StandardCopyOption.REPLACE_EXISTING; - /** * @author Brady * @since 10/11/2018 @@ -138,23 +132,16 @@ public class ProguardTask extends BaritoneGradleTask { private String findJavaByGradleCurrentRuntime() { String path = Jvm.current().getJavaExecutable().getAbsolutePath(); - - if (this.validateJavaVersion(path)) { - System.out.println("Using Gradle's runtime Java for ProGuard"); - return path; - } - return null; + System.out.println("Using Gradle's runtime Java for ProGuard"); + return path; } private String findJavaByJavaHome() { final String javaHomeEnv = System.getenv("JAVA_HOME"); if (javaHomeEnv != null) { - String path = Jvm.forHome(new File(javaHomeEnv)).getJavaExecutable().getAbsolutePath(); - if (this.validateJavaVersion(path)) { - System.out.println("Detected Java path by JAVA_HOME"); - return path; - } + System.out.println("Detected Java path by JAVA_HOME"); + return path; } return null; } @@ -170,19 +157,11 @@ public class ProguardTask extends BaritoneGradleTask { if (javacPath != null) { File javacFile = new File(javacPath); if (javacFile.exists()) { - File[] maybeJava = javacFile.getParentFile().listFiles(new FilenameFilter() { - @Override - public boolean accept(File dir, String name) { - return name.equals("java"); - } - }); - + File[] maybeJava = javacFile.getParentFile().listFiles((dir, name) -> name.equals("java")); if (maybeJava != null && maybeJava.length > 0) { String path = maybeJava[0].getAbsolutePath(); - if (this.validateJavaVersion(path)) { - System.out.println("Detected Java path by forkOptions"); - return path; - } + System.out.println("Detected Java path by forkOptions"); + return path; } } } @@ -190,21 +169,8 @@ public class ProguardTask extends BaritoneGradleTask { return null; } - private boolean validateJavaVersion(String java) { - final JavaVersion javaVersion = new DefaultJvmVersionDetector(new DefaultExecActionFactory(new IdentityFileResolver())).getJavaVersion(java); - - if (!javaVersion.getMajorVersion().equals("8")) { - System.out.println("Failed to validate Java version " + javaVersion.toString() + " [" + java + "] for ProGuard libraryjars"); - // throw new RuntimeException("Java version incorrect: " + javaVersion.getMajorVersion() + " for " + java); - return false; - } - - System.out.println("Validated Java version " + javaVersion.toString() + " [" + java + "] for ProGuard libraryjars"); - return true; - } - private void generateConfigs() throws Exception { - Files.copy(getRelativeFile(PROGUARD_CONFIG_TEMPLATE), getTemporaryFile(PROGUARD_CONFIG_DEST), REPLACE_EXISTING); + Files.copy(getRelativeFile(PROGUARD_CONFIG_TEMPLATE), getTemporaryFile(PROGUARD_CONFIG_DEST), StandardCopyOption.REPLACE_EXISTING); // Setup the template that will be used to derive the API and Standalone configs List template = Files.readAllLines(getTemporaryFile(PROGUARD_CONFIG_DEST)); @@ -236,14 +202,37 @@ public class ProguardTask extends BaritoneGradleTask { }); } - private void acquireDependencies() throws Exception { + private static final class Pair { + public final A a; + public final B b; + private Pair(final A a, final B b) { + this.a = a; + this.b = b; + } + + @Override + public String toString() { + return "Pair{" + + "a=" + this.a + + ", " + + "b=" + this.b + + '}'; + } + } + + private void acquireDependencies() throws Exception { // Create a map of all of the dependencies that we are able to access in this project // Likely a better way to do this, I just pair the dependency with the first valid configuration Map> dependencyLookupMap = new HashMap<>(); - getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config -> - config.getAllDependencies().forEach(dependency -> - dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency)))); + Map files = new HashMap<>(); + getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config -> { + for (File file : config.getFiles()) { + files.put(file.getName(), file); + } + config.getAllDependencies().forEach(dependency -> + dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), new Pair<>(config, dependency))); + }); // Create the directory if it doesn't already exist Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR); @@ -258,7 +247,7 @@ public class ProguardTask extends BaritoneGradleTask { Path cachedJar = getMinecraftJar(); Path inTempDir = getTemporaryFile("tempLibraries/minecraft.jar"); // TODO: maybe try not to copy every time - Files.copy(cachedJar, inTempDir, REPLACE_EXISTING); + Files.copy(cachedJar, inTempDir, StandardCopyOption.REPLACE_EXISTING); continue; } @@ -270,20 +259,21 @@ public class ProguardTask extends BaritoneGradleTask { pair = entry.getValue(); } } - - // The pair must be non-null - Objects.requireNonNull(pair); - // Find the library jar file, and copy it to tempLibraries - for (File file : pair.getLeft().files(pair.getRight())) { - if (file.getName().startsWith(lib)) { - if (lib.contains("mixin")) { - mixin = file; + if (pair == null) { + File libFile = files.get(lib + ".jar"); + if (libFile == null) { + libFile = files.values().stream().filter(file -> file.getName().startsWith(lib)).findFirst().orElse(null); + if (libFile == null) { + throw new IllegalStateException(lib); } - if (lib.contains("nether-pathfinder")) { - pathfinder = file; + } + copyTempLib(lib, libFile); + } else { + for (File file : pair.a.files(pair.b)) { + if (file.getName().startsWith(lib)) { + copyTempLib(lib, file); } - Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING); } } } @@ -295,87 +285,39 @@ public class ProguardTask extends BaritoneGradleTask { } } + private void copyTempLib(String lib, File libFile) throws IOException { + if (lib.contains("mixin")) { + mixin = libFile; + } + if (lib.contains("nether-pathfinder")) { + pathfinder = libFile; + } + Files.copy(libFile.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), StandardCopyOption.REPLACE_EXISTING); + } + // a bunch of epic stuff to get the path to the cached jar private Path getMinecraftJar() throws Exception { - MappingType mappingType; - try { - mappingType = getMappingType(); - } catch (Exception e) { - System.err.println("Failed to get mapping type, assuming NOTCH."); - mappingType = MappingType.NOTCH; - } - - String suffix; - switch (mappingType) { - case NOTCH: - suffix = ""; - break; - case SEARGE: - suffix = "-srgBin"; - break; - case CUSTOM: - throw new IllegalStateException("Custom mappings not supported!"); - default: - throw new IllegalStateException("Unknown mapping type: " + mappingType); - } - - DefaultConvention convention = (DefaultConvention) this.getProject().getConvention(); - Object extension = convention.getAsMap().get("minecraft"); - Objects.requireNonNull(extension); - - // for some reason cant use Class.forName - Class class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed - Field f_replacer = class_baseExtension.getDeclaredField("replacer"); - f_replacer.setAccessible(true); - Object replacer = f_replacer.get(extension); - Class class_replacementProvider = replacer.getClass(); - Field replacement_replaceMap = class_replacementProvider.getDeclaredField("replaceMap"); - replacement_replaceMap.setAccessible(true); - - Map replacements = (Map) replacement_replaceMap.get(replacer); - String cacheDir = replacements.get("CACHE_DIR").toString() + "/net/minecraft"; - String mcVersion = replacements.get("MC_VERSION").toString(); - String mcpInsert = replacements.get("MAPPING_CHANNEL").toString() + "/" + replacements.get("MAPPING_VERSION").toString(); - String fullJarName = "minecraft-" + mcVersion + suffix + ".jar"; - - String baseDir = String.format("%s/minecraft/%s/", cacheDir, mcVersion); - - String jarPath; - if (mappingType == MappingType.SEARGE) { - jarPath = String.format("%s/%s/%s", baseDir, mcpInsert, fullJarName); - } else { - jarPath = baseDir + fullJarName; - } - jarPath = jarPath - .replace("/", File.separator) - .replace("\\", File.separator); // hecking regex - - return new File(jarPath).toPath(); + return getObfuscatedMinecraftJar(getProject(), false); // always notch jar for now. } - // throws IllegalStateException if mapping type is ambiguous or it fails to find it - private MappingType getMappingType() { - // if it fails to find this then its probably a forgegradle version problem - Set reobf = (NamedDomainObjectContainer) this.getProject().getExtensions().getByName("reobf"); + private static Path getObfuscatedMinecraftJar(final Project project, final boolean srg) throws Exception { + final Object extension = Objects.requireNonNull(project.getExtensions().findByName("minecraft"), "Unable to find Minecraft extension."); - List mappingTypes = getUsedMappingTypes(reobf); - long mappingTypesUsed = mappingTypes.size(); - if (mappingTypesUsed == 0) { - throw new IllegalStateException("Failed to find mapping type (no jar task?)"); - } - if (mappingTypesUsed > 1) { - throw new IllegalStateException("Ambiguous mapping type (multiple jars with different mapping types?)"); - } + final Class mcpRepoClass = mcpRepoClass(extension.getClass().getClassLoader()); + final Field mcpRepoInstanceField = mcpRepoClass.getDeclaredField("INSTANCE"); + mcpRepoInstanceField.setAccessible(true); + final Method findMethod = mcpRepoClass.getDeclaredMethod(srg ? "findSrg" : "findRaw", String.class, String.class); + findMethod.setAccessible(true); - return mappingTypes.get(0); + final Object mcpRepo = mcpRepoInstanceField.get(null); + final String mcpVersion = (String) Objects.requireNonNull(project.getExtensions().getExtraProperties().get("MCP_VERSION"), "Extra property \"MCP_VERSION\" not found"); + return ((File) findMethod.invoke(mcpRepo, "joined", mcpVersion)).toPath(); } - private List getUsedMappingTypes(Set reobf) { - return reobf.stream() - .map(ReobfWrapper::new) - .map(ReobfWrapper::getMappingType) - .distinct() - .collect(Collectors.toList()); + private static Class mcpRepoClass(final ClassLoader loader) throws Exception { + final Method forName0 = Class.class.getDeclaredMethod("forName0", String.class, boolean.class, ClassLoader.class, Class.class); + forName0.setAccessible(true); + return (Class) forName0.invoke(null, "net.minecraftforge.gradle.mcp.MCPRepo", true, loader, null); } private void proguardApi() throws Exception { @@ -400,10 +342,18 @@ public class ProguardTask extends BaritoneGradleTask { this.url = url; } + public String getUrl() { + return url; + } + public void setExtract(String extract) { this.extract = extract; } + public String getExtract() { + return extract; + } + private void runProguard(Path config) throws Exception { // Delete the existing proguard output file. Proguard probably handles this already, but why not do it ourselves if (Files.exists(this.proguardOut)) { diff --git a/buildSrc/src/main/java/baritone/gradle/util/MappingType.java b/buildSrc/src/main/java/baritone/gradle/util/MappingType.java deleted file mode 100644 index a3be9b49f..000000000 --- a/buildSrc/src/main/java/baritone/gradle/util/MappingType.java +++ /dev/null @@ -1,29 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.gradle.util; - -/** - * All credits go to AsmLibGradle and its contributors. - * - * @see Original Source - */ -public enum MappingType { - SEARGE, - NOTCH, - CUSTOM // forgegradle -} diff --git a/buildSrc/src/main/java/baritone/gradle/util/ReobfWrapper.java b/buildSrc/src/main/java/baritone/gradle/util/ReobfWrapper.java deleted file mode 100644 index f752cd946..000000000 --- a/buildSrc/src/main/java/baritone/gradle/util/ReobfWrapper.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.gradle.util; - -import java.lang.reflect.Field; -import java.util.Objects; - -/** - * All credits go to AsmLibGradle and its contributors. - * - * @see Original Source - */ -public class ReobfWrapper { - - private final Object instance; - private final Class type; - - public ReobfWrapper(Object instance) { - this.instance = instance; - Objects.requireNonNull(instance); - this.type = instance.getClass(); - } - - public String getName() { - try { - Field nameField = type.getDeclaredField("name"); - nameField.setAccessible(true); - return (String) nameField.get(this.instance); - } catch (ReflectiveOperationException ex) { - throw new IllegalStateException(ex); - } - } - - public MappingType getMappingType() { - try { - Field enumField = type.getDeclaredField("mappingType"); - enumField.setAccessible(true); - Enum aEnum = (Enum) enumField.get(this.instance); - MappingType mappingType = MappingType.values()[aEnum.ordinal()]; - if (!aEnum.name().equals(mappingType.name())) { - throw new IllegalStateException("ForgeGradle ReobfMappingType is not equivalent to MappingType (version error?)"); - } - return mappingType; - } catch (ReflectiveOperationException ex) { - throw new IllegalStateException(ex); - } - } -} diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar index 4c5670a158b8953b61fd441194873cac2c99930d..7454180f2ae8848c63b8b4dea2cb829da983f2fa 100755 GIT binary patch literal 59536 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 QuEJmfE|#`Dqx|px0L@K;Y5)KL literal 54706 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 diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index 599a02b7a..c51cbf173 100755 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,5 @@ -#Tue Jul 31 21:56:56 PDT 2018 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists +distributionUrl=https\://services.gradle.org/distributions/gradle-6.9.4-all.zip zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip diff --git a/gradlew b/gradlew index cccdd3d51..744e882ed 100755 --- a/gradlew +++ b/gradlew @@ -1,5 +1,21 @@ #!/usr/bin/env sh +# +# Copyright 2015 the original author or authors. +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# https://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# + ############################################################################## ## ## Gradle start up script for UN*X @@ -28,7 +44,7 @@ APP_NAME="Gradle" APP_BASE_NAME=`basename "$0"` # Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -DEFAULT_JVM_OPTS="" +DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"' # Use the maximum available, or set MAX_FD != -1 to use that value. MAX_FD="maximum" @@ -56,7 +72,7 @@ case "`uname`" in Darwin* ) darwin=true ;; - MINGW* ) + MSYS* | MINGW* ) msys=true ;; NONSTOP* ) @@ -66,6 +82,7 @@ esac CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar + # Determine the Java command to use to start the JVM. if [ -n "$JAVA_HOME" ] ; then if [ -x "$JAVA_HOME/jre/sh/java" ] ; then @@ -109,10 +126,11 @@ if $darwin; then GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\"" fi -# For Cygwin, switch paths to Windows format before running java -if $cygwin ; then +# For Cygwin or MSYS, switch paths to Windows format before running java +if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then APP_HOME=`cygpath --path --mixed "$APP_HOME"` CLASSPATH=`cygpath --path --mixed "$CLASSPATH"` + JAVACMD=`cygpath --unix "$JAVACMD"` # We build the pattern for arguments to be converted via cygpath @@ -138,19 +156,19 @@ if $cygwin ; then else eval `echo args$i`="\"$arg\"" fi - i=$((i+1)) + i=`expr $i + 1` done case $i in - (0) set -- ;; - (1) set -- "$args0" ;; - (2) set -- "$args0" "$args1" ;; - (3) set -- "$args0" "$args1" "$args2" ;; - (4) set -- "$args0" "$args1" "$args2" "$args3" ;; - (5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; - (6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; - (7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; - (8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; - (9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; + 0) set -- ;; + 1) set -- "$args0" ;; + 2) set -- "$args0" "$args1" ;; + 3) set -- "$args0" "$args1" "$args2" ;; + 4) set -- "$args0" "$args1" "$args2" "$args3" ;; + 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;; + 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;; + 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;; + 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;; + 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;; esac fi @@ -159,14 +177,9 @@ save () { for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done echo " " } -APP_ARGS=$(save "$@") +APP_ARGS=`save "$@"` # Collect all arguments for the java command, following the shell quoting and substitution rules eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS" -# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong -if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then - cd "$(dirname "$0")" -fi - exec "$JAVACMD" "$@" diff --git a/gradlew.bat b/gradlew.bat index f9553162f..107acd32c 100755 --- a/gradlew.bat +++ b/gradlew.bat @@ -1,3 +1,19 @@ +@rem +@rem Copyright 2015 the original author or authors. +@rem +@rem Licensed under the Apache License, Version 2.0 (the "License"); +@rem you may not use this file except in compliance with the License. +@rem You may obtain a copy of the License at +@rem +@rem https://www.apache.org/licenses/LICENSE-2.0 +@rem +@rem Unless required by applicable law or agreed to in writing, software +@rem distributed under the License is distributed on an "AS IS" BASIS, +@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +@rem See the License for the specific language governing permissions and +@rem limitations under the License. +@rem + @if "%DEBUG%" == "" @echo off @rem ########################################################################## @rem @@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=. set APP_BASE_NAME=%~n0 set APP_HOME=%DIRNAME% +@rem Resolve any "." and ".." in APP_HOME to make it shorter. +for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi + @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. -set DEFAULT_JVM_OPTS= +set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m" @rem Find java.exe if defined JAVA_HOME goto findJavaFromJavaHome set JAVA_EXE=java.exe %JAVA_EXE% -version >NUL 2>&1 -if "%ERRORLEVEL%" == "0" goto init +if "%ERRORLEVEL%" == "0" goto execute echo. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. @@ -35,7 +54,7 @@ goto fail set JAVA_HOME=%JAVA_HOME:"=% set JAVA_EXE=%JAVA_HOME%/bin/java.exe -if exist "%JAVA_EXE%" goto init +if exist "%JAVA_EXE%" goto execute echo. echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% @@ -45,28 +64,14 @@ echo location of your Java installation. goto fail -:init -@rem Get command-line arguments, handling Windows variants - -if not "%OS%" == "Windows_NT" goto win9xME_args - -:win9xME_args -@rem Slurp the command line arguments. -set CMD_LINE_ARGS= -set _SKIP=2 - -:win9xME_args_slurp -if "x%~1" == "x" goto execute - -set CMD_LINE_ARGS=%* - :execute @rem Setup the command line set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar + @rem Execute Gradle -"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% +"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %* :end @rem End local scope for the variables with windows NT shell diff --git a/hacks.gradle b/hacks.gradle new file mode 100644 index 000000000..821a4d02e --- /dev/null +++ b/hacks.gradle @@ -0,0 +1,161 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +ext.doHackyStuff = { final Class clazz -> + def withExtension = { final File file, final String extension -> + def i = file.getName().lastIndexOf('.') + def name = file.getName().substring(0, i) + return new File(file.getParent(), "$name.$extension") + } + + // https://github.com/MinecraftForge/ForgeGradle/blob/6639464b29b0923187eee0a609e546ba9f1b998b/src/patcher/java/net/minecraftforge/gradle/patcher/PatcherPlugin.java#L545 + // https://github.com/MinecraftForge/ForgeGradle/blob/6639464b29b0923187eee0a609e546ba9f1b998b/src/userdev/java/net/minecraftforge/gradle/userdev/UserDevPlugin.java#L149 + // create createMcp2Obf task + this.tasks.register('createMcpToObf', clazz) + .configure { task -> + task.setNotch(true) + task.setReverse(true) + } + afterEvaluate { + def createMcp2Obf = this.tasks.getByName('createMcpToObf') + def createMcp2Srg = this.tasks.getByName('createMcpToSrg') + + // configure createMcp2Obf task + if (createMcp2Obf.getSrg() == null) { + createMcp2Obf.setSrg(createMcp2Srg.getSrg()) + createMcp2Obf.setMappings(createMcp2Srg.getMappings()) + createMcp2Obf.dependsOn(createMcp2Srg) + } + + def createSrgCopyTask = { final Task tsrgTask -> + def srgCopyTask = this.tasks.register("${tsrgTask.name}Srg", tsrgTask.getClass()) + tsrgTask.getDependsOn().forEach({ dep -> + srgCopyTask.get().dependsOn(dep) + }) + // https://github.com/MinecraftForge/ForgeGradle/blob/6639464b29b0923187eee0a609e546ba9f1b998b/src/mcp/java/net/minecraftforge/gradle/mcp/task/GenerateSRG.java#L39 + srgCopyTask.configure { task -> + task.setSrg(tsrgTask.getSrg()) + task.setMappings(tsrgTask.getMappings()) + // https://github.com/MinecraftForge/SrgUtils/blob/bb2ca35bb8d349a122ef512dedd24f54f7cd0bdf/src/main/java/net/minecraftforge/srgutils/IMappingFile.java#L44 + task.setFormat('SRG') + task.setNotch(tsrgTask.getNotch()) + task.setReverse(tsrgTask.getReverse()) + task.setOutput(withExtension(tsrgTask.getOutput(), 'srg')) + } + return srgCopyTask + } + def createMcp2ObfSrgCopyTask = createSrgCopyTask(createMcp2Obf) + createMcp2Obf.dependsOn(createMcp2ObfSrgCopyTask) + def createMcp2SrgSrgCopyTask = createSrgCopyTask(createMcp2Srg) + createMcp2Srg.dependsOn(createMcp2SrgSrgCopyTask) + + this.sourceSets.forEach({ set -> + def compileTask = this.project.tasks[set.compileJavaTaskName] + if (!(compileTask instanceof JavaCompile)) { + println("[Baritoe] Non-java compile task for ${set} of type ${compileTask}") + return + } + compileTask.dependsOn(createMcp2Obf) + compileTask.doFirst { + // inject legacy notch srg file + def createMcp2ObfSrgCopy = createMcp2ObfSrgCopyTask.get() + def reobfNotchSrgFileArgument = "-AreobfNotchSrgFile=${createMcp2ObfSrgCopy.output.canonicalPath}" + compileTask.options.compilerArgs += reobfNotchSrgFileArgument + println("[Baritoe] Injecting compiler argument: ${reobfNotchSrgFileArgument}") + + // inject legacy notch srg out file + def outTSrgFileArgument = '-AoutTsrgFile=' + def compilerArgsIterator = compileTask.options.compilerArgs.listIterator() + while (compilerArgsIterator.hasNext()) { + def compilerArg = compilerArgsIterator.next() + if (compilerArg.startsWith(outTSrgFileArgument)) { + def argumentFileValue = new File(compilerArg.substring(outTSrgFileArgument.length(), compilerArg.length())) + def outNotchSrgFile = withExtension(argumentFileValue, 'notch.srg') + def outNotchSrgFileArgument = "-AoutNotchSrgFile=${outNotchSrgFile.canonicalPath}" + println("[Baritoe] Injecting compiler argument: ${outNotchSrgFileArgument}") + compilerArgsIterator.add(outNotchSrgFileArgument) + } + } + } + }) + + // register reobf jars + def reobfExtension = this.project.getExtensions().getByName('reobf') + if (!reobfExtension) { + throw new IllegalStateException("Could not find \"reobf\" extension") + } + def reobfNotchJar = reobfExtension.create(jar.getName()) + reobfNotchJar.dependsOn(createMcp2Obf) + reobfNotchJar.setMappings(createMcp2Obf.getOutput()) + + // even more horrible hack :) for outNotchSrgFile injection + reobfNotchJar.doFirst { + // https://github.com/MinecraftForge/ForgeGradle/blob/6639464b29b0923187eee0a609e546ba9f1b998b/src/userdev/java/net/minecraftforge/gradle/userdev/tasks/RenameJar.java#L96 + def extraMappings = reobfNotchJar.getExtraMappings() + println("[Baritoe] Extra mappings: ${extraMappings}") + def copy = new ArrayList<>() + extraMappings.forEach { extraMapping -> + copy.add(withExtension(extraMapping, 'notch.srg')) + } + println("[Baritoe] New extra mappings: ${copy}") + reobfNotchJar.setExtraMappings(copy) + } + } +} + +// TODO: In-complete fg 5.0 port. Currently doesn't handle mixin notch srg mapping hack. +//ext.doHackyStuff = { final Class clazz -> +// afterEvaluate { +// def createMcp2Srg = this.tasks.getByName('createMcpToSrg') +// def createMcpToObf = this.tasks.register('createMcpToObf', clazz) +// createMcpToObf.configure { task -> +// task.setNotch(true) +// task.setReverse(true) +// task.getSrg().set(createMcp2Srg.getSrg().get()) +// task.getMappings().set(createMcp2Srg.getMappings().get()) +// task.dependsOn(createMcp2Srg) +// } +// reobf { +// jar { +// dependsOn(createMcpToObf) +// getMappings().set(createMcpToObf.get().getOutput().get()) +// } +// } +// this.sourceSets.forEach({ set -> +// def compileTask = this.project.tasks[set.compileJavaTaskName] +// if (!(compileTask instanceof JavaCompile)) { +// println("[Baritoe] Non-java compile task for ${set} of type ${compileTask}") +// return +// } +// compileTask.dependsOn(createMcpToObf) +// compileTask.doFirst { +// def reobfTSrgFile = '-AreobfTsrgFile=' +// def compilerArgsIterator = compileTask.options.compilerArgs.listIterator() +// while (compilerArgsIterator.hasNext()) { +// def compilerArg = compilerArgsIterator.next() +// if (compilerArg.startsWith(reobfTSrgFile)) { +// compilerArgsIterator.remove() +// def toInject = "-AreobfTsrgFile=${createMcpToObf.get().output.get().asFile.canonicalPath}" +// compilerArgsIterator.add(toInject) +// println("[Baritoe] Injecting compiler argument: ${toInject}") +// } +// } +// println("[Baritoe] Compiler arguments: ${compileTask.options.compilerArgs}") +// } +// }) +// } +//} \ No newline at end of file diff --git a/scripts/proguard.pro b/scripts/proguard.pro index 858494778..d493f60de 100644 --- a/scripts/proguard.pro +++ b/scripts/proguard.pro @@ -92,7 +92,7 @@ -libraryjars 'tempLibraries/text2speech-1.10.3.jar' -libraryjars 'tempLibraries/mixin-0.7.11-SNAPSHOT.jar' --libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist? +-libraryjars 'tempLibraries/launchwrapper-1.12.jar' -libraryjars 'tempLibraries/nether-pathfinder-.jar' From b72bbfce5e4eb28ded8b4bb9003d468d9baa47e6 Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Fri, 16 Jun 2023 22:36:58 -0400 Subject: [PATCH 023/276] make all json deterministic --- .../src/main/java/baritone/gradle/util/Determinizer.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java index 40d17ef03..35c1fe40a 100644 --- a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java +++ b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java @@ -64,9 +64,9 @@ public class Determinizer { JarEntry clone = new JarEntry(entry.getName()); clone.setTime(42069); jos.putNextEntry(clone); - if (entry.getName().endsWith(".refmap.json")) { - JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject(); - jos.write(writeSorted(object).getBytes()); + if (entry.getName().endsWith(".json")) { + JsonElement json = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))); + jos.write(writeSorted(json).getBytes()); } else if (entry.getName().equals("META-INF/MANIFEST.MF") && doForgeReplacementOfMetaInf) { // only replace for forge jar ByteArrayOutputStream cancer = new ByteArrayOutputStream(); copy(jarFile.getInputStream(entry), cancer); @@ -104,7 +104,7 @@ public class Determinizer { } } - private static String writeSorted(JsonObject in) throws IOException { + private static String writeSorted(JsonElement in) throws IOException { StringWriter writer = new StringWriter(); JsonWriter jw = new JsonWriter(writer); ORDERED_JSON_WRITER.write(jw, in); From 071e6164fef3fff38e7316641f723e46eb31827a Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 21:55:08 -0500 Subject: [PATCH 024/276] Fix nether-pathfinder on Windows --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 8e952df73..e9c0c24cd 100755 --- a/build.gradle +++ b/build.gradle @@ -105,9 +105,9 @@ dependencies { exclude module: 'commons-io' exclude module: 'log4j-core' } - runtime launchCompile('dev.babbaj:nether-pathfinder:0.2') + runtime launchCompile('dev.babbaj:nether-pathfinder:0.4') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.2' + implementation 'dev.babbaj:nether-pathfinder:0.4' } mixin { From f798ff26f696e0825ad4d94d2856cc14bd0deb51 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 16 Jun 2023 22:31:53 -0500 Subject: [PATCH 025/276] fixed seed --- src/main/java/baritone/Elytra.java | 74 ++++++++++++------- .../command/defaults/ElytraCommand.java | 2 +- .../java/baritone/utils/PathRenderer.java | 4 +- 3 files changed, 51 insertions(+), 29 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index e8e83c5b7..affe8e5e6 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -18,10 +18,7 @@ package baritone; import baritone.api.event.events.TickEvent; -import baritone.api.utils.BetterBlockPos; -import baritone.api.utils.Helper; -import baritone.api.utils.Rotation; -import baritone.api.utils.RotationUtils; +import baritone.api.utils.*; import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; @@ -37,20 +34,24 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.chunk.BlockStateContainer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.*; import java.util.stream.Collectors; public class Elytra extends Behavior implements Helper { + private static final long NETHER_SEED = 146008555100680L; + // Used exclusively for PathRenderer public List> lines; - public BlockPos goal; + public BlockPos aimPos; public List visiblePath; // NetherPathfinder stuff private long context; - private Long seed; // yay! private List path; @@ -60,28 +61,34 @@ public class Elytra extends Behavior implements Helper { protected Elytra(Baritone baritone) { super(baritone); + // lol + this.context = NetherPathfinder.newContext(NETHER_SEED); + this.lines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); this.path = new ArrayList<>(); } - public void path(long seed, BlockPos destination) { - this.setupContext(seed); - + public void path(BlockPos destination) { this.playerNear = 0; this.goingTo = 0; + long start = System.currentTimeMillis(); final PathSegment segment = NetherPathfinder.pathFind( this.context, ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, destination.getX(), destination.getY(), destination.getZ() ); + long end = System.currentTimeMillis(); this.path = Arrays.stream(segment.packed) .mapToObj(BlockPos::fromLong) .map(BetterBlockPos::new) .collect(Collectors.toList()); + final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(this.path.size() - 1))); + logDirect(String.format("Computed path in %dms. (%d blocks)", end - start, distance)); + if (!segment.finished) { logDirect("segment not finished. path incomplete"); } @@ -89,25 +96,10 @@ public class Elytra extends Behavior implements Helper { removeBacktracks(); } - private void setupContext(long seed) { - if (!Objects.equals(this.seed, seed)) { - this.freeContext(); - this.context = NetherPathfinder.newContext(seed); - } - this.seed = seed; - } - - private void freeContext() { - if (this.context != 0) { - NetherPathfinder.freeContext(this.context); - } - this.context = 0; - } - public void cancel() { this.visiblePath = Collections.emptyList(); this.path.clear(); - this.goal = null; + this.aimPos = null; this.playerNear = 0; this.goingTo = 0; this.sinceFirework = 0; @@ -196,7 +188,7 @@ public class Elytra extends Behavior implements Helper { long b = System.currentTimeMillis(); System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); goingTo = i; - goal = path.get(i).add(0, dy, 0); + aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); return; } @@ -368,6 +360,36 @@ public class Elytra extends Behavior implements Helper { } } + private static boolean[] pack(Chunk chunk) { + try { + boolean[] packed = new boolean[16 * 16 * 128]; + ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + for (int y0 = 0; y0 < 8; y0++) { + ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; + if (extendedblockstorage == null) { + continue; + } + BlockStateContainer bsc = extendedblockstorage.getData(); + int yReal = y0 << 4; + for (int y1 = 0; y1 < 16; y1++) { + int y = y1 | yReal; + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + IBlockState state = bsc.get(x, y1, z); + if (state.getBlock() != Blocks.AIR) { // instanceof BlockAir in 1.13+ + packed[x + (z << 4) + (y << 8)] = true; + } + } + } + } + } + return packed; + } catch (Exception e) { + e.printStackTrace(); + return null; + } + } + // TODO: Use the optimized version from builder-2 private RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { int x1 = MathHelper.floor(end.x); diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 99ddaa8e4..2d2e3f0ee 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -41,7 +41,7 @@ public class ElytraCommand extends Command { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); GoalXZ goal = (GoalXZ) customGoalProcess.getGoal(); - ((Baritone) baritone).elytra.path(146008555100680L, new BlockPos(goal.getX(), 64, goal.getZ())); + ((Baritone) baritone).elytra.path(new BlockPos(goal.getX(), 64, goal.getZ())); } @Override diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 934375c4c..a4c412298 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -106,8 +106,8 @@ public final class PathRenderer implements IRenderer { } drawPath(behavior.baritone.elytra.visiblePath, 0, Color.RED, false, 0, 0); - if (behavior.baritone.elytra.goal != null) { - drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.goal), partialTicks, Color.GREEN); + if (behavior.baritone.elytra.aimPos != null) { + drawGoal(renderView, new GoalBlock(behavior.baritone.elytra.aimPos), partialTicks, Color.GREEN); } if (!behavior.baritone.elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); From dc53c7939312507418debde09822dcdbfb7b36eb Mon Sep 17 00:00:00 2001 From: Leijurv Date: Fri, 16 Jun 2023 21:35:56 -0700 Subject: [PATCH 026/276] gaming --- build.gradle | 7 +- src/main/java/baritone/Elytra.java | 129 +++++++++++++++++++++++------ 2 files changed, 106 insertions(+), 30 deletions(-) diff --git a/build.gradle b/build.gradle index e6f3e1134..6f5ca491a 100755 --- a/build.gradle +++ b/build.gradle @@ -142,7 +142,8 @@ afterEvaluate { dependencies { // https://github.com/MinecraftMachina/lwjgl/releases/download/2.9.4-20150209-mmachina.2/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar - minecraft files("libs/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar") // TODO: use prism launcher maven + minecraft files("libs/lwjgl-platform-2.9.4-nightly-20150209-natives-osx.jar") + // TODO: use prism launcher maven // https://github.com/MinecraftMachina/Java-Objective-C-Bridge/releases/download/1.1.0-mmachina.1/java-objc-bridge-1.1.jar minecraft files("libs/java-objc-bridge-1.1.jar") // TODO: use prism launcher maven minecraft(group: 'net.java.dev.jna', name: 'jna') { @@ -174,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.4') + launchImplementation('dev.babbaj:nether-pathfinder:0.6') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.4' + implementation 'dev.babbaj:nether-pathfinder:0.6' } mixin { diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index affe8e5e6..97e4a0b43 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -17,8 +17,13 @@ package baritone; +import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.TickEvent; -import baritone.api.utils.*; +import baritone.api.event.events.type.EventState; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Helper; +import baritone.api.utils.Rotation; +import baritone.api.utils.RotationUtils; import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; @@ -39,6 +44,8 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.*; +import java.util.concurrent.Executor; +import java.util.concurrent.Executors; import java.util.stream.Collectors; public class Elytra extends Behavior implements Helper { @@ -69,31 +76,93 @@ public class Elytra extends Behavior implements Helper { this.path = new ArrayList<>(); } - public void path(BlockPos destination) { - this.playerNear = 0; - this.goingTo = 0; + private final Executor packer = Executors.newSingleThreadExecutor(); - long start = System.currentTimeMillis(); - final PathSegment segment = NetherPathfinder.pathFind( - this.context, - ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, - destination.getX(), destination.getY(), destination.getZ() - ); - long end = System.currentTimeMillis(); - - this.path = Arrays.stream(segment.packed) - .mapToObj(BlockPos::fromLong) - .map(BetterBlockPos::new) - .collect(Collectors.toList()); - - final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(this.path.size() - 1))); - logDirect(String.format("Computed path in %dms. (%d blocks)", end - start, distance)); - - if (!segment.finished) { - logDirect("segment not finished. path incomplete"); + @Override + public final void onChunkEvent(ChunkEvent event) { + if (event.getState() == EventState.POST && (event.getType() == ChunkEvent.Type.POPULATE_FULL || event.getType() == ChunkEvent.Type.POPULATE_PARTIAL)) { + Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); + packer.execute(() -> { + NetherPathfinder.insertChunkData(context, event.getX(), event.getZ(), pack(chunk)); + }); } + } - removeBacktracks(); + boolean recalculating; + + private void pathfindAroundObstacles() { + if (recalculating) { + return; + } + outer: + while (true) { + int rangeStartIncl = playerNear; + int rangeEndExcl = playerNear; + while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { + rangeEndExcl++; + } + if (rangeStartIncl >= rangeEndExcl) { + // not loaded yet? + return; + } + if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { + // we're in a wall + return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: + } + for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { + if (!clearView(pathAt(i), pathAt(i + 1))) { + // obstacle. where do we return to pathing? + // find the next valid segment + for (int j = i + 1; j < rangeEndExcl - 1; j++) { + if (clearView(pathAt(j), pathAt(j + 1))) { + // found it + // we want to replace the path from i to j + List afterSplice = path.subList(j + 1, path.size()); + recalculating = true; + path(path.get(j + 1), afterSplice); + break outer; + } + } + } + } + break; + } + } + + public void path(BlockPos destination) { + path(destination, new ArrayList<>()); + } + + public void path(BlockPos destination, List andThen) { + packer.execute(() -> { + long start = System.currentTimeMillis(); + final PathSegment segment = NetherPathfinder.pathFind( + this.context, + ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, + destination.getX(), destination.getY(), destination.getZ() + ); + long end = System.currentTimeMillis(); + + ctx.minecraft().addScheduledTask(() -> { + this.path = Arrays.stream(segment.packed) + .mapToObj(BlockPos::fromLong) + .map(BetterBlockPos::new) + .collect(Collectors.toList()); + final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(this.path.size() - 1))); + logDirect(String.format("Computed path in %dms. (%d blocks)", end - start, distance)); + + if (!segment.finished) { + logDirect("segment not finished. path incomplete"); + } + this.path.addAll(andThen); + if (!andThen.isEmpty()) { + recalculating = false; + } + this.playerNear = 0; + this.goingTo = 0; + removeBacktracks(); + }); + }); } public void cancel() { @@ -127,6 +196,8 @@ public class Elytra extends Behavior implements Helper { baritone.getInputOverrideHandler().clearAllKeys(); // FIXME: This breaks the regular path-finder lines.clear(); + pathfindAroundObstacles(); + if (!ctx.player().isElytraFlying()) { return; } @@ -361,9 +432,11 @@ public class Elytra extends Behavior implements Helper { } private static boolean[] pack(Chunk chunk) { + //System.out.println(chunk); try { boolean[] packed = new boolean[16 * 16 * 128]; ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + int count = 0; for (int y0 = 0; y0 < 8; y0++) { ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; if (extendedblockstorage == null) { @@ -376,17 +449,19 @@ public class Elytra extends Behavior implements Helper { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); - if (state.getBlock() != Blocks.AIR) { // instanceof BlockAir in 1.13+ + if (!passable(state)) { packed[x + (z << 4) + (y << 8)] = true; + count++; } } } } } + //System.out.println("breakpoint " + count); return packed; } catch (Exception e) { e.printStackTrace(); - return null; + throw new RuntimeException(e); } } @@ -401,7 +476,7 @@ public class Elytra extends Behavior implements Helper { BlockPos blockpos = new BlockPos(x2, y2, z2); IBlockState iblockstate = ctx.world().getBlockState(blockpos); if (!passable(iblockstate)) { - return Blocks.DIRT.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + return Blocks.SPONGE.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); } int steps = 200; while (steps-- >= 0) { @@ -479,7 +554,7 @@ public class Elytra extends Behavior implements Helper { blockpos = new BlockPos(x2, y2, z2); IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); if (!passable(iblockstate1)) { - return Blocks.DIRT.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + return Blocks.NETHERRACK.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); } } return null; From 1f303e69b0d246689ccbf96afbc3963092274058 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Fri, 16 Jun 2023 22:21:52 -0700 Subject: [PATCH 027/276] cut at render distance --- build.gradle | 4 ++-- src/main/java/baritone/Elytra.java | 17 ++++++----------- 2 files changed, 8 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 6f5ca491a..a389ae08f 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.6') + launchImplementation('dev.babbaj:nether-pathfinder:0.8') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.6' + implementation 'dev.babbaj:nether-pathfinder:0.8' } mixin { diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 97e4a0b43..1af15edda 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -83,6 +83,7 @@ public class Elytra extends Behavior implements Helper { if (event.getState() == EventState.POST && (event.getType() == ChunkEvent.Type.POPULATE_FULL || event.getType() == ChunkEvent.Type.POPULATE_PARTIAL)) { Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); packer.execute(() -> { + System.out.println("meow"); NetherPathfinder.insertChunkData(context, event.getX(), event.getZ(), pack(chunk)); }); } @@ -113,16 +114,10 @@ public class Elytra extends Behavior implements Helper { if (!clearView(pathAt(i), pathAt(i + 1))) { // obstacle. where do we return to pathing? // find the next valid segment - for (int j = i + 1; j < rangeEndExcl - 1; j++) { - if (clearView(pathAt(j), pathAt(j + 1))) { - // found it - // we want to replace the path from i to j - List afterSplice = path.subList(j + 1, path.size()); - recalculating = true; - path(path.get(j + 1), afterSplice); - break outer; - } - } + List afterSplice = path.subList(rangeEndExcl - 1, path.size()); + recalculating = true; + path(path.get(rangeEndExcl - 1), afterSplice); + break outer; } } break; @@ -457,7 +452,7 @@ public class Elytra extends Behavior implements Helper { } } } - //System.out.println("breakpoint " + count); + System.out.println("breakpoint " + count); return packed; } catch (Exception e) { e.printStackTrace(); From 157e4db7c5aab54236c551b5ba33a9062018feff Mon Sep 17 00:00:00 2001 From: Leijurv Date: Fri, 16 Jun 2023 22:39:50 -0700 Subject: [PATCH 028/276] fireworks hack --- src/main/java/baritone/Elytra.java | 29 +++++++++++++++++------------ 1 file changed, 17 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 1af15edda..75d90dc6f 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -206,17 +206,8 @@ public class Elytra extends Behavior implements Helper { Vec3d start = ctx.playerFeetAsVec(); boolean firework = isFireworkActive(); sinceFirework++; - if (!firework - && sinceFirework > 10 - && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend - && (ctx.player().posY < path.get(goingTo).y - 5 || start.distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! - && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending - ) { - logDirect("firework"); - ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); - sinceFirework = 0; - } final long t = System.currentTimeMillis(); + outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost boolean requireClear = relaxation == 0; @@ -256,12 +247,26 @@ public class Elytra extends Behavior implements Helper { goingTo = i; aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); - return; + break outermost; } } } + if (relaxation == 2) { + logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); + return; + } + } + + if (!firework + && sinceFirework > 10 + && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend + && (ctx.player().posY < path.get(goingTo).y - 5 || start.distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! + && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending + ) { + logDirect("firework"); + ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); + sinceFirework = 0; } - logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); } private boolean isFireworkActive() { From c5475498ca655a854874770d24a4eba79b2f6cbd Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 01:39:21 -0500 Subject: [PATCH 029/276] so cute --- .../baritone/api/event/events/ChunkEvent.java | 6 +- src/main/java/baritone/Elytra.java | 116 +++++++++++------- 2 files changed, 78 insertions(+), 44 deletions(-) diff --git a/src/api/java/baritone/api/event/events/ChunkEvent.java b/src/api/java/baritone/api/event/events/ChunkEvent.java index f27475bce..a7b5d96f0 100644 --- a/src/api/java/baritone/api/event/events/ChunkEvent.java +++ b/src/api/java/baritone/api/event/events/ChunkEvent.java @@ -106,6 +106,10 @@ public final class ChunkEvent { *

* And it's a partial chunk */ - POPULATE_PARTIAL + POPULATE_PARTIAL; + + public final boolean isPopulate() { + return this == POPULATE_FULL || this == POPULATE_PARTIAL; + } } } diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 75d90dc6f..e63682e11 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -44,9 +44,9 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.*; -import java.util.concurrent.Executor; -import java.util.concurrent.Executors; +import java.util.concurrent.*; import java.util.stream.Collectors; +import java.util.stream.Stream; public class Elytra extends Behavior implements Helper { @@ -57,10 +57,8 @@ public class Elytra extends Behavior implements Helper { public BlockPos aimPos; public List visiblePath; - // NetherPathfinder stuff - private long context; - - // yay! + // :sunglasses: + private final Context context; private List path; public int playerNear; private int goingTo; @@ -68,31 +66,67 @@ public class Elytra extends Behavior implements Helper { protected Elytra(Baritone baritone) { super(baritone); - // lol - this.context = NetherPathfinder.newContext(NETHER_SEED); - + this.context = new Context(NETHER_SEED); this.lines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); this.path = new ArrayList<>(); } - private final Executor packer = Executors.newSingleThreadExecutor(); + private static final class Context { + + private final long context; + private final long seed; + private final ExecutorService executor; + + public Context(long seed) { + this.context = NetherPathfinder.newContext(seed); + this.seed = seed; + this.executor = Executors.newSingleThreadExecutor(); + } + + public void queueForPacking(Chunk chunk) { + this.executor.submit(() -> NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk))); + } + + public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { + return CompletableFuture.supplyAsync(() -> + NetherPathfinder.pathFind( + this.context, + src.getX(), src.getY(), src.getZ(), + dst.getX(), dst.getY(), dst.getZ() + ), this.executor); + } + + public void destroy() { + // Ignore anything that was queued up, just shutdown the executor + this.executor.shutdownNow(); + + try { + while (!this.executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {} + } catch (InterruptedException e) { + e.printStackTrace(); + } + + NetherPathfinder.freeContext(this.context); + } + + public long getSeed() { + return this.seed; + } + } @Override public final void onChunkEvent(ChunkEvent event) { - if (event.getState() == EventState.POST && (event.getType() == ChunkEvent.Type.POPULATE_FULL || event.getType() == ChunkEvent.Type.POPULATE_PARTIAL)) { - Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); - packer.execute(() -> { - System.out.println("meow"); - NetherPathfinder.insertChunkData(context, event.getX(), event.getZ(), pack(chunk)); - }); + if (event.getState() == EventState.POST && event.getType().isPopulate()) { + final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); + this.context.queueForPacking(chunk); } } boolean recalculating; private void pathfindAroundObstacles() { - if (recalculating) { + if (this.recalculating) { return; } outer: @@ -115,7 +149,6 @@ public class Elytra extends Behavior implements Helper { // obstacle. where do we return to pathing? // find the next valid segment List afterSplice = path.subList(rangeEndExcl - 1, path.size()); - recalculating = true; path(path.get(rangeEndExcl - 1), afterSplice); break outer; } @@ -125,36 +158,33 @@ public class Elytra extends Behavior implements Helper { } public void path(BlockPos destination) { - path(destination, new ArrayList<>()); + path(destination, Collections.emptyList()); } public void path(BlockPos destination, List andThen) { - packer.execute(() -> { - long start = System.currentTimeMillis(); - final PathSegment segment = NetherPathfinder.pathFind( - this.context, - ctx.playerFeet().x, ctx.playerFeet().y, ctx.playerFeet().z, - destination.getX(), destination.getY(), destination.getZ() - ); - long end = System.currentTimeMillis(); + final boolean isRecalc = !andThen.isEmpty(); + this.recalculating = isRecalc; + + this.context.pathFindAsync(ctx.playerFeet(), destination).thenAccept(segment -> { + Stream newPath = Arrays.stream(segment.packed) + .mapToObj(BlockPos::fromLong) + .map(BetterBlockPos::new); + + List joined = Stream.concat(newPath, andThen.stream()).collect(Collectors.toList()); ctx.minecraft().addScheduledTask(() -> { - this.path = Arrays.stream(segment.packed) - .mapToObj(BlockPos::fromLong) - .map(BetterBlockPos::new) - .collect(Collectors.toList()); - final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(this.path.size() - 1))); - logDirect(String.format("Computed path in %dms. (%d blocks)", end - start, distance)); - - if (!segment.finished) { - logDirect("segment not finished. path incomplete"); - } - this.path.addAll(andThen); - if (!andThen.isEmpty()) { - recalculating = false; - } + this.path = joined; this.playerNear = 0; this.goingTo = 0; + + final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(segment.packed.length - 1))); + + if (isRecalc) { + this.recalculating = false; + logDirect(String.format("Recalculated segment (%d blocks)", distance)); + } else { + logDirect(String.format("Computed path (%d blocks)", distance)); + } removeBacktracks(); }); }); @@ -182,7 +212,7 @@ public class Elytra extends Behavior implements Helper { return; } - playerNear = fixNearPlayer(playerNear); + playerNear = calculateNear(playerNear); visiblePath = path.subList( Math.max(playerNear - 30, 0), Math.min(playerNear + 30, path.size()) @@ -390,7 +420,7 @@ public class Elytra extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - private int fixNearPlayer(int index) { + private int calculateNear(int index) { final BetterBlockPos pos = ctx.playerFeet(); for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { From 424f27c7986567168cc50b6caf7b5388d8bd13cf Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 01:41:17 -0500 Subject: [PATCH 030/276] remove debug msg --- src/main/java/baritone/Elytra.java | 4 ---- 1 file changed, 4 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index e63682e11..2f9aa223c 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -462,11 +462,9 @@ public class Elytra extends Behavior implements Helper { } private static boolean[] pack(Chunk chunk) { - //System.out.println(chunk); try { boolean[] packed = new boolean[16 * 16 * 128]; ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); - int count = 0; for (int y0 = 0; y0 < 8; y0++) { ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; if (extendedblockstorage == null) { @@ -481,13 +479,11 @@ public class Elytra extends Behavior implements Helper { IBlockState state = bsc.get(x, y1, z); if (!passable(state)) { packed[x + (z << 4) + (y << 8)] = true; - count++; } } } } } - System.out.println("breakpoint " + count); return packed; } catch (Exception e) { e.printStackTrace(); From 97e91ed680e581498666ff80d35a74923e36cdf1 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 01:42:49 -0500 Subject: [PATCH 031/276] one var --- src/main/java/baritone/Elytra.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/Elytra.java index 2f9aa223c..57f0f7cf4 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/Elytra.java @@ -166,11 +166,12 @@ public class Elytra extends Behavior implements Helper { this.recalculating = isRecalc; this.context.pathFindAsync(ctx.playerFeet(), destination).thenAccept(segment -> { - Stream newPath = Arrays.stream(segment.packed) - .mapToObj(BlockPos::fromLong) - .map(BetterBlockPos::new); - - List joined = Stream.concat(newPath, andThen.stream()).collect(Collectors.toList()); + final List joined = Stream.concat( + Arrays.stream(segment.packed) + .mapToObj(BlockPos::fromLong) + .map(BetterBlockPos::new), + andThen.stream() + ).collect(Collectors.toList()); ctx.minecraft().addScheduledTask(() -> { this.path = joined; From a67889ab4266b2fed6168a3813db8e33bd4832e1 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 01:55:07 -0500 Subject: [PATCH 032/276] refactoring --- src/main/java/baritone/Baritone.java | 8 ++++++-- .../{Elytra.java => behavior/ElytraBehavior.java} | 8 ++++---- .../baritone/command/defaults/ElytraCommand.java | 2 +- .../command/defaults/ExecutionControlCommands.java | 2 +- .../command/defaults/ForceCancelCommand.java | 2 +- src/main/java/baritone/utils/PathRenderer.java | 13 ++++++++----- 6 files changed, 21 insertions(+), 14 deletions(-) rename src/main/java/baritone/{Elytra.java => behavior/ElytraBehavior.java} (99%) diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 6199d03f5..457b49a45 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -64,7 +64,7 @@ public class Baritone implements IBaritone { private final GameEventHandler gameEventHandler; private final PathingBehavior pathingBehavior; - public final Elytra elytra; + private final ElytraBehavior elytraBehavior; private final LookBehavior lookBehavior; private final InventoryBehavior inventoryBehavior; private final InputOverrideHandler inputOverrideHandler; @@ -103,7 +103,7 @@ public class Baritone implements IBaritone { { this.pathingBehavior = this.registerBehavior(PathingBehavior::new); - this.elytra = this.registerBehavior(Elytra::new); + this.elytraBehavior = this.registerBehavior(ElytraBehavior::new); this.lookBehavior = this.registerBehavior(LookBehavior::new); this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new); this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new); @@ -232,6 +232,10 @@ public class Baritone implements IBaritone { return this.commandManager; } + public ElytraBehavior getElytraBehavior() { + return this.elytraBehavior; + } + @Override public void openClick() { new Thread(() -> { diff --git a/src/main/java/baritone/Elytra.java b/src/main/java/baritone/behavior/ElytraBehavior.java similarity index 99% rename from src/main/java/baritone/Elytra.java rename to src/main/java/baritone/behavior/ElytraBehavior.java index 57f0f7cf4..473fd7f8b 100644 --- a/src/main/java/baritone/Elytra.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -15,8 +15,9 @@ * along with Baritone. If not, see . */ -package baritone; +package baritone.behavior; +import baritone.Baritone; import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.TickEvent; import baritone.api.event.events.type.EventState; @@ -24,7 +25,6 @@ import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Helper; import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; -import baritone.behavior.Behavior; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; import dev.babbaj.pathfinder.NetherPathfinder; @@ -48,7 +48,7 @@ import java.util.concurrent.*; import java.util.stream.Collectors; import java.util.stream.Stream; -public class Elytra extends Behavior implements Helper { +public final class ElytraBehavior extends Behavior implements Helper { private static final long NETHER_SEED = 146008555100680L; @@ -64,7 +64,7 @@ public class Elytra extends Behavior implements Helper { private int goingTo; private int sinceFirework; - protected Elytra(Baritone baritone) { + public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new Context(NETHER_SEED); this.lines = new ArrayList<>(); diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 2d2e3f0ee..47db0e33e 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -41,7 +41,7 @@ public class ElytraCommand extends Command { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); GoalXZ goal = (GoalXZ) customGoalProcess.getGoal(); - ((Baritone) baritone).elytra.path(new BlockPos(goal.getX(), 64, goal.getZ())); + ((Baritone) baritone).getElytraBehavior().path(new BlockPos(goal.getX(), 64, goal.getZ())); } @Override diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index 66b2d156d..ef566bb8d 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -181,7 +181,7 @@ public class ExecutionControlCommands { paused[0] = false; } baritone.getPathingBehavior().cancelEverything(); - ((Baritone) baritone).elytra.cancel(); + ((Baritone) baritone).getElytraBehavior().cancel(); logDirect("ok canceled"); } diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index 3a54ce69e..60ccdab01 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -40,7 +40,7 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); - ((Baritone) baritone).elytra.cancel(); + ((Baritone) baritone).getElytraBehavior().cancel(); logDirect("ok force canceled"); } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 491d7906e..fa8925042 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -24,6 +24,7 @@ import baritone.api.pathing.goals.*; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.IPlayerContext; import baritone.api.utils.interfaces.IGoalRenderPos; +import baritone.behavior.ElytraBehavior; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; import com.mojang.realmsclient.util.Pair; @@ -101,15 +102,17 @@ public final class PathRenderer implements IRenderer { drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); } - drawPath(behavior.baritone.elytra.visiblePath, 0, Color.RED, false, 0, 0); - if (behavior.baritone.elytra.aimPos != null) { - drawGoal(ctx.player(), new GoalBlock(behavior.baritone.elytra.aimPos), partialTicks, Color.GREEN); + final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); + + drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0); + if (elytra.aimPos != null) { + drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN); } - if (!behavior.baritone.elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { + if (!elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); boolean orig = settings.renderPathAsLine.value; settings.renderPathAsLine.value = true; - for (Pair line : behavior.baritone.elytra.lines) { + for (Pair line : elytra.lines) { emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); } settings.renderPathAsLine.value = orig; From 395706edc9ebfb54ba8d3127397408c4354beae1 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 02:02:26 -0500 Subject: [PATCH 033/276] move context wrapper to new class --- .../baritone/behavior/ElytraBehavior.java | 90 ++------------- .../elytra/NetherPathfinderContext.java | 109 ++++++++++++++++++ 2 files changed, 117 insertions(+), 82 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 473fd7f8b..bd430b9e5 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -25,10 +25,9 @@ import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Helper; import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; +import baritone.behavior.elytra.NetherPathfinderContext; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; -import dev.babbaj.pathfinder.NetherPathfinder; -import dev.babbaj.pathfinder.PathSegment; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -39,17 +38,17 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; -import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.*; -import java.util.concurrent.*; import java.util.stream.Collectors; import java.util.stream.Stream; public final class ElytraBehavior extends Behavior implements Helper { + /** + * 2b2t seed + */ private static final long NETHER_SEED = 146008555100680L; // Used exclusively for PathRenderer @@ -58,7 +57,7 @@ public final class ElytraBehavior extends Behavior implements Helper { public List visiblePath; // :sunglasses: - private final Context context; + private final NetherPathfinderContext context; private List path; public int playerNear; private int goingTo; @@ -66,57 +65,14 @@ public final class ElytraBehavior extends Behavior implements Helper { public ElytraBehavior(Baritone baritone) { super(baritone); - this.context = new Context(NETHER_SEED); + this.context = new NetherPathfinderContext(NETHER_SEED); this.lines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); this.path = new ArrayList<>(); } - private static final class Context { - - private final long context; - private final long seed; - private final ExecutorService executor; - - public Context(long seed) { - this.context = NetherPathfinder.newContext(seed); - this.seed = seed; - this.executor = Executors.newSingleThreadExecutor(); - } - - public void queueForPacking(Chunk chunk) { - this.executor.submit(() -> NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk))); - } - - public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { - return CompletableFuture.supplyAsync(() -> - NetherPathfinder.pathFind( - this.context, - src.getX(), src.getY(), src.getZ(), - dst.getX(), dst.getY(), dst.getZ() - ), this.executor); - } - - public void destroy() { - // Ignore anything that was queued up, just shutdown the executor - this.executor.shutdownNow(); - - try { - while (!this.executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {} - } catch (InterruptedException e) { - e.printStackTrace(); - } - - NetherPathfinder.freeContext(this.context); - } - - public long getSeed() { - return this.seed; - } - } - @Override - public final void onChunkEvent(ChunkEvent event) { + public void onChunkEvent(ChunkEvent event) { if (event.getState() == EventState.POST && event.getType().isPopulate()) { final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); this.context.queueForPacking(chunk); @@ -366,7 +322,7 @@ public final class ElytraBehavior extends Behavior implements Helper { return bestPitch; } - private static boolean passable(IBlockState state) { + public static boolean passable(IBlockState state) { return state.getMaterial() == Material.AIR; } @@ -462,36 +418,6 @@ public final class ElytraBehavior extends Behavior implements Helper { } } - private static boolean[] pack(Chunk chunk) { - try { - boolean[] packed = new boolean[16 * 16 * 128]; - ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); - for (int y0 = 0; y0 < 8; y0++) { - ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; - if (extendedblockstorage == null) { - continue; - } - BlockStateContainer bsc = extendedblockstorage.getData(); - int yReal = y0 << 4; - for (int y1 = 0; y1 < 16; y1++) { - int y = y1 | yReal; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - IBlockState state = bsc.get(x, y1, z); - if (!passable(state)) { - packed[x + (z << 4) + (y << 8)] = true; - } - } - } - } - } - return packed; - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - // TODO: Use the optimized version from builder-2 private RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { int x1 = MathHelper.floor(end.x); diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java new file mode 100644 index 000000000..33a8569f7 --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -0,0 +1,109 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +import dev.babbaj.pathfinder.NetherPathfinder; +import dev.babbaj.pathfinder.PathSegment; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.world.chunk.BlockStateContainer; +import net.minecraft.world.chunk.Chunk; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; + +import static baritone.behavior.ElytraBehavior.passable; + +/** + * @author Brady + */ +public final class NetherPathfinderContext { + + private final long context; + private final long seed; + private final ExecutorService executor; + + public NetherPathfinderContext(long seed) { + this.context = NetherPathfinder.newContext(seed); + this.seed = seed; + this.executor = Executors.newSingleThreadExecutor(); + } + + public void queueForPacking(Chunk chunk) { + this.executor.submit(() -> NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk))); + } + + public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { + return CompletableFuture.supplyAsync(() -> + NetherPathfinder.pathFind( + this.context, + src.getX(), src.getY(), src.getZ(), + dst.getX(), dst.getY(), dst.getZ() + ), this.executor); + } + + public void destroy() { + // Ignore anything that was queued up, just shutdown the executor + this.executor.shutdownNow(); + + try { + while (!this.executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {} + } catch (InterruptedException e) { + e.printStackTrace(); + } + + NetherPathfinder.freeContext(this.context); + } + + public long getSeed() { + return this.seed; + } + + private static boolean[] pack(Chunk chunk) { + try { + boolean[] packed = new boolean[16 * 16 * 128]; + ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + for (int y0 = 0; y0 < 8; y0++) { + ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; + if (extendedblockstorage == null) { + continue; + } + BlockStateContainer bsc = extendedblockstorage.getData(); + int yReal = y0 << 4; + for (int y1 = 0; y1 < 16; y1++) { + int y = y1 | yReal; + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + IBlockState state = bsc.get(x, y1, z); + if (!passable(state)) { + packed[x + (z << 4) + (y << 8)] = true; + } + } + } + } + } + return packed; + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } +} From 0290b344dc7e9ccdf548bb2b44c28c49d33ed84a Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 02:33:43 -0500 Subject: [PATCH 034/276] Cancel before shutting down executor --- .../baritone/behavior/elytra/NetherPathfinderContext.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 33a8569f7..0fb1983f9 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -60,7 +60,12 @@ public final class NetherPathfinderContext { ), this.executor); } + public void cancel() { + NetherPathfinder.cancel(this.context); + } + public void destroy() { + this.cancel(); // Ignore anything that was queued up, just shutdown the executor this.executor.shutdownNow(); From d1a6de06e20ec677d902fd4234dfa7eb9422792d Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 14:15:57 -0500 Subject: [PATCH 035/276] =?UTF-8?q?=F0=9F=98=BC=20`PathManager`?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../baritone/behavior/ElytraBehavior.java | 366 +++++++++++------- .../behavior/elytra/UnpackedSegment.java | 65 ++++ 2 files changed, 299 insertions(+), 132 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/UnpackedSegment.java diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index bd430b9e5..2226f5b1b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -26,6 +26,7 @@ import baritone.api.utils.Helper; import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; import baritone.behavior.elytra.NetherPathfinderContext; +import baritone.behavior.elytra.UnpackedSegment; import baritone.utils.BlockStateInterface; import com.mojang.realmsclient.util.Pair; import net.minecraft.block.material.Material; @@ -41,8 +42,8 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.Chunk; import java.util.*; -import java.util.stream.Collectors; -import java.util.stream.Stream; +import java.util.concurrent.CompletableFuture; +import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements Helper { @@ -58,9 +59,7 @@ public final class ElytraBehavior extends Behavior implements Helper { // :sunglasses: private final NetherPathfinderContext context; - private List path; - public int playerNear; - private int goingTo; + private final PathManager pathManager; private int sinceFirework; public ElytraBehavior(Baritone baritone) { @@ -68,7 +67,217 @@ public final class ElytraBehavior extends Behavior implements Helper { this.context = new NetherPathfinderContext(NETHER_SEED); this.lines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); - this.path = new ArrayList<>(); + this.pathManager = new PathManager(); + } + + private final class PathManager { + + private BlockPos destination; + private List path; + private boolean completePath; + + private int playerNear; + private int goingTo; + + private boolean recalculating; + + public PathManager() { + // lol imagine initializing fields normally + this.clear(); + } + + public void tick() { + // Recalculate closest path node + this.playerNear = this.calculateNear(this.playerNear); + + // Obstacles are more important than an incomplete path, handle those first. + this.pathfindAroundObstacles(); + this.attemptNextSegment(); + } + + public void pathToDestination(BlockPos destination) { + this.destination = destination; + this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) + .thenRun(() -> { + final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); + if (this.completePath) { + logDirect(String.format("Computed path (%d blocks)", distance)); + } else { + logDirect(String.format("Computed segment (Next %d blocks)", distance)); + } + }); + } + + public void recalcSegment(final int upToIncl) { + if (this.recalculating) { + return; + } + + this.recalculating = true; + final List after = this.path.subList(upToIncl, this.path.size()); + final boolean complete = this.completePath; + + this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) + .thenRun(() -> { + this.recalculating = false; + final int recompute = this.path.size() - after.size() - 1; + final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); + logDirect(String.format("Recomputed segment (Next %d blocks)", distance)); + }); + } + + public void nextSegment(final int afterIncl) { + if (this.recalculating) { + return; + } + + this.recalculating = true; + final List before = this.path.subList(0, afterIncl + 1); + + this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) + .thenRun(() -> { + this.recalculating = false; + final int recompute = this.path.size() - before.size() - 1; + final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); + + if (this.completePath) { + logDirect(String.format("Computed path (%d blocks)", distance)); + } else { + logDirect(String.format("Computed next segment (Next %d blocks)", distance)); + } + }); + } + + private Vec3d pathAt(int i) { + return new Vec3d( + this.path.get(i).x + 0.5, + this.path.get(i).y + 0.5, + this.path.get(i).z + 0.5 + ); + } + + public void clear() { + this.path = Collections.emptyList(); + this.playerNear = 0; + this.goingTo = 0; + this.completePath = true; + } + + private void setPath(final UnpackedSegment segment) { + this.path = segment.collect(); + this.removeBacktracks(); + this.playerNear = 0; + this.goingTo = 0; + this.completePath = segment.isFinished(); + } + + public List getPath() { + return this.path; + } + + public int getNear() { + return this.playerNear; + } + + public void setGoingTo(int index) { + this.goingTo = index; + } + + public BetterBlockPos goingTo() { + return this.path.get(this.goingTo); + } + + // mickey resigned + private CompletableFuture path0(BlockPos src, BlockPos dst, UnaryOperator operator) { + return ElytraBehavior.this.context.pathFindAsync(src, dst) + .thenApply(UnpackedSegment::from) + .thenApply(operator) + .thenAcceptAsync(this::setPath, ctx.minecraft()::addScheduledTask); + } + + private void pathfindAroundObstacles() { + if (this.recalculating) { + return; + } + + outer: + while (true) { + int rangeStartIncl = playerNear; + int rangeEndExcl = playerNear; + while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { + rangeEndExcl++; + } + if (rangeStartIncl >= rangeEndExcl) { + // not loaded yet? + return; + } + if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { + // we're in a wall + return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: + } + for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { + if (!clearView(pathAt(i), pathAt(i + 1))) { + // obstacle. where do we return to pathing? + // find the next valid segment + this.recalcSegment(rangeEndExcl - 1); + break outer; + } + } + break; + } + } + + private void attemptNextSegment() { + if (this.recalculating) { + return; + } + + final int last = this.path.size() - 1; + if (!this.completePath && ctx.world().isBlockLoaded(this.path.get(last), false)) { + this.nextSegment(last); + } + } + + private int calculateNear(int index) { + final BetterBlockPos pos = ctx.playerFeet(); + for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop + } + } + for (int i = index; i < Math.min(index + 1000, path.size()); i += 10) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop + } + } + for (int i = index; i >= Math.max(index - 50, 0); i--) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop + } + } + for (int i = index; i < Math.min(index + 50, path.size()); i++) { + if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { + index = i; // intentional: this changes the bound of the loop + } + } + return index; + } + + private void removeBacktracks() { + Map positionFirstSeen = new HashMap<>(); + for (int i = 0; i < this.path.size(); i++) { + BetterBlockPos pos = this.path.get(i); + if (positionFirstSeen.containsKey(pos)) { + int j = positionFirstSeen.get(pos); + while (i > j) { + this.path.remove(i); + i--; + } + } else { + positionFirstSeen.put(pos, i); + } + } + } } @Override @@ -79,106 +288,38 @@ public final class ElytraBehavior extends Behavior implements Helper { } } - boolean recalculating; - - private void pathfindAroundObstacles() { - if (this.recalculating) { - return; - } - outer: - while (true) { - int rangeStartIncl = playerNear; - int rangeEndExcl = playerNear; - while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { - rangeEndExcl++; - } - if (rangeStartIncl >= rangeEndExcl) { - // not loaded yet? - return; - } - if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { - // we're in a wall - return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: - } - for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!clearView(pathAt(i), pathAt(i + 1))) { - // obstacle. where do we return to pathing? - // find the next valid segment - List afterSplice = path.subList(rangeEndExcl - 1, path.size()); - path(path.get(rangeEndExcl - 1), afterSplice); - break outer; - } - } - break; - } - } - public void path(BlockPos destination) { - path(destination, Collections.emptyList()); - } - - public void path(BlockPos destination, List andThen) { - final boolean isRecalc = !andThen.isEmpty(); - this.recalculating = isRecalc; - - this.context.pathFindAsync(ctx.playerFeet(), destination).thenAccept(segment -> { - final List joined = Stream.concat( - Arrays.stream(segment.packed) - .mapToObj(BlockPos::fromLong) - .map(BetterBlockPos::new), - andThen.stream() - ).collect(Collectors.toList()); - - ctx.minecraft().addScheduledTask(() -> { - this.path = joined; - this.playerNear = 0; - this.goingTo = 0; - - final int distance = (int) Math.sqrt(this.path.get(0).distanceSq(this.path.get(segment.packed.length - 1))); - - if (isRecalc) { - this.recalculating = false; - logDirect(String.format("Recalculated segment (%d blocks)", distance)); - } else { - logDirect(String.format("Computed path (%d blocks)", distance)); - } - removeBacktracks(); - }); - }); + this.pathManager.pathToDestination(destination); } public void cancel() { this.visiblePath = Collections.emptyList(); - this.path.clear(); + this.pathManager.clear(); this.aimPos = null; - this.playerNear = 0; - this.goingTo = 0; this.sinceFirework = 0; } - private Vec3d pathAt(int i) { - return new Vec3d(path.get(i).x + 0.5, path.get(i).y + 0.5, path.get(i).z + 0.5); - } - @Override public void onTick(TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { return; } + this.lines.clear(); + + final List path = this.pathManager.getPath(); if (path.isEmpty()) { return; } - playerNear = calculateNear(playerNear); - visiblePath = path.subList( + this.pathManager.tick(); + + final int playerNear = this.pathManager.getNear(); + this.visiblePath = path.subList( Math.max(playerNear - 30, 0), Math.min(playerNear + 30, path.size()) ); baritone.getInputOverrideHandler().clearAllKeys(); // FIXME: This breaks the regular path-finder - lines.clear(); - - pathfindAroundObstacles(); if (!ctx.player().isElytraFlying()) { return; @@ -204,19 +345,19 @@ public final class ElytraBehavior extends Behavior implements Helper { int minStep = playerNear; for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { - Vec3d dest = pathAt(i).add(0, dy, 0); + Vec3d dest = this.pathManager.pathAt(i).add(0, dy, 0); if (dy != 0) { if (i + lookahead >= path.size()) { continue; } if (start.distanceTo(dest) < 40) { - if (!clearView(dest, pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, pathAt(i + lookahead))) { + if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, this.pathManager.pathAt(i + lookahead))) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, pathAt(i))) { + if (!clearView(dest, this.pathManager.pathAt(i))) { continue; } } @@ -231,8 +372,8 @@ public final class ElytraBehavior extends Behavior implements Helper { } long b = System.currentTimeMillis(); System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); - goingTo = i; - aimPos = path.get(i).add(0, dy, 0); + this.pathManager.setGoingTo(i); + this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); break outermost; } @@ -244,11 +385,13 @@ public final class ElytraBehavior extends Behavior implements Helper { } } + final BetterBlockPos goingTo = this.pathManager.goingTo(); + if (!firework && sinceFirework > 10 - && (Baritone.settings().wasteFireworks.value || ctx.player().posY < path.get(goingTo).y + 5) // don't firework if trying to descend - && (ctx.player().posY < path.get(goingTo).y - 5 || start.distanceTo(new Vec3d(path.get(goingTo).x + 0.5, ctx.player().posY, path.get(goingTo).z + 0.5)) > 5) // UGH!!!!!!! - && new Vec3d(ctx.player().motionX, ctx.player().posY < path.get(goingTo).y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending + && (Baritone.settings().wasteFireworks.value || ctx.player().posY < goingTo.y + 5) // don't firework if trying to descend + && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! + && new Vec3d(ctx.player().motionX, ctx.player().posY < goingTo.y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending ) { logDirect("firework"); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); @@ -377,47 +520,6 @@ public final class ElytraBehavior extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - private int calculateNear(int index) { - final BetterBlockPos pos = ctx.playerFeet(); - for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { - if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { - index = i; // intentional: this changes the bound of the loop - } - } - for (int i = index; i < Math.min(index + 1000, path.size()); i += 10) { - if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { - index = i; // intentional: this changes the bound of the loop - } - } - for (int i = index; i >= Math.max(index - 50, 0); i--) { - if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { - index = i; // intentional: this changes the bound of the loop - } - } - for (int i = index; i < Math.min(index + 50, path.size()); i++) { - if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { - index = i; // intentional: this changes the bound of the loop - } - } - return index; - } - - private void removeBacktracks() { - Map positionFirstSeen = new HashMap<>(); - for (int i = 0; i < path.size(); i++) { - BetterBlockPos pos = path.get(i); - if (positionFirstSeen.containsKey(pos)) { - int j = positionFirstSeen.get(pos); - while (i > j) { - path.remove(i); - i--; - } - } else { - positionFirstSeen.put(pos, i); - } - } - } - // TODO: Use the optimized version from builder-2 private RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { int x1 = MathHelper.floor(end.x); diff --git a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java new file mode 100644 index 000000000..7798113da --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java @@ -0,0 +1,65 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +import baritone.api.utils.BetterBlockPos; +import dev.babbaj.pathfinder.PathSegment; +import net.minecraft.util.math.BlockPos; + +import java.util.Arrays; +import java.util.List; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +/** + * @author Brady + */ +public final class UnpackedSegment { + + private final Stream path; + private final boolean finished; + + public UnpackedSegment(Stream path, boolean finished) { + this.path = path; + this.finished = finished; + } + + public UnpackedSegment append(Stream other, boolean otherFinished) { + // The new segment is only finished if the one getting added on is + return new UnpackedSegment(Stream.concat(this.path, other), otherFinished); + } + + public UnpackedSegment prepend(Stream other) { + return new UnpackedSegment(Stream.concat(other, this.path), this.finished); + } + + public List collect() { + return this.path.collect(Collectors.toList()); + } + + public boolean isFinished() { + return this.finished; + } + + public static UnpackedSegment from(final PathSegment segment) { + return new UnpackedSegment( + Arrays.stream(segment.packed).mapToObj(BlockPos::fromLong).map(BetterBlockPos::new), + segment.finished + ); + } +} From 4c2984a9a0201ecd791ff4df82911e0de923cd09 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 14:21:32 -0500 Subject: [PATCH 036/276] Consistent `path` prefix for methods --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 2226f5b1b..3109a6dcc 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -108,7 +108,7 @@ public final class ElytraBehavior extends Behavior implements Helper { }); } - public void recalcSegment(final int upToIncl) { + public void pathRecalcSegment(final int upToIncl) { if (this.recalculating) { return; } @@ -126,7 +126,7 @@ public final class ElytraBehavior extends Behavior implements Helper { }); } - public void nextSegment(final int afterIncl) { + public void pathNextSegment(final int afterIncl) { if (this.recalculating) { return; } @@ -219,7 +219,7 @@ public final class ElytraBehavior extends Behavior implements Helper { if (!clearView(pathAt(i), pathAt(i + 1))) { // obstacle. where do we return to pathing? // find the next valid segment - this.recalcSegment(rangeEndExcl - 1); + this.pathRecalcSegment(rangeEndExcl - 1); break outer; } } @@ -234,7 +234,7 @@ public final class ElytraBehavior extends Behavior implements Helper { final int last = this.path.size() - 1; if (!this.completePath && ctx.world().isBlockLoaded(this.path.get(last), false)) { - this.nextSegment(last); + this.pathNextSegment(last); } } From 64a5ceabd8b1d4552435c0fc447e9b6ca3d9f59a Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 15:35:26 -0500 Subject: [PATCH 037/276] Fix the regular pathfinder issue --- src/main/java/baritone/behavior/ElytraBehavior.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3109a6dcc..214a0d1fd 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -319,11 +319,12 @@ public final class ElytraBehavior extends Behavior implements Helper { Math.min(playerNear + 30, path.size()) ); - baritone.getInputOverrideHandler().clearAllKeys(); // FIXME: This breaks the regular path-finder - if (!ctx.player().isElytraFlying()) { return; } + + baritone.getInputOverrideHandler().clearAllKeys(); + if (ctx.player().collidedHorizontally) { logDirect("hbonk"); } From 91609f4ebfc6598efda86316b60d00cca548d8b3 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 19:36:29 -0500 Subject: [PATCH 038/276] Use player bounding box in isClear --- .../baritone/behavior/ElytraBehavior.java | 46 +++++++++++++------ 1 file changed, 33 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 214a0d1fd..3e5dde199 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -35,10 +35,7 @@ import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.init.Blocks; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.RayTraceResult; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.*; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -339,7 +336,6 @@ public final class ElytraBehavior extends Behavior implements Helper { outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost - boolean requireClear = relaxation == 0; int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); @@ -363,7 +359,12 @@ public final class ElytraBehavior extends Behavior implements Helper { } } } - if (requireClear ? isClear(start, dest) : clearView(start, dest)) { + + // 1.0 -> 0.25 -> none + final Double grow = relaxation == 2 ? null + : relaxation == 0 ? 1.0d : 0.25d; + + if (isClear(start, dest, grow)) { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); long a = System.currentTimeMillis(); Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); @@ -406,13 +407,32 @@ public final class ElytraBehavior extends Behavior implements Helper { .anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); } - private boolean isClear(Vec3d start, Vec3d dest) { - Vec3d perpendicular = dest.subtract(start).crossProduct(new Vec3d(0, 1, 0)).normalize(); - return clearView(start, dest) - && clearView(start.add(0, 2, 0), dest.add(0, 2, 0)) - && clearView(start.add(0, -2, 0), dest.add(0, -2, 0)) - && clearView(start.add(perpendicular), dest.add(perpendicular)) - && clearView(start.subtract(perpendicular), dest.subtract(perpendicular)); + private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount) { + if (!clearView(start, dest)) { + return false; + } + if (growAmount == null) { + return true; + } + + final AxisAlignedBB bb = ctx.player().getEntityBoundingBox().grow(growAmount); + final Vec3d[] corners = new Vec3d[] { + new Vec3d(bb.minX, bb.minY, bb.minZ), + new Vec3d(bb.minX, bb.minY, bb.maxZ), + new Vec3d(bb.minX, bb.maxY, bb.minZ), + new Vec3d(bb.minX, bb.maxY, bb.maxZ), + new Vec3d(bb.maxX, bb.minY, bb.minZ), + new Vec3d(bb.maxX, bb.minY, bb.maxZ), + new Vec3d(bb.maxX, bb.maxY, bb.minZ), + new Vec3d(bb.maxX, bb.maxY, bb.maxZ), + }; + + for (final Vec3d corner : corners) { + if (!clearView(corner, dest.add(corner.subtract(start)))) { + return false; + } + } + return true; } private boolean clearView(Vec3d start, Vec3d dest) { From fcf8cd35d24a2b85630c9c10ceeec09360986f7f Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 19:58:19 -0500 Subject: [PATCH 039/276] Handle exception to ensure `recalculating` is reset --- .../baritone/behavior/ElytraBehavior.java | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3e5dde199..94033d60a 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -95,7 +95,11 @@ public final class ElytraBehavior extends Behavior implements Helper { public void pathToDestination(BlockPos destination) { this.destination = destination; this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) - .thenRun(() -> { + .whenComplete((__, ex) -> { + if (ex != null) { + logDirect("Failed to compute path to destination"); + return; + } final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); if (this.completePath) { logDirect(String.format("Computed path (%d blocks)", distance)); @@ -115,8 +119,12 @@ public final class ElytraBehavior extends Behavior implements Helper { final boolean complete = this.completePath; this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) - .thenRun(() -> { + .whenComplete((__, ex) -> { this.recalculating = false; + if (ex != null) { + logDirect("Failed to recompute segment"); + return; + } final int recompute = this.path.size() - after.size() - 1; final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); logDirect(String.format("Recomputed segment (Next %d blocks)", distance)); @@ -132,8 +140,13 @@ public final class ElytraBehavior extends Behavior implements Helper { final List before = this.path.subList(0, afterIncl + 1); this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) - .thenRun(() -> { + .whenComplete((__, ex) -> { this.recalculating = false; + if (ex != null) { + logDirect("Failed to compute next segment"); + return; + } + final int recompute = this.path.size() - before.size() - 1; final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); From fef7ba47010072af6bae29a204b60b00eca08296 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sat, 17 Jun 2023 20:03:30 -0700 Subject: [PATCH 040/276] tweaks --- build.gradle | 4 ++-- src/main/java/baritone/behavior/ElytraBehavior.java | 12 ++++++------ .../behavior/elytra/NetherPathfinderContext.java | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/build.gradle b/build.gradle index a389ae08f..6d0ba4f1a 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.8') + launchImplementation('dev.babbaj:nether-pathfinder:0.12') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.8' + implementation 'dev.babbaj:nether-pathfinder:0.12' } mixin { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 94033d60a..e745ad53c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -160,9 +160,9 @@ public final class ElytraBehavior extends Behavior implements Helper { private Vec3d pathAt(int i) { return new Vec3d( - this.path.get(i).x + 0.5, - this.path.get(i).y + 0.5, - this.path.get(i).z + 0.5 + this.path.get(i).x, + this.path.get(i).y, + this.path.get(i).z ); } @@ -326,7 +326,7 @@ public final class ElytraBehavior extends Behavior implements Helper { final int playerNear = this.pathManager.getNear(); this.visiblePath = path.subList( Math.max(playerNear - 30, 0), - Math.min(playerNear + 30, path.size()) + Math.min(playerNear + 100, path.size()) ); if (!ctx.player().isElytraFlying()) { @@ -429,7 +429,7 @@ public final class ElytraBehavior extends Behavior implements Helper { } final AxisAlignedBB bb = ctx.player().getEntityBoundingBox().grow(growAmount); - final Vec3d[] corners = new Vec3d[] { + final Vec3d[] corners = new Vec3d[]{ new Vec3d(bb.minX, bb.minY, bb.minZ), new Vec3d(bb.minX, bb.minY, bb.maxZ), new Vec3d(bb.minX, bb.maxY, bb.minZ), @@ -479,7 +479,7 @@ public final class ElytraBehavior extends Behavior implements Helper { totalMotion = totalMotion.add(stepped); Vec3d actualPosition = ctx.playerFeetAsVec().add(totalMotion); for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { - for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 0.8; y++) { + for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 1; y++) { for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { if (!passable(bsi.get0(x, y, z))) { continue outer; diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 0fb1983f9..1c512b9c2 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -56,7 +56,8 @@ public final class NetherPathfinderContext { NetherPathfinder.pathFind( this.context, src.getX(), src.getY(), src.getZ(), - dst.getX(), dst.getY(), dst.getZ() + dst.getX(), dst.getY(), dst.getZ(), + true ), this.executor); } From 94027d17f2b6ec55558e7ec75f19857d5bac4e41 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sat, 17 Jun 2023 20:12:05 -0700 Subject: [PATCH 041/276] gaming --- .../gradle/task/BaritoneGradleTask.java | 40 +++++++++---------- 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java b/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java index 7e26dac11..a542278aa 100644 --- a/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java +++ b/buildSrc/src/main/java/baritone/gradle/task/BaritoneGradleTask.java @@ -32,21 +32,21 @@ import java.nio.file.Paths; class BaritoneGradleTask extends DefaultTask { protected static final String - PROGUARD_ZIP = "proguard.zip", - PROGUARD_JAR = "proguard.jar", - PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro", - PROGUARD_CONFIG_DEST = "template.pro", - PROGUARD_API_CONFIG = "api.pro", - PROGUARD_STANDALONE_CONFIG = "standalone.pro", - PROGUARD_EXPORT_PATH = "proguard_out.jar", + PROGUARD_ZIP = "proguard.zip", + PROGUARD_JAR = "proguard.jar", + PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro", + PROGUARD_CONFIG_DEST = "template.pro", + PROGUARD_API_CONFIG = "api.pro", + PROGUARD_STANDALONE_CONFIG = "standalone.pro", + PROGUARD_EXPORT_PATH = "proguard_out.jar", - TEMP_LIBRARY_DIR = "tempLibraries/", + TEMP_LIBRARY_DIR = "tempLibraries/", - ARTIFACT_STANDARD = "%s-%s.jar", - ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar", - ARTIFACT_API = "%s-api-%s.jar", - ARTIFACT_STANDALONE = "%s-standalone-%s.jar", - ARTIFACT_FORGE_API = "%s-api-forge-%s.jar", + ARTIFACT_STANDARD = "%s-%s.jar", + ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar", + ARTIFACT_API = "%s-api-%s.jar", + ARTIFACT_STANDALONE = "%s-standalone-%s.jar", + ARTIFACT_FORGE_API = "%s-api-forge-%s.jar", ARTIFACT_FORGE_STANDALONE = "%s-standalone-forge-%s.jar"; protected String artifactName, artifactVersion; @@ -56,17 +56,17 @@ class BaritoneGradleTask extends DefaultTask { this.artifactName = getProject().getName(); this.artifactVersion = getProject().getVersion().toString(); - this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD)); - this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED)); - this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API)); - this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE)); - this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API)); + this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD)); + this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED)); + this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API)); + this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE)); + this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API)); this.artifactForgeStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_STANDALONE)); this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH); if (!Files.exists(this.artifactPath)) { - throw new IllegalStateException("Artifact not found! Run build first!"); + throw new IllegalStateException("Artifact not found! Run build first! " + this.artifactPath); } } @@ -82,7 +82,7 @@ class BaritoneGradleTask extends DefaultTask { } protected Path getRelativeFile(String file) { - return Paths.get(new File(file).getAbsolutePath()); + return Paths.get(this.getProject().file(file).getAbsolutePath()); } protected Path getTemporaryFile(String file) { From 76c5c1155f7b237d1d1dae6c5cc593949a2b998d Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 18 Jun 2023 00:51:07 -0400 Subject: [PATCH 042/276] Fix ElytraCommand throwing exception for invalid goals --- .../baritone/behavior/ElytraBehavior.java | 4 +-- .../elytra/NetherPathfinderContext.java | 4 +-- .../command/defaults/ElytraCommand.java | 29 +++++++++++++++++-- 3 files changed, 30 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index e745ad53c..d4608a705 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -386,7 +386,7 @@ public final class ElytraBehavior extends Behavior implements Helper { continue; } long b = System.currentTimeMillis(); - System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); + //System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); this.pathManager.setGoingTo(i); this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); @@ -648,4 +648,4 @@ public final class ElytraBehavior extends Behavior implements Helper { } return null; } -} +} \ No newline at end of file diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 1c512b9c2..2d407375a 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -100,7 +100,7 @@ public final class NetherPathfinderContext { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); if (!passable(state)) { - packed[x + (z << 4) + (y << 8)] = true; + packed[x | (z << 4) | (y << 8)] = true; } } } @@ -112,4 +112,4 @@ public final class NetherPathfinderContext { throw new RuntimeException(e); } } -} +} \ No newline at end of file diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 47db0e33e..1c9ee7882 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -22,6 +22,9 @@ import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; +import baritone.api.command.exception.CommandInvalidStateException; +import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalXZ; import baritone.api.process.ICustomGoalProcess; import net.minecraft.util.math.BlockPos; @@ -40,8 +43,28 @@ public class ElytraCommand extends Command { public void execute(String label, IArgConsumer args) throws CommandException { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); - GoalXZ goal = (GoalXZ) customGoalProcess.getGoal(); - ((Baritone) baritone).getElytraBehavior().path(new BlockPos(goal.getX(), 64, goal.getZ())); + Goal iGoal = customGoalProcess.getGoal(); + if (iGoal == null) { + throw new CommandInvalidStateException("No goal has been set"); + } + final int x, y, z; + if (iGoal instanceof GoalXZ) { + GoalXZ goal = (GoalXZ) iGoal; + x = goal.getX(); + y = 64; + z = goal.getZ(); + } else if (iGoal instanceof GoalBlock) { + GoalBlock goal = (GoalBlock) iGoal; + x = goal.x; + y = goal.y; + z = goal.z; + } else { + throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + } + if (y <= 0 || y >= 128) { + throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); + } + ((Baritone) baritone).getElytraBehavior().path(new BlockPos(x, y, z)); } @Override @@ -58,4 +81,4 @@ public class ElytraCommand extends Command { public List getLongDesc() { return Arrays.asList(); } -} +} \ No newline at end of file From da31a643b393e607fe26aa8aa70562ea9925bccb Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 17 Jun 2023 20:16:26 -0500 Subject: [PATCH 043/276] unscuff --- .../baritone/behavior/ElytraBehavior.java | 39 ++++++++++--------- 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index d4608a705..75ceb6b5b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -95,17 +95,19 @@ public final class ElytraBehavior extends Behavior implements Helper { public void pathToDestination(BlockPos destination) { this.destination = destination; this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) - .whenComplete((__, ex) -> { - if (ex != null) { - logDirect("Failed to compute path to destination"); - return; - } + .thenRun(() -> { final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); if (this.completePath) { logDirect(String.format("Computed path (%d blocks)", distance)); } else { logDirect(String.format("Computed segment (Next %d blocks)", distance)); } + }) + .whenComplete((result, ex) -> { + this.recalculating = false; + if (ex != null) { + logDirect("Failed to compute path to destination"); + } }); } @@ -119,15 +121,16 @@ public final class ElytraBehavior extends Behavior implements Helper { final boolean complete = this.completePath; this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) - .whenComplete((__, ex) -> { - this.recalculating = false; - if (ex != null) { - logDirect("Failed to recompute segment"); - return; - } + .thenRun(() -> { final int recompute = this.path.size() - after.size() - 1; final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); logDirect(String.format("Recomputed segment (Next %d blocks)", distance)); + }) + .whenComplete((result, ex) -> { + this.recalculating = false; + if (ex != null) { + logDirect("Failed to recompute segment"); + } }); } @@ -140,13 +143,7 @@ public final class ElytraBehavior extends Behavior implements Helper { final List before = this.path.subList(0, afterIncl + 1); this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) - .whenComplete((__, ex) -> { - this.recalculating = false; - if (ex != null) { - logDirect("Failed to compute next segment"); - return; - } - + .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); @@ -155,6 +152,12 @@ public final class ElytraBehavior extends Behavior implements Helper { } else { logDirect(String.format("Computed next segment (Next %d blocks)", distance)); } + }) + .whenComplete((result, ex) -> { + this.recalculating = false; + if (ex != null) { + logDirect("Failed to compute next segment"); + } }); } From 688bbb83c8dbe484b2b5285636b4a6b141ea2e4c Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 00:11:40 -0500 Subject: [PATCH 044/276] Rename `wasteFireworks` to `conserveFireworks` and invert --- src/api/java/baritone/api/Settings.java | 2 +- .../java/baritone/behavior/ElytraBehavior.java | 14 ++++++-------- 2 files changed, 7 insertions(+), 9 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index f5cf3c77a..24e54c136 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -51,7 +51,7 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); public final Setting elytraFireworkSpeed = new Setting<>(0.6); - public final Setting wasteFireworks = new Setting<>(false); + public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 75ceb6b5b..9945d0b31 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -345,10 +345,10 @@ public final class ElytraBehavior extends Behavior implements Helper { logDirect("vbonk"); } - Vec3d start = ctx.playerFeetAsVec(); - boolean firework = isFireworkActive(); - sinceFirework++; - final long t = System.currentTimeMillis(); + final Vec3d start = ctx.playerFeetAsVec(); + final boolean firework = isFireworkActive(); + this.sinceFirework++; + outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost @@ -382,14 +382,11 @@ public final class ElytraBehavior extends Behavior implements Helper { if (isClear(start, dest, grow)) { Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); - long a = System.currentTimeMillis(); Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); if (pitch == null) { baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), ctx.playerRotations().getPitch()), false); continue; } - long b = System.currentTimeMillis(); - //System.out.println("Solved pitch in " + (b - a) + " total time " + (b - t)); this.pathManager.setGoingTo(i); this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); @@ -404,10 +401,11 @@ public final class ElytraBehavior extends Behavior implements Helper { } final BetterBlockPos goingTo = this.pathManager.goingTo(); + final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; if (!firework && sinceFirework > 10 - && (Baritone.settings().wasteFireworks.value || ctx.player().posY < goingTo.y + 5) // don't firework if trying to descend + && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! && new Vec3d(ctx.player().motionX, ctx.player().posY < goingTo.y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending ) { From d66b8f1dd8b5c96f741ae016868b689501441aef Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 00:13:55 -0500 Subject: [PATCH 045/276] Extract `currentSpeed` into variable --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 9945d0b31..8fdcb34f6 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -402,12 +402,18 @@ public final class ElytraBehavior extends Behavior implements Helper { final BetterBlockPos goingTo = this.pathManager.goingTo(); final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; + final double currentSpeed = new Vec3d( + ctx.player().motionX, + // ignore y component if we are BOTH below where we want to be AND descending + ctx.player().posY < goingTo.y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, + ctx.player().motionZ + ).length(); if (!firework && sinceFirework > 10 && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! - && new Vec3d(ctx.player().motionX, ctx.player().posY < goingTo.y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ).length() < Baritone.settings().elytraFireworkSpeed.value // ignore y component if we are BOTH below where we want to be AND descending + && currentSpeed < Baritone.settings().elytraFireworkSpeed.value ) { logDirect("firework"); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); From d4e6a84ec96ce5d2043d2a1d5b4ee5d4cee113c3 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 10:57:13 -0500 Subject: [PATCH 046/276] Remove usage of realms Pair class --- src/api/java/baritone/api/utils/Pair.java | 59 +++++++++++++++++++ .../baritone/behavior/ElytraBehavior.java | 14 ++--- .../java/baritone/utils/PathRenderer.java | 2 +- 3 files changed, 65 insertions(+), 10 deletions(-) create mode 100644 src/api/java/baritone/api/utils/Pair.java diff --git a/src/api/java/baritone/api/utils/Pair.java b/src/api/java/baritone/api/utils/Pair.java new file mode 100644 index 000000000..ca7259520 --- /dev/null +++ b/src/api/java/baritone/api/utils/Pair.java @@ -0,0 +1,59 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.utils; + +import java.util.Objects; + +/** + * @author Brady + */ +public final class Pair { + + private final A a; + private final B b; + + public Pair(A a, B b) { + this.a = a; + this.b = b; + } + + public A first() { + return this.a; + } + + public B second() { + return this.b; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || o.getClass() != Pair.class) { + return false; + } + Pair pair = (Pair) o; + return Objects.equals(this.a, pair.a) && Objects.equals(this.b, pair.b); + } + + @Override + public int hashCode() { + return 31 * Objects.hashCode(this.a) + Objects.hashCode(this.b); + } +} diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 8fdcb34f6..6ace0a4e1 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -21,14 +21,10 @@ import baritone.Baritone; import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.TickEvent; import baritone.api.event.events.type.EventState; -import baritone.api.utils.BetterBlockPos; -import baritone.api.utils.Helper; -import baritone.api.utils.Rotation; -import baritone.api.utils.RotationUtils; +import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.UnpackedSegment; import baritone.utils.BlockStateInterface; -import com.mojang.realmsclient.util.Pair; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -381,15 +377,15 @@ public final class ElytraBehavior extends Behavior implements Helper { : relaxation == 0 ? 1.0d : 0.25d; if (isClear(start, dest, grow)) { - Rotation rot = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()); + float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); if (pitch == null) { - baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), ctx.playerRotations().getPitch()), false); + baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); continue; } this.pathManager.setGoingTo(i); this.aimPos = path.get(i).add(0, dy, 0); - baritone.getLookBehavior().updateTarget(new Rotation(rot.getYaw(), pitch), false); + baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch), false); break outermost; } } @@ -456,7 +452,7 @@ public final class ElytraBehavior extends Behavior implements Helper { } private boolean clearView(Vec3d start, Vec3d dest) { - lines.add(Pair.of(start, dest)); + lines.add(new Pair<>(start, dest)); RayTraceResult result = rayTraceBlocks(start, dest); return result == null || result.typeOfHit == RayTraceResult.Type.MISS; } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index fa8925042..7274f5dbc 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -23,11 +23,11 @@ import baritone.api.event.events.RenderEvent; import baritone.api.pathing.goals.*; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.IPlayerContext; +import baritone.api.utils.Pair; import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.behavior.ElytraBehavior; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; -import com.mojang.realmsclient.util.Pair; import net.minecraft.block.state.IBlockState; import net.minecraft.client.renderer.GlStateManager; import net.minecraft.client.renderer.tileentity.TileEntityBeaconRenderer; From aec683d80f027a61a64e315366d06b6b5f847b89 Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Sun, 18 Jun 2023 12:21:01 -0400 Subject: [PATCH 047/276] fast raytrace --- .../baritone/behavior/ElytraBehavior.java | 196 ++++++++++-------- 1 file changed, 107 insertions(+), 89 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 6ace0a4e1..3d396b5e1 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -28,10 +28,9 @@ import baritone.utils.BlockStateInterface; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; -import net.minecraft.init.Blocks; -import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.math.*; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -453,8 +452,7 @@ public final class ElytraBehavior extends Behavior implements Helper { private boolean clearView(Vec3d start, Vec3d dest) { lines.add(new Pair<>(start, dest)); - RayTraceResult result = rayTraceBlocks(start, dest); - return result == null || result.typeOfHit == RayTraceResult.Type.MISS; + return !rayTraceBlocks(ctx.world(), start.x, start.y, start.z, dest.x, dest.y, dest.z); } private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate) { @@ -557,98 +555,118 @@ public final class ElytraBehavior extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - // TODO: Use the optimized version from builder-2 - private RayTraceResult rayTraceBlocks(Vec3d start, Vec3d end) { - int x1 = MathHelper.floor(end.x); - int y1 = MathHelper.floor(end.y); - int z1 = MathHelper.floor(end.z); - int x2 = MathHelper.floor(start.x); - int y2 = MathHelper.floor(start.y); - int z2 = MathHelper.floor(start.z); - BlockPos blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate)) { - return Blocks.SPONGE.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + private final BlockPos.MutableBlockPos mutableRaytraceBlockPos = new BlockPos.MutableBlockPos(); + + private boolean rayTraceBlocks(final World world, + final double startX, final double startY, final double startZ, + final double endX, final double endY, final double endZ) { + int voxelCurrX = fastFloor(startX); + int voxelCurrY = fastFloor(startY); + int voxelCurrZ = fastFloor(startZ); + + Chunk prevChunk; + IBlockState currentState = (prevChunk = cachedChunk(world, this.mutableRaytraceBlockPos.setPos(voxelCurrX, voxelCurrY, voxelCurrZ), null)).getBlockState(this.mutableRaytraceBlockPos); + + // This is true if player is standing inside of block. + if (!passable(currentState)) { + return true; } - int steps = 200; + + final int voxelEndX = fastFloor(endX); + final int voxelEndY = fastFloor(endY); + final int voxelEndZ = fastFloor(endZ); + double currPosX = startX; + double currPosY = startY; + double currPosZ = startZ; + + int steps = 200; // TODO: should we lower the max steps? while (steps-- >= 0) { - if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { - return null; + if (voxelCurrX == voxelEndX && voxelCurrY == voxelEndY && voxelCurrZ == voxelEndZ) { + return false; } - if (x2 == x1 && y2 == y1 && z2 == z1) { - return null; + + final double distanceFromStartToEndX = endX - currPosX; + final double distanceFromStartToEndY = endY - currPosY; + final double distanceFromStartToEndZ = endZ - currPosZ; + + double nextIntegerX; + double nextIntegerY; + double nextIntegerZ; + // potentially more based branchless impl? + nextIntegerX = voxelCurrX + ((voxelCurrX - voxelEndX) >>> 31); // if voxelEnd > voxelIn, then voxelIn-voxelEnd will be negative, meaning the sign bit is 1 + nextIntegerY = voxelCurrY + ((voxelCurrY - voxelEndY) >>> 31); // if we do an unsigned right shift by 31, that sign bit becomes the LSB + nextIntegerZ = voxelCurrZ + ((voxelCurrZ - voxelEndZ) >>> 31); // therefore, this increments nextInteger iff EndX>inX, otherwise it leaves it alone + // remember: don't have to worry about the case when voxelEnd == voxelIn, because nextInteger value wont be used + + // these just have to be strictly greater than 1, might as well just go up to the next int + double fracIfSkipX = 2.0D; + double fracIfSkipY = 2.0D; + double fracIfSkipZ = 2.0D; + + // reminder to future self: don't "branchlessify" this, it's MUCH slower (pretty obviously, floating point div is much worse than a branch mispredict, but integer increment (like the other two removed branches) are cheap enough to be worth doing either way) + if (voxelEndX != voxelCurrX) { + fracIfSkipX = (nextIntegerX - currPosX) / distanceFromStartToEndX; } - boolean hitX = true; - boolean hitY = true; - boolean hitZ = true; - double nextX = 999.0D; - double nextY = 999.0D; - double nextZ = 999.0D; - if (x1 > x2) { - nextX = (double) x2 + 1.0D; - } else if (x1 < x2) { - nextX = (double) x2 + 0.0D; + if (voxelEndY != voxelCurrY) { + fracIfSkipY = (nextIntegerY - currPosY) / distanceFromStartToEndY; + } + if (voxelEndZ != voxelCurrZ) { + fracIfSkipZ = (nextIntegerZ - currPosZ) / distanceFromStartToEndZ; + } + + if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) { + // note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default + currPosX = nextIntegerX; + currPosY += distanceFromStartToEndY * fracIfSkipX; + currPosZ += distanceFromStartToEndZ * fracIfSkipX; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int xFloorOffset = (voxelEndX - voxelCurrX) >>> 31; + voxelCurrX = (fastFloor(currPosX) - xFloorOffset); + voxelCurrY = (fastFloor(currPosY)); + voxelCurrZ = (fastFloor(currPosZ)); + } else if (fracIfSkipY < fracIfSkipZ) { + currPosX += distanceFromStartToEndX * fracIfSkipY; + currPosY = nextIntegerY; + currPosZ += distanceFromStartToEndZ * fracIfSkipY; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int yFloorOffset = (voxelEndY - voxelCurrY) >>> 31; + voxelCurrX = (fastFloor(currPosX)); + voxelCurrY = (fastFloor(currPosY) - yFloorOffset); + voxelCurrZ = (fastFloor(currPosZ)); } else { - hitX = false; + currPosX += distanceFromStartToEndX * fracIfSkipZ; + currPosY += distanceFromStartToEndY * fracIfSkipZ; + currPosZ = nextIntegerZ; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int zFloorOffset = (voxelEndZ - voxelCurrZ) >>> 31; + voxelCurrX = (fastFloor(currPosX)); + voxelCurrY = (fastFloor(currPosY)); + voxelCurrZ = (fastFloor(currPosZ) - zFloorOffset); } - if (y1 > y2) { - nextY = (double) y2 + 1.0D; - } else if (y1 < y2) { - nextY = (double) y2 + 0.0D; - } else { - hitY = false; - } - if (z1 > z2) { - nextZ = (double) z2 + 1.0D; - } else if (z1 < z2) { - nextZ = (double) z2 + 0.0D; - } else { - hitZ = false; - } - double stepX = 999.0D; - double stepY = 999.0D; - double stepZ = 999.0D; - double dirX = end.x - start.x; - double dirY = end.y - start.y; - double dirZ = end.z - start.z; - if (hitX) { - stepX = (nextX - start.x) / dirX; - } - if (hitY) { - stepY = (nextY - start.y) / dirY; - } - if (hitZ) { - stepZ = (nextZ - start.z) / dirZ; - } - if (stepX == -0.0D) { - stepX = -1.0E-4D; - } - if (stepY == -0.0D) { - stepY = -1.0E-4D; - } - if (stepZ == -0.0D) { - stepZ = -1.0E-4D; - } - EnumFacing dir; - if (stepX < stepY && stepX < stepZ) { - dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; - start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); - } else if (stepY < stepZ) { - dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; - start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); - } else { - dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; - start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); - } - x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); - y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); - z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); - blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate1)) { - return Blocks.NETHERRACK.getDefaultState().collisionRayTrace(ctx.world(), blockpos, start, end); + + currentState = (prevChunk = cachedChunk(world, this.mutableRaytraceBlockPos.setPos(voxelCurrX, voxelCurrY, voxelCurrZ), prevChunk)).getBlockState(this.mutableRaytraceBlockPos); + if (!passable(currentState)) { + return true; } } - return null; + return false; + } + + private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; + private static final int FLOOR_DOUBLE_I = 1_073_741_824; + + private static int fastFloor(final double v) { + return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; + } + + private static Chunk cachedChunk(final World world, + final BlockPos pos, + final Chunk prevLookup) { + final int chunkX = pos.getX() >> 4; + final int chunkZ = pos.getZ() >> 4; + if (prevLookup != null && prevLookup.x == chunkX && prevLookup.z == chunkZ) { + return prevLookup; + } + return world.getChunk(chunkX, chunkZ); } } \ No newline at end of file From 68901695cae0aa5b8d40ce6cf07b9e88cfe5efed Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 13:23:41 -0500 Subject: [PATCH 048/276] Add experimental takeoff feature --- src/api/java/baritone/api/Settings.java | 1 + .../baritone/behavior/ElytraBehavior.java | 37 ++++++++++++++----- 2 files changed, 29 insertions(+), 9 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 24e54c136..9180c6ad7 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -54,6 +54,7 @@ public final class Settings { public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); + public final Setting experimentalTakeoff = new Setting<>(false); /** * Allow Baritone to break blocks diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3d396b5e1..fa15e1678 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -342,6 +342,7 @@ public final class ElytraBehavior extends Behavior implements Helper { final Vec3d start = ctx.playerFeetAsVec(); final boolean firework = isFireworkActive(); + boolean forceUseFirework = false; this.sinceFirework++; outermost: @@ -376,15 +377,18 @@ public final class ElytraBehavior extends Behavior implements Helper { : relaxation == 0 ? 1.0d : 0.25d; if (isClear(start, dest, grow)) { - float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - Float pitch = solvePitch(dest.subtract(start), steps, relaxation == 2); - if (pitch == null) { + final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); + + final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework); + if (pitch.first() == null) { baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); continue; } + forceUseFirework = pitch.second(); + this.pathManager.setGoingTo(i); this.aimPos = path.get(i).add(0, dy, 0); - baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch), false); + baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); break outermost; } } @@ -404,13 +408,13 @@ public final class ElytraBehavior extends Behavior implements Helper { ctx.player().motionZ ).length(); - if (!firework + if (forceUseFirework || (!firework && sinceFirework > 10 && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! - && currentSpeed < Baritone.settings().elytraFireworkSpeed.value + && currentSpeed < Baritone.settings().elytraFireworkSpeed.value) ) { - logDirect("firework"); + logDirect("firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); sinceFirework = 0; } @@ -455,7 +459,23 @@ public final class ElytraBehavior extends Behavior implements Helper { return !rayTraceBlocks(ctx.world(), start.x, start.y, start.z, dest.x, dest.y, dest.z); } - private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate) { + private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted) { + final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, currentlyBoosted); + if (pitch != null) { + return new Pair<>(pitch, false); + } + + if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { + final Float usingFirework = this.solvePitch(goalDirection, steps, relaxation == 2, true); + if (usingFirework != null) { + return new Pair<>(usingFirework, true); + } + } + + return new Pair<>(null, false); + } + + private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate, boolean firework) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -463,7 +483,6 @@ public final class ElytraBehavior extends Behavior implements Helper { goalDirection = goalDirection.normalize(); Rotation good = RotationUtils.calcRotationFromVec3d(new Vec3d(0, 0, 0), goalDirection, ctx.playerRotations()); // lazy lol - boolean firework = isFireworkActive(); Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); From 8dc32ae03c9866df9d7c6957290c018ad6b66d69 Mon Sep 17 00:00:00 2001 From: rfresh2 <89827146+rfresh2@users.noreply.github.com> Date: Sat, 17 Jun 2023 22:24:10 -0700 Subject: [PATCH 049/276] firework inv management + pause/resume --- src/api/java/baritone/api/IBaritone.java | 7 ++ src/api/java/baritone/api/Settings.java | 8 ++ .../api/behavior/IElytraBehavior.java | 35 ++++++++ .../mixins/MixinEntityFireworkRocket.java | 35 ++++++++ src/launch/resources/mixins.baritone.json | 3 +- src/main/java/baritone/Baritone.java | 1 + .../baritone/behavior/ElytraBehavior.java | 89 +++++++++++++++++-- .../baritone/behavior/InventoryBehavior.java | 16 ++++ .../command/defaults/ElytraCommand.java | 2 +- .../defaults/ExecutionControlCommands.java | 2 + .../utils/accessor/IEntityFireworkRocket.java | 24 +++++ 11 files changed, 215 insertions(+), 7 deletions(-) create mode 100644 src/api/java/baritone/api/behavior/IElytraBehavior.java create mode 100644 src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java create mode 100644 src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java diff --git a/src/api/java/baritone/api/IBaritone.java b/src/api/java/baritone/api/IBaritone.java index 0cc73b0d1..0913a8c43 100644 --- a/src/api/java/baritone/api/IBaritone.java +++ b/src/api/java/baritone/api/IBaritone.java @@ -17,6 +17,7 @@ package baritone.api; +import baritone.api.behavior.IElytraBehavior; import baritone.api.behavior.ILookBehavior; import baritone.api.behavior.IPathingBehavior; import baritone.api.cache.IWorldProvider; @@ -40,6 +41,12 @@ public interface IBaritone { */ IPathingBehavior getPathingBehavior(); + /** + * @return The {@link IElytraBehavior} instance + * @see IElytraBehavior + */ + IElytraBehavior getElytraBehavior(); + /** * @return The {@link ILookBehavior} instance * @see ILookBehavior diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 9180c6ad7..116df04e0 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -50,6 +50,14 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); + /** + * Allow users to control firework usage instead of Baritone. e.g. with their own client modules. + */ + public final Setting elytraUseFireworks = new Setting<>(true); + /** + * Allow Baritone to manage fireworks in the inventory and hotbar + */ + public final Setting elytraInventory = new Setting<>(true); public final Setting elytraFireworkSpeed = new Setting<>(0.6); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/behavior/IElytraBehavior.java new file mode 100644 index 000000000..dc44eacda --- /dev/null +++ b/src/api/java/baritone/api/behavior/IElytraBehavior.java @@ -0,0 +1,35 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.behavior; + +public interface IElytraBehavior extends IBehavior { + /** + * Pause the current {@link IElytraBehavior} if it is pathing. + */ + void pause(); + + /** + * Resume the current {@link IElytraBehavior} if it is paused. + */ + void resume(); + + /** + * Returns true if the current {@link IElytraBehavior} is actively pathing and not paused. + */ + boolean isActive(); +} diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java new file mode 100644 index 000000000..274e979a0 --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java @@ -0,0 +1,35 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.launch.mixins; + +import baritone.utils.accessor.IEntityFireworkRocket; +import net.minecraft.entity.EntityLivingBase; +import net.minecraft.entity.item.EntityFireworkRocket; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +@Mixin(EntityFireworkRocket.class) +public abstract class MixinEntityFireworkRocket implements IEntityFireworkRocket { + @Shadow + private EntityLivingBase boostedEntity; + + @Override + public EntityLivingBase getBoostedEntity() { + return boostedEntity; + } +} diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index 982736635..5c221de58 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -16,6 +16,7 @@ "MixinChunkProviderServer", "MixinChunkRenderContainer", "MixinChunkRenderWorker", + "MixinEntityFireworkRocket", "MixinEntityLivingBase", "MixinEntityPlayerSP", "MixinEntityRenderer", @@ -34,4 +35,4 @@ "MixinVboRenderList", "MixinWorldClient" ] -} \ No newline at end of file +} diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 457b49a45..05e1992c9 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -232,6 +232,7 @@ public class Baritone implements IBaritone { return this.commandManager; } + @Override public ElytraBehavior getElytraBehavior() { return this.elytraBehavior; } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index fa15e1678..3da503066 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -18,6 +18,7 @@ package baritone.behavior; import baritone.Baritone; +import baritone.api.behavior.IElytraBehavior; import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.TickEvent; import baritone.api.event.events.type.EventState; @@ -25,11 +26,19 @@ import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.UnpackedSegment; import baritone.utils.BlockStateInterface; +import baritone.utils.accessor.IEntityFireworkRocket; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.*; +import net.minecraft.util.NonNullList; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -37,7 +46,7 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.function.UnaryOperator; -public final class ElytraBehavior extends Behavior implements Helper { +public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { /** * 2b2t seed @@ -53,6 +62,7 @@ public final class ElytraBehavior extends Behavior implements Helper { private final NetherPathfinderContext context; private final PathManager pathManager; private int sinceFirework; + private boolean pawsed = false; public ElytraBehavior(Baritone baritone) { super(baritone); @@ -297,6 +307,7 @@ public final class ElytraBehavior extends Behavior implements Helper { } public void path(BlockPos destination) { + pawsed = false; this.pathManager.pathToDestination(destination); } @@ -305,6 +316,23 @@ public final class ElytraBehavior extends Behavior implements Helper { this.pathManager.clear(); this.aimPos = null; this.sinceFirework = 0; + pawsed = false; + } + + public boolean isActive() { + return !this.pathManager.getPath().isEmpty() && !isPaused(); + } + + public void pause() { + this.pawsed = true; + } + + public void resume() { + this.pawsed = false; + } + + public boolean isPaused() { + return this.pawsed; } @Override @@ -312,6 +340,7 @@ public final class ElytraBehavior extends Behavior implements Helper { if (event.getType() == TickEvent.Type.OUT) { return; } + if (isPaused()) return; this.lines.clear(); final List path = this.pathManager.getPath(); @@ -410,20 +439,69 @@ public final class ElytraBehavior extends Behavior implements Helper { if (forceUseFirework || (!firework && sinceFirework > 10 + && Baritone.settings().elytraUseFireworks.value && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! && currentSpeed < Baritone.settings().elytraFireworkSpeed.value) ) { + if (Baritone.settings().elytraInventory.value) { + final int firstFireworksInHotbar = firstFireworksInHotbar(); + if (firstFireworksInHotbar == -1) { + if (!swapToFireworksInInventory()) { + logDirect("no fireworks"); + return; + } + } else { + ctx.player().inventory.currentItem = firstFireworksInHotbar; + } + } logDirect("firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); sinceFirework = 0; } } + private boolean swapToFireworksInInventory() { + final int i = firstFireworksInInventory(); + if (i != -1) { + baritone.getInventoryBehavior().attemptToPutOnHotbar(i, (slot) -> slot != 7); + ctx.player().inventory.currentItem = 7; + return true; + } + return false; + } + + private int firstFireworksInInventory() { + final NonNullList invy = ctx.player().inventory.mainInventory; + for (int i = 0; i < invy.size(); i++) { + if (isBoostingFireworks(invy.get(i))) { + return i; + } + } + return -1; + } + + private int firstFireworksInHotbar() { + final NonNullList invy = ctx.player().inventory.mainInventory; + for (int i = 0; i < 9; i++) { + if (isBoostingFireworks(invy.get(i))) { + return i; + } + } + return -1; + } + + private boolean isBoostingFireworks(final ItemStack itemStack) { + final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); + return itemStack.getItem() == Items.FIREWORKS + && subCompound != null + && subCompound.hasKey("Flight"); + } + private boolean isFireworkActive() { - // TODO: Validate that the EntityFireworkRocket is attached to ctx.player() return ctx.world().loadedEntityList.stream() - .anyMatch(x -> (x instanceof EntityFireworkRocket) && ((EntityFireworkRocket) x).isAttachedToEntity()); + .filter(x -> x instanceof EntityFireworkRocket) + .anyMatch(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())); } private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount) { @@ -688,4 +766,5 @@ public final class ElytraBehavior extends Behavior implements Helper { } return world.getChunk(chunkX, chunkZ); } -} \ No newline at end of file +} + diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java index 93dc200cc..5c351adce 100644 --- a/src/main/java/baritone/behavior/InventoryBehavior.java +++ b/src/main/java/baritone/behavior/InventoryBehavior.java @@ -25,8 +25,10 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; import net.minecraft.inventory.ClickType; import net.minecraft.item.*; +import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; @@ -150,6 +152,20 @@ public final class InventoryBehavior extends Behavior implements Helper { return bestInd; } + private int firstFireworks() { + final NonNullList invy = ctx.player().inventory.mainInventory; + for (int i = 0; i < invy.size(); i++) { + final ItemStack itemStack = invy.get(i); + final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); + if (itemStack.getItem() == Items.FIREWORKS + && subCompound != null + && subCompound.hasKey("Flight")) { + return i; + } + } + return -1; + } + public boolean hasGenericThrowaway() { for (Item item : Baritone.settings().acceptableThrowawayItems.value) { if (throwaway(false, stack -> item.equals(stack.getItem()))) { diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 1c9ee7882..7c101fd3b 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -81,4 +81,4 @@ public class ElytraCommand extends Command { public List getLongDesc() { return Arrays.asList(); } -} \ No newline at end of file +} diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index ef566bb8d..6ca324ad7 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -89,6 +89,7 @@ public class ExecutionControlCommands { throw new CommandInvalidStateException("Already paused"); } paused[0] = true; + baritone.getElytraBehavior().pause(); logDirect("Paused"); } @@ -123,6 +124,7 @@ public class ExecutionControlCommands { throw new CommandInvalidStateException("Not paused"); } paused[0] = false; + baritone.getElytraBehavior().resume(); logDirect("Resumed"); } diff --git a/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java b/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java new file mode 100644 index 000000000..86c96acd9 --- /dev/null +++ b/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java @@ -0,0 +1,24 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.utils.accessor; + +import net.minecraft.entity.EntityLivingBase; + +public interface IEntityFireworkRocket { + EntityLivingBase getBoostedEntity(); +} From 1dbfc9abe39a71063cbcbefa946f3b8cd149feee Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 19:57:29 -0500 Subject: [PATCH 050/276] optimize block lookups and move goingTo to local --- .../baritone/behavior/ElytraBehavior.java | 59 ++++++------------- 1 file changed, 17 insertions(+), 42 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index fa15e1678..c2ef38425 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -30,7 +30,6 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.util.EnumHand; import net.minecraft.util.math.*; -import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -69,7 +68,6 @@ public final class ElytraBehavior extends Behavior implements Helper { private boolean completePath; private int playerNear; - private int goingTo; private boolean recalculating; @@ -167,7 +165,6 @@ public final class ElytraBehavior extends Behavior implements Helper { public void clear() { this.path = Collections.emptyList(); this.playerNear = 0; - this.goingTo = 0; this.completePath = true; } @@ -175,7 +172,6 @@ public final class ElytraBehavior extends Behavior implements Helper { this.path = segment.collect(); this.removeBacktracks(); this.playerNear = 0; - this.goingTo = 0; this.completePath = segment.isFinished(); } @@ -187,14 +183,6 @@ public final class ElytraBehavior extends Behavior implements Helper { return this.playerNear; } - public void setGoingTo(int index) { - this.goingTo = index; - } - - public BetterBlockPos goingTo() { - return this.path.get(this.goingTo); - } - // mickey resigned private CompletableFuture path0(BlockPos src, BlockPos dst, UnaryOperator operator) { return ElytraBehavior.this.context.pathFindAsync(src, dst) @@ -319,6 +307,7 @@ public final class ElytraBehavior extends Behavior implements Helper { return; } + this.bsi = new BlockStateInterface(ctx); this.pathManager.tick(); final int playerNear = this.pathManager.getNear(); @@ -342,6 +331,7 @@ public final class ElytraBehavior extends Behavior implements Helper { final Vec3d start = ctx.playerFeetAsVec(); final boolean firework = isFireworkActive(); + BetterBlockPos goingTo = null; boolean forceUseFirework = false; this.sinceFirework++; @@ -354,7 +344,8 @@ public final class ElytraBehavior extends Behavior implements Helper { int minStep = playerNear; for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { - Vec3d dest = this.pathManager.pathAt(i).add(0, dy, 0); + final BetterBlockPos pos = path.get(i); + Vec3d dest = new Vec3d(pos).add(0, dy, 0); if (dy != 0) { if (i + lookahead >= path.size()) { continue; @@ -385,9 +376,8 @@ public final class ElytraBehavior extends Behavior implements Helper { continue; } forceUseFirework = pitch.second(); - - this.pathManager.setGoingTo(i); - this.aimPos = path.get(i).add(0, dy, 0); + goingTo = pos; + this.aimPos = goingTo.add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); break outermost; } @@ -399,7 +389,6 @@ public final class ElytraBehavior extends Behavior implements Helper { } } - final BetterBlockPos goingTo = this.pathManager.goingTo(); final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; final double currentSpeed = new Vec3d( ctx.player().motionX, @@ -456,7 +445,7 @@ public final class ElytraBehavior extends Behavior implements Helper { private boolean clearView(Vec3d start, Vec3d dest) { lines.add(new Pair<>(start, dest)); - return !rayTraceBlocks(ctx.world(), start.x, start.y, start.z, dest.x, dest.y, dest.z); + return !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); } private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted) { @@ -486,7 +475,6 @@ public final class ElytraBehavior extends Behavior implements Helper { Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); - BlockStateInterface bsi = new BlockStateInterface(ctx); float minPitch = desperate ? -90 : Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); float maxPitch = desperate ? 90 : Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); outer: @@ -501,7 +489,7 @@ public final class ElytraBehavior extends Behavior implements Helper { for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 1; y++) { for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { - if (!passable(bsi.get0(x, y, z))) { + if (!this.passable(x, y, z)) { continue outer; } } @@ -519,6 +507,12 @@ public final class ElytraBehavior extends Behavior implements Helper { return bestPitch; } + private BlockStateInterface bsi; + + public boolean passable(int x, int y, int z) { + return passable(this.bsi.get0(x, y, z)); + } + public static boolean passable(IBlockState state) { return state.getMaterial() == Material.AIR; } @@ -574,20 +568,13 @@ public final class ElytraBehavior extends Behavior implements Helper { return new Vec3d(motionX, motionY, motionZ); } - private final BlockPos.MutableBlockPos mutableRaytraceBlockPos = new BlockPos.MutableBlockPos(); - - private boolean rayTraceBlocks(final World world, - final double startX, final double startY, final double startZ, + private boolean rayTraceBlocks(final double startX, final double startY, final double startZ, final double endX, final double endY, final double endZ) { int voxelCurrX = fastFloor(startX); int voxelCurrY = fastFloor(startY); int voxelCurrZ = fastFloor(startZ); - Chunk prevChunk; - IBlockState currentState = (prevChunk = cachedChunk(world, this.mutableRaytraceBlockPos.setPos(voxelCurrX, voxelCurrY, voxelCurrZ), null)).getBlockState(this.mutableRaytraceBlockPos); - - // This is true if player is standing inside of block. - if (!passable(currentState)) { + if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ)) { return true; } @@ -663,8 +650,7 @@ public final class ElytraBehavior extends Behavior implements Helper { voxelCurrZ = (fastFloor(currPosZ) - zFloorOffset); } - currentState = (prevChunk = cachedChunk(world, this.mutableRaytraceBlockPos.setPos(voxelCurrX, voxelCurrY, voxelCurrZ), prevChunk)).getBlockState(this.mutableRaytraceBlockPos); - if (!passable(currentState)) { + if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ)) { return true; } } @@ -677,15 +663,4 @@ public final class ElytraBehavior extends Behavior implements Helper { private static int fastFloor(final double v) { return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; } - - private static Chunk cachedChunk(final World world, - final BlockPos pos, - final Chunk prevLookup) { - final int chunkX = pos.getX() >> 4; - final int chunkZ = pos.getZ() >> 4; - if (prevLookup != null && prevLookup.x == chunkX && prevLookup.z == chunkZ) { - return prevLookup; - } - return world.getChunk(chunkX, chunkZ); - } } \ No newline at end of file From 812be14375df960cc0495fcd62acc30698db0fa6 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 18 Jun 2023 18:06:32 -0700 Subject: [PATCH 051/276] debug --- .../baritone/behavior/ElytraBehavior.java | 129 +++++++++++++++++- .../java/baritone/utils/PathRenderer.java | 14 +- 2 files changed, 134 insertions(+), 9 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c2ef38425..d0fd210eb 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -28,8 +28,12 @@ import baritone.utils.BlockStateInterface; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.*; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -44,7 +48,8 @@ public final class ElytraBehavior extends Behavior implements Helper { private static final long NETHER_SEED = 146008555100680L; // Used exclusively for PathRenderer - public List> lines; + public List> clearLines; + public List> blockedLines; public BlockPos aimPos; public List visiblePath; @@ -56,7 +61,8 @@ public final class ElytraBehavior extends Behavior implements Helper { public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new NetherPathfinderContext(NETHER_SEED); - this.lines = new ArrayList<>(); + this.clearLines = new ArrayList<>(); + this.blockedLines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); this.pathManager = new PathManager(); } @@ -300,7 +306,8 @@ public final class ElytraBehavior extends Behavior implements Helper { if (event.getType() == TickEvent.Type.OUT) { return; } - this.lines.clear(); + this.clearLines.clear(); + this.blockedLines.clear(); final List path = this.pathManager.getPath(); if (path.isEmpty()) { @@ -376,8 +383,12 @@ public final class ElytraBehavior extends Behavior implements Helper { continue; } forceUseFirework = pitch.second(); + logDirect("final dy " + dy); + logDirect("i " + i); + logDirect("playerNear " + playerNear); + logDirect("relaxation " + relaxation); goingTo = pos; - this.aimPos = goingTo.add(0, dy, 0); + this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); break outermost; } @@ -444,8 +455,18 @@ public final class ElytraBehavior extends Behavior implements Helper { } private boolean clearView(Vec3d start, Vec3d dest) { - lines.add(new Pair<>(start, dest)); - return !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); + boolean oxy = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); + boolean meow = !rayTraceBlocks(start, dest); + if (oxy != meow) { + logDirect(start + " " + dest + " " + oxy + " " + meow); + } + if (oxy) { + clearLines.add(new Pair<>(start, dest)); + return true; + } else { + blockedLines.add(new Pair<>(start, dest)); + return false; + } } private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted) { @@ -663,4 +684,98 @@ public final class ElytraBehavior extends Behavior implements Helper { private static int fastFloor(final double v) { return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; } + + private boolean rayTraceBlocks(Vec3d start, Vec3d end) { + int x1 = MathHelper.floor(end.x); + int y1 = MathHelper.floor(end.y); + int z1 = MathHelper.floor(end.z); + int x2 = MathHelper.floor(start.x); + int y2 = MathHelper.floor(start.y); + int z2 = MathHelper.floor(start.z); + BlockPos blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate)) { + return true; + } + int steps = 200; + while (steps-- >= 0) { + if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { + return false; + } + if (x2 == x1 && y2 == y1 && z2 == z1) { + return false; + } + boolean hitX = true; + boolean hitY = true; + boolean hitZ = true; + double nextX = 999.0D; + double nextY = 999.0D; + double nextZ = 999.0D; + if (x1 > x2) { + nextX = (double) x2 + 1.0D; + } else if (x1 < x2) { + nextX = (double) x2 + 0.0D; + } else { + hitX = false; + } + if (y1 > y2) { + nextY = (double) y2 + 1.0D; + } else if (y1 < y2) { + nextY = (double) y2 + 0.0D; + } else { + hitY = false; + } + if (z1 > z2) { + nextZ = (double) z2 + 1.0D; + } else if (z1 < z2) { + nextZ = (double) z2 + 0.0D; + } else { + hitZ = false; + } + double stepX = 999.0D; + double stepY = 999.0D; + double stepZ = 999.0D; + double dirX = end.x - start.x; + double dirY = end.y - start.y; + double dirZ = end.z - start.z; + if (hitX) { + stepX = (nextX - start.x) / dirX; + } + if (hitY) { + stepY = (nextY - start.y) / dirY; + } + if (hitZ) { + stepZ = (nextZ - start.z) / dirZ; + } + if (stepX == -0.0D) { + stepX = -1.0E-4D; + } + if (stepY == -0.0D) { + stepY = -1.0E-4D; + } + if (stepZ == -0.0D) { + stepZ = -1.0E-4D; + } + EnumFacing dir; + if (stepX < stepY && stepX < stepZ) { + dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; + start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); + } else if (stepY < stepZ) { + dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; + start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); + } else { + dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; + start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); + } + x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); + y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); + z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); + blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate1)) { + return true; + } + } + return false; + } } \ No newline at end of file diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 7274f5dbc..d608d4a2b 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -108,11 +108,21 @@ public final class PathRenderer implements IRenderer { if (elytra.aimPos != null) { drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN); } - if (!elytra.lines.isEmpty() && Baritone.settings().renderRaytraces.value) { + if (!elytra.clearLines.isEmpty() && Baritone.settings().renderRaytraces.value) { + IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + boolean orig = settings.renderPathAsLine.value; + settings.renderPathAsLine.value = true; + for (Pair line : elytra.clearLines) { + emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); + } + settings.renderPathAsLine.value = orig; + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } + if (!elytra.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); boolean orig = settings.renderPathAsLine.value; settings.renderPathAsLine.value = true; - for (Pair line : elytra.lines) { + for (Pair line : elytra.blockedLines) { emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); } settings.renderPathAsLine.value = orig; From a236031435d3c6d8c528c583da08df7372929cf7 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 18 Jun 2023 18:09:45 -0700 Subject: [PATCH 052/276] fix raytracer --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index d0fd210eb..3d3d4843c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -455,7 +455,7 @@ public final class ElytraBehavior extends Behavior implements Helper { } private boolean clearView(Vec3d start, Vec3d dest) { - boolean oxy = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); + boolean oxy = !rayTraceBlocks(start.x + 0.0001 * Math.random(), start.y + 0.0001 * Math.random(), start.z + 0.0001 * Math.random(), dest.x + 0.0001 * Math.random(), dest.y + 0.0001 * Math.random(), dest.z + 0.0001 * Math.random()); boolean meow = !rayTraceBlocks(start, dest); if (oxy != meow) { logDirect(start + " " + dest + " " + oxy + " " + meow); From efae476bc028f04dbe01d9b99e4adfaeade003c1 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 18 Jun 2023 18:16:13 -0700 Subject: [PATCH 053/276] solved --- src/main/java/baritone/behavior/ElytraBehavior.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3d3d4843c..97dc24102 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -162,9 +162,9 @@ public final class ElytraBehavior extends Behavior implements Helper { private Vec3d pathAt(int i) { return new Vec3d( - this.path.get(i).x, - this.path.get(i).y, - this.path.get(i).z + this.path.get(i).x + 0.000123, + this.path.get(i).y + 0.000456, + this.path.get(i).z + 0.000789 ); } @@ -351,8 +351,7 @@ public final class ElytraBehavior extends Behavior implements Helper { int minStep = playerNear; for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { - final BetterBlockPos pos = path.get(i); - Vec3d dest = new Vec3d(pos).add(0, dy, 0); + Vec3d dest = this.pathManager.pathAt(i).add(0, dy, 0); if (dy != 0) { if (i + lookahead >= path.size()) { continue; @@ -387,7 +386,7 @@ public final class ElytraBehavior extends Behavior implements Helper { logDirect("i " + i); logDirect("playerNear " + playerNear); logDirect("relaxation " + relaxation); - goingTo = pos; + goingTo = path.get(i); this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); break outermost; @@ -455,7 +454,7 @@ public final class ElytraBehavior extends Behavior implements Helper { } private boolean clearView(Vec3d start, Vec3d dest) { - boolean oxy = !rayTraceBlocks(start.x + 0.0001 * Math.random(), start.y + 0.0001 * Math.random(), start.z + 0.0001 * Math.random(), dest.x + 0.0001 * Math.random(), dest.y + 0.0001 * Math.random(), dest.z + 0.0001 * Math.random()); + boolean oxy = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); boolean meow = !rayTraceBlocks(start, dest); if (oxy != meow) { logDirect(start + " " + dest + " " + oxy + " " + meow); From 1837b66bb5153e14ad46cc7269fb3e6c70367bd0 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 21:24:13 -0500 Subject: [PATCH 054/276] Add `BlockChangeEvent` Moves the cache repack on block change functionality into `GameEventHandler` --- .../java/baritone/api/IBaritoneProvider.java | 17 +++ .../api/event/events/BlockChangeEvent.java | 49 +++++++ .../baritone/api/event/events/ChunkEvent.java | 15 +- .../listener/AbstractGameEventListener.java | 3 + .../event/listener/IGameEventListener.java | 7 + .../mixins/MixinNetHandlerPlayClient.java | 128 +++++++----------- .../java/baritone/event/GameEventHandler.java | 30 +++- 7 files changed, 164 insertions(+), 85 deletions(-) create mode 100644 src/api/java/baritone/api/event/events/BlockChangeEvent.java diff --git a/src/api/java/baritone/api/IBaritoneProvider.java b/src/api/java/baritone/api/IBaritoneProvider.java index 55d208e03..cf816b40f 100644 --- a/src/api/java/baritone/api/IBaritoneProvider.java +++ b/src/api/java/baritone/api/IBaritoneProvider.java @@ -23,6 +23,7 @@ import baritone.api.command.ICommandSystem; import baritone.api.schematic.ISchematicSystem; import net.minecraft.client.Minecraft; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.client.network.NetHandlerPlayClient; import java.util.List; import java.util.Objects; @@ -82,6 +83,22 @@ public interface IBaritoneProvider { return null; } + /** + * Provides the {@link IBaritone} instance for the player with the specified connection. + * + * @param connection The connection + * @return The {@link IBaritone} instance. + */ + default IBaritone getBaritoneForConnection(NetHandlerPlayClient connection) { + for (IBaritone baritone : this.getAllBaritones()) { + final EntityPlayerSP player = baritone.getPlayerContext().player(); + if (player != null && player.connection == connection) { + return baritone; + } + } + return null; + } + /** * Creates and registers a new {@link IBaritone} instance using the specified {@link Minecraft}. The existing * instance is returned if already registered. diff --git a/src/api/java/baritone/api/event/events/BlockChangeEvent.java b/src/api/java/baritone/api/event/events/BlockChangeEvent.java new file mode 100644 index 000000000..152c435ae --- /dev/null +++ b/src/api/java/baritone/api/event/events/BlockChangeEvent.java @@ -0,0 +1,49 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.event.events; + +import baritone.api.utils.Pair; +import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; + +import java.util.Collections; +import java.util.List; +import java.util.Set; + +/** + * @author Brady + */ +public final class BlockChangeEvent { + + private final Set affectedChunks; + private final List> blocks; + + public BlockChangeEvent(ChunkPos pos, List> blocks) { + this.affectedChunks = Collections.singleton(pos); + this.blocks = blocks; + } + + public Set getAffectedChunks() { + return this.affectedChunks; + } + + public List> getBlocks() { + return this.blocks; + } +} diff --git a/src/api/java/baritone/api/event/events/ChunkEvent.java b/src/api/java/baritone/api/event/events/ChunkEvent.java index a7b5d96f0..bb22a47b1 100644 --- a/src/api/java/baritone/api/event/events/ChunkEvent.java +++ b/src/api/java/baritone/api/event/events/ChunkEvent.java @@ -57,31 +57,38 @@ public final class ChunkEvent { /** * @return The state of the event */ - public final EventState getState() { + public EventState getState() { return this.state; } /** * @return The type of chunk event that occurred; */ - public final Type getType() { + public Type getType() { return this.type; } /** * @return The Chunk X position. */ - public final int getX() { + public int getX() { return this.x; } /** * @return The Chunk Z position. */ - public final int getZ() { + public int getZ() { return this.z; } + /** + * @return {@code true} if the event was fired after a chunk population + */ + public boolean isPostPopulate() { + return this.state == EventState.POST && this.type.isPopulate(); + } + public enum Type { /** diff --git a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java index 9eac8de46..64ae0c16e 100644 --- a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -45,6 +45,9 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onChunkEvent(ChunkEvent event) {} + @Override + default void onBlockChange(BlockChangeEvent event) {} + @Override default void onRenderPass(RenderEvent event) {} diff --git a/src/api/java/baritone/api/event/listener/IGameEventListener.java b/src/api/java/baritone/api/event/listener/IGameEventListener.java index b074e978b..71e9521ad 100644 --- a/src/api/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/IGameEventListener.java @@ -72,6 +72,13 @@ public interface IGameEventListener { */ void onChunkEvent(ChunkEvent event); + /** + * Runs after a single or multi block change packet is received and processed. + * + * @param event The event + */ + void onBlockChange(BlockChangeEvent event); + /** * Runs once per world render pass. Two passes are made when {@link GameSettings#anaglyph} is on. *

diff --git a/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java b/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java index f1c1f7972..cdbeffc6c 100644 --- a/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java +++ b/src/launch/java/baritone/launch/mixins/MixinNetHandlerPlayClient.java @@ -17,24 +17,29 @@ package baritone.launch.mixins; -import baritone.Baritone; import baritone.api.BaritoneAPI; import baritone.api.IBaritone; +import baritone.api.event.events.BlockChangeEvent; import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.type.EventState; -import baritone.cache.CachedChunk; -import net.minecraft.client.entity.EntityPlayerSP; +import baritone.api.utils.Pair; +import net.minecraft.block.state.IBlockState; import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.network.play.server.SPacketBlockChange; import net.minecraft.network.play.server.SPacketChunkData; import net.minecraft.network.play.server.SPacketCombatEvent; import net.minecraft.network.play.server.SPacketMultiBlockChange; +import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Arrays; +import java.util.Collections; +import java.util.stream.Collectors; + /** * @author Brady * @since 8/3/2018 @@ -50,19 +55,18 @@ public class MixinNetHandlerPlayClient { ) ) private void preRead(SPacketChunkData packetIn, CallbackInfo ci) { - for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { - EntityPlayerSP player = ibaritone.getPlayerContext().player(); - if (player != null && player.connection == (NetHandlerPlayClient) (Object) this) { - ibaritone.getGameEventHandler().onChunkEvent( - new ChunkEvent( - EventState.PRE, - packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL, - packetIn.getChunkX(), - packetIn.getChunkZ() - ) - ); - } + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForConnection((NetHandlerPlayClient) (Object) this); + if (baritone == null) { + return; } + baritone.getGameEventHandler().onChunkEvent( + new ChunkEvent( + EventState.PRE, + packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL, + packetIn.getChunkX(), + packetIn.getChunkZ() + ) + ); } @Inject( @@ -70,19 +74,18 @@ public class MixinNetHandlerPlayClient { at = @At("RETURN") ) private void postHandleChunkData(SPacketChunkData packetIn, CallbackInfo ci) { - for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { - EntityPlayerSP player = ibaritone.getPlayerContext().player(); - if (player != null && player.connection == (NetHandlerPlayClient) (Object) this) { - ibaritone.getGameEventHandler().onChunkEvent( - new ChunkEvent( - EventState.POST, - packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL, - packetIn.getChunkX(), - packetIn.getChunkZ() - ) - ); - } + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForConnection((NetHandlerPlayClient) (Object) this); + if (baritone == null) { + return; } + baritone.getGameEventHandler().onChunkEvent( + new ChunkEvent( + EventState.POST, + packetIn.isFullChunk() ? ChunkEvent.Type.POPULATE_FULL : ChunkEvent.Type.POPULATE_PARTIAL, + packetIn.getChunkX(), + packetIn.getChunkZ() + ) + ); } @Inject( @@ -90,25 +93,14 @@ public class MixinNetHandlerPlayClient { at = @At("RETURN") ) private void postHandleBlockChange(SPacketBlockChange packetIn, CallbackInfo ci) { - if (!Baritone.settings().repackOnAnyBlockChange.value) { + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForConnection((NetHandlerPlayClient) (Object) this); + if (baritone == null) { return; } - if (!CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(packetIn.getBlockState().getBlock())) { - return; - } - for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { - EntityPlayerSP player = ibaritone.getPlayerContext().player(); - if (player != null && player.connection == (NetHandlerPlayClient) (Object) this) { - ibaritone.getGameEventHandler().onChunkEvent( - new ChunkEvent( - EventState.POST, - ChunkEvent.Type.POPULATE_FULL, - packetIn.getBlockPosition().getX() >> 4, - packetIn.getBlockPosition().getZ() >> 4 - ) - ); - } - } + + final ChunkPos pos = new ChunkPos(packetIn.getBlockPosition().getX() >> 4, packetIn.getBlockPosition().getZ() >> 4); + final Pair changed = new Pair<>(packetIn.getBlockPosition(), packetIn.getBlockState()); + baritone.getGameEventHandler().onBlockChange(new BlockChangeEvent(pos, Collections.singletonList(changed))); } @Inject( @@ -116,35 +108,20 @@ public class MixinNetHandlerPlayClient { at = @At("RETURN") ) private void postHandleMultiBlockChange(SPacketMultiBlockChange packetIn, CallbackInfo ci) { - if (!Baritone.settings().repackOnAnyBlockChange.value) { + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForConnection((NetHandlerPlayClient) (Object) this); + if (baritone == null) { return; } - if (packetIn.getChangedBlocks().length == 0) { - return; - } - https://docs.oracle.com/javase/specs/jls/se7/html/jls-14.html#jls-14.15 - { - for (SPacketMultiBlockChange.BlockUpdateData update : packetIn.getChangedBlocks()) { - if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(update.getBlockState().getBlock())) { - break https; - } - } - return; - } - ChunkPos pos = new ChunkPos(packetIn.getChangedBlocks()[0].getPos()); - for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { - EntityPlayerSP player = ibaritone.getPlayerContext().player(); - if (player != null && player.connection == (NetHandlerPlayClient) (Object) this) { - ibaritone.getGameEventHandler().onChunkEvent( - new ChunkEvent( - EventState.POST, - ChunkEvent.Type.POPULATE_FULL, - pos.x, - pos.z - ) - ); - } - } + + // All blocks have the same ChunkPos + final ChunkPos pos = new ChunkPos(packetIn.getChangedBlocks()[0].getPos()); + + baritone.getGameEventHandler().onBlockChange(new BlockChangeEvent( + pos, + Arrays.stream(packetIn.getChangedBlocks()) + .map(data -> new Pair<>(data.getPos(), data.getBlockState())) + .collect(Collectors.toList()) + )); } @Inject( @@ -155,11 +132,10 @@ public class MixinNetHandlerPlayClient { ) ) private void onPlayerDeath(SPacketCombatEvent packetIn, CallbackInfo ci) { - for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { - EntityPlayerSP player = ibaritone.getPlayerContext().player(); - if (player != null && player.connection == (NetHandlerPlayClient) (Object) this) { - ibaritone.getGameEventHandler().onPlayerDeath(); - } + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForConnection((NetHandlerPlayClient) (Object) this); + if (baritone == null) { + return; } + baritone.getGameEventHandler().onPlayerDeath(); } } diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index 0b46eb5e1..ceb05e739 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -23,8 +23,11 @@ import baritone.api.event.events.type.EventState; import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IGameEventListener; import baritone.api.utils.Helper; +import baritone.api.utils.Pair; +import baritone.cache.CachedChunk; import baritone.cache.WorldProvider; import baritone.utils.BlockStateInterface; +import net.minecraft.block.state.IBlockState; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -75,13 +78,10 @@ public final class GameEventHandler implements IEventBus, Helper { } @Override - public final void onChunkEvent(ChunkEvent event) { + public void onChunkEvent(ChunkEvent event) { EventState state = event.getState(); ChunkEvent.Type type = event.getType(); - boolean isPostPopulate = state == EventState.POST - && (type == ChunkEvent.Type.POPULATE_FULL || type == ChunkEvent.Type.POPULATE_PARTIAL); - World world = baritone.getPlayerContext().world(); // Whenever the server sends us to another dimension, chunks are unloaded @@ -91,7 +91,7 @@ public final class GameEventHandler implements IEventBus, Helper { && type == ChunkEvent.Type.UNLOAD && world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ()); - if (isPostPopulate || isPreUnload) { + if (event.isPostPopulate() || isPreUnload) { baritone.getWorldProvider().ifWorldLoaded(worldData -> { Chunk chunk = world.getChunk(event.getX(), event.getZ()); worldData.getCachedWorld().queueForPacking(chunk); @@ -102,6 +102,26 @@ public final class GameEventHandler implements IEventBus, Helper { listeners.forEach(l -> l.onChunkEvent(event)); } + @Override + public void onBlockChange(BlockChangeEvent event) { + if (Baritone.settings().repackOnAnyBlockChange.value) { + final boolean keepingTrackOf = event.getBlocks().stream() + .map(Pair::second).map(IBlockState::getBlock) + .anyMatch(CachedChunk.BLOCKS_TO_KEEP_TRACK_OF::contains); + + if (keepingTrackOf) { + baritone.getWorldProvider().ifWorldLoaded(worldData -> { + final World world = baritone.getPlayerContext().world(); + event.getAffectedChunks().stream() + .map(pos -> world.getChunk(pos.x, pos.z)) + .forEach(worldData.getCachedWorld()::queueForPacking); + }); + } + } + + listeners.forEach(l -> l.onBlockChange(event)); + } + @Override public final void onRenderPass(RenderEvent event) { listeners.forEach(l -> l.onRenderPass(event)); From 9808f62fe4c004fd865970b4a1cfdf8f2cbadfe7 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 21:25:00 -0500 Subject: [PATCH 055/276] Send chunks to nether-pathfinder on `BlockUpdateEvent` --- .../java/baritone/behavior/ElytraBehavior.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 97dc24102..6260b42bf 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -18,9 +18,9 @@ package baritone.behavior; import baritone.Baritone; +import baritone.api.event.events.BlockChangeEvent; import baritone.api.event.events.ChunkEvent; import baritone.api.event.events.TickEvent; -import baritone.api.event.events.type.EventState; import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.UnpackedSegment; @@ -284,12 +284,19 @@ public final class ElytraBehavior extends Behavior implements Helper { @Override public void onChunkEvent(ChunkEvent event) { - if (event.getState() == EventState.POST && event.getType().isPopulate()) { + if (event.isPostPopulate()) { final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); this.context.queueForPacking(chunk); } } + @Override + public void onBlockChange(BlockChangeEvent event) { + event.getAffectedChunks().stream() + .map(pos -> ctx.world().getChunk(pos.x, pos.z)) + .forEach(this.context::queueForPacking); + } + public void path(BlockPos destination) { this.pathManager.pathToDestination(destination); } @@ -382,10 +389,6 @@ public final class ElytraBehavior extends Behavior implements Helper { continue; } forceUseFirework = pitch.second(); - logDirect("final dy " + dy); - logDirect("i " + i); - logDirect("playerNear " + playerNear); - logDirect("relaxation " + relaxation); goingTo = path.get(i); this.aimPos = path.get(i).add(0, dy, 0); baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); From 7a8f8e8d47b8703c588d11e96771fe158f314f45 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 21:42:04 -0500 Subject: [PATCH 056/276] fix noob error from resolving merge conflicts --- src/main/java/baritone/behavior/ElytraBehavior.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 200ca48cb..77f414776 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -340,7 +340,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } if (isPaused()) return; - this.lines.clear(); this.clearLines.clear(); this.blockedLines.clear(); From 0886f176b3280e0bbb902c265c3d3e4ef160b488 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 21:46:03 -0500 Subject: [PATCH 057/276] Make elytra API changes --- .../api/behavior/IElytraBehavior.java | 17 ++++++------- .../baritone/behavior/ElytraBehavior.java | 25 ++++++------------- .../command/defaults/ElytraCommand.java | 2 +- .../defaults/ExecutionControlCommands.java | 2 -- 4 files changed, 15 insertions(+), 31 deletions(-) diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/behavior/IElytraBehavior.java index dc44eacda..3c3b91466 100644 --- a/src/api/java/baritone/api/behavior/IElytraBehavior.java +++ b/src/api/java/baritone/api/behavior/IElytraBehavior.java @@ -17,19 +17,16 @@ package baritone.api.behavior; +import net.minecraft.util.math.BlockPos; + public interface IElytraBehavior extends IBehavior { - /** - * Pause the current {@link IElytraBehavior} if it is pathing. - */ - void pause(); + + void pathTo(BlockPos destination); + + void cancel(); /** - * Resume the current {@link IElytraBehavior} if it is paused. - */ - void resume(); - - /** - * Returns true if the current {@link IElytraBehavior} is actively pathing and not paused. + * Returns {@code true} if the current {@link IElytraBehavior} is actively pathing. */ boolean isActive(); } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 77f414776..12723a001 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -64,7 +64,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final NetherPathfinderContext context; private final PathManager pathManager; private int sinceFirework; - private boolean pawsed = false; public ElytraBehavior(Baritone baritone) { super(baritone); @@ -180,6 +179,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path = Collections.emptyList(); this.playerNear = 0; this.completePath = true; + this.destination = null; } private void setPath(final UnpackedSegment segment) { @@ -305,33 +305,22 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .forEach(this.context::queueForPacking); } - public void path(BlockPos destination) { - pawsed = false; + @Override + public void pathTo(BlockPos destination) { this.pathManager.pathToDestination(destination); } + @Override public void cancel() { this.visiblePath = Collections.emptyList(); this.pathManager.clear(); this.aimPos = null; this.sinceFirework = 0; - pawsed = false; } + @Override public boolean isActive() { - return !this.pathManager.getPath().isEmpty() && !isPaused(); - } - - public void pause() { - this.pawsed = true; - } - - public void resume() { - this.pawsed = false; - } - - public boolean isPaused() { - return this.pawsed; + return !this.pathManager.getPath().isEmpty(); } @Override @@ -339,7 +328,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (event.getType() == TickEvent.Type.OUT) { return; } - if (isPaused()) return; + this.clearLines.clear(); this.blockedLines.clear(); diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 7c101fd3b..f96901b9b 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -64,7 +64,7 @@ public class ElytraCommand extends Command { if (y <= 0 || y >= 128) { throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); } - ((Baritone) baritone).getElytraBehavior().path(new BlockPos(x, y, z)); + ((Baritone) baritone).getElytraBehavior().pathTo(new BlockPos(x, y, z)); } @Override diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index 6ca324ad7..ef566bb8d 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -89,7 +89,6 @@ public class ExecutionControlCommands { throw new CommandInvalidStateException("Already paused"); } paused[0] = true; - baritone.getElytraBehavior().pause(); logDirect("Paused"); } @@ -124,7 +123,6 @@ public class ExecutionControlCommands { throw new CommandInvalidStateException("Not paused"); } paused[0] = false; - baritone.getElytraBehavior().resume(); logDirect("Resumed"); } From 1257a0128cdcd95637b33c75c9baccd34ceac216 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 21:46:56 -0500 Subject: [PATCH 058/276] Remove unnecessary `Baritone` casts --- src/main/java/baritone/command/defaults/ElytraCommand.java | 2 +- .../baritone/command/defaults/ExecutionControlCommands.java | 2 +- src/main/java/baritone/command/defaults/ForceCancelCommand.java | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index f96901b9b..3414c7bb3 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -64,7 +64,7 @@ public class ElytraCommand extends Command { if (y <= 0 || y >= 128) { throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); } - ((Baritone) baritone).getElytraBehavior().pathTo(new BlockPos(x, y, z)); + baritone.getElytraBehavior().pathTo(new BlockPos(x, y, z)); } @Override diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index ef566bb8d..e7f7c9497 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -181,7 +181,7 @@ public class ExecutionControlCommands { paused[0] = false; } baritone.getPathingBehavior().cancelEverything(); - ((Baritone) baritone).getElytraBehavior().cancel(); + baritone.getElytraBehavior().cancel(); logDirect("ok canceled"); } diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index 60ccdab01..bc6dbd0a4 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -40,7 +40,7 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); - ((Baritone) baritone).getElytraBehavior().cancel(); + baritone.getElytraBehavior().cancel(); logDirect("ok force canceled"); } From 1da7ab2c2229373d1f4ba1bcb0cb70248961eb7e Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 18 Jun 2023 23:58:20 -0500 Subject: [PATCH 059/276] Fix raytracer rendering --- src/main/java/baritone/utils/PathRenderer.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index d608d4a2b..5898ce643 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -110,22 +110,16 @@ public final class PathRenderer implements IRenderer { } if (!elytra.clearLines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); - boolean orig = settings.renderPathAsLine.value; - settings.renderPathAsLine.value = true; for (Pair line : elytra.clearLines) { emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); } - settings.renderPathAsLine.value = orig; IRenderer.endLines(settings.renderPathIgnoreDepth.value); } if (!elytra.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); - boolean orig = settings.renderPathAsLine.value; - settings.renderPathAsLine.value = true; for (Pair line : elytra.blockedLines) { emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); } - settings.renderPathAsLine.value = orig; IRenderer.endLines(settings.renderPathIgnoreDepth.value); } @@ -179,13 +173,21 @@ public final class PathRenderer implements IRenderer { IRenderer.glColor(color, alpha); } - emitLine(start.x, start.y, start.z, end.x, end.y, end.z); + emitPathLine(start.x, start.y, start.z, end.x, end.y, end.z); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } private static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) { + double vpX = renderManager.viewerPosX; + double vpY = renderManager.viewerPosY; + double vpZ = renderManager.viewerPosZ; + buffer.pos(x1 - vpX, y1 - vpY, z1 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 - vpX, y2 - vpY, z2 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + } + + private static void emitPathLine(double x1, double y1, double z1, double x2, double y2, double z2) { double vpX = renderManager.viewerPosX; double vpY = renderManager.viewerPosY; double vpZ = renderManager.viewerPosZ; From 67efb7a5b676dbcf7afe59dede5155ab3dbbd821 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 00:34:22 -0500 Subject: [PATCH 060/276] Add `experimentalRaytrace` setting for native raytrace Update `nether-pathfinder` to 0.15 --- build.gradle | 4 +- src/api/java/baritone/api/Settings.java | 3 + .../baritone/behavior/ElytraBehavior.java | 57 +++++++++++++++---- .../elytra/NetherPathfinderContext.java | 23 +++++++- 4 files changed, 74 insertions(+), 13 deletions(-) diff --git a/build.gradle b/build.gradle index 6d0ba4f1a..c3ef73c32 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.12') + launchImplementation('dev.babbaj:nether-pathfinder:0.15') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.12' + implementation 'dev.babbaj:nether-pathfinder:0.15' } mixin { diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 116df04e0..3f46c24d9 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -62,7 +62,10 @@ public final class Settings { public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); + + // Experimental Elytra Settings public final Setting experimentalTakeoff = new Setting<>(false); + public final Setting experimentalRaytrace = new Setting<>(false); /** * Allow Baritone to break blocks diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 12723a001..2a6c3c0c8 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -40,7 +40,6 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -169,9 +168,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Vec3d pathAt(int i) { return new Vec3d( - this.path.get(i).x + 0.000123, - this.path.get(i).y + 0.000456, - this.path.get(i).z + 0.000789 + this.path.get(i).x, + this.path.get(i).y, + this.path.get(i).z ); } @@ -502,6 +501,44 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } final AxisAlignedBB bb = ctx.player().getEntityBoundingBox().grow(growAmount); + + if (Baritone.settings().experimentalRaytrace.value) { + final double ox = dest.x - start.x; + final double oy = dest.y - start.y; + final double oz = dest.z - start.z; + + final double[] src = new double[] { + bb.minX, bb.minY, bb.minZ, + bb.minX, bb.minY, bb.maxZ, + bb.minX, bb.maxY, bb.minZ, + bb.minX, bb.maxY, bb.maxZ, + bb.maxX, bb.minY, bb.minZ, + bb.maxX, bb.minY, bb.maxZ, + bb.maxX, bb.maxY, bb.minZ, + bb.maxX, bb.maxY, bb.maxZ, + }; + final double[] dst = new double[] { + bb.minX + ox, bb.minY + oy, bb.minZ + oz, + bb.minX + ox, bb.minY + oy, bb.maxZ + oz, + bb.minX + ox, bb.maxY + oy, bb.minZ + oz, + bb.minX + ox, bb.maxY + oy, bb.maxZ + oz, + bb.maxX + ox, bb.minY + oy, bb.minZ + oz, + bb.maxX + ox, bb.minY + oy, bb.maxZ + oz, + bb.maxX + ox, bb.maxY + oy, bb.minZ + oz, + bb.maxX + ox, bb.maxY + oy, bb.maxZ + oz, + }; + + // Batch together all 8 traces + final boolean[] hitOut = new boolean[8]; + this.context.raytrace(src, dst, hitOut); + for (boolean hit : hitOut) { + if (hit) { + return false; + } + } + return true; + } + final Vec3d[] corners = new Vec3d[]{ new Vec3d(bb.minX, bb.minY, bb.minZ), new Vec3d(bb.minX, bb.minY, bb.maxZ), @@ -522,12 +559,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private boolean clearView(Vec3d start, Vec3d dest) { - boolean oxy = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z); - boolean meow = !rayTraceBlocks(start, dest); - if (oxy != meow) { - logDirect(start + " " + dest + " " + oxy + " " + meow); - } - if (oxy) { + boolean clear = !(Baritone.settings().experimentalRaytrace.value + ? this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z) + : this.rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z) // ox method + ); + + if (clear) { clearLines.add(new Pair<>(start, dest)); return true; } else { diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 2d407375a..0a833ab5d 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -21,6 +21,7 @@ import dev.babbaj.pathfinder.NetherPathfinder; import dev.babbaj.pathfinder.PathSegment; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; @@ -57,10 +58,30 @@ public final class NetherPathfinderContext { this.context, src.getX(), src.getY(), src.getZ(), dst.getX(), dst.getY(), dst.getZ(), - true + true, + 10000 ), this.executor); } + public boolean raytrace(final double startX, final double startY, final double startZ, + final double endX, final double endY, final double endZ) { + final boolean[] hitOut = new boolean[1]; + NetherPathfinder.raytrace( + this.context, + true, + 1, + new double[] { startX, startY, startZ }, + new double[] { endX, endY, endZ }, + hitOut, + null + ); + return hitOut[0]; + } + + public void raytrace(final double[] src, final double[] dst, final boolean[] hitOut) { + NetherPathfinder.raytrace(this.context, true, hitOut.length, src, dst, hitOut, null); + } + public void cancel() { NetherPathfinder.cancel(this.context); } From 2b259d6dee9bbb60b683f8ee74786b4482d38cc2 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 18 Jun 2023 23:09:43 -0700 Subject: [PATCH 061/276] cuter debug --- .../baritone/behavior/ElytraBehavior.java | 30 +++++++++++-------- 1 file changed, 17 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 2a6c3c0c8..484d2d341 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -99,13 +99,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public void pathToDestination(BlockPos destination) { this.destination = destination; + final long start = System.nanoTime(); this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) .thenRun(() -> { - final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); + final double distance = this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); if (this.completePath) { - logDirect(String.format("Computed path (%d blocks)", distance)); + logDirect(String.format("Computed path (%.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); } else { - logDirect(String.format("Computed segment (Next %d blocks)", distance)); + logDirect(String.format("Computed segment (Next %.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); } }) .whenComplete((result, ex) -> { @@ -116,7 +117,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }); } - public void pathRecalcSegment(final int upToIncl) { + public void pathRecalcSegment(final int blockedAt, final int upToIncl) { if (this.recalculating) { return; } @@ -124,12 +125,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.recalculating = true; final List after = this.path.subList(upToIncl, this.path.size()); final boolean complete = this.completePath; + final BetterBlockPos blockage = this.path.get(blockedAt); + final long start = System.nanoTime(); this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) .thenRun(() -> { final int recompute = this.path.size() - after.size() - 1; - final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); - logDirect(String.format("Recomputed segment (Next %d blocks)", distance)); + final double distance = this.pathAt(0).distanceTo(this.pathAt(recompute)); // in spirit same as ctx.playerFeet().distanceTo(this.path.get(upToIncl)), but, thread safe (those could have changed in the meantime) + logDirect(String.format("Recalculated segment around path blockage near %s %s %s (next %.1f blocks in %.4f seconds)", SettingsUtil.maybeCensor(blockage.x), SettingsUtil.maybeCensor(blockage.y), SettingsUtil.maybeCensor(blockage.z), distance, (System.nanoTime() - start) / 1e9d)); }) .whenComplete((result, ex) -> { this.recalculating = false; @@ -146,16 +149,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.recalculating = true; final List before = this.path.subList(0, afterIncl + 1); + final long start = System.nanoTime(); this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; - final int distance = (int) this.pathAt(0).distanceTo(this.pathAt(recompute)); + final double distance = this.pathAt(0).distanceTo(this.pathAt(recompute)); if (this.completePath) { - logDirect(String.format("Computed path (%d blocks)", distance)); + logDirect(String.format("Computed path (%.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); } else { - logDirect(String.format("Computed next segment (Next %d blocks)", distance)); + logDirect(String.format("Computed segment (Next %.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); } }) .whenComplete((result, ex) -> { @@ -228,7 +232,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!clearView(pathAt(i), pathAt(i + 1))) { // obstacle. where do we return to pathing? // find the next valid segment - this.pathRecalcSegment(rangeEndExcl - 1); + this.pathRecalcSegment(i, rangeEndExcl - 1); break outer; } } @@ -443,7 +447,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ctx.player().inventory.currentItem = firstFireworksInHotbar; } } - logDirect("firework" + (forceUseFirework ? " takeoff" : "")); + logDirect("attempting to use firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); sinceFirework = 0; } @@ -507,7 +511,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final double oy = dest.y - start.y; final double oz = dest.z - start.z; - final double[] src = new double[] { + final double[] src = new double[]{ bb.minX, bb.minY, bb.minZ, bb.minX, bb.minY, bb.maxZ, bb.minX, bb.maxY, bb.minZ, @@ -517,7 +521,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H bb.maxX, bb.maxY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ, }; - final double[] dst = new double[] { + final double[] dst = new double[]{ bb.minX + ox, bb.minY + oy, bb.minZ + oz, bb.minX + ox, bb.minY + oy, bb.maxZ + oz, bb.minX + ox, bb.maxY + oy, bb.minZ + oz, From a32ac59ec1842050f09c5e6fe190e4b23be30e2f Mon Sep 17 00:00:00 2001 From: rycbar0 <100363533+rycbar0@users.noreply.github.com> Date: Mon, 19 Jun 2023 12:44:32 +0200 Subject: [PATCH 062/276] prevent went off with a bang --- src/main/java/baritone/behavior/ElytraBehavior.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 484d2d341..28628e68f 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -487,7 +487,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); return itemStack.getItem() == Items.FIREWORKS && subCompound != null - && subCompound.hasKey("Flight"); + && subCompound.hasKey("Flight") + && !subCompound.hasKey("Explosions"); } private boolean isFireworkActive() { From 9e10faa4c56da5af29226b344e8a0bb8ec807845 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 12:32:25 -0500 Subject: [PATCH 063/276] Elytra inventory modifications - Use `throwaway` to switch items - Remove inventory settings - Prioritizes boost fireworks, but works without - Avoids explosion fireworks --- src/api/java/baritone/api/Settings.java | 8 --- .../baritone/behavior/ElytraBehavior.java | 61 +++++-------------- 2 files changed, 16 insertions(+), 53 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 3f46c24d9..23f138eeb 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -50,14 +50,6 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); - /** - * Allow users to control firework usage instead of Baritone. e.g. with their own client modules. - */ - public final Setting elytraUseFireworks = new Setting<>(true); - /** - * Allow Baritone to manage fireworks in the inventory and hotbar - */ - public final Setting elytraInventory = new Setting<>(true); public final Setting elytraFireworkSpeed = new Setting<>(0.6); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 28628e68f..3ff824474 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -431,21 +431,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (forceUseFirework || (!firework && sinceFirework > 10 - && Baritone.settings().elytraUseFireworks.value && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! && currentSpeed < Baritone.settings().elytraFireworkSpeed.value) ) { - if (Baritone.settings().elytraInventory.value) { - final int firstFireworksInHotbar = firstFireworksInHotbar(); - if (firstFireworksInHotbar == -1) { - if (!swapToFireworksInInventory()) { - logDirect("no fireworks"); - return; - } - } else { - ctx.player().inventory.currentItem = firstFireworksInHotbar; - } + // Prioritize boosting fireworks over regular ones + // TODO: Take the minimum boost time into account? + if (!baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isBoostingFireworks) && + !baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isFireworks)) { + logDirect("no fireworks"); + return; } logDirect("attempting to use firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); @@ -453,42 +448,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private boolean swapToFireworksInInventory() { - final int i = firstFireworksInInventory(); - if (i != -1) { - baritone.getInventoryBehavior().attemptToPutOnHotbar(i, (slot) -> slot != 7); - ctx.player().inventory.currentItem = 7; - return true; + private static boolean isFireworks(final ItemStack itemStack) { + if (itemStack.getItem() != Items.FIREWORKS) { + return false; } - return false; - } - - private int firstFireworksInInventory() { - final NonNullList invy = ctx.player().inventory.mainInventory; - for (int i = 0; i < invy.size(); i++) { - if (isBoostingFireworks(invy.get(i))) { - return i; - } - } - return -1; - } - - private int firstFireworksInHotbar() { - final NonNullList invy = ctx.player().inventory.mainInventory; - for (int i = 0; i < 9; i++) { - if (isBoostingFireworks(invy.get(i))) { - return i; - } - } - return -1; - } - - private boolean isBoostingFireworks(final ItemStack itemStack) { + // If it has NBT data, make sure it won't cause us to explode. final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); - return itemStack.getItem() == Items.FIREWORKS - && subCompound != null - && subCompound.hasKey("Flight") - && !subCompound.hasKey("Explosions"); + return subCompound == null || !subCompound.hasKey("Explosions"); + } + + private static boolean isBoostingFireworks(final ItemStack itemStack) { + final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); + return isFireworks(itemStack) && subCompound != null && subCompound.hasKey("Flight"); } private boolean isFireworkActive() { From 6741dff12b241cb451735aae934295b69be867aa Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Mon, 19 Jun 2023 14:17:54 -0400 Subject: [PATCH 064/276] replaced (PI / 180) constants, RotationUtils calcVec3dFromRotation->calcLookDirectionFromRotation and named local variables. --- .../java/baritone/api/utils/RayTraceUtils.java | 2 +- .../java/baritone/api/utils/RotationUtils.java | 17 ++++++++++++----- .../java/baritone/behavior/ElytraBehavior.java | 10 +++++----- 3 files changed, 18 insertions(+), 11 deletions(-) diff --git a/src/api/java/baritone/api/utils/RayTraceUtils.java b/src/api/java/baritone/api/utils/RayTraceUtils.java index 4f763e392..d80f84e5e 100644 --- a/src/api/java/baritone/api/utils/RayTraceUtils.java +++ b/src/api/java/baritone/api/utils/RayTraceUtils.java @@ -50,7 +50,7 @@ public final class RayTraceUtils { } else { start = entity.getPositionEyes(1.0F); // do whatever is correct } - Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation); + Vec3d direction = RotationUtils.calcLookDirectionFromRotation(rotation); Vec3d end = start.add( direction.x * blockReachDistance, direction.y * blockReachDistance, diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java index 1991ab878..4ebb22dd5 100644 --- a/src/api/java/baritone/api/utils/RotationUtils.java +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -37,11 +37,13 @@ public final class RotationUtils { * Constant that a degree value is multiplied by to get the equivalent radian value */ public static final double DEG_TO_RAD = Math.PI / 180.0; + public static final float DEG_TO_RAD_F = (float) DEG_TO_RAD; /** * Constant that a radian value is multiplied by to get the equivalent degree value */ public static final double RAD_TO_DEG = 180.0 / Math.PI; + public static final float RAD_TO_DEG_F = (float) RAD_TO_DEG; /** * Offsets from the root block position to the center of each side. @@ -122,12 +124,17 @@ public final class RotationUtils { * @param rotation The input rotation * @return Look vector for the rotation */ + public static Vec3d calcLookDirectionFromRotation(Rotation rotation) { + float flatZ = MathHelper.cos((-rotation.getYaw() * DEG_TO_RAD_F) - (float) Math.PI); + float flatX = MathHelper.sin((-rotation.getYaw() * DEG_TO_RAD_F) - (float) Math.PI); + float pitchBase = -MathHelper.cos(-rotation.getPitch() * DEG_TO_RAD_F); + float pitchHeight = MathHelper.sin(-rotation.getPitch() * DEG_TO_RAD_F); + return new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); + } + + @Deprecated public static Vec3d calcVec3dFromRotation(Rotation rotation) { - float f = MathHelper.cos(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI); - float f1 = MathHelper.sin(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI); - float f2 = -MathHelper.cos(-rotation.getPitch() * (float) DEG_TO_RAD); - float f3 = MathHelper.sin(-rotation.getPitch() * (float) DEG_TO_RAD); - return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2)); + return calcLookDirectionFromRotation(rotation); } /** diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3ff824474..11512b7b1 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -622,10 +622,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H double motionX = motion.x; double motionY = motion.y; double motionZ = motion.z; - float flatZ = MathHelper.cos(-rotationYaw * 0.017453292F - (float) Math.PI); // 0.174... is Math.PI / 180 - float flatX = MathHelper.sin(-rotationYaw * 0.017453292F - (float) Math.PI); - float pitchBase = -MathHelper.cos(-rotationPitch * 0.017453292F); - float pitchHeight = MathHelper.sin(-rotationPitch * 0.017453292F); + float flatZ = MathHelper.cos((-rotationYaw * RotationUtils.DEG_TO_RAD_F) - (float) Math.PI); + float flatX = MathHelper.sin((-rotationYaw * RotationUtils.DEG_TO_RAD_F) - (float) Math.PI); + float pitchBase = -MathHelper.cos(-rotationPitch * RotationUtils.DEG_TO_RAD_F); + float pitchHeight = MathHelper.sin(-rotationPitch * RotationUtils.DEG_TO_RAD_F); Vec3d lookDirection = new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); if (firework) { @@ -635,7 +635,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; } - float pitchRadians = rotationPitch * 0.017453292F; + float pitchRadians = rotationPitch * RotationUtils.DEG_TO_RAD_F; double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); double thisIsAlwaysOne = lookDirection.length(); From 8d3b0c8f0772366c189f02d52ac126528f8379a5 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 14:10:41 -0500 Subject: [PATCH 065/276] Always enforce `sinceFirework` --- src/main/java/baritone/behavior/ElytraBehavior.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 11512b7b1..b885b842c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -429,11 +429,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ctx.player().motionZ ).length(); - if (forceUseFirework || (!firework - && sinceFirework > 10 + if (sinceFirework > 10 && (forceUseFirework || (!firework && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! - && currentSpeed < Baritone.settings().elytraFireworkSpeed.value) + && currentSpeed < Baritone.settings().elytraFireworkSpeed.value)) ) { // Prioritize boosting fireworks over regular ones // TODO: Take the minimum boost time into account? From 7d17ace15df27ede1c28df456eb4e0bb3f144332 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 15:15:29 -0500 Subject: [PATCH 066/276] Reset recalculating flag on `clear` --- src/main/java/baritone/behavior/ElytraBehavior.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b885b842c..4db310346 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -182,6 +182,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path = Collections.emptyList(); this.playerNear = 0; this.completePath = true; + this.recalculating = false; this.destination = null; } From c6a66240453c5a9c2744061e734fb2818fe41a1f Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 15:16:11 -0500 Subject: [PATCH 067/276] Reorder fields --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 4db310346..74e05edad 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -78,10 +78,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private BlockPos destination; private List path; private boolean completePath; - - private int playerNear; - private boolean recalculating; + private int playerNear; public PathManager() { // lol imagine initializing fields normally @@ -179,11 +177,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } public void clear() { + this.destination = null; this.path = Collections.emptyList(); - this.playerNear = 0; this.completePath = true; this.recalculating = false; - this.destination = null; + this.playerNear = 0; } private void setPath(final UnpackedSegment segment) { From 90f401a06746c89c37aa7c78489a8ee013dc8e29 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 15:19:32 -0500 Subject: [PATCH 068/276] Remove legacy raytracing methods --- src/api/java/baritone/api/Settings.java | 1 - .../baritone/behavior/ElytraBehavior.java | 270 ++---------------- 2 files changed, 28 insertions(+), 243 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 23f138eeb..3cfef2ffc 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -57,7 +57,6 @@ public final class Settings { // Experimental Elytra Settings public final Setting experimentalTakeoff = new Setting<>(false); - public final Setting experimentalRaytrace = new Setting<>(false); /** * Allow Baritone to break blocks diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 74e05edad..5a8614edc 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -476,56 +476,36 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final AxisAlignedBB bb = ctx.player().getEntityBoundingBox().grow(growAmount); - if (Baritone.settings().experimentalRaytrace.value) { - final double ox = dest.x - start.x; - final double oy = dest.y - start.y; - final double oz = dest.z - start.z; + final double ox = dest.x - start.x; + final double oy = dest.y - start.y; + final double oz = dest.z - start.z; - final double[] src = new double[]{ - bb.minX, bb.minY, bb.minZ, - bb.minX, bb.minY, bb.maxZ, - bb.minX, bb.maxY, bb.minZ, - bb.minX, bb.maxY, bb.maxZ, - bb.maxX, bb.minY, bb.minZ, - bb.maxX, bb.minY, bb.maxZ, - bb.maxX, bb.maxY, bb.minZ, - bb.maxX, bb.maxY, bb.maxZ, - }; - final double[] dst = new double[]{ - bb.minX + ox, bb.minY + oy, bb.minZ + oz, - bb.minX + ox, bb.minY + oy, bb.maxZ + oz, - bb.minX + ox, bb.maxY + oy, bb.minZ + oz, - bb.minX + ox, bb.maxY + oy, bb.maxZ + oz, - bb.maxX + ox, bb.minY + oy, bb.minZ + oz, - bb.maxX + ox, bb.minY + oy, bb.maxZ + oz, - bb.maxX + ox, bb.maxY + oy, bb.minZ + oz, - bb.maxX + ox, bb.maxY + oy, bb.maxZ + oz, - }; - - // Batch together all 8 traces - final boolean[] hitOut = new boolean[8]; - this.context.raytrace(src, dst, hitOut); - for (boolean hit : hitOut) { - if (hit) { - return false; - } - } - return true; - } - - final Vec3d[] corners = new Vec3d[]{ - new Vec3d(bb.minX, bb.minY, bb.minZ), - new Vec3d(bb.minX, bb.minY, bb.maxZ), - new Vec3d(bb.minX, bb.maxY, bb.minZ), - new Vec3d(bb.minX, bb.maxY, bb.maxZ), - new Vec3d(bb.maxX, bb.minY, bb.minZ), - new Vec3d(bb.maxX, bb.minY, bb.maxZ), - new Vec3d(bb.maxX, bb.maxY, bb.minZ), - new Vec3d(bb.maxX, bb.maxY, bb.maxZ), + final double[] src = new double[]{ + bb.minX, bb.minY, bb.minZ, + bb.minX, bb.minY, bb.maxZ, + bb.minX, bb.maxY, bb.minZ, + bb.minX, bb.maxY, bb.maxZ, + bb.maxX, bb.minY, bb.minZ, + bb.maxX, bb.minY, bb.maxZ, + bb.maxX, bb.maxY, bb.minZ, + bb.maxX, bb.maxY, bb.maxZ, + }; + final double[] dst = new double[]{ + bb.minX + ox, bb.minY + oy, bb.minZ + oz, + bb.minX + ox, bb.minY + oy, bb.maxZ + oz, + bb.minX + ox, bb.maxY + oy, bb.minZ + oz, + bb.minX + ox, bb.maxY + oy, bb.maxZ + oz, + bb.maxX + ox, bb.minY + oy, bb.minZ + oz, + bb.maxX + ox, bb.minY + oy, bb.maxZ + oz, + bb.maxX + ox, bb.maxY + oy, bb.minZ + oz, + bb.maxX + ox, bb.maxY + oy, bb.maxZ + oz, }; - for (final Vec3d corner : corners) { - if (!clearView(corner, dest.add(corner.subtract(start)))) { + // Batch together all 8 traces + final boolean[] hitOut = new boolean[8]; + this.context.raytrace(src, dst, hitOut); + for (boolean hit : hitOut) { + if (hit) { return false; } } @@ -533,11 +513,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private boolean clearView(Vec3d start, Vec3d dest) { - boolean clear = !(Baritone.settings().experimentalRaytrace.value - ? this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z) - : this.rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z) // ox method - ); - + boolean clear = !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); if (clear) { clearLines.add(new Pair<>(start, dest)); return true; @@ -666,195 +642,5 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Vec3d(motionX, motionY, motionZ); } - - private boolean rayTraceBlocks(final double startX, final double startY, final double startZ, - final double endX, final double endY, final double endZ) { - int voxelCurrX = fastFloor(startX); - int voxelCurrY = fastFloor(startY); - int voxelCurrZ = fastFloor(startZ); - - if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ)) { - return true; - } - - final int voxelEndX = fastFloor(endX); - final int voxelEndY = fastFloor(endY); - final int voxelEndZ = fastFloor(endZ); - double currPosX = startX; - double currPosY = startY; - double currPosZ = startZ; - - int steps = 200; // TODO: should we lower the max steps? - while (steps-- >= 0) { - if (voxelCurrX == voxelEndX && voxelCurrY == voxelEndY && voxelCurrZ == voxelEndZ) { - return false; - } - - final double distanceFromStartToEndX = endX - currPosX; - final double distanceFromStartToEndY = endY - currPosY; - final double distanceFromStartToEndZ = endZ - currPosZ; - - double nextIntegerX; - double nextIntegerY; - double nextIntegerZ; - // potentially more based branchless impl? - nextIntegerX = voxelCurrX + ((voxelCurrX - voxelEndX) >>> 31); // if voxelEnd > voxelIn, then voxelIn-voxelEnd will be negative, meaning the sign bit is 1 - nextIntegerY = voxelCurrY + ((voxelCurrY - voxelEndY) >>> 31); // if we do an unsigned right shift by 31, that sign bit becomes the LSB - nextIntegerZ = voxelCurrZ + ((voxelCurrZ - voxelEndZ) >>> 31); // therefore, this increments nextInteger iff EndX>inX, otherwise it leaves it alone - // remember: don't have to worry about the case when voxelEnd == voxelIn, because nextInteger value wont be used - - // these just have to be strictly greater than 1, might as well just go up to the next int - double fracIfSkipX = 2.0D; - double fracIfSkipY = 2.0D; - double fracIfSkipZ = 2.0D; - - // reminder to future self: don't "branchlessify" this, it's MUCH slower (pretty obviously, floating point div is much worse than a branch mispredict, but integer increment (like the other two removed branches) are cheap enough to be worth doing either way) - if (voxelEndX != voxelCurrX) { - fracIfSkipX = (nextIntegerX - currPosX) / distanceFromStartToEndX; - } - if (voxelEndY != voxelCurrY) { - fracIfSkipY = (nextIntegerY - currPosY) / distanceFromStartToEndY; - } - if (voxelEndZ != voxelCurrZ) { - fracIfSkipZ = (nextIntegerZ - currPosZ) / distanceFromStartToEndZ; - } - - if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) { - // note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default - currPosX = nextIntegerX; - currPosY += distanceFromStartToEndY * fracIfSkipX; - currPosZ += distanceFromStartToEndZ * fracIfSkipX; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int xFloorOffset = (voxelEndX - voxelCurrX) >>> 31; - voxelCurrX = (fastFloor(currPosX) - xFloorOffset); - voxelCurrY = (fastFloor(currPosY)); - voxelCurrZ = (fastFloor(currPosZ)); - } else if (fracIfSkipY < fracIfSkipZ) { - currPosX += distanceFromStartToEndX * fracIfSkipY; - currPosY = nextIntegerY; - currPosZ += distanceFromStartToEndZ * fracIfSkipY; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int yFloorOffset = (voxelEndY - voxelCurrY) >>> 31; - voxelCurrX = (fastFloor(currPosX)); - voxelCurrY = (fastFloor(currPosY) - yFloorOffset); - voxelCurrZ = (fastFloor(currPosZ)); - } else { - currPosX += distanceFromStartToEndX * fracIfSkipZ; - currPosY += distanceFromStartToEndY * fracIfSkipZ; - currPosZ = nextIntegerZ; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int zFloorOffset = (voxelEndZ - voxelCurrZ) >>> 31; - voxelCurrX = (fastFloor(currPosX)); - voxelCurrY = (fastFloor(currPosY)); - voxelCurrZ = (fastFloor(currPosZ) - zFloorOffset); - } - - if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ)) { - return true; - } - } - return false; - } - - private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; - private static final int FLOOR_DOUBLE_I = 1_073_741_824; - - private static int fastFloor(final double v) { - return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; - } - - private boolean rayTraceBlocks(Vec3d start, Vec3d end) { - int x1 = MathHelper.floor(end.x); - int y1 = MathHelper.floor(end.y); - int z1 = MathHelper.floor(end.z); - int x2 = MathHelper.floor(start.x); - int y2 = MathHelper.floor(start.y); - int z2 = MathHelper.floor(start.z); - BlockPos blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate)) { - return true; - } - int steps = 200; - while (steps-- >= 0) { - if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { - return false; - } - if (x2 == x1 && y2 == y1 && z2 == z1) { - return false; - } - boolean hitX = true; - boolean hitY = true; - boolean hitZ = true; - double nextX = 999.0D; - double nextY = 999.0D; - double nextZ = 999.0D; - if (x1 > x2) { - nextX = (double) x2 + 1.0D; - } else if (x1 < x2) { - nextX = (double) x2 + 0.0D; - } else { - hitX = false; - } - if (y1 > y2) { - nextY = (double) y2 + 1.0D; - } else if (y1 < y2) { - nextY = (double) y2 + 0.0D; - } else { - hitY = false; - } - if (z1 > z2) { - nextZ = (double) z2 + 1.0D; - } else if (z1 < z2) { - nextZ = (double) z2 + 0.0D; - } else { - hitZ = false; - } - double stepX = 999.0D; - double stepY = 999.0D; - double stepZ = 999.0D; - double dirX = end.x - start.x; - double dirY = end.y - start.y; - double dirZ = end.z - start.z; - if (hitX) { - stepX = (nextX - start.x) / dirX; - } - if (hitY) { - stepY = (nextY - start.y) / dirY; - } - if (hitZ) { - stepZ = (nextZ - start.z) / dirZ; - } - if (stepX == -0.0D) { - stepX = -1.0E-4D; - } - if (stepY == -0.0D) { - stepY = -1.0E-4D; - } - if (stepZ == -0.0D) { - stepZ = -1.0E-4D; - } - EnumFacing dir; - if (stepX < stepY && stepX < stepZ) { - dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; - start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); - } else if (stepY < stepZ) { - dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; - start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); - } else { - dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; - start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); - } - x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); - y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); - z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); - blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate1)) { - return true; - } - } - return false; - } } From 82156250df4cf43a3f33c07579d53964aca22da2 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 15:20:04 -0500 Subject: [PATCH 069/276] Update `nether-pathfinder` to 0.16 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index c3ef73c32..95abfec6a 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.15') + launchImplementation('dev.babbaj:nether-pathfinder:0.16') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.15' + implementation 'dev.babbaj:nether-pathfinder:0.16' } mixin { From 959b4cddbd400cb256a6d53c297a6d67154f6c5f Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 15:29:30 -0500 Subject: [PATCH 070/276] Remove unneeded `while (true)` --- .../baritone/behavior/ElytraBehavior.java | 43 ++++++++----------- 1 file changed, 19 insertions(+), 24 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5a8614edc..a0502d930 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -63,6 +63,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final NetherPathfinderContext context; private final PathManager pathManager; private int sinceFirework; + private BlockStateInterface bsi; public ElytraBehavior(Baritone baritone) { super(baritone); @@ -212,30 +213,26 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } - outer: - while (true) { - int rangeStartIncl = playerNear; - int rangeEndExcl = playerNear; - while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { - rangeEndExcl++; - } - if (rangeStartIncl >= rangeEndExcl) { - // not loaded yet? + int rangeStartIncl = playerNear; + int rangeEndExcl = playerNear; + while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { + rangeEndExcl++; + } + if (rangeStartIncl >= rangeEndExcl) { + // not loaded yet? + return; + } + if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { + // we're in a wall + return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: + } + for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { + if (!clearView(pathAt(i), pathAt(i + 1))) { + // obstacle. where do we return to pathing? + // find the next valid segment + this.pathRecalcSegment(i, rangeEndExcl - 1); return; } - if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { - // we're in a wall - return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: - } - for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!clearView(pathAt(i), pathAt(i + 1))) { - // obstacle. where do we return to pathing? - // find the next valid segment - this.pathRecalcSegment(i, rangeEndExcl - 1); - break outer; - } - } - break; } } @@ -582,8 +579,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - private BlockStateInterface bsi; - public boolean passable(int x, int y, int z) { return passable(this.bsi.get0(x, y, z)); } From e57a84ded4b0af83b8388c9dfad016782d14b70f Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 19 Jun 2023 17:58:06 -0400 Subject: [PATCH 071/276] use legacy raytrace with ignore liquid to get out of lava --- .../baritone/behavior/ElytraBehavior.java | 236 ++++++++++++++++-- .../elytra/NetherPathfinderContext.java | 4 +- 2 files changed, 219 insertions(+), 21 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index a0502d930..1bf098132 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -222,12 +222,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // not loaded yet? return; } - if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)))) { + if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)), false)) { // we're in a wall return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!clearView(pathAt(i), pathAt(i + 1))) { + if (!clearView(pathAt(i), pathAt(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment this.pathRecalcSegment(i, rangeEndExcl - 1); @@ -363,6 +363,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H BetterBlockPos goingTo = null; boolean forceUseFirework = false; this.sinceFirework++; + final boolean isInLava = ctx.player().isInLava(); outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) @@ -379,13 +380,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H continue; } if (start.distanceTo(dest) < 40) { - if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0)) || !clearView(dest, this.pathManager.pathAt(i + lookahead))) { + if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0), false) || !clearView(dest, this.pathManager.pathAt(i + lookahead), false)) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, this.pathManager.pathAt(i))) { + if (!clearView(dest, this.pathManager.pathAt(i), false)) { continue; } } @@ -395,10 +396,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Double grow = relaxation == 2 ? null : relaxation == 0 ? 1.0d : 0.25d; - if (isClear(start, dest, grow)) { + if (isClear(start, dest, grow, isInLava)) { final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework); + final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework, isInLava); if (pitch.first() == null) { baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); continue; @@ -463,8 +464,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .anyMatch(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())); } - private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount) { - if (!clearView(start, dest)) { + private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { + if (!clearView(start, dest, ignoreLava)) { return false; } if (growAmount == null) { @@ -509,8 +510,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return true; } - private boolean clearView(Vec3d start, Vec3d dest) { - boolean clear = !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); + private boolean clearView(Vec3d start, Vec3d dest, boolean ignoreLava) { + final boolean clear; + if (!ignoreLava) { + clear = !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); + } else { + clear = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z, true); + } + if (clear) { clearLines.add(new Pair<>(start, dest)); return true; @@ -520,14 +527,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted) { - final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, currentlyBoosted); + private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted, boolean ignoreLava) { + final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, currentlyBoosted, ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - final Float usingFirework = this.solvePitch(goalDirection, steps, relaxation == 2, true); + final Float usingFirework = this.solvePitch(goalDirection, steps, relaxation == 2, true, ignoreLava); if (usingFirework != null) { return new Pair<>(usingFirework, true); } @@ -536,7 +543,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Pair<>(null, false); } - private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate, boolean firework) { + private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate, boolean firework, boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -561,7 +568,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 1; y++) { for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { - if (!this.passable(x, y, z)) { + if (!this.passable(x, y, z, ignoreLava)) { continue outer; } } @@ -579,12 +586,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - public boolean passable(int x, int y, int z) { - return passable(this.bsi.get0(x, y, z)); + public boolean passable(int x, int y, int z, boolean ignoreLava) { + return passable(this.bsi.get0(x, y, z), ignoreLava); } - public static boolean passable(IBlockState state) { - return state.getMaterial() == Material.AIR; + public static boolean passable(IBlockState state, boolean ignoreLava) { + Material mat = state.getMaterial(); + return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); } private static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { @@ -637,5 +645,195 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Vec3d(motionX, motionY, motionZ); } + + private boolean rayTraceBlocks(final double startX, final double startY, final double startZ, + final double endX, final double endY, final double endZ, boolean ignoreLava) { + int voxelCurrX = fastFloor(startX); + int voxelCurrY = fastFloor(startY); + int voxelCurrZ = fastFloor(startZ); + + if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ, ignoreLava)) { + return true; + } + + final int voxelEndX = fastFloor(endX); + final int voxelEndY = fastFloor(endY); + final int voxelEndZ = fastFloor(endZ); + double currPosX = startX; + double currPosY = startY; + double currPosZ = startZ; + + int steps = 200; // TODO: should we lower the max steps? + while (steps-- >= 0) { + if (voxelCurrX == voxelEndX && voxelCurrY == voxelEndY && voxelCurrZ == voxelEndZ) { + return false; + } + + final double distanceFromStartToEndX = endX - currPosX; + final double distanceFromStartToEndY = endY - currPosY; + final double distanceFromStartToEndZ = endZ - currPosZ; + + double nextIntegerX; + double nextIntegerY; + double nextIntegerZ; + // potentially more based branchless impl? + nextIntegerX = voxelCurrX + ((voxelCurrX - voxelEndX) >>> 31); // if voxelEnd > voxelIn, then voxelIn-voxelEnd will be negative, meaning the sign bit is 1 + nextIntegerY = voxelCurrY + ((voxelCurrY - voxelEndY) >>> 31); // if we do an unsigned right shift by 31, that sign bit becomes the LSB + nextIntegerZ = voxelCurrZ + ((voxelCurrZ - voxelEndZ) >>> 31); // therefore, this increments nextInteger iff EndX>inX, otherwise it leaves it alone + // remember: don't have to worry about the case when voxelEnd == voxelIn, because nextInteger value wont be used + + // these just have to be strictly greater than 1, might as well just go up to the next int + double fracIfSkipX = 2.0D; + double fracIfSkipY = 2.0D; + double fracIfSkipZ = 2.0D; + + // reminder to future self: don't "branchlessify" this, it's MUCH slower (pretty obviously, floating point div is much worse than a branch mispredict, but integer increment (like the other two removed branches) are cheap enough to be worth doing either way) + if (voxelEndX != voxelCurrX) { + fracIfSkipX = (nextIntegerX - currPosX) / distanceFromStartToEndX; + } + if (voxelEndY != voxelCurrY) { + fracIfSkipY = (nextIntegerY - currPosY) / distanceFromStartToEndY; + } + if (voxelEndZ != voxelCurrZ) { + fracIfSkipZ = (nextIntegerZ - currPosZ) / distanceFromStartToEndZ; + } + + if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) { + // note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default + currPosX = nextIntegerX; + currPosY += distanceFromStartToEndY * fracIfSkipX; + currPosZ += distanceFromStartToEndZ * fracIfSkipX; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int xFloorOffset = (voxelEndX - voxelCurrX) >>> 31; + voxelCurrX = (fastFloor(currPosX) - xFloorOffset); + voxelCurrY = (fastFloor(currPosY)); + voxelCurrZ = (fastFloor(currPosZ)); + } else if (fracIfSkipY < fracIfSkipZ) { + currPosX += distanceFromStartToEndX * fracIfSkipY; + currPosY = nextIntegerY; + currPosZ += distanceFromStartToEndZ * fracIfSkipY; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int yFloorOffset = (voxelEndY - voxelCurrY) >>> 31; + voxelCurrX = (fastFloor(currPosX)); + voxelCurrY = (fastFloor(currPosY) - yFloorOffset); + voxelCurrZ = (fastFloor(currPosZ)); + } else { + currPosX += distanceFromStartToEndX * fracIfSkipZ; + currPosY += distanceFromStartToEndY * fracIfSkipZ; + currPosZ = nextIntegerZ; + // tested: faster to paste this 3 times with only one of the subtractions in each + final int zFloorOffset = (voxelEndZ - voxelCurrZ) >>> 31; + voxelCurrX = (fastFloor(currPosX)); + voxelCurrY = (fastFloor(currPosY)); + voxelCurrZ = (fastFloor(currPosZ) - zFloorOffset); + } + + if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ, ignoreLava)) { + return true; + } + } + return false; + } + + private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; + private static final int FLOOR_DOUBLE_I = 1_073_741_824; + + private static int fastFloor(final double v) { + return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; + } + + private boolean rayTraceBlocks(Vec3d start, Vec3d end, boolean ignoreLava) { + int x1 = MathHelper.floor(end.x); + int y1 = MathHelper.floor(end.y); + int z1 = MathHelper.floor(end.z); + int x2 = MathHelper.floor(start.x); + int y2 = MathHelper.floor(start.y); + int z2 = MathHelper.floor(start.z); + BlockPos blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate, ignoreLava)) { + return true; + } + int steps = 200; + while (steps-- >= 0) { + if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { + return false; + } + if (x2 == x1 && y2 == y1 && z2 == z1) { + return false; + } + boolean hitX = true; + boolean hitY = true; + boolean hitZ = true; + double nextX = 999.0D; + double nextY = 999.0D; + double nextZ = 999.0D; + if (x1 > x2) { + nextX = (double) x2 + 1.0D; + } else if (x1 < x2) { + nextX = (double) x2 + 0.0D; + } else { + hitX = false; + } + if (y1 > y2) { + nextY = (double) y2 + 1.0D; + } else if (y1 < y2) { + nextY = (double) y2 + 0.0D; + } else { + hitY = false; + } + if (z1 > z2) { + nextZ = (double) z2 + 1.0D; + } else if (z1 < z2) { + nextZ = (double) z2 + 0.0D; + } else { + hitZ = false; + } + double stepX = 999.0D; + double stepY = 999.0D; + double stepZ = 999.0D; + double dirX = end.x - start.x; + double dirY = end.y - start.y; + double dirZ = end.z - start.z; + if (hitX) { + stepX = (nextX - start.x) / dirX; + } + if (hitY) { + stepY = (nextY - start.y) / dirY; + } + if (hitZ) { + stepZ = (nextZ - start.z) / dirZ; + } + if (stepX == -0.0D) { + stepX = -1.0E-4D; + } + if (stepY == -0.0D) { + stepY = -1.0E-4D; + } + if (stepZ == -0.0D) { + stepZ = -1.0E-4D; + } + EnumFacing dir; + if (stepX < stepY && stepX < stepZ) { + dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; + start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); + } else if (stepY < stepZ) { + dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; + start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); + } else { + dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; + start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); + } + x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); + y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); + z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); + blockpos = new BlockPos(x2, y2, z2); + IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); + if (!passable(iblockstate1, ignoreLava)) { + return true; + } + } + return false; + } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 0a833ab5d..bdee1a037 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -120,7 +120,7 @@ public final class NetherPathfinderContext { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); - if (!passable(state)) { + if (!passable(state, false)) { packed[x | (z << 4) | (y << 8)] = true; } } @@ -133,4 +133,4 @@ public final class NetherPathfinderContext { throw new RuntimeException(e); } } -} \ No newline at end of file +} From 5f709eef9c0099b7d28b4e11ca46219c8350afde Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 19 Jun 2023 18:26:00 -0400 Subject: [PATCH 072/276] use world raytrace --- .../baritone/behavior/ElytraBehavior.java | 197 +----------------- 1 file changed, 2 insertions(+), 195 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 1bf098132..f2e22248b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -36,10 +36,7 @@ import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumHand; import net.minecraft.util.NonNullList; -import net.minecraft.util.math.AxisAlignedBB; -import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.*; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -515,7 +512,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!ignoreLava) { clear = !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); } else { - clear = !rayTraceBlocks(start.x, start.y, start.z, dest.x, dest.y, dest.z, true); + clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } if (clear) { @@ -645,195 +642,5 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Vec3d(motionX, motionY, motionZ); } - - private boolean rayTraceBlocks(final double startX, final double startY, final double startZ, - final double endX, final double endY, final double endZ, boolean ignoreLava) { - int voxelCurrX = fastFloor(startX); - int voxelCurrY = fastFloor(startY); - int voxelCurrZ = fastFloor(startZ); - - if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ, ignoreLava)) { - return true; - } - - final int voxelEndX = fastFloor(endX); - final int voxelEndY = fastFloor(endY); - final int voxelEndZ = fastFloor(endZ); - double currPosX = startX; - double currPosY = startY; - double currPosZ = startZ; - - int steps = 200; // TODO: should we lower the max steps? - while (steps-- >= 0) { - if (voxelCurrX == voxelEndX && voxelCurrY == voxelEndY && voxelCurrZ == voxelEndZ) { - return false; - } - - final double distanceFromStartToEndX = endX - currPosX; - final double distanceFromStartToEndY = endY - currPosY; - final double distanceFromStartToEndZ = endZ - currPosZ; - - double nextIntegerX; - double nextIntegerY; - double nextIntegerZ; - // potentially more based branchless impl? - nextIntegerX = voxelCurrX + ((voxelCurrX - voxelEndX) >>> 31); // if voxelEnd > voxelIn, then voxelIn-voxelEnd will be negative, meaning the sign bit is 1 - nextIntegerY = voxelCurrY + ((voxelCurrY - voxelEndY) >>> 31); // if we do an unsigned right shift by 31, that sign bit becomes the LSB - nextIntegerZ = voxelCurrZ + ((voxelCurrZ - voxelEndZ) >>> 31); // therefore, this increments nextInteger iff EndX>inX, otherwise it leaves it alone - // remember: don't have to worry about the case when voxelEnd == voxelIn, because nextInteger value wont be used - - // these just have to be strictly greater than 1, might as well just go up to the next int - double fracIfSkipX = 2.0D; - double fracIfSkipY = 2.0D; - double fracIfSkipZ = 2.0D; - - // reminder to future self: don't "branchlessify" this, it's MUCH slower (pretty obviously, floating point div is much worse than a branch mispredict, but integer increment (like the other two removed branches) are cheap enough to be worth doing either way) - if (voxelEndX != voxelCurrX) { - fracIfSkipX = (nextIntegerX - currPosX) / distanceFromStartToEndX; - } - if (voxelEndY != voxelCurrY) { - fracIfSkipY = (nextIntegerY - currPosY) / distanceFromStartToEndY; - } - if (voxelEndZ != voxelCurrZ) { - fracIfSkipZ = (nextIntegerZ - currPosZ) / distanceFromStartToEndZ; - } - - if (fracIfSkipX < fracIfSkipY && fracIfSkipX < fracIfSkipZ) { - // note: voxelEndX == voxelInX is impossible because allowSkip would be set to false in that case, meaning that the elapsed distance would stay at default - currPosX = nextIntegerX; - currPosY += distanceFromStartToEndY * fracIfSkipX; - currPosZ += distanceFromStartToEndZ * fracIfSkipX; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int xFloorOffset = (voxelEndX - voxelCurrX) >>> 31; - voxelCurrX = (fastFloor(currPosX) - xFloorOffset); - voxelCurrY = (fastFloor(currPosY)); - voxelCurrZ = (fastFloor(currPosZ)); - } else if (fracIfSkipY < fracIfSkipZ) { - currPosX += distanceFromStartToEndX * fracIfSkipY; - currPosY = nextIntegerY; - currPosZ += distanceFromStartToEndZ * fracIfSkipY; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int yFloorOffset = (voxelEndY - voxelCurrY) >>> 31; - voxelCurrX = (fastFloor(currPosX)); - voxelCurrY = (fastFloor(currPosY) - yFloorOffset); - voxelCurrZ = (fastFloor(currPosZ)); - } else { - currPosX += distanceFromStartToEndX * fracIfSkipZ; - currPosY += distanceFromStartToEndY * fracIfSkipZ; - currPosZ = nextIntegerZ; - // tested: faster to paste this 3 times with only one of the subtractions in each - final int zFloorOffset = (voxelEndZ - voxelCurrZ) >>> 31; - voxelCurrX = (fastFloor(currPosX)); - voxelCurrY = (fastFloor(currPosY)); - voxelCurrZ = (fastFloor(currPosZ) - zFloorOffset); - } - - if (!this.passable(voxelCurrX, voxelCurrY, voxelCurrZ, ignoreLava)) { - return true; - } - } - return false; - } - - private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; - private static final int FLOOR_DOUBLE_I = 1_073_741_824; - - private static int fastFloor(final double v) { - return ((int) (v + FLOOR_DOUBLE_D)) - FLOOR_DOUBLE_I; - } - - private boolean rayTraceBlocks(Vec3d start, Vec3d end, boolean ignoreLava) { - int x1 = MathHelper.floor(end.x); - int y1 = MathHelper.floor(end.y); - int z1 = MathHelper.floor(end.z); - int x2 = MathHelper.floor(start.x); - int y2 = MathHelper.floor(start.y); - int z2 = MathHelper.floor(start.z); - BlockPos blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate, ignoreLava)) { - return true; - } - int steps = 200; - while (steps-- >= 0) { - if (Double.isNaN(start.x) || Double.isNaN(start.y) || Double.isNaN(start.z)) { - return false; - } - if (x2 == x1 && y2 == y1 && z2 == z1) { - return false; - } - boolean hitX = true; - boolean hitY = true; - boolean hitZ = true; - double nextX = 999.0D; - double nextY = 999.0D; - double nextZ = 999.0D; - if (x1 > x2) { - nextX = (double) x2 + 1.0D; - } else if (x1 < x2) { - nextX = (double) x2 + 0.0D; - } else { - hitX = false; - } - if (y1 > y2) { - nextY = (double) y2 + 1.0D; - } else if (y1 < y2) { - nextY = (double) y2 + 0.0D; - } else { - hitY = false; - } - if (z1 > z2) { - nextZ = (double) z2 + 1.0D; - } else if (z1 < z2) { - nextZ = (double) z2 + 0.0D; - } else { - hitZ = false; - } - double stepX = 999.0D; - double stepY = 999.0D; - double stepZ = 999.0D; - double dirX = end.x - start.x; - double dirY = end.y - start.y; - double dirZ = end.z - start.z; - if (hitX) { - stepX = (nextX - start.x) / dirX; - } - if (hitY) { - stepY = (nextY - start.y) / dirY; - } - if (hitZ) { - stepZ = (nextZ - start.z) / dirZ; - } - if (stepX == -0.0D) { - stepX = -1.0E-4D; - } - if (stepY == -0.0D) { - stepY = -1.0E-4D; - } - if (stepZ == -0.0D) { - stepZ = -1.0E-4D; - } - EnumFacing dir; - if (stepX < stepY && stepX < stepZ) { - dir = x1 > x2 ? EnumFacing.WEST : EnumFacing.EAST; - start = new Vec3d(nextX, start.y + dirY * stepX, start.z + dirZ * stepX); - } else if (stepY < stepZ) { - dir = y1 > y2 ? EnumFacing.DOWN : EnumFacing.UP; - start = new Vec3d(start.x + dirX * stepY, nextY, start.z + dirZ * stepY); - } else { - dir = z1 > z2 ? EnumFacing.NORTH : EnumFacing.SOUTH; - start = new Vec3d(start.x + dirX * stepZ, start.y + dirY * stepZ, nextZ); - } - x2 = MathHelper.floor(start.x) - (dir == EnumFacing.EAST ? 1 : 0); - y2 = MathHelper.floor(start.y) - (dir == EnumFacing.UP ? 1 : 0); - z2 = MathHelper.floor(start.z) - (dir == EnumFacing.SOUTH ? 1 : 0); - blockpos = new BlockPos(x2, y2, z2); - IBlockState iblockstate1 = ctx.world().getBlockState(blockpos); - if (!passable(iblockstate1, ignoreLava)) { - return true; - } - } - return false; - } } From cd1c07deef082149a210dd345f0d8f6dae564183 Mon Sep 17 00:00:00 2001 From: 0x22 <0x22@futureclient.net> Date: Mon, 19 Jun 2023 22:22:57 -0400 Subject: [PATCH 073/276] added elytraFireworkSetbackUseDelay setting. --- src/api/java/baritone/api/Settings.java | 1 + .../baritone/behavior/ElytraBehavior.java | 33 ++++++++++++++++--- 2 files changed, 30 insertions(+), 4 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 3cfef2ffc..aa2a4a957 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -51,6 +51,7 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); public final Setting elytraFireworkSpeed = new Setting<>(0.6); + public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15L); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f2e22248b..0b50bb804 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -21,6 +21,7 @@ import baritone.Baritone; import baritone.api.behavior.IElytraBehavior; import baritone.api.event.events.BlockChangeEvent; import baritone.api.event.events.ChunkEvent; +import baritone.api.event.events.PacketEvent; import baritone.api.event.events.TickEvent; import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; @@ -33,9 +34,8 @@ import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.init.Items; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; -import net.minecraft.util.EnumFacing; +import net.minecraft.network.play.server.SPacketPlayerPosLook; import net.minecraft.util.EnumHand; -import net.minecraft.util.NonNullList; import net.minecraft.util.math.*; import net.minecraft.world.chunk.Chunk; @@ -50,6 +50,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private static final long NETHER_SEED = 146008555100680L; + private static final long MS_IN_NANOS = 1_000_000L; + private static final long TICK_IN_MS = 50L; + private static final long TICK_IN_NANOS = TICK_IN_MS * MS_IN_NANOS; + // Used exclusively for PathRenderer public List> clearLines; public List> blockedLines; @@ -62,6 +66,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private int sinceFirework; private BlockStateInterface bsi; + private long lastSetBack = Long.MIN_VALUE; + public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new NetherPathfinderContext(NETHER_SEED); @@ -301,6 +307,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .forEach(this.context::queueForPacking); } + @Override + public void onReceivePacket(PacketEvent event) { + if (event.getPacket() instanceof SPacketPlayerPosLook) { + this.lastSetBack = System.nanoTime(); + } + } + @Override public void pathTo(BlockPos destination) { this.pathManager.pathToDestination(destination); @@ -312,6 +325,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.pathManager.clear(); this.aimPos = null; this.sinceFirework = 0; + this.lastSetBack = Long.MIN_VALUE; } @Override @@ -415,18 +429,29 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + this.tickUseFireworks(start, firework, goingTo, forceUseFirework); + } + + private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { + final long now = System.nanoTime(); + final long timeSinceLastSetback = now - this.lastSetBack; + if (timeSinceLastSetback < Baritone.settings().elytraFireworkSetbackUseDelay.value * TICK_IN_NANOS) { + logDebug("waiting for elytraFireworkSetbackUseDelay: " + (timeSinceLastSetback / TICK_IN_NANOS)); + return; + } final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; final double currentSpeed = new Vec3d( ctx.player().motionX, // ignore y component if we are BOTH below where we want to be AND descending ctx.player().posY < goingTo.y ? Math.max(0, ctx.player().motionY) : ctx.player().motionY, ctx.player().motionZ - ).length(); + ).lengthSquared(); + final double elytraFireworkSpeed = Baritone.settings().elytraFireworkSpeed.value; if (sinceFirework > 10 && (forceUseFirework || (!firework && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! - && currentSpeed < Baritone.settings().elytraFireworkSpeed.value)) + && currentSpeed < elytraFireworkSpeed * elytraFireworkSpeed)) ) { // Prioritize boosting fireworks over regular ones // TODO: Take the minimum boost time into account? From 753b1cf1c365161e2eff25234ff59c38d44e3c6c Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 21:36:09 -0500 Subject: [PATCH 074/276] Interpolate path positions - Update `nether-pathfinder` to 0.17 - Utilize new batched visibility raytracing to efficiently trace bounding box paths --- build.gradle | 4 +- .../baritone/behavior/ElytraBehavior.java | 80 ++++++++++--------- .../elytra/NetherPathfinderContext.java | 22 ++++- 3 files changed, 65 insertions(+), 41 deletions(-) diff --git a/build.gradle b/build.gradle index 95abfec6a..7608c07ad 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.16') + launchImplementation('dev.babbaj:nether-pathfinder:0.17') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.16' + implementation 'dev.babbaj:nether-pathfinder:0.17' } mixin { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 0b50bb804..9331e3945 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -379,47 +379,59 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { for (int dy : heights) { - Vec3d dest = this.pathManager.pathAt(i).add(0, dy, 0); - if (dy != 0) { - if (i + lookahead >= path.size()) { - continue; - } - if (start.distanceTo(dest) < 40) { - if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0), false) || !clearView(dest, this.pathManager.pathAt(i + lookahead), false)) { - // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position - continue; - } + for (float interp : interps) { + Vec3d dest; + if (interp == 1 || i == minStep) { + dest = this.pathManager.pathAt(i); } else { - // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, this.pathManager.pathAt(i), false)) { + dest = this.pathManager.pathAt(i).scale(interp) + .add(this.pathManager.pathAt(i - 1).scale(1.0d - interp)); + } + + dest = dest.add(0, dy, 0); + if (dy != 0) { + if (i + lookahead >= path.size()) { continue; } + if (start.distanceTo(dest) < 40) { + if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0), false) + || !clearView(dest, this.pathManager.pathAt(i + lookahead), false)) { + // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position + continue; + } + } else { + // but if it's far away, allow gaining altitude if we could lose it again by the time we get there + if (!clearView(dest, this.pathManager.pathAt(i), false)) { + continue; + } + } } - } - // 1.0 -> 0.25 -> none - final Double grow = relaxation == 2 ? null - : relaxation == 0 ? 1.0d : 0.25d; + // 1.0 -> 0.25 -> none + final Double grow = relaxation == 2 ? null + : relaxation == 0 ? 1.0d : 0.25d; - if (isClear(start, dest, grow, isInLava)) { - final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); + if (isClear(start, dest, grow, isInLava)) { + final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework, isInLava); - if (pitch.first() == null) { - baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); - continue; + final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework, isInLava); + if (pitch.first() == null) { + baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); + continue; + } + forceUseFirework = pitch.second(); + goingTo = new BetterBlockPos(dest.x, dest.y, dest.z); + this.aimPos = goingTo; + baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); + break outermost; } - forceUseFirework = pitch.second(); - goingTo = path.get(i); - this.aimPos = path.get(i).add(0, dy, 0); - baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); - break outermost; } } } @@ -520,22 +532,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H bb.maxX + ox, bb.maxY + oy, bb.minZ + oz, bb.maxX + ox, bb.maxY + oy, bb.maxZ + oz, }; - - // Batch together all 8 traces - final boolean[] hitOut = new boolean[8]; - this.context.raytrace(src, dst, hitOut); - for (boolean hit : hitOut) { - if (hit) { - return false; - } - } - return true; + return this.context.raytrace(8, src, dst, NetherPathfinderContext.Visibility.ALL); } private boolean clearView(Vec3d start, Vec3d dest, boolean ignoreLava) { final boolean clear; if (!ignoreLava) { - clear = !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); + // if start == dest then the cpp raytracer dies + clear = start.equals(dest) || !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); } else { clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index bdee1a037..7c30a51b1 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -21,7 +21,6 @@ import dev.babbaj.pathfinder.NetherPathfinder; import dev.babbaj.pathfinder.PathSegment; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; -import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; @@ -82,6 +81,18 @@ public final class NetherPathfinderContext { NetherPathfinder.raytrace(this.context, true, hitOut.length, src, dst, hitOut, null); } + public boolean raytrace(final int count, final double[] src, final double[] dst, int visibility) { + switch (visibility) { + case Visibility.ALL: + return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, false); + case Visibility.NONE: + return !NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true); + case Visibility.ANY: + return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true); + } + throw new IllegalArgumentException("lol"); + } + public void cancel() { NetherPathfinder.cancel(this.context); } @@ -133,4 +144,13 @@ public final class NetherPathfinderContext { throw new RuntimeException(e); } } + + public static final class Visibility { + + private Visibility() {} + + public static final int ALL = 0; + public static final int NONE = 1; + public static final int ANY = 2; + } } From ee0a6c2523d1abf09ea415064a8a4dbc4c097dd9 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 21:45:52 -0500 Subject: [PATCH 075/276] Use new single trace `isVisible` api --- .../baritone/behavior/ElytraBehavior.java | 2 +- .../elytra/NetherPathfinderContext.java | 30 +++++++++---------- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 9331e3945..94abdd64d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -539,7 +539,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final boolean clear; if (!ignoreLava) { // if start == dest then the cpp raytracer dies - clear = start.equals(dest) || !this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); + clear = start.equals(dest) || this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); } else { clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 7c30a51b1..befb5163a 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -62,26 +62,24 @@ public final class NetherPathfinderContext { ), this.executor); } + /** + * Performs a raytrace from the given start position to the given end position, returning {@code true} if there is + * visibility between the two points. + * + * @param startX The start X coordinate + * @param startY The start Y coordinate + * @param startZ The start Z coordinate + * @param endX The end X coordinate + * @param endY The end Y coordinate + * @param endZ The end Z coordinate + * @return {@code true} if there is visibility between the points + */ public boolean raytrace(final double startX, final double startY, final double startZ, final double endX, final double endY, final double endZ) { - final boolean[] hitOut = new boolean[1]; - NetherPathfinder.raytrace( - this.context, - true, - 1, - new double[] { startX, startY, startZ }, - new double[] { endX, endY, endZ }, - hitOut, - null - ); - return hitOut[0]; + return NetherPathfinder.isVisible(this.context, true, startX, startY, startZ, endX, endY, endZ); } - public void raytrace(final double[] src, final double[] dst, final boolean[] hitOut) { - NetherPathfinder.raytrace(this.context, true, hitOut.length, src, dst, hitOut, null); - } - - public boolean raytrace(final int count, final double[] src, final double[] dst, int visibility) { + public boolean raytrace(final int count, final double[] src, final double[] dst, final int visibility) { switch (visibility) { case Visibility.ALL: return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, false); From 5d7655fbdf5313eea8a7d505a9890c6712989e16 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 22:52:27 -0500 Subject: [PATCH 076/276] Fix silly 0x integer wraparound trolle --- src/main/java/baritone/behavior/ElytraBehavior.java | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 94abdd64d..6d8b2cb3b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -84,6 +84,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private boolean completePath; private boolean recalculating; private int playerNear; + private int maxPlayerNear; public PathManager() { // lol imagine initializing fields normally @@ -92,6 +93,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public void tick() { // Recalculate closest path node + final int prevMax = this.maxPlayerNear; this.playerNear = this.calculateNear(this.playerNear); // Obstacles are more important than an incomplete path, handle those first. @@ -446,9 +448,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { final long now = System.nanoTime(); - final long timeSinceLastSetback = now - this.lastSetBack; - if (timeSinceLastSetback < Baritone.settings().elytraFireworkSetbackUseDelay.value * TICK_IN_NANOS) { - logDebug("waiting for elytraFireworkSetbackUseDelay: " + (timeSinceLastSetback / TICK_IN_NANOS)); + final long waitUntil = this.lastSetBack + Baritone.settings().elytraFireworkSetbackUseDelay.value * TICK_IN_NANOS; + final long remaining = waitUntil - now; + if (remaining < 0) { + logDebug("waiting for elytraFireworkSetbackUseDelay: " + (remaining / TICK_IN_NANOS)); return; } final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; From 14ff90ccf14f3cea388db711a73d2ed95f91620d Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 19 Jun 2023 23:12:46 -0500 Subject: [PATCH 077/276] remaining ticks mojang incident --- src/api/java/baritone/api/Settings.java | 2 +- .../baritone/behavior/ElytraBehavior.java | 36 ++++++++++--------- 2 files changed, 21 insertions(+), 17 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index aa2a4a957..be959ef12 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -51,7 +51,7 @@ public final class Settings { public final Setting elytraSimulationTicks = new Setting<>(20); public final Setting elytraPitchRange = new Setting<>(25); public final Setting elytraFireworkSpeed = new Setting<>(0.6); - public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15L); + public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 6d8b2cb3b..1973e1bd4 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -63,11 +63,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private final NetherPathfinderContext context; private final PathManager pathManager; - private int sinceFirework; + private int remainingFireworkTicks; + private int remainingSetBackTicks; private BlockStateInterface bsi; - private long lastSetBack = Long.MIN_VALUE; - public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new NetherPathfinderContext(NETHER_SEED); @@ -84,7 +83,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private boolean completePath; private boolean recalculating; private int playerNear; - private int maxPlayerNear; public PathManager() { // lol imagine initializing fields normally @@ -93,7 +91,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public void tick() { // Recalculate closest path node - final int prevMax = this.maxPlayerNear; this.playerNear = this.calculateNear(this.playerNear); // Obstacles are more important than an incomplete path, handle those first. @@ -312,7 +309,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void onReceivePacket(PacketEvent event) { if (event.getPacket() instanceof SPacketPlayerPosLook) { - this.lastSetBack = System.nanoTime(); + ctx.minecraft().addScheduledTask(() -> { + this.remainingSetBackTicks = Baritone.settings().elytraFireworkSetbackUseDelay.value; + }); } } @@ -326,8 +325,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.visiblePath = Collections.emptyList(); this.pathManager.clear(); this.aimPos = null; - this.sinceFirework = 0; - this.lastSetBack = Long.MIN_VALUE; + this.remainingFireworkTicks = 0; + this.remainingSetBackTicks = 0; } @Override @@ -341,6 +340,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } + // Certified mojang employee incident + if (this.remainingFireworkTicks > 0) { + this.remainingFireworkTicks--; + } + if (this.remainingSetBackTicks > 0) { + this.remainingSetBackTicks--; + } + this.clearLines.clear(); this.blockedLines.clear(); @@ -375,7 +382,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final boolean firework = isFireworkActive(); BetterBlockPos goingTo = null; boolean forceUseFirework = false; - this.sinceFirework++; + final boolean isInLava = ctx.player().isInLava(); outermost: @@ -447,11 +454,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { - final long now = System.nanoTime(); - final long waitUntil = this.lastSetBack + Baritone.settings().elytraFireworkSetbackUseDelay.value * TICK_IN_NANOS; - final long remaining = waitUntil - now; - if (remaining < 0) { - logDebug("waiting for elytraFireworkSetbackUseDelay: " + (remaining / TICK_IN_NANOS)); + if (this.remainingSetBackTicks > 0) { + logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; } final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; @@ -463,7 +467,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ).lengthSquared(); final double elytraFireworkSpeed = Baritone.settings().elytraFireworkSpeed.value; - if (sinceFirework > 10 && (forceUseFirework || (!firework + if (this.remainingFireworkTicks <= 0 && (forceUseFirework || (!firework && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! && currentSpeed < elytraFireworkSpeed * elytraFireworkSpeed)) @@ -477,7 +481,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } logDirect("attempting to use firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); - sinceFirework = 0; + this.remainingFireworkTicks = 10; } } From 6c6b44ee65d8752acaee9db53d5a7822b00c0ccb Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 13:43:14 -0500 Subject: [PATCH 078/276] Recalculate path if stuck --- .../baritone/behavior/ElytraBehavior.java | 59 ++++++++++++++----- 1 file changed, 43 insertions(+), 16 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 1973e1bd4..f04fed343 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -50,10 +50,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private static final long NETHER_SEED = 146008555100680L; - private static final long MS_IN_NANOS = 1_000_000L; - private static final long TICK_IN_MS = 50L; - private static final long TICK_IN_NANOS = TICK_IN_MS * MS_IN_NANOS; - // Used exclusively for PathRenderer public List> clearLines; public List> blockedLines; @@ -82,6 +78,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private List path; private boolean completePath; private boolean recalculating; + + private int maxPlayerNear; + private int ticksNearUnchanged; private int playerNear; public PathManager() { @@ -91,7 +90,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public void tick() { // Recalculate closest path node + final int prevMaxNear = this.maxPlayerNear; this.playerNear = this.calculateNear(this.playerNear); + this.maxPlayerNear = Math.max(this.maxPlayerNear, this.playerNear); + + if (this.maxPlayerNear == prevMaxNear) { + this.ticksNearUnchanged++; + } else { + this.ticksNearUnchanged = 0; + } // Obstacles are more important than an incomplete path, handle those first. this.pathfindAroundObstacles(); @@ -118,23 +125,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }); } - public void pathRecalcSegment(final int blockedAt, final int upToIncl) { + public CompletableFuture pathRecalcSegment(final int upToIncl) { if (this.recalculating) { - return; + throw new IllegalStateException("already recalculating"); } this.recalculating = true; final List after = this.path.subList(upToIncl, this.path.size()); final boolean complete = this.completePath; - final BetterBlockPos blockage = this.path.get(blockedAt); - final long start = System.nanoTime(); - this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) - .thenRun(() -> { - final int recompute = this.path.size() - after.size() - 1; - final double distance = this.pathAt(0).distanceTo(this.pathAt(recompute)); // in spirit same as ctx.playerFeet().distanceTo(this.path.get(upToIncl)), but, thread safe (those could have changed in the meantime) - logDirect(String.format("Recalculated segment around path blockage near %s %s %s (next %.1f blocks in %.4f seconds)", SettingsUtil.maybeCensor(blockage.x), SettingsUtil.maybeCensor(blockage.y), SettingsUtil.maybeCensor(blockage.z), distance, (System.nanoTime() - start) / 1e9d)); - }) + return this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) .whenComplete((result, ex) -> { this.recalculating = false; if (ex != null) { @@ -185,13 +185,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.completePath = true; this.recalculating = false; this.playerNear = 0; + this.ticksNearUnchanged = 0; + this.maxPlayerNear = 0; } private void setPath(final UnpackedSegment segment) { this.path = segment.collect(); this.removeBacktracks(); - this.playerNear = 0; this.completePath = segment.isFinished(); + this.playerNear = 0; + this.ticksNearUnchanged = 0; + this.maxPlayerNear = 0; } public List getPath() { @@ -228,11 +232,34 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // we're in a wall return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } + + if (this.ticksNearUnchanged > 100) { + this.pathRecalcSegment(rangeEndExcl - 1) + .thenRun(() -> { + logDirect("Recalculating segment, no progress in last 100 ticks"); + }); + this.ticksNearUnchanged = 0; + return; + } + for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { if (!clearView(pathAt(i), pathAt(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment - this.pathRecalcSegment(i, rangeEndExcl - 1); + final BetterBlockPos blockage = this.path.get(i); + final double distance = Math.sqrt(ctx.playerFeet().distanceSq(this.path.get(rangeEndExcl - 1))); + + final long start = System.nanoTime(); + this.pathRecalcSegment(rangeEndExcl - 1) + .thenRun(() -> { + logDirect(String.format("Recalculated segment around path blockage near %s %s %s (next %.1f blocks in %.4f seconds)", + SettingsUtil.maybeCensor(blockage.x), + SettingsUtil.maybeCensor(blockage.y), + SettingsUtil.maybeCensor(blockage.z), + distance, + (System.nanoTime() - start) / 1e9d + )); + }); return; } } From 0ecabdd04714e68ac27e080e9c7831b3547e767c Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 13:43:42 -0500 Subject: [PATCH 079/276] Update `nether-pathfinder` to 0.18 --- build.gradle | 4 ++-- .../baritone/behavior/elytra/NetherPathfinderContext.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 7608c07ad..41a495f4f 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.17') + launchImplementation('dev.babbaj:nether-pathfinder:0.18') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.17' + implementation 'dev.babbaj:nether-pathfinder:0.18' } mixin { diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index befb5163a..f269cd33b 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -82,11 +82,11 @@ public final class NetherPathfinderContext { public boolean raytrace(final int count, final double[] src, final double[] dst, final int visibility) { switch (visibility) { case Visibility.ALL: - return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, false); + return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, false) == -1; case Visibility.NONE: - return !NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true); + return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) == -1; case Visibility.ANY: - return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true); + return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) != -1; } throw new IllegalArgumentException("lol"); } From 7d22a71507215c2e9ae3099c7dc1fe3c8145e692 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 13:50:26 -0500 Subject: [PATCH 080/276] Only count unchanged ticks when using elytra --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f04fed343..f54b66d6c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -94,7 +94,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.playerNear = this.calculateNear(this.playerNear); this.maxPlayerNear = Math.max(this.maxPlayerNear, this.playerNear); - if (this.maxPlayerNear == prevMaxNear) { + if (this.maxPlayerNear == prevMaxNear && ctx.player().isElytraFlying()) { this.ticksNearUnchanged++; } else { this.ticksNearUnchanged = 0; From c057081f07a0079289e16b53764f2567b1fd14bf Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 20 Jun 2023 15:48:12 -0400 Subject: [PATCH 081/276] fix 0.5 offset in elytra path rendering --- .../java/baritone/utils/PathRenderer.java | 27 +++++++++++-------- 1 file changed, 16 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 5898ce643..0b08a1f32 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -104,7 +104,7 @@ public final class PathRenderer implements IRenderer { final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); - drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0); + 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); } @@ -138,6 +138,10 @@ public final class PathRenderer implements IRenderer { } private static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { + drawPath(positions, startIndex, color, fadeOut, fadeStart0, fadeEnd0, 0.5D); + } + + private static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0, double offset) { IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); int fadeStart = fadeStart0 + startIndex; @@ -173,7 +177,7 @@ public final class PathRenderer implements IRenderer { IRenderer.glColor(color, alpha); } - emitPathLine(start.x, start.y, start.z, end.x, end.y, end.z); + emitPathLine(start.x, start.y, start.z, end.x, end.y, end.z, offset); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); @@ -187,24 +191,25 @@ public final class PathRenderer implements IRenderer { buffer.pos(x2 - vpX, y2 - vpY, z2 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); } - private static void emitPathLine(double x1, double y1, double z1, double x2, double y2, double z2) { + private static void emitPathLine(double x1, double y1, double z1, double x2, double y2, double z2, double offset) { + final double extraOffset = offset + 0.03D; double vpX = renderManager.viewerPosX; double vpY = renderManager.viewerPosY; double vpZ = renderManager.viewerPosZ; boolean renderPathAsFrickinThingy = !settings.renderPathAsLine.value; - buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x1 + offset - vpX, y1 + offset - vpY, z1 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 + offset - vpX, y2 + offset - vpY, z2 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); if (renderPathAsFrickinThingy) { - buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 + offset - vpX, y2 + offset - vpY, z2 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 + offset - vpX, y2 + extraOffset - vpY, z2 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 + offset - vpX, y2 + extraOffset - vpY, z2 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x1 + offset - vpX, y1 + extraOffset - vpY, z1 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x1 + offset - vpX, y1 + extraOffset - vpY, z1 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x1 + offset - vpX, y1 + offset - vpY, z1 + offset - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); } } From 0aad3470d9785002aa876648f37b99842c404871 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 15:05:59 -0500 Subject: [PATCH 082/276] Differ between no pitch solution and no solution at all --- .../baritone/behavior/ElytraBehavior.java | 41 ++++++++++++++----- 1 file changed, 31 insertions(+), 10 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f54b66d6c..e3d0164b8 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -408,9 +408,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Vec3d start = ctx.playerFeetAsVec(); final boolean firework = isFireworkActive(); BetterBlockPos goingTo = null; - boolean forceUseFirework = false; - final boolean isInLava = ctx.player().isInLava(); + Solution solution = null; outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) @@ -459,25 +458,34 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework, isInLava); if (pitch.first() == null) { - baritone.getLookBehavior().updateTarget(new Rotation(yaw, ctx.playerRotations().getPitch()), false); + solution = new Solution(new Rotation(yaw, ctx.playerRotations().getPitch()), false, false); continue; } - forceUseFirework = pitch.second(); goingTo = new BetterBlockPos(dest.x, dest.y, dest.z); this.aimPos = goingTo; - baritone.getLookBehavior().updateTarget(new Rotation(yaw, pitch.first()), false); + + // A solution was found with yaw AND pitch, break out of the loop to use it + solution = new Solution(new Rotation(yaw, pitch.first()), true, pitch.second()); break outermost; } } } } - if (relaxation == 2) { - logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); - return; - } } - this.tickUseFireworks(start, firework, goingTo, forceUseFirework); + if (solution == null) { + logDirect("no solution"); + return; + } + + baritone.getLookBehavior().updateTarget(solution.rotation, false); + + if (!solution.solvedPitch) { + logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); + return; + } + + this.tickUseFireworks(start, firework, goingTo, solution.forceUseFirework); } private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { @@ -512,6 +520,19 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + private static final class Solution { + + public final Rotation rotation; + public final boolean solvedPitch; + public final boolean forceUseFirework; + + public Solution(Rotation rotation, boolean solvedPitch, boolean forceUseFirework) { + this.rotation = rotation; + this.solvedPitch = solvedPitch; + this.forceUseFirework = forceUseFirework; + } + } + private static boolean isFireworks(final ItemStack itemStack) { if (itemStack.getItem() != Items.FIREWORKS) { return false; From e3c82831583611cce3ba8df9fbe06e4533c73f69 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 15:15:02 -0500 Subject: [PATCH 083/276] Move solver into separate method --- .../baritone/behavior/ElytraBehavior.java | 57 ++++++++++--------- 1 file changed, 31 insertions(+), 26 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index e3d0164b8..1be445b2c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -406,16 +406,32 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } final Vec3d start = ctx.playerFeetAsVec(); - final boolean firework = isFireworkActive(); - BetterBlockPos goingTo = null; + final boolean currentlyBoosted = this.isFireworkActive(); + + final Solution solution = this.solveAngles(path, playerNear, start, currentlyBoosted); + if (solution == null) { + logDirect("no solution"); + return; + } + + baritone.getLookBehavior().updateTarget(solution.rotation, false); + + if (!solution.solvedPitch) { + logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); + return; + } + + this.tickUseFireworks(start, currentlyBoosted, solution.goingTo, solution.forceUseFirework); + } + + private Solution solveAngles(final List path, final int playerNear, final Vec3d start, final boolean currentlyBoosted) { final boolean isInLava = ctx.player().isInLava(); Solution solution = null; - outermost: for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) - int[] heights = firework ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + int[] heights = currentlyBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; - int steps = relaxation < 2 ? firework ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + int steps = relaxation < 2 ? currentlyBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; @@ -456,36 +472,23 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (isClear(start, dest, grow, isInLava)) { final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, firework, isInLava); + final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, currentlyBoosted, isInLava); if (pitch.first() == null) { - solution = new Solution(new Rotation(yaw, ctx.playerRotations().getPitch()), false, false); + solution = new Solution(new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; } - goingTo = new BetterBlockPos(dest.x, dest.y, dest.z); + + final BetterBlockPos goingTo = new BetterBlockPos(dest.x, dest.y, dest.z); this.aimPos = goingTo; - // A solution was found with yaw AND pitch, break out of the loop to use it - solution = new Solution(new Rotation(yaw, pitch.first()), true, pitch.second()); - break outermost; + // A solution was found with yaw AND pitch, so just immediately return it. + return new Solution(new Rotation(yaw, pitch.first()), goingTo, true, pitch.second()); } } } } } - - if (solution == null) { - logDirect("no solution"); - return; - } - - baritone.getLookBehavior().updateTarget(solution.rotation, false); - - if (!solution.solvedPitch) { - logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); - return; - } - - this.tickUseFireworks(start, firework, goingTo, solution.forceUseFirework); + return solution; } private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { @@ -523,11 +526,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private static final class Solution { public final Rotation rotation; + public final BetterBlockPos goingTo; public final boolean solvedPitch; public final boolean forceUseFirework; - public Solution(Rotation rotation, boolean solvedPitch, boolean forceUseFirework) { + public Solution(Rotation rotation, BetterBlockPos goingTo, boolean solvedPitch, boolean forceUseFirework) { this.rotation = rotation; + this.goingTo = goingTo; this.solvedPitch = solvedPitch; this.forceUseFirework = forceUseFirework; } From 4076263afa5cbbbb3e5aa6d43e8eae4cf9f21c4f Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 17:00:42 -0500 Subject: [PATCH 084/276] Un-scuff PRE TickEvent injector --- .../java/baritone/launch/mixins/MixinMinecraft.java | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index 19d4741ca..ddd17e8d5 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -38,6 +38,7 @@ import org.spongepowered.asm.mixin.Shadow; 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.Slice; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.LocalCapture; @@ -69,9 +70,15 @@ public class MixinMinecraft { value = "FIELD", opcode = Opcodes.GETFIELD, target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;", - ordinal = 5, - shift = At.Shift.BY, - by = -3 + ordinal = 0, + shift = At.Shift.BEFORE + ), + slice = @Slice( + from = @At( + value = "FIELD", + opcode = Opcodes.PUTFIELD, + target = "net/minecraft/client/Minecraft.leftClickCounter:I" + ) ) ) private void runTick(CallbackInfo ci) { From 2a82f6048a25c966098c127770fcb52c9ee21279 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 17:18:30 -0500 Subject: [PATCH 085/276] Implement POST TickEvent with new `onPostTick` callback --- .../baritone/api/event/events/TickEvent.java | 9 ++++++ .../listener/AbstractGameEventListener.java | 3 ++ .../event/listener/IGameEventListener.java | 8 +++++ .../launch/mixins/MixinMinecraft.java | 30 ++++++++++++++++--- .../java/baritone/event/GameEventHandler.java | 5 ++++ 5 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/api/java/baritone/api/event/events/TickEvent.java b/src/api/java/baritone/api/event/events/TickEvent.java index 5c484ae49..405ad3c49 100644 --- a/src/api/java/baritone/api/event/events/TickEvent.java +++ b/src/api/java/baritone/api/event/events/TickEvent.java @@ -18,9 +18,18 @@ package baritone.api.event.events; import baritone.api.event.events.type.EventState; +import net.minecraft.client.Minecraft; import java.util.function.BiFunction; +/** + * Called on and after each game tick of the primary {@link Minecraft} instance and dispatched to all Baritone + * instances. + *

+ * When {@link #state} is {@link EventState#PRE}, the event is being called just prior to when the current in-game + * screen is ticked. When {@link #state} is {@link EventState#POST}, the event is being called at the very end + * of the {@link Minecraft#runTick()} method. + */ public final class TickEvent { private static int overallTickCount; diff --git a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java index 64ae0c16e..54aabe387 100644 --- a/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/AbstractGameEventListener.java @@ -33,6 +33,9 @@ public interface AbstractGameEventListener extends IGameEventListener { @Override default void onTick(TickEvent event) {} + @Override + default void onPostTick(TickEvent event) {} + @Override default void onPlayerUpdate(PlayerUpdateEvent event) {} diff --git a/src/api/java/baritone/api/event/listener/IGameEventListener.java b/src/api/java/baritone/api/event/listener/IGameEventListener.java index 71e9521ad..22466ce52 100644 --- a/src/api/java/baritone/api/event/listener/IGameEventListener.java +++ b/src/api/java/baritone/api/event/listener/IGameEventListener.java @@ -41,6 +41,14 @@ public interface IGameEventListener { */ void onTick(TickEvent event); + /** + * Run once per game tick after the tick is completed + * + * @param event The event + * @see Minecraft#runTick() + */ + void onPostTick(TickEvent event); + /** * Run once per game tick from before and after the player rotation is sent to the server. * diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index ddd17e8d5..13bc2cdf2 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -35,6 +35,7 @@ import net.minecraft.util.math.BlockPos; import org.spongepowered.asm.lib.Opcodes; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; @@ -53,9 +54,13 @@ public class MixinMinecraft { @Shadow public EntityPlayerSP player; + @Shadow public WorldClient world; + @Unique + private BiFunction tickProvider; + @Inject( method = "init", at = @At("RETURN") @@ -82,18 +87,35 @@ public class MixinMinecraft { ) ) private void runTick(CallbackInfo ci) { - final BiFunction tickProvider = TickEvent.createNextProvider(); + this.tickProvider = TickEvent.createNextProvider(); for (IBaritone baritone : BaritoneAPI.getProvider().getAllBaritones()) { - TickEvent.Type type = baritone.getPlayerContext().player() != null && baritone.getPlayerContext().world() != null ? TickEvent.Type.IN : TickEvent.Type.OUT; - - baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type)); + baritone.getGameEventHandler().onTick(this.tickProvider.apply(EventState.PRE, type)); } } + @Inject( + method = "runTick", + at = @At("RETURN") + ) + private void postRunTick() { + if (this.tickProvider == null) { + return; + } + + for (IBaritone baritone : BaritoneAPI.getProvider().getAllBaritones()) { + TickEvent.Type type = baritone.getPlayerContext().player() != null && baritone.getPlayerContext().world() != null + ? TickEvent.Type.IN + : TickEvent.Type.OUT; + baritone.getGameEventHandler().onPostTick(this.tickProvider.apply(EventState.POST, type)); + } + + this.tickProvider = null; + } + @Inject( method = "runTick", at = @At( diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index ceb05e739..d26f2de24 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -62,6 +62,11 @@ public final class GameEventHandler implements IEventBus, Helper { listeners.forEach(l -> l.onTick(event)); } + @Override + public void onPostTick(TickEvent event) { + listeners.forEach(l -> l.onPostTick(event)); + } + @Override public final void onPlayerUpdate(PlayerUpdateEvent event) { listeners.forEach(l -> l.onPlayerUpdate(event)); From 57a17e907ea79b944ec253628434ac08e9408cac Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 17:30:38 -0500 Subject: [PATCH 086/276] Add missing `CallbackInfo` --- src/launch/java/baritone/launch/mixins/MixinMinecraft.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java index 13bc2cdf2..543ed3280 100644 --- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java +++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java @@ -101,7 +101,7 @@ public class MixinMinecraft { method = "runTick", at = @At("RETURN") ) - private void postRunTick() { + private void postRunTick(CallbackInfo ci) { if (this.tickProvider == null) { return; } From 1d092a71652f5cd7be3c1a169a3ba2b2ddee847a Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 20:09:53 -0500 Subject: [PATCH 087/276] Compute angles on another thread between ticks --- .../baritone/api/utils/BetterBlockPos.java | 14 ++ .../baritone/behavior/ElytraBehavior.java | 167 +++++++++++++----- .../elytra/NetherPathfinderContext.java | 5 +- 3 files changed, 140 insertions(+), 46 deletions(-) diff --git a/src/api/java/baritone/api/utils/BetterBlockPos.java b/src/api/java/baritone/api/utils/BetterBlockPos.java index a9b02445b..01e53402e 100644 --- a/src/api/java/baritone/api/utils/BetterBlockPos.java +++ b/src/api/java/baritone/api/utils/BetterBlockPos.java @@ -202,6 +202,20 @@ public final class BetterBlockPos extends BlockPos { return amt == 0 ? this : new BetterBlockPos(x - amt, y, z); } + public double distanceSq(final BetterBlockPos to) { + double dx = (double) this.x - to.x; + double dy = (double) this.y - to.y; + double dz = (double) this.z - to.z; + return dx * dx + dy * dy + dz * dz; + } + + public double distanceTo(final BetterBlockPos to) { + double dx = (double) this.x - to.x; + double dy = (double) this.y - to.y; + double dz = (double) this.z - to.z; + return Math.sqrt(dx * dx + dy * dy + dz * dz); + } + @Override @Nonnull public String toString() { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 1be445b2c..59ff847d7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -19,10 +19,7 @@ package baritone.behavior; import baritone.Baritone; import baritone.api.behavior.IElytraBehavior; -import baritone.api.event.events.BlockChangeEvent; -import baritone.api.event.events.ChunkEvent; -import baritone.api.event.events.PacketEvent; -import baritone.api.event.events.TickEvent; +import baritone.api.event.events.*; import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.UnpackedSegment; @@ -41,6 +38,8 @@ import net.minecraft.world.chunk.Chunk; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.Future; +import java.util.function.IntFunction; import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -63,13 +62,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private int remainingSetBackTicks; private BlockStateInterface bsi; + private Future solver; + private boolean solveNextTick; + public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new NetherPathfinderContext(NETHER_SEED); this.clearLines = new ArrayList<>(); this.blockedLines = new ArrayList<>(); this.visiblePath = Collections.emptyList(); - this.pathManager = new PathManager(); + this.pathManager = this.new PathManager(); } private final class PathManager { @@ -90,11 +92,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public void tick() { // Recalculate closest path node + this.updatePlayerNear(); final int prevMaxNear = this.maxPlayerNear; - this.playerNear = this.calculateNear(this.playerNear); this.maxPlayerNear = Math.max(this.maxPlayerNear, this.playerNear); - if (this.maxPlayerNear == prevMaxNear && ctx.player().isElytraFlying()) { + if (this.maxPlayerNear == prevMaxNear) { this.ticksNearUnchanged++; } else { this.ticksNearUnchanged = 0; @@ -247,7 +249,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // obstacle. where do we return to pathing? // find the next valid segment final BetterBlockPos blockage = this.path.get(i); - final double distance = Math.sqrt(ctx.playerFeet().distanceSq(this.path.get(rangeEndExcl - 1))); + final double distance = ctx.playerFeet().distanceTo(this.path.get(rangeEndExcl - 1)); final long start = System.nanoTime(); this.pathRecalcSegment(rangeEndExcl - 1) @@ -276,7 +278,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private int calculateNear(int index) { + public void updatePlayerNear() { + int index = this.playerNear; final BetterBlockPos pos = ctx.playerFeet(); for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { if (path.get(i).distanceSq(pos) < path.get(index).distanceSq(pos)) { @@ -298,7 +301,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H index = i; // intentional: this changes the bound of the loop } } - return index; + this.playerNear = index; } private void removeBacktracks() { @@ -367,6 +370,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } + // Fetch the previous solution, regardless of if it's going to be used + Solution solution = null; + if (this.solver != null) { + try { + solution = this.solver.get(); + } catch (Exception ignored) { + // it doesn't matter if get() fails since the solution can just be recalculated synchronously + } finally { + this.solver = null; + } + } + // Certified mojang employee incident if (this.remainingFireworkTicks > 0) { this.remainingFireworkTicks--; @@ -379,7 +394,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.blockedLines.clear(); final List path = this.pathManager.getPath(); - if (path.isEmpty()) { + if (path.isEmpty() || !ctx.player().isElytraFlying()) { return; } @@ -392,10 +407,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Math.min(playerNear + 100, path.size()) ); - if (!ctx.player().isElytraFlying()) { - return; - } - baritone.getInputOverrideHandler().clearAllKeys(); if (ctx.player().collidedHorizontally) { @@ -405,10 +416,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H logDirect("vbonk"); } - final Vec3d start = ctx.playerFeetAsVec(); - final boolean currentlyBoosted = this.isFireworkActive(); + final SolverContext solverContext = this.new SolverContext(); + this.solveNextTick = true; + + // If there's no previously calculated solution to use, or the context used at the end of last tick doesn't match this tick + if (solution == null || !solution.context.equals(solverContext)) { + solution = this.solveAngles(solverContext); + } - final Solution solution = this.solveAngles(path, playerNear, start, currentlyBoosted); if (solution == null) { logDirect("no solution"); return; @@ -419,12 +434,43 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!solution.solvedPitch) { logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); return; + } else { + this.aimPos = solution.goingTo; } - this.tickUseFireworks(start, currentlyBoosted, solution.goingTo, solution.forceUseFirework); + this.tickUseFireworks( + solution.context.start, + solution.context.currentlyBoosted, + solution.goingTo, + solution.forceUseFirework + ); } - private Solution solveAngles(final List path, final int playerNear, final Vec3d start, final boolean currentlyBoosted) { + @Override + public void onPostTick(TickEvent event) { + if (event.getType() == TickEvent.Type.IN && this.solveNextTick) { + // We're at the end of the tick, the player's position likely updated and the closest path node could've + // changed. Updating it now will avoid unnecessary recalculation on the main thread. + this.pathManager.updatePlayerNear(); + + final SolverContext context = this.new SolverContext(); + this.solver = CompletableFuture.supplyAsync(() -> this.solveAngles(context)); + this.solveNextTick = false; + } + } + + private Solution solveAngles(final SolverContext context) { + final List path = context.path; + final int playerNear = context.playerNear; + final Vec3d start = context.start; + final boolean currentlyBoosted = context.currentlyBoosted; + + final IntFunction pathAt = (i) -> new Vec3d( + path.get(i).x, + path.get(i).y, + path.get(i).z + ); + final boolean isInLava = ctx.player().isInLava(); Solution solution = null; @@ -440,10 +486,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (float interp : interps) { Vec3d dest; if (interp == 1 || i == minStep) { - dest = this.pathManager.pathAt(i); + dest = pathAt.apply(i); } else { - dest = this.pathManager.pathAt(i).scale(interp) - .add(this.pathManager.pathAt(i - 1).scale(1.0d - interp)); + dest = pathAt.apply(i).scale(interp).add(pathAt.apply(i - 1).scale(1.0d - interp)); } dest = dest.add(0, dy, 0); @@ -452,14 +497,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H continue; } if (start.distanceTo(dest) < 40) { - if (!clearView(dest, this.pathManager.pathAt(i + lookahead).add(0, dy, 0), false) - || !clearView(dest, this.pathManager.pathAt(i + lookahead), false)) { + if (!clearView(dest, pathAt.apply(i + lookahead).add(0, dy, 0), false) + || !clearView(dest, pathAt.apply(i + lookahead), false)) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, this.pathManager.pathAt(i), false)) { + if (!clearView(dest, pathAt.apply(i), false)) { continue; } } @@ -474,15 +519,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, currentlyBoosted, isInLava); if (pitch.first() == null) { - solution = new Solution(new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); + solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; } - final BetterBlockPos goingTo = new BetterBlockPos(dest.x, dest.y, dest.z); - this.aimPos = goingTo; - // A solution was found with yaw AND pitch, so just immediately return it. - return new Solution(new Rotation(yaw, pitch.first()), goingTo, true, pitch.second()); + return new Solution( + context, + new Rotation(yaw, pitch.first()), + new BetterBlockPos(dest.x, dest.y, dest.z), + true, + pitch.second() + ); } } } @@ -523,14 +571,47 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + private final class SolverContext { + + public final List path; + public final int playerNear; + public final Vec3d start; + public final boolean currentlyBoosted; + + public SolverContext() { + this.path = ElytraBehavior.this.pathManager.getPath(); + this.playerNear = ElytraBehavior.this.pathManager.getNear(); + this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); + this.currentlyBoosted = ElytraBehavior.this.isFireworkActive(); + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || o.getClass() != SolverContext.class) { + return false; + } + + SolverContext other = (SolverContext) o; + return this.path == other.path // Contents aren't modified, just compare by reference + && this.playerNear == other.playerNear + && Objects.equals(this.start, other.start) + && this.currentlyBoosted == other.currentlyBoosted; + } + } + private static final class Solution { + public final SolverContext context; public final Rotation rotation; public final BetterBlockPos goingTo; public final boolean solvedPitch; public final boolean forceUseFirework; - public Solution(Rotation rotation, BetterBlockPos goingTo, boolean solvedPitch, boolean forceUseFirework) { + public Solution(SolverContext context, Rotation rotation, BetterBlockPos goingTo, boolean solvedPitch, boolean forceUseFirework) { + this.context = context; this.rotation = rotation; this.goingTo = goingTo; this.solvedPitch = solvedPitch; @@ -605,10 +686,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } if (clear) { - clearLines.add(new Pair<>(start, dest)); + this.clearLines.add(new Pair<>(start, dest)); return true; } else { - blockedLines.add(new Pair<>(start, dest)); + this.blockedLines.add(new Pair<>(start, dest)); return false; } } @@ -672,15 +753,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - public boolean passable(int x, int y, int z, boolean ignoreLava) { - return passable(this.bsi.get0(x, y, z), ignoreLava); - } - - public static boolean passable(IBlockState state, boolean ignoreLava) { - Material mat = state.getMaterial(); - return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); - } - private static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { double motionX = motion.x; double motionY = motion.y; @@ -731,5 +803,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Vec3d(motionX, motionY, motionZ); } + + private boolean passable(int x, int y, int z, boolean ignoreLava) { + return passable(this.bsi.get0(x, y, z), ignoreLava); + } + + private static boolean passable(IBlockState state, boolean ignoreLava) { + Material mat = state.getMaterial(); + return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); + } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index f269cd33b..8dcd87274 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -19,6 +19,7 @@ package baritone.behavior.elytra; import dev.babbaj.pathfinder.NetherPathfinder; import dev.babbaj.pathfinder.PathSegment; +import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.world.chunk.BlockStateContainer; @@ -30,8 +31,6 @@ import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import static baritone.behavior.ElytraBehavior.passable; - /** * @author Brady */ @@ -129,7 +128,7 @@ public final class NetherPathfinderContext { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); - if (!passable(state, false)) { + if (state.getMaterial() != Material.AIR) { packed[x | (z << 4) | (y << 8)] = true; } } From 7a12ef530c3a56dce284b996e054d88df75f9af5 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 20:11:34 -0500 Subject: [PATCH 088/276] Cancel solver on behavior cancel --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 59ff847d7..77c426c69 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -357,6 +357,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.aimPos = null; this.remainingFireworkTicks = 0; this.remainingSetBackTicks = 0; + this.solver.cancel(true); + this.solver = null; } @Override From fa158c6e67d7ccfe43a93e3721e969e75c3598a6 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 20:18:56 -0500 Subject: [PATCH 089/276] Remove unnecessary conversions to Vec3d --- src/main/java/baritone/behavior/ElytraBehavior.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 77c426c69..7bcedea59 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -112,7 +112,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final long start = System.nanoTime(); this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) .thenRun(() -> { - final double distance = this.pathAt(0).distanceTo(this.pathAt(this.path.size() - 1)); + final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1)); if (this.completePath) { logDirect(String.format("Computed path (%.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); } else { @@ -157,7 +157,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; - final double distance = this.pathAt(0).distanceTo(this.pathAt(recompute)); + final double distance = this.path.get(0).distanceTo(this.path.get(recompute)); if (this.completePath) { logDirect(String.format("Computed path (%.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d)); From 141a48a15e56446f91b7ff2c9410c2b5b005cc52 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 20:30:10 -0500 Subject: [PATCH 090/276] Some refactoring, more precise `goingTo` --- .../baritone/behavior/ElytraBehavior.java | 57 +++++++++---------- .../elytra/NetherPathfinderContext.java | 13 +++++ 2 files changed, 39 insertions(+), 31 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 7bcedea59..328ee6818 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -437,13 +437,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H logDirect("no pitch solution, probably gonna crash in a few ticks LOL!!!"); return; } else { - this.aimPos = solution.goingTo; + this.aimPos = new BetterBlockPos(solution.goingTo.x, solution.goingTo.y, solution.goingTo.z); } this.tickUseFireworks( solution.context.start, - solution.context.currentlyBoosted, solution.goingTo, + solution.context.isBoosted, solution.forceUseFirework ); } @@ -465,7 +465,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final List path = context.path; final int playerNear = context.playerNear; final Vec3d start = context.start; - final boolean currentlyBoosted = context.currentlyBoosted; + final boolean isBoosted = context.isBoosted; final IntFunction pathAt = (i) -> new Vec3d( path.get(i).x, @@ -477,9 +477,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Solution solution = null; for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) - int[] heights = currentlyBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + int[] heights = isBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; - int steps = relaxation < 2 ? currentlyBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + int steps = relaxation < 2 ? isBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; @@ -499,14 +499,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H continue; } if (start.distanceTo(dest) < 40) { - if (!clearView(dest, pathAt.apply(i + lookahead).add(0, dy, 0), false) - || !clearView(dest, pathAt.apply(i + lookahead), false)) { + if (!this.clearView(dest, pathAt.apply(i + lookahead).add(0, dy, 0), false) + || !this.clearView(dest, pathAt.apply(i + lookahead), false)) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!clearView(dest, pathAt.apply(i), false)) { + if (!this.clearView(dest, pathAt.apply(i), false)) { continue; } } @@ -516,23 +516,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Double grow = relaxation == 2 ? null : relaxation == 0 ? 1.0d : 0.25d; - if (isClear(start, dest, grow, isInLava)) { + if (this.isClear(start, dest, grow, isInLava)) { + // Yaw is trivial, just calculate the rotation required to face the destination final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, currentlyBoosted, isInLava); + final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, isBoosted, isInLava); if (pitch.first() == null) { solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; } // A solution was found with yaw AND pitch, so just immediately return it. - return new Solution( - context, - new Rotation(yaw, pitch.first()), - new BetterBlockPos(dest.x, dest.y, dest.z), - true, - pitch.second() - ); + return new Solution(context, new Rotation(yaw, pitch.first()), dest, true, pitch.second()); } } } @@ -541,7 +536,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return solution; } - private void tickUseFireworks(final Vec3d start, final boolean firework, final BetterBlockPos goingTo, final boolean forceUseFirework) { + private void tickUseFireworks(final Vec3d start, final Vec3d goingTo, final boolean isBoosted, final boolean forceUseFirework) { if (this.remainingSetBackTicks > 0) { logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; @@ -555,7 +550,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ).lengthSquared(); final double elytraFireworkSpeed = Baritone.settings().elytraFireworkSpeed.value; - if (this.remainingFireworkTicks <= 0 && (forceUseFirework || (!firework + if (this.remainingFireworkTicks <= 0 && (forceUseFirework || (!isBoosted && useOnDescend && (ctx.player().posY < goingTo.y - 5 || start.distanceTo(new Vec3d(goingTo.x + 0.5, ctx.player().posY, goingTo.z + 0.5)) > 5) // UGH!!!!!!! && currentSpeed < elytraFireworkSpeed * elytraFireworkSpeed)) @@ -578,13 +573,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final List path; public final int playerNear; public final Vec3d start; - public final boolean currentlyBoosted; + public final boolean isBoosted; public SolverContext() { - this.path = ElytraBehavior.this.pathManager.getPath(); - this.playerNear = ElytraBehavior.this.pathManager.getNear(); - this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.currentlyBoosted = ElytraBehavior.this.isFireworkActive(); + this.path = ElytraBehavior.this.pathManager.getPath(); + this.playerNear = ElytraBehavior.this.pathManager.getNear(); + this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); + this.isBoosted = ElytraBehavior.this.isFireworkActive(); } @Override @@ -600,7 +595,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.path == other.path // Contents aren't modified, just compare by reference && this.playerNear == other.playerNear && Objects.equals(this.start, other.start) - && this.currentlyBoosted == other.currentlyBoosted; + && this.isBoosted == other.isBoosted; } } @@ -608,11 +603,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final SolverContext context; public final Rotation rotation; - public final BetterBlockPos goingTo; + public final Vec3d goingTo; public final boolean solvedPitch; public final boolean forceUseFirework; - public Solution(SolverContext context, Rotation rotation, BetterBlockPos goingTo, boolean solvedPitch, boolean forceUseFirework) { + public Solution(SolverContext context, Rotation rotation, Vec3d goingTo, boolean solvedPitch, boolean forceUseFirework) { this.context = context; this.rotation = rotation; this.goingTo = goingTo; @@ -642,7 +637,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { - if (!clearView(start, dest, ignoreLava)) { + if (!this.clearView(start, dest, ignoreLava)) { return false; } if (growAmount == null) { @@ -682,7 +677,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final boolean clear; if (!ignoreLava) { // if start == dest then the cpp raytracer dies - clear = start.equals(dest) || this.context.raytrace(start.x, start.y, start.z, dest.x, dest.y, dest.z); + clear = start.equals(dest) || this.context.raytrace(start, dest); } else { clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } @@ -696,8 +691,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean currentlyBoosted, boolean ignoreLava) { - final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, currentlyBoosted, ignoreLava); + private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean isBoosted, boolean ignoreLava) { + final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, isBoosted, ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 8dcd87274..da3753bf3 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -22,6 +22,7 @@ import dev.babbaj.pathfinder.PathSegment; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; @@ -78,6 +79,18 @@ public final class NetherPathfinderContext { return NetherPathfinder.isVisible(this.context, true, startX, startY, startZ, endX, endY, endZ); } + /** + * Performs a raytrace from the given start position to the given end position, returning {@code true} if there is + * visibility between the two points. + * + * @param start The starting point + * @param end The ending point + * @return {@code true} if there is visibility between the points + */ + public boolean raytrace(final Vec3d start, final Vec3d end) { + return NetherPathfinder.isVisible(this.context, true, start.x, start.y, start.z, end.x, end.y, end.z); + } + public boolean raytrace(final int count, final double[] src, final double[] dst, final int visibility) { switch (visibility) { case Visibility.ALL: From e76f79214e4fb19b1cbbc3331ae92d31b6cd3b14 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 21:07:21 -0500 Subject: [PATCH 091/276] Replace `pathAt` with `NetherPath` --- .../baritone/behavior/ElytraBehavior.java | 50 ++++++---------- .../baritone/behavior/elytra/NetherPath.java | 58 +++++++++++++++++++ .../behavior/elytra/UnpackedSegment.java | 5 +- 3 files changed, 79 insertions(+), 34 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/NetherPath.java diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 328ee6818..4494a54aa 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -22,6 +22,7 @@ import baritone.api.behavior.IElytraBehavior; import baritone.api.event.events.*; import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; +import baritone.behavior.elytra.NetherPath; import baritone.behavior.elytra.UnpackedSegment; import baritone.utils.BlockStateInterface; import baritone.utils.accessor.IEntityFireworkRocket; @@ -39,7 +40,6 @@ import net.minecraft.world.chunk.Chunk; import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.Future; -import java.util.function.IntFunction; import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -77,7 +77,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final class PathManager { private BlockPos destination; - private List path; + private NetherPath path; private boolean completePath; private boolean recalculating; @@ -173,17 +173,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }); } - private Vec3d pathAt(int i) { - return new Vec3d( - this.path.get(i).x, - this.path.get(i).y, - this.path.get(i).z - ); - } - public void clear() { this.destination = null; - this.path = Collections.emptyList(); + this.path = NetherPath.emptyPath(); this.completePath = true; this.recalculating = false; this.playerNear = 0; @@ -200,7 +192,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.maxPlayerNear = 0; } - public List getPath() { + public NetherPath getPath() { return this.path; } @@ -245,7 +237,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!clearView(pathAt(i), pathAt(i + 1), false)) { + if (!ElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment final BetterBlockPos blockage = this.path.get(i); @@ -392,8 +384,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.remainingSetBackTicks--; } + // Reset rendered elements this.clearLines.clear(); this.blockedLines.clear(); + this.aimPos = null; final List path = this.pathManager.getPath(); if (path.isEmpty() || !ctx.player().isElytraFlying()) { @@ -462,17 +456,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private Solution solveAngles(final SolverContext context) { - final List path = context.path; + final NetherPath path = context.path; final int playerNear = context.playerNear; final Vec3d start = context.start; final boolean isBoosted = context.isBoosted; - final IntFunction pathAt = (i) -> new Vec3d( - path.get(i).x, - path.get(i).y, - path.get(i).z - ); - final boolean isInLava = ctx.player().isInLava(); Solution solution = null; @@ -488,9 +476,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (float interp : interps) { Vec3d dest; if (interp == 1 || i == minStep) { - dest = pathAt.apply(i); + dest = path.getVec(i); } else { - dest = pathAt.apply(i).scale(interp).add(pathAt.apply(i - 1).scale(1.0d - interp)); + dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); } dest = dest.add(0, dy, 0); @@ -499,24 +487,24 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H continue; } if (start.distanceTo(dest) < 40) { - if (!this.clearView(dest, pathAt.apply(i + lookahead).add(0, dy, 0), false) - || !this.clearView(dest, pathAt.apply(i + lookahead), false)) { + if (!this.clearView(dest, path.getVec(i + lookahead).add(0, dy, 0), false) + || !this.clearView(dest, path.getVec(i + lookahead), false)) { // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } } else { // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!this.clearView(dest, pathAt.apply(i), false)) { + if (!this.clearView(dest, path.getVec(i), false)) { continue; } } } // 1.0 -> 0.25 -> none - final Double grow = relaxation == 2 ? null + final Double growth = relaxation == 2 ? null : relaxation == 0 ? 1.0d : 0.25d; - if (this.isClear(start, dest, grow, isInLava)) { + if (this.isHitboxClear(start, dest, growth, isInLava)) { // Yaw is trivial, just calculate the rotation required to face the destination final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); @@ -570,7 +558,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final class SolverContext { - public final List path; + public final NetherPath path; public final int playerNear; public final Vec3d start; public final boolean isBoosted; @@ -636,7 +624,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .anyMatch(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())); } - private boolean isClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { + private boolean isHitboxClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { if (!this.clearView(start, dest, ignoreLava)) { return false; } @@ -713,7 +701,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // yaw is easy so we only care about pitch goalDirection = goalDirection.normalize(); - Rotation good = RotationUtils.calcRotationFromVec3d(new Vec3d(0, 0, 0), goalDirection, ctx.playerRotations()); // lazy lol + Rotation good = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()); // lazy lol Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; @@ -723,7 +711,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H outer: for (float pitch = minPitch; pitch <= maxPitch; pitch++) { Vec3d stepped = motion; - Vec3d totalMotion = new Vec3d(0, 0, 0); + Vec3d totalMotion = Vec3d.ZERO; for (int i = 0; i < steps; i++) { stepped = step(stepped, pitch, good.getYaw(), firework); Vec3d actualPositionPrevTick = ctx.playerFeetAsVec().add(totalMotion); diff --git a/src/main/java/baritone/behavior/elytra/NetherPath.java b/src/main/java/baritone/behavior/elytra/NetherPath.java new file mode 100644 index 000000000..e90075b87 --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/NetherPath.java @@ -0,0 +1,58 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +import baritone.api.utils.BetterBlockPos; +import net.minecraft.util.math.Vec3d; + +import java.util.AbstractList; +import java.util.Collections; +import java.util.List; + +/** + * @author Brady + */ +public final class NetherPath extends AbstractList { + + private static final NetherPath EMPTY_PATH = new NetherPath(Collections.emptyList()); + + private final List backing; + + NetherPath(List backing) { + this.backing = backing; + } + + @Override + public BetterBlockPos get(int index) { + return this.backing.get(index); + } + + @Override + public int size() { + return this.backing.size(); + } + + public Vec3d getVec(int index) { + final BetterBlockPos pos = this.get(index); + return new Vec3d(pos.x, pos.y, pos.z); + } + + public static NetherPath emptyPath() { + return EMPTY_PATH; + } +} diff --git a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java index 7798113da..8771aaabd 100644 --- a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java +++ b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java @@ -22,7 +22,6 @@ import dev.babbaj.pathfinder.PathSegment; import net.minecraft.util.math.BlockPos; import java.util.Arrays; -import java.util.List; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -48,8 +47,8 @@ public final class UnpackedSegment { return new UnpackedSegment(Stream.concat(other, this.path), this.finished); } - public List collect() { - return this.path.collect(Collectors.toList()); + public NetherPath collect() { + return new NetherPath(this.path.collect(Collectors.toList())); } public boolean isFinished() { From bd7a57f7aabbb1eb599044b47e720dc3ded2e349 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 21:27:54 -0500 Subject: [PATCH 092/276] We do a little trolling --- .../baritone/behavior/ElytraBehavior.java | 19 +--------------- .../behavior/elytra/UnpackedSegment.java | 22 ++++++++++++++++++- 2 files changed, 22 insertions(+), 19 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 4494a54aa..aab8be41d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -185,7 +185,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private void setPath(final UnpackedSegment segment) { this.path = segment.collect(); - this.removeBacktracks(); this.completePath = segment.isFinished(); this.playerNear = 0; this.ticksNearUnchanged = 0; @@ -295,22 +294,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } this.playerNear = index; } - - private void removeBacktracks() { - Map positionFirstSeen = new HashMap<>(); - for (int i = 0; i < this.path.size(); i++) { - BetterBlockPos pos = this.path.get(i); - if (positionFirstSeen.containsKey(pos)) { - int j = positionFirstSeen.get(pos); - while (i > j) { - this.path.remove(i); - i--; - } - } else { - positionFirstSeen.put(pos, i); - } - } - } } @Override @@ -466,7 +449,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = isBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost - float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; + float[] interps = new float[] {1.0f}; int steps = relaxation < 2 ? isBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); diff --git a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java index 8771aaabd..22fa4f82d 100644 --- a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java +++ b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java @@ -22,6 +22,9 @@ import dev.babbaj.pathfinder.PathSegment; import net.minecraft.util.math.BlockPos; import java.util.Arrays; +import java.util.HashMap; +import java.util.List; +import java.util.Map; import java.util.stream.Collectors; import java.util.stream.Stream; @@ -48,7 +51,24 @@ public final class UnpackedSegment { } public NetherPath collect() { - return new NetherPath(this.path.collect(Collectors.toList())); + final List path = this.path.collect(Collectors.toList()); + + // Remove backtracks + final Map positionFirstSeen = new HashMap<>(); + for (int i = 0; i < path.size(); i++) { + BetterBlockPos pos = path.get(i); + if (positionFirstSeen.containsKey(pos)) { + int j = positionFirstSeen.get(pos); + while (i > j) { + path.remove(i); + i--; + } + } else { + positionFirstSeen.put(pos, i); + } + } + + return new NetherPath(path); } public boolean isFinished() { From 2eb912835a2e98c452726a689c07901359a67381 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 21:28:30 -0500 Subject: [PATCH 093/276] Restore interp values --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index aab8be41d..15d4f5f09 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -449,7 +449,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = isBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost - float[] interps = new float[] {1.0f}; + float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; int steps = relaxation < 2 ? isBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); From 699e8bdea6b545842f234e3360b30db76c223b7d Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 22:36:27 -0500 Subject: [PATCH 094/276] troll concurrency fix for rn --- src/main/java/baritone/behavior/ElytraBehavior.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 15d4f5f09..6f585d30c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -39,6 +39,7 @@ import net.minecraft.world.chunk.Chunk; import java.util.*; import java.util.concurrent.CompletableFuture; +import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; import java.util.function.UnaryOperator; @@ -68,8 +69,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public ElytraBehavior(Baritone baritone) { super(baritone); this.context = new NetherPathfinderContext(NETHER_SEED); - this.clearLines = new ArrayList<>(); - this.blockedLines = new ArrayList<>(); + this.clearLines = new CopyOnWriteArrayList<>(); + this.blockedLines = new CopyOnWriteArrayList<>(); this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); } From defa6399e2bcf0f722dfc5890779ba1e9a100bf6 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 23:01:07 -0500 Subject: [PATCH 095/276] Tweak hitbox constraints --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 6f585d30c..eb6e2c4b0 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -486,7 +486,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // 1.0 -> 0.25 -> none final Double growth = relaxation == 2 ? null - : relaxation == 0 ? 1.0d : 0.25d; + : relaxation == 0 ? 0.5d : 0.25d; if (this.isHitboxClear(start, dest, growth, isInLava)) { // Yaw is trivial, just calculate the rotation required to face the destination From d42bfcfa53fc4d27f46cae301b35a7d6f97c0612 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 20 Jun 2023 23:15:45 -0500 Subject: [PATCH 096/276] Fix NPE --- src/main/java/baritone/behavior/ElytraBehavior.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index eb6e2c4b0..5f3e92838 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -333,8 +333,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.aimPos = null; this.remainingFireworkTicks = 0; this.remainingSetBackTicks = 0; - this.solver.cancel(true); - this.solver = null; + if (this.solver != null) { + this.solver.cancel(true); + this.solver = null; + } } @Override From cfd9a690528508d6427fc068e426dceeff01943d Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 00:21:37 -0500 Subject: [PATCH 097/276] Revert how PathManager tick works --- src/main/java/baritone/behavior/ElytraBehavior.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5f3e92838..14a15706e 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -97,7 +97,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final int prevMaxNear = this.maxPlayerNear; this.maxPlayerNear = Math.max(this.maxPlayerNear, this.playerNear); - if (this.maxPlayerNear == prevMaxNear) { + if (this.maxPlayerNear == prevMaxNear && ctx.player().isElytraFlying()) { this.ticksNearUnchanged++; } else { this.ticksNearUnchanged = 0; @@ -376,7 +376,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.aimPos = null; final List path = this.pathManager.getPath(); - if (path.isEmpty() || !ctx.player().isElytraFlying()) { + if (path.isEmpty()) { return; } @@ -389,6 +389,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Math.min(playerNear + 100, path.size()) ); + if (!ctx.player().isElytraFlying()) { + return; + } baritone.getInputOverrideHandler().clearAllKeys(); if (ctx.player().collidedHorizontally) { From 877fd25608202596336af3ead8d19d2349c47394 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 00:52:43 -0500 Subject: [PATCH 098/276] Distinguish unexpected exceptions in path calc --- .../exception/CommandUnhandledException.java | 7 +---- src/api/java/baritone/api/utils/Helper.java | 7 +++++ .../baritone/behavior/ElytraBehavior.java | 19 ++++++++++--- .../elytra/NetherPathfinderContext.java | 21 ++++++++------ .../elytra/PathCalculationException.java | 28 +++++++++++++++++++ 5 files changed, 64 insertions(+), 18 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/PathCalculationException.java diff --git a/src/api/java/baritone/api/command/exception/CommandUnhandledException.java b/src/api/java/baritone/api/command/exception/CommandUnhandledException.java index 5dce59313..a1f826262 100644 --- a/src/api/java/baritone/api/command/exception/CommandUnhandledException.java +++ b/src/api/java/baritone/api/command/exception/CommandUnhandledException.java @@ -19,7 +19,6 @@ package baritone.api.command.exception; import baritone.api.command.ICommand; import baritone.api.command.argument.ICommandArgument; -import net.minecraft.util.text.TextFormatting; import java.util.List; @@ -37,10 +36,6 @@ public class CommandUnhandledException extends RuntimeException implements IComm @Override public void handle(ICommand command, List args) { - HELPER.logDirect("An unhandled exception occurred. " + - "The error is in your game's log, please report this at https://github.com/cabaletta/baritone/issues", - TextFormatting.RED); - - this.printStackTrace(); + HELPER.logUnhandledException(this); } } diff --git a/src/api/java/baritone/api/utils/Helper.java b/src/api/java/baritone/api/utils/Helper.java index b99074ae0..d604e0006 100755 --- a/src/api/java/baritone/api/utils/Helper.java +++ b/src/api/java/baritone/api/utils/Helper.java @@ -230,4 +230,11 @@ public interface Helper { default void logDirect(String message) { logDirect(message, BaritoneAPI.getSettings().logAsToast.value); } + + default void logUnhandledException(final Throwable exception) { + HELPER.logDirect("An unhandled exception occurred. " + + "The error is in your game's log, please report this at https://github.com/cabaletta/baritone/issues", + TextFormatting.RED); + exception.printStackTrace(); + } } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 14a15706e..193c95227 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -23,6 +23,7 @@ import baritone.api.event.events.*; import baritone.api.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.NetherPath; +import baritone.behavior.elytra.PathCalculationException; import baritone.behavior.elytra.UnpackedSegment; import baritone.utils.BlockStateInterface; import baritone.utils.accessor.IEntityFireworkRocket; @@ -108,7 +109,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.attemptNextSegment(); } - public void pathToDestination(BlockPos destination) { + public void pathToDestination(final BlockPos destination) { this.destination = destination; final long start = System.nanoTime(); this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) @@ -123,7 +124,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .whenComplete((result, ex) -> { this.recalculating = false; if (ex != null) { - logDirect("Failed to compute path to destination"); + if (ex instanceof PathCalculationException) { + logDirect("Failed to compute path to destination"); + } else { + logUnhandledException(ex); + } } }); } @@ -141,7 +146,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .whenComplete((result, ex) -> { this.recalculating = false; if (ex != null) { - logDirect("Failed to recompute segment"); + if (ex instanceof PathCalculationException) { + logDirect("Failed to recompute segment"); + } else { + logUnhandledException(ex); + } } }); } @@ -168,8 +177,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex != null) { + if (ex instanceof PathCalculationException) { logDirect("Failed to compute next segment"); + } else { + logUnhandledException(ex); } }); } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index da3753bf3..d82372a99 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -52,14 +52,19 @@ public final class NetherPathfinderContext { } public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { - return CompletableFuture.supplyAsync(() -> - NetherPathfinder.pathFind( - this.context, - src.getX(), src.getY(), src.getZ(), - dst.getX(), dst.getY(), dst.getZ(), - true, - 10000 - ), this.executor); + return CompletableFuture.supplyAsync(() -> { + final PathSegment segment = NetherPathfinder.pathFind( + this.context, + src.getX(), src.getY(), src.getZ(), + dst.getX(), dst.getY(), dst.getZ(), + true, + 10000 + ); + if (segment == null) { + throw new PathCalculationException("Path calculation failed"); + } + return segment; + }, this.executor); } /** diff --git a/src/main/java/baritone/behavior/elytra/PathCalculationException.java b/src/main/java/baritone/behavior/elytra/PathCalculationException.java new file mode 100644 index 000000000..73ce82faf --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/PathCalculationException.java @@ -0,0 +1,28 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +/** + * @author Brady + */ +public final class PathCalculationException extends RuntimeException { + + public PathCalculationException(final String message) { + super(message); + } +} From 0aff31b7685008adf23f7251e328b74c05570ebc Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 18:59:44 -0500 Subject: [PATCH 099/276] Perfect elytra simulation --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 193c95227..a0839f100 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -713,7 +713,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Vec3d stepped = motion; Vec3d totalMotion = Vec3d.ZERO; for (int i = 0; i < steps; i++) { - stepped = step(stepped, pitch, good.getYaw(), firework); + stepped = step(stepped, pitch, good.getYaw(), firework && i > 0); Vec3d actualPositionPrevTick = ctx.playerFeetAsVec().add(totalMotion); totalMotion = totalMotion.add(stepped); Vec3d actualPosition = ctx.playerFeetAsVec().add(totalMotion); @@ -781,9 +781,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H motionX += (lookDirection.x / pitchBase2 * flatMotion - motionX) * 0.1; motionZ += (lookDirection.z / pitchBase2 * flatMotion - motionZ) * 0.1; } - motionX *= 0.99; - motionY *= 0.98; - motionZ *= 0.99; + motionX *= 0.99f; + motionY *= 0.98f; + motionZ *= 0.99f; //System.out.println(motionX + " " + motionY + " " + motionZ); return new Vec3d(motionX, motionY, motionZ); From 4776fa18765a9b56d9abea493117f2e119fd5abf Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 21:19:12 -0500 Subject: [PATCH 100/276] Don't update `playerNear` on an empty path --- src/main/java/baritone/behavior/ElytraBehavior.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index a0839f100..b63d81a33 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -282,6 +282,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } public void updatePlayerNear() { + if (this.path.isEmpty()) { + return; + } + int index = this.playerNear; final BetterBlockPos pos = ctx.playerFeet(); for (int i = index; i >= Math.max(index - 1000, 0); i -= 10) { From 47dc0f9b941a6d9c8643cc9a03986998a6940498 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 21:30:04 -0500 Subject: [PATCH 101/276] Add missing exception null check to async completed callback --- src/main/java/baritone/behavior/ElytraBehavior.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b63d81a33..a6fd769d0 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -177,10 +177,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex instanceof PathCalculationException) { - logDirect("Failed to compute next segment"); - } else { - logUnhandledException(ex); + if (ex != null) { + if (ex instanceof PathCalculationException) { + logDirect("Failed to compute next segment"); + } else { + logUnhandledException(ex); + } } }); } From 535fd17a42b6b9a110c28ac298e5ac9e1e3379f4 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Thu, 22 Jun 2023 08:30:25 -0400 Subject: [PATCH 102/276] simplify null check --- src/main/java/baritone/behavior/ElytraBehavior.java | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index a6fd769d0..da2b4f41b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -123,12 +123,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex != null) { - if (ex instanceof PathCalculationException) { - logDirect("Failed to compute path to destination"); - } else { - logUnhandledException(ex); - } + if (ex instanceof PathCalculationException) { + logDirect("Failed to compute path to destination"); + } else if (ex != null) { + logUnhandledException(ex); } }); } From b366b1b1d1aa79185389c5541b3451c436c6179d Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 11:40:45 -0500 Subject: [PATCH 103/276] Fix other null checks --- .../baritone/behavior/ElytraBehavior.java | 20 ++++++++----------- 1 file changed, 8 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index da2b4f41b..5e370fa28 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -143,12 +143,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex != null) { - if (ex instanceof PathCalculationException) { - logDirect("Failed to recompute segment"); - } else { - logUnhandledException(ex); - } + if (ex instanceof PathCalculationException) { + logDirect("Failed to recompute segment"); + } else if (ex != null) { + logUnhandledException(ex); } }); } @@ -175,12 +173,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex != null) { - if (ex instanceof PathCalculationException) { - logDirect("Failed to compute next segment"); - } else { - logUnhandledException(ex); - } + if (ex instanceof PathCalculationException) { + logDirect("Failed to compute next segment"); + } else if (ex != null) { + logUnhandledException(ex); } }); } From f4a99253f44f727dbff097c92c28796d4860b830 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 12:08:30 -0500 Subject: [PATCH 104/276] Prevent head bonks --- src/main/java/baritone/behavior/ElytraBehavior.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5e370fa28..89acee39f 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -628,6 +628,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!this.clearView(start, dest, ignoreLava)) { return false; } + // Prevent head bonks + // Even though the player's hitbox is supposed to be 0.6 tall, there's no way it's actually that short + if (!this.clearView(start.add(0, 1.6, 0), dest, ignoreLava)) { + return false; + } if (growAmount == null) { return true; } From 9cf5538058579470f87ccb6a009f99b1681aa0b2 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 12:50:06 -0500 Subject: [PATCH 105/276] Improve stepper collision detection --- .../baritone/behavior/ElytraBehavior.java | 45 ++++++++++++------- 1 file changed, 28 insertions(+), 17 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 89acee39f..5f25119a7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -628,7 +628,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!this.clearView(start, dest, ignoreLava)) { return false; } - // Prevent head bonks + // Avoid head bonks // Even though the player's hitbox is supposed to be 0.6 tall, there's no way it's actually that short if (!this.clearView(start.add(0, 1.6, 0), dest, ignoreLava)) { return false; @@ -684,14 +684,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(Vec3d goalDirection, int steps, int relaxation, boolean isBoosted, boolean ignoreLava) { - final Float pitch = this.solvePitch(goalDirection, steps, relaxation == 2, isBoosted, ignoreLava); + private Pair solvePitch(Vec3d goalDelta, int steps, int relaxation, boolean isBoosted, boolean ignoreLava) { + final Float pitch = this.solvePitch(goalDelta, steps, relaxation == 2, isBoosted, ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - final Float usingFirework = this.solvePitch(goalDirection, steps, relaxation == 2, true, ignoreLava); + final Float usingFirework = this.solvePitch(goalDelta, steps, relaxation == 2, true, ignoreLava); if (usingFirework != null) { return new Pair<>(usingFirework, true); } @@ -700,37 +700,48 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Pair<>(null, false); } - private Float solvePitch(Vec3d goalDirection, int steps, boolean desperate, boolean firework, boolean ignoreLava) { + private Float solvePitch(Vec3d goalDelta, int steps, boolean desperate, boolean firework, boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch - goalDirection = goalDirection.normalize(); + final Vec3d goalDirection = goalDelta.normalize(); Rotation good = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()); // lazy lol Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; - Vec3d motion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); - float minPitch = desperate ? -90 : Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); - float maxPitch = desperate ? 90 : Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); + + final Vec3d initialMotion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); + final AxisAlignedBB initialBB = ctx.player().getEntityBoundingBox(); + final float minPitch = desperate ? -90 : Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); + final float maxPitch = desperate ? 90 : Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); + outer: for (float pitch = minPitch; pitch <= maxPitch; pitch++) { - Vec3d stepped = motion; + Vec3d motion = initialMotion; + AxisAlignedBB hitbox = initialBB; Vec3d totalMotion = Vec3d.ZERO; for (int i = 0; i < steps; i++) { - stepped = step(stepped, pitch, good.getYaw(), firework && i > 0); - Vec3d actualPositionPrevTick = ctx.playerFeetAsVec().add(totalMotion); - totalMotion = totalMotion.add(stepped); - Vec3d actualPosition = ctx.playerFeetAsVec().add(totalMotion); - for (int x = MathHelper.floor(Math.min(actualPosition.x, actualPositionPrevTick.x) - 0.31); x <= Math.max(actualPosition.x, actualPositionPrevTick.x) + 0.31; x++) { - for (int y = MathHelper.floor(Math.min(actualPosition.y, actualPositionPrevTick.y) - 0.2); y <= Math.max(actualPosition.y, actualPositionPrevTick.y) + 1; y++) { - for (int z = MathHelper.floor(Math.min(actualPosition.z, actualPositionPrevTick.z) - 0.31); z <= Math.max(actualPosition.z, actualPositionPrevTick.z) + 0.31; z++) { + motion = step(motion, pitch, good.getYaw(), firework && i > 0); + + final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z) + // Additional padding for safety + .grow(0.01, 0.01, 0.01) + // Expand 0.4 up and 0.2 down for head bonk avoidance + .expand(0, 0.4, 0).expand(0, -0.2, 0); + + for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { + for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { + for (int z = MathHelper.floor(inMotion.minZ); z < MathHelper.ceil(inMotion.maxZ); z++) { if (!this.passable(x, y, z, ignoreLava)) { continue outer; } } } } + + hitbox = hitbox.offset(motion.x, motion.y, motion.z); + totalMotion = totalMotion.add(motion); } double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); // tried to incorporate a "speedGoodness" but it kept making it do stupid stuff (aka always losing altitude) From 90434b3178516fe92c4dbe9538bc432e95a1bf15 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 12:54:30 -0500 Subject: [PATCH 106/276] A bit more flexibility --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5f25119a7..77c2d9f00 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -630,7 +630,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } // Avoid head bonks // Even though the player's hitbox is supposed to be 0.6 tall, there's no way it's actually that short - if (!this.clearView(start.add(0, 1.6, 0), dest, ignoreLava)) { + if (!this.clearView(start.add(0, 1, 0), dest, ignoreLava)) { return false; } if (growAmount == null) { From bce2c74a8e3cab5b14986c3f01084a587fc21af4 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 18:07:11 -0500 Subject: [PATCH 107/276] NO MORE CONCUSSIONS! --- .../baritone/behavior/ElytraBehavior.java | 80 ++++++++++++++----- 1 file changed, 60 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 77c2d9f00..041813d4c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -123,10 +123,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex instanceof PathCalculationException) { - logDirect("Failed to compute path to destination"); - } else if (ex != null) { - logUnhandledException(ex); + if (ex != null) { + final Throwable cause = ex.getCause(); + if (cause instanceof PathCalculationException) { + logDirect("Failed to compute path to destination"); + } else { + logUnhandledException(cause); + } } }); } @@ -143,10 +146,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex instanceof PathCalculationException) { - logDirect("Failed to recompute segment"); - } else if (ex != null) { - logUnhandledException(ex); + if (ex != null) { + final Throwable cause = ex.getCause(); + if (cause instanceof PathCalculationException) { + logDirect("Failed to recompute segment"); + } else { + logUnhandledException(cause); + } } }); } @@ -173,10 +179,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }) .whenComplete((result, ex) -> { this.recalculating = false; - if (ex instanceof PathCalculationException) { - logDirect("Failed to compute next segment"); - } else if (ex != null) { - logUnhandledException(ex); + if (ex != null) { + final Throwable cause = ex.getCause(); + if (cause instanceof PathCalculationException) { + logDirect("Failed to compute next segment"); + } else { + logUnhandledException(cause); + } } }); } @@ -628,11 +637,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!this.clearView(start, dest, ignoreLava)) { return false; } - // Avoid head bonks - // Even though the player's hitbox is supposed to be 0.6 tall, there's no way it's actually that short - if (!this.clearView(start.add(0, 1, 0), dest, ignoreLava)) { - return false; - } if (growAmount == null) { return true; } @@ -722,13 +726,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H AxisAlignedBB hitbox = initialBB; Vec3d totalMotion = Vec3d.ZERO; for (int i = 0; i < steps; i++) { + if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { + continue outer; + } motion = step(motion, pitch, good.getYaw(), firework && i > 0); final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z) // Additional padding for safety - .grow(0.01, 0.01, 0.01) - // Expand 0.4 up and 0.2 down for head bonk avoidance - .expand(0, 0.4, 0).expand(0, -0.2, 0); + .grow(0.01, 0.01, 0.01); for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { @@ -813,5 +818,40 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Material mat = state.getMaterial(); return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); } + + /** + * Minecraft 1.12's pushOutOfBlocks logic doesn't account for players being able to fit under single block spaces, + * so whenever the edge of a ceiling is encountered while elytra flying it tries to push the player out. + */ + private static final class MC_1_12_Collision_Fix { + + public static boolean bonk(final IPlayerContext ctx, final AxisAlignedBB aabb) { + final Vec3d center = aabb.getCenter(); + final double width = (double) ctx.player().width * 0.35D; + final double x = center.x; + final double y = aabb.minY + 0.5D; + final double z = center.z; + + return pushOutOfBlocks(ctx, x - width, y, z + width) + || pushOutOfBlocks(ctx, x - width, y, z - width) + || pushOutOfBlocks(ctx, x + width, y, z - width) + || pushOutOfBlocks(ctx, x + width, y, z + width); + } + + private static boolean pushOutOfBlocks(final IPlayerContext ctx, final double x, final double y, final double z) { + final BlockPos pos = new BlockPos(x, y, z); + if (isOpenBlockSpace(ctx, pos)) { + return false; + } + return isOpenBlockSpace(ctx, pos.west()) + || isOpenBlockSpace(ctx, pos.east()) + || isOpenBlockSpace(ctx, pos.north()) + || isOpenBlockSpace(ctx, pos.south()); + } + + private static boolean isOpenBlockSpace(IPlayerContext ctx, BlockPos pos) { + return !ctx.world().getBlockState(pos).isNormalCube() && !ctx.world().getBlockState(pos.up()).isNormalCube(); + } + } } From 878a32228a09eed651fde46b1203d974ebfb3506 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 18:22:40 -0500 Subject: [PATCH 108/276] Add avoidance setting --- src/api/java/baritone/api/Settings.java | 1 + src/main/java/baritone/behavior/ElytraBehavior.java | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index be959ef12..71a2d996b 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -52,6 +52,7 @@ public final class Settings { public final Setting elytraPitchRange = new Setting<>(25); public final Setting elytraFireworkSpeed = new Setting<>(0.6); public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15); + public final Setting elytraMinimumAvoidance = new Setting<>(0.2); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 041813d4c..345da254d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -509,9 +509,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - // 1.0 -> 0.25 -> none + final double minAvoidance = Baritone.settings().elytraMinimumAvoidance.value; final Double growth = relaxation == 2 ? null - : relaxation == 0 ? 0.5d : 0.25d; + : relaxation == 0 ? 2 * minAvoidance : minAvoidance; if (this.isHitboxClear(start, dest, growth, isInLava)) { // Yaw is trivial, just calculate the rotation required to face the destination From c10903be6985d553d623b590088b3943cfe98d92 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 23 Jun 2023 16:17:59 -0700 Subject: [PATCH 109/276] Remove `firstFireworks` from `InventoryBehavior` --- .../java/baritone/behavior/InventoryBehavior.java | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java index 5c351adce..1ab31eb53 100644 --- a/src/main/java/baritone/behavior/InventoryBehavior.java +++ b/src/main/java/baritone/behavior/InventoryBehavior.java @@ -152,20 +152,6 @@ public final class InventoryBehavior extends Behavior implements Helper { return bestInd; } - private int firstFireworks() { - final NonNullList invy = ctx.player().inventory.mainInventory; - for (int i = 0; i < invy.size(); i++) { - final ItemStack itemStack = invy.get(i); - final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); - if (itemStack.getItem() == Items.FIREWORKS - && subCompound != null - && subCompound.hasKey("Flight")) { - return i; - } - } - return -1; - } - public boolean hasGenericThrowaway() { for (Item item : Baritone.settings().acceptableThrowawayItems.value) { if (throwaway(false, stack -> item.equals(stack.getItem()))) { From f56e0569a2878fff0828f9041d6c9736d1d0ec58 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 23 Jun 2023 16:30:10 -0700 Subject: [PATCH 110/276] Add `minimumBoostTicks` --- .../baritone/behavior/ElytraBehavior.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 345da254d..e2c87c2c7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -60,7 +60,19 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private final NetherPathfinderContext context; private final PathManager pathManager; + + /** + * Remaining cool-down ticks between firework usage + */ private int remainingFireworkTicks; + + /** + * The most recent minimum number of firework boost ticks, equivalent to {@code 10 * (1 + Flight)} + *

+ * Updated every time a firework is automatically used + */ + private int minimumBoostTicks; + private int remainingSetBackTicks; private BlockStateInterface bsi; @@ -561,6 +573,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } logDirect("attempting to use firework" + (forceUseFirework ? " takeoff" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); + this.minimumBoostTicks = 10 * (1 + getFireworkBoost(ctx.player().getHeldItemMainhand()).orElse(0)); this.remainingFireworkTicks = 10; } } @@ -576,7 +589,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.isBoosted = ElytraBehavior.this.isFireworkActive(); + this.isBoosted = ElytraBehavior.this.getAttachedFirework().isPresent(); } @Override @@ -618,19 +631,30 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return false; } // If it has NBT data, make sure it won't cause us to explode. - final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); - return subCompound == null || !subCompound.hasKey("Explosions"); + final NBTTagCompound compound = itemStack.getSubCompound("Fireworks"); + return compound == null || !compound.hasKey("Explosions"); } private static boolean isBoostingFireworks(final ItemStack itemStack) { - final NBTTagCompound subCompound = itemStack.getSubCompound("Fireworks"); - return isFireworks(itemStack) && subCompound != null && subCompound.hasKey("Flight"); + return getFireworkBoost(itemStack).isPresent(); } - private boolean isFireworkActive() { + private static OptionalInt getFireworkBoost(final ItemStack itemStack) { + if (isFireworks(itemStack)) { + final NBTTagCompound compound = itemStack.getSubCompound("Fireworks"); + if (compound != null && compound.hasKey("Flight")) { + return OptionalInt.of(compound.getByte("Flight")); + } + } + return OptionalInt.empty(); + } + + private Optional getAttachedFirework() { return ctx.world().loadedEntityList.stream() - .filter(x -> x instanceof EntityFireworkRocket) - .anyMatch(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())); + .filter(x -> x instanceof EntityFireworkRocket) + .filter(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())) + .map(x -> (EntityFireworkRocket) x) + .findFirst(); } private boolean isHitboxClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { From 2ccd464a4989013609b6d293a3167b1cc854b83d Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 24 Jun 2023 21:44:08 -0700 Subject: [PATCH 111/276] Utilize aim processor API for correct elytra simulation --- .../baritone/api/utils/IPlayerContext.java | 4 ++ .../baritone/behavior/ElytraBehavior.java | 43 +++++++++++++------ 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java index 14ca69fb9..8edd8f648 100644 --- a/src/api/java/baritone/api/utils/IPlayerContext.java +++ b/src/api/java/baritone/api/utils/IPlayerContext.java @@ -75,6 +75,10 @@ public interface IPlayerContext { return new Vec3d(player().posX, player().posY + player().getEyeHeight(), player().posZ); } + default Vec3d playerMotion() { + return new Vec3d(player().motionX, player().motionY, player().motionZ); + } + BetterBlockPos viewerPos(); default Rotation playerRotations() { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index e2c87c2c7..d3e1c76f7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -19,6 +19,8 @@ package baritone.behavior; import baritone.Baritone; 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.utils.*; import baritone.behavior.elytra.NetherPathfinderContext; @@ -433,7 +435,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H logDirect("vbonk"); } - final SolverContext solverContext = this.new SolverContext(); + final SolverContext solverContext = this.new SolverContext(false); this.solveNextTick = true; // If there's no previously calculated solution to use, or the context used at the end of last tick doesn't match this tick @@ -470,7 +472,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // changed. Updating it now will avoid unnecessary recalculation on the main thread. this.pathManager.updatePlayerNear(); - final SolverContext context = this.new SolverContext(); + final SolverContext context = this.new SolverContext(true); this.solver = CompletableFuture.supplyAsync(() -> this.solveAngles(context)); this.solveNextTick = false; } @@ -529,7 +531,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Yaw is trivial, just calculate the rotation required to face the destination final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(dest.subtract(start), steps, relaxation, isBoosted, isInLava); + final Pair pitch = this.solvePitch(context, dest.subtract(start), steps, relaxation, isInLava); if (pitch.first() == null) { solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; @@ -584,12 +586,20 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final int playerNear; public final Vec3d start; public final boolean isBoosted; + public final IAimProcessor aimProcessor; - public SolverContext() { + public SolverContext(boolean async) { this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); this.isBoosted = ElytraBehavior.this.getAttachedFirework().isPresent(); + + ITickableAimProcessor aim = ElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); + if (async) { + // async computation is done at the end of a tick, advance by 1 to prepare for the next tick + aim.advance(1); + } + this.aimProcessor = aim; } @Override @@ -712,14 +722,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(Vec3d goalDelta, int steps, int relaxation, boolean isBoosted, boolean ignoreLava) { - final Float pitch = this.solvePitch(goalDelta, steps, relaxation == 2, isBoosted, ignoreLava); + private Pair solvePitch(SolverContext context, Vec3d goalDelta, int steps, int relaxation, boolean ignoreLava) { + final Float pitch = this.solvePitch(context, goalDelta, steps, relaxation == 2, context.isBoosted, ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - final Float usingFirework = this.solvePitch(goalDelta, steps, relaxation == 2, true, ignoreLava); + final Float usingFirework = this.solvePitch(context, goalDelta, steps, relaxation == 2, true, ignoreLava); if (usingFirework != null) { return new Pair<>(usingFirework, true); } @@ -728,32 +738,39 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Pair<>(null, false); } - private Float solvePitch(Vec3d goalDelta, int steps, boolean desperate, boolean firework, boolean ignoreLava) { + private Float solvePitch(SolverContext context, Vec3d goalDelta, int steps, boolean desperate, boolean firework, boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch final Vec3d goalDirection = goalDelta.normalize(); - Rotation good = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()); // lazy lol + final float goodPitch = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()).getPitch(); Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; - final Vec3d initialMotion = new Vec3d(ctx.player().motionX, ctx.player().motionY, ctx.player().motionZ); + final Vec3d initialMotion = ctx.playerMotion(); final AxisAlignedBB initialBB = ctx.player().getEntityBoundingBox(); - final float minPitch = desperate ? -90 : Math.max(good.getPitch() - Baritone.settings().elytraPitchRange.value, -89); - final float maxPitch = desperate ? 90 : Math.min(good.getPitch() + Baritone.settings().elytraPitchRange.value, 89); + final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); + final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); outer: for (float pitch = minPitch; pitch <= maxPitch; pitch++) { + final ITickableAimProcessor aimProcessor = context.aimProcessor.fork(); + Vec3d delta = goalDelta; Vec3d motion = initialMotion; AxisAlignedBB hitbox = initialBB; Vec3d totalMotion = Vec3d.ZERO; + for (int i = 0; i < steps; i++) { if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { continue outer; } - motion = step(motion, pitch, good.getYaw(), firework && i > 0); + final Rotation rotation = aimProcessor.nextRotation( + RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) + ); + motion = step(motion, rotation.getPitch(), rotation.getYaw(), firework && i > 0); + delta = delta.subtract(motion); final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z) // Additional padding for safety From 615266ed963a47ac1c7c6a4363d36ec229a36034 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 24 Jun 2023 21:57:00 -0700 Subject: [PATCH 112/276] Replace manual calculation with util method --- .../java/baritone/behavior/ElytraBehavior.java | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index d3e1c76f7..642def293 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -769,12 +769,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Rotation rotation = aimProcessor.nextRotation( RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) ); - motion = step(motion, rotation.getPitch(), rotation.getYaw(), firework && i > 0); + motion = step(motion, rotation, firework && i > 0); delta = delta.subtract(motion); - final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z) - // Additional padding for safety - .grow(0.01, 0.01, 0.01); + // Collision box while the player is in motion, with additional padding for safety + final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z).grow(0.01); for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { @@ -800,15 +799,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - private static Vec3d step(Vec3d motion, float rotationPitch, float rotationYaw, boolean firework) { + private static Vec3d step(final Vec3d motion, final Rotation rotation, final boolean firework) { double motionX = motion.x; double motionY = motion.y; double motionZ = motion.z; - float flatZ = MathHelper.cos((-rotationYaw * RotationUtils.DEG_TO_RAD_F) - (float) Math.PI); - float flatX = MathHelper.sin((-rotationYaw * RotationUtils.DEG_TO_RAD_F) - (float) Math.PI); - float pitchBase = -MathHelper.cos(-rotationPitch * RotationUtils.DEG_TO_RAD_F); - float pitchHeight = MathHelper.sin(-rotationPitch * RotationUtils.DEG_TO_RAD_F); - Vec3d lookDirection = new Vec3d(flatX * pitchBase, pitchHeight, flatZ * pitchBase); + final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); if (firework) { // See EntityFireworkRocket @@ -817,7 +812,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; } - float pitchRadians = rotationPitch * RotationUtils.DEG_TO_RAD_F; + float pitchRadians = rotation.getPitch() * RotationUtils.DEG_TO_RAD_F; double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); double thisIsAlwaysOne = lookDirection.length(); From 32b7c8265077a2b25873ddb0750d2d74a63f02fd Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 24 Jun 2023 22:11:08 -0700 Subject: [PATCH 113/276] Add `renderHitboxRaytraces` setting --- src/api/java/baritone/api/Settings.java | 1 + .../java/baritone/behavior/ElytraBehavior.java | 15 +++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 1b39c3cab..48d1c85d2 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -55,6 +55,7 @@ public final class Settings { public final Setting elytraMinimumAvoidance = new Setting<>(0.2); public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); + public final Setting renderHitboxRaytraces = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); // Experimental Elytra Settings diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 642def293..af353896f 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -701,6 +701,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H bb.maxX + ox, bb.maxY + oy, bb.minZ + oz, bb.maxX + ox, bb.maxY + oy, bb.maxZ + oz, }; + + // Use non-batching method without early failure + if (Baritone.settings().renderHitboxRaytraces.value) { + boolean clear = true; + for (int i = 0; i < 8; i++) { + final Vec3d s = new Vec3d(src[i * 3], src[i * 3 + 1], src[i * 3 + 2]); + final Vec3d d = new Vec3d(dst[i * 3], dst[i * 3 + 1], dst[i * 3 + 2]); + // Don't forward ignoreLava since the batch call doesn't care about it + if (!this.clearView(s, d, false)) { + clear = false; + } + } + return clear; + } + return this.context.raytrace(8, src, dst, NetherPathfinderContext.Visibility.ALL); } From a1a3d93dc1e3a04db2c1c4c707353c2090e22bdc Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 24 Jun 2023 22:27:38 -0700 Subject: [PATCH 114/276] Add `renderElytraSimulation` setting --- src/api/java/baritone/api/Settings.java | 1 + src/main/java/baritone/behavior/ElytraBehavior.java | 10 ++++++++++ src/main/java/baritone/utils/PathRenderer.java | 11 +++++++++++ 3 files changed, 22 insertions(+) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 48d1c85d2..960759fa2 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -56,6 +56,7 @@ public final class Settings { public final Setting conserveFireworks = new Setting<>(true); public final Setting renderRaytraces = new Setting<>(false); public final Setting renderHitboxRaytraces = new Setting<>(false); + public final Setting renderElytraSimulation = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); // Experimental Elytra Settings diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index af353896f..cb0355832 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -56,6 +56,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Used exclusively for PathRenderer public List> clearLines; public List> blockedLines; + public List simulationLine; public BlockPos aimPos; public List visiblePath; @@ -407,6 +408,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Reset rendered elements this.clearLines.clear(); this.blockedLines.clear(); + this.simulationLine = null; this.aimPos = null; final List path = this.pathManager.getPath(); @@ -763,6 +765,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Float bestPitch = null; double bestDot = Double.NEGATIVE_INFINITY; + List bestLine = null; final Vec3d initialMotion = ctx.playerMotion(); final AxisAlignedBB initialBB = ctx.player().getEntityBoundingBox(); @@ -776,6 +779,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Vec3d motion = initialMotion; AxisAlignedBB hitbox = initialBB; Vec3d totalMotion = Vec3d.ZERO; + List line = new ArrayList<>(); + line.add(totalMotion); for (int i = 0; i < steps; i++) { if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { @@ -802,6 +807,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H hitbox = hitbox.offset(motion.x, motion.y, motion.z); totalMotion = totalMotion.add(motion); + line.add(totalMotion); } double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); // tried to incorporate a "speedGoodness" but it kept making it do stupid stuff (aka always losing altitude) @@ -809,8 +815,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (goodness > bestDot) { bestDot = goodness; bestPitch = pitch; + bestLine = line; } } + if (bestLine != null) { + this.simulationLine = bestLine; + } return bestPitch; } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 0b08a1f32..da2f69e7b 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -122,6 +122,17 @@ public final class PathRenderer implements IRenderer { } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } + if (elytra.simulationLine != null && Baritone.settings().renderElytraSimulation.value) { + IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + for (int i = 0; i < elytra.simulationLine.size() - 1; i++) { + Vec3d src = elytra.simulationLine.get(i); + Vec3d dst = elytra.simulationLine.get(i + 1); + // Center line on viewer pos + buffer.pos(src.x, src.y, src.z).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(dst.x, dst.y, dst.z).color(color[0], color[1], color[2], color[3]).endVertex(); + } + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } // If there is a path calculation currently running, render the path calculation process From 1902e6c1f351caabe8035879f59a7c77dc6efdc1 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 24 Jun 2023 22:37:21 -0700 Subject: [PATCH 115/276] Reset `minimumBoostTicks` to 0 when not boosted --- src/main/java/baritone/behavior/ElytraBehavior.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index cb0355832..2ceea192a 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -550,6 +550,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void tickUseFireworks(final Vec3d start, final Vec3d goingTo, final boolean isBoosted, final boolean forceUseFirework) { + if (!isBoosted) { + this.minimumBoostTicks = 0; + } if (this.remainingSetBackTicks > 0) { logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; From 9d1addd114ebc33c87aef59c13ce716a489caf2f Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 25 Jun 2023 15:28:06 -0700 Subject: [PATCH 116/276] Add `smoothLook` setting --- src/api/java/baritone/api/Settings.java | 1 + src/main/java/baritone/behavior/LookBehavior.java | 14 ++++++++++++-- 2 files changed, 13 insertions(+), 2 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 960759fa2..5ec5b6ed4 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -58,6 +58,7 @@ public final class Settings { public final Setting renderHitboxRaytraces = new Setting<>(false); public final Setting renderElytraSimulation = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); + public final Setting smoothLook = new Setting<>(false); // Experimental Elytra Settings public final Setting experimentalTakeoff = new Setting<>(false); diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 9dd379771..f59d1be83 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -26,6 +26,7 @@ import baritone.api.event.events.*; import baritone.api.utils.IPlayerContext; import baritone.api.utils.Rotation; import baritone.behavior.look.ForkableRandom; +import com.google.common.collect.EvictingQueue; import net.minecraft.network.play.client.CPacketPlayer; import java.util.Optional; @@ -51,9 +52,12 @@ public final class LookBehavior extends Behavior implements ILookBehavior { private final AimProcessor processor; + private final EvictingQueue smoothYawBuffer; + public LookBehavior(Baritone baritone) { super(baritone); this.processor = new AimProcessor(baritone.getPlayerContext()); + this.smoothYawBuffer = EvictingQueue.create(10); } @Override @@ -96,8 +100,14 @@ public final class LookBehavior extends Behavior implements ILookBehavior { case POST: { // Reset the player's rotations back to their original values if (this.prevRotation != null) { - ctx.player().rotationYaw = this.prevRotation.getYaw(); - ctx.player().rotationPitch = this.prevRotation.getPitch(); + if (Baritone.settings().smoothLook.value) { + ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream() + .mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); + ctx.player().rotationPitch = this.prevRotation.getPitch(); + } else { + ctx.player().rotationYaw = this.prevRotation.getYaw(); + ctx.player().rotationPitch = this.prevRotation.getPitch(); + } this.prevRotation = null; } // The target is done being used for this game tick, so it can be invalidated From 9bd085644504897f05ef52ffb3401ed8aef5ea3d Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 25 Jun 2023 15:32:02 -0700 Subject: [PATCH 117/276] lol --- src/main/java/baritone/behavior/LookBehavior.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index f59d1be83..93ea561b5 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -101,6 +101,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { // Reset the player's rotations back to their original values if (this.prevRotation != null) { if (Baritone.settings().smoothLook.value) { + this.smoothYawBuffer.add(this.target.rotation.getYaw()); ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream() .mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); ctx.player().rotationPitch = this.prevRotation.getPitch(); From 0981114b782f8de1d978f3372a16d8d64dad4271 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 13:55:18 -0500 Subject: [PATCH 118/276] Create `FireworkBoost` class for additional boost context Also initialize `boostedEntity` in `EntityFireworkRocket` if `null` since it's lazily initialized in `onUpdate()` --- .../baritone/launch/mixins/MixinEntity.java | 37 +++++++++++ .../mixins/MixinEntityFireworkRocket.java | 21 +++++- src/launch/resources/mixins.baritone.json | 1 + .../baritone/behavior/ElytraBehavior.java | 64 ++++++++++++++++--- .../utils/accessor/IEntityFireworkRocket.java | 1 + 5 files changed, 112 insertions(+), 12 deletions(-) create mode 100644 src/launch/java/baritone/launch/mixins/MixinEntity.java diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java new file mode 100644 index 000000000..a611507b8 --- /dev/null +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -0,0 +1,37 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.launch.mixins; + +import net.minecraft.entity.Entity; +import net.minecraft.network.datasync.EntityDataManager; +import net.minecraft.world.World; +import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Shadow; + +/** + * @author Brady + */ +@Mixin(Entity.class) +public abstract class MixinEntity { + + @Shadow + public World world; + + @Shadow + protected EntityDataManager dataManager; +} diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java index 274e979a0..559ae0d54 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java @@ -18,18 +18,35 @@ package baritone.launch.mixins; import baritone.utils.accessor.IEntityFireworkRocket; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityFireworkRocket; +import net.minecraft.network.datasync.DataParameter; +import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(EntityFireworkRocket.class) -public abstract class MixinEntityFireworkRocket implements IEntityFireworkRocket { +public abstract class MixinEntityFireworkRocket extends MixinEntity implements IEntityFireworkRocket { + + @Shadow + @Final + private static DataParameter BOOSTED_ENTITY_ID; + @Shadow private EntityLivingBase boostedEntity; + @Shadow + public abstract boolean isAttachedToEntity(); + @Override public EntityLivingBase getBoostedEntity() { - return boostedEntity; + if (this.isAttachedToEntity() && this.boostedEntity == null) { + final Entity entity = this.world.getEntityByID(this.dataManager.get(BOOSTED_ENTITY_ID)); + if (entity instanceof EntityLivingBase) { + this.boostedEntity = (EntityLivingBase) entity; + } + } + return this.boostedEntity; } } diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index 5c221de58..cbade3329 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -16,6 +16,7 @@ "MixinChunkProviderServer", "MixinChunkRenderContainer", "MixinChunkRenderWorker", + "MixinEntity", "MixinEntityFireworkRocket", "MixinEntityLivingBase", "MixinEntityPlayerSP", diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 2ceea192a..922d824de 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -462,7 +462,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.tickUseFireworks( solution.context.start, solution.goingTo, - solution.context.isBoosted, + solution.context.boost.isBoosted(), solution.forceUseFirework ); } @@ -484,15 +484,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final NetherPath path = context.path; final int playerNear = context.playerNear; final Vec3d start = context.start; - final boolean isBoosted = context.isBoosted; final boolean isInLava = ctx.player().isInLava(); Solution solution = null; for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) - int[] heights = isBoosted ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost + int[] heights = context.boost.isBoosted() ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; - int steps = relaxation < 2 ? isBoosted ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + int steps = relaxation < 2 ? context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; @@ -590,14 +589,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final NetherPath path; public final int playerNear; public final Vec3d start; - public final boolean isBoosted; + public final FireworkBoost boost; public final IAimProcessor aimProcessor; public SolverContext(boolean async) { this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.isBoosted = ElytraBehavior.this.getAttachedFirework().isPresent(); + this.boost = new FireworkBoost( + ElytraBehavior.this.getAttachedFirework().orElse(null), + ElytraBehavior.this.minimumBoostTicks + ); ITickableAimProcessor aim = ElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); if (async) { @@ -620,7 +622,49 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.path == other.path // Contents aren't modified, just compare by reference && this.playerNear == other.playerNear && Objects.equals(this.start, other.start) - && this.isBoosted == other.isBoosted; + && Objects.equals(this.boost, other.boost); + } + } + + private static final class FireworkBoost { + + private final EntityFireworkRocket firework; + private final int minimumBoostTicks; + private final int maximumBoostTicks; + + public FireworkBoost(final EntityFireworkRocket firework, final int minimumBoostTicks) { + this.firework = firework; + + // this.lifetime = 10 * i + this.rand.nextInt(6) + this.rand.nextInt(7); + this.minimumBoostTicks = minimumBoostTicks; + this.maximumBoostTicks = minimumBoostTicks + 11; + } + + public boolean isBoosted() { + return this.firework != null; + } + + public int getGuaranteedBoostTicks() { + return this.isBoosted() ? Math.max(0, this.minimumBoostTicks - this.firework.ticksExisted) : 0; + } + + public int getMaximumBoostTicks() { + return this.isBoosted() ? Math.max(0, this.maximumBoostTicks - this.firework.ticksExisted) : 0; + } + + @Override + public boolean equals(Object o) { + if (this == o) { + return true; + } + if (o == null || o.getClass() != FireworkBoost.class) { + return false; + } + + FireworkBoost other = (FireworkBoost) o; + return Objects.equals(this.firework, other.firework) + && this.minimumBoostTicks == other.minimumBoostTicks + && this.maximumBoostTicks == other.maximumBoostTicks; } } @@ -743,7 +787,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private Pair solvePitch(SolverContext context, Vec3d goalDelta, int steps, int relaxation, boolean ignoreLava) { - final Float pitch = this.solvePitch(context, goalDelta, steps, relaxation == 2, context.isBoosted, ignoreLava); + final Float pitch = this.solvePitch(context, goalDelta, steps, relaxation == 2, context.boost.isBoosted(), ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } @@ -827,13 +871,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - private static Vec3d step(final Vec3d motion, final Rotation rotation, final boolean firework) { + private static Vec3d step(final Vec3d motion, final Rotation rotation, final boolean applyFireworkBoost) { double motionX = motion.x; double motionY = motion.y; double motionZ = motion.z; final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); - if (firework) { + if (applyFireworkBoost) { // See EntityFireworkRocket motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; diff --git a/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java b/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java index 86c96acd9..1b22d1ffd 100644 --- a/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java +++ b/src/main/java/baritone/utils/accessor/IEntityFireworkRocket.java @@ -20,5 +20,6 @@ package baritone.utils.accessor; import net.minecraft.entity.EntityLivingBase; public interface IEntityFireworkRocket { + EntityLivingBase getBoostedEntity(); } From d244a3904036ece828534e5aa8b30babfc038f03 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 13:57:24 -0500 Subject: [PATCH 119/276] Make `MixinEntityLivingBase` extend `MixinEntity` --- .../java/baritone/launch/mixins/MixinEntity.java | 9 +++++++++ .../baritone/launch/mixins/MixinEntityLivingBase.java | 10 ++-------- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java index a611507b8..c4f99acbd 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntity.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -34,4 +34,13 @@ public abstract class MixinEntity { @Shadow protected EntityDataManager dataManager; + + @Shadow + public float rotationPitch; + + @Shadow + public float rotationYaw; + + @Shadow + public abstract void moveRelative(float strafe, float up, float forward, float friction); } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index f8544dd2f..db2faa940 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -21,9 +21,7 @@ import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.event.events.RotationMoveEvent; import net.minecraft.client.entity.EntityPlayerSP; -import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; -import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -40,7 +38,7 @@ import static org.spongepowered.asm.lib.Opcodes.GETFIELD; * @since 9/10/2018 */ @Mixin(EntityLivingBase.class) -public abstract class MixinEntityLivingBase extends Entity { +public abstract class MixinEntityLivingBase extends MixinEntity { /** * Event called to override the movement direction when jumping @@ -51,10 +49,6 @@ public abstract class MixinEntityLivingBase extends Entity { @Unique private RotationMoveEvent elytraRotationEvent; - public MixinEntityLivingBase(World worldIn) { - super(worldIn); - } - @Inject( method = "jump", at = @At("HEAD") @@ -123,7 +117,7 @@ public abstract class MixinEntityLivingBase extends Entity { private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) { Optional baritone = this.getBaritone(); if (!baritone.isPresent()) { - moveRelative(strafe, up, forward, friction); + this.moveRelative(strafe, up, forward, friction); return; } From c18715b8d7a27470e2b3c345f5bbb97faae4ac99 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 14:00:38 -0500 Subject: [PATCH 120/276] Reset `minimumBoostTicks` to 0 earlier --- src/main/java/baritone/behavior/ElytraBehavior.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 922d824de..22359a3da 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -404,6 +404,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (this.remainingSetBackTicks > 0) { this.remainingSetBackTicks--; } + if (!this.getAttachedFirework().isPresent()) { + this.minimumBoostTicks = 0; + } // Reset rendered elements this.clearLines.clear(); @@ -549,9 +552,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void tickUseFireworks(final Vec3d start, final Vec3d goingTo, final boolean isBoosted, final boolean forceUseFirework) { - if (!isBoosted) { - this.minimumBoostTicks = 0; - } if (this.remainingSetBackTicks > 0) { logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; From 0b5a310f1835f841e2b445b5f778eca06b265598 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 15:35:40 -0500 Subject: [PATCH 121/276] Move firework boost calculation into `solvePitch` --- .../baritone/behavior/ElytraBehavior.java | 32 +++++++++++-------- 1 file changed, 19 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 22359a3da..e1a134725 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -69,6 +69,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private int remainingFireworkTicks; + /** + * Remaining cool-down ticks after the player's position and rotation are reset by the server + */ + private int remainingSetBackTicks; + /** * The most recent minimum number of firework boost ticks, equivalent to {@code 10 * (1 + Flight)} *

@@ -76,7 +81,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private int minimumBoostTicks; - private int remainingSetBackTicks; private BlockStateInterface bsi; private Future solver; @@ -836,7 +840,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Rotation rotation = aimProcessor.nextRotation( RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) ); - motion = step(motion, rotation, firework && i > 0); + final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); + + motion = step(motion, lookDirection, rotation.getPitch()); delta = delta.subtract(motion); // Collision box while the player is in motion, with additional padding for safety @@ -855,6 +861,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H hitbox = hitbox.offset(motion.x, motion.y, motion.z); totalMotion = totalMotion.add(motion); line.add(totalMotion); + + if (firework) { + // See EntityFireworkRocket + motion = motion.add( + lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, + lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motion.y) * 0.5, + lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motion.z) * 0.5 + ); + } } double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); // tried to incorporate a "speedGoodness" but it kept making it do stupid stuff (aka always losing altitude) @@ -871,20 +886,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - private static Vec3d step(final Vec3d motion, final Rotation rotation, final boolean applyFireworkBoost) { + private static Vec3d step(final Vec3d motion, final Vec3d lookDirection, final float pitch) { double motionX = motion.x; double motionY = motion.y; double motionZ = motion.z; - final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); - if (applyFireworkBoost) { - // See EntityFireworkRocket - motionX += lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motionX) * 0.5; - motionY += lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motionY) * 0.5; - motionZ += lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motionZ) * 0.5; - } - - float pitchRadians = rotation.getPitch() * RotationUtils.DEG_TO_RAD_F; + float pitchRadians = pitch * RotationUtils.DEG_TO_RAD_F; double pitchBase2 = Math.sqrt(lookDirection.x * lookDirection.x + lookDirection.z * lookDirection.z); double flatMotion = Math.sqrt(motionX * motionX + motionZ * motionZ); double thisIsAlwaysOne = lookDirection.length(); @@ -962,4 +969,3 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } } - From f0148a625e790e155884d2a8ddb2a992c98a4cf4 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 16:04:05 -0500 Subject: [PATCH 122/276] Move `steps` into `solvePitch` --- src/main/java/baritone/behavior/ElytraBehavior.java | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index e1a134725..7deea42b9 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -498,7 +498,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = context.boost.isBoosted() ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; - int steps = relaxation < 2 ? context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; @@ -539,7 +538,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Yaw is trivial, just calculate the rotation required to face the destination final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(context, dest.subtract(start), steps, relaxation, isInLava); + final Pair pitch = this.solvePitch(context, dest.subtract(start), relaxation, isInLava); if (pitch.first() == null) { solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; @@ -790,7 +789,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(SolverContext context, Vec3d goalDelta, int steps, int relaxation, boolean ignoreLava) { + private Pair solvePitch(SolverContext context, Vec3d goalDelta, int relaxation, boolean ignoreLava) { + final int steps = relaxation < 2 ? context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + final Float pitch = this.solvePitch(context, goalDelta, steps, relaxation == 2, context.boost.isBoosted(), ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); From db0bfbe7229df54260d3dda30995d33552672c95 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 16:12:56 -0500 Subject: [PATCH 123/276] Move elytra simulation into new method --- .../baritone/behavior/ElytraBehavior.java | 107 +++++++++--------- 1 file changed, 54 insertions(+), 53 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 7deea42b9..ef8134c2a 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -807,7 +807,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Pair<>(null, false); } - private Float solvePitch(SolverContext context, Vec3d goalDelta, int steps, boolean desperate, boolean firework, boolean ignoreLava) { + private Float solvePitch(final SolverContext context, final Vec3d goalDelta, final int steps, + final boolean desperate, final boolean firework, final boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -819,66 +820,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H double bestDot = Double.NEGATIVE_INFINITY; List bestLine = null; - final Vec3d initialMotion = ctx.playerMotion(); - final AxisAlignedBB initialBB = ctx.player().getEntityBoundingBox(); final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); - outer: for (float pitch = minPitch; pitch <= maxPitch; pitch++) { - final ITickableAimProcessor aimProcessor = context.aimProcessor.fork(); - Vec3d delta = goalDelta; - Vec3d motion = initialMotion; - AxisAlignedBB hitbox = initialBB; - Vec3d totalMotion = Vec3d.ZERO; - List line = new ArrayList<>(); - line.add(totalMotion); - - for (int i = 0; i < steps; i++) { - if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { - continue outer; - } - final Rotation rotation = aimProcessor.nextRotation( - RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) - ); - final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); - - motion = step(motion, lookDirection, rotation.getPitch()); - delta = delta.subtract(motion); - - // Collision box while the player is in motion, with additional padding for safety - final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z).grow(0.01); - - for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { - for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { - for (int z = MathHelper.floor(inMotion.minZ); z < MathHelper.ceil(inMotion.maxZ); z++) { - if (!this.passable(x, y, z, ignoreLava)) { - continue outer; - } - } - } - } - - hitbox = hitbox.offset(motion.x, motion.y, motion.z); - totalMotion = totalMotion.add(motion); - line.add(totalMotion); - - if (firework) { - // See EntityFireworkRocket - motion = motion.add( - lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, - lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motion.y) * 0.5, - lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motion.z) * 0.5 - ); - } + Vec3d totalMotion = this.simulate(context.aimProcessor.fork(), goalDelta, pitch, steps, firework, ignoreLava); + if (totalMotion == null) { + continue; } - double directionalGoodness = goalDirection.dotProduct(totalMotion.normalize()); - // tried to incorporate a "speedGoodness" but it kept making it do stupid stuff (aka always losing altitude) - double goodness = directionalGoodness; + double goodness = goalDirection.dotProduct(totalMotion.normalize()); if (goodness > bestDot) { bestDot = goodness; bestPitch = pitch; - bestLine = line; } } if (bestLine != null) { @@ -887,6 +840,54 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } + private Vec3d simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, + final int ticks, final boolean firework, final boolean ignoreLava) { + Vec3d delta = goalDelta; + Vec3d motion = ctx.playerMotion(); + AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); + Vec3d totalMotion = Vec3d.ZERO; + + for (int i = 0; i < ticks; i++) { + if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { + return null; + } + final Rotation rotation = aimProcessor.nextRotation( + RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) + ); + final Vec3d lookDirection = RotationUtils.calcLookDirectionFromRotation(rotation); + + motion = step(motion, lookDirection, rotation.getPitch()); + delta = delta.subtract(motion); + + // Collision box while the player is in motion, with additional padding for safety + final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z).grow(0.01); + + for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { + for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { + for (int z = MathHelper.floor(inMotion.minZ); z < MathHelper.ceil(inMotion.maxZ); z++) { + if (!this.passable(x, y, z, ignoreLava)) { + return null; + } + } + } + } + + hitbox = hitbox.offset(motion.x, motion.y, motion.z); + totalMotion = totalMotion.add(motion); + + if (firework) { + // See EntityFireworkRocket + motion = motion.add( + lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, + lookDirection.y * 0.1 + (lookDirection.y * 1.5 - motion.y) * 0.5, + lookDirection.z * 0.1 + (lookDirection.z * 1.5 - motion.z) * 0.5 + ); + } + } + + return totalMotion; + } + private static Vec3d step(final Vec3d motion, final Vec3d lookDirection, final float pitch) { double motionX = motion.x; double motionY = motion.y; From 452b2c278b0fe17f84b31803af1e55d24d6b2cc8 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 16:21:15 -0500 Subject: [PATCH 124/276] Fix `renderElytraSimulation` --- .../baritone/behavior/ElytraBehavior.java | 30 ++++++++++++------- 1 file changed, 20 insertions(+), 10 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index ef8134c2a..c60f920a9 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -824,14 +824,23 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); for (float pitch = minPitch; pitch <= maxPitch; pitch++) { - Vec3d totalMotion = this.simulate(context.aimProcessor.fork(), goalDelta, pitch, steps, firework, ignoreLava); - if (totalMotion == null) { + final List displacement = this.simulate( + context.aimProcessor.fork(), + goalDelta, + pitch, + steps, + firework ? Integer.MAX_VALUE : 0, + ignoreLava + ); + if (displacement == null) { continue; } - double goodness = goalDirection.dotProduct(totalMotion.normalize()); + final Vec3d result = displacement.get(displacement.size() - 1); + double goodness = goalDirection.dotProduct(result.normalize()); if (goodness > bestDot) { bestDot = goodness; bestPitch = pitch; + bestLine = displacement; } } if (bestLine != null) { @@ -840,12 +849,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return bestPitch; } - private Vec3d simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, - final int ticks, final boolean firework, final boolean ignoreLava) { + private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, + final int ticks, int ticksBoosted, final boolean ignoreLava) { Vec3d delta = goalDelta; Vec3d motion = ctx.playerMotion(); AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); - Vec3d totalMotion = Vec3d.ZERO; + List displacement = new ArrayList<>(); + displacement.add(Vec3d.ZERO); for (int i = 0; i < ticks; i++) { if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { @@ -872,10 +882,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - hitbox = hitbox.offset(motion.x, motion.y, motion.z); - totalMotion = totalMotion.add(motion); + hitbox = hitbox.offset(motion); + displacement.add(displacement.get(displacement.size() - 1).add(motion)); - if (firework) { + if (ticksBoosted-- > 0) { // See EntityFireworkRocket motion = motion.add( lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, @@ -885,7 +895,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - return totalMotion; + return displacement; } private static Vec3d step(final Vec3d motion, final Vec3d lookDirection, final float pitch) { From 3e94cac56768042ab9d39a409fdbe9d5c98929af Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 16:25:21 -0500 Subject: [PATCH 125/276] clarity --- src/main/java/baritone/behavior/ElytraBehavior.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c60f920a9..3f056d7e6 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -789,16 +789,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(SolverContext context, Vec3d goalDelta, int relaxation, boolean ignoreLava) { - final int steps = relaxation < 2 ? context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value : 3; + private Pair solvePitch(final SolverContext context, final Vec3d goalDelta, + final int relaxation, final boolean ignoreLava) { + final boolean desperate = relaxation == 2; + final int steps = desperate ? 3 : context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value; - final Float pitch = this.solvePitch(context, goalDelta, steps, relaxation == 2, context.boost.isBoosted(), ignoreLava); + final Float pitch = this.solvePitch(context, goalDelta, steps, desperate, context.boost.isBoosted(), ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - final Float usingFirework = this.solvePitch(context, goalDelta, steps, relaxation == 2, true, ignoreLava); + final Float usingFirework = this.solvePitch(context, goalDelta, steps, desperate, true, ignoreLava); if (usingFirework != null) { return new Pair<>(usingFirework, true); } From 04a5a1a620ffeb3b6a92ed9eed504a58f3e45f7d Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 16:58:29 -0500 Subject: [PATCH 126/276] Replace `bool firework` with `ticksBoosted` in `solvePitch` --- .../java/baritone/behavior/ElytraBehavior.java | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3f056d7e6..6a7e98f83 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -792,15 +792,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Pair solvePitch(final SolverContext context, final Vec3d goalDelta, final int relaxation, final boolean ignoreLava) { final boolean desperate = relaxation == 2; - final int steps = desperate ? 3 : context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value; + final int ticks = desperate ? 3 : context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value; + final int ticksBoosted = context.boost.isBoosted() ? ticks : 0; - final Float pitch = this.solvePitch(context, goalDelta, steps, desperate, context.boost.isBoosted(), ignoreLava); + final Float pitch = this.solvePitch(context, goalDelta, ticks, ticksBoosted, desperate, ignoreLava); if (pitch != null) { return new Pair<>(pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - final Float usingFirework = this.solvePitch(context, goalDelta, steps, desperate, true, ignoreLava); + // Simulate as if we were boosted for the entire duration + final Float usingFirework = this.solvePitch(context, goalDelta, ticks, ticks, desperate, ignoreLava); if (usingFirework != null) { return new Pair<>(usingFirework, true); } @@ -809,8 +811,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new Pair<>(null, false); } - private Float solvePitch(final SolverContext context, final Vec3d goalDelta, final int steps, - final boolean desperate, final boolean firework, final boolean ignoreLava) { + private Float solvePitch(final SolverContext context, final Vec3d goalDelta, final int ticks, + final int ticksBoosted, final boolean desperate, final boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -830,8 +832,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H context.aimProcessor.fork(), goalDelta, pitch, - steps, - firework ? Integer.MAX_VALUE : 0, + ticks, + ticksBoosted, ignoreLava ); if (displacement == null) { From 02fc62f1c474b14553cc803eb912c519a8a1fd42 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 26 Jun 2023 18:37:06 -0500 Subject: [PATCH 127/276] Stop simulation when goal reached --- src/main/java/baritone/behavior/ElytraBehavior.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 6a7e98f83..abfad1ed9 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -854,7 +854,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, - final int ticks, int ticksBoosted, final boolean ignoreLava) { + final int ticks, int ticksBoosted, final boolean ignoreLava) { Vec3d delta = goalDelta; Vec3d motion = ctx.playerMotion(); AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); @@ -865,6 +865,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { return null; } + if (delta.lengthSquared() < 1) { + break; + } final Rotation rotation = aimProcessor.nextRotation( RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, delta, ctx.playerRotations()).withPitch(pitch) ); From 4ccaf681c5aae01e76892f340f0debc290327a11 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 27 Jun 2023 02:54:53 -0500 Subject: [PATCH 128/276] Somewhat functional `elytraAutoJump`, but mostly scuffed --- src/api/java/baritone/api/Settings.java | 1 + src/main/java/baritone/Baritone.java | 1 + .../baritone/behavior/ElytraBehavior.java | 177 +++++++++++++++++- 3 files changed, 171 insertions(+), 8 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 5ec5b6ed4..0842ac10a 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -58,6 +58,7 @@ public final class Settings { public final Setting renderHitboxRaytraces = new Setting<>(false); public final Setting renderElytraSimulation = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); +` public final Setting elytraAutoJump = new Setting<>(false); public final Setting smoothLook = new Setting<>(false); // Experimental Elytra Settings diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 5723cc422..dcbad33f5 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -121,6 +121,7 @@ public class Baritone implements IBaritone { this.farmProcess = this.registerProcess(FarmProcess::new); this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new); this.registerProcess(BackfillProcess::new); + this.registerProcess(__ -> this.elytraBehavior.new ElytraProcess()); // pain } this.worldProvider = new WorldProvider(this); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index abfad1ed9..1720cf24e 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -22,11 +22,19 @@ 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.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.utils.BlockStateInterface; import baritone.utils.accessor.IEntityFireworkRocket; import net.minecraft.block.material.Material; @@ -82,6 +90,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private int minimumBoostTicks; private BlockStateInterface bsi; + private BlockPos destination; private Future solver; private boolean solveNextTick; @@ -97,7 +106,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final class PathManager { - private BlockPos destination; private NetherPath path; private boolean completePath; private boolean recalculating; @@ -128,10 +136,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.attemptNextSegment(); } - public void pathToDestination(final BlockPos destination) { - this.destination = destination; + public void pathToDestination() { + this.pathToDestination(ctx.playerFeet()); + } + + public void pathToDestination(final BlockPos from) { final long start = System.nanoTime(); - this.path0(ctx.playerFeet(), destination, UnaryOperator.identity()) + this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity()) .thenRun(() -> { final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1)); if (this.completePath) { @@ -185,7 +196,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final List before = this.path.subList(0, afterIncl + 1); final long start = System.nanoTime(); - this.path0(this.path.get(afterIncl), this.destination, segment -> segment.prepend(before.stream())) + this.path0(this.path.get(afterIncl), ElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; final double distance = this.path.get(0).distanceTo(this.path.get(recompute)); @@ -210,7 +221,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } public void clear() { - this.destination = null; this.path = NetherPath.emptyPath(); this.completePath = true; this.recalculating = false; @@ -362,11 +372,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void pathTo(BlockPos destination) { - this.pathManager.pathToDestination(destination); + this.destination = destination; + if (!Baritone.settings().elytraAutoJump.value || ctx.player().isElytraFlying()) { + this.pathManager.pathToDestination(); + } } @Override public void cancel() { + this.destination = null; this.visiblePath = Collections.emptyList(); this.pathManager.clear(); this.aimPos = null; @@ -435,7 +449,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (!ctx.player().isElytraFlying()) { return; } - baritone.getInputOverrideHandler().clearAllKeys(); if (ctx.player().collidedHorizontally) { logDirect("hbonk"); @@ -987,4 +1000,152 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return !ctx.world().getBlockState(pos).isNormalCube() && !ctx.world().getBlockState(pos.up()).isNormalCube(); } } + + public final class ElytraProcess implements IBaritoneProcess { + + private State state; + private Goal goal; + + @Override + public boolean isActive() { + return ElytraBehavior.this.destination != null; + } + + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + if (calcFailed) { + onLostControl(); + logDirect("Failed to get to jump off spot, canceling"); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + if (ctx.player().isElytraFlying()) { + this.state = State.FLYING; + this.goal = null; + baritone.getInputOverrideHandler().clearAllKeys(); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + if (!Baritone.settings().elytraAutoJump.value) { + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + // 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.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())) { + this.state = State.START_FLYING; + } else { + return new PathingCommand(this.goal, 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); + } + } + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + @Override + public boolean isTemporary() { + return false; + } + + @Override + public void onLostControl() { + this.goal = null; + this.state = State.GET_TO_JUMP; + ElytraBehavior.this.cancel(); + } + + @Override + public double priority() { + return 10; + } + + @Override + public String displayName0() { + return "Elytra"; + } + + // ok... now this.. is disgusting + // TODO: make less scuffed + private BlockPos findJumpOffSpot() { + BlockPos best = null; + final BetterBlockPos feet = ctx.playerFeet(); + final List nearby = FasterWorldScanner.getChunkRange(feet.x >> 4, feet.z >> 4, 3); + for (ChunkPos pos : nearby) { + final Chunk chunk = ctx.world().getChunk(pos.x, pos.z); + int[][] obstruction = new int[16][16]; + for (int y0 = 0; y0 < 8; y0++) { + for (int z = 0; z < 16; z++) { + for (int x = 0; x < 16; x++) { + int y = feet.y - y0; + if (chunk.getBlockState(x, y, z).getMaterial() != Material.AIR) { + if (obstruction[x][z] == 0 || obstruction[x][z] > y0 + 1) { + obstruction[x][z] = y0 + 1; + } + } + } + } + } + for (int x = 0; x < 16; x++) { + for (int z = 0; z < 16; z++) { + if (obstruction[x][z] != 0) { + continue; + } + + 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(); + + 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; + } + } + + private enum State { + GET_TO_JUMP, + START_FLYING, + FLYING + } } From ff12832a216c1c7b74375601e2bb16fa19cb8fd8 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 27 Jun 2023 12:30:41 -0500 Subject: [PATCH 129/276] whoops --- src/api/java/baritone/api/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 0842ac10a..47643245d 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -58,7 +58,7 @@ public final class Settings { public final Setting renderHitboxRaytraces = new Setting<>(false); public final Setting renderElytraSimulation = new Setting<>(false); public final Setting elytraFreeLook = new Setting<>(false); -` public final Setting elytraAutoJump = new Setting<>(false); + public final Setting elytraAutoJump = new Setting<>(false); public final Setting smoothLook = new Setting<>(false); // Experimental Elytra Settings From 3b31387092a7fa6e05ad3b025d2e8c6e00eecb53 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 27 Jun 2023 13:02:01 -0500 Subject: [PATCH 130/276] Render simulation line from player pos --- .../java/baritone/utils/PathRenderer.java | 21 ++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index da2f69e7b..d09567914 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -111,25 +111,28 @@ public final class PathRenderer implements IRenderer { if (!elytra.clearLines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); for (Pair line : elytra.clearLines) { - emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); + emitLine(line.first(), line.second()); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } if (!elytra.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); for (Pair line : elytra.blockedLines) { - emitLine(line.first().x, line.first().y, line.first().z, line.second().x, line.second().y, line.second().z); + emitLine(line.first(), line.second()); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } if (elytra.simulationLine != null && Baritone.settings().renderElytraSimulation.value) { IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + final Vec3d offset = new Vec3d( + ctx.player().prevPosX + (ctx.player().posX - ctx.player().prevPosX) * partialTicks, + ctx.player().prevPosY + (ctx.player().posY - ctx.player().prevPosY) * partialTicks, + ctx.player().prevPosZ + (ctx.player().posZ - ctx.player().prevPosZ) * partialTicks + ); for (int i = 0; i < elytra.simulationLine.size() - 1; i++) { - Vec3d src = elytra.simulationLine.get(i); - Vec3d dst = elytra.simulationLine.get(i + 1); - // Center line on viewer pos - buffer.pos(src.x, src.y, src.z).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(dst.x, dst.y, dst.z).color(color[0], color[1], color[2], color[3]).endVertex(); + final Vec3d src = elytra.simulationLine.get(i).add(offset); + final Vec3d dst = elytra.simulationLine.get(i + 1).add(offset); + emitLine(src, dst); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } @@ -194,6 +197,10 @@ public final class PathRenderer implements IRenderer { IRenderer.endLines(settings.renderPathIgnoreDepth.value); } + private static void emitLine(Vec3d start, Vec3d end) { + emitLine(start.x, start.y, start.z, end.x, end.y, end.z); + } + private static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) { double vpX = renderManager.viewerPosX; double vpY = renderManager.viewerPosY; From c48de3286025e54fb813f6133f0993c13c3a560d Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 27 Jun 2023 16:31:08 -0500 Subject: [PATCH 131/276] `PitchResult` --- .../baritone/behavior/ElytraBehavior.java | 45 +++++++++++-------- 1 file changed, 27 insertions(+), 18 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 1720cf24e..048a00e12 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -684,6 +684,19 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + private static final class PitchResult { + + public final float pitch; + public final double dot; + public final List steps; + + public PitchResult(float pitch, double dot, List steps) { + this.pitch = pitch; + this.dot = dot; + this.steps = steps; + } + } + private static final class Solution { public final SolverContext context; @@ -808,24 +821,24 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final int ticks = desperate ? 3 : context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value; final int ticksBoosted = context.boost.isBoosted() ? ticks : 0; - final Float pitch = this.solvePitch(context, goalDelta, ticks, ticksBoosted, desperate, ignoreLava); + final PitchResult pitch = this.solvePitch(context, goalDelta, ticks, ticksBoosted, desperate, ignoreLava); if (pitch != null) { - return new Pair<>(pitch, false); + return new Pair<>(pitch.pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { // Simulate as if we were boosted for the entire duration - final Float usingFirework = this.solvePitch(context, goalDelta, ticks, ticks, desperate, ignoreLava); + final PitchResult usingFirework = this.solvePitch(context, goalDelta, ticks, ticks, desperate, ignoreLava); if (usingFirework != null) { - return new Pair<>(usingFirework, true); + return new Pair<>(usingFirework.pitch, true); } } return new Pair<>(null, false); } - private Float solvePitch(final SolverContext context, final Vec3d goalDelta, final int ticks, - final int ticksBoosted, final boolean desperate, final boolean ignoreLava) { + private PitchResult solvePitch(final SolverContext context, final Vec3d goalDelta, final int ticks, + final int ticksBoosted, final boolean desperate, final boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -833,9 +846,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Vec3d goalDirection = goalDelta.normalize(); final float goodPitch = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()).getPitch(); - Float bestPitch = null; - double bestDot = Double.NEGATIVE_INFINITY; - List bestLine = null; + PitchResult result = null; final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); @@ -852,18 +863,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (displacement == null) { continue; } - final Vec3d result = displacement.get(displacement.size() - 1); - double goodness = goalDirection.dotProduct(result.normalize()); - if (goodness > bestDot) { - bestDot = goodness; - bestPitch = pitch; - bestLine = displacement; + final Vec3d last = displacement.get(displacement.size() - 1); + double goodness = goalDirection.dotProduct(last.normalize()); + if (result == null || goodness > result.dot) { + result = new PitchResult(pitch, goodness, displacement); } } - if (bestLine != null) { - this.simulationLine = bestLine; + if (result != null) { + this.simulationLine = result.steps; } - return bestPitch; + return result; } private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, From 03ee30bca90dd090acd0499754fbdc2728d8f0b2 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 00:46:14 -0500 Subject: [PATCH 132/276] Call elytra `tick()` from the process --- .../java/baritone/api/behavior/IBehavior.java | 8 +++++- src/main/java/baritone/Baritone.java | 8 +++++- .../baritone/behavior/ElytraBehavior.java | 27 +++++++++++++++---- 3 files changed, 36 insertions(+), 7 deletions(-) diff --git a/src/api/java/baritone/api/behavior/IBehavior.java b/src/api/java/baritone/api/behavior/IBehavior.java index 811563b93..aea44ed3e 100644 --- a/src/api/java/baritone/api/behavior/IBehavior.java +++ b/src/api/java/baritone/api/behavior/IBehavior.java @@ -27,4 +27,10 @@ import baritone.api.event.listener.IGameEventListener; * @see IGameEventListener * @since 9/23/2018 */ -public interface IBehavior extends AbstractGameEventListener {} +public interface IBehavior extends AbstractGameEventListener { + + /** + * Called after Baritone's initialization is complete + */ + default void onLoad() {} +} diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index dcbad33f5..313725c4e 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -40,6 +40,8 @@ import net.minecraft.client.Minecraft; import java.io.IOException; import java.nio.file.Files; import java.nio.file.Path; +import java.util.ArrayList; +import java.util.List; import java.util.concurrent.Executor; import java.util.concurrent.SynchronousQueue; import java.util.concurrent.ThreadPoolExecutor; @@ -63,6 +65,7 @@ public class Baritone implements IBaritone { private final GameEventHandler gameEventHandler; + private final List behaviors; private final PathingBehavior pathingBehavior; private final ElytraBehavior elytraBehavior; private final LookBehavior lookBehavior; @@ -89,6 +92,7 @@ public class Baritone implements IBaritone { Baritone(Minecraft mc) { this.mc = mc; + this.behaviors = new ArrayList<>(); this.gameEventHandler = new GameEventHandler(this); this.directory = mc.gameDir.toPath().resolve("baritone"); @@ -121,15 +125,17 @@ public class Baritone implements IBaritone { this.farmProcess = this.registerProcess(FarmProcess::new); this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new); this.registerProcess(BackfillProcess::new); - this.registerProcess(__ -> this.elytraBehavior.new ElytraProcess()); // pain } this.worldProvider = new WorldProvider(this); this.selectionManager = new SelectionManager(this); this.commandManager = new CommandManager(this); + + this.behaviors.forEach(IBehavior::onLoad); } public void registerBehavior(IBehavior behavior) { + this.behaviors.add(behavior); this.gameEventHandler.registerEventListener(behavior); } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 048a00e12..759d4b0bc 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -71,6 +71,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private final NetherPathfinderContext context; private final PathManager pathManager; + private final ElytraProcess process; /** * Remaining cool-down ticks between firework usage @@ -93,6 +94,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private BlockPos destination; private Future solver; + private Solution pendingSolution; private boolean solveNextTick; public ElytraBehavior(Baritone baritone) { @@ -102,6 +104,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.blockedLines = new CopyOnWriteArrayList<>(); this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); + this.process = new ElytraProcess(); + } + + @Override + public void onLoad() { + baritone.getPathingControlManager().registerProcess(this.process); } private final class PathManager { @@ -398,16 +406,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } @Override - public void onTick(TickEvent event) { + public void onTick(final TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { return; } // Fetch the previous solution, regardless of if it's going to be used - Solution solution = null; + this.pendingSolution = null; if (this.solver != null) { try { - solution = this.solver.get(); + this.pendingSolution = this.solver.get(); } catch (Exception ignored) { // it doesn't matter if get() fails since the solution can just be recalculated synchronously } finally { @@ -431,7 +439,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.blockedLines.clear(); this.simulationLine = null; this.aimPos = null; + } + /** + * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control + */ + private void tick() { final List path = this.pathManager.getPath(); if (path.isEmpty()) { return; @@ -461,8 +474,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.solveNextTick = true; // If there's no previously calculated solution to use, or the context used at the end of last tick doesn't match this tick - if (solution == null || !solution.context.equals(solverContext)) { + final Solution solution; + if (this.pendingSolution == null || !this.pendingSolution.context.equals(solverContext)) { solution = this.solveAngles(solverContext); + } else { + solution = this.pendingSolution; } if (solution == null) { @@ -1010,7 +1026,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - public final class ElytraProcess implements IBaritoneProcess { + private final class ElytraProcess implements IBaritoneProcess { private State state; private Goal goal; @@ -1032,6 +1048,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.state = State.FLYING; this.goal = null; baritone.getInputOverrideHandler().clearAllKeys(); + ElytraBehavior.this.tick(); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } From 70166f385db5e333fe2b9407ea62345225b388d9 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 00:47:20 -0500 Subject: [PATCH 133/276] That should be in the other tick method --- .../java/baritone/behavior/ElytraBehavior.java | 14 +++++--------- 1 file changed, 5 insertions(+), 9 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 759d4b0bc..3cb5c2f12 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -439,12 +439,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.blockedLines.clear(); this.simulationLine = null; this.aimPos = null; - } - /** - * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control - */ - private void tick() { final List path = this.pathManager.getPath(); if (path.isEmpty()) { return; @@ -458,11 +453,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Math.max(playerNear - 30, 0), Math.min(playerNear + 100, path.size()) ); + } - if (!ctx.player().isElytraFlying()) { - return; - } - + /** + * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control + */ + private void tick() { if (ctx.player().collidedHorizontally) { logDirect("hbonk"); } From 7861860187a34e65f6acffd3f4286dbd9d82080f Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 00:48:28 -0500 Subject: [PATCH 134/276] Clarify --- src/main/java/baritone/behavior/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3cb5c2f12..a118d5fbc 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -456,7 +456,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } /** - * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control + * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control and the player is flying */ private void tick() { if (ctx.player().collidedHorizontally) { From 7a61ab813742cbef4b09a634681e385d16f03d5c Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 00:58:51 -0500 Subject: [PATCH 135/276] We need event priorities. --- src/main/java/baritone/Baritone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 313725c4e..805fb0488 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -107,8 +107,8 @@ public class Baritone implements IBaritone { { this.lookBehavior = this.registerBehavior(LookBehavior::new); - this.pathingBehavior = this.registerBehavior(PathingBehavior::new); this.elytraBehavior = this.registerBehavior(ElytraBehavior::new); + this.pathingBehavior = this.registerBehavior(PathingBehavior::new); this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new); this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new); this.registerBehavior(WaypointBehavior::new); From bb39fea4151fa16c3c0d5b5d85c701aba251f8a2 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 01:04:08 -0500 Subject: [PATCH 136/276] Considerations --- src/main/java/baritone/behavior/ElytraBehavior.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index a118d5fbc..82045c7bc 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -459,6 +459,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control and the player is flying */ private void tick() { + if (this.pathManager.getPath().isEmpty()) { + return; + } + if (ctx.player().collidedHorizontally) { logDirect("hbonk"); } @@ -506,6 +510,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // changed. Updating it now will avoid unnecessary recalculation on the main thread. this.pathManager.updatePlayerNear(); + // TODO: If we used a firework at the end of the last tick, then it's worth it to solve with the assumption + // that we'll be boosted next tick (if our ping to the server is less than 50ms) since a recalc won't + // be needed on the main thread. final SolverContext context = this.new SolverContext(true); this.solver = CompletableFuture.supplyAsync(() -> this.solveAngles(context)); this.solveNextTick = false; From 0bb6f1b094a0151f375ce06e0f78564eee1531d4 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 01:05:22 -0500 Subject: [PATCH 137/276] Invalidate `pendingSolution` --- src/main/java/baritone/behavior/ElytraBehavior.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 82045c7bc..7e328bfd4 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -398,6 +398,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.solver.cancel(true); this.solver = null; } + this.pendingSolution = null; } @Override From d640ebb02d8df07e1c12a30c8adfe4af1179b6e3 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 17:47:01 -0500 Subject: [PATCH 138/276] Reliability improvements --- .../baritone/behavior/ElytraBehavior.java | 212 +++++++++++++----- 1 file changed, 156 insertions(+), 56 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 7e328bfd4..b4b119921 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -37,6 +37,8 @@ import baritone.behavior.elytra.UnpackedSegment; import baritone.cache.FasterWorldScanner; import baritone.utils.BlockStateInterface; import baritone.utils.accessor.IEntityFireworkRocket; +import it.unimi.dsi.fastutil.floats.FloatArrayList; +import it.unimi.dsi.fastutil.floats.FloatIterator; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -52,6 +54,7 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; +import java.util.function.Supplier; import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -530,57 +533,84 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) int[] heights = context.boost.isBoosted() ? new int[]{20, 10, 5, 0} : new int[]{0}; // attempt to gain height, if we can, so as not to waste the boost - float[] interps = new float[] {1.0f, 0.75f, 0.5f, 0.25f}; int lookahead = relaxation == 0 ? 2 : 3; // ideally this would be expressed as a distance in blocks, rather than a number of voxel steps //int minStep = Math.max(0, playerNear - relaxation); int minStep = playerNear; + for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { + final List> candidates = new ArrayList<>(); for (int dy : heights) { - for (float interp : interps) { - Vec3d dest; - if (interp == 1 || i == minStep) { - dest = path.getVec(i); + if (i == minStep) { + // no interp + candidates.add(new Pair<>(path.getVec(i).add(0, dy, 0), dy)); + } else { + if (relaxation == 2) { + final Vec3d delta = path.getVec(i).subtract(path.getVec(i - 1)); + final double stepLength = 0.5; + final int steps = MathHelper.floor(delta.length() / stepLength); + final Vec3d step = delta.normalize().scale(stepLength); + + Vec3d stepped = path.getVec(i); + for (int interp = 0; interp < steps; interp++) { + candidates.add(new Pair<>(stepped.add(0, dy, 0), dy)); + stepped = stepped.subtract(step); + } } else { - dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); + final float[] interps = relaxation == 0 + ? new float[]{1.0f, 0.75f, 0.5f, 0.25f} + : new float[]{1.0f, 0.875f, 0.75f, 0.625f, 0.5f, 0.375f, 0.25f, 0.125f}; + for (float interp : interps) { + Vec3d dest; + if (interp == 1) { + dest = path.getVec(i); + } else { + dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); + } + candidates.add(new Pair<>(dest.add(0, dy, 0), dy)); + } } + } + } - dest = dest.add(0, dy, 0); - if (dy != 0) { - if (i + lookahead >= path.size()) { + for (final Pair candidate : candidates) { + final Vec3d dest = candidate.first(); + final Integer augment = candidate.second(); + + if (augment != 0) { + if (i + lookahead >= path.size()) { + continue; + } + if (start.distanceTo(dest) < 40) { + if (!this.clearView(dest, path.getVec(i + lookahead).add(0, augment, 0), false) + || !this.clearView(dest, path.getVec(i + lookahead), false)) { + // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position continue; } - if (start.distanceTo(dest) < 40) { - if (!this.clearView(dest, path.getVec(i + lookahead).add(0, dy, 0), false) - || !this.clearView(dest, path.getVec(i + lookahead), false)) { - // aka: don't go upwards if doing so would prevent us from being able to see the next position **OR** the modified next position - continue; - } - } else { - // but if it's far away, allow gaining altitude if we could lose it again by the time we get there - if (!this.clearView(dest, path.getVec(i), false)) { - continue; - } - } - } - - final double minAvoidance = Baritone.settings().elytraMinimumAvoidance.value; - final Double growth = relaxation == 2 ? null - : relaxation == 0 ? 2 * minAvoidance : minAvoidance; - - if (this.isHitboxClear(start, dest, growth, isInLava)) { - // Yaw is trivial, just calculate the rotation required to face the destination - final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - - final Pair pitch = this.solvePitch(context, dest.subtract(start), relaxation, isInLava); - if (pitch.first() == null) { - solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); + } else { + // but if it's far away, allow gaining altitude if we could lose it again by the time we get there + if (!this.clearView(dest, path.getVec(i), false)) { continue; } - - // A solution was found with yaw AND pitch, so just immediately return it. - return new Solution(context, new Rotation(yaw, pitch.first()), dest, true, pitch.second()); } } + + final double minAvoidance = Baritone.settings().elytraMinimumAvoidance.value; + final Double growth = relaxation == 2 ? null + : relaxation == 0 ? 2 * minAvoidance : minAvoidance; + + if (this.isHitboxClear(start, dest, growth, isInLava)) { + // Yaw is trivial, just calculate the rotation required to face the destination + final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); + + final Pair pitch = this.solvePitch(context, dest, relaxation, isInLava); + if (pitch == null) { + solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); + continue; + } + + // A solution was found with yaw AND pitch, so just immediately return it. + return new Solution(context, new Rotation(yaw, pitch.first()), dest, true, pitch.second()); + } } } } @@ -680,10 +710,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.firework != null; } + /** + * @return The guaranteed number of remaining ticks with boost + */ public int getGuaranteedBoostTicks() { return this.isBoosted() ? Math.max(0, this.minimumBoostTicks - this.firework.ticksExisted) : 0; } + /** + * @return The maximum number of remaining ticks with boost + */ public int getMaximumBoostTicks() { return this.isBoosted() ? Math.max(0, this.maximumBoostTicks - this.firework.ticksExisted) : 0; } @@ -835,43 +871,92 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(final SolverContext context, final Vec3d goalDelta, - final int relaxation, final boolean ignoreLava) { - final boolean desperate = relaxation == 2; - final int ticks = desperate ? 3 : context.boost.isBoosted() ? 5 : Baritone.settings().elytraSimulationTicks.value; - final int ticksBoosted = context.boost.isBoosted() ? ticks : 0; + @FunctionalInterface + private interface IntBiFunction { + T apply(int left, int right); + } - final PitchResult pitch = this.solvePitch(context, goalDelta, ticks, ticksBoosted, desperate, ignoreLava); - if (pitch != null) { - return new Pair<>(pitch.pitch, false); + private static FloatArrayList pitchesToSolveFor(final float goodPitch, final boolean desperate) { + final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); + final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); + + final FloatArrayList pitchValues = new FloatArrayList(MathHelper.ceil(maxPitch - minPitch) + 1); + for (float pitch = goodPitch; pitch <= maxPitch; pitch++) { + pitchValues.add(pitch); + } + for (float pitch = goodPitch - 1; pitch >= minPitch; pitch--) { + pitchValues.add(pitch); + } + + return pitchValues; + } + + private Pair solvePitch(final SolverContext context, final Vec3d goal, + final int relaxation, final boolean ignoreLava) { + + final boolean desperate = relaxation == 2; + final float goodPitch = RotationUtils.calcRotationFromVec3d(context.start, goal, ctx.playerRotations()).getPitch(); + final FloatArrayList pitches = pitchesToSolveFor(goodPitch, desperate); + + final IntBiFunction solve = (ticks, ticksBoosted) -> + this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ignoreLava); + + final List> tests = new ArrayList<>(); + + if (context.boost.isBoosted()) { + final int guaranteed = context.boost.getGuaranteedBoostTicks(); + if (guaranteed == 0) { + // uncertain when boost will run out + final int lookahead = Math.max(4, 10 - context.boost.getMaximumBoostTicks()); + tests.add(() -> solve.apply(lookahead, 1)); + tests.add(() -> solve.apply(5, 5)); + } else if (guaranteed <= 5) { + // boost will run out within 5 ticks + tests.add(() -> solve.apply(guaranteed + 5, guaranteed)); + } else { + // there's plenty of guaranteed boost + tests.add(() -> solve.apply(guaranteed + 1, guaranteed)); + } + } + + // Standard test, assume (not) boosted for entire duration + final int ticks = desperate ? 3 : context.boost.isBoosted() ? Math.max(5, context.boost.getGuaranteedBoostTicks()) : Baritone.settings().elytraSimulationTicks.value; + tests.add(() -> solve.apply(ticks, context.boost.isBoosted() ? ticks : 0)); + + final Optional result = tests.stream() + .map(Supplier::get) + .filter(Objects::nonNull) + .findFirst(); + if (result.isPresent()) { + return new Pair<>(result.get().pitch, false); } if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { // Simulate as if we were boosted for the entire duration - final PitchResult usingFirework = this.solvePitch(context, goalDelta, ticks, ticks, desperate, ignoreLava); + final PitchResult usingFirework = solve.apply(ticks, ticks); if (usingFirework != null) { return new Pair<>(usingFirework.pitch, true); } } - return new Pair<>(null, false); + return null; } - private PitchResult solvePitch(final SolverContext context, final Vec3d goalDelta, final int ticks, - final int ticksBoosted, final boolean desperate, final boolean ignoreLava) { + private PitchResult solvePitch(final SolverContext context, final Vec3d goal, final int relaxation, + final FloatIterator pitches, final int ticks, final int ticksBoosted, + final boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch + final Vec3d goalDelta = goal.subtract(context.start); final Vec3d goalDirection = goalDelta.normalize(); - final float goodPitch = RotationUtils.calcRotationFromVec3d(Vec3d.ZERO, goalDirection, ctx.playerRotations()).getPitch(); PitchResult result = null; - final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); - final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); - - for (float pitch = minPitch; pitch <= maxPitch; pitch++) { + outer: + while (pitches.hasNext()) { + final float pitch = pitches.nextFloat(); final List displacement = this.simulate( context.aimProcessor.fork(), goalDelta, @@ -883,9 +968,24 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (displacement == null) { continue; } - final Vec3d last = displacement.get(displacement.size() - 1); - double goodness = goalDirection.dotProduct(last.normalize()); + final int lastIndex = displacement.size() - 1; + final Vec3d last = displacement.get(lastIndex); + final double goodness = goalDirection.dotProduct(last.normalize()); if (result == null || goodness > result.dot) { + if (relaxation == 0) { + // Ensure that the goal is visible along the entire simulated path + // Reverse order iteration since the last position is most likely to fail + for (int i = lastIndex; i >= 1; i--) { + if (!clearView(context.start.add(displacement.get(i)), goal, false)) { + continue outer; + } + } + } else if (relaxation == 1) { + // Ensure that the goal is visible from the final position + if (!clearView(context.start.add(last), goal, false)) { + continue; + } + } result = new PitchResult(pitch, goodness, displacement); } } From 5126ec9c36b0ea47cbef6d0d344a05b4565b9fbc Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 17:49:33 -0500 Subject: [PATCH 139/276] interp double --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b4b119921..9bdb255ee 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -556,10 +556,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H stepped = stepped.subtract(step); } } else { - final float[] interps = relaxation == 0 - ? new float[]{1.0f, 0.75f, 0.5f, 0.25f} - : new float[]{1.0f, 0.875f, 0.75f, 0.625f, 0.5f, 0.375f, 0.25f, 0.125f}; - for (float interp : interps) { + final double[] interps = relaxation == 0 + ? new double[]{1.0, 0.75, 0.5, 0.25} + : new double[]{1.0, 0.875, 0.75, 0.625, 0.5, 0.375, 0.25, 0.125}; + for (double interp : interps) { Vec3d dest; if (interp == 1) { dest = path.getVec(i); From 4b689bd9462d29e34f7b7af59e203fbfdaeb97ee Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 17:55:47 -0500 Subject: [PATCH 140/276] Fix `Supplier` meme --- .../baritone/behavior/ElytraBehavior.java | 34 ++++++++++++------- 1 file changed, 22 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 9bdb255ee..c2df278a4 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -871,11 +871,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - @FunctionalInterface - private interface IntBiFunction { - T apply(int left, int right); - } - private static FloatArrayList pitchesToSolveFor(final float goodPitch, final boolean desperate) { final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); @@ -891,6 +886,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return pitchValues; } + @FunctionalInterface + private interface IntBiFunction { + T apply(int left, int right); + } + + private static final class IntPair { + public final int first; + public final int second; + + public IntPair(int first, int second) { + this.first = first; + this.second = second; + } + } + private Pair solvePitch(final SolverContext context, final Vec3d goal, final int relaxation, final boolean ignoreLava) { @@ -901,30 +911,30 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final IntBiFunction solve = (ticks, ticksBoosted) -> this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ignoreLava); - final List> tests = new ArrayList<>(); + final List tests = new ArrayList<>(); if (context.boost.isBoosted()) { final int guaranteed = context.boost.getGuaranteedBoostTicks(); if (guaranteed == 0) { // uncertain when boost will run out final int lookahead = Math.max(4, 10 - context.boost.getMaximumBoostTicks()); - tests.add(() -> solve.apply(lookahead, 1)); - tests.add(() -> solve.apply(5, 5)); + tests.add(new IntPair(lookahead, 1)); + tests.add(new IntPair(5, 5)); } else if (guaranteed <= 5) { // boost will run out within 5 ticks - tests.add(() -> solve.apply(guaranteed + 5, guaranteed)); + tests.add(new IntPair(guaranteed + 5, guaranteed)); } else { // there's plenty of guaranteed boost - tests.add(() -> solve.apply(guaranteed + 1, guaranteed)); + tests.add(new IntPair(guaranteed + 1, guaranteed)); } } // Standard test, assume (not) boosted for entire duration final int ticks = desperate ? 3 : context.boost.isBoosted() ? Math.max(5, context.boost.getGuaranteedBoostTicks()) : Baritone.settings().elytraSimulationTicks.value; - tests.add(() -> solve.apply(ticks, context.boost.isBoosted() ? ticks : 0)); + tests.add(new IntPair(ticks, context.boost.isBoosted() ? ticks : 0)); final Optional result = tests.stream() - .map(Supplier::get) + .map(i -> solve.apply(i.first, i.second)) .filter(Objects::nonNull) .findFirst(); if (result.isPresent()) { From 48462da47373eab1a04cdd5f5927ac6698b263a1 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 28 Jun 2023 21:47:37 -0500 Subject: [PATCH 141/276] Disable interp on relaxation 0 --- .../baritone/behavior/ElytraBehavior.java | 46 +++++++++---------- 1 file changed, 22 insertions(+), 24 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c2df278a4..5d1f51e00 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -540,34 +540,32 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { final List> candidates = new ArrayList<>(); for (int dy : heights) { - if (i == minStep) { + if (relaxation == 0 || i == minStep) { // no interp candidates.add(new Pair<>(path.getVec(i).add(0, dy, 0), dy)); + } else if (relaxation == 1) { + // Create 4 points along the segment + final double[] interps = new double[]{1.0, 0.75, 0.5, 0.25}; + for (double interp : interps) { + Vec3d dest; + if (interp == 1) { + dest = path.getVec(i); + } else { + dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); + } + candidates.add(new Pair<>(dest.add(0, dy, 0), dy)); + } } else { - if (relaxation == 2) { - final Vec3d delta = path.getVec(i).subtract(path.getVec(i - 1)); - final double stepLength = 0.5; - final int steps = MathHelper.floor(delta.length() / stepLength); - final Vec3d step = delta.normalize().scale(stepLength); + // Create a point along the segment every 0.5 blocks + final Vec3d delta = path.getVec(i).subtract(path.getVec(i - 1)); + final double stepLength = 0.5; + final int steps = MathHelper.floor(delta.length() / stepLength); + final Vec3d step = delta.normalize().scale(stepLength); - Vec3d stepped = path.getVec(i); - for (int interp = 0; interp < steps; interp++) { - candidates.add(new Pair<>(stepped.add(0, dy, 0), dy)); - stepped = stepped.subtract(step); - } - } else { - final double[] interps = relaxation == 0 - ? new double[]{1.0, 0.75, 0.5, 0.25} - : new double[]{1.0, 0.875, 0.75, 0.625, 0.5, 0.375, 0.25, 0.125}; - for (double interp : interps) { - Vec3d dest; - if (interp == 1) { - dest = path.getVec(i); - } else { - dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); - } - candidates.add(new Pair<>(dest.add(0, dy, 0), dy)); - } + Vec3d stepped = path.getVec(i).add(0, dy, 0); + for (int interp = 0; interp < steps; interp++) { + candidates.add(new Pair<>(stepped, dy)); + stepped = stepped.subtract(step); } } } From fbb66a0586ee70d7d59a6eebf234d23e59252835 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 14:14:49 -0500 Subject: [PATCH 142/276] Tweaks --- src/api/java/baritone/api/Settings.java | 3 - .../baritone/behavior/ElytraBehavior.java | 78 ++++++++++--------- 2 files changed, 43 insertions(+), 38 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 47643245d..679a29043 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -61,9 +61,6 @@ public final class Settings { public final Setting elytraAutoJump = new Setting<>(false); public final Setting smoothLook = new Setting<>(false); - // Experimental Elytra Settings - public final Setting experimentalTakeoff = new Setting<>(false); - /** * Allow Baritone to break blocks */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5d1f51e00..1479a9efe 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -54,7 +54,6 @@ import java.util.*; import java.util.concurrent.CompletableFuture; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Future; -import java.util.function.Supplier; import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -540,19 +539,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { final List> candidates = new ArrayList<>(); for (int dy : heights) { - if (relaxation == 0 || i == minStep) { + if (i == minStep) { // no interp candidates.add(new Pair<>(path.getVec(i).add(0, dy, 0), dy)); - } else if (relaxation == 1) { - // Create 4 points along the segment - final double[] interps = new double[]{1.0, 0.75, 0.5, 0.25}; + } else if (relaxation < 2) { + final double[] interps = relaxation == 0 + ? new double[]{1.0, 0.75, 0.5, 0.25} + : new double[]{1.0, 0.875, 0.75, 0.625, 0.5, 0.375, 0.25, 0.125}; for (double interp : interps) { - Vec3d dest; - if (interp == 1) { - dest = path.getVec(i); - } else { - dest = path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0d - interp)); - } + final Vec3d dest = interp == 1.0 + ? path.getVec(i) + : path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0 - interp)); candidates.add(new Pair<>(dest.add(0, dy, 0), dy)); } } else { @@ -641,7 +638,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H logDirect("no fireworks"); return; } - logDirect("attempting to use firework" + (forceUseFirework ? " takeoff" : "")); + logDirect("attempting to use firework" + (forceUseFirework ? " (forced)" : "")); ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); this.minimumBoostTicks = 10 * (1 + getFireworkBoost(ctx.player().getHeldItemMainhand()).orElse(0)); this.remainingFireworkTicks = 10; @@ -885,17 +882,19 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } @FunctionalInterface - private interface IntBiFunction { - T apply(int left, int right); + private interface IntTriFunction { + T apply(int first, int second, int third); } - private static final class IntPair { + private static final class IntTriple { public final int first; public final int second; + public final int third; - public IntPair(int first, int second) { + public IntTriple(int first, int second, int third) { this.first = first; this.second = second; + this.third = third; } } @@ -906,44 +905,52 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final float goodPitch = RotationUtils.calcRotationFromVec3d(context.start, goal, ctx.playerRotations()).getPitch(); final FloatArrayList pitches = pitchesToSolveFor(goodPitch, desperate); - final IntBiFunction solve = (ticks, ticksBoosted) -> - this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ignoreLava); + final IntTriFunction solve = (ticks, ticksBoosted, ticksBoostDelay) -> + this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ticksBoostDelay, ignoreLava); - final List tests = new ArrayList<>(); + final List tests = new ArrayList<>(); if (context.boost.isBoosted()) { final int guaranteed = context.boost.getGuaranteedBoostTicks(); if (guaranteed == 0) { // uncertain when boost will run out final int lookahead = Math.max(4, 10 - context.boost.getMaximumBoostTicks()); - tests.add(new IntPair(lookahead, 1)); - tests.add(new IntPair(5, 5)); + tests.add(new IntTriple(lookahead, 1, 0)); + tests.add(new IntTriple(5, 5, 0)); } else if (guaranteed <= 5) { // boost will run out within 5 ticks - tests.add(new IntPair(guaranteed + 5, guaranteed)); + tests.add(new IntTriple(guaranteed + 5, guaranteed, 0)); } else { // there's plenty of guaranteed boost - tests.add(new IntPair(guaranteed + 1, guaranteed)); + tests.add(new IntTriple(guaranteed + 1, guaranteed, 0)); } } // Standard test, assume (not) boosted for entire duration final int ticks = desperate ? 3 : context.boost.isBoosted() ? Math.max(5, context.boost.getGuaranteedBoostTicks()) : Baritone.settings().elytraSimulationTicks.value; - tests.add(new IntPair(ticks, context.boost.isBoosted() ? ticks : 0)); + tests.add(new IntTriple(ticks, context.boost.isBoosted() ? ticks : 0, 0)); final Optional result = tests.stream() - .map(i -> solve.apply(i.first, i.second)) + .map(i -> solve.apply(i.first, i.second, i.third)) .filter(Objects::nonNull) .findFirst(); if (result.isPresent()) { return new Pair<>(result.get().pitch, false); } - if (Baritone.settings().experimentalTakeoff.value && relaxation > 0) { - // Simulate as if we were boosted for the entire duration - final PitchResult usingFirework = solve.apply(ticks, ticks); - if (usingFirework != null) { - return new Pair<>(usingFirework.pitch, true); + // If we used a firework would we be able to get out of the current situation??? perhaps + if (relaxation > 0) { + final List testsBoost = new ArrayList<>(); + testsBoost.add(new IntTriple(ticks, 10, 3)); + testsBoost.add(new IntTriple(ticks, 10, 2)); + testsBoost.add(new IntTriple(ticks, 10, 1)); + + final Optional resultBoost = testsBoost.stream() + .map(i -> solve.apply(i.first, i.second, i.third)) + .filter(Objects::nonNull) + .findFirst(); + if (resultBoost.isPresent()) { + return new Pair<>(resultBoost.get().pitch, true); } } @@ -952,7 +959,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private PitchResult solvePitch(final SolverContext context, final Vec3d goal, final int relaxation, final FloatIterator pitches, final int ticks, final int ticksBoosted, - final boolean ignoreLava) { + final int ticksBoostDelay, final boolean ignoreLava) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -971,6 +978,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H pitch, ticks, ticksBoosted, + ticksBoostDelay, ignoreLava ); if (displacement == null) { @@ -980,7 +988,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Vec3d last = displacement.get(lastIndex); final double goodness = goalDirection.dotProduct(last.normalize()); if (result == null || goodness > result.dot) { - if (relaxation == 0) { + if (relaxation < 2) { // Ensure that the goal is visible along the entire simulated path // Reverse order iteration since the last position is most likely to fail for (int i = lastIndex; i >= 1; i--) { @@ -988,7 +996,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H continue outer; } } - } else if (relaxation == 1) { + } else { // Ensure that the goal is visible from the final position if (!clearView(context.start.add(last), goal, false)) { continue; @@ -1004,7 +1012,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, - final int ticks, int ticksBoosted, final boolean ignoreLava) { + final int ticks, int ticksBoosted, final int ticksBoostDelay, final boolean ignoreLava) { Vec3d delta = goalDelta; Vec3d motion = ctx.playerMotion(); AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); @@ -1042,7 +1050,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H hitbox = hitbox.offset(motion); displacement.add(displacement.get(displacement.size() - 1).add(motion)); - if (ticksBoosted-- > 0) { + if (i >= ticksBoostDelay && ticksBoosted-- > 0) { // See EntityFireworkRocket motion = motion.add( lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, From 12898df2f1274b34bdf0954c4d2ec73b27e19f8f Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 14:46:04 -0500 Subject: [PATCH 143/276] Reduce main thread recalculations after using a firework --- .../baritone/behavior/ElytraBehavior.java | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 1479a9efe..26bb68445 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -97,6 +97,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Future solver; private Solution pendingSolution; + private boolean deployedFireworkLastTick; + private final int[] nextTickBoostCounter; private boolean solveNextTick; public ElytraBehavior(Baritone baritone) { @@ -107,6 +109,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); this.process = new ElytraProcess(); + this.nextTickBoostCounter = new int[2]; } @Override @@ -401,6 +404,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.solver = null; } this.pendingSolution = null; + this.nextTickBoostCounter[0] = 0; + this.nextTickBoostCounter[1] = 0; } @Override @@ -484,6 +489,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H solution = this.pendingSolution; } + if (this.deployedFireworkLastTick) { + this.nextTickBoostCounter[solverContext.boost.isBoosted() ? 1 : 0]++; + this.deployedFireworkLastTick = false; + } + if (solution == null) { logDirect("no solution"); return; @@ -642,6 +652,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ctx.playerController().processRightClick(ctx.player(), ctx.world(), EnumHand.MAIN_HAND); this.minimumBoostTicks = 10 * (1 + getFireworkBoost(ctx.player().getHeldItemMainhand()).orElse(0)); this.remainingFireworkTicks = 10; + this.deployedFireworkLastTick = true; } } @@ -657,10 +668,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.boost = new FireworkBoost( - ElytraBehavior.this.getAttachedFirework().orElse(null), - ElytraBehavior.this.minimumBoostTicks - ); + + final Integer fireworkTicksExisted; + if (async && ElytraBehavior.this.deployedFireworkLastTick) { + final int[] counter = ElytraBehavior.this.nextTickBoostCounter; + fireworkTicksExisted = counter[1] > counter[0] ? 0 : null; + } else { + fireworkTicksExisted = ElytraBehavior.this.getAttachedFirework().map(e -> e.ticksExisted).orElse(null); + } + this.boost = new FireworkBoost(fireworkTicksExisted, ElytraBehavior.this.minimumBoostTicks); ITickableAimProcessor aim = ElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); if (async) { @@ -689,12 +705,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private static final class FireworkBoost { - private final EntityFireworkRocket firework; + private final Integer fireworkTicksExisted; private final int minimumBoostTicks; private final int maximumBoostTicks; - public FireworkBoost(final EntityFireworkRocket firework, final int minimumBoostTicks) { - this.firework = firework; + public FireworkBoost(final Integer fireworkTicksExisted, final int minimumBoostTicks) { + this.fireworkTicksExisted = fireworkTicksExisted; // this.lifetime = 10 * i + this.rand.nextInt(6) + this.rand.nextInt(7); this.minimumBoostTicks = minimumBoostTicks; @@ -702,21 +718,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } public boolean isBoosted() { - return this.firework != null; + return this.fireworkTicksExisted != null; } /** * @return The guaranteed number of remaining ticks with boost */ public int getGuaranteedBoostTicks() { - return this.isBoosted() ? Math.max(0, this.minimumBoostTicks - this.firework.ticksExisted) : 0; + return this.isBoosted() ? Math.max(0, this.minimumBoostTicks - this.fireworkTicksExisted) : 0; } /** * @return The maximum number of remaining ticks with boost */ public int getMaximumBoostTicks() { - return this.isBoosted() ? Math.max(0, this.maximumBoostTicks - this.firework.ticksExisted) : 0; + return this.isBoosted() ? Math.max(0, this.maximumBoostTicks - this.fireworkTicksExisted) : 0; } @Override @@ -729,7 +745,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } FireworkBoost other = (FireworkBoost) o; - return Objects.equals(this.firework, other.firework) + if (!this.isBoosted() && !other.isBoosted()) { + return true; + } + + return Objects.equals(this.fireworkTicksExisted, other.fireworkTicksExisted) && this.minimumBoostTicks == other.minimumBoostTicks && this.maximumBoostTicks == other.maximumBoostTicks; } From 222f53b105d007b74b4bf8a46b372c22cea860f4 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 14:46:42 -0500 Subject: [PATCH 144/276] Use `Arrays.fill` --- src/main/java/baritone/behavior/ElytraBehavior.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 26bb68445..da54fbb4f 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -404,8 +404,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.solver = null; } this.pendingSolution = null; - this.nextTickBoostCounter[0] = 0; - this.nextTickBoostCounter[1] = 0; + Arrays.fill(this.nextTickBoostCounter, 0); } @Override From 494ebfa10dd8fb7a0793a8cdd936198916334671 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 14:53:12 -0500 Subject: [PATCH 145/276] More accurate `isActive` return value --- src/main/java/baritone/behavior/ElytraBehavior.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index da54fbb4f..d7082074e 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -409,7 +409,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public boolean isActive() { - return !this.pathManager.getPath().isEmpty(); + return baritone.getPathingControlManager().mostRecentInControl() + .filter(process -> this.process == process).isPresent(); } @Override From f30cb916bd38541ab9c267793e8a05e90cab5a5e Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 14:53:55 -0500 Subject: [PATCH 146/276] Remove addressed TODO --- src/main/java/baritone/behavior/ElytraBehavior.java | 3 --- 1 file changed, 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index d7082074e..ab403aa80 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -523,9 +523,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // changed. Updating it now will avoid unnecessary recalculation on the main thread. this.pathManager.updatePlayerNear(); - // TODO: If we used a firework at the end of the last tick, then it's worth it to solve with the assumption - // that we'll be boosted next tick (if our ping to the server is less than 50ms) since a recalc won't - // be needed on the main thread. final SolverContext context = this.new SolverContext(true); this.solver = CompletableFuture.supplyAsync(() -> this.solveAngles(context)); this.solveNextTick = false; From 974b86aac1c9db64eb573ceb78ec4be27dc927ec Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 18:50:29 -0500 Subject: [PATCH 147/276] Bump `nether-pathfinder` to 0.20 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 41a495f4f..58929d98b 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.18') + launchImplementation('dev.babbaj:nether-pathfinder:0.20') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.18' + implementation 'dev.babbaj:nether-pathfinder:0.20' } mixin { From 5a48f4119e602fea947861ba5b7dc2ed7faceb49 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 19:15:06 -0500 Subject: [PATCH 148/276] Reduce number of raytraces when validating simulation --- .../baritone/behavior/ElytraBehavior.java | 74 +++++++++---------- 1 file changed, 36 insertions(+), 38 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index ab403aa80..3318e105a 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -546,27 +546,23 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) { final List> candidates = new ArrayList<>(); for (int dy : heights) { - if (i == minStep) { + if (relaxation == 0 || i == minStep) { // no interp - candidates.add(new Pair<>(path.getVec(i).add(0, dy, 0), dy)); - } else if (relaxation < 2) { - final double[] interps = relaxation == 0 - ? new double[]{1.0, 0.75, 0.5, 0.25} - : new double[]{1.0, 0.875, 0.75, 0.625, 0.5, 0.375, 0.25, 0.125}; + candidates.add(new Pair<>(path.getVec(i), dy)); + } else if (relaxation == 1) { + final double[] interps = new double[]{1.0, 0.75, 0.5, 0.25}; for (double interp : interps) { final Vec3d dest = interp == 1.0 ? path.getVec(i) : path.getVec(i).scale(interp).add(path.getVec(i - 1).scale(1.0 - interp)); - candidates.add(new Pair<>(dest.add(0, dy, 0), dy)); + candidates.add(new Pair<>(dest, dy)); } } else { - // Create a point along the segment every 0.5 blocks + // Create a point along the segment every block final Vec3d delta = path.getVec(i).subtract(path.getVec(i - 1)); - final double stepLength = 0.5; - final int steps = MathHelper.floor(delta.length() / stepLength); - final Vec3d step = delta.normalize().scale(stepLength); - - Vec3d stepped = path.getVec(i).add(0, dy, 0); + final int steps = MathHelper.floor(delta.length()); + final Vec3d step = delta.normalize(); + Vec3d stepped = path.getVec(i); for (int interp = 0; interp < steps; interp++) { candidates.add(new Pair<>(stepped, dy)); stepped = stepped.subtract(step); @@ -575,8 +571,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } for (final Pair candidate : candidates) { - final Vec3d dest = candidate.first(); final Integer augment = candidate.second(); + final Vec3d dest = candidate.first().add(0, augment, 0); if (augment != 0) { if (i + lookahead >= path.size()) { @@ -933,7 +929,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // uncertain when boost will run out final int lookahead = Math.max(4, 10 - context.boost.getMaximumBoostTicks()); tests.add(new IntTriple(lookahead, 1, 0)); - tests.add(new IntTriple(5, 5, 0)); } else if (guaranteed <= 5) { // boost will run out within 5 ticks tests.add(new IntTriple(guaranteed + 5, guaranteed, 0)); @@ -956,7 +951,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } // If we used a firework would we be able to get out of the current situation??? perhaps - if (relaxation > 0) { + if (desperate) { final List testsBoost = new ArrayList<>(); testsBoost.add(new IntTriple(ticks, 10, 3)); testsBoost.add(new IntTriple(ticks, 10, 2)); @@ -984,9 +979,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Vec3d goalDelta = goal.subtract(context.start); final Vec3d goalDirection = goalDelta.normalize(); - PitchResult result = null; + final Deque bestResults = new ArrayDeque<>(); - outer: while (pitches.hasNext()) { final float pitch = pitches.nextFloat(); final List displacement = this.simulate( @@ -1001,31 +995,35 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (displacement == null) { continue; } - final int lastIndex = displacement.size() - 1; - final Vec3d last = displacement.get(lastIndex); + final Vec3d last = displacement.get(displacement.size() - 1); final double goodness = goalDirection.dotProduct(last.normalize()); - if (result == null || goodness > result.dot) { - if (relaxation < 2) { - // Ensure that the goal is visible along the entire simulated path - // Reverse order iteration since the last position is most likely to fail - for (int i = lastIndex; i >= 1; i--) { - if (!clearView(context.start.add(displacement.get(i)), goal, false)) { - continue outer; - } - } - } else { - // Ensure that the goal is visible from the final position - if (!clearView(context.start.add(last), goal, false)) { - continue; - } - } - result = new PitchResult(pitch, goodness, displacement); + final PitchResult bestSoFar = bestResults.peek(); + if (bestSoFar == null || goodness > bestSoFar.dot) { + bestResults.push(new PitchResult(pitch, goodness, displacement)); } } - if (result != null) { + + outer: + for (final PitchResult result : bestResults) { + if (relaxation < 2) { + // Ensure that the goal is visible along the entire simulated path + // Reverse order iteration since the last position is most likely to fail + for (int i = result.steps.size() - 1; i >= 1; i--) { + if (!clearView(context.start.add(result.steps.get(i)), goal, false)) { + continue outer; + } + } + } else { + // Ensure that the goal is visible from the final position + if (!clearView(context.start.add(result.steps.get(result.steps.size() - 1)), goal, false)) { + continue; + } + } + this.simulationLine = result.steps; + return result; } - return result; + return null; } private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, From 3eb7610f8917eb5f30d25593341ea98435c41e79 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 20:45:59 -0500 Subject: [PATCH 149/276] Block lookup optimization --- .../baritone/behavior/ElytraBehavior.java | 42 +++++++++---------- 1 file changed, 21 insertions(+), 21 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3318e105a..192aa90b1 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -870,13 +870,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } - if (clear) { - this.clearLines.add(new Pair<>(start, dest)); - return true; - } else { - this.blockedLines.add(new Pair<>(start, dest)); - return false; + if (Baritone.settings().renderRaytraces.value) { + (clear ? this.clearLines : this.blockedLines).add(new Pair<>(start, dest)); } + return clear; } private static FloatArrayList pitchesToSolveFor(final float goodPitch, final boolean desperate) { @@ -1035,7 +1032,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H displacement.add(Vec3d.ZERO); for (int i = 0; i < ticks; i++) { - if (MC_1_12_Collision_Fix.bonk(ctx, hitbox)) { + if (MC_1_12_Collision_Fix.bonk(ctx, this.bsi, hitbox)) { return null; } if (delta.lengthSquared() < 1) { @@ -1132,32 +1129,35 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private static final class MC_1_12_Collision_Fix { - public static boolean bonk(final IPlayerContext ctx, final AxisAlignedBB aabb) { + public static boolean bonk(final IPlayerContext ctx, final BlockStateInterface bsi, final AxisAlignedBB aabb) { final Vec3d center = aabb.getCenter(); final double width = (double) ctx.player().width * 0.35D; final double x = center.x; final double y = aabb.minY + 0.5D; final double z = center.z; - return pushOutOfBlocks(ctx, x - width, y, z + width) - || pushOutOfBlocks(ctx, x - width, y, z - width) - || pushOutOfBlocks(ctx, x + width, y, z - width) - || pushOutOfBlocks(ctx, x + width, y, z + width); + return pushOutOfBlocks(bsi, x - width, y, z + width) + || pushOutOfBlocks(bsi, x - width, y, z - width) + || pushOutOfBlocks(bsi, x + width, y, z - width) + || pushOutOfBlocks(bsi, x + width, y, z + width); } - private static boolean pushOutOfBlocks(final IPlayerContext ctx, final double x, final double y, final double z) { - final BlockPos pos = new BlockPos(x, y, z); - if (isOpenBlockSpace(ctx, pos)) { + private static boolean pushOutOfBlocks(final BlockStateInterface bsi, + final double xIn, final double yIn, final double zIn) { + final int x = MathHelper.floor(xIn); + final int y = MathHelper.floor(yIn); + final int z = MathHelper.floor(zIn); + if (isOpenBlockSpace(bsi, x, y, z)) { return false; } - return isOpenBlockSpace(ctx, pos.west()) - || isOpenBlockSpace(ctx, pos.east()) - || isOpenBlockSpace(ctx, pos.north()) - || isOpenBlockSpace(ctx, pos.south()); + return isOpenBlockSpace(bsi, x - 1, y, z) + || isOpenBlockSpace(bsi, x + 1, y, z) + || isOpenBlockSpace(bsi, x, y, z - 1) + || isOpenBlockSpace(bsi, x, y, z + 1); } - private static boolean isOpenBlockSpace(IPlayerContext ctx, BlockPos pos) { - return !ctx.world().getBlockState(pos).isNormalCube() && !ctx.world().getBlockState(pos.up()).isNormalCube(); + private static boolean isOpenBlockSpace(BlockStateInterface bsi, final int x, final int y, final int z) { + return !bsi.get0(x, y, z).isNormalCube() && !bsi.get0(x, y + 1, z).isNormalCube(); } } From b8ede0a652d11aa578b7fea44679f03cc447ea4e Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 22:54:55 -0500 Subject: [PATCH 150/276] Remove unnecessary `IPlayerContext` argument --- src/main/java/baritone/behavior/ElytraBehavior.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 192aa90b1..12cb77a7a 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1032,7 +1032,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H displacement.add(Vec3d.ZERO); for (int i = 0; i < ticks; i++) { - if (MC_1_12_Collision_Fix.bonk(ctx, this.bsi, hitbox)) { + if (MC_1_12_Collision_Fix.bonk(this.bsi, hitbox)) { return null; } if (delta.lengthSquared() < 1) { @@ -1129,9 +1129,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private static final class MC_1_12_Collision_Fix { - public static boolean bonk(final IPlayerContext ctx, final BlockStateInterface bsi, final AxisAlignedBB aabb) { + public static boolean bonk(final BlockStateInterface bsi, final AxisAlignedBB aabb) { final Vec3d center = aabb.getCenter(); - final double width = (double) ctx.player().width * 0.35D; + final double width = (aabb.maxX - aabb.minX) * 0.35D; final double x = center.x; final double y = aabb.minY + 0.5D; final double z = center.z; From b4578931d3262af35a8dbb3cfb519fe197ef3591 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 22:59:15 -0500 Subject: [PATCH 151/276] Reduce passing around of `ignoreLava` --- .../baritone/behavior/ElytraBehavior.java | 24 ++++++++++--------- 1 file changed, 13 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 12cb77a7a..954755fa4 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -533,8 +533,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final NetherPath path = context.path; final int playerNear = context.playerNear; final Vec3d start = context.start; - - final boolean isInLava = ctx.player().isInLava(); Solution solution = null; for (int relaxation = 0; relaxation < 3; relaxation++) { // try for a strict solution first, then relax more and more (if we're in a corner or near some blocks, it will have to relax its constraints a bit) @@ -596,11 +594,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final Double growth = relaxation == 2 ? null : relaxation == 0 ? 2 * minAvoidance : minAvoidance; - if (this.isHitboxClear(start, dest, growth, isInLava)) { + if (this.isHitboxClear(context, dest, growth)) { // Yaw is trivial, just calculate the rotation required to face the destination final float yaw = RotationUtils.calcRotationFromVec3d(start, dest, ctx.playerRotations()).getYaw(); - final Pair pitch = this.solvePitch(context, dest, relaxation, isInLava); + final Pair pitch = this.solvePitch(context, dest, relaxation); if (pitch == null) { solution = new Solution(context, new Rotation(yaw, ctx.playerRotations().getPitch()), null, false, false); continue; @@ -654,6 +652,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final NetherPath path; public final int playerNear; public final Vec3d start; + public final boolean ignoreLava; public final FireworkBoost boost; public final IAimProcessor aimProcessor; @@ -661,6 +660,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); + this.ignoreLava = ElytraBehavior.this.ctx.player().isInLava(); final Integer fireworkTicksExisted; if (async && ElytraBehavior.this.deployedFireworkLastTick) { @@ -692,6 +692,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.path == other.path // Contents aren't modified, just compare by reference && this.playerNear == other.playerNear && Objects.equals(this.start, other.start) + && this.ignoreLava == other.ignoreLava && Objects.equals(this.boost, other.boost); } } @@ -809,7 +810,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .findFirst(); } - private boolean isHitboxClear(final Vec3d start, final Vec3d dest, final Double growAmount, boolean ignoreLava) { + private boolean isHitboxClear(final SolverContext context, final Vec3d dest, final Double growAmount) { + final Vec3d start = context.start; + final boolean ignoreLava = context.ignoreLava; + if (!this.clearView(start, dest, ignoreLava)) { return false; } @@ -908,15 +912,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private Pair solvePitch(final SolverContext context, final Vec3d goal, - final int relaxation, final boolean ignoreLava) { - + private Pair solvePitch(final SolverContext context, final Vec3d goal, final int relaxation) { final boolean desperate = relaxation == 2; final float goodPitch = RotationUtils.calcRotationFromVec3d(context.start, goal, ctx.playerRotations()).getPitch(); final FloatArrayList pitches = pitchesToSolveFor(goodPitch, desperate); final IntTriFunction solve = (ticks, ticksBoosted, ticksBoostDelay) -> - this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ticksBoostDelay, ignoreLava); + this.solvePitch(context, goal, relaxation, pitches.iterator(), ticks, ticksBoosted, ticksBoostDelay); final List tests = new ArrayList<>(); @@ -968,7 +970,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private PitchResult solvePitch(final SolverContext context, final Vec3d goal, final int relaxation, final FloatIterator pitches, final int ticks, final int ticksBoosted, - final int ticksBoostDelay, final boolean ignoreLava) { + final int ticksBoostDelay) { // we are at a certain velocity, but we have a target velocity // what pitch would get us closest to our target velocity? // yaw is easy so we only care about pitch @@ -987,7 +989,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ticks, ticksBoosted, ticksBoostDelay, - ignoreLava + context.ignoreLava ); if (displacement == null) { continue; From 4590ba3ff83788c64e1fe0e3b79a0b12b444ff53 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 29 Jun 2023 23:35:12 -0500 Subject: [PATCH 152/276] Use separate executor for solver --- src/main/java/baritone/behavior/ElytraBehavior.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 954755fa4..3fbe06e44 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -51,9 +51,7 @@ import net.minecraft.util.math.*; import net.minecraft.world.chunk.Chunk; import java.util.*; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.concurrent.Future; +import java.util.concurrent.*; import java.util.function.UnaryOperator; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -92,13 +90,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private int minimumBoostTicks; + private boolean deployedFireworkLastTick; + private final int[] nextTickBoostCounter; + private BlockStateInterface bsi; private BlockPos destination; + private final ExecutorService solverExecutor; private Future solver; private Solution pendingSolution; - private boolean deployedFireworkLastTick; - private final int[] nextTickBoostCounter; private boolean solveNextTick; public ElytraBehavior(Baritone baritone) { @@ -109,6 +109,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); this.process = new ElytraProcess(); + this.solverExecutor = Executors.newSingleThreadExecutor(); this.nextTickBoostCounter = new int[2]; } @@ -524,7 +525,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.pathManager.updatePlayerNear(); final SolverContext context = this.new SolverContext(true); - this.solver = CompletableFuture.supplyAsync(() -> this.solveAngles(context)); + this.solver = this.solverExecutor.submit(() -> this.solveAngles(context)); this.solveNextTick = false; } } From d32f1b2a16a947794ef5b7e20827eb16faba9a6c Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 30 Jun 2023 20:38:45 -0500 Subject: [PATCH 153/276] Add hit pos raytrace method to context --- .../baritone/behavior/elytra/NetherPathfinderContext.java | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index d82372a99..f0197ca78 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -108,6 +108,10 @@ public final class NetherPathfinderContext { throw new IllegalArgumentException("lol"); } + public void raytrace(final int count, final double[] src, final double[] dst, final boolean[] hitsOut, final double[] hitPosOut) { + NetherPathfinder.raytrace(this.context, true, count, src, dst, hitsOut, hitPosOut); + } + public void cancel() { NetherPathfinder.cancel(this.context); } From 83066fc57c1173aa6595375578751410fcc2cdcb Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 30 Jun 2023 20:42:03 -0500 Subject: [PATCH 154/276] Find jump off spot using INSANE custom CalculationContext --- .../api/process/PathingCommandType.java | 7 +- .../baritone/behavior/ElytraBehavior.java | 175 +++++++++--------- .../baritone/behavior/PathingBehavior.java | 2 +- .../pathing/movement/CalculationContext.java | 4 +- .../movement/movements/MovementDescend.java | 8 + .../baritone/utils/InputOverrideHandler.java | 2 +- .../java/baritone/utils/PathRenderer.java | 4 +- .../baritone/utils/PathingControlManager.java | 4 +- 8 files changed, 117 insertions(+), 89 deletions(-) diff --git a/src/api/java/baritone/api/process/PathingCommandType.java b/src/api/java/baritone/api/process/PathingCommandType.java index af25591af..cde38eaf2 100644 --- a/src/api/java/baritone/api/process/PathingCommandType.java +++ b/src/api/java/baritone/api/process/PathingCommandType.java @@ -56,5 +56,10 @@ public enum PathingCommandType { /** * Go and ask the next process what to do */ - DEFER + DEFER, + + /** + * Sets the goal and calculates a path, but pauses instead of immediately starting the path. + */ + SET_GOAL_AND_PAUSE } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 3fbe06e44..c31624435 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -18,24 +18,28 @@ package baritone.behavior; import baritone.Baritone; +import baritone.api.IBaritone; import baritone.api.behavior.IElytraBehavior; import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.event.events.*; import baritone.api.pathing.goals.Goal; -import baritone.api.pathing.goals.GoalGetToBlock; +import baritone.api.pathing.goals.GoalYLevel; +import baritone.api.pathing.movement.IMovement; +import baritone.api.pathing.path.IPathExecutor; import baritone.api.process.IBaritoneProcess; import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.*; import baritone.api.utils.input.Input; -import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.NetherPath; import baritone.behavior.elytra.PathCalculationException; import baritone.behavior.elytra.UnpackedSegment; -import baritone.cache.FasterWorldScanner; +import baritone.pathing.movement.CalculationContext; +import baritone.pathing.movement.movements.MovementFall; import baritone.utils.BlockStateInterface; +import baritone.utils.PathingCommandContext; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; @@ -54,6 +58,8 @@ import java.util.*; import java.util.concurrent.*; import java.util.function.UnaryOperator; +import static baritone.api.pathing.movement.ActionCosts.COST_INF; + public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { /** @@ -106,7 +112,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.context = new NetherPathfinderContext(NETHER_SEED); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); - this.visiblePath = Collections.emptyList(); this.pathManager = this.new PathManager(); this.process = new ElytraProcess(); this.solverExecutor = Executors.newSingleThreadExecutor(); @@ -395,9 +400,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void cancel() { this.destination = null; - this.visiblePath = Collections.emptyList(); this.pathManager.clear(); - this.aimPos = null; this.remainingFireworkTicks = 0; this.remainingSetBackTicks = 0; if (this.solver != null) { @@ -446,12 +449,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Reset rendered elements this.clearLines.clear(); this.blockedLines.clear(); + this.visiblePath = null; this.simulationLine = null; this.aimPos = null; final List path = this.pathManager.getPath(); if (path.isEmpty()) { return; + } else if (this.destination == null) { + this.pathManager.clear(); + return; } this.bsi = new BlockStateInterface(ctx); @@ -1190,43 +1197,67 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (!Baritone.settings().elytraAutoJump.value) { - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + if (this.state == State.FLYING || this.state == State.START_FLYING) { + this.state = ctx.player().onGround && Baritone.settings().elytraAutoJump.value + ? State.LOCATE_JUMP + : State.START_FLYING; } - // We were flying, but we're not anymore, reset the state - if (this.state == State.FLYING) { - this.state = State.GET_TO_JUMP; + if (this.state == State.LOCATE_JUMP) { + if (this.goal == null) { + this.goal = new GoalYLevel(31); + } + this.state = State.VALIDATE_PATH; + return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new WalkOffCalculationContext(baritone)); + } + + if (this.state == State.VALIDATE_PATH) { + final IPathExecutor executor = baritone.getPathingBehavior().getCurrent(); + if (executor != null && executor.getPath().getGoal() == this.goal) { + final IMovement fall = executor.getPath().movements().stream() + .filter(movement -> movement instanceof MovementFall) + .findFirst().orElse(null); + + if (fall != null) { + ElytraBehavior.this.pathManager.pathToDestination(fall.getSrc()); + this.state = State.WAIT_ELYTRA_PATH; + } else { + onLostControl(); + logDirect("Jump off path didn't include a fall movement, canceling"); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + } + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + + // yucky + if (this.state == State.WAIT_ELYTRA_PATH) { + if (!ElytraBehavior.this.pathManager.getPath().isEmpty()) { + this.state = State.GET_TO_JUMP; + } + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } if (this.state == State.GET_TO_JUMP) { - if (this.goal == null) { - final BlockPos jumpOff = this.findJumpOffSpot(); - if (jumpOff == null) { - onLostControl(); - logDirect("Couldn't find a suitable spot to jump off of, canceling"); - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); - } - this.goal = new GoalGetToBlock(jumpOff); - ElytraBehavior.this.pathManager.pathToDestination(jumpOff.add(0, -4, 0)); - } - if (this.goal.isInGoal(ctx.playerFeet())) { + final IPathExecutor executor = baritone.getPathingBehavior().getCurrent(); + final boolean canStartFlying = ctx.player().fallDistance > 1.0f + && !isSafeToCancel + && executor != null + && executor.getPath().movements().get(executor.getPosition()) instanceof MovementFall; + + if (canStartFlying) { this.state = State.START_FLYING; } else { - return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); + return new PathingCommand(null, PathingCommandType.SET_GOAL_AND_PATH); } } - if (this.state == State.START_FLYING && isSafeToCancel && !ElytraBehavior.this.pathManager.getPath().isEmpty()) { - baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d( - ctx.playerHead(), - VecUtils.getBlockPosCenter(((IGoalRenderPos) this.goal).getGoalPos()), - ctx.playerRotations() - ), false); - baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true); - if (ctx.player().fallDistance > 0.0f) { - baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); + if (this.state == State.START_FLYING) { + if (!isSafeToCancel) { + // owned + baritone.getPathingBehavior().secretInternalSegmentCancel(); } + baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); } return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } @@ -1239,7 +1270,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void onLostControl() { this.goal = null; - this.state = State.GET_TO_JUMP; + this.state = State.START_FLYING; ElytraBehavior.this.cancel(); } @@ -1252,64 +1283,42 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public String displayName0() { return "Elytra"; } + } - // ok... now this.. is disgusting - // TODO: make less scuffed - private BlockPos findJumpOffSpot() { - BlockPos best = null; - final BetterBlockPos feet = ctx.playerFeet(); - final List nearby = FasterWorldScanner.getChunkRange(feet.x >> 4, feet.z >> 4, 3); - for (ChunkPos pos : nearby) { - final Chunk chunk = ctx.world().getChunk(pos.x, pos.z); - int[][] obstruction = new int[16][16]; - for (int y0 = 0; y0 < 8; y0++) { - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - int y = feet.y - y0; - if (chunk.getBlockState(x, y, z).getMaterial() != Material.AIR) { - if (obstruction[x][z] == 0 || obstruction[x][z] > y0 + 1) { - obstruction[x][z] = y0 + 1; - } - } - } - } - } - for (int x = 0; x < 16; x++) { - for (int z = 0; z < 16; z++) { - if (obstruction[x][z] != 0) { - continue; - } + /** + * Custom calculation context which makes the player fall into lava + */ + private static final class WalkOffCalculationContext extends CalculationContext { - final int[] adjacent = new int[4]; - if (x > 0) adjacent[0] = obstruction[x - 1][z]; - if (z > 0) adjacent[1] = obstruction[x][z - 1]; - if (x < 15) adjacent[2] = obstruction[x + 1][z]; - if (z < 15) adjacent[3] = obstruction[x][z + 1]; - final OptionalInt minLevel = Arrays.stream(adjacent).filter(i -> i != 0).min(); + public WalkOffCalculationContext(IBaritone baritone) { + super(baritone, true); + this.allowFallIntoLava = true; + this.maxFallHeightNoWater = 10000; + } - if (minLevel.isPresent() && minLevel.getAsInt() <= 4) { - final int yActual = feet.y - minLevel.getAsInt() + 2; // lol - // The target spot itself is clear - if (chunk.getBlockState(x, yActual, z).getMaterial() != Material.AIR - || chunk.getBlockState(x, yActual + 1, z).getMaterial() != Material.AIR) { - continue; - } - // lessgooo - final BlockPos target = new BlockPos(chunk.x << 4 | x, yActual, chunk.z << 4 | z); - if (best == null || target.distanceSq(feet) < best.distanceSq(feet)) { - best = target; - } - } - } - } - } - return best; + @Override + public double costOfPlacingAt(int x, int y, int z, IBlockState current) { + return COST_INF; + } + + @Override + public double breakCostMultiplierAt(int x, int y, int z, IBlockState current) { + return COST_INF; + } + + @Override + public double placeBucketCost() { + return COST_INF; } } private enum State { + LOCATE_JUMP, + VALIDATE_PATH, + WAIT_ELYTRA_PATH, GET_TO_JUMP, START_FLYING, - FLYING + FLYING, + RESTART_FLYING, } } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 31a884622..9b1bd9187 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -352,7 +352,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } // just cancel the current path - private void secretInternalSegmentCancel() { + public void secretInternalSegmentCancel() { queuePathEvent(PathEvent.CANCELED); synchronized (pathPlanLock) { getInProgress().ifPresent(AbstractNodeCostSearch::cancel); diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 129f00e20..2e7db9946 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -66,11 +66,12 @@ public class CalculationContext { public final boolean allowJumpAt256; public final boolean allowParkourAscend; public final boolean assumeWalkOnWater; + public boolean allowFallIntoLava; public final int frostWalker; public final boolean allowDiagonalDescend; public final boolean allowDiagonalAscend; public final boolean allowDownward; - public final int maxFallHeightNoWater; + public int maxFallHeightNoWater; public final int maxFallHeightBucket; public final double waterWalkSpeed; public final double breakBlockAdditionalCost; @@ -105,6 +106,7 @@ public class CalculationContext { this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value; this.allowParkourAscend = Baritone.settings().allowParkourAscend.value; this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value; + this.allowFallIntoLava = false; // Super secret internal setting for ElytraBehavior this.frostWalker = EnchantmentHelper.getMaxEnchantmentLevel(Enchantments.FROST_WALKER, baritone.getPlayerContext().player()); this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value; this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value; diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 2d8180356..7dac6159d 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -178,6 +178,14 @@ public class MovementDescend extends Movement { res.cost = tentativeCost;// TODO incorporate water swim up cost? return false; } + if (context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { + // found a fall into lava + res.x = destX; + res.y = newY; + res.z = destZ; + res.cost = tentativeCost; + return false; + } if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) { // if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know // this effectively "resets" our falling speed diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java index f110b9ce1..fe232786b 100755 --- a/src/main/java/baritone/utils/InputOverrideHandler.java +++ b/src/main/java/baritone/utils/InputOverrideHandler.java @@ -107,7 +107,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri } private boolean inControl() { - for (Input input : new Input[]{Input.MOVE_FORWARD, Input.MOVE_BACK, Input.MOVE_LEFT, Input.MOVE_RIGHT, Input.SNEAK}) { + for (Input input : new Input[]{Input.MOVE_FORWARD, Input.MOVE_BACK, Input.MOVE_LEFT, Input.MOVE_RIGHT, Input.SNEAK, Input.JUMP}) { if (isInputForcedDown(input)) { return true; } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index d09567914..eb7615de8 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -104,7 +104,9 @@ public final class PathRenderer implements IRenderer { final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); - drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0, 0.0D); + if (elytra.visiblePath != null) { + drawPath(elytra.visiblePath, 0, Color.RED, false, 0, 0, 0.0D); + } if (elytra.aimPos != null) { drawGoal(ctx.player(), new GoalBlock(elytra.aimPos), partialTicks, Color.GREEN); } diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index 236e41cc6..a174c842b 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -99,6 +99,8 @@ public class PathingControlManager implements IPathingControlManager { // get rid of the in progress stuff from the last process } switch (command.commandType) { + case SET_GOAL_AND_PAUSE: + p.secretInternalSetGoalAndPath(command); case REQUEST_PAUSE: p.requestPause(); break; @@ -119,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager { case SET_GOAL_AND_PATH: // now this i can do if (command.goal != null) { - baritone.getPathingBehavior().secretInternalSetGoalAndPath(command); + p.secretInternalSetGoalAndPath(command); } break; default: From 3498082f2b7077877ef095fe9178cc632ba85f07 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 30 Jun 2023 20:53:42 -0500 Subject: [PATCH 155/276] Better state switch and start path halfway down fall --- .../baritone/behavior/ElytraBehavior.java | 35 ++++++++++++------- 1 file changed, 23 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c31624435..b844d7564 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -155,13 +155,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.attemptNextSegment(); } - public void pathToDestination() { - this.pathToDestination(ctx.playerFeet()); + public CompletableFuture pathToDestination() { + return this.pathToDestination(ctx.playerFeet()); } - public void pathToDestination(final BlockPos from) { + public CompletableFuture pathToDestination(final BlockPos from) { final long start = System.nanoTime(); - this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity()) + return this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity()) .thenRun(() -> { final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1)); if (this.completePath) { @@ -1219,8 +1219,19 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .findFirst().orElse(null); if (fall != null) { - ElytraBehavior.this.pathManager.pathToDestination(fall.getSrc()); - this.state = State.WAIT_ELYTRA_PATH; + final BetterBlockPos from = new BetterBlockPos( + (fall.getSrc().x + fall.getDest().x) / 2, + (fall.getSrc().y + fall.getDest().y) / 2, + (fall.getSrc().z + fall.getDest().z) / 2 + ); + ElytraBehavior.this.pathManager.pathToDestination(from).whenComplete((result, ex) -> { + if (ex == null) { + this.state = State.GET_TO_JUMP; + } else { + this.onLostControl(); // this is fine :Smile: + } + }); + this.state = State.PAUSE; } else { onLostControl(); logDirect("Jump off path didn't include a fall movement, canceling"); @@ -1231,10 +1242,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } // yucky - if (this.state == State.WAIT_ELYTRA_PATH) { - if (!ElytraBehavior.this.pathManager.getPath().isEmpty()) { - this.state = State.GET_TO_JUMP; - } + if (this.state == State.PAUSE) { return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } @@ -1257,7 +1265,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // owned baritone.getPathingBehavior().secretInternalSegmentCancel(); } - baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); + baritone.getInputOverrideHandler().clearAllKeys(); + if (ctx.player().fallDistance > 1.0f) { + baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); + } } return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } @@ -1315,7 +1326,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private enum State { LOCATE_JUMP, VALIDATE_PATH, - WAIT_ELYTRA_PATH, + PAUSE, GET_TO_JUMP, START_FLYING, FLYING, From 2f7dc2397e97994a5dd36fc6730636bb055fa05a Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 1 Jul 2023 01:32:03 -0500 Subject: [PATCH 156/276] Better start position selection and validation --- .../baritone/behavior/ElytraBehavior.java | 33 ++++++++++++++++--- .../movement/movements/MovementDescend.java | 2 +- 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b844d7564..d7f6ff8b9 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -56,6 +56,7 @@ import net.minecraft.world.chunk.Chunk; import java.util.*; import java.util.concurrent.*; +import java.util.function.Supplier; import java.util.function.UnaryOperator; import static baritone.api.pathing.movement.ActionCosts.COST_INF; @@ -1225,11 +1226,17 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H (fall.getSrc().z + fall.getDest().z) / 2 ); ElytraBehavior.this.pathManager.pathToDestination(from).whenComplete((result, ex) -> { + if (!ElytraBehavior.this.clearView(new Vec3d(from), ElytraBehavior.this.pathManager.getPath().getVec(0), false)) { + onLostControl(); + // TODO: Get to higher ground and then look again + logDirect("Can't see start of path from jump spot, canceling"); + return; + } if (ex == null) { this.state = State.GET_TO_JUMP; - } else { - this.onLostControl(); // this is fine :Smile: + return; } + onLostControl(); }); this.state = State.PAUSE; } else { @@ -1292,7 +1299,24 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public String displayName0() { - return "Elytra"; + final Supplier status = () -> { + switch (this.state) { + case LOCATE_JUMP: + return "Finding spot to jump off"; + case VALIDATE_PATH: + return "Validating path"; + case PAUSE: + return "Waiting for elytra path"; + case GET_TO_JUMP: + return "Walking to takeoff"; + case START_FLYING: + return "Begin flying"; + case FLYING: + return "Flying"; + } + return "Unknown"; + }; + return "Elytra - " + status.get(); } } @@ -1329,7 +1353,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H PAUSE, GET_TO_JUMP, START_FLYING, - FLYING, - RESTART_FLYING, + FLYING } } diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 7dac6159d..51275bc00 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -178,7 +178,7 @@ public class MovementDescend extends Movement { res.cost = tentativeCost;// TODO incorporate water swim up cost? return false; } - if (context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { + if (fallHeight >= 8 && context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { // found a fall into lava res.x = destX; res.y = newY; From 14b5a0cec3a601cb5c67b1e1fac0d40826b1e492 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 1 Jul 2023 17:28:23 -0500 Subject: [PATCH 157/276] Fix Forge support --- src/launch/java/baritone/launch/mixins/MixinEntity.java | 3 --- .../java/baritone/launch/mixins/MixinEntityLivingBase.java | 5 +++-- 2 files changed, 3 insertions(+), 5 deletions(-) diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java index c4f99acbd..b71ee499e 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntity.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -40,7 +40,4 @@ public abstract class MixinEntity { @Shadow public float rotationYaw; - - @Shadow - public abstract void moveRelative(float strafe, float up, float forward, float friction); } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index db2faa940..56b70f085 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -117,7 +117,8 @@ public abstract class MixinEntityLivingBase extends MixinEntity { private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) { Optional baritone = this.getBaritone(); if (!baritone.isPresent()) { - this.moveRelative(strafe, up, forward, friction); + // If a shadow is used here it breaks on Forge + self.moveRelative(strafe, up, forward, friction); return; } @@ -127,7 +128,7 @@ public abstract class MixinEntityLivingBase extends MixinEntity { this.rotationYaw = event.getYaw(); this.rotationPitch = event.getPitch(); - this.moveRelative(strafe, up, forward, friction); + self.moveRelative(strafe, up, forward, friction); this.rotationYaw = event.getOriginal().getYaw(); this.rotationPitch = event.getOriginal().getPitch(); From ccd737d0a1e3c5afbd0db7b361cc2916b9862bd9 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 1 Jul 2023 18:38:13 -0500 Subject: [PATCH 158/276] Actually fix Forge by reverting Mixin change completely --- .../java/baritone/launch/mixins/MixinEntity.java | 6 ------ .../launch/mixins/MixinEntityLivingBase.java | 12 +++++++++--- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java index b71ee499e..a611507b8 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntity.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntity.java @@ -34,10 +34,4 @@ public abstract class MixinEntity { @Shadow protected EntityDataManager dataManager; - - @Shadow - public float rotationPitch; - - @Shadow - public float rotationYaw; } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index 56b70f085..92f065184 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -21,7 +21,9 @@ import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.event.events.RotationMoveEvent; import net.minecraft.client.entity.EntityPlayerSP; +import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; @@ -38,7 +40,7 @@ import static org.spongepowered.asm.lib.Opcodes.GETFIELD; * @since 9/10/2018 */ @Mixin(EntityLivingBase.class) -public abstract class MixinEntityLivingBase extends MixinEntity { +public abstract class MixinEntityLivingBase extends Entity { /** * Event called to override the movement direction when jumping @@ -49,6 +51,10 @@ public abstract class MixinEntityLivingBase extends MixinEntity { @Unique private RotationMoveEvent elytraRotationEvent; + public MixinEntityLivingBase(World worldIn) { + super(worldIn); + } + @Inject( method = "jump", at = @At("HEAD") @@ -118,7 +124,7 @@ public abstract class MixinEntityLivingBase extends MixinEntity { Optional baritone = this.getBaritone(); if (!baritone.isPresent()) { // If a shadow is used here it breaks on Forge - self.moveRelative(strafe, up, forward, friction); + this.moveRelative(strafe, up, forward, friction); return; } @@ -128,7 +134,7 @@ public abstract class MixinEntityLivingBase extends MixinEntity { this.rotationYaw = event.getYaw(); this.rotationPitch = event.getPitch(); - self.moveRelative(strafe, up, forward, friction); + this.moveRelative(strafe, up, forward, friction); this.rotationYaw = event.getOriginal().getYaw(); this.rotationPitch = event.getOriginal().getPitch(); From dee7df1534aec68f4bb017eb6d8f5ecc54e4b6f3 Mon Sep 17 00:00:00 2001 From: Brady Date: Sat, 1 Jul 2023 19:38:38 -0500 Subject: [PATCH 159/276] I HATE OLD MIXIN!!!! awesome buggy 0.7.11 hates referencing shadows in mixin superclasses wooooooo --- .../baritone/launch/mixins/MixinEntity.java | 37 ------------------- .../mixins/MixinEntityFireworkRocket.java | 7 +++- .../launch/mixins/MixinEntityLivingBase.java | 2 +- src/launch/resources/mixins.baritone.json | 1 - 4 files changed, 7 insertions(+), 40 deletions(-) delete mode 100644 src/launch/java/baritone/launch/mixins/MixinEntity.java diff --git a/src/launch/java/baritone/launch/mixins/MixinEntity.java b/src/launch/java/baritone/launch/mixins/MixinEntity.java deleted file mode 100644 index a611507b8..000000000 --- a/src/launch/java/baritone/launch/mixins/MixinEntity.java +++ /dev/null @@ -1,37 +0,0 @@ -/* - * This file is part of Baritone. - * - * Baritone is free software: you can redistribute it and/or modify - * it under the terms of the GNU Lesser General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * Baritone is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU Lesser General Public License for more details. - * - * You should have received a copy of the GNU Lesser General Public License - * along with Baritone. If not, see . - */ - -package baritone.launch.mixins; - -import net.minecraft.entity.Entity; -import net.minecraft.network.datasync.EntityDataManager; -import net.minecraft.world.World; -import org.spongepowered.asm.mixin.Mixin; -import org.spongepowered.asm.mixin.Shadow; - -/** - * @author Brady - */ -@Mixin(Entity.class) -public abstract class MixinEntity { - - @Shadow - public World world; - - @Shadow - protected EntityDataManager dataManager; -} diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java index 559ae0d54..f6c6fbd3e 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityFireworkRocket.java @@ -22,12 +22,13 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.network.datasync.DataParameter; +import net.minecraft.world.World; import org.spongepowered.asm.mixin.Final; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Shadow; @Mixin(EntityFireworkRocket.class) -public abstract class MixinEntityFireworkRocket extends MixinEntity implements IEntityFireworkRocket { +public abstract class MixinEntityFireworkRocket extends Entity implements IEntityFireworkRocket { @Shadow @Final @@ -39,6 +40,10 @@ public abstract class MixinEntityFireworkRocket extends MixinEntity implements I @Shadow public abstract boolean isAttachedToEntity(); + private MixinEntityFireworkRocket(World worldIn) { + super(worldIn); + } + @Override public EntityLivingBase getBoostedEntity() { if (this.isAttachedToEntity() && this.boostedEntity == null) { diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index 92f065184..df1163ea8 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -51,7 +51,7 @@ public abstract class MixinEntityLivingBase extends Entity { @Unique private RotationMoveEvent elytraRotationEvent; - public MixinEntityLivingBase(World worldIn) { + private MixinEntityLivingBase(World worldIn) { super(worldIn); } diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone.json index cbade3329..5c221de58 100644 --- a/src/launch/resources/mixins.baritone.json +++ b/src/launch/resources/mixins.baritone.json @@ -16,7 +16,6 @@ "MixinChunkProviderServer", "MixinChunkRenderContainer", "MixinChunkRenderWorker", - "MixinEntity", "MixinEntityFireworkRocket", "MixinEntityLivingBase", "MixinEntityPlayerSP", From fc209599af9ffb17785ea36d3728147ac2357712 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 2 Jul 2023 01:03:34 -0500 Subject: [PATCH 160/276] Update `nether-pathfinder` to 0.21 --- build.gradle | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/build.gradle b/build.gradle index 58929d98b..99d7cc823 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.20') + launchImplementation('dev.babbaj:nether-pathfinder:0.21') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.20' + implementation 'dev.babbaj:nether-pathfinder:0.21' } mixin { From c8259d3e90b372ba55b25172dae133ed5761fc72 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 3 Jul 2023 13:27:23 -0500 Subject: [PATCH 161/276] ZOOM --- .../baritone/api/utils/BetterBlockPos.java | 20 ++++ .../baritone/behavior/ElytraBehavior.java | 99 +++++++++++++------ .../behavior/elytra/UnpackedSegment.java | 3 +- .../java/baritone/utils/BaritoneMath.java | 37 +++++++ 4 files changed, 125 insertions(+), 34 deletions(-) create mode 100644 src/main/java/baritone/utils/BaritoneMath.java diff --git a/src/api/java/baritone/api/utils/BetterBlockPos.java b/src/api/java/baritone/api/utils/BetterBlockPos.java index 01e53402e..3eb8068c1 100644 --- a/src/api/java/baritone/api/utils/BetterBlockPos.java +++ b/src/api/java/baritone/api/utils/BetterBlockPos.java @@ -35,6 +35,15 @@ import javax.annotation.Nonnull; */ public final class BetterBlockPos extends BlockPos { + private static final int NUM_X_BITS = 26; + private static final int NUM_Z_BITS = NUM_X_BITS; + private static final int NUM_Y_BITS = 64 - NUM_X_BITS - NUM_Z_BITS; + private static final int Y_SHIFT = NUM_Z_BITS; + private static final int X_SHIFT = Y_SHIFT + NUM_Y_BITS; + private static final long X_MASK = (1L << NUM_X_BITS) - 1L; + private static final long Y_MASK = (1L << NUM_Y_BITS) - 1L; + private static final long Z_MASK = (1L << NUM_Z_BITS) - 1L; + public static final BetterBlockPos ORIGIN = new BetterBlockPos(0, 0, 0); public final int x; @@ -226,4 +235,15 @@ public final class BetterBlockPos extends BlockPos { SettingsUtil.maybeCensor(z) ); } + + public static long serializeToLong(final int x, final int y, final int z) { + return ((long) x & X_MASK) << X_SHIFT | ((long) y & Y_MASK) << Y_SHIFT | ((long) z & Z_MASK); + } + + public static BetterBlockPos deserializeFromLong(final long serialized) { + final int x = (int) (serialized << 64 - X_SHIFT - NUM_X_BITS >> 64 - NUM_X_BITS); + final int y = (int) (serialized << 64 - Y_SHIFT - NUM_Y_BITS >> 64 - NUM_Y_BITS); + final int z = (int) (serialized << 64 - NUM_Z_BITS >> 64 - NUM_Z_BITS); + return new BetterBlockPos(x, y, z); + } } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index d7f6ff8b9..73ccb69f1 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -43,6 +43,7 @@ import baritone.utils.PathingCommandContext; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; +import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; @@ -60,6 +61,8 @@ import java.util.function.Supplier; import java.util.function.UnaryOperator; import static baritone.api.pathing.movement.ActionCosts.COST_INF; +import static baritone.utils.BaritoneMath.fastCeil; +import static baritone.utils.BaritoneMath.fastFloor; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { @@ -447,6 +450,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H this.minimumBoostTicks = 0; } + // lol + MC_1_12_Collision_Fix.clear(); + // Reset rendered elements this.clearLines.clear(); this.blockedLines.clear(); @@ -567,7 +573,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } else { // Create a point along the segment every block final Vec3d delta = path.getVec(i).subtract(path.getVec(i - 1)); - final int steps = MathHelper.floor(delta.length()); + final int steps = fastFloor(delta.length()); final Vec3d step = delta.normalize(); Vec3d stepped = path.getVec(i); for (int interp = 0; interp < steps; interp++) { @@ -893,7 +899,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final float minPitch = desperate ? -90 : Math.max(goodPitch - Baritone.settings().elytraPitchRange.value, -89); final float maxPitch = desperate ? 90 : Math.min(goodPitch + Baritone.settings().elytraPitchRange.value, 89); - final FloatArrayList pitchValues = new FloatArrayList(MathHelper.ceil(maxPitch - minPitch) + 1); + final FloatArrayList pitchValues = new FloatArrayList(fastCeil(maxPitch - minPitch) + 1); for (float pitch = goodPitch; pitch <= maxPitch; pitch++) { pitchValues.add(pitch); } @@ -1039,11 +1045,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Vec3d delta = goalDelta; Vec3d motion = ctx.playerMotion(); AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); - List displacement = new ArrayList<>(); + List displacement = new ArrayList<>(ticks + 1); displacement.add(Vec3d.ZERO); for (int i = 0; i < ticks; i++) { - if (MC_1_12_Collision_Fix.bonk(this.bsi, hitbox)) { + final double cx = hitbox.minX + (hitbox.maxX - hitbox.minX) * 0.5D; + final double cz = hitbox.minZ + (hitbox.maxZ - hitbox.minZ) * 0.5D; + if (MC_1_12_Collision_Fix.bonk(this.bsi, cx, hitbox.minY, cz)) { return null; } if (delta.lengthSquared() < 1) { @@ -1060,9 +1068,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Collision box while the player is in motion, with additional padding for safety final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z).grow(0.01); - for (int x = MathHelper.floor(inMotion.minX); x < MathHelper.ceil(inMotion.maxX); x++) { - for (int y = MathHelper.floor(inMotion.minY); y < MathHelper.ceil(inMotion.maxY); y++) { - for (int z = MathHelper.floor(inMotion.minZ); z < MathHelper.ceil(inMotion.maxZ); z++) { + for (int x = fastFloor(inMotion.minX); x < fastCeil(inMotion.maxX); x++) { + for (int y = fastFloor(inMotion.minY); y < fastCeil(inMotion.maxY); y++) { + for (int z = fastFloor(inMotion.minZ); z < fastCeil(inMotion.maxZ); z++) { if (!this.passable(x, y, z, ignoreLava)) { return null; } @@ -1140,35 +1148,62 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H */ private static final class MC_1_12_Collision_Fix { - public static boolean bonk(final BlockStateInterface bsi, final AxisAlignedBB aabb) { - final Vec3d center = aabb.getCenter(); - final double width = (aabb.maxX - aabb.minX) * 0.35D; - final double x = center.x; - final double y = aabb.minY + 0.5D; - final double z = center.z; + private static final Long2ReferenceOpenHashMap PUSH_OUT_CACHE = new Long2ReferenceOpenHashMap<>(); + private static final Long2ReferenceOpenHashMap IS_OPEN_CACHE = new Long2ReferenceOpenHashMap<>(); + private static final double WIDTH = 0.35D * 0.6F; - return pushOutOfBlocks(bsi, x - width, y, z + width) - || pushOutOfBlocks(bsi, x - width, y, z - width) - || pushOutOfBlocks(bsi, x + width, y, z - width) - || pushOutOfBlocks(bsi, x + width, y, z + width); - } - - private static boolean pushOutOfBlocks(final BlockStateInterface bsi, - final double xIn, final double yIn, final double zIn) { - final int x = MathHelper.floor(xIn); - final int y = MathHelper.floor(yIn); - final int z = MathHelper.floor(zIn); - if (isOpenBlockSpace(bsi, x, y, z)) { - return false; + public static void clear() { + // TODO: I don't like this.... + if (MC_1_12_Collision_Fix.PUSH_OUT_CACHE.size() > 4096) { + MC_1_12_Collision_Fix.PUSH_OUT_CACHE.clear(); + } + if (MC_1_12_Collision_Fix.IS_OPEN_CACHE.size() > 4096) { + MC_1_12_Collision_Fix.IS_OPEN_CACHE.clear(); } - return isOpenBlockSpace(bsi, x - 1, y, z) - || isOpenBlockSpace(bsi, x + 1, y, z) - || isOpenBlockSpace(bsi, x, y, z - 1) - || isOpenBlockSpace(bsi, x, y, z + 1); } - private static boolean isOpenBlockSpace(BlockStateInterface bsi, final int x, final int y, final int z) { - return !bsi.get0(x, y, z).isNormalCube() && !bsi.get0(x, y + 1, z).isNormalCube(); + public static boolean bonk(final BlockStateInterface bsi, final double xIn, final double yIn, final double zIn) { + final int y = fastFloor(yIn + 0.5D); + final int minX = fastFloor(xIn - WIDTH); + final int minZ = fastFloor(zIn - WIDTH); + final int maxX = fastFloor(xIn + WIDTH); + final int maxZ = fastFloor(zIn + WIDTH); + + if (minX == maxX && minZ == maxZ) { + return pushOutOfBlocks(bsi, minX, y, minZ); + } else if (minX == maxX) { + return pushOutOfBlocks(bsi, minX, y, minZ) || pushOutOfBlocks(bsi, minX, y, maxZ); + } else if (minZ == maxZ) { + return pushOutOfBlocks(bsi, minX, y, minZ) || pushOutOfBlocks(bsi, maxX, y, minZ); + } + + return pushOutOfBlocks(bsi, minX, y, maxZ) + || pushOutOfBlocks(bsi, minX, y, minZ) + || pushOutOfBlocks(bsi, maxX, y, minZ) + || pushOutOfBlocks(bsi, maxX, y, maxZ); + } + + private static boolean pushOutOfBlocks(final BlockStateInterface bsi, final int x, final int y, final int z) { + final long hash = BetterBlockPos.serializeToLong(x, y, z); + Boolean result = PUSH_OUT_CACHE.get(hash); + if (result == null) { + PUSH_OUT_CACHE.put(hash, result = !isOpenBlockSpace(bsi, x, y, z) && ( + isOpenBlockSpace(bsi, x - 1, y, z) + || isOpenBlockSpace(bsi, x + 1, y, z) + || isOpenBlockSpace(bsi, x, y, z - 1) + || isOpenBlockSpace(bsi, x, y, z + 1)) + ); + } + return result; + } + + private static boolean isOpenBlockSpace(final BlockStateInterface bsi, final int x, final int y, final int z) { + final long hash = BetterBlockPos.serializeToLong(x, y, z); + Boolean result = IS_OPEN_CACHE.get(hash); + if (result == null) { + IS_OPEN_CACHE.put(hash, result = !bsi.get0(x, y, z).isNormalCube() && !bsi.get0(x, y + 1, z).isNormalCube()); + } + return result; } } diff --git a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java index 22fa4f82d..0e0759625 100644 --- a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java +++ b/src/main/java/baritone/behavior/elytra/UnpackedSegment.java @@ -19,7 +19,6 @@ package baritone.behavior.elytra; import baritone.api.utils.BetterBlockPos; import dev.babbaj.pathfinder.PathSegment; -import net.minecraft.util.math.BlockPos; import java.util.Arrays; import java.util.HashMap; @@ -77,7 +76,7 @@ public final class UnpackedSegment { public static UnpackedSegment from(final PathSegment segment) { return new UnpackedSegment( - Arrays.stream(segment.packed).mapToObj(BlockPos::fromLong).map(BetterBlockPos::new), + Arrays.stream(segment.packed).mapToObj(BetterBlockPos::deserializeFromLong), segment.finished ); } diff --git a/src/main/java/baritone/utils/BaritoneMath.java b/src/main/java/baritone/utils/BaritoneMath.java new file mode 100644 index 000000000..944fc899e --- /dev/null +++ b/src/main/java/baritone/utils/BaritoneMath.java @@ -0,0 +1,37 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.utils; + +/** + * @author Brady + */ +public final class BaritoneMath { + + private BaritoneMath() {} + + private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; + private static final int FLOOR_DOUBLE_I = 1_073_741_824; + + public static int fastFloor(final double v) { + return (int) (v + FLOOR_DOUBLE_D) - FLOOR_DOUBLE_I; + } + + public static int fastCeil(final double v) { + return FLOOR_DOUBLE_I - (int) (FLOOR_DOUBLE_D - v); + } +} From 4c0c263d1100d5f48caf9bf303ceb7654d73a463 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 3 Jul 2023 13:28:53 -0500 Subject: [PATCH 162/276] trolling --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 73ccb69f1..f22a3151d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1154,11 +1154,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public static void clear() { // TODO: I don't like this.... - if (MC_1_12_Collision_Fix.PUSH_OUT_CACHE.size() > 4096) { - MC_1_12_Collision_Fix.PUSH_OUT_CACHE.clear(); + if (PUSH_OUT_CACHE.size() > 4096) { + PUSH_OUT_CACHE.clear(); } - if (MC_1_12_Collision_Fix.IS_OPEN_CACHE.size() > 4096) { - MC_1_12_Collision_Fix.IS_OPEN_CACHE.clear(); + if (IS_OPEN_CACHE.size() > 4096) { + IS_OPEN_CACHE.clear(); } } From 2552eb8dca36d7fac1ffe2eb4e3b81149c29763a Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 6 Jul 2023 18:57:51 -0700 Subject: [PATCH 163/276] Add setting documentation --- src/api/java/baritone/api/Settings.java | 81 +++++++++++++++++++++---- 1 file changed, 68 insertions(+), 13 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index c85280f60..9eed667f9 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -48,19 +48,6 @@ import java.util.function.Consumer; */ public final class Settings { - public final Setting elytraSimulationTicks = new Setting<>(20); - public final Setting elytraPitchRange = new Setting<>(25); - public final Setting elytraFireworkSpeed = new Setting<>(0.6); - public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15); - public final Setting elytraMinimumAvoidance = new Setting<>(0.2); - public final Setting conserveFireworks = new Setting<>(true); - public final Setting renderRaytraces = new Setting<>(false); - public final Setting renderHitboxRaytraces = new Setting<>(false); - public final Setting renderElytraSimulation = new Setting<>(false); - public final Setting elytraFreeLook = new Setting<>(false); - public final Setting elytraAutoJump = new Setting<>(false); - public final Setting smoothLook = new Setting<>(false); - /** * Allow Baritone to break blocks */ @@ -748,6 +735,17 @@ public final class Settings { */ public final Setting blockFreeLook = new Setting<>(false); + /** + * Automatically elytra fly without having to force the client-sided rotations. Requires {@link #freeLook}. + */ + public final Setting elytraFreeLook = new Setting<>(false); + + /** + * Forces the client-sided rotations to an average of the last 10 ticks of server-sided rotations. + * Requires {@link #freeLook}. + */ + public final Setting smoothLook = new Setting<>(false); + /** * When true, the player will remain with its existing look direction as often as possible. * Although, in some cases this can get it stuck, hence this setting to disable that behavior. @@ -1333,6 +1331,63 @@ public final class Settings { */ public final Setting notificationOnMineFail = new Setting<>(true); + /** + * The number of ticks of elytra movement to simulate while firework boost is not active. Higher values are + * computationally more expensive. + */ + public final Setting elytraSimulationTicks = new Setting<>(20); + + /** + * The maximum allowed deviation in pitch from a direct line-of-sight to the flight target. Higher values are + * computationally more expensive. + */ + public final Setting elytraPitchRange = new Setting<>(25); + + /** + * The minimum speed that the player can drop to (in blocks/tick) before a firework is automatically deployed. + */ + public final Setting elytraFireworkSpeed = new Setting<>(0.6); + + /** + * The delay after the player's position is set-back by the server that a firework may be automatically deployed. + * Value is in ticks. + */ + public final Setting elytraFireworkSetbackUseDelay = new Setting<>(15); + + /** + * The minimum padding value that is added to the player's hitbox when considering which point to fly to on the + * path. High values can result in points not being considered which are otherwise safe to fly to. Low values can + * result in flight paths which are extremely tight, and there's the possibility of crashing due to getting too low + * to the ground. + */ + public final Setting elytraMinimumAvoidance = new Setting<>(0.2); + + /** + * If enabled, avoids using fireworks when descending along the flight path. + */ + public final Setting conserveFireworks = new Setting<>(true); + + /** + * Renders the raytraces that are performed by the elytra fly calculation. + */ + public final Setting renderRaytraces = new Setting<>(false); + + /** + * Renders the raytraces that are used in the hitbox part of the elytra fly calculation. + * Requires {@link #renderRaytraces}. + */ + public final Setting renderHitboxRaytraces = new Setting<>(false); + + /** + * Renders the best elytra flight path that was simulated each tick. + */ + public final Setting renderElytraSimulation = new Setting<>(false); + + /** + * Automatically path to and jump off of ledges to initiate elytra flight when grounded. + */ + public final Setting elytraAutoJump = new Setting<>(false); + /** * A map of lowercase setting field names to their respective setting */ From aeeb00120559a72f2123a11880375291b3c575cd Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 6 Jul 2023 19:02:13 -0700 Subject: [PATCH 164/276] Fix some codacy issues --- src/main/java/baritone/behavior/ElytraBehavior.java | 8 +++++--- src/main/java/baritone/behavior/InventoryBehavior.java | 2 -- .../baritone/behavior/elytra/NetherPathfinderContext.java | 7 ++++--- .../java/baritone/command/defaults/ElytraCommand.java | 1 - .../command/defaults/ExecutionControlCommands.java | 1 - .../baritone/command/defaults/ForceCancelCommand.java | 1 - src/main/java/baritone/utils/BaritoneMath.java | 4 ++-- 7 files changed, 11 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f22a3151d..fb8747bb2 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1041,12 +1041,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, - final int ticks, int ticksBoosted, final int ticksBoostDelay, final boolean ignoreLava) { + final int ticks, final int ticksBoosted, final int ticksBoostDelay, final boolean ignoreLava) { Vec3d delta = goalDelta; Vec3d motion = ctx.playerMotion(); AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); List displacement = new ArrayList<>(ticks + 1); displacement.add(Vec3d.ZERO); + int remainingTicksBoosted = ticksBoosted; for (int i = 0; i < ticks; i++) { final double cx = hitbox.minX + (hitbox.maxX - hitbox.minX) * 0.5D; @@ -1081,7 +1082,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H hitbox = hitbox.offset(motion); displacement.add(displacement.get(displacement.size() - 1).add(motion)); - if (i >= ticksBoostDelay && ticksBoosted-- > 0) { + if (i >= ticksBoostDelay && remainingTicksBoosted-- > 0) { // See EntityFireworkRocket motion = motion.add( lookDirection.x * 0.1 + (lookDirection.x * 1.5 - motion.x) * 0.5, @@ -1348,8 +1349,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return "Begin flying"; case FLYING: return "Flying"; + default: + return "Unknown"; } - return "Unknown"; }; return "Elytra - " + status.get(); } diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java index 1ab31eb53..93dc200cc 100644 --- a/src/main/java/baritone/behavior/InventoryBehavior.java +++ b/src/main/java/baritone/behavior/InventoryBehavior.java @@ -25,10 +25,8 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.init.Blocks; -import net.minecraft.init.Items; import net.minecraft.inventory.ClickType; import net.minecraft.item.*; -import net.minecraft.nbt.NBTTagCompound; import net.minecraft.util.EnumFacing; import net.minecraft.util.NonNullList; diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index f0197ca78..8e9a862c0 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -104,8 +104,9 @@ public final class NetherPathfinderContext { return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) == -1; case Visibility.ANY: return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) != -1; + default: + throw new IllegalArgumentException("lol"); } - throw new IllegalArgumentException("lol"); } public void raytrace(final int count, final double[] src, final double[] dst, final boolean[] hitsOut, final double[] hitPosOut) { @@ -166,10 +167,10 @@ public final class NetherPathfinderContext { public static final class Visibility { - private Visibility() {} - public static final int ALL = 0; public static final int NONE = 1; public static final int ANY = 2; + + private Visibility() {} } } diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 3414c7bb3..93c4c2544 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -17,7 +17,6 @@ package baritone.command.defaults; -import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index e7f7c9497..43adca19f 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -17,7 +17,6 @@ package baritone.command.defaults; -import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index bc6dbd0a4..ad19f168c 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -17,7 +17,6 @@ package baritone.command.defaults; -import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.behavior.IPathingBehavior; import baritone.api.command.Command; diff --git a/src/main/java/baritone/utils/BaritoneMath.java b/src/main/java/baritone/utils/BaritoneMath.java index 944fc899e..be546f248 100644 --- a/src/main/java/baritone/utils/BaritoneMath.java +++ b/src/main/java/baritone/utils/BaritoneMath.java @@ -22,11 +22,11 @@ package baritone.utils; */ public final class BaritoneMath { - private BaritoneMath() {} - private static final double FLOOR_DOUBLE_D = 1_073_741_824.0; private static final int FLOOR_DOUBLE_I = 1_073_741_824; + private BaritoneMath() {} + public static int fastFloor(final double v) { return (int) (v + FLOOR_DOUBLE_D) - FLOOR_DOUBLE_I; } From c4ac23837fd0ddddebd39795dd5004251ad0c3e6 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 6 Jul 2023 19:31:37 -0700 Subject: [PATCH 165/276] Set `safeToCancel` to `false` while flying --- src/main/java/baritone/behavior/ElytraBehavior.java | 4 ++++ src/main/java/baritone/behavior/PathingBehavior.java | 3 +++ 2 files changed, 7 insertions(+) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index fb8747bb2..9ff48f3a2 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1208,6 +1208,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + public boolean isSafeToCancel() { + return !this.isActive() || !(this.process.state == State.FLYING || this.process.state == State.START_FLYING); + } + private final class ElytraProcess implements IBaritoneProcess { private State state; diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 9b1bd9187..19266b2c2 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -148,6 +148,9 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } } if (current == null) { + if (baritone.getElytraBehavior().isActive()) { + safeToCancel = baritone.getElytraBehavior().isSafeToCancel(); + } return; } safeToCancel = current.onTick(); From ecfd664f30d2dd37b0a8ad9035e21bb793cac5d6 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 6 Jul 2023 20:11:50 -0700 Subject: [PATCH 166/276] Fix `isSafeToCancel()` return value --- src/main/java/baritone/behavior/PathingBehavior.java | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 19266b2c2..670dd827c 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -148,9 +148,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } } if (current == null) { - if (baritone.getElytraBehavior().isActive()) { - safeToCancel = baritone.getElytraBehavior().isSafeToCancel(); - } return; } safeToCancel = current.onTick(); @@ -312,7 +309,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, } public boolean isSafeToCancel() { - return current == null || safeToCancel; + if (current == null) { + return !baritone.getElytraBehavior().isActive() || baritone.getElytraBehavior().isSafeToCancel(); + } + return safeToCancel; } public void requestPause() { From 8de239f4688609de996107f36048e59f66ac2310 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 6 Jul 2023 23:15:35 -0700 Subject: [PATCH 167/276] Use soft references for chunks queued for packing --- src/main/java/baritone/cache/CachedWorld.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/cache/CachedWorld.java b/src/main/java/baritone/cache/CachedWorld.java index 32112f20f..bed3185a5 100644 --- a/src/main/java/baritone/cache/CachedWorld.java +++ b/src/main/java/baritone/cache/CachedWorld.java @@ -23,6 +23,7 @@ import baritone.api.IBaritone; import baritone.api.cache.ICachedWorld; import baritone.api.cache.IWorldData; import baritone.api.utils.Helper; +import com.google.common.cache.CacheBuilder; import it.unimi.dsi.fastutil.longs.Long2ObjectMap; import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap; import net.minecraft.util.math.BlockPos; @@ -35,7 +36,6 @@ import java.nio.file.Path; import java.util.ArrayList; import java.util.List; import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.LinkedBlockingQueue; /** @@ -69,7 +69,7 @@ public final class CachedWorld implements ICachedWorld, Helper { * All chunk positions pending packing. This map will be updated in-place if a new update to the chunk occurs * while waiting in the queue for the packer thread to get to it. */ - private final Map toPackMap = new ConcurrentHashMap<>(); + private final Map toPackMap = CacheBuilder.newBuilder().softValues().build().asMap(); private final int dimension; From b6bf4427ef077a75ad71314e1c97ff0106f454a0 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 00:30:07 -0700 Subject: [PATCH 168/276] Use soft references for nether chunk packing queue --- .../elytra/NetherPathfinderContext.java | 25 ++++++++++++------- 1 file changed, 16 insertions(+), 9 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 8e9a862c0..3fd7987e5 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -27,6 +27,7 @@ import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; +import java.lang.ref.SoftReference; import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; @@ -47,8 +48,16 @@ public final class NetherPathfinderContext { this.executor = Executors.newSingleThreadExecutor(); } - public void queueForPacking(Chunk chunk) { - this.executor.submit(() -> NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk))); + public void queueForPacking(final Chunk chunkIn) { + final SoftReference ref = new SoftReference<>(chunkIn); + this.executor.execute(() -> { + // TODO: Prioritize packing recent chunks and/or ones that the path goes through, + // and prune the oldest chunks per chunkPackerQueueMaxSize + final Chunk chunk = ref.get(); + if (chunk != null) { + NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk)); + } + }); } public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { @@ -74,9 +83,9 @@ public final class NetherPathfinderContext { * @param startX The start X coordinate * @param startY The start Y coordinate * @param startZ The start Z coordinate - * @param endX The end X coordinate - * @param endY The end Y coordinate - * @param endZ The end Z coordinate + * @param endX The end X coordinate + * @param endY The end Y coordinate + * @param endZ The end Z coordinate * @return {@code true} if there is visibility between the points */ public boolean raytrace(final double startX, final double startY, final double startZ, @@ -89,7 +98,7 @@ public final class NetherPathfinderContext { * visibility between the two points. * * @param start The starting point - * @param end The ending point + * @param end The ending point * @return {@code true} if there is visibility between the points */ public boolean raytrace(final Vec3d start, final Vec3d end) { @@ -151,9 +160,7 @@ public final class NetherPathfinderContext { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); - if (state.getMaterial() != Material.AIR) { - packed[x | (z << 4) | (y << 8)] = true; - } + packed[x | (z << 4) | (y << 8)] = state.getMaterial() != Material.AIR; } } } From 537100a5e59e60eab80715faf8e00b0c0326eea0 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 10:44:56 -0700 Subject: [PATCH 169/276] Nether seed setting and automatic context reset --- src/api/java/baritone/api/Settings.java | 6 +++++ .../baritone/behavior/ElytraBehavior.java | 23 +++++++++++++------ 2 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 9eed667f9..08fe54d3a 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1388,6 +1388,12 @@ public final class Settings { */ public final Setting elytraAutoJump = new Setting<>(false); + /** + * The seed used to generate chunks for long distance elytra path-finding in the nether. + * Defaults to 2b2t's nether seed. + */ + public final Setting elytraNetherSeed = new Setting<>(146008555100680L); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 9ff48f3a2..edabf2912 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -66,11 +66,6 @@ import static baritone.utils.BaritoneMath.fastFloor; public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { - /** - * 2b2t seed - */ - private static final long NETHER_SEED = 146008555100680L; - // Used exclusively for PathRenderer public List> clearLines; public List> blockedLines; @@ -79,7 +74,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public List visiblePath; // :sunglasses: - private final NetherPathfinderContext context; + private NetherPathfinderContext context; private final PathManager pathManager; private final ElytraProcess process; @@ -113,7 +108,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public ElytraBehavior(Baritone baritone) { super(baritone); - this.context = new NetherPathfinderContext(NETHER_SEED); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); this.pathManager = this.new PathManager(); @@ -439,6 +433,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + // Setup/reset context + final long netherSeed = Baritone.settings().elytraNetherSeed.value; + if (this.context == null || this.context.getSeed() != netherSeed) { + if (this.context != null) { + this.context.destroy(); + } + this.context = new NetherPathfinderContext(netherSeed); + + if (this.isActive()) { + // TODO: Re-pack chunks? + logDirect("Nether seed changed, recalculating path"); + this.pathManager.pathToDestination(); + } + } + // Certified mojang employee incident if (this.remainingFireworkTicks > 0) { this.remainingFireworkTicks--; From bfb4ffcafcf5c51cfe25791f8e61f93e92baa088 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 11:19:18 -0700 Subject: [PATCH 170/276] Reset context on world load/unload --- .../baritone/behavior/ElytraBehavior.java | 23 ++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index edabf2912..98bcf7a3f 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -23,6 +23,7 @@ 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.event.events.type.EventState; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalYLevel; import baritone.api.pathing.movement.IMovement; @@ -75,6 +76,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private NetherPathfinderContext context; + private boolean forceResetContext; private final PathManager pathManager; private final ElytraProcess process; @@ -363,6 +365,24 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + @Override + public void onWorldEvent(WorldEvent event) { + if (event.getWorld() != null) { + if (event.getState() == EventState.PRE) { + // Reset the context when it's safe to do so on the next game tick + this.forceResetContext = true; + } + } else { + if (event.getState() == EventState.POST) { + // Exiting the world, just destroy and invalidate the context + if (this.context != null) { + this.context.destroy(); + this.context = null; + } + } + } + } + @Override public void onChunkEvent(ChunkEvent event) { if (event.isPostPopulate()) { @@ -435,11 +455,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Setup/reset context final long netherSeed = Baritone.settings().elytraNetherSeed.value; - if (this.context == null || this.context.getSeed() != netherSeed) { + if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext) { if (this.context != null) { this.context.destroy(); } this.context = new NetherPathfinderContext(netherSeed); + this.forceResetContext = false; if (this.isActive()) { // TODO: Re-pack chunks? From 308b9bbfea2e58b44c4f1edae35f247de2557112 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 13:26:43 -0700 Subject: [PATCH 171/276] Apply minimum fall height to regular falls too --- src/main/java/baritone/behavior/ElytraBehavior.java | 1 + .../baritone/pathing/movement/CalculationContext.java | 2 ++ .../pathing/movement/movements/MovementDescend.java | 9 +++++---- 3 files changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 98bcf7a3f..6374e7524 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1399,6 +1399,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public WalkOffCalculationContext(IBaritone baritone) { super(baritone, true); this.allowFallIntoLava = true; + this.minFallHeight = 8; this.maxFallHeightNoWater = 10000; } diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 2e7db9946..75b6acd9b 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -71,6 +71,7 @@ public class CalculationContext { public final boolean allowDiagonalDescend; public final boolean allowDiagonalAscend; public final boolean allowDownward; + public int minFallHeight; public int maxFallHeightNoWater; public final int maxFallHeightBucket; public final double waterWalkSpeed; @@ -111,6 +112,7 @@ public class CalculationContext { this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value; this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value; this.allowDownward = Baritone.settings().allowDownward.value; + this.minFallHeight = 3; // Minimum fall height used by MovementFall this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.value; this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.value; int depth = EnchantmentHelper.getDepthStriderModifier(player); diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java index 51275bc00..032171fe9 100644 --- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java +++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java @@ -154,10 +154,11 @@ public class MovementDescend extends Movement { // this check prevents it from getting the block at y=-1 and crashing return false; } + boolean reachedMinimum = fallHeight >= context.minFallHeight; IBlockState ontoBlock = context.get(destX, newY, destZ); int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; - if (MovementHelper.isWater(ontoBlock.getBlock())) { + if (reachedMinimum && MovementHelper.isWater(ontoBlock.getBlock())) { if (!MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) { return false; } @@ -178,7 +179,7 @@ public class MovementDescend extends Movement { res.cost = tentativeCost;// TODO incorporate water swim up cost? return false; } - if (fallHeight >= 8 && context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { + if (reachedMinimum && context.allowFallIntoLava && MovementHelper.isLava(ontoBlock.getBlock())) { // found a fall into lava res.x = destX; res.y = newY; @@ -203,7 +204,7 @@ public class MovementDescend extends Movement { if (MovementHelper.isBottomSlab(ontoBlock)) { return false; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect } - if (unprotectedFallHeight <= context.maxFallHeightNoWater + 1) { + if (reachedMinimum && unprotectedFallHeight <= context.maxFallHeightNoWater + 1) { // fallHeight = 4 means onto.up() is 3 blocks down, which is the max res.x = destX; res.y = newY + 1; @@ -211,7 +212,7 @@ public class MovementDescend extends Movement { res.cost = tentativeCost; return false; } - if (context.hasWaterBucket && unprotectedFallHeight <= context.maxFallHeightBucket + 1) { + if (reachedMinimum && context.hasWaterBucket && unprotectedFallHeight <= context.maxFallHeightBucket + 1) { res.x = destX; res.y = newY + 1;// this is the block we're falling onto, so dest is +1 res.z = destZ; From fe67489419dd3025e74e6700636814adf1dfb3ac Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 14:38:11 -0700 Subject: [PATCH 172/276] Combine `VALIDATE_PATH` and `LOCATE_JUMP` states --- src/main/java/baritone/behavior/ElytraBehavior.java | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 6374e7524..f08fb9be6 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1278,11 +1278,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H 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() @@ -1315,7 +1310,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } } - return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new WalkOffCalculationContext(baritone)); } // yucky @@ -1373,8 +1368,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H switch (this.state) { case LOCATE_JUMP: return "Finding spot to jump off"; - case VALIDATE_PATH: - return "Validating path"; case PAUSE: return "Waiting for elytra path"; case GET_TO_JUMP: From 487b3a759aaebaae9bd5c757261a0376cc54dff5 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 18:35:02 -0700 Subject: [PATCH 173/276] `mostRecentGoal`, fixes immediate goal clear --- .../java/baritone/api/process/ICustomGoalProcess.java | 5 +++++ .../java/baritone/command/defaults/ElytraCommand.java | 2 +- src/main/java/baritone/process/CustomGoalProcess.java | 11 +++++++++++ 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/process/ICustomGoalProcess.java b/src/api/java/baritone/api/process/ICustomGoalProcess.java index 5084aff2f..2bae55ce3 100644 --- a/src/api/java/baritone/api/process/ICustomGoalProcess.java +++ b/src/api/java/baritone/api/process/ICustomGoalProcess.java @@ -38,6 +38,11 @@ public interface ICustomGoalProcess extends IBaritoneProcess { */ Goal getGoal(); + /** + * @return The most recent set goal, which doesn't invalidate upon {@link #onLostControl()} + */ + Goal mostRecentGoal(); + /** * Sets the goal and begins the path execution. * diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 93c4c2544..cd7034ef8 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -42,7 +42,7 @@ public class ElytraCommand extends Command { public void execute(String label, IArgConsumer args) throws CommandException { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); - Goal iGoal = customGoalProcess.getGoal(); + Goal iGoal = customGoalProcess.mostRecentGoal(); if (iGoal == null) { throw new CommandInvalidStateException("No goal has been set"); } diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java index ea9ff2092..71d212b38 100644 --- a/src/main/java/baritone/process/CustomGoalProcess.java +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -36,6 +36,11 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC */ private Goal goal; + /** + * The most recent goal. Not invalidated upon {@link #onLostControl()} + */ + private Goal mostRecentGoal; + /** * The current process state. * @@ -50,6 +55,7 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC @Override public void setGoal(Goal goal) { this.goal = goal; + this.mostRecentGoal = goal; if (this.state == State.NONE) { this.state = State.GOAL_SET; } @@ -68,6 +74,11 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC return this.goal; } + @Override + public Goal mostRecentGoal() { + return this.mostRecentGoal; + } + @Override public boolean isActive() { return this.state != State.NONE; From c0cdfb7781e86b9c89bae4c9930d3a0461fb8512 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 7 Jul 2023 19:44:59 -0700 Subject: [PATCH 174/276] Add commands for pathfinder reset and chunk repack --- .../api/behavior/IElytraBehavior.java | 12 ++++ .../baritone/behavior/ElytraBehavior.java | 30 +++++++-- .../command/defaults/ElytraCommand.java | 67 +++++++++++++------ 3 files changed, 80 insertions(+), 29 deletions(-) diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/behavior/IElytraBehavior.java index 3c3b91466..21169b896 100644 --- a/src/api/java/baritone/api/behavior/IElytraBehavior.java +++ b/src/api/java/baritone/api/behavior/IElytraBehavior.java @@ -19,8 +19,20 @@ package baritone.api.behavior; import net.minecraft.util.math.BlockPos; +import java.util.concurrent.CompletableFuture; + public interface IElytraBehavior extends IBehavior { + /** + * Marks the nether pathfinder context to be reset when it is safe to do so. Because this operation is not + * immediate, a {@link CompletableFuture} is returned that will complete after the context has been reset. + * + * @return A {@link CompletableFuture} that is completed when the context is reset + */ + CompletableFuture resetContext(); + + void repackChunks(); + void pathTo(BlockPos destination); void cancel(); diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index f08fb9be6..5549281f7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -41,6 +41,7 @@ import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.movements.MovementFall; import baritone.utils.BlockStateInterface; import baritone.utils.PathingCommandContext; +import baritone.utils.accessor.IChunkProviderClient; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; @@ -76,7 +77,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private NetherPathfinderContext context; - private boolean forceResetContext; + private CompletableFuture forceResetContext; private final PathManager pathManager; private final ElytraProcess process; @@ -370,7 +371,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (event.getWorld() != null) { if (event.getState() == EventState.PRE) { // Reset the context when it's safe to do so on the next game tick - this.forceResetContext = true; + this.resetContext(); } } else { if (event.getState() == EventState.POST) { @@ -429,6 +430,20 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Arrays.fill(this.nextTickBoostCounter, 0); } + @Override + public CompletableFuture resetContext() { + if (this.forceResetContext == null) { + this.forceResetContext = new CompletableFuture<>(); + } + return this.forceResetContext; + } + + @Override + public void repackChunks() { + ((IChunkProviderClient) ctx.world().getChunkProvider()).loadedChunks().values() + .forEach(this.context::queueForPacking); + } + @Override public boolean isActive() { return baritone.getPathingControlManager().mostRecentInControl() @@ -455,15 +470,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Setup/reset context final long netherSeed = Baritone.settings().elytraNetherSeed.value; - if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext) { + if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext != null) { if (this.context != null) { this.context.destroy(); } this.context = new NetherPathfinderContext(netherSeed); - this.forceResetContext = false; - - if (this.isActive()) { - // TODO: Re-pack chunks? + if (this.forceResetContext != null) { + this.forceResetContext.complete(null); + this.forceResetContext = null; + } + if (this.context.getSeed() != netherSeed && this.isActive()) { logDirect("Nether seed changed, recalculating path"); this.pathManager.pathToDestination(); } diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index cd7034ef8..de8cbadef 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -18,6 +18,7 @@ package baritone.command.defaults; import baritone.api.IBaritone; +import baritone.api.behavior.IElytraBehavior; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; @@ -40,30 +41,52 @@ public class ElytraCommand extends Command { @Override public void execute(String label, IArgConsumer args) throws CommandException { - ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); - args.requireMax(0); - Goal iGoal = customGoalProcess.mostRecentGoal(); - if (iGoal == null) { - throw new CommandInvalidStateException("No goal has been set"); + final ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); + final IElytraBehavior elytra = baritone.getElytraBehavior(); + if (!args.hasAny()) { + Goal iGoal = customGoalProcess.mostRecentGoal(); + if (iGoal == null) { + throw new CommandInvalidStateException("No goal has been set"); + } + final int x, y, z; + if (iGoal instanceof GoalXZ) { + GoalXZ goal = (GoalXZ) iGoal; + x = goal.getX(); + y = 64; + z = goal.getZ(); + } else if (iGoal instanceof GoalBlock) { + GoalBlock goal = (GoalBlock) iGoal; + x = goal.x; + y = goal.y; + z = goal.z; + } else { + throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + } + if (y <= 0 || y >= 128) { + throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); + } + elytra.pathTo(new BlockPos(x, y, z)); + return; } - final int x, y, z; - if (iGoal instanceof GoalXZ) { - GoalXZ goal = (GoalXZ) iGoal; - x = goal.getX(); - y = 64; - z = goal.getZ(); - } else if (iGoal instanceof GoalBlock) { - GoalBlock goal = (GoalBlock) iGoal; - x = goal.x; - y = goal.y; - z = goal.z; - } else { - throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + + final String action = args.getString(); + switch (action) { + case "reset": { + elytra.resetContext().whenComplete((result, ex) -> { + logDirect("Context reset, repacking chunks"); + elytra.repackChunks(); + }); + break; + } + case "repack": { + elytra.repackChunks(); + logDirect("Queued all loaded chunks for repacking"); + break; + } + default: { + throw new CommandInvalidStateException("Invalid action"); + } } - if (y <= 0 || y >= 128) { - throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); - } - baritone.getElytraBehavior().pathTo(new BlockPos(x, y, z)); } @Override From 7a935fb2ea3cf491497b09b7a73b51a27f9ae83c Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 9 Jul 2023 09:12:21 -0700 Subject: [PATCH 175/276] Fix simulation not respecting `ignoreLava` --- build.gradle | 4 ++-- src/main/java/baritone/behavior/ElytraBehavior.java | 6 +++--- 2 files changed, 5 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 99d7cc823..686f2bfbc 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.21') + launchImplementation('dev.babbaj:nether-pathfinder:0.22') testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.21' + implementation 'dev.babbaj:nether-pathfinder:0.22' } mixin { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 5549281f7..bc2485b47 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -386,7 +386,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void onChunkEvent(ChunkEvent event) { - if (event.isPostPopulate()) { + if (event.isPostPopulate() && this.context != null) { final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); this.context.queueForPacking(chunk); } @@ -1069,13 +1069,13 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Ensure that the goal is visible along the entire simulated path // Reverse order iteration since the last position is most likely to fail for (int i = result.steps.size() - 1; i >= 1; i--) { - if (!clearView(context.start.add(result.steps.get(i)), goal, false)) { + if (!clearView(context.start.add(result.steps.get(i)), goal, context.ignoreLava)) { continue outer; } } } else { // Ensure that the goal is visible from the final position - if (!clearView(context.start.add(result.steps.get(result.steps.size() - 1)), goal, false)) { + if (!clearView(context.start.add(result.steps.get(result.steps.size() - 1)), goal, context.ignoreLava)) { continue; } } From 96a64b454ed62dab970afbe75e31f695ecd3b8a1 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 9 Jul 2023 22:29:31 -0400 Subject: [PATCH 176/276] optimize uploading chunk data --- build.gradle | 4 +- .../elytra/NetherPathfinderContext.java | 60 ++++++++++++++++++- 2 files changed, 59 insertions(+), 5 deletions(-) diff --git a/build.gradle b/build.gradle index 686f2bfbc..da0e2232b 100755 --- a/build.gradle +++ b/build.gradle @@ -175,9 +175,9 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.22') + launchImplementation('dev.babbaj:nether-pathfinder:0.24') + implementation 'dev.babbaj:nether-pathfinder:0.24' testImplementation 'junit:junit:4.12' - implementation 'dev.babbaj:nether-pathfinder:0.22' } mixin { diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 3fd7987e5..ed179b5b4 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -17,10 +17,14 @@ package baritone.behavior.elytra; +import baritone.utils.accessor.IBitArray; +import baritone.utils.accessor.IBlockStateContainer; import dev.babbaj.pathfinder.NetherPathfinder; +import dev.babbaj.pathfinder.Octree; import dev.babbaj.pathfinder.PathSegment; -import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; +import net.minecraft.util.BitArray; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.BlockStateContainer; @@ -55,7 +59,8 @@ public final class NetherPathfinderContext { // and prune the oldest chunks per chunkPackerQueueMaxSize final Chunk chunk = ref.get(); if (chunk != null) { - NetherPathfinder.insertChunkData(this.context, chunk.x, chunk.z, pack(chunk)); + long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); + writeChunkData(chunk, ptr); } }); } @@ -144,6 +149,8 @@ public final class NetherPathfinderContext { return this.seed; } + private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); + private static boolean[] pack(Chunk chunk) { try { boolean[] packed = new boolean[16 * 16 * 128]; @@ -160,7 +167,7 @@ public final class NetherPathfinderContext { for (int z = 0; z < 16; z++) { for (int x = 0; x < 16; x++) { IBlockState state = bsc.get(x, y1, z); - packed[x | (z << 4) | (y << 8)] = state.getMaterial() != Material.AIR; + packed[x | (z << 4) | (y << 8)] = state != AIR_BLOCK_STATE; } } } @@ -172,6 +179,53 @@ public final class NetherPathfinderContext { } } + private static void writeChunkData(Chunk chunk, long ptr) { + try { + ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); + for (int y0 = 0; y0 < 8; y0++) { + final ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; + if (extendedblockstorage == null) { + continue; + } + final BlockStateContainer bsc = extendedblockstorage.getData(); + final int airId = ((IBlockStateContainer) bsc).getPalette().idFor(AIR_BLOCK_STATE); + // pasted from FasterWorldScanner + final BitArray array = ((IBlockStateContainer) bsc).getStorage(); + if (array == null) continue; + final long[] longArray = array.getBackingLongArray(); + final int arraySize = array.size(); + final int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); + final long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); + + final int yReal = y0 << 4; + for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { + final int i = idx * bitsPerEntry; + final int j = i >> 6; + final int l = i & 63; + final int k = kl >> 6; + final long jl = longArray[j] >>> l; + + final int id; + if (j == k) { + id = (int) (jl & maxEntryValue); + } else { + id = (int) ((jl | longArray[k] << (64 - l)) & maxEntryValue); + } + Octree.setBlock(ptr, + ((idx & 255) & 15), + yReal + (idx >> 8), + ((idx & 255) >> 4), + id != airId + ); + } + } + Octree.setIsFromJava(ptr); + } catch (Exception e) { + e.printStackTrace(); + throw new RuntimeException(e); + } + } + public static final class Visibility { public static final int ALL = 0; From eec4edea059416188daca4f2f6e429a87799c38e Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 9 Jul 2023 20:00:35 -0700 Subject: [PATCH 177/276] Remove old pack method --- .../elytra/NetherPathfinderContext.java | 32 ++----------------- 1 file changed, 2 insertions(+), 30 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index ed179b5b4..b4f3daa9a 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -42,6 +42,8 @@ import java.util.concurrent.TimeUnit; */ public final class NetherPathfinderContext { + private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); + private final long context; private final long seed; private final ExecutorService executor; @@ -149,36 +151,6 @@ public final class NetherPathfinderContext { return this.seed; } - private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); - - private static boolean[] pack(Chunk chunk) { - try { - boolean[] packed = new boolean[16 * 16 * 128]; - ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); - for (int y0 = 0; y0 < 8; y0++) { - ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; - if (extendedblockstorage == null) { - continue; - } - BlockStateContainer bsc = extendedblockstorage.getData(); - int yReal = y0 << 4; - for (int y1 = 0; y1 < 16; y1++) { - int y = y1 | yReal; - for (int z = 0; z < 16; z++) { - for (int x = 0; x < 16; x++) { - IBlockState state = bsc.get(x, y1, z); - packed[x | (z << 4) | (y << 8)] = state != AIR_BLOCK_STATE; - } - } - } - } - return packed; - } catch (Exception e) { - e.printStackTrace(); - throw new RuntimeException(e); - } - } - private static void writeChunkData(Chunk chunk, long ptr) { try { ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); From dc53a95befb002a01d8d75b5de2755e485754323 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 10 Jul 2023 00:45:12 -0400 Subject: [PATCH 178/276] don't send the whole chunk for small changes --- .../api/event/events/BlockChangeEvent.java | 8 ++++---- .../java/baritone/behavior/ElytraBehavior.java | 4 +--- .../behavior/elytra/NetherPathfinderContext.java | 16 ++++++++++++++++ .../java/baritone/event/GameEventHandler.java | 6 +++--- 4 files changed, 24 insertions(+), 10 deletions(-) diff --git a/src/api/java/baritone/api/event/events/BlockChangeEvent.java b/src/api/java/baritone/api/event/events/BlockChangeEvent.java index 152c435ae..a65a51f35 100644 --- a/src/api/java/baritone/api/event/events/BlockChangeEvent.java +++ b/src/api/java/baritone/api/event/events/BlockChangeEvent.java @@ -31,16 +31,16 @@ import java.util.Set; */ public final class BlockChangeEvent { - private final Set affectedChunks; + private final ChunkPos chunk; private final List> blocks; public BlockChangeEvent(ChunkPos pos, List> blocks) { - this.affectedChunks = Collections.singleton(pos); + this.chunk = pos; this.blocks = blocks; } - public Set getAffectedChunks() { - return this.affectedChunks; + public ChunkPos getChunkPos() { + return this.chunk; } public List> getBlocks() { diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index bc2485b47..93bcbb5bf 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -394,9 +394,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H @Override public void onBlockChange(BlockChangeEvent event) { - event.getAffectedChunks().stream() - .map(pos -> ctx.world().getChunk(pos.x, pos.z)) - .forEach(this.context::queueForPacking); + this.context.queueBlockUpdate(event); } @Override diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index ed179b5b4..aaa4c62bf 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -17,6 +17,7 @@ package baritone.behavior.elytra; +import baritone.api.event.events.BlockChangeEvent; import baritone.utils.accessor.IBitArray; import baritone.utils.accessor.IBlockStateContainer; import dev.babbaj.pathfinder.NetherPathfinder; @@ -26,6 +27,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.BitArray; import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.Chunk; @@ -65,6 +67,20 @@ public final class NetherPathfinderContext { }); } + public void queueBlockUpdate(BlockChangeEvent event) { + this.executor.execute(() -> { + ChunkPos chunkPos = event.getChunkPos(); + long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); + if (ptr == 0) return; // this shouldn't ever happen + event.getBlocks().forEach(pair -> { + BlockPos pos = pair.first(); + if (pos.getY() >= 128) return; + boolean isSolid = pair.second() != AIR_BLOCK_STATE; + Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); + }); + }); + } + public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { return CompletableFuture.supplyAsync(() -> { final PathSegment segment = NetherPathfinder.pathFind( diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java index d26f2de24..1027a0126 100644 --- a/src/main/java/baritone/event/GameEventHandler.java +++ b/src/main/java/baritone/event/GameEventHandler.java @@ -28,6 +28,7 @@ import baritone.cache.CachedChunk; import baritone.cache.WorldProvider; import baritone.utils.BlockStateInterface; import net.minecraft.block.state.IBlockState; +import net.minecraft.util.math.ChunkPos; import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; @@ -117,9 +118,8 @@ public final class GameEventHandler implements IEventBus, Helper { if (keepingTrackOf) { baritone.getWorldProvider().ifWorldLoaded(worldData -> { final World world = baritone.getPlayerContext().world(); - event.getAffectedChunks().stream() - .map(pos -> world.getChunk(pos.x, pos.z)) - .forEach(worldData.getCachedWorld()::queueForPacking); + ChunkPos pos = event.getChunkPos(); + worldData.getCachedWorld().queueForPacking(world.getChunk(pos.x, pos.z)); }); } } From 5dc403e643c9f641373b7e8889badd28281eeefb Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 10 Jul 2023 00:12:10 -0700 Subject: [PATCH 179/276] crucial performance optimization --- .../baritone/behavior/ElytraBehavior.java | 31 ++++++++++++------- 1 file changed, 20 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 93bcbb5bf..ec2363f29 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -33,8 +33,8 @@ import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.*; import baritone.api.utils.input.Input; -import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.NetherPath; +import baritone.behavior.elytra.NetherPathfinderContext; import baritone.behavior.elytra.PathCalculationException; import baritone.behavior.elytra.UnpackedSegment; import baritone.pathing.movement.CalculationContext; @@ -54,7 +54,10 @@ import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketPlayerPosLook; import net.minecraft.util.EnumHand; -import net.minecraft.util.math.*; +import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.MathHelper; +import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.Chunk; import java.util.*; @@ -716,9 +719,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final IAimProcessor aimProcessor; public SolverContext(boolean async) { - this.path = ElytraBehavior.this.pathManager.getPath(); + this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); - this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); + this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); this.ignoreLava = ElytraBehavior.this.ctx.player().isInLava(); final Integer fireworkTicksExisted; @@ -863,10 +866,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Optional getAttachedFirework() { return ctx.world().loadedEntityList.stream() - .filter(x -> x instanceof EntityFireworkRocket) - .filter(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())) - .map(x -> (EntityFireworkRocket) x) - .findFirst(); + .filter(x -> x instanceof EntityFireworkRocket) + .filter(x -> Objects.equals(((IEntityFireworkRocket) x).getBoostedEntity(), ctx.player())) + .map(x -> (EntityFireworkRocket) x) + .findFirst(); } private boolean isHitboxClear(final SolverContext context, final Vec3d dest, final Double growAmount) { @@ -1113,9 +1116,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // Collision box while the player is in motion, with additional padding for safety final AxisAlignedBB inMotion = hitbox.expand(motion.x, motion.y, motion.z).grow(0.01); - for (int x = fastFloor(inMotion.minX); x < fastCeil(inMotion.maxX); x++) { - for (int y = fastFloor(inMotion.minY); y < fastCeil(inMotion.maxY); y++) { - for (int z = fastFloor(inMotion.minZ); z < fastCeil(inMotion.maxZ); z++) { + int xmin = fastFloor(inMotion.minX); + int xmax = fastCeil(inMotion.maxX); + int ymin = fastFloor(inMotion.minY); + int ymax = fastCeil(inMotion.maxY); + int zmin = fastFloor(inMotion.minZ); + int zmax = fastCeil(inMotion.maxZ); + for (int x = xmin; x < xmax; x++) { + for (int y = ymin; y < ymax; y++) { + for (int z = zmin; z < zmax; z++) { if (!this.passable(x, y, z, ignoreLava)) { return null; } From 349c951b5538d8f6b0eb653e99792d99f3f5dde1 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 11 Jul 2023 22:47:09 -0500 Subject: [PATCH 180/276] Better handling of unsupported systems --- .../api/behavior/IElytraBehavior.java | 10 +++ src/main/java/baritone/Baritone.java | 5 +- .../baritone/behavior/ElytraBehavior.java | 72 ++++++++++++++++--- .../elytra/NetherPathfinderContext.java | 4 ++ .../behavior/elytra/NullElytraBehavior.java | 70 ++++++++++++++++++ .../command/defaults/ElytraCommand.java | 11 +++ src/main/java/baritone/utils/IRenderer.java | 13 ++++ .../java/baritone/utils/PathRenderer.java | 59 +-------------- 8 files changed, 177 insertions(+), 67 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/NullElytraBehavior.java diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/behavior/IElytraBehavior.java index 21169b896..95ae62926 100644 --- a/src/api/java/baritone/api/behavior/IElytraBehavior.java +++ b/src/api/java/baritone/api/behavior/IElytraBehavior.java @@ -41,4 +41,14 @@ public interface IElytraBehavior extends IBehavior { * Returns {@code true} if the current {@link IElytraBehavior} is actively pathing. */ boolean isActive(); + + /** + * @return {@code true} if the native library loaded and elytra is actually usable + */ + boolean isLoaded(); + + /* + * FOR INTERNAL USE ONLY. MAY BE REMOVED AT ANY TIME. + */ + boolean isSafeToCancel(); } diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 805fb0488..970bfc0a9 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -21,6 +21,7 @@ import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.Settings; import baritone.api.behavior.IBehavior; +import baritone.api.behavior.IElytraBehavior; import baritone.api.event.listener.IEventBus; import baritone.api.process.IBaritoneProcess; import baritone.api.utils.IPlayerContext; @@ -107,7 +108,7 @@ public class Baritone implements IBaritone { { this.lookBehavior = this.registerBehavior(LookBehavior::new); - this.elytraBehavior = this.registerBehavior(ElytraBehavior::new); + this.elytraBehavior = this.registerBehavior(ElytraBehavior::create); this.pathingBehavior = this.registerBehavior(PathingBehavior::new); this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new); this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new); @@ -240,7 +241,7 @@ public class Baritone implements IBaritone { } @Override - public ElytraBehavior getElytraBehavior() { + public IElytraBehavior getElytraBehavior() { return this.elytraBehavior; } diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index ec2363f29..7fc47032b 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -19,12 +19,14 @@ package baritone.behavior; import baritone.Baritone; import baritone.api.IBaritone; +import baritone.api.Settings; 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.event.events.type.EventState; import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalYLevel; import baritone.api.pathing.movement.IMovement; import baritone.api.pathing.path.IPathExecutor; @@ -33,13 +35,12 @@ import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.*; import baritone.api.utils.input.Input; -import baritone.behavior.elytra.NetherPath; -import baritone.behavior.elytra.NetherPathfinderContext; -import baritone.behavior.elytra.PathCalculationException; -import baritone.behavior.elytra.UnpackedSegment; +import baritone.behavior.elytra.*; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.movements.MovementFall; import baritone.utils.BlockStateInterface; +import baritone.utils.IRenderer; +import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.accessor.IChunkProviderClient; import baritone.utils.accessor.IEntityFireworkRocket; @@ -60,7 +61,9 @@ import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.Chunk; +import java.awt.*; import java.util.*; +import java.util.List; import java.util.concurrent.*; import java.util.function.Supplier; import java.util.function.UnaryOperator; @@ -112,7 +115,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Solution pendingSolution; private boolean solveNextTick; - public ElytraBehavior(Baritone baritone) { + private ElytraBehavior(Baritone baritone) { super(baritone); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); @@ -369,6 +372,45 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + @Override + public void onRenderPass(RenderEvent event) { + final Settings settings = Baritone.settings(); + if (this.visiblePath != null) { + PathRenderer.drawPath(this.visiblePath, 0, Color.RED, false, 0, 0, 0.0D); + } + if (this.aimPos != null) { + PathRenderer.drawGoal(ctx.player(), new GoalBlock(this.aimPos), event.getPartialTicks(), Color.GREEN); + } + if (!this.clearLines.isEmpty() && settings.renderRaytraces.value) { + IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + for (Pair line : this.clearLines) { + IRenderer.emitLine(line.first(), line.second()); + } + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } + if (!this.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { + IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + for (Pair line : this.blockedLines) { + IRenderer.emitLine(line.first(), line.second()); + } + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } + if (this.simulationLine != null && Baritone.settings().renderElytraSimulation.value) { + IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); + final Vec3d offset = new Vec3d( + ctx.player().prevPosX + (ctx.player().posX - ctx.player().prevPosX) * event.getPartialTicks(), + ctx.player().prevPosY + (ctx.player().posY - ctx.player().prevPosY) * event.getPartialTicks(), + ctx.player().prevPosZ + (ctx.player().posZ - ctx.player().prevPosZ) * event.getPartialTicks() + ); + for (int i = 0; i < this.simulationLine.size() - 1; i++) { + final Vec3d src = this.simulationLine.get(i).add(offset); + final Vec3d dst = this.simulationLine.get(i + 1).add(offset); + IRenderer.emitLine(src, dst); + } + IRenderer.endLines(settings.renderPathIgnoreDepth.value); + } + } + @Override public void onWorldEvent(WorldEvent event) { if (event.getWorld() != null) { @@ -451,6 +493,16 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H .filter(process -> this.process == process).isPresent(); } + @Override + public boolean isLoaded() { + return true; + } + + @Override + public boolean isSafeToCancel() { + return !this.isActive() || !(this.process.state == State.FLYING || this.process.state == State.START_FLYING); + } + @Override public void onTick(final TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { @@ -1261,10 +1313,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - public boolean isSafeToCancel() { - return !this.isActive() || !(this.process.state == State.FLYING || this.process.state == State.START_FLYING); - } - private final class ElytraProcess implements IBaritoneProcess { private State state; @@ -1443,4 +1491,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H START_FLYING, FLYING } + + public static T create(final Baritone baritone) { + return (T) (NetherPathfinderContext.isSupported() + ? new ElytraBehavior(baritone) + : new NullElytraBehavior(baritone)); + } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index a30cb4aa1..9bbb2a24a 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -222,4 +222,8 @@ public final class NetherPathfinderContext { private Visibility() {} } + + public static boolean isSupported() { + return NetherPathfinder.isThisSystemSupported(); + } } diff --git a/src/main/java/baritone/behavior/elytra/NullElytraBehavior.java b/src/main/java/baritone/behavior/elytra/NullElytraBehavior.java new file mode 100644 index 000000000..b173d82b8 --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/NullElytraBehavior.java @@ -0,0 +1,70 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +import baritone.Baritone; +import baritone.api.behavior.IElytraBehavior; +import baritone.behavior.Behavior; +import net.minecraft.util.math.BlockPos; + +import java.util.concurrent.CompletableFuture; + +/** + * @author Brady + */ +public final class NullElytraBehavior extends Behavior implements IElytraBehavior { + + public NullElytraBehavior(Baritone baritone) { + super(baritone); + } + + @Override + public CompletableFuture resetContext() { + throw new UnsupportedOperationException("Called resetContext() on NullElytraBehavior"); + } + + @Override + public void repackChunks() { + throw new UnsupportedOperationException("Called repackChunks() on NullElytraBehavior"); + } + + @Override + public void pathTo(BlockPos destination) { + throw new UnsupportedOperationException("Called pathTo() on NullElytraBehavior"); + } + + @Override + public void cancel() { + throw new UnsupportedOperationException("Called cancel() on NullElytraBehavior"); + } + + @Override + public boolean isActive() { + return false; + } + + @Override + public boolean isLoaded() { + return false; + } + + @Override + public boolean isSafeToCancel() { + return true; + } +} diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index de8cbadef..252559b75 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -43,6 +43,17 @@ public class ElytraCommand extends Command { public void execute(String label, IArgConsumer args) throws CommandException { final ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); final IElytraBehavior elytra = baritone.getElytraBehavior(); + if (!elytra.isLoaded()) { + final String osArch = System.getProperty("os.arch"); + final String osName = System.getProperty("os.name"); + throw new CommandInvalidStateException(String.format( + "legacy architectures are not supported. your CPU is %s and your operating system is %s." + + "supported architectures are x86_64 or arm64, supported operating systems are windows," + + "linux, and mac", + osArch, osName + )); + } + if (!args.hasAny()) { Goal iGoal = customGoalProcess.mostRecentGoal(); if (iGoal == null) { diff --git a/src/main/java/baritone/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java index 680d7e380..3fd5c2556 100644 --- a/src/main/java/baritone/utils/IRenderer.java +++ b/src/main/java/baritone/utils/IRenderer.java @@ -27,6 +27,7 @@ import net.minecraft.client.renderer.entity.RenderManager; import net.minecraft.client.renderer.texture.TextureManager; import net.minecraft.client.renderer.vertex.DefaultVertexFormats; import net.minecraft.util.math.AxisAlignedBB; +import net.minecraft.util.math.Vec3d; import java.awt.*; @@ -120,4 +121,16 @@ public interface IRenderer { emitAABB(aabb); tessellator.draw(); } + + static void emitLine(Vec3d start, Vec3d end) { + emitLine(start.x, start.y, start.z, end.x, end.y, end.z); + } + + static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) { + double vpX = renderManager.viewerPosX; + double vpY = renderManager.viewerPosY; + double vpZ = renderManager.viewerPosZ; + buffer.pos(x1 - vpX, y1 - vpY, z1 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + buffer.pos(x2 - vpX, y2 - vpY, z2 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); + } } diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index eb7615de8..0fcad054a 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -17,15 +17,12 @@ package baritone.utils; -import baritone.Baritone; import baritone.api.BaritoneAPI; import baritone.api.event.events.RenderEvent; import baritone.api.pathing.goals.*; import baritone.api.utils.BetterBlockPos; import baritone.api.utils.IPlayerContext; -import baritone.api.utils.Pair; import baritone.api.utils.interfaces.IGoalRenderPos; -import baritone.behavior.ElytraBehavior; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; import net.minecraft.block.state.IBlockState; @@ -102,44 +99,6 @@ public final class PathRenderer implements IRenderer { drawPath(next.getPath().positions(), 0, settings.colorNextPath.value, settings.fadePath.value, 10, 20); } - final ElytraBehavior elytra = behavior.baritone.getElytraBehavior(); - - 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); - } - if (!elytra.clearLines.isEmpty() && Baritone.settings().renderRaytraces.value) { - IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); - for (Pair line : elytra.clearLines) { - emitLine(line.first(), line.second()); - } - IRenderer.endLines(settings.renderPathIgnoreDepth.value); - } - if (!elytra.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { - IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); - for (Pair line : elytra.blockedLines) { - emitLine(line.first(), line.second()); - } - IRenderer.endLines(settings.renderPathIgnoreDepth.value); - } - if (elytra.simulationLine != null && Baritone.settings().renderElytraSimulation.value) { - IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); - final Vec3d offset = new Vec3d( - ctx.player().prevPosX + (ctx.player().posX - ctx.player().prevPosX) * partialTicks, - ctx.player().prevPosY + (ctx.player().posY - ctx.player().prevPosY) * partialTicks, - ctx.player().prevPosZ + (ctx.player().posZ - ctx.player().prevPosZ) * partialTicks - ); - for (int i = 0; i < elytra.simulationLine.size() - 1; i++) { - final Vec3d src = elytra.simulationLine.get(i).add(offset); - final Vec3d dst = elytra.simulationLine.get(i + 1).add(offset); - emitLine(src, dst); - } - IRenderer.endLines(settings.renderPathIgnoreDepth.value); - } - - // If there is a path calculation currently running, render the path calculation process behavior.getInProgress().ifPresent(currentlyRunning -> { currentlyRunning.bestPathSoFar().ifPresent(p -> { @@ -153,11 +112,11 @@ public final class PathRenderer implements IRenderer { }); } - private static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { + public static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) { drawPath(positions, startIndex, color, fadeOut, fadeStart0, fadeEnd0, 0.5D); } - private static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0, double offset) { + public static void drawPath(List positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0, double offset) { IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); int fadeStart = fadeStart0 + startIndex; @@ -199,18 +158,6 @@ public final class PathRenderer implements IRenderer { IRenderer.endLines(settings.renderPathIgnoreDepth.value); } - private static void emitLine(Vec3d start, Vec3d end) { - emitLine(start.x, start.y, start.z, end.x, end.y, end.z); - } - - private static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) { - double vpX = renderManager.viewerPosX; - double vpY = renderManager.viewerPosY; - double vpZ = renderManager.viewerPosZ; - buffer.pos(x1 - vpX, y1 - vpY, z1 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - buffer.pos(x2 - vpX, y2 - vpY, z2 - vpZ).color(color[0], color[1], color[2], color[3]).endVertex(); - } - private static void emitPathLine(double x1, double y1, double z1, double x2, double y2, double z2, double offset) { final double extraOffset = offset + 0.03D; double vpX = renderManager.viewerPosX; @@ -255,7 +202,7 @@ public final class PathRenderer implements IRenderer { IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value); } - private static void drawGoal(Entity player, Goal goal, float partialTicks, Color color) { + public static void drawGoal(Entity player, Goal goal, float partialTicks, Color color) { drawGoal(player, goal, partialTicks, color, true); } From 7c696b70555a8a759d49565d4ebf6a855ff2cf2a Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 11 Jul 2023 22:49:51 -0500 Subject: [PATCH 181/276] trolled --- src/main/java/baritone/Baritone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 970bfc0a9..61866e927 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -68,7 +68,7 @@ public class Baritone implements IBaritone { private final List behaviors; private final PathingBehavior pathingBehavior; - private final ElytraBehavior elytraBehavior; + private final IElytraBehavior elytraBehavior; private final LookBehavior lookBehavior; private final InventoryBehavior inventoryBehavior; private final InputOverrideHandler inputOverrideHandler; From 8f5105c4546560a93f0acf0d0141e8f1b9f2fd3b Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 11 Jul 2023 22:50:35 -0500 Subject: [PATCH 182/276] trolled pt2 --- src/main/java/baritone/command/defaults/ElytraCommand.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 252559b75..298a23cd7 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -47,8 +47,8 @@ public class ElytraCommand extends Command { final String osArch = System.getProperty("os.arch"); final String osName = System.getProperty("os.name"); throw new CommandInvalidStateException(String.format( - "legacy architectures are not supported. your CPU is %s and your operating system is %s." + - "supported architectures are x86_64 or arm64, supported operating systems are windows," + + "legacy architectures are not supported. your CPU is %s and your operating system is %s. " + + "supported architectures are x86_64 or arm64, supported operating systems are windows, " + "linux, and mac", osArch, osName )); From 42771686c6534cdebb4205597311c7011d192f55 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Wed, 12 Jul 2023 16:42:14 -0400 Subject: [PATCH 183/276] auto swap elytra --- src/api/java/baritone/api/Settings.java | 15 +++++ .../baritone/behavior/ElytraBehavior.java | 55 +++++++++++++++++++ .../elytra/NetherPathfinderContext.java | 10 ++-- 3 files changed, 74 insertions(+), 6 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 08fe54d3a..3f039fe91 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1394,6 +1394,21 @@ public final class Settings { */ public final Setting elytraNetherSeed = new Setting<>(146008555100680L); + /** + * Automatically swap the current elytra with a new one when the durability gets too low + */ + public final Setting elytraAutoSwap = new Setting<>(true); + + /** + * The minimum durability an elytra can have before being swapped + */ + public final Setting elytraMinimumDurability = new Setting<>(5); + + /** + * The number of ticks between doing inventory clicks + */ + public final Setting elytraInventoryTicks = new Setting<>(5); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 7fc47032b..c39950f33 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -51,10 +51,12 @@ import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.init.Items; +import net.minecraft.inventory.ClickType; import net.minecraft.item.ItemStack; import net.minecraft.nbt.NBTTagCompound; import net.minecraft.network.play.server.SPacketPlayerPosLook; import net.minecraft.util.EnumHand; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; @@ -115,6 +117,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Solution pendingSolution; private boolean solveNextTick; + // auto swap + private int tickCounter; + private int tickLastTransaction = -Baritone.settings().elytraInventoryTicks.value; + private final Queue transactionQueue = new LinkedList<>(); + private ElytraBehavior(Baritone baritone) { super(baritone); this.clearLines = new CopyOnWriteArrayList<>(); @@ -585,6 +592,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } + trySwapElytra(); + if (ctx.player().collidedHorizontally) { logDirect("hbonk"); } @@ -1248,6 +1257,50 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); } + private void tickInventoryTransactions() { + if (tickCounter - tickLastTransaction > Baritone.settings().elytraInventoryTicks.value) { + Runnable r = transactionQueue.poll(); + if (r != null) { + r.run(); + tickLastTransaction = tickCounter; + } + } + tickCounter++; + } + + private void queueWindowClick(int windowId, int slotId, int button, ClickType type) { + transactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, type, ctx.player())); + } + + private int findGoodElytra() { + NonNullList invy = ctx.player().inventory.mainInventory; + for (int i = 0; i < invy.size(); i++) { + ItemStack slot = invy.get(i); + if (slot.getItem() == Items.ELYTRA && (slot.getItem().getMaxDamage() - slot.getItemDamage()) > Baritone.settings().elytraMinimumDurability.value) { + return i; + } + } + return -1; + } + + private void trySwapElytra() { + if (!Baritone.settings().elytraAutoSwap.value) return; + if (!transactionQueue.isEmpty()) return; + + ItemStack chest = ctx.player().inventory.armorInventory.get(2); + if (chest.getItem() != Items.ELYTRA) return; + if (chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) return; + + int goodElytraSlot = findGoodElytra(); + if (goodElytraSlot != -1) { + final int CHEST_SLOT = 6; + final int slotId = goodElytraSlot < 9 ? goodElytraSlot + 36 : goodElytraSlot; + queueWindowClick(ctx.player().inventoryContainer.windowId, slotId, 0, ClickType.PICKUP); + queueWindowClick(ctx.player().inventoryContainer.windowId, CHEST_SLOT, 0, ClickType.PICKUP); + queueWindowClick(ctx.player().inventoryContainer.windowId, slotId, 0, ClickType.PICKUP); + } + } + /** * Minecraft 1.12's pushOutOfBlocks logic doesn't account for players being able to fit under single block spaces, * so whenever the edge of a ceiling is encountered while elytra flying it tries to push the player out. @@ -1331,6 +1384,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } + tickInventoryTransactions(); + if (ctx.player().isElytraFlying()) { this.state = State.FLYING; this.goal = null; diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 9bbb2a24a..063082afb 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -199,12 +199,10 @@ public final class NetherPathfinderContext { } else { id = (int) ((jl | longArray[k] << (64 - l)) & maxEntryValue); } - Octree.setBlock(ptr, - ((idx & 255) & 15), - yReal + (idx >> 8), - ((idx & 255) >> 4), - id != airId - ); + int x = (idx & 15); + int y = yReal + (idx >> 8); + int z = ((idx >> 4) & 15); + Octree.setBlock(ptr, x, y, z, id != airId); } } Octree.setIsFromJava(ptr); From 0b5d5b81768217544be3240355e2d2d90228c358 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Wed, 12 Jul 2023 22:54:04 -0400 Subject: [PATCH 184/276] use ticksBetweenInventoryMoves --- src/api/java/baritone/api/Settings.java | 5 ----- src/main/java/baritone/behavior/ElytraBehavior.java | 4 ++-- 2 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 3f039fe91..eafa22b22 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1404,11 +1404,6 @@ public final class Settings { */ public final Setting elytraMinimumDurability = new Setting<>(5); - /** - * The number of ticks between doing inventory clicks - */ - public final Setting elytraInventoryTicks = new Setting<>(5); - /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index c39950f33..0c5d47023 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -119,7 +119,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // auto swap private int tickCounter; - private int tickLastTransaction = -Baritone.settings().elytraInventoryTicks.value; + private int tickLastTransaction = -Baritone.settings().ticksBetweenInventoryMoves.value; private final Queue transactionQueue = new LinkedList<>(); private ElytraBehavior(Baritone baritone) { @@ -1258,7 +1258,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void tickInventoryTransactions() { - if (tickCounter - tickLastTransaction > Baritone.settings().elytraInventoryTicks.value) { + if (tickCounter - tickLastTransaction > Baritone.settings().ticksBetweenInventoryMoves.value) { Runnable r = transactionQueue.poll(); if (r != null) { r.run(); From 461f56c4d648d62bc6d7ea1c05be6cd923143f63 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Thu, 13 Jul 2023 14:21:15 -0400 Subject: [PATCH 185/276] countdown instead of count up --- src/main/java/baritone/behavior/ElytraBehavior.java | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 0c5d47023..cbff38815 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -118,8 +118,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private boolean solveNextTick; // auto swap - private int tickCounter; - private int tickLastTransaction = -Baritone.settings().ticksBetweenInventoryMoves.value; + private int invTickCountdown = 0; private final Queue transactionQueue = new LinkedList<>(); private ElytraBehavior(Baritone baritone) { @@ -1258,14 +1257,14 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void tickInventoryTransactions() { - if (tickCounter - tickLastTransaction > Baritone.settings().ticksBetweenInventoryMoves.value) { + if (invTickCountdown <= 0) { Runnable r = transactionQueue.poll(); if (r != null) { r.run(); - tickLastTransaction = tickCounter; + invTickCountdown = Baritone.settings().ticksBetweenInventoryMoves.value; } } - tickCounter++; + if (invTickCountdown > 0) invTickCountdown--; } private void queueWindowClick(int windowId, int slotId, int button, ClickType type) { From d35571923f41ae507fb066b9322ef18ea2dfebed Mon Sep 17 00:00:00 2001 From: Babbaj Date: Thu, 13 Jul 2023 14:35:33 -0400 Subject: [PATCH 186/276] appease brady --- .../java/baritone/behavior/ElytraBehavior.java | 15 +++++++++------ 1 file changed, 9 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index cbff38815..0d61d1894 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -544,6 +544,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } + tickInventoryTransactions(); + // Certified mojang employee incident if (this.remainingFireworkTicks > 0) { this.remainingFireworkTicks--; @@ -1283,12 +1285,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void trySwapElytra() { - if (!Baritone.settings().elytraAutoSwap.value) return; - if (!transactionQueue.isEmpty()) return; + if (!Baritone.settings().elytraAutoSwap.value || !transactionQueue.isEmpty()) { + return; + } ItemStack chest = ctx.player().inventory.armorInventory.get(2); - if (chest.getItem() != Items.ELYTRA) return; - if (chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) return; + if (chest.getItem() != Items.ELYTRA + || chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) { + return; + } int goodElytraSlot = findGoodElytra(); if (goodElytraSlot != -1) { @@ -1383,8 +1388,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - tickInventoryTransactions(); - if (ctx.player().isElytraFlying()) { this.state = State.FLYING; this.goal = null; From 29bf046aa8412f80a4eceb529dca02d6dfd170f8 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 13 Jul 2023 14:28:51 -0500 Subject: [PATCH 187/276] BlockStateOctreeInterface --- .../baritone/behavior/ElytraBehavior.java | 18 ++++--- .../elytra/BlockStateOctreeInterface.java | 50 +++++++++++++++++++ .../elytra/NetherPathfinderContext.java | 3 +- 3 files changed, 63 insertions(+), 8 deletions(-) create mode 100644 src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 0d61d1894..ceab9db7c 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -110,6 +110,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private final int[] nextTickBoostCounter; private BlockStateInterface bsi; + private BlockStateOctreeInterface boi; private BlockPos destination; private final ExecutorService solverExecutor; @@ -299,7 +300,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // not loaded yet? return; } - if (!passable(ctx.world().getBlockState(path.get(rangeStartIncl)), false)) { + final BetterBlockPos rangeStart = path.get(rangeStartIncl); + if (!ElytraBehavior.this.passable(rangeStart.x, rangeStart.y, rangeStart.z, false)) { // we're in a wall return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } @@ -575,7 +577,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } + // ctx AND context???? :DDD this.bsi = new BlockStateInterface(ctx); + this.boi = new BlockStateOctreeInterface(context); this.pathManager.tick(); final int playerNear = this.pathManager.getNear(); @@ -1250,12 +1254,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private boolean passable(int x, int y, int z, boolean ignoreLava) { - return passable(this.bsi.get0(x, y, z), ignoreLava); - } - - private static boolean passable(IBlockState state, boolean ignoreLava) { - Material mat = state.getMaterial(); - return mat == Material.AIR || (ignoreLava && mat == Material.LAVA); + if (ignoreLava) { + final Material mat = this.bsi.get0(x, y, z).getMaterial(); + return mat == Material.AIR || mat == Material.LAVA; + } else { + return !this.boi.get0(x, y, z); + } } private void tickInventoryTransactions() { diff --git a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java new file mode 100644 index 000000000..261abdbf6 --- /dev/null +++ b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java @@ -0,0 +1,50 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.behavior.elytra; + +import dev.babbaj.pathfinder.NetherPathfinder; +import dev.babbaj.pathfinder.Octree; + +/** + * @author Brady + */ +public final class BlockStateOctreeInterface { + + private final long context; + private long chunkPtr; + private int prevChunkX; + private int prevChunkZ; + + public BlockStateOctreeInterface(final NetherPathfinderContext context) { + this.context = context.context; + } + + public boolean get0(final int x, final int y, final int z) { + if (y < 0 || y >= 128) { + return false; + } + final int chunkX = x >> 4; + final int chunkZ = z >> 4; + if (chunkX != this.prevChunkX || chunkZ != this.prevChunkZ || this.chunkPtr == 0) { + this.prevChunkX = chunkX; + this.prevChunkZ = chunkZ; + this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.context, chunkX, chunkZ); + } + return Octree.getBlock(this.chunkPtr, x & 0xF, y & 0x7F, z & 0xF); + } +} diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 063082afb..457b2a7a5 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -46,7 +46,8 @@ public final class NetherPathfinderContext { private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); - private final long context; + // Visible for access in BlockStateOctreeInterface + final long context; private final long seed; private final ExecutorService executor; From 1d109d4b9fb7abe9d2d1ea31def84abf6cb32aee Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 13 Jul 2023 14:47:19 -0500 Subject: [PATCH 188/276] crucial performance optimization --- .../behavior/elytra/BlockStateOctreeInterface.java | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java index 261abdbf6..8a07b96e5 100644 --- a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java @@ -27,20 +27,22 @@ public final class BlockStateOctreeInterface { private final long context; private long chunkPtr; - private int prevChunkX; - private int prevChunkZ; + + // Guarantee that the first lookup will fetch the context by setting MAX_VALUE + private int prevChunkX = Integer.MAX_VALUE; + private int prevChunkZ = Integer.MAX_VALUE; public BlockStateOctreeInterface(final NetherPathfinderContext context) { this.context = context.context; } public boolean get0(final int x, final int y, final int z) { - if (y < 0 || y >= 128) { + if ((y | (128 - y)) < 0) { return false; } final int chunkX = x >> 4; final int chunkZ = z >> 4; - if (chunkX != this.prevChunkX || chunkZ != this.prevChunkZ || this.chunkPtr == 0) { + if (((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { this.prevChunkX = chunkX; this.prevChunkZ = chunkZ; this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.context, chunkX, chunkZ); From b468b8eb95f27efa27756c244973809fec8d4dfd Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 15 Jul 2023 22:17:21 -0400 Subject: [PATCH 189/276] landing procedure --- .../baritone/behavior/ElytraBehavior.java | 22 ++++++++++++++++++- .../baritone/behavior/elytra/NetherPath.java | 4 ++++ 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index ceab9db7c..43c138846 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -1393,6 +1393,23 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } if (ctx.player().isElytraFlying()) { + if (ctx.player().getDistanceSqToCenter(ElytraBehavior.this.pathManager.path.getLast()) < (5 * 5)) { + this.state = State.LANDING; + } + } + + if (this.state == State.LANDING) { + if (ctx.player().isElytraFlying()) { + BetterBlockPos endPos = ElytraBehavior.this.pathManager.path.getLast(); + Vec3d from = ctx.player().getPositionVector(); + Vec3d to = new Vec3d(endPos.x, from.y, endPos.z); + Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); + baritone.getLookBehavior().updateTarget(rotation, false); + } else { + this.onLostControl(); + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + } else if (ctx.player().isElytraFlying()) { this.state = State.FLYING; this.goal = null; baritone.getInputOverrideHandler().clearAllKeys(); @@ -1508,6 +1525,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return "Begin flying"; case FLYING: return "Flying"; + case LANDING: + return "Landing"; default: return "Unknown"; } @@ -1550,7 +1569,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H PAUSE, GET_TO_JUMP, START_FLYING, - FLYING + FLYING, + LANDING } public static T create(final Baritone baritone) { diff --git a/src/main/java/baritone/behavior/elytra/NetherPath.java b/src/main/java/baritone/behavior/elytra/NetherPath.java index e90075b87..e8f8e2793 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPath.java +++ b/src/main/java/baritone/behavior/elytra/NetherPath.java @@ -47,6 +47,10 @@ public final class NetherPath extends AbstractList { return this.backing.size(); } + public BetterBlockPos getLast() { + return this.backing.get(this.backing.size() - 1); + } + public Vec3d getVec(int index) { final BetterBlockPos pos = this.get(index); return new Vec3d(pos.x, pos.y, pos.z); From 716b3ae0d23ae7a253f87b76b983dd94f1f5a730 Mon Sep 17 00:00:00 2001 From: Brady Hahn Date: Sat, 15 Jul 2023 22:23:35 -0500 Subject: [PATCH 190/276] Update ElytraBehavior.java i love github web editor --- src/main/java/baritone/behavior/ElytraBehavior.java | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 43c138846..197ea61b8 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -306,7 +306,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } - if (this.ticksNearUnchanged > 100) { + if (ElytraBehavior.this.process.state != State.LANDING && this.ticksNearUnchanged > 100) { this.pathRecalcSegment(rangeEndExcl - 1) .thenRun(() -> { logDirect("Recalculating segment, no progress in last 100 ticks"); @@ -1393,14 +1393,15 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } if (ctx.player().isElytraFlying()) { - if (ctx.player().getDistanceSqToCenter(ElytraBehavior.this.pathManager.path.getLast()) < (5 * 5)) { + final BetterBlockPos last = ElytraBehavior.this.pathManager.path.getLast(); + if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { this.state = State.LANDING; } } if (this.state == State.LANDING) { - if (ctx.player().isElytraFlying()) { - BetterBlockPos endPos = ElytraBehavior.this.pathManager.path.getLast(); + final BetterBlockPos endPos = ElytraBehavior.this.pathManager.path.getLast(); + if (ctx.player().isElytraFlying() && endPos != null) { Vec3d from = ctx.player().getPositionVector(); Vec3d to = new Vec3d(endPos.x, from.y, endPos.z); Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); From e579bf980d3f2021b57723f3e9d7c0c4d0a70b15 Mon Sep 17 00:00:00 2001 From: Brady Hahn Date: Sat, 15 Jul 2023 22:23:59 -0500 Subject: [PATCH 191/276] Update NetherPath.java --- src/main/java/baritone/behavior/elytra/NetherPath.java | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPath.java b/src/main/java/baritone/behavior/elytra/NetherPath.java index e8f8e2793..e746665c4 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPath.java +++ b/src/main/java/baritone/behavior/elytra/NetherPath.java @@ -47,8 +47,11 @@ public final class NetherPath extends AbstractList { return this.backing.size(); } + /** + * @return The last position in the path, or {@code null} if empty + */ public BetterBlockPos getLast() { - return this.backing.get(this.backing.size() - 1); + return this.isEmpty() ? null : this.backing.get(this.backing.size() - 1); } public Vec3d getVec(int index) { From 76d3a13f58ba5b430f6ceed8f6d53db090d39713 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 16 Jul 2023 01:19:51 -0400 Subject: [PATCH 192/276] cull far away chunks from the cache --- build.gradle | 4 ++-- src/api/java/baritone/api/Settings.java | 11 +++++++++++ .../java/baritone/behavior/ElytraBehavior.java | 15 +++++++++++---- .../behavior/elytra/NetherPathfinderContext.java | 4 ++++ 4 files changed, 28 insertions(+), 6 deletions(-) diff --git a/build.gradle b/build.gradle index da0e2232b..e44d68e04 100755 --- a/build.gradle +++ b/build.gradle @@ -175,8 +175,8 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.24') - implementation 'dev.babbaj:nether-pathfinder:0.24' + launchImplementation('dev.babbaj:nether-pathfinder:0.34') + implementation 'dev.babbaj:nether-pathfinder:0.34' testImplementation 'junit:junit:4.12' } diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index eafa22b22..e203a0ebf 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -38,6 +38,7 @@ import java.lang.reflect.ParameterizedType; import java.lang.reflect.Type; import java.util.List; import java.util.*; +import java.util.concurrent.TimeUnit; import java.util.function.BiConsumer; import java.util.function.Consumer; @@ -1404,6 +1405,16 @@ public final class Settings { */ public final Setting elytraMinimumDurability = new Setting<>(5); + /** + * Time between culling far away chunks from the nether pathfinder chunk cache + */ + public final Setting elytraTimeBetweenCacheCullSecs = new Setting<>(TimeUnit.MINUTES.toSeconds(3)); + + /** + * Maximum distance chunks can be before being culled from the nether pathfinder chunk cache + */ + public final Setting elytraCacheCullDistance = new Setting<>(5000); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 197ea61b8..42f226e79 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -118,9 +118,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private Solution pendingSolution; private boolean solveNextTick; + private long timeLastCacheCull = 0L; + // auto swap private int invTickCountdown = 0; - private final Queue transactionQueue = new LinkedList<>(); + private final Queue invTransactionQueue = new LinkedList<>(); private ElytraBehavior(Baritone baritone) { super(baritone); @@ -516,6 +518,11 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (event.getType() == TickEvent.Type.OUT) { return; } + final long now = System.currentTimeMillis(); + if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value); + this.timeLastCacheCull = now; + } // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; @@ -1264,7 +1271,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private void tickInventoryTransactions() { if (invTickCountdown <= 0) { - Runnable r = transactionQueue.poll(); + Runnable r = invTransactionQueue.poll(); if (r != null) { r.run(); invTickCountdown = Baritone.settings().ticksBetweenInventoryMoves.value; @@ -1274,7 +1281,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void queueWindowClick(int windowId, int slotId, int button, ClickType type) { - transactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, type, ctx.player())); + invTransactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, type, ctx.player())); } private int findGoodElytra() { @@ -1289,7 +1296,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } private void trySwapElytra() { - if (!Baritone.settings().elytraAutoSwap.value || !transactionQueue.isEmpty()) { + if (!Baritone.settings().elytraAutoSwap.value || !invTransactionQueue.isEmpty()) { return; } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index 457b2a7a5..e0eb7de0b 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -57,6 +57,10 @@ public final class NetherPathfinderContext { this.executor = Executors.newSingleThreadExecutor(); } + public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks) { + this.executor.execute(() -> NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks)); + } + public void queueForPacking(final Chunk chunkIn) { final SoftReference ref = new SoftReference<>(chunkIn); this.executor.execute(() -> { From f3bb5a0cb2b490ce7ce1cf98120f27567a9ea4a6 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 16 Jul 2023 13:53:02 -0400 Subject: [PATCH 193/276] make sure BlockStateOctreeInterface doesn't use freed chunk pointers --- .../java/baritone/behavior/ElytraBehavior.java | 2 +- .../elytra/BlockStateOctreeInterface.java | 17 +++++++++++------ .../elytra/NetherPathfinderContext.java | 10 ++++++++-- 3 files changed, 20 insertions(+), 9 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index 42f226e79..b9bbd65e7 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -520,7 +520,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } final long now = System.currentTimeMillis(); if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { - this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value); + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); this.timeLastCacheCull = now; } diff --git a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java index 8a07b96e5..b81a6aed5 100644 --- a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java @@ -25,15 +25,17 @@ import dev.babbaj.pathfinder.Octree; */ public final class BlockStateOctreeInterface { - private final long context; - private long chunkPtr; + private final NetherPathfinderContext context; + private final long contextPtr; + volatile long chunkPtr; // Guarantee that the first lookup will fetch the context by setting MAX_VALUE private int prevChunkX = Integer.MAX_VALUE; private int prevChunkZ = Integer.MAX_VALUE; public BlockStateOctreeInterface(final NetherPathfinderContext context) { - this.context = context.context; + this.context = context; + this.contextPtr = context.context; } public boolean get0(final int x, final int y, final int z) { @@ -42,11 +44,14 @@ public final class BlockStateOctreeInterface { } final int chunkX = x >> 4; final int chunkZ = z >> 4; - if (((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { + long pointer = this.chunkPtr; + if (pointer == 0 | ((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { this.prevChunkX = chunkX; this.prevChunkZ = chunkZ; - this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.context, chunkX, chunkZ); + synchronized (this.context.cacheLock) { + this.chunkPtr = pointer = NetherPathfinder.getOrCreateChunk(this.contextPtr, chunkX, chunkZ); + } } - return Octree.getBlock(this.chunkPtr, x & 0xF, y & 0x7F, z & 0xF); + return Octree.getBlock(pointer, x & 0xF, y & 0x7F, z & 0xF); } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index e0eb7de0b..ebe563374 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -45,6 +45,7 @@ import java.util.concurrent.TimeUnit; public final class NetherPathfinderContext { private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); + public final Object cacheLock = new Object(); // Visible for access in BlockStateOctreeInterface final long context; @@ -57,8 +58,13 @@ public final class NetherPathfinderContext { this.executor = Executors.newSingleThreadExecutor(); } - public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks) { - this.executor.execute(() -> NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks)); + public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { + this.executor.execute(() -> { + synchronized (this.cacheLock) { + boi.chunkPtr = 0L; + NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks); + } + }); } public void queueForPacking(final Chunk chunkIn) { From 41e8c69db9718a2032fb109ce1f4d34de3b5a41a Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 16 Jul 2023 18:58:42 -0400 Subject: [PATCH 194/276] consistent elytra setting naming --- src/api/java/baritone/api/Settings.java | 10 +++++----- src/main/java/baritone/behavior/ElytraBehavior.java | 12 ++++++------ 2 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index e203a0ebf..2ec56b1a4 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1366,23 +1366,23 @@ public final class Settings { /** * If enabled, avoids using fireworks when descending along the flight path. */ - public final Setting conserveFireworks = new Setting<>(true); + public final Setting elytraConserveFireworks = new Setting<>(true); /** * Renders the raytraces that are performed by the elytra fly calculation. */ - public final Setting renderRaytraces = new Setting<>(false); + public final Setting elytraRenderRaytraces = new Setting<>(false); /** * Renders the raytraces that are used in the hitbox part of the elytra fly calculation. - * Requires {@link #renderRaytraces}. + * Requires {@link #elytraRenderRaytraces}. */ - public final Setting renderHitboxRaytraces = new Setting<>(false); + public final Setting elytraRenderHitboxRaytraces = new Setting<>(false); /** * Renders the best elytra flight path that was simulated each tick. */ - public final Setting renderElytraSimulation = new Setting<>(false); + public final Setting elytraRenderSimulation = new Setting<>(false); /** * Automatically path to and jump off of ledges to initiate elytra flight when grounded. diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b9bbd65e7..1f969dc23 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -391,21 +391,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (this.aimPos != null) { PathRenderer.drawGoal(ctx.player(), new GoalBlock(this.aimPos), event.getPartialTicks(), Color.GREEN); } - if (!this.clearLines.isEmpty() && settings.renderRaytraces.value) { + if (!this.clearLines.isEmpty() && settings.elytraRenderRaytraces.value) { IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); for (Pair line : this.clearLines) { IRenderer.emitLine(line.first(), line.second()); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } - if (!this.blockedLines.isEmpty() && Baritone.settings().renderRaytraces.value) { + if (!this.blockedLines.isEmpty() && Baritone.settings().elytraRenderRaytraces.value) { IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); for (Pair line : this.blockedLines) { IRenderer.emitLine(line.first(), line.second()); } IRenderer.endLines(settings.renderPathIgnoreDepth.value); } - if (this.simulationLine != null && Baritone.settings().renderElytraSimulation.value) { + if (this.simulationLine != null && Baritone.settings().elytraRenderSimulation.value) { IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value); final Vec3d offset = new Vec3d( ctx.player().prevPosX + (ctx.player().posX - ctx.player().prevPosX) * event.getPartialTicks(), @@ -753,7 +753,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; } - final boolean useOnDescend = !Baritone.settings().conserveFireworks.value || ctx.player().posY < goingTo.y + 5; + final boolean useOnDescend = !Baritone.settings().elytraConserveFireworks.value || ctx.player().posY < goingTo.y + 5; final double currentSpeed = new Vec3d( ctx.player().motionX, // ignore y component if we are BOTH below where we want to be AND descending @@ -984,7 +984,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H }; // Use non-batching method without early failure - if (Baritone.settings().renderHitboxRaytraces.value) { + if (Baritone.settings().elytraRenderHitboxRaytraces.value) { boolean clear = true; for (int i = 0; i < 8; i++) { final Vec3d s = new Vec3d(src[i * 3], src[i * 3 + 1], src[i * 3 + 2]); @@ -1009,7 +1009,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H clear = ctx.world().rayTraceBlocks(start, dest, false, false, false) == null; } - if (Baritone.settings().renderRaytraces.value) { + if (Baritone.settings().elytraRenderRaytraces.value) { (clear ? this.clearLines : this.blockedLines).add(new Pair<>(start, dest)); } return clear; From 0e567f2f90b32a3b669c45ec9f58c36f4432a1dc Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 16 Jul 2023 18:17:15 -0700 Subject: [PATCH 195/276] shrimple --- .../elytra/NetherPathfinderContext.java | 76 +++++++++++-------- 1 file changed, 44 insertions(+), 32 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index ebe563374..defc3fa19 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -34,10 +34,7 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.lang.ref.SoftReference; -import java.util.concurrent.CompletableFuture; -import java.util.concurrent.ExecutorService; -import java.util.concurrent.Executors; -import java.util.concurrent.TimeUnit; +import java.util.concurrent.*; /** * @author Brady @@ -50,12 +47,15 @@ public final class NetherPathfinderContext { // Visible for access in BlockStateOctreeInterface final long context; private final long seed; - private final ExecutorService executor; + private final ThreadPoolExecutor executor; + private final ExecutorService executorHighPriority; public NetherPathfinderContext(long seed) { this.context = NetherPathfinder.newContext(seed); this.seed = seed; - this.executor = Executors.newSingleThreadExecutor(); + + this.executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); + this.executorHighPriority = Executors.newSingleThreadExecutor(); } public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { @@ -68,46 +68,58 @@ public final class NetherPathfinderContext { } public void queueForPacking(final Chunk chunkIn) { + if (this.executor.getQueue().size() > 50000) { + return; + } final SoftReference ref = new SoftReference<>(chunkIn); this.executor.execute(() -> { - // TODO: Prioritize packing recent chunks and/or ones that the path goes through, - // and prune the oldest chunks per chunkPackerQueueMaxSize - final Chunk chunk = ref.get(); - if (chunk != null) { - long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); - writeChunkData(chunk, ptr); + synchronized (this.cacheLock) { + // TODO: Prioritize packing recent chunks and/or ones that the path goes through, + // and prune the oldest chunks per chunkPackerQueueMaxSize + final Chunk chunk = ref.get(); + if (chunk != null) { + long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); + writeChunkData(chunk, ptr); + } } }); } public void queueBlockUpdate(BlockChangeEvent event) { + if (this.executor.getQueue().size() > 50000) { + return; + } this.executor.execute(() -> { - ChunkPos chunkPos = event.getChunkPos(); - long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); - if (ptr == 0) return; // this shouldn't ever happen - event.getBlocks().forEach(pair -> { - BlockPos pos = pair.first(); - if (pos.getY() >= 128) return; - boolean isSolid = pair.second() != AIR_BLOCK_STATE; - Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); - }); + synchronized (this.cacheLock) { + ChunkPos chunkPos = event.getChunkPos(); + long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); + if (ptr == 0) return; // this shouldn't ever happen + event.getBlocks().forEach(pair -> { + BlockPos pos = pair.first(); + if (pos.getY() >= 128) return; + boolean isSolid = pair.second() != AIR_BLOCK_STATE; + Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); + }); + } }); } public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { return CompletableFuture.supplyAsync(() -> { - final PathSegment segment = NetherPathfinder.pathFind( - this.context, - src.getX(), src.getY(), src.getZ(), - dst.getX(), dst.getY(), dst.getZ(), - true, - 10000 - ); - if (segment == null) { - throw new PathCalculationException("Path calculation failed"); + synchronized (this.cacheLock) { + final PathSegment segment = NetherPathfinder.pathFind( + this.context, + src.getX(), src.getY(), src.getZ(), + dst.getX(), dst.getY(), dst.getZ(), + true, + 10000 + ); + if (segment == null) { + throw new PathCalculationException("Path calculation failed"); + } + return segment; } - return segment; - }, this.executor); + }, this.executorHighPriority); } /** From edc92753cfa98a11d30c855d661ad8f3d1f1be9c Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 16 Jul 2023 18:17:53 -0700 Subject: [PATCH 196/276] Revert "shrimple" This reverts commit 0e567f2f90b32a3b669c45ec9f58c36f4432a1dc. --- .../elytra/NetherPathfinderContext.java | 76 ++++++++----------- 1 file changed, 32 insertions(+), 44 deletions(-) diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java index defc3fa19..ebe563374 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java @@ -34,7 +34,10 @@ import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.lang.ref.SoftReference; -import java.util.concurrent.*; +import java.util.concurrent.CompletableFuture; +import java.util.concurrent.ExecutorService; +import java.util.concurrent.Executors; +import java.util.concurrent.TimeUnit; /** * @author Brady @@ -47,15 +50,12 @@ public final class NetherPathfinderContext { // Visible for access in BlockStateOctreeInterface final long context; private final long seed; - private final ThreadPoolExecutor executor; - private final ExecutorService executorHighPriority; + private final ExecutorService executor; public NetherPathfinderContext(long seed) { this.context = NetherPathfinder.newContext(seed); this.seed = seed; - - this.executor = new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<>()); - this.executorHighPriority = Executors.newSingleThreadExecutor(); + this.executor = Executors.newSingleThreadExecutor(); } public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { @@ -68,58 +68,46 @@ public final class NetherPathfinderContext { } public void queueForPacking(final Chunk chunkIn) { - if (this.executor.getQueue().size() > 50000) { - return; - } final SoftReference ref = new SoftReference<>(chunkIn); this.executor.execute(() -> { - synchronized (this.cacheLock) { - // TODO: Prioritize packing recent chunks and/or ones that the path goes through, - // and prune the oldest chunks per chunkPackerQueueMaxSize - final Chunk chunk = ref.get(); - if (chunk != null) { - long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); - writeChunkData(chunk, ptr); - } + // TODO: Prioritize packing recent chunks and/or ones that the path goes through, + // and prune the oldest chunks per chunkPackerQueueMaxSize + final Chunk chunk = ref.get(); + if (chunk != null) { + long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.x, chunk.z); + writeChunkData(chunk, ptr); } }); } public void queueBlockUpdate(BlockChangeEvent event) { - if (this.executor.getQueue().size() > 50000) { - return; - } this.executor.execute(() -> { - synchronized (this.cacheLock) { - ChunkPos chunkPos = event.getChunkPos(); - long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); - if (ptr == 0) return; // this shouldn't ever happen - event.getBlocks().forEach(pair -> { - BlockPos pos = pair.first(); - if (pos.getY() >= 128) return; - boolean isSolid = pair.second() != AIR_BLOCK_STATE; - Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); - }); - } + ChunkPos chunkPos = event.getChunkPos(); + long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x, chunkPos.z); + if (ptr == 0) return; // this shouldn't ever happen + event.getBlocks().forEach(pair -> { + BlockPos pos = pair.first(); + if (pos.getY() >= 128) return; + boolean isSolid = pair.second() != AIR_BLOCK_STATE; + Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid); + }); }); } public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) { return CompletableFuture.supplyAsync(() -> { - synchronized (this.cacheLock) { - final PathSegment segment = NetherPathfinder.pathFind( - this.context, - src.getX(), src.getY(), src.getZ(), - dst.getX(), dst.getY(), dst.getZ(), - true, - 10000 - ); - if (segment == null) { - throw new PathCalculationException("Path calculation failed"); - } - return segment; + final PathSegment segment = NetherPathfinder.pathFind( + this.context, + src.getX(), src.getY(), src.getZ(), + dst.getX(), dst.getY(), dst.getZ(), + true, + 10000 + ); + if (segment == null) { + throw new PathCalculationException("Path calculation failed"); } - }, this.executorHighPriority); + return segment; + }, this.executor); } /** From 32a4c4644eccaaf0b50a0daf3ae1b144a57b85a0 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 20:21:40 -0500 Subject: [PATCH 197/276] Move cull code --- src/main/java/baritone/behavior/ElytraBehavior.java | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/behavior/ElytraBehavior.java index b9bbd65e7..0ad6ad62d 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/behavior/ElytraBehavior.java @@ -518,11 +518,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H if (event.getType() == TickEvent.Type.OUT) { return; } - final long now = System.currentTimeMillis(); - if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { - this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); - this.timeLastCacheCull = now; - } // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; @@ -594,6 +589,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Math.max(playerNear - 30, 0), Math.min(playerNear + 100, path.size()) ); + + final long now = System.currentTimeMillis(); + if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); + this.timeLastCacheCull = now; + } } /** From 108dbdae5d8ba87eac0dcb1dd7a7ce625f23d874 Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 16 Jul 2023 20:29:30 -0500 Subject: [PATCH 198/276] partially appease codacy --- src/api/java/baritone/api/event/events/BlockChangeEvent.java | 2 -- src/main/java/baritone/command/defaults/ElytraCommand.java | 4 +++- src/main/java/baritone/utils/PathRenderer.java | 1 - 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/api/java/baritone/api/event/events/BlockChangeEvent.java b/src/api/java/baritone/api/event/events/BlockChangeEvent.java index a65a51f35..00743f025 100644 --- a/src/api/java/baritone/api/event/events/BlockChangeEvent.java +++ b/src/api/java/baritone/api/event/events/BlockChangeEvent.java @@ -22,9 +22,7 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; -import java.util.Collections; import java.util.List; -import java.util.Set; /** * @author Brady diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 298a23cd7..5288ade47 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -59,7 +59,9 @@ public class ElytraCommand extends Command { if (iGoal == null) { throw new CommandInvalidStateException("No goal has been set"); } - final int x, y, z; + final int x; + final int y; + final int z; if (iGoal instanceof GoalXZ) { GoalXZ goal = (GoalXZ) iGoal; x = goal.getX(); diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index 0fcad054a..a30ec45b7 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -33,7 +33,6 @@ import net.minecraft.init.Blocks; import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; -import net.minecraft.util.math.Vec3d; import java.awt.*; import java.util.Arrays; From 1b82bd1f33b7bc76537f7a299917d78862dbd217 Mon Sep 17 00:00:00 2001 From: Brady Date: Mon, 17 Jul 2023 17:58:08 -0500 Subject: [PATCH 199/276] pitch smooth look and setting for ticks --- src/api/java/baritone/api/Settings.java | 15 +++++++-- .../java/baritone/behavior/LookBehavior.java | 32 ++++++++++++------- 2 files changed, 34 insertions(+), 13 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 2ec56b1a4..3ab2a068b 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -742,10 +742,21 @@ public final class Settings { public final Setting elytraFreeLook = new Setting<>(false); /** - * Forces the client-sided rotations to an average of the last 10 ticks of server-sided rotations. + * Forces the client-sided yaw rotation to an average of the last {@link #smoothLookTicks} of server-sided rotations. * Requires {@link #freeLook}. */ - public final Setting smoothLook = new Setting<>(false); + public final Setting smoothLookYaw = new Setting<>(false); + + /** + * Forces the client-sided pitch rotation to an average of the last {@link #smoothLookTicks} of server-sided rotations. + * Requires {@link #freeLook}. + */ + public final Setting smoothLookPitch = new Setting<>(false); + + /** + * The number of ticks to average across for {@link #smoothLookYaw} and {@link #smoothLookPitch}; + */ + public final Setting smoothLookTicks = new Setting<>(10); /** * When true, the player will remain with its existing look direction as often as possible. diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index d93607644..5f6421d08 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -26,9 +26,10 @@ import baritone.api.event.events.*; import baritone.api.utils.IPlayerContext; import baritone.api.utils.Rotation; import baritone.behavior.look.ForkableRandom; -import com.google.common.collect.EvictingQueue; import net.minecraft.network.play.client.CPacketPlayer; +import java.util.ArrayDeque; +import java.util.Deque; import java.util.Optional; public final class LookBehavior extends Behavior implements ILookBehavior { @@ -52,12 +53,14 @@ public final class LookBehavior extends Behavior implements ILookBehavior { private final AimProcessor processor; - private final EvictingQueue smoothYawBuffer; + private final Deque smoothYawBuffer; + private final Deque smoothPitchBuffer; public LookBehavior(Baritone baritone) { super(baritone); this.processor = new AimProcessor(baritone.getPlayerContext()); - this.smoothYawBuffer = EvictingQueue.create(10); + this.smoothYawBuffer = new ArrayDeque<>(); + this.smoothPitchBuffer = new ArrayDeque<>(); } @Override @@ -100,15 +103,22 @@ public final class LookBehavior extends Behavior implements ILookBehavior { case POST: { // Reset the player's rotations back to their original values if (this.prevRotation != null) { - if (Baritone.settings().smoothLook.value) { - this.smoothYawBuffer.add(this.target.rotation.getYaw()); - ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream() - .mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); - ctx.player().rotationPitch = this.prevRotation.getPitch(); - } else { - ctx.player().rotationYaw = this.prevRotation.getYaw(); - ctx.player().rotationPitch = this.prevRotation.getPitch(); + this.smoothYawBuffer.add(this.target.rotation.getYaw()); + while (this.smoothYawBuffer.size() > Baritone.settings().smoothLookTicks.value) { + this.smoothYawBuffer.pop(); } + this.smoothPitchBuffer.add(this.target.rotation.getPitch()); + while (this.smoothPitchBuffer.size() > Baritone.settings().smoothLookTicks.value) { + this.smoothPitchBuffer.pop(); + } + + ctx.player().rotationYaw = Baritone.settings().smoothLookYaw.value + ? (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw) + : this.prevRotation.getYaw(); + ctx.player().rotationPitch = Baritone.settings().smoothLookPitch.value + ? (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch) + : this.prevRotation.getPitch(); + this.prevRotation = null; } // The target is done being used for this game tick, so it can be invalidated From 9a6241af8a5cf4d8bd686ccefc3a3dab11dbfeff Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 16 Jul 2023 22:56:17 -0400 Subject: [PATCH 200/276] refactor elytra into being just a process --- src/api/java/baritone/api/IBaritone.java | 13 +- .../IElytraProcess.java} | 9 +- src/main/java/baritone/Baritone.java | 11 +- .../baritone/behavior/PathingBehavior.java | 2 +- .../command/defaults/ElytraCommand.java | 4 +- .../defaults/ExecutionControlCommands.java | 2 +- .../command/defaults/ForceCancelCommand.java | 2 +- .../java/baritone/process/ElytraProcess.java | 255 ++++++++++++++++ .../elytra/BlockStateOctreeInterface.java | 2 +- .../elytra/LegacyElytraBehavior.java} | 275 +++--------------- .../elytra/NetherPath.java | 2 +- .../elytra/NetherPathfinderContext.java | 4 +- .../elytra/NullElytraProcess.java} | 26 +- .../elytra/PathCalculationException.java | 2 +- .../elytra/UnpackedSegment.java | 2 +- 15 files changed, 340 insertions(+), 271 deletions(-) rename src/api/java/baritone/api/{behavior/IElytraBehavior.java => process/IElytraProcess.java} (87%) create mode 100644 src/main/java/baritone/process/ElytraProcess.java rename src/main/java/baritone/{behavior => process}/elytra/BlockStateOctreeInterface.java (98%) rename src/main/java/baritone/{behavior/ElytraBehavior.java => process/elytra/LegacyElytraBehavior.java} (84%) rename src/main/java/baritone/{behavior => process}/elytra/NetherPath.java (98%) rename src/main/java/baritone/{behavior => process}/elytra/NetherPathfinderContext.java (98%) rename src/main/java/baritone/{behavior/elytra/NullElytraBehavior.java => process/elytra/NullElytraProcess.java} (72%) rename src/main/java/baritone/{behavior => process}/elytra/PathCalculationException.java (96%) rename src/main/java/baritone/{behavior => process}/elytra/UnpackedSegment.java (98%) diff --git a/src/api/java/baritone/api/IBaritone.java b/src/api/java/baritone/api/IBaritone.java index 0913a8c43..3c9681532 100644 --- a/src/api/java/baritone/api/IBaritone.java +++ b/src/api/java/baritone/api/IBaritone.java @@ -17,7 +17,6 @@ package baritone.api; -import baritone.api.behavior.IElytraBehavior; import baritone.api.behavior.ILookBehavior; import baritone.api.behavior.IPathingBehavior; import baritone.api.cache.IWorldProvider; @@ -41,12 +40,6 @@ public interface IBaritone { */ IPathingBehavior getPathingBehavior(); - /** - * @return The {@link IElytraBehavior} instance - * @see IElytraBehavior - */ - IElytraBehavior getElytraBehavior(); - /** * @return The {@link ILookBehavior} instance * @see ILookBehavior @@ -95,6 +88,12 @@ public interface IBaritone { */ IGetToBlockProcess getGetToBlockProcess(); + /** + * @return The {@link IElytraProcess} instance + * @see IElytraProcess + */ + IElytraProcess getElytraProcess(); + /** * @return The {@link IWorldProvider} instance * @see IWorldProvider diff --git a/src/api/java/baritone/api/behavior/IElytraBehavior.java b/src/api/java/baritone/api/process/IElytraProcess.java similarity index 87% rename from src/api/java/baritone/api/behavior/IElytraBehavior.java rename to src/api/java/baritone/api/process/IElytraProcess.java index 95ae62926..06c658f42 100644 --- a/src/api/java/baritone/api/behavior/IElytraBehavior.java +++ b/src/api/java/baritone/api/process/IElytraProcess.java @@ -15,13 +15,13 @@ * along with Baritone. If not, see . */ -package baritone.api.behavior; +package baritone.api.process; import net.minecraft.util.math.BlockPos; import java.util.concurrent.CompletableFuture; -public interface IElytraBehavior extends IBehavior { +public interface IElytraProcess extends IBaritoneProcess { /** * Marks the nether pathfinder context to be reset when it is safe to do so. Because this operation is not @@ -37,11 +37,6 @@ public interface IElytraBehavior extends IBehavior { void cancel(); - /** - * Returns {@code true} if the current {@link IElytraBehavior} is actively pathing. - */ - boolean isActive(); - /** * @return {@code true} if the native library loaded and elytra is actually usable */ diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 61866e927..c6d31a3dd 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -21,9 +21,9 @@ import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.Settings; import baritone.api.behavior.IBehavior; -import baritone.api.behavior.IElytraBehavior; import baritone.api.event.listener.IEventBus; import baritone.api.process.IBaritoneProcess; +import baritone.api.process.IElytraProcess; import baritone.api.utils.IPlayerContext; import baritone.behavior.*; import baritone.cache.WorldProvider; @@ -68,7 +68,6 @@ public class Baritone implements IBaritone { private final List behaviors; private final PathingBehavior pathingBehavior; - private final IElytraBehavior elytraBehavior; private final LookBehavior lookBehavior; private final InventoryBehavior inventoryBehavior; private final InputOverrideHandler inputOverrideHandler; @@ -81,6 +80,7 @@ public class Baritone implements IBaritone { private final ExploreProcess exploreProcess; private final FarmProcess farmProcess; private final InventoryPauserProcess inventoryPauserProcess; + private final ElytraProcess elytraProcess; private final PathingControlManager pathingControlManager; private final SelectionManager selectionManager; @@ -108,7 +108,6 @@ public class Baritone implements IBaritone { { this.lookBehavior = this.registerBehavior(LookBehavior::new); - this.elytraBehavior = this.registerBehavior(ElytraBehavior::create); this.pathingBehavior = this.registerBehavior(PathingBehavior::new); this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new); this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new); @@ -125,6 +124,8 @@ public class Baritone implements IBaritone { this.exploreProcess = this.registerProcess(ExploreProcess::new); this.farmProcess = this.registerProcess(FarmProcess::new); this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new); + this.elytraProcess = this.registerProcess(ElytraProcess::create); + this.registerProcess(BackfillProcess::new); } @@ -241,8 +242,8 @@ public class Baritone implements IBaritone { } @Override - public IElytraBehavior getElytraBehavior() { - return this.elytraBehavior; + public IElytraProcess getElytraProcess() { + return this.elytraProcess; } @Override diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 670dd827c..0404921ae 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -310,7 +310,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, public boolean isSafeToCancel() { if (current == null) { - return !baritone.getElytraBehavior().isActive() || baritone.getElytraBehavior().isSafeToCancel(); + return !baritone.getElytraProcess().isActive() || baritone.getElytraProcess().isSafeToCancel(); } return safeToCancel; } diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 5288ade47..05695d82b 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -18,7 +18,6 @@ package baritone.command.defaults; import baritone.api.IBaritone; -import baritone.api.behavior.IElytraBehavior; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; @@ -27,6 +26,7 @@ import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalXZ; import baritone.api.process.ICustomGoalProcess; +import baritone.api.process.IElytraProcess; import net.minecraft.util.math.BlockPos; import java.util.Arrays; @@ -42,7 +42,7 @@ public class ElytraCommand extends Command { @Override public void execute(String label, IArgConsumer args) throws CommandException { final ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); - final IElytraBehavior elytra = baritone.getElytraBehavior(); + final IElytraProcess elytra = baritone.getElytraProcess(); if (!elytra.isLoaded()) { final String osArch = System.getProperty("os.arch"); final String osName = System.getProperty("os.name"); diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index 43adca19f..b91014a67 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -180,7 +180,7 @@ public class ExecutionControlCommands { paused[0] = false; } baritone.getPathingBehavior().cancelEverything(); - baritone.getElytraBehavior().cancel(); + baritone.getElytraProcess().cancel(); // TODO: this shouldnt be necessary logDirect("ok canceled"); } diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index ad19f168c..d86cddd5e 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -39,7 +39,7 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); - baritone.getElytraBehavior().cancel(); + baritone.getElytraProcess().cancel(); logDirect("ok force canceled"); } diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java new file mode 100644 index 000000000..121b37b8a --- /dev/null +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -0,0 +1,255 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.process; + +import baritone.Baritone; +import baritone.api.pathing.goals.Goal; +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.IElytraProcess; +import baritone.api.process.PathingCommand; +import baritone.api.process.PathingCommandType; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.Rotation; +import baritone.api.utils.RotationUtils; +import baritone.api.utils.input.Input; +import baritone.pathing.movement.movements.MovementFall; +import baritone.process.elytra.LegacyElytraBehavior; +import baritone.process.elytra.NetherPathfinderContext; +import baritone.process.elytra.NullElytraProcess; +import baritone.utils.BaritoneProcessHelper; +import baritone.utils.PathingCommandContext; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.Vec3d; + + +import java.util.concurrent.*; +import java.util.function.Supplier; + +public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess { + public State state; + private Goal goal; + private LegacyElytraBehavior behavior; + + private ElytraProcess(Baritone baritone) { + super(baritone); + this.behavior = new LegacyElytraBehavior(baritone, this); + baritone.getGameEventHandler().registerEventListener(this.behavior); + } + + public static T create(final Baritone baritone) { + return (T) (NetherPathfinderContext.isSupported() + ? new ElytraProcess(baritone) + : new NullElytraProcess(baritone)); + } + + @Override + public boolean isActive() { + return behavior.destination != null; + } + + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + if (calcFailed) { + onLostControl(); + logDirect("Failed to get to jump off spot, canceling"); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + if (ctx.player().isElytraFlying()) { + final BetterBlockPos last = behavior.pathManager.path.getLast(); + if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { + this.state = State.LANDING; + } + } + + if (this.state == State.LANDING) { + final BetterBlockPos endPos = behavior.pathManager.path.getLast(); + if (ctx.player().isElytraFlying() && endPos != null) { + Vec3d from = ctx.player().getPositionVector(); + Vec3d to = new Vec3d(endPos.x, from.y, endPos.z); + Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); + baritone.getLookBehavior().updateTarget(rotation, false); + } else { + this.onLostControl(); + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + } else if (ctx.player().isElytraFlying()) { + this.state = State.FLYING; + this.goal = null; + baritone.getInputOverrideHandler().clearAllKeys(); + behavior.tick(); + 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; + } + + if (this.state == State.LOCATE_JUMP) { + if (this.goal == null) { + this.goal = new GoalYLevel(31); + } + 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) { + final BetterBlockPos from = new BetterBlockPos( + (fall.getSrc().x + fall.getDest().x) / 2, + (fall.getSrc().y + fall.getDest().y) / 2, + (fall.getSrc().z + fall.getDest().z) / 2 + ); + behavior.pathManager.pathToDestination(from).whenComplete((result, ex) -> { + if (!behavior.clearView(new Vec3d(from), behavior.pathManager.getPath().getVec(0), false)) { + onLostControl(); + // TODO: Get to higher ground and then look again + logDirect("Can't see start of path from jump spot, canceling"); + return; + } + if (ex == null) { + this.state = State.GET_TO_JUMP; + return; + } + onLostControl(); + }); + this.state = State.PAUSE; + } else { + onLostControl(); + logDirect("Jump off path didn't include a fall movement, canceling"); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + } + return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new LegacyElytraBehavior.WalkOffCalculationContext(baritone)); + } + + // yucky + if (this.state == State.PAUSE) { + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + + if (this.state == State.GET_TO_JUMP) { + 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(null, PathingCommandType.SET_GOAL_AND_PATH); + } + } + + if (this.state == State.START_FLYING) { + if (!isSafeToCancel) { + // owned + baritone.getPathingBehavior().secretInternalSegmentCancel(); + } + baritone.getInputOverrideHandler().clearAllKeys(); + if (ctx.player().fallDistance > 1.0f) { + baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); + } + } + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } + + @Override + public boolean isTemporary() { + return false; + } + + @Override + public void onLostControl() { + this.goal = null; + this.state = State.START_FLYING; + behavior.cancel(); + } + + + + @Override + public String displayName0() { + final Supplier status = () -> { + switch (this.state) { + case LOCATE_JUMP: + return "Finding spot to jump off"; + case PAUSE: + return "Waiting for elytra path"; + case GET_TO_JUMP: + return "Walking to takeoff"; + case START_FLYING: + return "Begin flying"; + case FLYING: + return "Flying"; + case LANDING: + return "Landing"; + default: + return "Unknown"; + } + }; + return "Elytra - " + status.get(); + } + + @Override + public CompletableFuture resetContext() { + return behavior.resetContext(); + } + + @Override + public void repackChunks() { + behavior.repackChunks(); + } + + @Override + public void pathTo(BlockPos destination) { + behavior.pathTo(destination); + } + + @Override + public void cancel() { + behavior.cancel(); + } + + @Override + public boolean isLoaded() { + return true; + } + + @Override + public boolean isSafeToCancel() { + return behavior.isSafeToCancel(); + } + + public enum State { + LOCATE_JUMP, + VALIDATE_PATH, + PAUSE, + GET_TO_JUMP, + START_FLYING, + FLYING, + LANDING + } +} diff --git a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java similarity index 98% rename from src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java rename to src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java index b81a6aed5..f9e700085 100644 --- a/src/main/java/baritone/behavior/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; import dev.babbaj.pathfinder.NetherPathfinder; import dev.babbaj.pathfinder.Octree; diff --git a/src/main/java/baritone/behavior/ElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java similarity index 84% rename from src/main/java/baritone/behavior/ElytraBehavior.java rename to src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 6e1765180..48066f3ea 100644 --- a/src/main/java/baritone/behavior/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -15,33 +15,23 @@ * along with Baritone. If not, see . */ -package baritone.behavior; +package baritone.process.elytra; import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.Settings; -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.event.events.type.EventState; -import baritone.api.pathing.goals.Goal; +import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.pathing.goals.GoalBlock; -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.behavior.elytra.*; import baritone.pathing.movement.CalculationContext; -import baritone.pathing.movement.movements.MovementFall; +import baritone.process.ElytraProcess; import baritone.utils.BlockStateInterface; import baritone.utils.IRenderer; import baritone.utils.PathRenderer; -import baritone.utils.PathingCommandContext; import baritone.utils.accessor.IChunkProviderClient; import baritone.utils.accessor.IEntityFireworkRocket; import it.unimi.dsi.fastutil.floats.FloatArrayList; @@ -67,14 +57,16 @@ import java.awt.*; import java.util.*; import java.util.List; import java.util.concurrent.*; -import java.util.function.Supplier; import java.util.function.UnaryOperator; import static baritone.api.pathing.movement.ActionCosts.COST_INF; import static baritone.utils.BaritoneMath.fastCeil; import static baritone.utils.BaritoneMath.fastFloor; -public final class ElytraBehavior extends Behavior implements IElytraBehavior, Helper { +public final class LegacyElytraBehavior implements AbstractGameEventListener, Helper { + private final Baritone baritone; + private final IPlayerContext ctx; + // Used exclusively for PathRenderer public List> clearLines; @@ -86,7 +78,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // :sunglasses: private NetherPathfinderContext context; private CompletableFuture forceResetContext; - private final PathManager pathManager; + public final PathManager pathManager; private final ElytraProcess process; /** @@ -111,7 +103,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private BlockStateInterface bsi; private BlockStateOctreeInterface boi; - private BlockPos destination; + public BlockPos destination; private final ExecutorService solverExecutor; private Future solver; @@ -124,24 +116,20 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H private int invTickCountdown = 0; private final Queue invTransactionQueue = new LinkedList<>(); - private ElytraBehavior(Baritone baritone) { - super(baritone); + public LegacyElytraBehavior(Baritone baritone, ElytraProcess process) { + this.baritone = baritone; + this.ctx = baritone.getPlayerContext(); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); this.pathManager = this.new PathManager(); - this.process = new ElytraProcess(); + this.process = process; this.solverExecutor = Executors.newSingleThreadExecutor(); this.nextTickBoostCounter = new int[2]; } - @Override - public void onLoad() { - baritone.getPathingControlManager().registerProcess(this.process); - } + public final class PathManager { - private final class PathManager { - - private NetherPath path; + public NetherPath path; private boolean completePath; private boolean recalculating; @@ -177,7 +165,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public CompletableFuture pathToDestination(final BlockPos from) { final long start = System.nanoTime(); - return this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity()) + return this.path0(from, LegacyElytraBehavior.this.destination, UnaryOperator.identity()) .thenRun(() -> { final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1)); if (this.completePath) { @@ -231,7 +219,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H final List before = this.path.subList(0, afterIncl + 1); final long start = System.nanoTime(); - this.path0(this.path.get(afterIncl), ElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) + this.path0(this.path.get(afterIncl), LegacyElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; final double distance = this.path.get(0).distanceTo(this.path.get(recompute)); @@ -282,7 +270,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H // mickey resigned private CompletableFuture path0(BlockPos src, BlockPos dst, UnaryOperator operator) { - return ElytraBehavior.this.context.pathFindAsync(src, dst) + return LegacyElytraBehavior.this.context.pathFindAsync(src, dst) .thenApply(UnpackedSegment::from) .thenApply(operator) .thenAcceptAsync(this::setPath, ctx.minecraft()::addScheduledTask); @@ -303,12 +291,12 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return; } final BetterBlockPos rangeStart = path.get(rangeStartIncl); - if (!ElytraBehavior.this.passable(rangeStart.x, rangeStart.y, rangeStart.z, false)) { + if (!LegacyElytraBehavior.this.passable(rangeStart.x, rangeStart.y, rangeStart.z, false)) { // we're in a wall return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } - if (ElytraBehavior.this.process.state != State.LANDING && this.ticksNearUnchanged > 100) { + if (LegacyElytraBehavior.this.process.state != ElytraProcess.State.LANDING && this.ticksNearUnchanged > 100) { this.pathRecalcSegment(rangeEndExcl - 1) .thenRun(() -> { logDirect("Recalculating segment, no progress in last 100 ticks"); @@ -318,7 +306,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!ElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { + if (!LegacyElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment final BetterBlockPos blockage = this.path.get(i); @@ -461,7 +449,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - @Override public void pathTo(BlockPos destination) { this.destination = destination; if (!Baritone.settings().elytraAutoJump.value || ctx.player().isElytraFlying()) { @@ -469,7 +456,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - @Override public void cancel() { this.destination = null; this.pathManager.clear(); @@ -483,7 +469,6 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H Arrays.fill(this.nextTickBoostCounter, 0); } - @Override public CompletableFuture resetContext() { if (this.forceResetContext == null) { this.forceResetContext = new CompletableFuture<>(); @@ -491,26 +476,18 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.forceResetContext; } - @Override public void repackChunks() { ((IChunkProviderClient) ctx.world().getChunkProvider()).loadedChunks().values() .forEach(this.context::queueForPacking); } - @Override public boolean isActive() { return baritone.getPathingControlManager().mostRecentInControl() .filter(process -> this.process == process).isPresent(); } - @Override - public boolean isLoaded() { - return true; - } - - @Override public boolean isSafeToCancel() { - return !this.isActive() || !(this.process.state == State.FLYING || this.process.state == State.START_FLYING); + return !this.isActive() || !(this.process.state == ElytraProcess.State.FLYING || this.process.state == ElytraProcess.State.START_FLYING); } @Override @@ -598,9 +575,9 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } /** - * Called by {@link ElytraProcess#onTick(boolean, boolean)} when the process is in control and the player is flying + * Called by {@link baritone.process.ElytraProcess#onTick(boolean, boolean)} when the process is in control and the player is flying */ - private void tick() { + public void tick() { if (this.pathManager.getPath().isEmpty()) { return; } @@ -770,8 +747,8 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ) { // Prioritize boosting fireworks over regular ones // TODO: Take the minimum boost time into account? - if (!baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isBoostingFireworks) && - !baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isFireworks)) { + if (!baritone.getInventoryBehavior().throwaway(true, LegacyElytraBehavior::isBoostingFireworks) && + !baritone.getInventoryBehavior().throwaway(true, LegacyElytraBehavior::isFireworks)) { logDirect("no fireworks"); return; } @@ -793,21 +770,21 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H public final IAimProcessor aimProcessor; public SolverContext(boolean async) { - this.path = ElytraBehavior.this.pathManager.getPath(); - this.playerNear = ElytraBehavior.this.pathManager.getNear(); - this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.ignoreLava = ElytraBehavior.this.ctx.player().isInLava(); + this.path = LegacyElytraBehavior.this.pathManager.getPath(); + this.playerNear = LegacyElytraBehavior.this.pathManager.getNear(); + this.start = LegacyElytraBehavior.this.ctx.playerFeetAsVec(); + this.ignoreLava = LegacyElytraBehavior.this.ctx.player().isInLava(); final Integer fireworkTicksExisted; - if (async && ElytraBehavior.this.deployedFireworkLastTick) { - final int[] counter = ElytraBehavior.this.nextTickBoostCounter; + if (async && LegacyElytraBehavior.this.deployedFireworkLastTick) { + final int[] counter = LegacyElytraBehavior.this.nextTickBoostCounter; fireworkTicksExisted = counter[1] > counter[0] ? 0 : null; } else { - fireworkTicksExisted = ElytraBehavior.this.getAttachedFirework().map(e -> e.ticksExisted).orElse(null); + fireworkTicksExisted = LegacyElytraBehavior.this.getAttachedFirework().map(e -> e.ticksExisted).orElse(null); } - this.boost = new FireworkBoost(fireworkTicksExisted, ElytraBehavior.this.minimumBoostTicks); + this.boost = new FireworkBoost(fireworkTicksExisted, LegacyElytraBehavior.this.minimumBoostTicks); - ITickableAimProcessor aim = ElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); + ITickableAimProcessor aim = LegacyElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); if (async) { // async computation is done at the end of a tick, advance by 1 to prepare for the next tick aim.advance(1); @@ -1001,7 +978,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H return this.context.raytrace(8, src, dst, NetherPathfinderContext.Visibility.ALL); } - private boolean clearView(Vec3d start, Vec3d dest, boolean ignoreLava) { + public boolean clearView(Vec3d start, Vec3d dest, boolean ignoreLava) { final boolean clear; if (!ignoreLava) { // if start == dest then the cpp raytracer dies @@ -1303,7 +1280,7 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H ItemStack chest = ctx.player().inventory.armorInventory.get(2); if (chest.getItem() != Items.ELYTRA - || chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) { + || chest.getItem().getMaxDamage() - chest.getItemDamage() > Baritone.settings().elytraMinimumDurability.value) { return; } @@ -1382,172 +1359,10 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private final class ElytraProcess implements IBaritoneProcess { - - private State state; - private Goal goal; - - @Override - public boolean isActive() { - return ElytraBehavior.this.destination != null; - } - - @Override - public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { - if (calcFailed) { - onLostControl(); - logDirect("Failed to get to jump off spot, canceling"); - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); - } - - if (ctx.player().isElytraFlying()) { - final BetterBlockPos last = ElytraBehavior.this.pathManager.path.getLast(); - if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { - this.state = State.LANDING; - } - } - - if (this.state == State.LANDING) { - final BetterBlockPos endPos = ElytraBehavior.this.pathManager.path.getLast(); - if (ctx.player().isElytraFlying() && endPos != null) { - Vec3d from = ctx.player().getPositionVector(); - Vec3d to = new Vec3d(endPos.x, from.y, endPos.z); - Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); - baritone.getLookBehavior().updateTarget(rotation, false); - } else { - this.onLostControl(); - return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); - } - } else if (ctx.player().isElytraFlying()) { - this.state = State.FLYING; - this.goal = null; - baritone.getInputOverrideHandler().clearAllKeys(); - ElytraBehavior.this.tick(); - 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; - } - - if (this.state == State.LOCATE_JUMP) { - if (this.goal == null) { - this.goal = new GoalYLevel(31); - } - 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) { - final BetterBlockPos from = new BetterBlockPos( - (fall.getSrc().x + fall.getDest().x) / 2, - (fall.getSrc().y + fall.getDest().y) / 2, - (fall.getSrc().z + fall.getDest().z) / 2 - ); - ElytraBehavior.this.pathManager.pathToDestination(from).whenComplete((result, ex) -> { - if (!ElytraBehavior.this.clearView(new Vec3d(from), ElytraBehavior.this.pathManager.getPath().getVec(0), false)) { - onLostControl(); - // TODO: Get to higher ground and then look again - logDirect("Can't see start of path from jump spot, canceling"); - return; - } - if (ex == null) { - this.state = State.GET_TO_JUMP; - return; - } - onLostControl(); - }); - this.state = State.PAUSE; - } else { - onLostControl(); - logDirect("Jump off path didn't include a fall movement, canceling"); - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); - } - } - return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new WalkOffCalculationContext(baritone)); - } - - // yucky - if (this.state == State.PAUSE) { - return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); - } - - if (this.state == State.GET_TO_JUMP) { - 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(null, PathingCommandType.SET_GOAL_AND_PATH); - } - } - - if (this.state == State.START_FLYING) { - if (!isSafeToCancel) { - // owned - baritone.getPathingBehavior().secretInternalSegmentCancel(); - } - baritone.getInputOverrideHandler().clearAllKeys(); - if (ctx.player().fallDistance > 1.0f) { - baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true); - } - } - return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); - } - - @Override - public boolean isTemporary() { - return false; - } - - @Override - public void onLostControl() { - this.goal = null; - this.state = State.START_FLYING; - ElytraBehavior.this.cancel(); - } - - @Override - public double priority() { - return 10; - } - - @Override - public String displayName0() { - final Supplier status = () -> { - switch (this.state) { - case LOCATE_JUMP: - return "Finding spot to jump off"; - case PAUSE: - return "Waiting for elytra path"; - case GET_TO_JUMP: - return "Walking to takeoff"; - case START_FLYING: - return "Begin flying"; - case FLYING: - return "Flying"; - case LANDING: - return "Landing"; - default: - return "Unknown"; - } - }; - return "Elytra - " + status.get(); - } - } - /** * Custom calculation context which makes the player fall into lava */ - private static final class WalkOffCalculationContext extends CalculationContext { + public static final class WalkOffCalculationContext extends CalculationContext { public WalkOffCalculationContext(IBaritone baritone) { super(baritone, true); @@ -1572,19 +1387,5 @@ public final class ElytraBehavior extends Behavior implements IElytraBehavior, H } } - private enum State { - LOCATE_JUMP, - VALIDATE_PATH, - PAUSE, - GET_TO_JUMP, - START_FLYING, - FLYING, - LANDING - } - public static T create(final Baritone baritone) { - return (T) (NetherPathfinderContext.isSupported() - ? new ElytraBehavior(baritone) - : new NullElytraBehavior(baritone)); - } } diff --git a/src/main/java/baritone/behavior/elytra/NetherPath.java b/src/main/java/baritone/process/elytra/NetherPath.java similarity index 98% rename from src/main/java/baritone/behavior/elytra/NetherPath.java rename to src/main/java/baritone/process/elytra/NetherPath.java index e746665c4..59cd447ce 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPath.java +++ b/src/main/java/baritone/process/elytra/NetherPath.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; import baritone.api.utils.BetterBlockPos; import net.minecraft.util.math.Vec3d; diff --git a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java similarity index 98% rename from src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java rename to src/main/java/baritone/process/elytra/NetherPathfinderContext.java index ebe563374..46a840981 100644 --- a/src/main/java/baritone/behavior/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; import baritone.api.event.events.BlockChangeEvent; import baritone.utils.accessor.IBitArray; @@ -38,6 +38,7 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; +import java.util.concurrent.atomic.AtomicInteger; /** * @author Brady @@ -51,6 +52,7 @@ public final class NetherPathfinderContext { final long context; private final long seed; private final ExecutorService executor; + private final AtomicInteger packQueueSize = new AtomicInteger(); public NetherPathfinderContext(long seed) { this.context = NetherPathfinder.newContext(seed); diff --git a/src/main/java/baritone/behavior/elytra/NullElytraBehavior.java b/src/main/java/baritone/process/elytra/NullElytraProcess.java similarity index 72% rename from src/main/java/baritone/behavior/elytra/NullElytraBehavior.java rename to src/main/java/baritone/process/elytra/NullElytraProcess.java index b173d82b8..a84caf43f 100644 --- a/src/main/java/baritone/behavior/elytra/NullElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/NullElytraProcess.java @@ -15,11 +15,12 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; import baritone.Baritone; -import baritone.api.behavior.IElytraBehavior; -import baritone.behavior.Behavior; +import baritone.api.process.IElytraProcess; +import baritone.api.process.PathingCommand; +import baritone.utils.BaritoneProcessHelper; import net.minecraft.util.math.BlockPos; import java.util.concurrent.CompletableFuture; @@ -27,9 +28,9 @@ import java.util.concurrent.CompletableFuture; /** * @author Brady */ -public final class NullElytraBehavior extends Behavior implements IElytraBehavior { +public final class NullElytraProcess extends BaritoneProcessHelper implements IElytraProcess { - public NullElytraBehavior(Baritone baritone) { + public NullElytraProcess(Baritone baritone) { super(baritone); } @@ -58,6 +59,21 @@ public final class NullElytraBehavior extends Behavior implements IElytraBehavio return false; } + @Override + public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + throw new UnsupportedOperationException("Called onTick on NullElytraProcess"); + } + + @Override + public void onLostControl() { + + } + + @Override + public String displayName0() { + return "NullElytraProcess"; + } + @Override public boolean isLoaded() { return false; diff --git a/src/main/java/baritone/behavior/elytra/PathCalculationException.java b/src/main/java/baritone/process/elytra/PathCalculationException.java similarity index 96% rename from src/main/java/baritone/behavior/elytra/PathCalculationException.java rename to src/main/java/baritone/process/elytra/PathCalculationException.java index 73ce82faf..7c9721487 100644 --- a/src/main/java/baritone/behavior/elytra/PathCalculationException.java +++ b/src/main/java/baritone/process/elytra/PathCalculationException.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; /** * @author Brady diff --git a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java b/src/main/java/baritone/process/elytra/UnpackedSegment.java similarity index 98% rename from src/main/java/baritone/behavior/elytra/UnpackedSegment.java rename to src/main/java/baritone/process/elytra/UnpackedSegment.java index 0e0759625..02f07feb8 100644 --- a/src/main/java/baritone/behavior/elytra/UnpackedSegment.java +++ b/src/main/java/baritone/process/elytra/UnpackedSegment.java @@ -15,7 +15,7 @@ * along with Baritone. If not, see . */ -package baritone.behavior.elytra; +package baritone.process.elytra; import baritone.api.utils.BetterBlockPos; import dev.babbaj.pathfinder.PathSegment; From dbc0a46b103687f8480f0dc6be688c1ed09e6a0e Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 00:34:48 -0400 Subject: [PATCH 201/276] call elytra event handlers from ElytraProcess --- .../baritone/api/process/IElytraProcess.java | 1 + .../baritone/behavior/PathingBehavior.java | 2 + .../java/baritone/process/ElytraProcess.java | 65 +++++++++++++++---- .../process/elytra/LegacyElytraBehavior.java | 26 ++++---- .../elytra/NetherPathfinderContext.java | 1 - 5 files changed, 66 insertions(+), 29 deletions(-) diff --git a/src/api/java/baritone/api/process/IElytraProcess.java b/src/api/java/baritone/api/process/IElytraProcess.java index 06c658f42..b1bd3d833 100644 --- a/src/api/java/baritone/api/process/IElytraProcess.java +++ b/src/api/java/baritone/api/process/IElytraProcess.java @@ -29,6 +29,7 @@ public interface IElytraProcess extends IBaritoneProcess { * * @return A {@link CompletableFuture} that is completed when the context is reset */ + @Deprecated CompletableFuture resetContext(); void repackChunks(); diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 0404921ae..9b15b88ba 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -33,6 +33,7 @@ import baritone.pathing.calc.AbstractNodeCostSearch; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.MovementHelper; import baritone.pathing.path.PathExecutor; +import baritone.process.ElytraProcess; import baritone.utils.PathRenderer; import baritone.utils.PathingCommandContext; import baritone.utils.pathing.Favoring; @@ -93,6 +94,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, @Override public void onTick(TickEvent event) { + ((ElytraProcess) baritone.getElytraProcess()).onTickBeforePathingBehavior(event); dispatchEvents(); if (event.getType() == TickEvent.Type.OUT) { secretInternalSegmentCancel(); diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 121b37b8a..11f4fdeaf 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -18,6 +18,8 @@ package baritone.process; import baritone.Baritone; +import baritone.api.event.events.*; +import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalYLevel; import baritone.api.pathing.movement.IMovement; @@ -43,7 +45,7 @@ import net.minecraft.util.math.Vec3d; import java.util.concurrent.*; import java.util.function.Supplier; -public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess { +public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { public State state; private Goal goal; private LegacyElytraBehavior behavior; @@ -51,7 +53,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private ElytraProcess(Baritone baritone) { super(baritone); this.behavior = new LegacyElytraBehavior(baritone, this); - baritone.getGameEventHandler().registerEventListener(this.behavior); + baritone.getGameEventHandler().registerEventListener(this); } public static T create(final Baritone baritone) { @@ -62,7 +64,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public boolean isActive() { - return behavior.destination != null; + return behavior != null; } @Override @@ -176,16 +178,12 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - @Override - public boolean isTemporary() { - return false; - } - @Override public void onLostControl() { this.goal = null; - this.state = State.START_FLYING; - behavior.cancel(); + this.state = State.START_FLYING; // TODO: null state? + if (this.behavior != null) this.behavior.cancel(); + this.behavior = null; } @@ -220,17 +218,22 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void repackChunks() { - behavior.repackChunks(); + this.behavior.repackChunks(); } @Override public void pathTo(BlockPos destination) { - behavior.pathTo(destination); + this.behavior = new LegacyElytraBehavior(this.baritone, this); + if (ctx.world() != null) { + this.behavior.repackChunks(); + } + this.behavior.pathTo(destination); } @Override public void cancel() { - behavior.cancel(); + if (this.behavior != null) this.behavior.cancel(); + this.behavior = null; } @Override @@ -240,7 +243,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public boolean isSafeToCancel() { - return behavior.isSafeToCancel(); + return !this.isActive() || !(this.state == State.FLYING || this.state == State.START_FLYING); } public enum State { @@ -252,4 +255,38 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro FLYING, LANDING } + + @Override + public void onRenderPass(RenderEvent event) { + if (this.behavior != null) this.behavior.onRenderPass(event); + } + + @Override + public void onWorldEvent(WorldEvent event) { + if (this.behavior != null) this.behavior.onWorldEvent(event); + } + + @Override + public void onChunkEvent(ChunkEvent event) { + if (this.behavior != null) this.behavior.onChunkEvent(event); + } + + @Override + public void onBlockChange(BlockChangeEvent event) { + if (this.behavior != null) this.behavior.onBlockChange(event); + } + + @Override + public void onReceivePacket(PacketEvent event) { + if (this.behavior != null) this.behavior.onReceivePacket(event); + } + + public void onTickBeforePathingBehavior(final TickEvent event) { + if (this.behavior != null) this.behavior.onTick(event); + } + + @Override + public void onPostTick(TickEvent event) { + if (this.behavior != null) this.behavior.onPostTick(event); + } } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 48066f3ea..6553f1ef8 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -24,7 +24,6 @@ import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.event.events.*; import baritone.api.event.events.type.EventState; -import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.pathing.goals.GoalBlock; import baritone.api.utils.*; import baritone.pathing.movement.CalculationContext; @@ -51,6 +50,7 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; +import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.awt.*; @@ -63,7 +63,7 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF; import static baritone.utils.BaritoneMath.fastCeil; import static baritone.utils.BaritoneMath.fastFloor; -public final class LegacyElytraBehavior implements AbstractGameEventListener, Helper { +public final class LegacyElytraBehavior implements Helper { private final Baritone baritone; private final IPlayerContext ctx; @@ -76,7 +76,7 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H public List visiblePath; // :sunglasses: - private NetherPathfinderContext context; + private NetherPathfinderContext context; // TODO: make this final private CompletableFuture forceResetContext; public final PathManager pathManager; private final ElytraProcess process; @@ -125,6 +125,8 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H this.process = process; this.solverExecutor = Executors.newSingleThreadExecutor(); this.nextTickBoostCounter = new int[2]; + + this.context = new NetherPathfinderContext(Baritone.settings().elytraNetherSeed.value); } public final class PathManager { @@ -370,7 +372,6 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H } } - @Override public void onRenderPass(RenderEvent event) { final Settings settings = Baritone.settings(); if (this.visiblePath != null) { @@ -409,7 +410,7 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H } } - @Override + // TODO: move this logic to ElytraProcess public void onWorldEvent(WorldEvent event) { if (event.getWorld() != null) { if (event.getState() == EventState.PRE) { @@ -427,7 +428,6 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H } } - @Override public void onChunkEvent(ChunkEvent event) { if (event.isPostPopulate() && this.context != null) { final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); @@ -435,12 +435,16 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H } } - @Override + public void uploadRenderDistance(World world) { + ((IChunkProviderClient) world.getChunkProvider()).loadedChunks().forEach((l, chunk) -> { + this.context.queueForPacking(chunk); + }); + } + public void onBlockChange(BlockChangeEvent event) { this.context.queueBlockUpdate(event); } - @Override public void onReceivePacket(PacketEvent event) { if (event.getPacket() instanceof SPacketPlayerPosLook) { ctx.minecraft().addScheduledTask(() -> { @@ -486,11 +490,6 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H .filter(process -> this.process == process).isPresent(); } - public boolean isSafeToCancel() { - return !this.isActive() || !(this.process.state == ElytraProcess.State.FLYING || this.process.state == ElytraProcess.State.START_FLYING); - } - - @Override public void onTick(final TickEvent event) { if (event.getType() == TickEvent.Type.OUT) { return; @@ -629,7 +628,6 @@ public final class LegacyElytraBehavior implements AbstractGameEventListener, H ); } - @Override public void onPostTick(TickEvent event) { if (event.getType() == TickEvent.Type.IN && this.solveNextTick) { // We're at the end of the tick, the player's position likely updated and the closest path node could've diff --git a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java index 46a840981..69ac41992 100644 --- a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java @@ -52,7 +52,6 @@ public final class NetherPathfinderContext { final long context; private final long seed; private final ExecutorService executor; - private final AtomicInteger packQueueSize = new AtomicInteger(); public NetherPathfinderContext(long seed) { this.context = NetherPathfinder.newContext(seed); From 4b5d629df6097a8b0735314f48fd57f61c939c9c Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 17:21:06 -0400 Subject: [PATCH 202/276] fix off by one error (causing the last point to be stuck in terrain) --- build.gradle | 4 ++-- .../java/baritone/process/elytra/LegacyElytraBehavior.java | 3 ++- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index e44d68e04..04017277c 100755 --- a/build.gradle +++ b/build.gradle @@ -175,8 +175,8 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.34') - implementation 'dev.babbaj:nether-pathfinder:0.34' + launchImplementation('dev.babbaj:nether-pathfinder:0.39') + implementation 'dev.babbaj:nether-pathfinder:0.39' testImplementation 'junit:junit:4.12' } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 6553f1ef8..f537f93bc 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -195,7 +195,7 @@ public final class LegacyElytraBehavior implements Helper { } this.recalculating = true; - final List after = this.path.subList(upToIncl, this.path.size()); + final List after = this.path.subList(upToIncl + 1, this.path.size()); final boolean complete = this.completePath; return this.path0(ctx.playerFeet(), this.path.get(upToIncl), segment -> segment.append(after.stream(), complete)) @@ -288,6 +288,7 @@ public final class LegacyElytraBehavior implements Helper { while (rangeEndExcl < path.size() && ctx.world().isBlockLoaded(path.get(rangeEndExcl), false)) { rangeEndExcl++; } + // rangeEndExcl now represents an index either not in the path, or just outside render distance if (rangeStartIncl >= rangeEndExcl) { // not loaded yet? return; From afe9359d3e781db9c12af778769658ce25e58ac5 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 18:11:33 -0400 Subject: [PATCH 203/276] don't call onTick if we are pawsed --- .../java/baritone/behavior/PathingBehavior.java | 1 - src/main/java/baritone/process/ElytraProcess.java | 15 ++++++++++----- .../process/elytra/LegacyElytraBehavior.java | 6 +----- 3 files changed, 11 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 9b15b88ba..3733a9144 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -94,7 +94,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, @Override public void onTick(TickEvent event) { - ((ElytraProcess) baritone.getElytraProcess()).onTickBeforePathingBehavior(event); dispatchEvents(); if (event.getType() == TickEvent.Type.OUT) { secretInternalSegmentCancel(); diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 11f4fdeaf..0f6763346 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -49,6 +49,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public State state; private Goal goal; private LegacyElytraBehavior behavior; + private boolean skippedThisTick = false; private ElytraProcess(Baritone baritone) { super(baritone); @@ -69,6 +70,14 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { + IBaritoneProcess procLastTick = baritone.getPathingControlManager().mostRecentInControl().orElse(null); + // this is true if the pause process was running or any other processes that causes us to not tick + skippedThisTick = procLastTick != null && procLastTick.priority() > this.priority(); + if (skippedThisTick) { + return new PathingCommand(null, PathingCommandType.DEFER); + } + + this.behavior.onTick(); if (calcFailed) { onLostControl(); logDirect("Failed to get to jump off spot, canceling"); @@ -281,12 +290,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (this.behavior != null) this.behavior.onReceivePacket(event); } - public void onTickBeforePathingBehavior(final TickEvent event) { - if (this.behavior != null) this.behavior.onTick(event); - } - @Override public void onPostTick(TickEvent event) { - if (this.behavior != null) this.behavior.onPostTick(event); + if (this.behavior != null && !skippedThisTick) this.behavior.onPostTick(event); } } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index f537f93bc..2ce91a866 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -491,11 +491,7 @@ public final class LegacyElytraBehavior implements Helper { .filter(process -> this.process == process).isPresent(); } - public void onTick(final TickEvent event) { - if (event.getType() == TickEvent.Type.OUT) { - return; - } - + public void onTick() { // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; if (this.solver != null) { From 2f0497756b1133e05a3db77037cb411eb6b4c48e Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 18:16:09 -0400 Subject: [PATCH 204/276] simplify icky code --- src/main/java/baritone/process/ElytraProcess.java | 10 ++-------- 1 file changed, 2 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 0f6763346..cf21b8207 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -70,13 +70,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { - IBaritoneProcess procLastTick = baritone.getPathingControlManager().mostRecentInControl().orElse(null); - // this is true if the pause process was running or any other processes that causes us to not tick - skippedThisTick = procLastTick != null && procLastTick.priority() > this.priority(); - if (skippedThisTick) { - return new PathingCommand(null, PathingCommandType.DEFER); - } - this.behavior.onTick(); if (calcFailed) { onLostControl(); @@ -292,6 +285,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void onPostTick(TickEvent event) { - if (this.behavior != null && !skippedThisTick) this.behavior.onPostTick(event); + IBaritoneProcess procThisTick = baritone.getPathingControlManager().mostRecentInControl().orElse(null); + if (this.behavior != null && procThisTick == this) this.behavior.onPostTick(event); } } From ff1b3e7c5f24daa0de448bf834019fda90bd62ae Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 22:57:24 -0400 Subject: [PATCH 205/276] simplify management of elytra state --- build.gradle | 4 +- .../baritone/api/process/IElytraProcess.java | 21 ++--- .../command/defaults/ElytraCommand.java | 9 +- .../defaults/ExecutionControlCommands.java | 1 - .../command/defaults/ForceCancelCommand.java | 2 +- .../java/baritone/process/ElytraProcess.java | 92 ++++++++++--------- .../process/elytra/LegacyElytraBehavior.java | 74 ++------------- .../process/elytra/NullElytraProcess.java | 12 +-- 8 files changed, 76 insertions(+), 139 deletions(-) diff --git a/build.gradle b/build.gradle index 04017277c..accb7ca54 100755 --- a/build.gradle +++ b/build.gradle @@ -175,8 +175,8 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.39') - implementation 'dev.babbaj:nether-pathfinder:0.39' + launchImplementation('dev.babbaj:nether-pathfinder:0.41') + implementation 'dev.babbaj:nether-pathfinder:0.41' testImplementation 'junit:junit:4.12' } diff --git a/src/api/java/baritone/api/process/IElytraProcess.java b/src/api/java/baritone/api/process/IElytraProcess.java index b1bd3d833..639f69f0e 100644 --- a/src/api/java/baritone/api/process/IElytraProcess.java +++ b/src/api/java/baritone/api/process/IElytraProcess.java @@ -19,24 +19,21 @@ package baritone.api.process; import net.minecraft.util.math.BlockPos; -import java.util.concurrent.CompletableFuture; - public interface IElytraProcess extends IBaritoneProcess { - /** - * Marks the nether pathfinder context to be reset when it is safe to do so. Because this operation is not - * immediate, a {@link CompletableFuture} is returned that will complete after the context has been reset. - * - * @return A {@link CompletableFuture} that is completed when the context is reset - */ - @Deprecated - CompletableFuture resetContext(); - void repackChunks(); + /** + * @return Where it is currently flying to, null if not active + */ + BlockPos currentDestination(); + void pathTo(BlockPos destination); - void cancel(); + /** + * Resets the state of the process but will maintain the same destination and will try to keep flying + */ + void resetState(); /** * @return {@code true} if the native library loaded and elytra is actually usable diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 05695d82b..418a6c7ac 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -85,10 +85,11 @@ public class ElytraCommand extends Command { final String action = args.getString(); switch (action) { case "reset": { - elytra.resetContext().whenComplete((result, ex) -> { - logDirect("Context reset, repacking chunks"); - elytra.repackChunks(); - }); + BlockPos destination = elytra.currentDestination(); + elytra.onLostControl(); + elytra.pathTo(destination); + elytra.repackChunks(); + logDirect("Reset state but still flying to same goal"); break; } case "repack": { diff --git a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java index b91014a67..6f6293ccd 100644 --- a/src/main/java/baritone/command/defaults/ExecutionControlCommands.java +++ b/src/main/java/baritone/command/defaults/ExecutionControlCommands.java @@ -180,7 +180,6 @@ public class ExecutionControlCommands { paused[0] = false; } baritone.getPathingBehavior().cancelEverything(); - baritone.getElytraProcess().cancel(); // TODO: this shouldnt be necessary logDirect("ok canceled"); } diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index d86cddd5e..b5abb6392 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -39,7 +39,7 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); - baritone.getElytraProcess().cancel(); + baritone.getElytraProcess().onLostControl(); // is this necessary? logDirect("ok force canceled"); } diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index cf21b8207..793f2a807 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -19,6 +19,7 @@ package baritone.process; import baritone.Baritone; import baritone.api.event.events.*; +import baritone.api.event.events.type.EventState; import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalYLevel; @@ -42,9 +43,6 @@ import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import java.util.concurrent.*; -import java.util.function.Supplier; - public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { public State state; private Goal goal; @@ -63,14 +61,32 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro : new NullElytraProcess(baritone)); } + + @Override public boolean isActive() { return behavior != null; } + @Override + public void resetState() { + BlockPos destination = this.currentDestination(); + this.onLostControl(); + this.pathTo(destination); + this.repackChunks(); + } + @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { - this.behavior.onTick(); + final long seedSetting = Baritone.settings().elytraNetherSeed.value; + if (this.behavior != null && seedSetting != behavior.context.getSeed()) { + logDirect("Nether seed changed, recalculating path"); + this.resetState(); + } + + if (this.behavior != null) { + this.behavior.onTick(); + } if (calcFailed) { onLostControl(); logDirect("Failed to get to jump off spot, canceling"); @@ -184,38 +200,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public void onLostControl() { this.goal = null; this.state = State.START_FLYING; // TODO: null state? - if (this.behavior != null) this.behavior.cancel(); + if (this.behavior != null) this.behavior.destroy(); this.behavior = null; } - - @Override public String displayName0() { - final Supplier status = () -> { - switch (this.state) { - case LOCATE_JUMP: - return "Finding spot to jump off"; - case PAUSE: - return "Waiting for elytra path"; - case GET_TO_JUMP: - return "Walking to takeoff"; - case START_FLYING: - return "Begin flying"; - case FLYING: - return "Flying"; - case LANDING: - return "Landing"; - default: - return "Unknown"; - } - }; - return "Elytra - " + status.get(); - } - - @Override - public CompletableFuture resetContext() { - return behavior.resetContext(); + return "Elytra - " + this.state.description; } @Override @@ -223,6 +214,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.behavior.repackChunks(); } + @Override + public BlockPos currentDestination() { + return this.behavior != null ? this.behavior.destination : null; + } + @Override public void pathTo(BlockPos destination) { this.behavior = new LegacyElytraBehavior(this.baritone, this); @@ -232,12 +228,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.behavior.pathTo(destination); } - @Override - public void cancel() { - if (this.behavior != null) this.behavior.cancel(); - this.behavior = null; - } - @Override public boolean isLoaded() { return true; @@ -249,13 +239,19 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } public enum State { - LOCATE_JUMP, - VALIDATE_PATH, - PAUSE, - GET_TO_JUMP, - START_FLYING, - FLYING, - LANDING + LOCATE_JUMP("Finding spot to jump off"), + VALIDATE_PATH("Validating path"), + PAUSE("Waiting for elytra path"), + GET_TO_JUMP("Walking to takeoff"), + START_FLYING("Begin flying"), + FLYING("Flying"), + LANDING("Landing"); + + public String description; + + State(String desc) { + this.description = desc; + } } @Override @@ -265,7 +261,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void onWorldEvent(WorldEvent event) { - if (this.behavior != null) this.behavior.onWorldEvent(event); + if (event.getWorld() != null && event.getState() == EventState.POST) { + // Exiting the world, just destroy + if (this.behavior != null) { + this.behavior.destroy(); + this.behavior = new LegacyElytraBehavior(baritone, this); + } + } } @Override diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 2ce91a866..11e69e620 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -23,7 +23,6 @@ import baritone.api.Settings; import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.event.events.*; -import baritone.api.event.events.type.EventState; import baritone.api.pathing.goals.GoalBlock; import baritone.api.utils.*; import baritone.pathing.movement.CalculationContext; @@ -50,7 +49,6 @@ import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.MathHelper; import net.minecraft.util.math.Vec3d; -import net.minecraft.world.World; import net.minecraft.world.chunk.Chunk; import java.awt.*; @@ -76,8 +74,7 @@ public final class LegacyElytraBehavior implements Helper { public List visiblePath; // :sunglasses: - private NetherPathfinderContext context; // TODO: make this final - private CompletableFuture forceResetContext; + public final NetherPathfinderContext context; // TODO: make this final public final PathManager pathManager; private final ElytraProcess process; @@ -102,8 +99,8 @@ public final class LegacyElytraBehavior implements Helper { private final int[] nextTickBoostCounter; private BlockStateInterface bsi; - private BlockStateOctreeInterface boi; - public BlockPos destination; + private final BlockStateOctreeInterface boi; + public BlockPos destination; // TODO: make this final? private final ExecutorService solverExecutor; private Future solver; @@ -127,6 +124,7 @@ public final class LegacyElytraBehavior implements Helper { this.nextTickBoostCounter = new int[2]; this.context = new NetherPathfinderContext(Baritone.settings().elytraNetherSeed.value); + this.boi = new BlockStateOctreeInterface(context); } public final class PathManager { @@ -411,24 +409,6 @@ public final class LegacyElytraBehavior implements Helper { } } - // TODO: move this logic to ElytraProcess - public void onWorldEvent(WorldEvent event) { - if (event.getWorld() != null) { - if (event.getState() == EventState.PRE) { - // Reset the context when it's safe to do so on the next game tick - this.resetContext(); - } - } else { - if (event.getState() == EventState.POST) { - // Exiting the world, just destroy and invalidate the context - if (this.context != null) { - this.context.destroy(); - this.context = null; - } - } - } - } - public void onChunkEvent(ChunkEvent event) { if (event.isPostPopulate() && this.context != null) { final Chunk chunk = ctx.world().getChunk(event.getX(), event.getZ()); @@ -436,12 +416,6 @@ public final class LegacyElytraBehavior implements Helper { } } - public void uploadRenderDistance(World world) { - ((IChunkProviderClient) world.getChunkProvider()).loadedChunks().forEach((l, chunk) -> { - this.context.queueForPacking(chunk); - }); - } - public void onBlockChange(BlockChangeEvent event) { this.context.queueBlockUpdate(event); } @@ -461,24 +435,11 @@ public final class LegacyElytraBehavior implements Helper { } } - public void cancel() { - this.destination = null; - this.pathManager.clear(); - this.remainingFireworkTicks = 0; - this.remainingSetBackTicks = 0; + public void destroy() { if (this.solver != null) { this.solver.cancel(true); - this.solver = null; } - this.pendingSolution = null; - Arrays.fill(this.nextTickBoostCounter, 0); - } - - public CompletableFuture resetContext() { - if (this.forceResetContext == null) { - this.forceResetContext = new CompletableFuture<>(); - } - return this.forceResetContext; + this.context.destroy(); } public void repackChunks() { @@ -486,11 +447,6 @@ public final class LegacyElytraBehavior implements Helper { .forEach(this.context::queueForPacking); } - public boolean isActive() { - return baritone.getPathingControlManager().mostRecentInControl() - .filter(process -> this.process == process).isPresent(); - } - public void onTick() { // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; @@ -504,23 +460,6 @@ public final class LegacyElytraBehavior implements Helper { } } - // Setup/reset context - final long netherSeed = Baritone.settings().elytraNetherSeed.value; - if (this.context == null || this.context.getSeed() != netherSeed || this.forceResetContext != null) { - if (this.context != null) { - this.context.destroy(); - } - this.context = new NetherPathfinderContext(netherSeed); - if (this.forceResetContext != null) { - this.forceResetContext.complete(null); - this.forceResetContext = null; - } - if (this.context.getSeed() != netherSeed && this.isActive()) { - logDirect("Nether seed changed, recalculating path"); - this.pathManager.pathToDestination(); - } - } - tickInventoryTransactions(); // Certified mojang employee incident @@ -554,7 +493,6 @@ public final class LegacyElytraBehavior implements Helper { // ctx AND context???? :DDD this.bsi = new BlockStateInterface(ctx); - this.boi = new BlockStateOctreeInterface(context); this.pathManager.tick(); final int playerNear = this.pathManager.getNear(); diff --git a/src/main/java/baritone/process/elytra/NullElytraProcess.java b/src/main/java/baritone/process/elytra/NullElytraProcess.java index a84caf43f..0c11ba618 100644 --- a/src/main/java/baritone/process/elytra/NullElytraProcess.java +++ b/src/main/java/baritone/process/elytra/NullElytraProcess.java @@ -35,13 +35,13 @@ public final class NullElytraProcess extends BaritoneProcessHelper implements IE } @Override - public CompletableFuture resetContext() { - throw new UnsupportedOperationException("Called resetContext() on NullElytraBehavior"); + public void repackChunks() { + throw new UnsupportedOperationException("Called repackChunks() on NullElytraBehavior"); } @Override - public void repackChunks() { - throw new UnsupportedOperationException("Called repackChunks() on NullElytraBehavior"); + public BlockPos currentDestination() { + return null; } @Override @@ -50,8 +50,8 @@ public final class NullElytraProcess extends BaritoneProcessHelper implements IE } @Override - public void cancel() { - throw new UnsupportedOperationException("Called cancel() on NullElytraBehavior"); + public void resetState() { + } @Override From ccd80dfc8fec365185730eec928d68e89f988cd1 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 17 Jul 2023 23:02:35 -0400 Subject: [PATCH 206/276] that isn't necessary --- src/main/java/baritone/command/defaults/ForceCancelCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/baritone/command/defaults/ForceCancelCommand.java b/src/main/java/baritone/command/defaults/ForceCancelCommand.java index b5abb6392..513d61bcb 100644 --- a/src/main/java/baritone/command/defaults/ForceCancelCommand.java +++ b/src/main/java/baritone/command/defaults/ForceCancelCommand.java @@ -39,7 +39,6 @@ public class ForceCancelCommand extends Command { IPathingBehavior pathingBehavior = baritone.getPathingBehavior(); pathingBehavior.cancelEverything(); pathingBehavior.forceCancel(); - baritone.getElytraProcess().onLostControl(); // is this necessary? logDirect("ok force canceled"); } From f4996137a33d6dc0dcecdd15395a823308d5e6ca Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 18 Jul 2023 00:02:23 -0400 Subject: [PATCH 207/276] minor code improvements --- src/main/java/baritone/Baritone.java | 1 - src/main/java/baritone/command/defaults/ElytraCommand.java | 5 +---- src/main/java/baritone/process/ElytraProcess.java | 3 +-- 3 files changed, 2 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index c6d31a3dd..0bd6a814a 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -125,7 +125,6 @@ public class Baritone implements IBaritone { this.farmProcess = this.registerProcess(FarmProcess::new); this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new); this.elytraProcess = this.registerProcess(ElytraProcess::create); - this.registerProcess(BackfillProcess::new); } diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 418a6c7ac..eea7f3f33 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -85,10 +85,7 @@ public class ElytraCommand extends Command { final String action = args.getString(); switch (action) { case "reset": { - BlockPos destination = elytra.currentDestination(); - elytra.onLostControl(); - elytra.pathTo(destination); - elytra.repackChunks(); + elytra.resetState(); logDirect("Reset state but still flying to same goal"); break; } diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 793f2a807..6738cab55 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -47,7 +47,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public State state; private Goal goal; private LegacyElytraBehavior behavior; - private boolean skippedThisTick = false; private ElytraProcess(Baritone baritone) { super(baritone); @@ -247,7 +246,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro FLYING("Flying"), LANDING("Landing"); - public String description; + public final String description; State(String desc) { this.description = desc; From ba78c48a7563f1b77ef3348ece08a57cf0f4e84f Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 18 Jul 2023 00:07:26 -0400 Subject: [PATCH 208/276] shutdown solverExecutor --- src/main/java/baritone/process/elytra/LegacyElytraBehavior.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 11e69e620..c7a164593 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -439,6 +439,7 @@ public final class LegacyElytraBehavior implements Helper { if (this.solver != null) { this.solver.cancel(true); } + this.solverExecutor.shutdown(); this.context.destroy(); } From 38553b33248f0146ec18cb56bc62f3b8515ea46a Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 18 Jul 2023 14:52:09 -0400 Subject: [PATCH 209/276] behavior can't be null in onTick --- .../java/baritone/process/ElytraProcess.java | 25 ++++++++++--------- 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 6738cab55..eb3c1bdd8 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -78,14 +78,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { final long seedSetting = Baritone.settings().elytraNetherSeed.value; - if (this.behavior != null && seedSetting != behavior.context.getSeed()) { + if (seedSetting != behavior.context.getSeed()) { logDirect("Nether seed changed, recalculating path"); this.resetState(); } - if (this.behavior != null) { - this.behavior.onTick(); - } + this.behavior.onTick(); + if (calcFailed) { onLostControl(); logDirect("Failed to get to jump off spot, canceling"); @@ -199,8 +198,10 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public void onLostControl() { this.goal = null; this.state = State.START_FLYING; // TODO: null state? - if (this.behavior != null) this.behavior.destroy(); - this.behavior = null; + if (this.behavior != null) { + this.behavior.destroy(); + this.behavior = null; + } } @Override @@ -210,7 +211,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void repackChunks() { - this.behavior.repackChunks(); + if (this.behavior != null) { + this.behavior.repackChunks(); + } } @Override @@ -260,12 +263,10 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void onWorldEvent(WorldEvent event) { - if (event.getWorld() != null && event.getState() == EventState.POST) { + if (event.getWorld() != null && event.getState() == EventState.POST && this.behavior != null) { // Exiting the world, just destroy - if (this.behavior != null) { - this.behavior.destroy(); - this.behavior = new LegacyElytraBehavior(baritone, this); - } + this.behavior.destroy(); + this.behavior = new LegacyElytraBehavior(baritone, this); } } From 0239a2cad435d5a04e94555ddee280e493527222 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 18 Jul 2023 15:36:29 -0400 Subject: [PATCH 210/276] notificationOnPathComplete and disconnectOnArrival --- src/main/java/baritone/process/ElytraProcess.java | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index eb3c1bdd8..e75fbeb81 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -94,6 +94,15 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (ctx.player().isElytraFlying()) { final BetterBlockPos last = behavior.pathManager.path.getLast(); if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { + if (Baritone.settings().notificationOnPathComplete.value) { + logNotification("Pathing complete", false); + } + if (Baritone.settings().disconnectOnArrival.value) { + // don't be active when the user logs back in + this.onLostControl(); + ctx.world().sendQuittingDisconnectingPacket(); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } this.state = State.LANDING; } } From 218de1cb984678855009fd487b7c9b97452205fd Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 18 Jul 2023 16:48:00 -0500 Subject: [PATCH 211/276] Requested changes --- src/api/java/baritone/api/behavior/IBehavior.java | 8 +------- src/main/java/baritone/Baritone.java | 5 ----- src/main/java/baritone/process/ElytraProcess.java | 15 ++++++--------- .../process/elytra/LegacyElytraBehavior.java | 10 +++++----- 4 files changed, 12 insertions(+), 26 deletions(-) diff --git a/src/api/java/baritone/api/behavior/IBehavior.java b/src/api/java/baritone/api/behavior/IBehavior.java index aea44ed3e..811563b93 100644 --- a/src/api/java/baritone/api/behavior/IBehavior.java +++ b/src/api/java/baritone/api/behavior/IBehavior.java @@ -27,10 +27,4 @@ import baritone.api.event.listener.IGameEventListener; * @see IGameEventListener * @since 9/23/2018 */ -public interface IBehavior extends AbstractGameEventListener { - - /** - * Called after Baritone's initialization is complete - */ - default void onLoad() {} -} +public interface IBehavior extends AbstractGameEventListener {} diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 0bd6a814a..08bc6fa24 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -66,7 +66,6 @@ public class Baritone implements IBaritone { private final GameEventHandler gameEventHandler; - private final List behaviors; private final PathingBehavior pathingBehavior; private final LookBehavior lookBehavior; private final InventoryBehavior inventoryBehavior; @@ -93,7 +92,6 @@ public class Baritone implements IBaritone { Baritone(Minecraft mc) { this.mc = mc; - this.behaviors = new ArrayList<>(); this.gameEventHandler = new GameEventHandler(this); this.directory = mc.gameDir.toPath().resolve("baritone"); @@ -131,12 +129,9 @@ public class Baritone implements IBaritone { this.worldProvider = new WorldProvider(this); this.selectionManager = new SelectionManager(this); this.commandManager = new CommandManager(this); - - this.behaviors.forEach(IBehavior::onLoad); } public void registerBehavior(IBehavior behavior) { - this.behaviors.add(behavior); this.gameEventHandler.registerEventListener(behavior); } diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index e75fbeb81..edd0da2f6 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -42,15 +42,14 @@ import baritone.utils.PathingCommandContext; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; - public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { + public State state; private Goal goal; private LegacyElytraBehavior behavior; private ElytraProcess(Baritone baritone) { super(baritone); - this.behavior = new LegacyElytraBehavior(baritone, this); baritone.getGameEventHandler().registerEventListener(this); } @@ -60,11 +59,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro : new NullElytraProcess(baritone)); } - - @Override public boolean isActive() { - return behavior != null; + return this.behavior != null; } @Override @@ -78,7 +75,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { final long seedSetting = Baritone.settings().elytraNetherSeed.value; - if (seedSetting != behavior.context.getSeed()) { + if (seedSetting != this.behavior.context.getSeed()) { logDirect("Nether seed changed, recalculating path"); this.resetState(); } @@ -232,11 +229,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { - this.behavior = new LegacyElytraBehavior(this.baritone, this); + this.behavior = new LegacyElytraBehavior(this.baritone, this, destination); if (ctx.world() != null) { this.behavior.repackChunks(); } - this.behavior.pathTo(destination); + this.behavior.pathTo(); } @Override @@ -275,7 +272,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (event.getWorld() != null && event.getState() == EventState.POST && this.behavior != null) { // Exiting the world, just destroy this.behavior.destroy(); - this.behavior = new LegacyElytraBehavior(baritone, this); + this.behavior = null; } } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index c7a164593..825d3087d 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -74,7 +74,7 @@ public final class LegacyElytraBehavior implements Helper { public List visiblePath; // :sunglasses: - public final NetherPathfinderContext context; // TODO: make this final + public final NetherPathfinderContext context; public final PathManager pathManager; private final ElytraProcess process; @@ -100,7 +100,7 @@ public final class LegacyElytraBehavior implements Helper { private BlockStateInterface bsi; private final BlockStateOctreeInterface boi; - public BlockPos destination; // TODO: make this final? + public final BlockPos destination; private final ExecutorService solverExecutor; private Future solver; @@ -113,13 +113,14 @@ public final class LegacyElytraBehavior implements Helper { private int invTickCountdown = 0; private final Queue invTransactionQueue = new LinkedList<>(); - public LegacyElytraBehavior(Baritone baritone, ElytraProcess process) { + public LegacyElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination) { this.baritone = baritone; this.ctx = baritone.getPlayerContext(); this.clearLines = new CopyOnWriteArrayList<>(); this.blockedLines = new CopyOnWriteArrayList<>(); this.pathManager = this.new PathManager(); this.process = process; + this.destination = destination; this.solverExecutor = Executors.newSingleThreadExecutor(); this.nextTickBoostCounter = new int[2]; @@ -428,8 +429,7 @@ public final class LegacyElytraBehavior implements Helper { } } - public void pathTo(BlockPos destination) { - this.destination = destination; + public void pathTo() { if (!Baritone.settings().elytraAutoJump.value || ctx.player().isElytraFlying()) { this.pathManager.pathToDestination(); } From 097e30850f4a577c01b668c7d4a35a6acc27ee54 Mon Sep 17 00:00:00 2001 From: Brady Date: Tue, 18 Jul 2023 23:35:09 -0500 Subject: [PATCH 212/276] Move `WalkOffCalculationContext` into `ElytraProcess` --- .../java/baritone/process/ElytraProcess.java | 35 ++++++++++++++++++- .../process/elytra/LegacyElytraBehavior.java | 34 ------------------ 2 files changed, 34 insertions(+), 35 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index edd0da2f6..c56ab9896 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -18,6 +18,7 @@ package baritone.process; import baritone.Baritone; +import baritone.api.IBaritone; import baritone.api.event.events.*; import baritone.api.event.events.type.EventState; import baritone.api.event.listener.AbstractGameEventListener; @@ -33,15 +34,19 @@ import baritone.api.utils.BetterBlockPos; import baritone.api.utils.Rotation; import baritone.api.utils.RotationUtils; import baritone.api.utils.input.Input; +import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.movements.MovementFall; import baritone.process.elytra.LegacyElytraBehavior; import baritone.process.elytra.NetherPathfinderContext; import baritone.process.elytra.NullElytraProcess; import baritone.utils.BaritoneProcessHelper; import baritone.utils.PathingCommandContext; +import net.minecraft.block.state.IBlockState; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import static baritone.api.pathing.movement.ActionCosts.COST_INF; + public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { public State state; @@ -165,7 +170,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } } - return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new LegacyElytraBehavior.WalkOffCalculationContext(baritone)); + return new PathingCommandContext(this.goal, PathingCommandType.SET_GOAL_AND_PAUSE, new WalkOffCalculationContext(baritone)); } // yucky @@ -296,4 +301,32 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro IBaritoneProcess procThisTick = baritone.getPathingControlManager().mostRecentInControl().orElse(null); if (this.behavior != null && procThisTick == this) this.behavior.onPostTick(event); } + + /** + * Custom calculation context which makes the player fall into lava + */ + public static final class WalkOffCalculationContext extends CalculationContext { + + public WalkOffCalculationContext(IBaritone baritone) { + super(baritone, true); + this.allowFallIntoLava = true; + this.minFallHeight = 8; + this.maxFallHeightNoWater = 10000; + } + + @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; + } + } } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java index 825d3087d..c147442ce 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java @@ -18,14 +18,12 @@ package baritone.process.elytra; import baritone.Baritone; -import baritone.api.IBaritone; import baritone.api.Settings; import baritone.api.behavior.look.IAimProcessor; import baritone.api.behavior.look.ITickableAimProcessor; import baritone.api.event.events.*; import baritone.api.pathing.goals.GoalBlock; import baritone.api.utils.*; -import baritone.pathing.movement.CalculationContext; import baritone.process.ElytraProcess; import baritone.utils.BlockStateInterface; import baritone.utils.IRenderer; @@ -36,7 +34,6 @@ import it.unimi.dsi.fastutil.floats.FloatArrayList; import it.unimi.dsi.fastutil.floats.FloatIterator; import it.unimi.dsi.fastutil.longs.Long2ReferenceOpenHashMap; import net.minecraft.block.material.Material; -import net.minecraft.block.state.IBlockState; import net.minecraft.entity.item.EntityFireworkRocket; import net.minecraft.init.Items; import net.minecraft.inventory.ClickType; @@ -57,7 +54,6 @@ import java.util.List; import java.util.concurrent.*; import java.util.function.UnaryOperator; -import static baritone.api.pathing.movement.ActionCosts.COST_INF; import static baritone.utils.BaritoneMath.fastCeil; import static baritone.utils.BaritoneMath.fastFloor; @@ -1292,34 +1288,4 @@ public final class LegacyElytraBehavior implements Helper { return result; } } - - /** - * Custom calculation context which makes the player fall into lava - */ - public static final class WalkOffCalculationContext extends CalculationContext { - - public WalkOffCalculationContext(IBaritone baritone) { - super(baritone, true); - this.allowFallIntoLava = true; - this.minFallHeight = 8; - this.maxFallHeightNoWater = 10000; - } - - @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; - } - } - - } From 664375a678080df599c154e04b9cb05444782198 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 22 Jul 2023 01:55:12 -0400 Subject: [PATCH 213/276] make elytra play nice with CustomGoalProcess --- .../baritone/api/process/IElytraProcess.java | 3 ++ .../command/defaults/ElytraCommand.java | 23 +++--------- .../baritone/process/CustomGoalProcess.java | 3 ++ .../java/baritone/process/ElytraProcess.java | 36 +++++++++++++++++-- .../process/elytra/NullElytraProcess.java | 6 ++++ .../baritone/utils/PathingControlManager.java | 14 +++++--- 6 files changed, 58 insertions(+), 27 deletions(-) diff --git a/src/api/java/baritone/api/process/IElytraProcess.java b/src/api/java/baritone/api/process/IElytraProcess.java index 639f69f0e..d0ca6f00c 100644 --- a/src/api/java/baritone/api/process/IElytraProcess.java +++ b/src/api/java/baritone/api/process/IElytraProcess.java @@ -17,6 +17,7 @@ package baritone.api.process; +import baritone.api.pathing.goals.Goal; import net.minecraft.util.math.BlockPos; public interface IElytraProcess extends IBaritoneProcess { @@ -30,6 +31,8 @@ public interface IElytraProcess extends IBaritoneProcess { void pathTo(BlockPos destination); + void pathTo(Goal destination); + /** * Resets the state of the process but will maintain the same destination and will try to keep flying */ diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index eea7f3f33..7f985ad55 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -59,26 +59,11 @@ public class ElytraCommand extends Command { if (iGoal == null) { throw new CommandInvalidStateException("No goal has been set"); } - final int x; - final int y; - final int z; - if (iGoal instanceof GoalXZ) { - GoalXZ goal = (GoalXZ) iGoal; - x = goal.getX(); - y = 64; - z = goal.getZ(); - } else if (iGoal instanceof GoalBlock) { - GoalBlock goal = (GoalBlock) iGoal; - x = goal.x; - y = goal.y; - z = goal.z; - } else { - throw new CommandInvalidStateException("The goal must be a GoalXZ or GoalBlock"); + try { + elytra.pathTo(iGoal); + } catch (IllegalArgumentException ex) { + throw new CommandInvalidStateException(ex.getMessage()); } - if (y <= 0 || y >= 128) { - throw new CommandInvalidStateException("The y of the goal is not between 0 and 128"); - } - elytra.pathTo(new BlockPos(x, y, z)); return; } diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java index 71d212b38..25c7a3d63 100644 --- a/src/main/java/baritone/process/CustomGoalProcess.java +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -56,6 +56,9 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC public void setGoal(Goal goal) { this.goal = goal; this.mostRecentGoal = goal; + if (baritone.getElytraProcess().isActive()) { + baritone.getElytraProcess().pathTo(goal); + } if (this.state == State.NONE) { this.state = State.GOAL_SET; } diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index c56ab9896..816658593 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -23,6 +23,8 @@ import baritone.api.event.events.*; import baritone.api.event.events.type.EventState; import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalBlock; +import baritone.api.pathing.goals.GoalXZ; import baritone.api.pathing.goals.GoalYLevel; import baritone.api.pathing.movement.IMovement; import baritone.api.pathing.path.IPathExecutor; @@ -48,7 +50,6 @@ import net.minecraft.util.math.Vec3d; import static baritone.api.pathing.movement.ActionCosts.COST_INF; public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { - public State state; private Goal goal; private LegacyElytraBehavior behavior; @@ -93,7 +94,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (ctx.player().isElytraFlying()) { + if (ctx.player().isElytraFlying() && this.state != State.LANDING) { final BetterBlockPos last = behavior.pathManager.path.getLast(); if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { if (Baritone.settings().notificationOnPathComplete.value) { @@ -215,6 +216,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } } + @Override + public double priority() { + return 0; // higher priority than CustomGoalProcess + } + @Override public String displayName0() { return "Elytra - " + this.state.description; @@ -234,6 +240,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { + this.onLostControl(); this.behavior = new LegacyElytraBehavior(this.baritone, this, destination); if (ctx.world() != null) { this.behavior.repackChunks(); @@ -241,6 +248,30 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.behavior.pathTo(); } + @Override + public void pathTo(Goal iGoal) { + final int x; + final int y; + final int z; + if (iGoal instanceof GoalXZ) { + GoalXZ goal = (GoalXZ) iGoal; + x = goal.getX(); + y = 64; + z = goal.getZ(); + } else if (iGoal instanceof GoalBlock) { + GoalBlock goal = (GoalBlock) iGoal; + x = goal.x; + y = goal.y; + z = goal.z; + } else { + throw new IllegalArgumentException("The goal must be a GoalXZ or GoalBlock"); + } + if (y <= 0 || y >= 128) { + throw new IllegalArgumentException("The y of the goal is not between 0 and 128"); + } + this.pathTo(new BlockPos(x, y, z)); + } + @Override public boolean isLoaded() { return true; @@ -253,7 +284,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public enum State { LOCATE_JUMP("Finding spot to jump off"), - VALIDATE_PATH("Validating path"), PAUSE("Waiting for elytra path"), GET_TO_JUMP("Walking to takeoff"), START_FLYING("Begin flying"), diff --git a/src/main/java/baritone/process/elytra/NullElytraProcess.java b/src/main/java/baritone/process/elytra/NullElytraProcess.java index 0c11ba618..cd944cc7c 100644 --- a/src/main/java/baritone/process/elytra/NullElytraProcess.java +++ b/src/main/java/baritone/process/elytra/NullElytraProcess.java @@ -18,6 +18,7 @@ package baritone.process.elytra; import baritone.Baritone; +import baritone.api.pathing.goals.Goal; import baritone.api.process.IElytraProcess; import baritone.api.process.PathingCommand; import baritone.utils.BaritoneProcessHelper; @@ -49,6 +50,11 @@ public final class NullElytraProcess extends BaritoneProcessHelper implements IE throw new UnsupportedOperationException("Called pathTo() on NullElytraBehavior"); } + @Override + public void pathTo(Goal destination) { + throw new UnsupportedOperationException("Called pathTo() on NullElytraBehavior"); + } + @Override public void resetState() { diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index a174c842b..2ae4b00ce 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -27,6 +27,8 @@ import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.behavior.PathingBehavior; import baritone.pathing.path.PathExecutor; +import baritone.process.CustomGoalProcess; +import baritone.process.ElytraProcess; import net.minecraft.util.math.BlockPos; import java.util.*; @@ -109,10 +111,6 @@ public class PathingControlManager implements IPathingControlManager { p.cancelSegmentIfSafe(); break; case FORCE_REVALIDATE_GOAL_AND_PATH: - if (!p.isPathing() && !p.getInProgress().isPresent()) { - p.secretInternalSetGoalAndPath(command); - } - break; case REVALIDATE_GOAL_AND_PATH: if (!p.isPathing() && !p.getInProgress().isPresent()) { p.secretInternalSetGoalAndPath(command); @@ -209,7 +207,13 @@ public class PathingControlManager implements IPathingControlManager { } else if (exec.commandType != PathingCommandType.DEFER) { inControlThisTick = proc; if (!proc.isTemporary()) { - iterator.forEachRemaining(IBaritoneProcess::onLostControl); + iterator.forEachRemaining(it -> { + // TODO: find a better way to make these behave well together + if (proc instanceof CustomGoalProcess && it instanceof ElytraProcess) { + return; + } + it.onLostControl(); + }); } return exec; } From 7f9e50bbe27d6e80da0e7481e854304d0e48e885 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 22 Jul 2023 19:12:53 -0400 Subject: [PATCH 214/276] initial safe landing impl --- .../command/defaults/ElytraCommand.java | 3 - .../java/baritone/process/ElytraProcess.java | 64 ++++++++++++++++++- 2 files changed, 61 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index eea7f3f33..3232ecb03 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -23,11 +23,8 @@ import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; import baritone.api.command.exception.CommandInvalidStateException; import baritone.api.pathing.goals.Goal; -import baritone.api.pathing.goals.GoalBlock; -import baritone.api.pathing.goals.GoalXZ; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.IElytraProcess; -import net.minecraft.util.math.BlockPos; import java.util.Arrays; import java.util.List; diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index c56ab9896..ff082fada 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -42,14 +42,21 @@ import baritone.process.elytra.NullElytraProcess; import baritone.utils.BaritoneProcessHelper; import baritone.utils.PathingCommandContext; import net.minecraft.block.state.IBlockState; +import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import java.util.HashSet; +import java.util.LinkedList; +import java.util.Queue; +import java.util.Set; + import static baritone.api.pathing.movement.ActionCosts.COST_INF; public class ElytraProcess extends BaritoneProcessHelper implements IBaritoneProcess, IElytraProcess, AbstractGameEventListener { public State state; + private boolean goingToLandingSpot; private Goal goal; private LegacyElytraBehavior behavior; @@ -93,8 +100,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (ctx.player().isElytraFlying()) { - final BetterBlockPos last = behavior.pathManager.path.getLast(); + if (ctx.player().isElytraFlying() && this.state != State.LANDING) { + final BetterBlockPos last = this.behavior.pathManager.path.getLast(); if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { if (Baritone.settings().notificationOnPathComplete.value) { logNotification("Pathing complete", false); @@ -105,6 +112,14 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro ctx.world().sendQuittingDisconnectingPacket(); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } + if (!goingToLandingSpot) { + BlockPos landingSpot = findSafeLandingSpot(); + if (landingSpot != null) { + this.pathTo(landingSpot); + this.goingToLandingSpot = true; + return this.onTick(calcFailed, isSafeToCancel); + } + } this.state = State.LANDING; } } @@ -208,6 +223,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void onLostControl() { this.goal = null; + this.goingToLandingSpot = false; this.state = State.START_FLYING; // TODO: null state? if (this.behavior != null) { this.behavior.destroy(); @@ -234,6 +250,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { + this.onLostControl(); this.behavior = new LegacyElytraBehavior(this.baritone, this, destination); if (ctx.world() != null) { this.behavior.repackChunks(); @@ -253,7 +270,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public enum State { LOCATE_JUMP("Finding spot to jump off"), - VALIDATE_PATH("Validating path"), PAUSE("Waiting for elytra path"), GET_TO_JUMP("Walking to takeoff"), START_FLYING("Begin flying"), @@ -329,4 +345,46 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return COST_INF; } } + + private static boolean isInBounds(BlockPos pos) { + return pos.getY() >= 0 && pos.getY() < 128; + } + + private boolean isSafeLandingSpot(BlockPos pos) { + BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); + while (mut.getY() >= 0) { + IBlockState state = ctx.world().getBlockState(mut); + if (state.getMaterial().isLiquid()) { // lava + return false; + } + if (state.getMaterial().blocksMovement() && state.getBlock() != Blocks.MAGMA) { + return true; + } + mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); + } + return false; // void + } + + private BlockPos findSafeLandingSpot() { + final BlockPos start = new BlockPos(ctx.playerFeet()); + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); + queue.add(start); + + while (!queue.isEmpty()) { + BlockPos pos = queue.poll(); + if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { + if (isSafeLandingSpot(pos)) { + return pos; + } + if (visited.add(pos.north())) queue.add(pos.north()); + if (visited.add(pos.east())) queue.add(pos.east()); + if (visited.add(pos.south())) queue.add(pos.south()); + if (visited.add(pos.west())) queue.add(pos.west()); + if (visited.add(pos.up())) queue.add(pos.up()); + if (visited.add(pos.down())) queue.add(pos.down()); + } + } + return null; + } } From c9aa1658b2ae7a8fc5f9cb423ec13da7147ff5c6 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 22 Jul 2023 20:24:36 -0400 Subject: [PATCH 215/276] improvements/fixes --- .../java/baritone/process/ElytraProcess.java | 36 +++++++++++++------ 1 file changed, 26 insertions(+), 10 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index ff082fada..ccab3e2cd 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -57,6 +57,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public State state; private boolean goingToLandingSpot; + private BetterBlockPos landingSpot; private Goal goal; private LegacyElytraBehavior behavior; @@ -102,7 +103,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (ctx.player().isElytraFlying() && this.state != State.LANDING) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); - if (last != null && ctx.player().getDistanceSqToCenter(last) < (5 * 5)) { + if (last != null && ctx.player().getDistanceSqToCenter(last) < 1) { if (Baritone.settings().notificationOnPathComplete.value) { logNotification("Pathing complete", false); } @@ -113,22 +114,25 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } if (!goingToLandingSpot) { - BlockPos landingSpot = findSafeLandingSpot(); + BetterBlockPos landingSpot = findSafeLandingSpot(); if (landingSpot != null) { this.pathTo(landingSpot); + this.landingSpot = landingSpot; this.goingToLandingSpot = true; return this.onTick(calcFailed, isSafeToCancel); } + // don't spam call findLandingSpot if it somehow fails (it's slow) + this.goingToLandingSpot = true; } this.state = State.LANDING; } } if (this.state == State.LANDING) { - final BetterBlockPos endPos = behavior.pathManager.path.getLast(); + final BetterBlockPos endPos = this.landingSpot != null ? this.landingSpot : behavior.pathManager.path.getLast(); if (ctx.player().isElytraFlying() && endPos != null) { Vec3d from = ctx.player().getPositionVector(); - Vec3d to = new Vec3d(endPos.x, from.y, endPos.z); + Vec3d to = new Vec3d(((double) endPos.x) + 0.5, from.y, ((double) endPos.z) + 0.5); Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); baritone.getLookBehavior().updateTarget(rotation, false); } else { @@ -350,6 +354,18 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return pos.getY() >= 0 && pos.getY() < 128; } + private boolean isAtEdge(BlockPos pos) { + return ctx.world().isAirBlock(pos.north()) + || ctx.world().isAirBlock(pos.south()) + || ctx.world().isAirBlock(pos.east()) + || ctx.world().isAirBlock(pos.west()) + // corners + || ctx.world().isAirBlock(pos.north().west()) + || ctx.world().isAirBlock(pos.north().east()) + || ctx.world().isAirBlock(pos.south().west()) + || ctx.world().isAirBlock(pos.south().east()); + } + private boolean isSafeLandingSpot(BlockPos pos) { BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); while (mut.getY() >= 0) { @@ -358,21 +374,21 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return false; } if (state.getMaterial().blocksMovement() && state.getBlock() != Blocks.MAGMA) { - return true; + return !isAtEdge(mut); } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); } return false; // void } - private BlockPos findSafeLandingSpot() { - final BlockPos start = new BlockPos(ctx.playerFeet()); - Queue queue = new LinkedList<>(); - Set visited = new HashSet<>(); + private BetterBlockPos findSafeLandingSpot() { + final BetterBlockPos start = ctx.playerFeet(); + Queue queue = new LinkedList<>(); + Set visited = new HashSet<>(); queue.add(start); while (!queue.isEmpty()) { - BlockPos pos = queue.poll(); + BetterBlockPos pos = queue.poll(); if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { if (isSafeLandingSpot(pos)) { return pos; From 58723a33cabc5f5a0d0aaa7454441d11f3a743b8 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 00:05:11 -0400 Subject: [PATCH 216/276] hate cherry pick now --- src/main/java/baritone/command/defaults/ElytraCommand.java | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 3232ecb03..eea7f3f33 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -23,8 +23,11 @@ import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; import baritone.api.command.exception.CommandInvalidStateException; import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalBlock; +import baritone.api.pathing.goals.GoalXZ; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.IElytraProcess; +import net.minecraft.util.math.BlockPos; import java.util.Arrays; import java.util.List; From 9e784435956010f986f1bc337c0be2ec3549881f Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 00:53:26 -0400 Subject: [PATCH 217/276] resolve comment --- src/main/java/baritone/process/ElytraProcess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index ccab3e2cd..490c7e2e2 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -370,10 +370,10 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); while (mut.getY() >= 0) { IBlockState state = ctx.world().getBlockState(mut); - if (state.getMaterial().isLiquid()) { // lava + if (state.getMaterial().isLiquid() || state.getBlock() != Blocks.MAGMA) { // lava return false; } - if (state.getMaterial().blocksMovement() && state.getBlock() != Blocks.MAGMA) { + if (state.getMaterial().blocksMovement()) { return !isAtEdge(mut); } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); From 985148b49aa7d58c0fce181e1fb16494c987083b Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:00:23 -0400 Subject: [PATCH 218/276] check for specific blocks to land on and anything non air is lava --- src/main/java/baritone/process/ElytraProcess.java | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 490c7e2e2..4b089ec49 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -41,6 +41,8 @@ import baritone.process.elytra.NetherPathfinderContext; import baritone.process.elytra.NullElytraProcess; import baritone.utils.BaritoneProcessHelper; import baritone.utils.PathingCommandContext; +import net.minecraft.block.Block; +import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; @@ -370,12 +372,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); while (mut.getY() >= 0) { IBlockState state = ctx.world().getBlockState(mut); - if (state.getMaterial().isLiquid() || state.getBlock() != Blocks.MAGMA) { // lava + Block block = state.getBlock(); + + if (block == Blocks.NETHERRACK || block == Blocks.GRAVEL || state.getMaterial() == Material.ROCK) { + return true; + } else if (block != Blocks.AIR) { return false; } - if (state.getMaterial().blocksMovement()) { - return !isAtEdge(mut); - } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); } return false; // void From bf63ffbc1dd0d9fe1d02d9667494e8de17cc7802 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:01:59 -0400 Subject: [PATCH 219/276] cringe fence hater :sob: --- src/main/java/baritone/process/ElytraProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 4b089ec49..9fdcdcc75 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -374,7 +374,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro IBlockState state = ctx.world().getBlockState(mut); Block block = state.getBlock(); - if (block == Blocks.NETHERRACK || block == Blocks.GRAVEL || state.getMaterial() == Material.ROCK) { + if (block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK) { return true; } else if (block != Blocks.AIR) { return false; From 9bfa2025d5327aaae0903fedb115ef93fb7e387f Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:14:19 -0400 Subject: [PATCH 220/276] memoize isSafeLandingSPot --- src/main/java/baritone/process/ElytraProcess.java | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 9fdcdcc75..b4ce3623a 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -41,6 +41,7 @@ import baritone.process.elytra.NetherPathfinderContext; import baritone.process.elytra.NullElytraProcess; import baritone.utils.BaritoneProcessHelper; import baritone.utils.PathingCommandContext; +import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.block.Block; import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; @@ -368,9 +369,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro || ctx.world().isAirBlock(pos.south().east()); } - private boolean isSafeLandingSpot(BlockPos pos) { + private boolean isSafeLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) { BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); + checkedSpots.add(mut.toLong()); while (mut.getY() >= 0) { + IBlockState state = ctx.world().getBlockState(mut); Block block = state.getBlock(); @@ -380,6 +383,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return false; } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); + if (checkedSpots.contains(mut.toLong())) { + return false; + } } return false; // void } @@ -388,14 +394,16 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro final BetterBlockPos start = ctx.playerFeet(); Queue queue = new LinkedList<>(); Set visited = new HashSet<>(); + LongOpenHashSet checkedPositions = new LongOpenHashSet(); queue.add(start); while (!queue.isEmpty()) { BetterBlockPos pos = queue.poll(); if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { - if (isSafeLandingSpot(pos)) { + if (isSafeLandingSpot(pos, checkedPositions)) { return pos; } + checkedPositions.add(pos.toLong()); if (visited.add(pos.north())) queue.add(pos.north()); if (visited.add(pos.east())) queue.add(pos.east()); if (visited.add(pos.south())) queue.add(pos.south()); From c0ead0147a9741b10ae869d9e1173cd2485ee3b1 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:38:07 -0400 Subject: [PATCH 221/276] use priority queue to bias upwards --- src/main/java/baritone/process/ElytraProcess.java | 12 +++++------- 1 file changed, 5 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index b4ce3623a..135221967 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -48,11 +48,9 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; +import net.minecraft.util.math.Vec3i; -import java.util.HashSet; -import java.util.LinkedList; -import java.util.Queue; -import java.util.Set; +import java.util.*; import static baritone.api.pathing.movement.ActionCosts.COST_INF; @@ -373,12 +371,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); checkedSpots.add(mut.toLong()); while (mut.getY() >= 0) { - IBlockState state = ctx.world().getBlockState(mut); Block block = state.getBlock(); if (block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK) { - return true; + return !isAtEdge(mut); } else if (block != Blocks.AIR) { return false; } @@ -392,7 +389,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private BetterBlockPos findSafeLandingSpot() { final BetterBlockPos start = ctx.playerFeet(); - Queue queue = new LinkedList<>(); + Queue queue = new PriorityQueue<>(Comparator.comparingInt(Vec3i::getY).reversed()); + //Queue queue = new LinkedList<>(); Set visited = new HashSet<>(); LongOpenHashSet checkedPositions = new LongOpenHashSet(); queue.add(start); From eec85b20be04b0ccd20d3d75656b4ded11625d2e Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:45:39 -0400 Subject: [PATCH 222/276] fix bias in comparator --- src/main/java/baritone/process/ElytraProcess.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 135221967..d0ec7dd6b 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -389,8 +389,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private BetterBlockPos findSafeLandingSpot() { final BetterBlockPos start = ctx.playerFeet(); - Queue queue = new PriorityQueue<>(Comparator.comparingInt(Vec3i::getY).reversed()); - //Queue queue = new LinkedList<>(); + Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x-start.x)*(pos.x-start.x) + (pos.z-start.z)*(pos.z-start.z)).thenComparingInt(pos -> -pos.y)); Set visited = new HashSet<>(); LongOpenHashSet checkedPositions = new LongOpenHashSet(); queue.add(start); From b81d712a33eef0e2a663b11eb17c73b01452c84c Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 01:57:27 -0400 Subject: [PATCH 223/276] higher priority is good enough lol --- src/main/java/baritone/utils/PathingControlManager.java | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index 2ae4b00ce..6123412f7 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -207,13 +207,7 @@ public class PathingControlManager implements IPathingControlManager { } else if (exec.commandType != PathingCommandType.DEFER) { inControlThisTick = proc; if (!proc.isTemporary()) { - iterator.forEachRemaining(it -> { - // TODO: find a better way to make these behave well together - if (proc instanceof CustomGoalProcess && it instanceof ElytraProcess) { - return; - } - it.onLostControl(); - }); + iterator.forEachRemaining(IBaritoneProcess::onLostControl); } return exec; } From 9707dd7ce83526207d592b1620911896cc93e413 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sat, 22 Jul 2023 23:02:29 -0700 Subject: [PATCH 224/276] redo checkedpositions given y descending iteration order --- src/main/java/baritone/process/ElytraProcess.java | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index d0ec7dd6b..873dd5e48 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -43,12 +43,10 @@ import baritone.utils.BaritoneProcessHelper; import baritone.utils.PathingCommandContext; import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.block.Block; -import net.minecraft.block.material.Material; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; -import net.minecraft.util.math.Vec3i; import java.util.*; @@ -369,8 +367,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private boolean isSafeLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) { BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); - checkedSpots.add(mut.toLong()); while (mut.getY() >= 0) { + if (checkedSpots.contains(mut.toLong())) { + return false; + } + checkedSpots.add(mut.toLong()); IBlockState state = ctx.world().getBlockState(mut); Block block = state.getBlock(); @@ -380,16 +381,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return false; } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); - if (checkedSpots.contains(mut.toLong())) { - return false; - } } return false; // void } private BetterBlockPos findSafeLandingSpot() { final BetterBlockPos start = ctx.playerFeet(); - Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x-start.x)*(pos.x-start.x) + (pos.z-start.z)*(pos.z-start.z)).thenComparingInt(pos -> -pos.y)); + Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x - start.x) * (pos.x - start.x) + (pos.z - start.z) * (pos.z - start.z)).thenComparingInt(pos -> -pos.y)); Set visited = new HashSet<>(); LongOpenHashSet checkedPositions = new LongOpenHashSet(); queue.add(start); @@ -400,7 +398,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (isSafeLandingSpot(pos, checkedPositions)) { return pos; } - checkedPositions.add(pos.toLong()); if (visited.add(pos.north())) queue.add(pos.north()); if (visited.add(pos.east())) queue.add(pos.east()); if (visited.add(pos.south())) queue.add(pos.south()); From f7f05210935d202fab13b6b615c444f0595f65fa Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sat, 22 Jul 2023 23:29:07 -0700 Subject: [PATCH 225/276] not legacy --- .../java/baritone/process/ElytraProcess.java | 6 +-- ...lytraBehavior.java => ElytraBehavior.java} | 41 ++++++++++--------- 2 files changed, 24 insertions(+), 23 deletions(-) rename src/main/java/baritone/process/elytra/{LegacyElytraBehavior.java => ElytraBehavior.java} (97%) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 188625508..327018faf 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -38,7 +38,7 @@ import baritone.api.utils.RotationUtils; import baritone.api.utils.input.Input; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.movements.MovementFall; -import baritone.process.elytra.LegacyElytraBehavior; +import baritone.process.elytra.ElytraBehavior; import baritone.process.elytra.NetherPathfinderContext; import baritone.process.elytra.NullElytraProcess; import baritone.utils.BaritoneProcessHelper; @@ -59,7 +59,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private boolean goingToLandingSpot; private BetterBlockPos landingSpot; private Goal goal; - private LegacyElytraBehavior behavior; + private ElytraBehavior behavior; private ElytraProcess(Baritone baritone) { super(baritone); @@ -260,7 +260,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { this.onLostControl(); - this.behavior = new LegacyElytraBehavior(this.baritone, this, destination); + this.behavior = new ElytraBehavior(this.baritone, this, destination); if (ctx.world() != null) { this.behavior.repackChunks(); } diff --git a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java similarity index 97% rename from src/main/java/baritone/process/elytra/LegacyElytraBehavior.java rename to src/main/java/baritone/process/elytra/ElytraBehavior.java index c147442ce..a99b4e331 100644 --- a/src/main/java/baritone/process/elytra/LegacyElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -49,15 +49,16 @@ import net.minecraft.util.math.Vec3d; import net.minecraft.world.chunk.Chunk; import java.awt.*; -import java.util.*; import java.util.List; +import java.util.Queue; +import java.util.*; import java.util.concurrent.*; import java.util.function.UnaryOperator; import static baritone.utils.BaritoneMath.fastCeil; import static baritone.utils.BaritoneMath.fastFloor; -public final class LegacyElytraBehavior implements Helper { +public final class ElytraBehavior implements Helper { private final Baritone baritone; private final IPlayerContext ctx; @@ -109,7 +110,7 @@ public final class LegacyElytraBehavior implements Helper { private int invTickCountdown = 0; private final Queue invTransactionQueue = new LinkedList<>(); - public LegacyElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination) { + public ElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination) { this.baritone = baritone; this.ctx = baritone.getPlayerContext(); this.clearLines = new CopyOnWriteArrayList<>(); @@ -162,7 +163,7 @@ public final class LegacyElytraBehavior implements Helper { public CompletableFuture pathToDestination(final BlockPos from) { final long start = System.nanoTime(); - return this.path0(from, LegacyElytraBehavior.this.destination, UnaryOperator.identity()) + return this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity()) .thenRun(() -> { final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1)); if (this.completePath) { @@ -216,7 +217,7 @@ public final class LegacyElytraBehavior implements Helper { final List before = this.path.subList(0, afterIncl + 1); final long start = System.nanoTime(); - this.path0(this.path.get(afterIncl), LegacyElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) + this.path0(this.path.get(afterIncl), ElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; final double distance = this.path.get(0).distanceTo(this.path.get(recompute)); @@ -267,7 +268,7 @@ public final class LegacyElytraBehavior implements Helper { // mickey resigned private CompletableFuture path0(BlockPos src, BlockPos dst, UnaryOperator operator) { - return LegacyElytraBehavior.this.context.pathFindAsync(src, dst) + return ElytraBehavior.this.context.pathFindAsync(src, dst) .thenApply(UnpackedSegment::from) .thenApply(operator) .thenAcceptAsync(this::setPath, ctx.minecraft()::addScheduledTask); @@ -289,12 +290,12 @@ public final class LegacyElytraBehavior implements Helper { return; } final BetterBlockPos rangeStart = path.get(rangeStartIncl); - if (!LegacyElytraBehavior.this.passable(rangeStart.x, rangeStart.y, rangeStart.z, false)) { + if (!ElytraBehavior.this.passable(rangeStart.x, rangeStart.y, rangeStart.z, false)) { // we're in a wall return; // previous iterations of this function SHOULD have fixed this by now :rage_cat: } - if (LegacyElytraBehavior.this.process.state != ElytraProcess.State.LANDING && this.ticksNearUnchanged > 100) { + if (ElytraBehavior.this.process.state != ElytraProcess.State.LANDING && this.ticksNearUnchanged > 100) { this.pathRecalcSegment(rangeEndExcl - 1) .thenRun(() -> { logDirect("Recalculating segment, no progress in last 100 ticks"); @@ -304,7 +305,7 @@ public final class LegacyElytraBehavior implements Helper { } for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (!LegacyElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { + if (!ElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment final BetterBlockPos blockage = this.path.get(i); @@ -677,8 +678,8 @@ public final class LegacyElytraBehavior implements Helper { ) { // Prioritize boosting fireworks over regular ones // TODO: Take the minimum boost time into account? - if (!baritone.getInventoryBehavior().throwaway(true, LegacyElytraBehavior::isBoostingFireworks) && - !baritone.getInventoryBehavior().throwaway(true, LegacyElytraBehavior::isFireworks)) { + if (!baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isBoostingFireworks) && + !baritone.getInventoryBehavior().throwaway(true, ElytraBehavior::isFireworks)) { logDirect("no fireworks"); return; } @@ -700,21 +701,21 @@ public final class LegacyElytraBehavior implements Helper { public final IAimProcessor aimProcessor; public SolverContext(boolean async) { - this.path = LegacyElytraBehavior.this.pathManager.getPath(); - this.playerNear = LegacyElytraBehavior.this.pathManager.getNear(); - this.start = LegacyElytraBehavior.this.ctx.playerFeetAsVec(); - this.ignoreLava = LegacyElytraBehavior.this.ctx.player().isInLava(); + this.path = ElytraBehavior.this.pathManager.getPath(); + this.playerNear = ElytraBehavior.this.pathManager.getNear(); + this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); + this.ignoreLava = ElytraBehavior.this.ctx.player().isInLava(); final Integer fireworkTicksExisted; - if (async && LegacyElytraBehavior.this.deployedFireworkLastTick) { - final int[] counter = LegacyElytraBehavior.this.nextTickBoostCounter; + if (async && ElytraBehavior.this.deployedFireworkLastTick) { + final int[] counter = ElytraBehavior.this.nextTickBoostCounter; fireworkTicksExisted = counter[1] > counter[0] ? 0 : null; } else { - fireworkTicksExisted = LegacyElytraBehavior.this.getAttachedFirework().map(e -> e.ticksExisted).orElse(null); + fireworkTicksExisted = ElytraBehavior.this.getAttachedFirework().map(e -> e.ticksExisted).orElse(null); } - this.boost = new FireworkBoost(fireworkTicksExisted, LegacyElytraBehavior.this.minimumBoostTicks); + this.boost = new FireworkBoost(fireworkTicksExisted, ElytraBehavior.this.minimumBoostTicks); - ITickableAimProcessor aim = LegacyElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); + ITickableAimProcessor aim = ElytraBehavior.this.baritone.getLookBehavior().getAimProcessor().fork(); if (async) { // async computation is done at the end of a tick, advance by 1 to prepare for the next tick aim.advance(1); From 75e8035551fcce2c1e0076f767f9aa3fc086681d Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 14:26:31 -0400 Subject: [PATCH 226/276] safe landing improvements --- .../java/baritone/process/ElytraProcess.java | 62 +++++++++++++------ 1 file changed, 42 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 327018faf..be385a853 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -383,36 +383,57 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return pos.getY() >= 0 && pos.getY() < 128; } - private boolean isAtEdge(BlockPos pos) { - return ctx.world().isAirBlock(pos.north()) - || ctx.world().isAirBlock(pos.south()) - || ctx.world().isAirBlock(pos.east()) - || ctx.world().isAirBlock(pos.west()) - // corners - || ctx.world().isAirBlock(pos.north().west()) - || ctx.world().isAirBlock(pos.north().east()) - || ctx.world().isAirBlock(pos.south().west()) - || ctx.world().isAirBlock(pos.south().east()); + private boolean isSafeBlock(Block block) { + return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK; + } + private boolean isSafeBlock(BlockPos pos) { + return isSafeBlock(ctx.world().getBlockState(pos).getBlock()); } - private boolean isSafeLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) { + private boolean isAtEdge(BlockPos pos) { + return !isSafeBlock(pos.north()) + || !isSafeBlock(pos.south()) + || !isSafeBlock(pos.east()) + || !isSafeBlock(pos.west()) + // corners + || !isSafeBlock(pos.north().west()) + || !isSafeBlock(pos.north().east()) + || !isSafeBlock(pos.south().west()) + || !isSafeBlock(pos.south().east()); + } + + private boolean isColumnAir(BlockPos landingSpot, int minHeight) { + BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(landingSpot); + final int maxY = mut.getY() + minHeight; + for (int y = mut.getY() + 1; y <= maxY; y++) { + mut.setPos(mut.getX(), y, mut.getZ()); + if (!ctx.world().isAirBlock(mut)) { + return false; + } + } + return true; + } + + private BetterBlockPos checkLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) { BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); while (mut.getY() >= 0) { if (checkedSpots.contains(mut.toLong())) { - return false; + return null; } checkedSpots.add(mut.toLong()); - IBlockState state = ctx.world().getBlockState(mut); - Block block = state.getBlock(); + Block block = ctx.world().getBlockState(mut).getBlock(); - if (block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK) { - return !isAtEdge(mut); + if (isSafeBlock(block)) { + if (!isAtEdge(mut)) { + return new BetterBlockPos(mut); + } + return null; } else if (block != Blocks.AIR) { - return false; + return null; } mut.setPos(mut.getX(), mut.getY() - 1, mut.getZ()); } - return false; // void + return null; // void } private BetterBlockPos findSafeLandingSpot() { @@ -425,8 +446,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro while (!queue.isEmpty()) { BetterBlockPos pos = queue.poll(); if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { - if (isSafeLandingSpot(pos, checkedPositions)) { - return pos; + BetterBlockPos actualLandingSpot = checkLandingSpot(pos, checkedPositions); + if (actualLandingSpot != null && isColumnAir(actualLandingSpot, 15)) { + return actualLandingSpot.up(15); } if (visited.add(pos.north())) queue.add(pos.north()); if (visited.add(pos.east())) queue.add(pos.east()); From 212ef4d4cc8d3d52d07d9dc20e33f585a657144c Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 23 Jul 2023 11:44:29 -0700 Subject: [PATCH 227/276] waste fireworks smiling_imp --- src/api/java/baritone/api/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 3ab2a068b..d664b569c 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1377,7 +1377,7 @@ public final class Settings { /** * If enabled, avoids using fireworks when descending along the flight path. */ - public final Setting elytraConserveFireworks = new Setting<>(true); + public final Setting elytraConserveFireworks = new Setting<>(false); /** * Renders the raytraces that are performed by the elytra fly calculation. From e63aad782518667b180dde3c7bb404ca8fb45903 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 15:09:56 -0400 Subject: [PATCH 228/276] elytra command improvements --- .../command/defaults/ElytraCommand.java | 44 +++++++++++++------ 1 file changed, 31 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 7f985ad55..f7aaebc81 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -22,12 +22,10 @@ import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; import baritone.api.command.exception.CommandException; import baritone.api.command.exception.CommandInvalidStateException; +import baritone.api.command.helpers.TabCompleteHelper; import baritone.api.pathing.goals.Goal; -import baritone.api.pathing.goals.GoalBlock; -import baritone.api.pathing.goals.GoalXZ; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.IElytraProcess; -import net.minecraft.util.math.BlockPos; import java.util.Arrays; import java.util.List; @@ -43,15 +41,12 @@ public class ElytraCommand extends Command { public void execute(String label, IArgConsumer args) throws CommandException { final ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); final IElytraProcess elytra = baritone.getElytraProcess(); + if (args.hasExactlyOne() && args.peekString().equals("supported")) { + logDirect(elytra.isLoaded() ? "yes" : unsupportedSystemMessage()); + return; + } if (!elytra.isLoaded()) { - final String osArch = System.getProperty("os.arch"); - final String osName = System.getProperty("os.name"); - throw new CommandInvalidStateException(String.format( - "legacy architectures are not supported. your CPU is %s and your operating system is %s. " + - "supported architectures are x86_64 or arm64, supported operating systems are windows, " + - "linux, and mac", - osArch, osName - )); + throw new CommandInvalidStateException(unsupportedSystemMessage()); } if (!args.hasAny()) { @@ -87,7 +82,11 @@ public class ElytraCommand extends Command { @Override public Stream tabComplete(String label, IArgConsumer args) throws CommandException { - return Stream.empty(); + TabCompleteHelper helper = new TabCompleteHelper(); + if (args.hasExactlyOne()) { + helper.append("reset", "repack", "supported"); + } + return helper.filterPrefix(args.getString()).stream(); } @Override @@ -97,6 +96,25 @@ public class ElytraCommand extends Command { @Override public List getLongDesc() { - return Arrays.asList(); + return Arrays.asList( + "The elytra command tells baritone to, in the nether, automatically fly to the current goal.", + "", + "Usage:", + "> elytra - fly to the current goal", + "> elytra reset - Resets the state of the process, but will try to keep flying to the same goal.", + "> elytra repack - Queues all of the chunks in render distance to be given to the native library.", + "> elytra supported - Tells you if baritone ships a native library that is compatible with your PC." + ); + } + + private static String unsupportedSystemMessage() { + final String osArch = System.getProperty("os.arch"); + final String osName = System.getProperty("os.name"); + return String.format( + "Legacy architectures are not supported. your CPU is %s and your operating system is %s. " + + "Supported architectures are 64 bit x86, and 64 bit arm, supported operating systems are Windows, " + + "Linux, and Mac", + osArch, osName + ); } } From 293b556b56e95ea73824b7b65a93091ec4deb9f4 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 23 Jul 2023 20:46:12 -0400 Subject: [PATCH 229/276] add dimension checks --- src/main/java/baritone/command/defaults/ElytraCommand.java | 3 +++ src/main/java/baritone/process/ElytraProcess.java | 3 +++ 2 files changed, 6 insertions(+) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index f7aaebc81..6ba08dba9 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -54,6 +54,9 @@ public class ElytraCommand extends Command { if (iGoal == null) { throw new CommandInvalidStateException("No goal has been set"); } + if (ctx.player().dimension != -1) { + throw new CommandInvalidStateException("Only works in the nether"); + } try { elytra.pathTo(iGoal); } catch (IllegalArgumentException ex) { diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index be385a853..754587a47 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -259,6 +259,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { + if (ctx.player() == null || ctx.player().dimension != -1) { + return; + } this.onLostControl(); this.behavior = new ElytraBehavior(this.baritone, this, destination); if (ctx.world() != null) { From 45400a968562a6f6d880f7c2de97cfcc1f1ab8f6 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 24 Jul 2023 03:30:06 -0400 Subject: [PATCH 230/276] fix concurrency concerns --- .../elytra/BlockStateOctreeInterface.java | 11 ++++------- .../baritone/process/elytra/ElytraBehavior.java | 17 +++++++++++------ .../process/elytra/NetherPathfinderContext.java | 7 ++++--- 3 files changed, 19 insertions(+), 16 deletions(-) diff --git a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java index f9e700085..efbfb9216 100644 --- a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java @@ -27,7 +27,7 @@ public final class BlockStateOctreeInterface { private final NetherPathfinderContext context; private final long contextPtr; - volatile long chunkPtr; + transient long chunkPtr; // Guarantee that the first lookup will fetch the context by setting MAX_VALUE private int prevChunkX = Integer.MAX_VALUE; @@ -44,14 +44,11 @@ public final class BlockStateOctreeInterface { } final int chunkX = x >> 4; final int chunkZ = z >> 4; - long pointer = this.chunkPtr; - if (pointer == 0 | ((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { + if (this.chunkPtr == 0 | ((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) { this.prevChunkX = chunkX; this.prevChunkZ = chunkZ; - synchronized (this.context.cacheLock) { - this.chunkPtr = pointer = NetherPathfinder.getOrCreateChunk(this.contextPtr, chunkX, chunkZ); - } + this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.contextPtr, chunkX, chunkZ); } - return Octree.getBlock(pointer, x & 0xF, y & 0x7F, z & 0xF); + return Octree.getBlock(this.chunkPtr, x & 0xF, y & 0x7F, z & 0xF); } } diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index a99b4e331..0e6b7ad2a 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -446,6 +446,17 @@ public final class ElytraBehavior implements Helper { } public void onTick() { + synchronized (this.context.cullingLock) { + this.onTick0(); + } + final long now = System.currentTimeMillis(); + if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { + this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); + this.timeLastCacheCull = now; + } + } + + private void onTick0() { // Fetch the previous solution, regardless of if it's going to be used this.pendingSolution = null; if (this.solver != null) { @@ -498,12 +509,6 @@ public final class ElytraBehavior implements Helper { Math.max(playerNear - 30, 0), Math.min(playerNear + 100, path.size()) ); - - final long now = System.currentTimeMillis(); - if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) { - this.context.queueCacheCulling(ctx.player().chunkCoordX, ctx.player().chunkCoordZ, Baritone.settings().elytraCacheCullDistance.value, this.boi); - this.timeLastCacheCull = now; - } } /** diff --git a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java index 69ac41992..991457d10 100644 --- a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java @@ -38,7 +38,6 @@ import java.util.concurrent.CompletableFuture; import java.util.concurrent.ExecutorService; import java.util.concurrent.Executors; import java.util.concurrent.TimeUnit; -import java.util.concurrent.atomic.AtomicInteger; /** * @author Brady @@ -46,7 +45,9 @@ import java.util.concurrent.atomic.AtomicInteger; public final class NetherPathfinderContext { private static final IBlockState AIR_BLOCK_STATE = Blocks.AIR.getDefaultState(); - public final Object cacheLock = new Object(); + // This lock must be held while there are active pointers to chunks in java, + // but we just hold it for the entire tick so we don't have to think much about it. + public final Object cullingLock = new Object(); // Visible for access in BlockStateOctreeInterface final long context; @@ -61,7 +62,7 @@ public final class NetherPathfinderContext { public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) { this.executor.execute(() -> { - synchronized (this.cacheLock) { + synchronized (this.cullingLock) { boi.chunkPtr = 0L; NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks); } From 1e0dce8f416db615c2f76f20c1d5419f576a4a91 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 24 Jul 2023 03:30:38 -0400 Subject: [PATCH 231/276] 127 instead of 128 --- .../java/baritone/process/elytra/BlockStateOctreeInterface.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java index efbfb9216..7db0e2d64 100644 --- a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java +++ b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java @@ -39,7 +39,7 @@ public final class BlockStateOctreeInterface { } public boolean get0(final int x, final int y, final int z) { - if ((y | (128 - y)) < 0) { + if ((y | (127 - y)) < 0) { return false; } final int chunkX = x >> 4; From f14bb282f049d7ad723c6ebcb3c5e61fec12a9c6 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 24 Jul 2023 04:41:19 -0400 Subject: [PATCH 232/276] add null check to resetState --- src/main/java/baritone/process/ElytraProcess.java | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 754587a47..1ab9f74f5 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -81,8 +81,10 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public void resetState() { BlockPos destination = this.currentDestination(); this.onLostControl(); - this.pathTo(destination); - this.repackChunks(); + if (destination != null) { + this.pathTo(destination); + this.repackChunks(); + } } @Override From 601a781983ba3157fec32c29c3817e787530c340 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 24 Jul 2023 08:21:46 -0400 Subject: [PATCH 233/276] improve control flow (fixes behavior.onTick() being called twice) --- .../java/baritone/process/ElytraProcess.java | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 1ab9f74f5..126621ed9 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -58,6 +58,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public State state; private boolean goingToLandingSpot; private BetterBlockPos landingSpot; + private boolean reachedGoal; // this basically just prevents potential notification spam private Goal goal; private ElytraBehavior behavior; @@ -106,27 +107,29 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (ctx.player().isElytraFlying() && this.state != State.LANDING) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); if (last != null && ctx.player().getDistanceSqToCenter(last) < 1) { - if (Baritone.settings().notificationOnPathComplete.value) { + if (Baritone.settings().notificationOnPathComplete.value && !reachedGoal) { logNotification("Pathing complete", false); } - if (Baritone.settings().disconnectOnArrival.value) { + if (Baritone.settings().disconnectOnArrival.value && !reachedGoal) { // don't be active when the user logs back in this.onLostControl(); ctx.world().sendQuittingDisconnectingPacket(); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } + reachedGoal = true; + if (!goingToLandingSpot) { BetterBlockPos landingSpot = findSafeLandingSpot(); + // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes if (landingSpot != null) { this.pathTo(landingSpot); this.landingSpot = landingSpot; this.goingToLandingSpot = true; - return this.onTick(calcFailed, isSafeToCancel); } - // don't spam call findLandingSpot if it somehow fails (it's slow) - this.goingToLandingSpot = true; + } else { + // we are goingToLandingSpot and we are in the in the last node of the path + this.state = State.LANDING; } - this.state = State.LANDING; } } @@ -230,6 +233,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public void onLostControl() { this.goal = null; this.goingToLandingSpot = false; + this.reachedGoal = false; this.state = State.START_FLYING; // TODO: null state? if (this.behavior != null) { this.behavior.destroy(); From 90f2b39fba61b2adcb7741f4c4711374a596e30e Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 26 Jul 2023 19:52:25 -0500 Subject: [PATCH 234/276] Remove glPushAttrib/glPopAttrib usage --- src/main/java/baritone/utils/IRenderer.java | 2 ++ src/main/java/baritone/utils/PathRenderer.java | 6 ------ 2 files changed, 2 insertions(+), 6 deletions(-) diff --git a/src/main/java/baritone/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java index 680d7e380..6ccc0847c 100644 --- a/src/main/java/baritone/utils/IRenderer.java +++ b/src/main/java/baritone/utils/IRenderer.java @@ -57,6 +57,7 @@ public interface IRenderer { GlStateManager.glLineWidth(lineWidth); GlStateManager.disableTexture2D(); GlStateManager.depthMask(false); + GlStateManager.disableLighting(); if (ignoreDepth) { GlStateManager.disableDepth(); @@ -77,6 +78,7 @@ public interface IRenderer { GlStateManager.depthMask(true); GlStateManager.enableTexture2D(); GlStateManager.disableBlend(); + GlStateManager.enableLighting(); } static void emitAABB(AxisAlignedBB aabb) { diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index b3abc8cd2..93f916f1d 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -41,8 +41,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import static org.lwjgl.opengl.GL11.*; - /** * @author Brady * @since 8/9/2018 @@ -239,8 +237,6 @@ public final class PathRenderer implements IRenderer { GoalXZ goalPos = (GoalXZ) goal; if (settings.renderGoalXZBeacon.value) { - glPushAttrib(GL_LIGHTING_BIT); - textureManager.bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM); if (settings.renderGoalIgnoreDepth.value) { @@ -262,8 +258,6 @@ public final class PathRenderer implements IRenderer { if (settings.renderGoalIgnoreDepth.value) { GlStateManager.enableDepth(); } - - glPopAttrib(); return; } From 6b611cf4c7e0be9a7e19aeeb0c635a0175dd65d9 Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 28 Jul 2023 01:30:54 -0500 Subject: [PATCH 235/276] Move more state into `SolverContext` --- .../process/elytra/ElytraBehavior.java | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 0e6b7ad2a..f5a32c5f2 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -701,15 +701,26 @@ public final class ElytraBehavior implements Helper { public final NetherPath path; public final int playerNear; public final Vec3d start; + public final Vec3d motion; + public final AxisAlignedBB boundingBox; public final boolean ignoreLava; public final FireworkBoost boost; public final IAimProcessor aimProcessor; + /** + * Creates a new SolverContext using the current state of the path, player, and firework boost at the time of + * construction. + * + * @param async Whether the computation is being done asynchronously at the end of a game tick. + */ public SolverContext(boolean async) { this.path = ElytraBehavior.this.pathManager.getPath(); this.playerNear = ElytraBehavior.this.pathManager.getNear(); - this.start = ElytraBehavior.this.ctx.playerFeetAsVec(); - this.ignoreLava = ElytraBehavior.this.ctx.player().isInLava(); + + this.start = ctx.playerFeetAsVec(); + this.motion = ctx.playerMotion(); + this.boundingBox = ctx.player().getEntityBoundingBox(); + this.ignoreLava = ctx.player().isInLava(); final Integer fireworkTicksExisted; if (async && ElytraBehavior.this.deployedFireworkLastTick) { @@ -741,6 +752,8 @@ public final class ElytraBehavior implements Helper { return this.path == other.path // Contents aren't modified, just compare by reference && this.playerNear == other.playerNear && Objects.equals(this.start, other.start) + && Objects.equals(this.motion, other.motion) + && Objects.equals(this.boundingBox, other.boundingBox) && this.ignoreLava == other.ignoreLava && Objects.equals(this.boost, other.boost); } @@ -752,6 +765,11 @@ public final class ElytraBehavior implements Helper { private final int minimumBoostTicks; private final int maximumBoostTicks; + /** + * @param fireworkTicksExisted The ticksExisted of the attached firework entity, or {@code null} if no entity. + * @param minimumBoostTicks The minimum number of boost ticks that the attached firework entity, if any, will + * provide. + */ public FireworkBoost(final Integer fireworkTicksExisted, final int minimumBoostTicks) { this.fireworkTicksExisted = fireworkTicksExisted; @@ -870,7 +888,7 @@ public final class ElytraBehavior implements Helper { return true; } - final AxisAlignedBB bb = ctx.player().getEntityBoundingBox().grow(growAmount); + final AxisAlignedBB bb = context.boundingBox.grow(growAmount); final double ox = dest.x - start.x; final double oy = dest.y - start.y; @@ -1032,13 +1050,12 @@ public final class ElytraBehavior implements Helper { while (pitches.hasNext()) { final float pitch = pitches.nextFloat(); final List displacement = this.simulate( - context.aimProcessor.fork(), + context, goalDelta, pitch, ticks, ticksBoosted, - ticksBoostDelay, - context.ignoreLava + ticksBoostDelay ); if (displacement == null) { continue; @@ -1074,11 +1091,12 @@ public final class ElytraBehavior implements Helper { return null; } - private List simulate(final ITickableAimProcessor aimProcessor, final Vec3d goalDelta, final float pitch, - final int ticks, final int ticksBoosted, final int ticksBoostDelay, final boolean ignoreLava) { + private List simulate(final SolverContext context, final Vec3d goalDelta, final float pitch, final int ticks, + final int ticksBoosted, final int ticksBoostDelay) { + final ITickableAimProcessor aimProcessor = context.aimProcessor.fork(); Vec3d delta = goalDelta; - Vec3d motion = ctx.playerMotion(); - AxisAlignedBB hitbox = ctx.player().getEntityBoundingBox(); + Vec3d motion = context.motion; + AxisAlignedBB hitbox = context.boundingBox; List displacement = new ArrayList<>(ticks + 1); displacement.add(Vec3d.ZERO); int remainingTicksBoosted = ticksBoosted; @@ -1112,7 +1130,7 @@ public final class ElytraBehavior implements Helper { for (int x = xmin; x < xmax; x++) { for (int y = ymin; y < ymax; y++) { for (int z = zmin; z < zmax; z++) { - if (!this.passable(x, y, z, ignoreLava)) { + if (!this.passable(x, y, z, context.ignoreLava)) { return null; } } From 4b5a094f308f3a06a63a2f3dd28d5bb4ca9de3dd Mon Sep 17 00:00:00 2001 From: Brady Date: Fri, 28 Jul 2023 01:41:03 -0500 Subject: [PATCH 236/276] Render fields can be private now --- .../baritone/process/elytra/ElytraBehavior.java | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index f5a32c5f2..c0cd07c87 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -62,13 +62,12 @@ public final class ElytraBehavior implements Helper { private final Baritone baritone; private final IPlayerContext ctx; - - // Used exclusively for PathRenderer - public List> clearLines; - public List> blockedLines; - public List simulationLine; - public BlockPos aimPos; - public List visiblePath; + // Render stuff + private final List> clearLines; + private final List> blockedLines; + private List simulationLine; + private BlockPos aimPos; + private List visiblePath; // :sunglasses: public final NetherPathfinderContext context; From 31d1656c48633528afa511bad9bb683d58336884 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 29 Jul 2023 00:22:52 -0400 Subject: [PATCH 237/276] safer landing --- .../java/baritone/process/ElytraProcess.java | 48 +++++++++++++------ .../process/elytra/ElytraBehavior.java | 4 ++ 2 files changed, 38 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 126621ed9..ff374aad1 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -104,8 +104,18 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (ctx.player().isElytraFlying() && this.state != State.LANDING) { + if (ctx.player().isElytraFlying() && this.state != State.LANDING && this.behavior.pathManager.isComplete()) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); + if (last != null && ctx.player().getDistanceSqToCenter(last) < (48 * 48) && !goingToLandingSpot) { + BetterBlockPos landingSpot = findSafeLandingSpot(last); + // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes + if (landingSpot != null) { + this.pathTo(landingSpot); + this.landingSpot = landingSpot; + this.goingToLandingSpot = true; + } + } + if (last != null && ctx.player().getDistanceSqToCenter(last) < 1) { if (Baritone.settings().notificationOnPathComplete.value && !reachedGoal) { logNotification("Pathing complete", false); @@ -118,16 +128,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } reachedGoal = true; - if (!goingToLandingSpot) { - BetterBlockPos landingSpot = findSafeLandingSpot(); - // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes - if (landingSpot != null) { - this.pathTo(landingSpot); - this.landingSpot = landingSpot; - this.goingToLandingSpot = true; - } - } else { - // we are goingToLandingSpot and we are in the in the last node of the path + // we are goingToLandingSpot and we are in the last node of the path + if (this.goingToLandingSpot) { this.state = State.LANDING; } } @@ -423,6 +425,25 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return true; } + private boolean hasAirBubble(BlockPos pos) { + final int radius = 2; // Half of 5, as we're counting blocks in each direction from the center + + for (int x = -radius; x <= radius; x++) { + for (int y = -radius; y <= radius; y++) { + for (int z = -radius; z <= radius; z++) { + BlockPos currentPos = pos.add(x, y, z); + IBlockState blockState = ctx.world().getBlockState(currentPos); + + if (blockState.getBlock() != Blocks.AIR) { + return false; + } + } + } + } + + return true; + } + private BetterBlockPos checkLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) { BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos); while (mut.getY() >= 0) { @@ -445,8 +466,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return null; // void } - private BetterBlockPos findSafeLandingSpot() { - final BetterBlockPos start = ctx.playerFeet(); + private BetterBlockPos findSafeLandingSpot(BetterBlockPos start) { Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x - start.x) * (pos.x - start.x) + (pos.z - start.z) * (pos.z - start.z)).thenComparingInt(pos -> -pos.y)); Set visited = new HashSet<>(); LongOpenHashSet checkedPositions = new LongOpenHashSet(); @@ -456,7 +476,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BetterBlockPos pos = queue.poll(); if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { BetterBlockPos actualLandingSpot = checkLandingSpot(pos, checkedPositions); - if (actualLandingSpot != null && isColumnAir(actualLandingSpot, 15)) { + if (actualLandingSpot != null && isColumnAir(actualLandingSpot, 15) && hasAirBubble(actualLandingSpot.up(15))) { return actualLandingSpot.up(15); } if (visited.add(pos.north())) queue.add(pos.north()); diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index c0cd07c87..9311b296c 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -366,6 +366,10 @@ public final class ElytraBehavior implements Helper { } this.playerNear = index; } + + public boolean isComplete() { + return this.completePath; + } } public void onRenderPass(RenderEvent event) { From 2e2c0ecc0b895c68c92be21ce2bf1b36df494576 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sat, 29 Jul 2023 11:52:37 -0400 Subject: [PATCH 238/276] use MutableBlockPos --- src/main/java/baritone/process/ElytraProcess.java | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index ff374aad1..ca6988b20 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -427,14 +427,12 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private boolean hasAirBubble(BlockPos pos) { final int radius = 2; // Half of 5, as we're counting blocks in each direction from the center - + BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(); for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { for (int z = -radius; z <= radius; z++) { - BlockPos currentPos = pos.add(x, y, z); - IBlockState blockState = ctx.world().getBlockState(currentPos); - - if (blockState.getBlock() != Blocks.AIR) { + mut.setPos(pos.getX() + x, pos.getY() + y, pos.getZ() + z); + if (!ctx.world().isAirBlock(mut)) { return false; } } From d6adb52718e741e12eb658007dbc8da26835e10b Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 15:46:18 -0700 Subject: [PATCH 239/276] tweaks --- .../java/baritone/process/ElytraProcess.java | 47 ++++++++++++------- .../process/elytra/ElytraBehavior.java | 7 ++- 2 files changed, 37 insertions(+), 17 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index ca6988b20..f5329d8d1 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -88,6 +88,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } } + private static final String AUTO_JUMP_FAILURE_MSG = "Failed to compute a walking path to a spot to jump off from. Consider starting from a higher location, near an overhang. Or, you can disable elytraAutoJump and just manually begin gliding."; + @Override public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { final long seedSetting = Baritone.settings().elytraNetherSeed.value; @@ -100,13 +102,14 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (calcFailed) { onLostControl(); - logDirect("Failed to get to jump off spot, canceling"); + logDirect(AUTO_JUMP_FAILURE_MSG); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } if (ctx.player().isElytraFlying() && this.state != State.LANDING && this.behavior.pathManager.isComplete()) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); if (last != null && ctx.player().getDistanceSqToCenter(last) < (48 * 48) && !goingToLandingSpot) { + logDirect("Path complete, picking a nearby safe landing spot..."); BetterBlockPos landingSpot = findSafeLandingSpot(last); // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes if (landingSpot != null) { @@ -131,6 +134,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro // we are goingToLandingSpot and we are in the last node of the path if (this.goingToLandingSpot) { this.state = State.LANDING; + logDirect("Above the landing spot, landing..."); } } } @@ -141,17 +145,30 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro Vec3d from = ctx.player().getPositionVector(); Vec3d to = new Vec3d(((double) endPos.x) + 0.5, from.y, ((double) endPos.z) + 0.5); Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations()); - baritone.getLookBehavior().updateTarget(rotation, false); - } else { - this.onLostControl(); - return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + baritone.getLookBehavior().updateTarget(new Rotation(rotation.getYaw(), 0), false); // this will be overwritten, probably, by behavior tick + + if (ctx.player().posY < endPos.y - LANDING_COLUMN_HEIGHT) { + logDirect("bad landing spot, trying again..."); + badLandingSpots.add(endPos); + } } - } else if (ctx.player().isElytraFlying()) { - this.state = State.FLYING; + } + + if (ctx.player().isElytraFlying()) { + behavior.landingMode = this.state == State.LANDING; this.goal = null; baritone.getInputOverrideHandler().clearAllKeys(); behavior.tick(); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } else if (this.state == State.LANDING) { + if (Math.sqrt(ctx.player().motionX * ctx.player().motionX + ctx.player().motionZ * ctx.player().motionZ) > 0.001) { + logDirect("Landed, but still moving, waiting for velocity to die down... " + ctx.player().motionX + " " + ctx.player().motionZ); + baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true); + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); + } + baritone.getInputOverrideHandler().clearAllKeys(); + this.onLostControl(); + return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } if (this.state == State.FLYING || this.state == State.START_FLYING) { @@ -177,12 +194,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro (fall.getSrc().z + fall.getDest().z) / 2 ); behavior.pathManager.pathToDestination(from).whenComplete((result, ex) -> { - if (!behavior.clearView(new Vec3d(from), behavior.pathManager.getPath().getVec(0), false)) { - onLostControl(); - // TODO: Get to higher ground and then look again - logDirect("Can't see start of path from jump spot, canceling"); - return; - } if (ex == null) { this.state = State.GET_TO_JUMP; return; @@ -192,7 +203,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.state = State.PAUSE; } else { onLostControl(); - logDirect("Jump off path didn't include a fall movement, canceling"); + logDirect(AUTO_JUMP_FAILURE_MSG); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } } @@ -397,6 +408,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private boolean isSafeBlock(Block block) { return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK; } + private boolean isSafeBlock(BlockPos pos) { return isSafeBlock(ctx.world().getBlockState(pos).getBlock()); } @@ -464,6 +476,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return null; // void } + private static final int LANDING_COLUMN_HEIGHT = 15; + private Set badLandingSpots = new HashSet<>(); + private BetterBlockPos findSafeLandingSpot(BetterBlockPos start) { Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x - start.x) * (pos.x - start.x) + (pos.z - start.z) * (pos.z - start.z)).thenComparingInt(pos -> -pos.y)); Set visited = new HashSet<>(); @@ -474,8 +489,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BetterBlockPos pos = queue.poll(); if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { BetterBlockPos actualLandingSpot = checkLandingSpot(pos, checkedPositions); - if (actualLandingSpot != null && isColumnAir(actualLandingSpot, 15) && hasAirBubble(actualLandingSpot.up(15))) { - return actualLandingSpot.up(15); + if (actualLandingSpot != null && isColumnAir(actualLandingSpot, LANDING_COLUMN_HEIGHT) && hasAirBubble(actualLandingSpot.up(LANDING_COLUMN_HEIGHT)) && !badLandingSpots.contains(actualLandingSpot.up(LANDING_COLUMN_HEIGHT))) { + return actualLandingSpot.up(LANDING_COLUMN_HEIGHT); } if (visited.add(pos.north())) queue.add(pos.north()); if (visited.add(pos.east())) queue.add(pos.east()); diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 9311b296c..39af6fc38 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -84,6 +84,8 @@ public final class ElytraBehavior implements Helper { */ private int remainingSetBackTicks; + public boolean landingMode; + /** * The most recent minimum number of firework boost ticks, equivalent to {@code 10 * (1 + Flight)} *

@@ -583,7 +585,7 @@ public final class ElytraBehavior implements Helper { private Solution solveAngles(final SolverContext context) { final NetherPath path = context.path; - final int playerNear = context.playerNear; + final int playerNear = landingMode ? path.size() - 1 : context.playerNear; final Vec3d start = context.start; Solution solution = null; @@ -670,6 +672,9 @@ public final class ElytraBehavior implements Helper { logDebug("waiting for elytraFireworkSetbackUseDelay: " + this.remainingSetBackTicks); return; } + if (this.landingMode) { + return; + } final boolean useOnDescend = !Baritone.settings().elytraConserveFireworks.value || ctx.player().posY < goingTo.y + 5; final double currentSpeed = new Vec3d( ctx.player().motionX, From a83d275622998c710e665f40e823e1543a99bb7b Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 15:47:43 -0700 Subject: [PATCH 240/276] forgot --- src/main/java/baritone/process/ElytraProcess.java | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index f5329d8d1..6a19707e4 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -150,6 +150,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (ctx.player().posY < endPos.y - LANDING_COLUMN_HEIGHT) { logDirect("bad landing spot, trying again..."); badLandingSpots.add(endPos); + goingToLandingSpot = false; + this.state = State.FLYING; } } } From 3a6e5541fb79270a4e8421dbd298281444ecc91c Mon Sep 17 00:00:00 2001 From: Brady Date: Sun, 30 Jul 2023 17:48:40 -0500 Subject: [PATCH 241/276] Don't deploy elytra while PathingBehavior is active --- .../launch/mixins/MixinEntityPlayerSP.java | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java index 281ff96f5..efc56ca65 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java @@ -27,6 +27,8 @@ import baritone.behavior.LookBehavior; import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.settings.KeyBinding; import net.minecraft.entity.player.PlayerCapabilities; +import net.minecraft.item.ItemElytra; +import net.minecraft.item.ItemStack; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; @@ -123,4 +125,19 @@ public class MixinEntityPlayerSP { ((LookBehavior) baritone.getLookBehavior()).pig(); } } + + @Redirect( + method = "onLivingUpdate", + at = @At( + value = "INVOKE", + target = "net/minecraft/item/ItemElytra.isUsable(Lnet/minecraft/item/ItemStack;)Z" + ) + ) + private boolean isElytraUsable(ItemStack stack) { + IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this); + if (baritone != null && baritone.getPathingBehavior().isPathing()) { + return false; + } + return ItemElytra.isUsable(stack); + } } From 27e45b816d1fb876d7165379d5559fa01f449644 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 30 Jul 2023 19:45:25 -0400 Subject: [PATCH 242/276] increase air bubble radius, append destination to path when landing --- src/main/java/baritone/process/ElytraProcess.java | 11 ++++++++--- .../baritone/process/elytra/ElytraBehavior.java | 14 ++++++++++++-- .../baritone/process/elytra/UnpackedSegment.java | 4 ++-- 3 files changed, 22 insertions(+), 7 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 6a19707e4..cfcf5373f 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -113,7 +113,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro BetterBlockPos landingSpot = findSafeLandingSpot(last); // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes if (landingSpot != null) { - this.pathTo(landingSpot); + this.pathTo0(landingSpot, true); this.landingSpot = landingSpot; this.goingToLandingSpot = true; } @@ -248,6 +248,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro public void onLostControl() { this.goal = null; this.goingToLandingSpot = false; + this.landingSpot = null; this.reachedGoal = false; this.state = State.START_FLYING; // TODO: null state? if (this.behavior != null) { @@ -280,11 +281,15 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void pathTo(BlockPos destination) { + this.pathTo0(destination, false); + } + + private void pathTo0(BlockPos destination, boolean appendDestination) { if (ctx.player() == null || ctx.player().dimension != -1) { return; } this.onLostControl(); - this.behavior = new ElytraBehavior(this.baritone, this, destination); + this.behavior = new ElytraBehavior(this.baritone, this, destination, appendDestination); if (ctx.world() != null) { this.behavior.repackChunks(); } @@ -440,7 +445,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } private boolean hasAirBubble(BlockPos pos) { - final int radius = 2; // Half of 5, as we're counting blocks in each direction from the center + final int radius = 4; // Half of the full width, rounded down, as we're counting blocks in each direction from the center BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(); for (int x = -radius; x <= radius; x++) { for (int y = -radius; y <= radius; y++) { diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 39af6fc38..211835dda 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -99,6 +99,7 @@ public final class ElytraBehavior implements Helper { private BlockStateInterface bsi; private final BlockStateOctreeInterface boi; public final BlockPos destination; + private final boolean appendDestination; private final ExecutorService solverExecutor; private Future solver; @@ -111,7 +112,7 @@ public final class ElytraBehavior implements Helper { private int invTickCountdown = 0; private final Queue invTransactionQueue = new LinkedList<>(); - public ElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination) { + public ElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination, boolean appendDestination) { this.baritone = baritone; this.ctx = baritone.getPlayerContext(); this.clearLines = new CopyOnWriteArrayList<>(); @@ -119,6 +120,7 @@ public final class ElytraBehavior implements Helper { this.pathManager = this.new PathManager(); this.process = process; this.destination = destination; + this.appendDestination = appendDestination; this.solverExecutor = Executors.newSingleThreadExecutor(); this.nextTickBoostCounter = new int[2]; @@ -252,7 +254,15 @@ public final class ElytraBehavior implements Helper { } private void setPath(final UnpackedSegment segment) { - this.path = segment.collect(); + List path = segment.collect(); + if (ElytraBehavior.this.appendDestination) { + BlockPos dest = ElytraBehavior.this.destination; + BlockPos last = !path.isEmpty() ? path.get(path.size() - 1) : null; + if (last != null && ElytraBehavior.this.clearView(new Vec3d(dest), new Vec3d(last), false)) { + path.add(new BetterBlockPos(dest)); + } + } + this.path = new NetherPath(path); this.completePath = segment.isFinished(); this.playerNear = 0; this.ticksNearUnchanged = 0; diff --git a/src/main/java/baritone/process/elytra/UnpackedSegment.java b/src/main/java/baritone/process/elytra/UnpackedSegment.java index 02f07feb8..e50ab3235 100644 --- a/src/main/java/baritone/process/elytra/UnpackedSegment.java +++ b/src/main/java/baritone/process/elytra/UnpackedSegment.java @@ -49,7 +49,7 @@ public final class UnpackedSegment { return new UnpackedSegment(Stream.concat(other, this.path), this.finished); } - public NetherPath collect() { + public List collect() { final List path = this.path.collect(Collectors.toList()); // Remove backtracks @@ -67,7 +67,7 @@ public final class UnpackedSegment { } } - return new NetherPath(path); + return path; } public boolean isFinished() { From 7e9cf2e1e9733cc5258cfe9a55c153dab0fd343f Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 22:47:39 -0700 Subject: [PATCH 243/276] ok its based now --- src/main/java/baritone/process/ElytraProcess.java | 3 ++- .../java/baritone/process/elytra/ElytraBehavior.java | 10 ++++++++-- 2 files changed, 10 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index cfcf5373f..761ab78ea 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -164,10 +164,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } else if (this.state == State.LANDING) { if (Math.sqrt(ctx.player().motionX * ctx.player().motionX + ctx.player().motionZ * ctx.player().motionZ) > 0.001) { - logDirect("Landed, but still moving, waiting for velocity to die down... " + ctx.player().motionX + " " + ctx.player().motionZ); + logDirect("Landed, but still moving, waiting for velocity to die down... "); baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true); return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); } + logDirect("Done :)"); baritone.getInputOverrideHandler().clearAllKeys(); this.onLostControl(); return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 211835dda..503944981 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -634,7 +634,10 @@ public final class ElytraBehavior implements Helper { for (final Pair candidate : candidates) { final Integer augment = candidate.second(); - final Vec3d dest = candidate.first().add(0, augment, 0); + Vec3d dest = candidate.first().add(0, augment, 0); + if (landingMode) { + dest = dest.add(0.5, 0.5, 0.5); + } if (augment != 0) { if (i + lookahead >= path.size()) { @@ -1079,7 +1082,10 @@ public final class ElytraBehavior implements Helper { continue; } final Vec3d last = displacement.get(displacement.size() - 1); - final double goodness = goalDirection.dotProduct(last.normalize()); + double goodness = goalDirection.dotProduct(last.normalize()); + if (landingMode) { + goodness = -goalDelta.subtract(last).length(); + } final PitchResult bestSoFar = bestResults.peek(); if (bestSoFar == null || goodness > bestSoFar.dot) { bestResults.push(new PitchResult(pitch, goodness, displacement)); From 36df7b17f8586083f4d3d541af220480ccb0fb38 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 22:56:33 -0700 Subject: [PATCH 244/276] destroy async --- src/main/java/baritone/process/ElytraProcess.java | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 761ab78ea..757e9a294 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -252,8 +252,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.landingSpot = null; this.reachedGoal = false; this.state = State.START_FLYING; // TODO: null state? - if (this.behavior != null) { - this.behavior.destroy(); + destroyBehaviorAsync(); + } + + private void destroyBehaviorAsync() { + ElytraBehavior behavior = this.behavior; + if (behavior != null) { + Baritone.getExecutor().execute(behavior::destroy); this.behavior = null; } } @@ -353,10 +358,9 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro @Override public void onWorldEvent(WorldEvent event) { - if (event.getWorld() != null && event.getState() == EventState.POST && this.behavior != null) { + if (event.getWorld() != null && event.getState() == EventState.POST) { // Exiting the world, just destroy - this.behavior.destroy(); - this.behavior = null; + destroyBehaviorAsync(); } } From 134bfb2a164d8263b702a354e67b353460670434 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 23:24:04 -0700 Subject: [PATCH 245/276] fix two cases where it could get stuck indefinitely --- src/main/java/baritone/process/ElytraProcess.java | 11 ++++++++--- .../java/baritone/process/elytra/ElytraBehavior.java | 10 +++++++++- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 757e9a294..33acd6d4e 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -149,9 +149,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (ctx.player().posY < endPos.y - LANDING_COLUMN_HEIGHT) { logDirect("bad landing spot, trying again..."); - badLandingSpots.add(endPos); - goingToLandingSpot = false; - this.state = State.FLYING; + landingSpotIsBad(endPos); } } } @@ -245,6 +243,13 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } + public void landingSpotIsBad(BetterBlockPos endPos) { + badLandingSpots.add(endPos); + goingToLandingSpot = false; + this.landingSpot = null; + this.state = State.FLYING; + } + @Override public void onLostControl() { this.goal = null; diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 503944981..4164bae5e 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -219,8 +219,9 @@ public final class ElytraBehavior implements Helper { this.recalculating = true; final List before = this.path.subList(0, afterIncl + 1); final long start = System.nanoTime(); + final BetterBlockPos pathStart = this.path.get(afterIncl); - this.path0(this.path.get(afterIncl), ElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) + this.path0(pathStart, ElytraBehavior.this.destination, segment -> segment.prepend(before.stream())) .thenRun(() -> { final int recompute = this.path.size() - before.size() - 1; final double distance = this.path.get(0).distanceTo(this.path.get(recompute)); @@ -237,6 +238,10 @@ public final class ElytraBehavior implements Helper { final Throwable cause = ex.getCause(); if (cause instanceof PathCalculationException) { logDirect("Failed to compute next segment"); + if (ctx.player().getDistanceSq(pathStart) < 16 * 16) { + logDirect("Player is near the segment start, therefore repeating this calculation is pointless. Marking as complete"); + completePath = true; + } } else { logUnhandledException(cause); } @@ -260,6 +265,9 @@ public final class ElytraBehavior implements Helper { BlockPos last = !path.isEmpty() ? path.get(path.size() - 1) : null; if (last != null && ElytraBehavior.this.clearView(new Vec3d(dest), new Vec3d(last), false)) { path.add(new BetterBlockPos(dest)); + } else { + logDirect("unable to land at " + ElytraBehavior.this.destination); + process.landingSpotIsBad(new BetterBlockPos(ElytraBehavior.this.destination)); } } this.path = new NetherPath(path); From 9630224e7817bd1571308e7805569a4e56688df0 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 23:26:46 -0700 Subject: [PATCH 246/276] whatever --- src/main/java/baritone/process/ElytraProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 33acd6d4e..433597d06 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -263,8 +263,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private void destroyBehaviorAsync() { ElytraBehavior behavior = this.behavior; if (behavior != null) { - Baritone.getExecutor().execute(behavior::destroy); this.behavior = null; + Baritone.getExecutor().execute(behavior::destroy); } } From d921d2e36709f262da4120e0a91fa2a14f70cb1e Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 30 Jul 2023 23:33:49 -0700 Subject: [PATCH 247/276] live a little --- src/api/java/baritone/api/Settings.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index d664b569c..4baabfbdd 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1358,7 +1358,7 @@ public final class Settings { /** * The minimum speed that the player can drop to (in blocks/tick) before a firework is automatically deployed. */ - public final Setting elytraFireworkSpeed = new Setting<>(0.6); + public final Setting elytraFireworkSpeed = new Setting<>(1.2); /** * The delay after the player's position is set-back by the server that a firework may be automatically deployed. @@ -1393,7 +1393,7 @@ public final class Settings { /** * Renders the best elytra flight path that was simulated each tick. */ - public final Setting elytraRenderSimulation = new Setting<>(false); + public final Setting elytraRenderSimulation = new Setting<>(true); /** * Automatically path to and jump off of ledges to initiate elytra flight when grounded. From 7662810405a3f73496f6054886674e0009d74a61 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 00:12:01 -0700 Subject: [PATCH 248/276] add back unsegmenting --- src/main/java/baritone/utils/PathRenderer.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java index a30ec45b7..c04bdf10f 100644 --- a/src/main/java/baritone/utils/PathRenderer.java +++ b/src/main/java/baritone/utils/PathRenderer.java @@ -129,12 +129,12 @@ public final class PathRenderer implements IRenderer { int dirY = end.y - start.y; int dirZ = end.z - start.z; - /*while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && + while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && (dirX == positions.get(next + 1).x - end.x && dirY == positions.get(next + 1).y - end.y && dirZ == positions.get(next + 1).z - end.z)) { end = positions.get(++next); - }*/ + } if (fadeOut) { float alpha; From 83feddf6bedda7b46e400994939f64fdc1501b77 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 00:12:15 -0700 Subject: [PATCH 249/276] recalc if all points out of view --- src/main/java/baritone/process/elytra/ElytraBehavior.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 4164bae5e..cf7db7ac3 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -323,7 +323,11 @@ public final class ElytraBehavior implements Helper { return; } + boolean canSeeAny = false; for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { + if (ElytraBehavior.this.clearView(ctx.playerFeetAsVec(), this.path.getVec(i), false)) { + canSeeAny = true; + } if (!ElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { // obstacle. where do we return to pathing? // find the next valid segment @@ -344,6 +348,9 @@ public final class ElytraBehavior implements Helper { return; } } + if (!canSeeAny) { + this.pathRecalcSegment(rangeEndExcl - 1).thenRun(() -> logDirect("Recalculated segment since no path points were visible")); + } } private void attemptNextSegment() { From cc8afe95c5d8cf9f1c028ad8013b8df6b42d5c27 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 00:18:43 -0700 Subject: [PATCH 250/276] setting for nether fortress --- src/api/java/baritone/api/Settings.java | 5 +++++ src/main/java/baritone/process/ElytraProcess.java | 2 +- 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 4baabfbdd..5262549c2 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1426,6 +1426,11 @@ public final class Settings { */ public final Setting elytraCacheCullDistance = new Setting<>(5000); + /** + * Should elytra consider nether brick a valid landing block + */ + public final Setting elytraAllowLandOnNetherFortress = new Setting<>(false); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 433597d06..f687e39ca 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -423,7 +423,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } private boolean isSafeBlock(Block block) { - return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.NETHER_BRICK; + return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || (block == Blocks.NETHER_BRICK && Baritone.settings().elytraAllowLandOnNetherFortress.value); } private boolean isSafeBlock(BlockPos pos) { From 541b710ea73cc1a9339c05df34d08095730b06ff Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 00:27:50 -0700 Subject: [PATCH 251/276] too aggressive --- src/main/java/baritone/process/elytra/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index cf7db7ac3..65bce93fe 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -348,7 +348,7 @@ public final class ElytraBehavior implements Helper { return; } } - if (!canSeeAny) { + if (!canSeeAny && rangeStartIncl < rangeEndExcl - 2 && process.state != ElytraProcess.State.GET_TO_JUMP) { this.pathRecalcSegment(rangeEndExcl - 1).thenRun(() -> logDirect("Recalculated segment since no path points were visible")); } } From 64a881f99035920f600ec950eb8de743a74532be Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 01:36:01 -0700 Subject: [PATCH 252/276] elytra warning --- src/api/java/baritone/api/Settings.java | 5 +++ .../command/defaults/ElytraCommand.java | 39 ++++++++++++++++++- 2 files changed, 42 insertions(+), 2 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 5262549c2..d7086dad4 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1431,6 +1431,11 @@ public final class Settings { */ public final Setting elytraAllowLandOnNetherFortress = new Setting<>(false); + /** + * Has the user read and understood the elytra terms and conditions + */ + public final Setting elytraTermsAccepted = new Setting<>(false); + /** * A map of lowercase setting field names to their respective setting */ diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 6ba08dba9..a0d39d850 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.Baritone; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; @@ -26,6 +27,9 @@ import baritone.api.command.helpers.TabCompleteHelper; import baritone.api.pathing.goals.Goal; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.IElytraProcess; +import net.minecraft.util.text.TextComponentString; +import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.event.HoverEvent; import java.util.Arrays; import java.util.List; @@ -50,6 +54,11 @@ public class ElytraCommand extends Command { } if (!args.hasAny()) { + if (!Baritone.settings().elytraTermsAccepted.value && !ctx.player().isElytraFlying()) { + // only gatekeep if they are standing on the ground, don't mess them up in midair lol + gatekeep(); + return; + } Goal iGoal = customGoalProcess.mostRecentGoal(); if (iGoal == null) { throw new CommandInvalidStateException("No goal has been set"); @@ -83,6 +92,32 @@ public class ElytraCommand extends Command { } } + private void gatekeep() { + TextComponentString gatekeep = new TextComponentString(""); + gatekeep.appendText("Once you've read the below, and entered the seed, run "); + TextComponentString cmd = new TextComponentString(Baritone.settings().prefix.value + "set elytraTermsAccepted true"); + cmd.getStyle().setColor(TextFormatting.GRAY); + gatekeep.appendSibling(cmd); + gatekeep.appendText(" and then try again.\n"); + gatekeep.appendText("Baritone Elytra is an experimental feature. It is only intended for long distance travel in the Nether using fireworks for vanilla boost. It will not work with any other mods (\"hacks\") for non-vanilla boost. "); + TextComponentString gatekeep2 = new TextComponentString("If you want Baritone to attempt to take off from the ground for you, you can enable the elytraAutoJump setting. This may not be advisable on laggy servers. "); + gatekeep2.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraAutoJump true"))); + gatekeep.appendSibling(gatekeep2); + TextComponentString gatekeep3 = new TextComponentString("If you want Baritone to go slower and use less fireworks, enable the elytraConserveFireworks setting and/or decrease the elytraFireworkSpeed setting. "); + gatekeep3.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraConserveFireworks true\n" + Baritone.settings().prefix.value + "set elytraFireworkSpeed 0.6\n(the 0.6 number is just an example, tweak to your liking)"))); + gatekeep.appendSibling(gatekeep3); + TextComponentString gatekeep4 = new TextComponentString("Baritone Elytra "); + TextComponentString red = new TextComponentString("needs to know the seed"); + red.getStyle().setColor(TextFormatting.RED).setUnderlined(true).setBold(true); + gatekeep4.appendSibling(red); + gatekeep4.appendText(" of the world you are in. If it doesn't have the correct seed, it will constantly frustratingly recalculate and backtrack. It uses the seed to generate terrain far beyond what you can see, since terrain obstacles in the Nether can be much larger than your render distance. "); + gatekeep.appendSibling(gatekeep4); + TextComponentString gatekeep5 = new TextComponentString("If you're on 2b2t, no need to change anything, since its seed is the default. Otherwise, set it with: " + Baritone.settings().prefix.value + "set elytraNetherSeed seedgoeshere"); + gatekeep5.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString("2b2t's nether seed is 146008555100680, so for example you would run\n" + Baritone.settings().prefix.value + "set elytraNetherSeed 146008555100680\n\nAlso, if you're on 2b2t, note that the Nether near spawn is old terrain gen, so you'll see recalculating and backtracking there.\nIt'll only work well further away from spawn/highways."))); + gatekeep.appendSibling(gatekeep5); + logDirect(gatekeep); + } + @Override public Stream tabComplete(String label, IArgConsumer args) throws CommandException { TabCompleteHelper helper = new TabCompleteHelper(); @@ -114,8 +149,8 @@ public class ElytraCommand extends Command { final String osArch = System.getProperty("os.arch"); final String osName = System.getProperty("os.name"); return String.format( - "Legacy architectures are not supported. your CPU is %s and your operating system is %s. " + - "Supported architectures are 64 bit x86, and 64 bit arm, supported operating systems are Windows, " + + "Legacy architectures are not supported. Your CPU is %s and your operating system is %s. " + + "Supported architectures are 64 bit x86, and 64 bit ARM. Supported operating systems are Windows, " + "Linux, and Mac", osArch, osName ); From 46f38f2ce7bc170899ef7ff2e82a45f6b00626ec Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 31 Jul 2023 15:06:25 -0700 Subject: [PATCH 253/276] orderly shutdown --- src/main/java/baritone/process/elytra/ElytraBehavior.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 65bce93fe..64615ed8a 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -467,6 +467,11 @@ public final class ElytraBehavior implements Helper { this.solver.cancel(true); } this.solverExecutor.shutdown(); + try { + while (!this.solverExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {} + } catch (InterruptedException e) { + e.printStackTrace(); + } this.context.destroy(); } From c0a1e6540ff312668a9d666433bf5917484a594c Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 31 Jul 2023 16:14:09 -0400 Subject: [PATCH 254/276] simplify smoothLook into one setting and separate smoothLook from freeLook --- src/api/java/baritone/api/Settings.java | 10 ++------- .../java/baritone/behavior/LookBehavior.java | 21 ++++++++++--------- 2 files changed, 13 insertions(+), 18 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index d7086dad4..46a7f62e2 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -745,16 +745,10 @@ public final class Settings { * Forces the client-sided yaw rotation to an average of the last {@link #smoothLookTicks} of server-sided rotations. * Requires {@link #freeLook}. */ - public final Setting smoothLookYaw = new Setting<>(false); + public final Setting smoothLook = new Setting<>(false); /** - * Forces the client-sided pitch rotation to an average of the last {@link #smoothLookTicks} of server-sided rotations. - * Requires {@link #freeLook}. - */ - public final Setting smoothLookPitch = new Setting<>(false); - - /** - * The number of ticks to average across for {@link #smoothLookYaw} and {@link #smoothLookPitch}; + * The number of ticks to average across for {@link #smoothLook}; */ public final Setting smoothLookTicks = new Setting<>(10); diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 5f6421d08..869b8efb8 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -112,12 +112,15 @@ public final class LookBehavior extends Behavior implements ILookBehavior { this.smoothPitchBuffer.pop(); } - ctx.player().rotationYaw = Baritone.settings().smoothLookYaw.value - ? (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw) - : this.prevRotation.getYaw(); - ctx.player().rotationPitch = Baritone.settings().smoothLookPitch.value - ? (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch) - : this.prevRotation.getPitch(); + if (Baritone.settings().freeLook.value) { + ctx.player().rotationYaw = this.prevRotation.getYaw(); + ctx.player().rotationPitch = this.prevRotation.getPitch(); + } else if (Baritone.settings().smoothLook.value) { + ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); + ctx.player().rotationPitch = ctx.player().isElytraFlying() + ? (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch) + : this.prevRotation.getPitch(); + } this.prevRotation = null; } @@ -327,12 +330,10 @@ public final class LookBehavior extends Behavior implements ILookBehavior { final boolean blockFreeLook = settings.blockFreeLook.value; final boolean freeLook = settings.freeLook.value; - if (!freeLook) return CLIENT; + if (!freeLook && !settings.smoothLook.value) return CLIENT; if (!blockFreeLook && blockInteract) return CLIENT; - if (ctx.player().isElytraFlying()) { - return settings.elytraFreeLook.value ? SERVER : CLIENT; - } + // Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player // rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be From 0ca173f5dcb4c770791b93242bf47ee83560a264 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 31 Jul 2023 16:41:10 -0400 Subject: [PATCH 255/276] separate smooth look setting for elytra --- src/api/java/baritone/api/Settings.java | 8 ++++++-- src/main/java/baritone/behavior/LookBehavior.java | 8 ++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 46a7f62e2..051cb5686 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -737,16 +737,20 @@ public final class Settings { public final Setting blockFreeLook = new Setting<>(false); /** - * Automatically elytra fly without having to force the client-sided rotations. Requires {@link #freeLook}. + * Automatically elytra fly without having to force the client-sided rotations. */ public final Setting elytraFreeLook = new Setting<>(false); /** * Forces the client-sided yaw rotation to an average of the last {@link #smoothLookTicks} of server-sided rotations. - * Requires {@link #freeLook}. */ public final Setting smoothLook = new Setting<>(false); + /** + * Same as {@link #smoothLook} but for elytra flying. + */ + public final Setting elytraSmoothLook = new Setting<>(true); + /** * The number of ticks to average across for {@link #smoothLook}; */ diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 869b8efb8..133c00e73 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -112,10 +112,10 @@ public final class LookBehavior extends Behavior implements ILookBehavior { this.smoothPitchBuffer.pop(); } - if (Baritone.settings().freeLook.value) { + if ((ctx.player().isElytraFlying() && Baritone.settings().elytraFreeLook.value) || (!ctx.player().isElytraFlying() && Baritone.settings().freeLook.value)) { ctx.player().rotationYaw = this.prevRotation.getYaw(); ctx.player().rotationPitch = this.prevRotation.getPitch(); - } else if (Baritone.settings().smoothLook.value) { + } else if ((ctx.player().isElytraFlying() && Baritone.settings().elytraSmoothLook.value) || (!ctx.player().isElytraFlying() && Baritone.settings().smoothLook.value)) { ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); ctx.player().rotationPitch = ctx.player().isElytraFlying() ? (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch) @@ -328,13 +328,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior { final Settings settings = Baritone.settings(); final boolean antiCheat = settings.antiCheatCompatibility.value; final boolean blockFreeLook = settings.blockFreeLook.value; - final boolean freeLook = settings.freeLook.value; - if (!freeLook && !settings.smoothLook.value) return CLIENT; if (!blockFreeLook && blockInteract) return CLIENT; - - // Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player // rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be // whatever the player is mousing over visually. Let's just settle for setting it silently. From 7aa3eda3f6d75c5fdaea7a6c4be71921f2e1c34c Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 31 Jul 2023 17:07:38 -0400 Subject: [PATCH 256/276] fix nudgeToLevel with smoothLook --- src/main/java/baritone/behavior/LookBehavior.java | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 133c00e73..9a43f0099 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -117,9 +117,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior { ctx.player().rotationPitch = this.prevRotation.getPitch(); } else if ((ctx.player().isElytraFlying() && Baritone.settings().elytraSmoothLook.value) || (!ctx.player().isElytraFlying() && Baritone.settings().smoothLook.value)) { ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); - ctx.player().rotationPitch = ctx.player().isElytraFlying() - ? (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch) - : this.prevRotation.getPitch(); + if (ctx.player().isElytraFlying()) { + ctx.player().rotationPitch = (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch); + } } this.prevRotation = null; From 379156951940a04e602dd0409a24bc69847b7768 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Mon, 31 Jul 2023 22:31:45 -0400 Subject: [PATCH 257/276] refactor so that Target.Mode is not a lie fine yes honey --- .../java/baritone/behavior/LookBehavior.java | 43 ++++++++++--------- 1 file changed, 23 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 9a43f0099..5c46c6d2f 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -91,10 +91,8 @@ public final class LookBehavior extends Behavior implements ILookBehavior { // Just return for PRE, we still want to set target to null on POST return; } - if (this.target.mode == Target.Mode.SERVER) { - this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch); - } + this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch); final Rotation actual = this.processor.peekRotation(this.target.rotation); ctx.player().rotationYaw = actual.getYaw(); ctx.player().rotationPitch = actual.getPitch(); @@ -103,22 +101,21 @@ public final class LookBehavior extends Behavior implements ILookBehavior { case POST: { // Reset the player's rotations back to their original values if (this.prevRotation != null) { - this.smoothYawBuffer.add(this.target.rotation.getYaw()); + this.smoothYawBuffer.addLast(this.target.rotation.getYaw()); while (this.smoothYawBuffer.size() > Baritone.settings().smoothLookTicks.value) { - this.smoothYawBuffer.pop(); + this.smoothYawBuffer.removeFirst(); } - this.smoothPitchBuffer.add(this.target.rotation.getPitch()); + this.smoothPitchBuffer.addLast(this.target.rotation.getPitch()); while (this.smoothPitchBuffer.size() > Baritone.settings().smoothLookTicks.value) { - this.smoothPitchBuffer.pop(); + this.smoothPitchBuffer.removeFirst(); } - - if ((ctx.player().isElytraFlying() && Baritone.settings().elytraFreeLook.value) || (!ctx.player().isElytraFlying() && Baritone.settings().freeLook.value)) { + if (this.target.mode == Target.Mode.SERVER) { ctx.player().rotationYaw = this.prevRotation.getYaw(); ctx.player().rotationPitch = this.prevRotation.getPitch(); - } else if ((ctx.player().isElytraFlying() && Baritone.settings().elytraSmoothLook.value) || (!ctx.player().isElytraFlying() && Baritone.settings().smoothLook.value)) { - ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getYaw); + } else if (ctx.player().isElytraFlying() ? Baritone.settings().elytraSmoothLook.value : Baritone.settings().smoothLook.value) { + ctx.player().rotationYaw = (float) this.smoothYawBuffer.stream().mapToDouble(d -> d).average().orElse(this.prevRotation.getYaw()); if (ctx.player().isElytraFlying()) { - ctx.player().rotationPitch = (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElseGet(this.prevRotation::getPitch); + ctx.player().rotationPitch = (float) this.smoothPitchBuffer.stream().mapToDouble(d -> d).average().orElse(this.prevRotation.getPitch()); } } @@ -329,15 +326,21 @@ public final class LookBehavior extends Behavior implements ILookBehavior { final boolean antiCheat = settings.antiCheatCompatibility.value; final boolean blockFreeLook = settings.blockFreeLook.value; - if (!blockFreeLook && blockInteract) return CLIENT; + if (ctx.player().isElytraFlying()) { + // always need to set angles while flying + return settings.elytraFreeLook.value ? SERVER : CLIENT; + } else if (settings.freeLook.value) { + // Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player + // rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be + // whatever the player is mousing over visually. Let's just settle for setting it silently. + if (blockInteract) { + return blockFreeLook ? SERVER : CLIENT; + } + return antiCheat ? SERVER : NONE; + } - // Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player - // rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be - // whatever the player is mousing over visually. Let's just settle for setting it silently. - if (antiCheat || blockInteract) return SERVER; - - // Pathing regularly without antiCheatCompatibility, don't set the player rotation - return NONE; + // all freeLook settings are disabled so set the angles + return CLIENT; } } } From 7813a9caba9712c85b42d7f9da995af1cacba374 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 1 Aug 2023 11:30:30 -0700 Subject: [PATCH 258/276] looks better --- src/api/java/baritone/api/Settings.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 051cb5686..aeaa55542 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -754,7 +754,7 @@ public final class Settings { /** * The number of ticks to average across for {@link #smoothLook}; */ - public final Setting smoothLookTicks = new Setting<>(10); + public final Setting smoothLookTicks = new Setting<>(5); /** * When true, the player will remain with its existing look direction as often as possible. From 8c1ccd6c19058b7d3f9de4b8a770665b3f3a6388 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 1 Aug 2023 11:45:53 -0700 Subject: [PATCH 259/276] reduce dumb behavior --- src/main/java/baritone/process/elytra/ElytraBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 64615ed8a..9d497932b 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -325,7 +325,7 @@ public final class ElytraBehavior implements Helper { boolean canSeeAny = false; for (int i = rangeStartIncl; i < rangeEndExcl - 1; i++) { - if (ElytraBehavior.this.clearView(ctx.playerFeetAsVec(), this.path.getVec(i), false)) { + if (ElytraBehavior.this.clearView(ctx.playerFeetAsVec(), this.path.getVec(i), false) || ElytraBehavior.this.clearView(ctx.playerHead(), this.path.getVec(i), false)) { canSeeAny = true; } if (!ElytraBehavior.this.clearView(this.path.getVec(i), this.path.getVec(i + 1), false)) { From 70640246b6ca0b83ed1f63de627509bf955e1c81 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Tue, 1 Aug 2023 14:11:25 -0700 Subject: [PATCH 260/276] fix infinite memory usage / crash --- src/main/java/baritone/process/ElytraProcess.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index f687e39ca..23ca7647f 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -115,8 +115,8 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro if (landingSpot != null) { this.pathTo0(landingSpot, true); this.landingSpot = landingSpot; - this.goingToLandingSpot = true; } + this.goingToLandingSpot = true; } if (last != null && ctx.player().getDistanceSqToCenter(last) < 1) { @@ -504,7 +504,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro while (!queue.isEmpty()) { BetterBlockPos pos = queue.poll(); - if (ctx.world().isBlockLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { + if (ctx.world().isBlockLoaded(pos, false) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) { BetterBlockPos actualLandingSpot = checkLandingSpot(pos, checkedPositions); if (actualLandingSpot != null && isColumnAir(actualLandingSpot, LANDING_COLUMN_HEIGHT) && hasAirBubble(actualLandingSpot.up(LANDING_COLUMN_HEIGHT)) && !badLandingSpots.contains(actualLandingSpot.up(LANDING_COLUMN_HEIGHT))) { return actualLandingSpot.up(LANDING_COLUMN_HEIGHT); From f5bd737ee97d5963e8d4f7f78ade428a2f92f804 Mon Sep 17 00:00:00 2001 From: Dennis <43997085+TheAlan404@users.noreply.github.com> Date: Wed, 2 Aug 2023 21:19:35 +0300 Subject: [PATCH 261/276] add badge count badge --- README.md | 1 + 1 file changed, 1 insertion(+) diff --git a/README.md b/README.md index c6a90ff93..a5bf404e1 100644 --- a/README.md +++ b/README.md @@ -32,6 +32,7 @@ Code size GitHub repo size Lines of Code + yes

From 139fd03470116b17b7d07e0a6fc00b640552dcbd Mon Sep 17 00:00:00 2001 From: Brady Hahn Date: Wed, 2 Aug 2023 17:07:03 -0500 Subject: [PATCH 262/276] Update lines of code badge to match style --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a5bf404e1..b99f4a20c 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ GitHub commits Code size GitHub repo size - Lines of Code + Lines of Code yes

From 0edcf650444219033bfbfecdb0f2bc49cbc0817a Mon Sep 17 00:00:00 2001 From: William Gray Date: Mon, 7 Aug 2023 21:33:42 +0000 Subject: [PATCH 263/276] fix badges --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b99f4a20c..de3241e31 100644 --- a/README.md +++ b/README.md @@ -46,8 +46,8 @@

- forthebadge - forthebadge + forthebadge + forthebadge

A Minecraft pathfinder bot. From 15a38c4871caac7329da9e90869133cebccdeaaf Mon Sep 17 00:00:00 2001 From: Babbaj Date: Sun, 13 Aug 2023 21:58:07 -0400 Subject: [PATCH 264/276] add setting that makes unknown chunks air --- build.gradle | 4 ++-- src/api/java/baritone/api/Settings.java | 6 ++++++ .../baritone/process/elytra/NetherPathfinderContext.java | 5 ++++- 3 files changed, 12 insertions(+), 3 deletions(-) diff --git a/build.gradle b/build.gradle index accb7ca54..0c8e58364 100755 --- a/build.gradle +++ b/build.gradle @@ -175,8 +175,8 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:0.41') - implementation 'dev.babbaj:nether-pathfinder:0.41' + launchImplementation('dev.babbaj:nether-pathfinder:1.2') + implementation 'dev.babbaj:nether-pathfinder:1.2' testImplementation 'junit:junit:4.12' } diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index aeaa55542..076f8f395 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1404,6 +1404,12 @@ public final class Settings { */ public final Setting elytraNetherSeed = new Setting<>(146008555100680L); + /** + * Whether nether-pathfinder should generate terrain based on {@link #elytraNetherSeed}. + * If false all chunks that haven't been loaded are assumed to be air. + */ + public final Setting elytraPredictTerrain = new Setting<>(true); + /** * Automatically swap the current elytra with a new one when the durability gets too low */ diff --git a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java index 991457d10..93e0587f0 100644 --- a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java @@ -17,6 +17,7 @@ package baritone.process.elytra; +import baritone.Baritone; import baritone.api.event.events.BlockChangeEvent; import baritone.utils.accessor.IBitArray; import baritone.utils.accessor.IBlockStateContainer; @@ -103,7 +104,9 @@ public final class NetherPathfinderContext { src.getX(), src.getY(), src.getZ(), dst.getX(), dst.getY(), dst.getZ(), true, - 10000 + false, + 10000, + !Baritone.settings().elytraPredictTerrain.value ); if (segment == null) { throw new PathCalculationException("Path calculation failed"); From 4e3a7abac93e7fec43824ff9d1b88b4f4488d27e Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 13 Aug 2023 19:29:19 -0700 Subject: [PATCH 265/276] recompute on change --- src/main/java/baritone/process/ElytraProcess.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index 23ca7647f..a93980cbd 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -61,6 +61,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro private boolean reachedGoal; // this basically just prevents potential notification spam private Goal goal; private ElytraBehavior behavior; + private boolean predictingTerrain; private ElytraProcess(Baritone baritone) { super(baritone); @@ -97,6 +98,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro logDirect("Nether seed changed, recalculating path"); this.resetState(); } + if (predictingTerrain != Baritone.settings().elytraPredictTerrain.value) { + logDirect("elytraPredictTerrain setting changed, recalculating path"); + predictingTerrain = Baritone.settings().elytraPredictTerrain.value; + this.resetState(); + } this.behavior.onTick(); @@ -300,6 +306,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return; } this.onLostControl(); + this.predictingTerrain = Baritone.settings().elytraPredictTerrain.value; this.behavior = new ElytraBehavior(this.baritone, this, destination, appendDestination); if (ctx.world() != null) { this.behavior.repackChunks(); From 36534eeb2d95185d1461d7e03f1ecb3d2ddbf24a Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 13 Aug 2023 22:13:33 -0700 Subject: [PATCH 266/276] vastly more helpful --- .../command/defaults/ElytraCommand.java | 112 +++++++++++++++--- 1 file changed, 98 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index a0d39d850..7064deb5c 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -27,14 +27,22 @@ import baritone.api.command.helpers.TabCompleteHelper; import baritone.api.pathing.goals.Goal; import baritone.api.process.ICustomGoalProcess; import baritone.api.process.IElytraProcess; +import net.minecraft.client.multiplayer.ServerData; +import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.TextComponentString; import net.minecraft.util.text.TextFormatting; +import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; +import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX; + public class ElytraCommand extends Command { public ElytraCommand(IBaritone baritone) { @@ -54,10 +62,13 @@ public class ElytraCommand extends Command { } if (!args.hasAny()) { - if (!Baritone.settings().elytraTermsAccepted.value && !ctx.player().isElytraFlying()) { + if (Baritone.settings().elytraTermsAccepted.value) { + if (detectOn2b2t()) { + warn2b2t(); + } + } else { // only gatekeep if they are standing on the ground, don't mess them up in midair lol gatekeep(); - return; } Goal iGoal = customGoalProcess.mostRecentGoal(); if (iGoal == null) { @@ -92,32 +103,105 @@ public class ElytraCommand extends Command { } } + private void warn2b2t() { + if (!Baritone.settings().elytraPredictTerrain.value) { + if (ctx.playerFeet().distanceSq(0, 0, 0) > 2000 * 2000) { + TextComponentString clippy = new TextComponentString(""); + clippy.appendText("It looks like you're on 2b2t and more than 2000 blocks from spawn. It is recommended that you "); + TextComponentString predictTerrain = new TextComponentString("enable elytraPredictTerrain"); + predictTerrain.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraPredictTerrain true"))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraPredictTerrain true")); + clippy.appendSibling(predictTerrain); + logDirect(clippy); + } + } else { + long seed = Baritone.settings().elytraNetherSeed.value; + if (seed != NEW_2B2T_SEED && seed != OLD_2B2T_SEED) { + logDirect(new TextComponentString("It looks like you're on 2b2t, but elytraNetherSeed is incorrect.")); // match color + logDirect(suggest2b2tSeeds()); + } + } + } + + private ITextComponent suggest2b2tSeeds() { + TextComponentString clippy = new TextComponentString(""); + clippy.appendText("Within a few hundred blocks of spawn/axis/highways/etc, the terrain is too fragmented to be predictable. Baritone Elytra will still work, just with backtracking. "); + clippy.appendText("However, once you get more than a few thousand blocks out, you should try "); + TextComponentString olderSeed = new TextComponentString("the older seed (click here)"); + olderSeed.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraNetherSeed " + OLD_2B2T_SEED))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraNetherSeed " + OLD_2B2T_SEED)); + clippy.appendSibling(olderSeed); + clippy.appendText(". Once you're further out into newer terrain generation (this includes everything 1.12 and upwards), you should try "); + TextComponentString newerSeed = new TextComponentString("the newer seed (click here)"); + newerSeed.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraNetherSeed " + NEW_2B2T_SEED))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraNetherSeed " + NEW_2B2T_SEED)); + clippy.appendSibling(newerSeed); + clippy.appendText(". "); + return clippy; + } + private void gatekeep() { TextComponentString gatekeep = new TextComponentString(""); - gatekeep.appendText("Once you've read the below, and entered the seed, run "); - TextComponentString cmd = new TextComponentString(Baritone.settings().prefix.value + "set elytraTermsAccepted true"); - cmd.getStyle().setColor(TextFormatting.GRAY); - gatekeep.appendSibling(cmd); - gatekeep.appendText(" and then try again.\n"); + gatekeep.appendText("To disable this message, enable the setting elytraTermsAccepted\n"); gatekeep.appendText("Baritone Elytra is an experimental feature. It is only intended for long distance travel in the Nether using fireworks for vanilla boost. It will not work with any other mods (\"hacks\") for non-vanilla boost. "); - TextComponentString gatekeep2 = new TextComponentString("If you want Baritone to attempt to take off from the ground for you, you can enable the elytraAutoJump setting. This may not be advisable on laggy servers. "); + TextComponentString gatekeep2 = new TextComponentString("If you want Baritone to attempt to take off from the ground for you, you can enable the elytraAutoJump setting (not advisable on laggy servers!). "); gatekeep2.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraAutoJump true"))); gatekeep.appendSibling(gatekeep2); - TextComponentString gatekeep3 = new TextComponentString("If you want Baritone to go slower and use less fireworks, enable the elytraConserveFireworks setting and/or decrease the elytraFireworkSpeed setting. "); + TextComponentString gatekeep3 = new TextComponentString("If you want Baritone to go slower, enable the elytraConserveFireworks setting and/or decrease the elytraFireworkSpeed setting. "); gatekeep3.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraConserveFireworks true\n" + Baritone.settings().prefix.value + "set elytraFireworkSpeed 0.6\n(the 0.6 number is just an example, tweak to your liking)"))); gatekeep.appendSibling(gatekeep3); TextComponentString gatekeep4 = new TextComponentString("Baritone Elytra "); - TextComponentString red = new TextComponentString("needs to know the seed"); + TextComponentString red = new TextComponentString("wants to know the seed"); red.getStyle().setColor(TextFormatting.RED).setUnderlined(true).setBold(true); gatekeep4.appendSibling(red); - gatekeep4.appendText(" of the world you are in. If it doesn't have the correct seed, it will constantly frustratingly recalculate and backtrack. It uses the seed to generate terrain far beyond what you can see, since terrain obstacles in the Nether can be much larger than your render distance. "); + gatekeep4.appendText(" of the world you are in. If it doesn't have the correct seed, it will frequently backtrack. It uses the seed to generate terrain far beyond what you can see, since terrain obstacles in the Nether can be much larger than your render distance. "); gatekeep.appendSibling(gatekeep4); - TextComponentString gatekeep5 = new TextComponentString("If you're on 2b2t, no need to change anything, since its seed is the default. Otherwise, set it with: " + Baritone.settings().prefix.value + "set elytraNetherSeed seedgoeshere"); - gatekeep5.getStyle().setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString("2b2t's nether seed is 146008555100680, so for example you would run\n" + Baritone.settings().prefix.value + "set elytraNetherSeed 146008555100680\n\nAlso, if you're on 2b2t, note that the Nether near spawn is old terrain gen, so you'll see recalculating and backtracking there.\nIt'll only work well further away from spawn/highways."))); - gatekeep.appendSibling(gatekeep5); + gatekeep.appendText("\n"); + if (detectOn2b2t()) { + TextComponentString gatekeep5 = new TextComponentString("It looks like you're on 2b2t, so elytraPredictTerrain is defaulting to true. "); + gatekeep5.appendSibling(suggest2b2tSeeds()); + if (Baritone.settings().elytraNetherSeed.value == NEW_2B2T_SEED) { + gatekeep5.appendText("You are using the newer seed. "); + } else if (Baritone.settings().elytraNetherSeed.value == OLD_2B2T_SEED) { + gatekeep5.appendText("You are using the older seed. "); + } else { + gatekeep5.appendText("Defaulting to the newer seed. "); + Baritone.settings().elytraNetherSeed.value = NEW_2B2T_SEED; + } + gatekeep.appendSibling(gatekeep5); + } else { + if (Baritone.settings().elytraNetherSeed.value == NEW_2B2T_SEED) { + TextComponentString gatekeep5 = new TextComponentString("Baritone doesn't know the seed of your world. Set it with: " + Baritone.settings().prefix.value + "set elytraNetherSeed seedgoeshere\n"); + gatekeep5.appendText("For the time being, elytraPredictTerrain is defaulting to false since the seed is unknown."); + gatekeep.appendSibling(gatekeep5); + Baritone.settings().elytraPredictTerrain.value = false; + } else { + if (Baritone.settings().elytraPredictTerrain.value) { + TextComponentString gatekeep5 = new TextComponentString("Baritone Elytra is predicting terrain assuming that " + Baritone.settings().elytraNetherSeed.value + " is the correct seed. Change that with " + Baritone.settings().prefix.value + "set elytraNetherSeed seedgoeshere, or disable it with " + Baritone.settings().prefix.value + "set elytraPredictTerrain false"); + gatekeep.appendSibling(gatekeep5); + } else { + TextComponentString gatekeep5 = new TextComponentString("Baritone Elytra is not predicting terrain. If you don't know the seed, this is the correct thing to do. If you do know the seed, input it with " + Baritone.settings().prefix.value + "set elytraNetherSeed seedgoeshere, and then enable it with " + Baritone.settings().prefix.value + "set elytraPredictTerrain true"); + gatekeep.appendSibling(gatekeep5); + } + } + } logDirect(gatekeep); } + private boolean detect2b2tPlayers() { + // if any cached worlds are 2b2t worlds + try (Stream stream = Files.list(((Baritone) baritone).getDirectory())) { + return stream.anyMatch(path -> path.getFileName().toString().toLowerCase().contains("2b2t")); + } catch (IOException e) { + throw new RuntimeException(e); + } + } + + private boolean detectOn2b2t() { + ServerData data = ctx.minecraft().getCurrentServerData(); + return data != null && data.serverIP.toLowerCase().contains("2b2t"); + } + + private static final long OLD_2B2T_SEED = -4172144997902289642L; + private static final long NEW_2B2T_SEED = 146008555100680L; + @Override public Stream tabComplete(String label, IArgConsumer args) throws CommandException { TabCompleteHelper helper = new TabCompleteHelper(); From d67a3d8bbc0b4bf4aae376e8de6003de02953170 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 13 Aug 2023 22:37:47 -0700 Subject: [PATCH 267/276] much better safety --- src/api/java/baritone/api/Settings.java | 10 +++++ .../java/baritone/process/ElytraProcess.java | 43 +++++++++++++++++-- .../process/elytra/ElytraBehavior.java | 2 +- 3 files changed, 51 insertions(+), 4 deletions(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 076f8f395..44701b798 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -1420,6 +1420,16 @@ public final class Settings { */ public final Setting elytraMinimumDurability = new Setting<>(5); + /** + * The minimum fireworks before landing early for safety + */ + public final Setting elytraMinFireworksBeforeLanding = new Setting<>(5); + + /** + * Automatically land when elytra is almost out of durability, or almost out of fireworks + */ + public final Setting elytraAllowEmergencyLand = new Setting<>(true); + /** * Time between culling far away chunks from the nether pathfinder chunk cache */ diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index a93980cbd..c6c41881d 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -47,6 +47,9 @@ import it.unimi.dsi.fastutil.longs.LongOpenHashSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.init.Blocks; +import net.minecraft.init.Items; +import net.minecraft.item.ItemStack; +import net.minecraft.util.NonNullList; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.Vec3d; @@ -112,11 +115,21 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); } - if (ctx.player().isElytraFlying() && this.state != State.LANDING && this.behavior.pathManager.isComplete()) { + boolean safetyLanding = false; + if (ctx.player().isElytraFlying() && shouldLandForSafety()) { + if (Baritone.settings().elytraAllowEmergencyLand.value) { + logDirect("Emergency landing - almost out of elytra durability or fireworks"); + safetyLanding = true; + } else { + logDirect("almost out of elytra durability or fireworks, but I'm going to continue since elytraAllowEmergencyLand is false"); + } + } + if (ctx.player().isElytraFlying() && this.state != State.LANDING && (this.behavior.pathManager.isComplete() || safetyLanding)) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); - if (last != null && ctx.player().getDistanceSqToCenter(last) < (48 * 48) && !goingToLandingSpot) { + logDirect((last != null) + " " + this.state + " " + safetyLanding + " " + goingToLandingSpot); + if (last != null && (ctx.player().getDistanceSqToCenter(last) < (48 * 48) || safetyLanding) && (!goingToLandingSpot || (safetyLanding && this.landingSpot == null))) { logDirect("Path complete, picking a nearby safe landing spot..."); - BetterBlockPos landingSpot = findSafeLandingSpot(last); + BetterBlockPos landingSpot = findSafeLandingSpot(ctx.playerFeet()); // if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes if (landingSpot != null) { this.pathTo0(landingSpot, true); @@ -185,6 +198,11 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } if (this.state == State.LOCATE_JUMP) { + if (shouldLandForSafety()) { + logDirect("Not taking off, because elytra durability or fireworks are so low that I would immediately emergency land anyway."); + onLostControl(); + return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); + } if (this.goal == null) { this.goal = new GoalYLevel(31); } @@ -338,6 +356,25 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro this.pathTo(new BlockPos(x, y, z)); } + private boolean shouldLandForSafety() { + ItemStack chest = ctx.player().inventory.armorInventory.get(2); + if (chest.getItem() != Items.ELYTRA || chest.getItem().getMaxDamage() - chest.getItemDamage() < Baritone.settings().elytraMinimumDurability.value) { + // elytrabehavior replaces when durability <= minimumDurability, so if durability < minimumDurability then we can reasonably assume that the elytra will soon be broken without replacement + return true; + } + NonNullList inv = ctx.player().inventory.mainInventory; + int qty = 0; + for (int i = 0; i < 36; i++) { + if (ElytraBehavior.isFireworks(inv.get(i))) { + qty += inv.get(i).getCount(); + } + } + if (qty <= Baritone.settings().elytraMinFireworksBeforeLanding.value) { + return true; + } + return false; + } + @Override public boolean isLoaded() { return true; diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java index 9d497932b..709d22334 100644 --- a/src/main/java/baritone/process/elytra/ElytraBehavior.java +++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java @@ -887,7 +887,7 @@ public final class ElytraBehavior implements Helper { } } - private static boolean isFireworks(final ItemStack itemStack) { + public static boolean isFireworks(final ItemStack itemStack) { if (itemStack.getItem() != Items.FIREWORKS) { return false; } From 81e004380fff168e42ed082c4b3ae1510c912971 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 13 Aug 2023 22:42:51 -0700 Subject: [PATCH 268/276] thanks lamp! i love lamp! --- src/main/java/baritone/command/defaults/ElytraCommand.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 7064deb5c..6db6a877d 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -199,7 +199,7 @@ public class ElytraCommand extends Command { return data != null && data.serverIP.toLowerCase().contains("2b2t"); } - private static final long OLD_2B2T_SEED = -4172144997902289642L; + private static final long OLD_2B2T_SEED = -4100785268875389365L; private static final long NEW_2B2T_SEED = 146008555100680L; @Override From 535eccfc245f0d6a0199c364d0254fdb97f07946 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 13 Aug 2023 22:46:51 -0700 Subject: [PATCH 269/276] no longer applies --- src/main/java/baritone/command/defaults/ElytraCommand.java | 1 - 1 file changed, 1 deletion(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 6db6a877d..19f3a030f 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -67,7 +67,6 @@ public class ElytraCommand extends Command { warn2b2t(); } } else { - // only gatekeep if they are standing on the ground, don't mess them up in midair lol gatekeep(); } Goal iGoal = customGoalProcess.mostRecentGoal(); From bd263e1bf88bedff5d84ba41bf00ee82c1b6b3ee Mon Sep 17 00:00:00 2001 From: leijurv Date: Mon, 14 Aug 2023 01:40:15 -0700 Subject: [PATCH 270/276] message for 2b players just in case the update actually happens --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index de3241e31..a98eda73f 100644 --- a/README.md +++ b/README.md @@ -69,6 +69,8 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s | [1.19.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-forge-1.9.3.jar) | [1.19.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-fabric-1.9.3.jar) | | [1.20.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-forge-1.10.1.jar) | [1.20.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-fabric-1.10.1.jar) | +**Message for 2b2t players looking for 1.19/1.20 Baritone** (download it from right above ^). Please check back in a few days for Baritone Elytra ([vid 1](https://youtu.be/4bGGPo8yiHo) [vid 2](https://www.youtube.com/watch?v=pUN9nmINe3I)], which will be ported to 1.19/1.20 soon! It will work on 2b2t with its anticheat, that was the whole point of Baritone Elytra (it's fully vanilla compatible). Also join [**the discord**](http://discord.gg/s6fRBAUpmr). Thanks! + **How to immediately get started:** Type `#goto 1000 500` in chat to go to x=1000 z=500. Type `#mine diamond_ore` to mine diamond ore. Type `#stop` to stop. For more, read [the usage page](USAGE.md) and/or watch this [tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa) For other versions of Minecraft or more complicated situations or for development, see [Installation & setup](SETUP.md). Also consider just installing [Impact](https://impactclient.net/), which comes with Baritone and is easier to install than wrangling with version JSONs and zips. For 1.16.5, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it. There's a [showcase video](https://youtu.be/CZkLXWo4Fg4) made by @Adovin#6313 on Baritone which I recommend. From b0929991b15d011b9af60f29abf3e927db531b68 Mon Sep 17 00:00:00 2001 From: leijurv Date: Mon, 14 Aug 2023 01:40:47 -0700 Subject: [PATCH 271/276] typo --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a98eda73f..674825c2b 100644 --- a/README.md +++ b/README.md @@ -69,7 +69,7 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s | [1.19.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-forge-1.9.3.jar) | [1.19.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-fabric-1.9.3.jar) | | [1.20.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-forge-1.10.1.jar) | [1.20.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-fabric-1.10.1.jar) | -**Message for 2b2t players looking for 1.19/1.20 Baritone** (download it from right above ^). Please check back in a few days for Baritone Elytra ([vid 1](https://youtu.be/4bGGPo8yiHo) [vid 2](https://www.youtube.com/watch?v=pUN9nmINe3I)], which will be ported to 1.19/1.20 soon! It will work on 2b2t with its anticheat, that was the whole point of Baritone Elytra (it's fully vanilla compatible). Also join [**the discord**](http://discord.gg/s6fRBAUpmr). Thanks! +**Message for 2b2t players looking for 1.19/1.20 Baritone** Download it from right above ^. But also please check back in a few days for Baritone Elytra ([vid 1](https://youtu.be/4bGGPo8yiHo) [vid 2](https://www.youtube.com/watch?v=pUN9nmINe3I)), which will be ported to 1.19/1.20 soon! It will work on 2b2t with its anticheat, that was the whole point of Baritone Elytra (it's fully vanilla compatible). Also join [**the discord**](http://discord.gg/s6fRBAUpmr). Thanks! **How to immediately get started:** Type `#goto 1000 500` in chat to go to x=1000 z=500. Type `#mine diamond_ore` to mine diamond ore. Type `#stop` to stop. For more, read [the usage page](USAGE.md) and/or watch this [tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa) From f35e55ef66531d68aaa3680b9551da032c40db0c Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 14 Aug 2023 12:34:24 -0700 Subject: [PATCH 272/276] unused --- .../java/baritone/command/defaults/ElytraCommand.java | 9 --------- 1 file changed, 9 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 19f3a030f..ddbe6fa19 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -184,15 +184,6 @@ public class ElytraCommand extends Command { logDirect(gatekeep); } - private boolean detect2b2tPlayers() { - // if any cached worlds are 2b2t worlds - try (Stream stream = Files.list(((Baritone) baritone).getDirectory())) { - return stream.anyMatch(path -> path.getFileName().toString().toLowerCase().contains("2b2t")); - } catch (IOException e) { - throw new RuntimeException(e); - } - } - private boolean detectOn2b2t() { ServerData data = ctx.minecraft().getCurrentServerData(); return data != null && data.serverIP.toLowerCase().contains("2b2t"); From 7b911aa0a71e1bc53c9458e8b41de3db7a005beb Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 14 Aug 2023 20:51:39 -0700 Subject: [PATCH 273/276] clean up elytra given 2b2t status --- .../command/defaults/ElytraCommand.java | 39 ++++++++----------- .../java/baritone/process/ElytraProcess.java | 1 - 2 files changed, 16 insertions(+), 24 deletions(-) diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index ddbe6fa19..5895c36ad 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -34,9 +34,6 @@ import net.minecraft.util.text.TextFormatting; import net.minecraft.util.text.event.ClickEvent; import net.minecraft.util.text.event.HoverEvent; -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; import java.util.Arrays; import java.util.List; import java.util.stream.Stream; @@ -103,16 +100,7 @@ public class ElytraCommand extends Command { } private void warn2b2t() { - if (!Baritone.settings().elytraPredictTerrain.value) { - if (ctx.playerFeet().distanceSq(0, 0, 0) > 2000 * 2000) { - TextComponentString clippy = new TextComponentString(""); - clippy.appendText("It looks like you're on 2b2t and more than 2000 blocks from spawn. It is recommended that you "); - TextComponentString predictTerrain = new TextComponentString("enable elytraPredictTerrain"); - predictTerrain.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraPredictTerrain true"))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraPredictTerrain true")); - clippy.appendSibling(predictTerrain); - logDirect(clippy); - } - } else { + if (Baritone.settings().elytraPredictTerrain.value) { long seed = Baritone.settings().elytraNetherSeed.value; if (seed != NEW_2B2T_SEED && seed != OLD_2B2T_SEED) { logDirect(new TextComponentString("It looks like you're on 2b2t, but elytraNetherSeed is incorrect.")); // match color @@ -128,11 +116,11 @@ public class ElytraCommand extends Command { TextComponentString olderSeed = new TextComponentString("the older seed (click here)"); olderSeed.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraNetherSeed " + OLD_2B2T_SEED))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraNetherSeed " + OLD_2B2T_SEED)); clippy.appendSibling(olderSeed); - clippy.appendText(". Once you're further out into newer terrain generation (this includes everything 1.12 and upwards), you should try "); + clippy.appendText(". Once you're further out into newer terrain generation (this includes everything up through 1.12), you should try "); TextComponentString newerSeed = new TextComponentString("the newer seed (click here)"); newerSeed.getStyle().setUnderlined(true).setBold(true).setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, new TextComponentString(Baritone.settings().prefix.value + "set elytraNetherSeed " + NEW_2B2T_SEED))).setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, FORCE_COMMAND_PREFIX + "set elytraNetherSeed " + NEW_2B2T_SEED)); clippy.appendSibling(newerSeed); - clippy.appendText(". "); + clippy.appendText(". Once you get into 1.19 terrain, the terrain becomes unpredictable again, due to custom non-vanilla generation, and you should set #elytraPredictTerrain to false. "); return clippy; } @@ -154,15 +142,19 @@ public class ElytraCommand extends Command { gatekeep.appendSibling(gatekeep4); gatekeep.appendText("\n"); if (detectOn2b2t()) { - TextComponentString gatekeep5 = new TextComponentString("It looks like you're on 2b2t, so elytraPredictTerrain is defaulting to true. "); + TextComponentString gatekeep5 = new TextComponentString("It looks like you're on 2b2t. "); gatekeep5.appendSibling(suggest2b2tSeeds()); - if (Baritone.settings().elytraNetherSeed.value == NEW_2B2T_SEED) { - gatekeep5.appendText("You are using the newer seed. "); - } else if (Baritone.settings().elytraNetherSeed.value == OLD_2B2T_SEED) { - gatekeep5.appendText("You are using the older seed. "); + if (!Baritone.settings().elytraPredictTerrain.value) { + gatekeep5.appendText(Baritone.settings().prefix.value + "elytraPredictTerrain is currently disabled. "); } else { - gatekeep5.appendText("Defaulting to the newer seed. "); - Baritone.settings().elytraNetherSeed.value = NEW_2B2T_SEED; + if (Baritone.settings().elytraNetherSeed.value == NEW_2B2T_SEED) { + gatekeep5.appendText("You are using the newer seed. "); + } else if (Baritone.settings().elytraNetherSeed.value == OLD_2B2T_SEED) { + gatekeep5.appendText("You are using the older seed. "); + } else { + gatekeep5.appendText("Defaulting to the newer seed. "); + Baritone.settings().elytraNetherSeed.value = NEW_2B2T_SEED; + } } gatekeep.appendSibling(gatekeep5); } else { @@ -185,8 +177,9 @@ public class ElytraCommand extends Command { } private boolean detectOn2b2t() { + if (true) return true; ServerData data = ctx.minecraft().getCurrentServerData(); - return data != null && data.serverIP.toLowerCase().contains("2b2t"); + return data != null && data.serverIP.toLowerCase().contains("2b2t.org"); } private static final long OLD_2B2T_SEED = -4100785268875389365L; diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java index c6c41881d..bf0dd9802 100644 --- a/src/main/java/baritone/process/ElytraProcess.java +++ b/src/main/java/baritone/process/ElytraProcess.java @@ -126,7 +126,6 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro } if (ctx.player().isElytraFlying() && this.state != State.LANDING && (this.behavior.pathManager.isComplete() || safetyLanding)) { final BetterBlockPos last = this.behavior.pathManager.path.getLast(); - logDirect((last != null) + " " + this.state + " " + safetyLanding + " " + goingToLandingSpot); if (last != null && (ctx.player().getDistanceSqToCenter(last) < (48 * 48) || safetyLanding) && (!goingToLandingSpot || (safetyLanding && this.landingSpot == null))) { logDirect("Path complete, picking a nearby safe landing spot..."); BetterBlockPos landingSpot = findSafeLandingSpot(ctx.playerFeet()); From b1be4f29adf8fbdc785e04e4221fc46ceb471e27 Mon Sep 17 00:00:00 2001 From: Babbaj Date: Tue, 15 Aug 2023 01:14:53 -0400 Subject: [PATCH 274/276] make raytracer collide with unknown chunks --- build.gradle | 4 ++-- .../process/elytra/NetherPathfinderContext.java | 12 ++++++------ 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/build.gradle b/build.gradle index 0c8e58364..b9e486351 100755 --- a/build.gradle +++ b/build.gradle @@ -175,8 +175,8 @@ dependencies { transitive = false } launchAnnotationProcessor 'org.spongepowered:mixin:0.8.4-SNAPSHOT:processor' - launchImplementation('dev.babbaj:nether-pathfinder:1.2') - implementation 'dev.babbaj:nether-pathfinder:1.2' + launchImplementation('dev.babbaj:nether-pathfinder:1.3.0') + implementation 'dev.babbaj:nether-pathfinder:1.3.0' testImplementation 'junit:junit:4.12' } diff --git a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java index 93e0587f0..55a780a79 100644 --- a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java +++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java @@ -129,7 +129,7 @@ public final class NetherPathfinderContext { */ public boolean raytrace(final double startX, final double startY, final double startZ, final double endX, final double endY, final double endZ) { - return NetherPathfinder.isVisible(this.context, true, startX, startY, startZ, endX, endY, endZ); + return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, startX, startY, startZ, endX, endY, endZ); } /** @@ -141,24 +141,24 @@ public final class NetherPathfinderContext { * @return {@code true} if there is visibility between the points */ public boolean raytrace(final Vec3d start, final Vec3d end) { - return NetherPathfinder.isVisible(this.context, true, start.x, start.y, start.z, end.x, end.y, end.z); + return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, start.x, start.y, start.z, end.x, end.y, end.z); } public boolean raytrace(final int count, final double[] src, final double[] dst, final int visibility) { switch (visibility) { case Visibility.ALL: - return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, false) == -1; + return NetherPathfinder.isVisibleMulti(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, false) == -1; case Visibility.NONE: - return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) == -1; + return NetherPathfinder.isVisibleMulti(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, true) == -1; case Visibility.ANY: - return NetherPathfinder.isVisibleMulti(this.context, true, count, src, dst, true) != -1; + return NetherPathfinder.isVisibleMulti(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, true) != -1; default: throw new IllegalArgumentException("lol"); } } public void raytrace(final int count, final double[] src, final double[] dst, final boolean[] hitsOut, final double[] hitPosOut) { - NetherPathfinder.raytrace(this.context, true, count, src, dst, hitsOut, hitPosOut); + NetherPathfinder.raytrace(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, hitsOut, hitPosOut); } public void cancel() { From 661b16af7e651c4c5b98f73016faee7f201c57a4 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 14 Aug 2023 22:20:42 -0700 Subject: [PATCH 275/276] v1.2.18 --- build.gradle | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/build.gradle b/build.gradle index b9e486351..b91dcf43c 100755 --- a/build.gradle +++ b/build.gradle @@ -16,7 +16,7 @@ */ group 'baritone' -version '1.2.17' +version '1.2.18' buildscript { repositories { From ca4385da7a8cd002cc841a82606c8dd02fb7779b Mon Sep 17 00:00:00 2001 From: Leijurv Date: Mon, 14 Aug 2023 22:34:38 -0700 Subject: [PATCH 276/276] update readme --- README.md | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 674825c2b..bc3552c5a 100644 --- a/README.md +++ b/README.md @@ -60,10 +60,10 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s | Forge | Fabric | |---------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------| -| [1.12.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.2.17/baritone-api-forge-1.2.17.jar) | | -| [1.16.5 Forge](https://github.com/cabaletta/baritone/releases/download/v1.6.4/baritone-api-forge-1.6.4.jar) | [1.16.5 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.6.4/baritone-api-fabric-1.6.4.jar) | +| [1.12.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.2.18/baritone-api-forge-1.2.18.jar) | | +| [1.16.5 Forge](https://github.com/cabaletta/baritone/releases/download/v1.6.5/baritone-api-forge-1.6.5.jar) | [1.16.5 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.6.5/baritone-api-fabric-1.6.5.jar) | | [1.17.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.7.3/baritone-api-forge-1.7.3.jar) | [1.17.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.7.3/baritone-api-fabric-1.7.3.jar) | -| [1.18.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.8.4/baritone-api-forge-1.8.4.jar) | [1.18.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.8.4/baritone-api-fabric-1.8.4.jar) | +| [1.18.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.8.5/baritone-api-forge-1.8.5.jar) | [1.18.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.8.5/baritone-api-fabric-1.8.5.jar) | | [1.19.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.4/baritone-api-forge-1.9.4.jar) | [1.19.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.4/baritone-api-fabric-1.9.4.jar) | | [1.19.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.1/baritone-api-forge-1.9.1.jar) | [1.19.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.1/baritone-api-fabric-1.9.1.jar) | | [1.19.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-forge-1.9.3.jar) | [1.19.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-fabric-1.9.3.jar) | @@ -71,7 +71,7 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s **Message for 2b2t players looking for 1.19/1.20 Baritone** Download it from right above ^. But also please check back in a few days for Baritone Elytra ([vid 1](https://youtu.be/4bGGPo8yiHo) [vid 2](https://www.youtube.com/watch?v=pUN9nmINe3I)), which will be ported to 1.19/1.20 soon! It will work on 2b2t with its anticheat, that was the whole point of Baritone Elytra (it's fully vanilla compatible). Also join [**the discord**](http://discord.gg/s6fRBAUpmr). Thanks! -**How to immediately get started:** Type `#goto 1000 500` in chat to go to x=1000 z=500. Type `#mine diamond_ore` to mine diamond ore. Type `#stop` to stop. For more, read [the usage page](USAGE.md) and/or watch this [tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa) +**How to immediately get started:** Type `#goto 1000 500` in chat to go to x=1000 z=500. Type `#mine diamond_ore` to mine diamond ore. Type `#stop` to stop. For more, read [the usage page](USAGE.md) and/or watch this [tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa). Also try `#elytra` for Elytra flying in the Nether using fireworks. For other versions of Minecraft or more complicated situations or for development, see [Installation & setup](SETUP.md). Also consider just installing [Impact](https://impactclient.net/), which comes with Baritone and is easier to install than wrangling with version JSONs and zips. For 1.16.5, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it. There's a [showcase video](https://youtu.be/CZkLXWo4Fg4) made by @Adovin#6313 on Baritone which I recommend.