diff --git a/README.md b/README.md
index 8ae8090d7..c6a90ff93 100644
--- a/README.md
+++ b/README.md
@@ -4,14 +4,16 @@
-
-
-
-
-
-
-
-
+
+
+
+
+
+
+
+
+
+
@@ -64,6 +66,7 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s
| [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) |
+| [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) |
**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)
diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java
index 343fe823a..30506fd08 100644
--- a/src/api/java/baritone/api/Settings.java
+++ b/src/api/java/baritone/api/Settings.java
@@ -729,6 +729,12 @@ public final class Settings {
*/
public final Setting freeLook = new Setting<>(true);
+ /**
+ * Break and place blocks without having to force the client-sided rotations. Having this setting enabled implies
+ * {@link #freeLook}.
+ */
+ public final Setting blockFreeLook = new Setting<>(false);
+
/**
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
*
diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java
index 058a5dd88..218e8b59a 100644
--- a/src/api/java/baritone/api/behavior/ILookBehavior.java
+++ b/src/api/java/baritone/api/behavior/ILookBehavior.java
@@ -26,14 +26,11 @@ import baritone.api.utils.Rotation;
public interface ILookBehavior extends IBehavior {
/**
- * Updates the current {@link ILookBehavior} target to target
- * the specified rotations on the next tick. If force is {@code true},
- * then freeLook will be overriden and angles will be set regardless.
- * If any sort of block interaction is required, force should be {@code true},
- * otherwise, it should be {@code false};
+ * Updates the current {@link ILookBehavior} target to target the specified rotations on the next tick. If any sort
+ * of block interaction is required, {@code blockInteract} should be {@code true}.
*
- * @param rotation The target rotations
- * @param force Whether or not to "force" the rotations
+ * @param rotation The target rotations
+ * @param blockInteract Whether the target rotations are needed for a block interaction
*/
- void updateTarget(Rotation rotation, boolean force);
+ void updateTarget(Rotation rotation, boolean blockInteract);
}
diff --git a/src/api/java/baritone/api/command/datatypes/ForAxis.java b/src/api/java/baritone/api/command/datatypes/ForAxis.java
new file mode 100644
index 000000000..48efb39b7
--- /dev/null
+++ b/src/api/java/baritone/api/command/datatypes/ForAxis.java
@@ -0,0 +1,43 @@
+/*
+ * 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.command.datatypes;
+
+import baritone.api.command.exception.CommandException;
+import baritone.api.command.helpers.TabCompleteHelper;
+import net.minecraft.util.EnumFacing;
+
+import java.util.Locale;
+import java.util.stream.Stream;
+
+public enum ForAxis implements IDatatypeFor {
+ INSTANCE;
+
+ @Override
+ public EnumFacing.Axis get(IDatatypeContext ctx) throws CommandException {
+ return EnumFacing.Axis.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US));
+ }
+
+ @Override
+ public Stream tabComplete(IDatatypeContext ctx) throws CommandException {
+ return new TabCompleteHelper()
+ .append(Stream.of(EnumFacing.Axis.values())
+ .map(EnumFacing.Axis::getName).map(String::toLowerCase))
+ .filterPrefix(ctx.getConsumer().getString())
+ .stream();
+ }
+}
diff --git a/src/api/java/baritone/api/pathing/goals/GoalAxis.java b/src/api/java/baritone/api/pathing/goals/GoalAxis.java
index 7c9b26705..ad8fb892e 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalAxis.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalAxis.java
@@ -42,6 +42,11 @@ public class GoalAxis implements Goal {
return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.value + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.value, y);
}
+ @Override
+ public boolean equals(Object o) {
+ return o.getClass() == GoalAxis.class;
+ }
+
@Override
public String toString() {
return "GoalAxis";
diff --git a/src/api/java/baritone/api/pathing/goals/GoalBlock.java b/src/api/java/baritone/api/pathing/goals/GoalBlock.java
index bd339549b..d76fdc7af 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalBlock.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalBlock.java
@@ -66,6 +66,21 @@ public class GoalBlock implements Goal, IGoalRenderPos {
return calculate(xDiff, yDiff, zDiff);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalBlock goal = (GoalBlock) o;
+ return x == goal.x
+ && y == goal.y
+ && z == goal.z;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalComposite.java b/src/api/java/baritone/api/pathing/goals/GoalComposite.java
index 47522492b..d64f8e33e 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalComposite.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalComposite.java
@@ -67,6 +67,19 @@ public class GoalComposite implements Goal {
return min;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalComposite goal = (GoalComposite) o;
+ return Arrays.equals(goals, goal.goals);
+ }
+
@Override
public String toString() {
return "GoalComposite" + Arrays.toString(goals);
diff --git a/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java b/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java
index 8d6fdcb30..b5caafa48 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java
@@ -60,6 +60,21 @@ public class GoalGetToBlock implements Goal, IGoalRenderPos {
return GoalBlock.calculate(xDiff, yDiff < 0 ? yDiff + 1 : yDiff, zDiff);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalGetToBlock goal = (GoalGetToBlock) o;
+ return x == goal.x
+ && y == goal.y
+ && z == goal.z;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalInverted.java b/src/api/java/baritone/api/pathing/goals/GoalInverted.java
index 354e2ce39..e559088ef 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalInverted.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalInverted.java
@@ -17,6 +17,8 @@
package baritone.api.pathing.goals;
+import java.util.Objects;
+
/**
* Invert any goal.
*
@@ -50,6 +52,19 @@ public class GoalInverted implements Goal {
return Double.NEGATIVE_INFINITY;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalInverted goal = (GoalInverted) o;
+ return Objects.equals(origin, goal.origin);
+ }
+
@Override
public String toString() {
return String.format("GoalInverted{%s}", origin.toString());
diff --git a/src/api/java/baritone/api/pathing/goals/GoalNear.java b/src/api/java/baritone/api/pathing/goals/GoalNear.java
index 2252446cd..166138ff4 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalNear.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalNear.java
@@ -86,6 +86,22 @@ public class GoalNear implements Goal, IGoalRenderPos {
return new BlockPos(x, y, z);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalNear goal = (GoalNear) o;
+ return x == goal.x
+ && y == goal.y
+ && z == goal.z
+ && rangeSq == goal.rangeSq;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java
index b704ae4a6..166ad5a98 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java
@@ -23,6 +23,7 @@ import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
import net.minecraft.util.math.BlockPos;
import java.util.Arrays;
+import java.util.Objects;
/**
* Useful for automated combat (retreating specifically)
@@ -124,6 +125,21 @@ public class GoalRunAway implements Goal {
return maxInside;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalRunAway goal = (GoalRunAway) o;
+ return distanceSq == goal.distanceSq
+ && Arrays.equals(from, goal.from)
+ && Objects.equals(maintainY, goal.maintainY);
+ }
+
@Override
public String toString() {
if (maintainY != null) {
diff --git a/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java b/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java
index e93f47ac0..b8e4b43b2 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java
@@ -69,6 +69,23 @@ public class GoalStrictDirection implements Goal {
return Double.NEGATIVE_INFINITY;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalStrictDirection goal = (GoalStrictDirection) o;
+ return x == goal.x
+ && y == goal.y
+ && z == goal.z
+ && dx == goal.dx
+ && dz == goal.dz;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java b/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java
index 27be981e4..d6fff33a2 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java
@@ -72,6 +72,21 @@ public class GoalTwoBlocks implements Goal, IGoalRenderPos {
return new BlockPos(x, y, z);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalTwoBlocks goal = (GoalTwoBlocks) o;
+ return x == goal.x
+ && y == goal.y
+ && z == goal.z;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalXZ.java b/src/api/java/baritone/api/pathing/goals/GoalXZ.java
index 63d39cd78..2c551d395 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalXZ.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalXZ.java
@@ -64,6 +64,19 @@ public class GoalXZ implements Goal {
return calculate(xDiff, zDiff);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalXZ goal = (GoalXZ) o;
+ return x == goal.x && z == goal.z;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/pathing/goals/GoalYLevel.java b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
index 603ef9bd1..37745e8de 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
@@ -58,6 +58,19 @@ public class GoalYLevel implements Goal, ActionCosts {
return 0;
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ GoalYLevel goal = (GoalYLevel) o;
+ return level == goal.level;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/schematic/MaskSchematic.java b/src/api/java/baritone/api/schematic/MaskSchematic.java
index 229f58d5b..2853c6e58 100644
--- a/src/api/java/baritone/api/schematic/MaskSchematic.java
+++ b/src/api/java/baritone/api/schematic/MaskSchematic.java
@@ -17,6 +17,7 @@
package baritone.api.schematic;
+import baritone.api.schematic.mask.Mask;
import net.minecraft.block.state.IBlockState;
import java.util.List;
@@ -41,4 +42,14 @@ public abstract class MaskSchematic extends AbstractSchematic {
public IBlockState desiredState(int x, int y, int z, IBlockState current, List approxPlaceable) {
return schematic.desiredState(x, y, z, current, approxPlaceable);
}
+
+ public static MaskSchematic create(ISchematic schematic, Mask function) {
+ return new MaskSchematic(schematic) {
+
+ @Override
+ protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
+ return function.partOfMask(x, y, z, currentState);
+ }
+ };
+ }
}
diff --git a/src/api/java/baritone/api/schematic/mask/AbstractMask.java b/src/api/java/baritone/api/schematic/mask/AbstractMask.java
new file mode 100644
index 000000000..ce92af0ec
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/AbstractMask.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.schematic.mask;
+
+/**
+ * @author Brady
+ */
+public abstract class AbstractMask implements Mask {
+
+ private final int widthX;
+ private final int heightY;
+ private final int lengthZ;
+
+ public AbstractMask(int widthX, int heightY, int lengthZ) {
+ this.widthX = widthX;
+ this.heightY = heightY;
+ this.lengthZ = lengthZ;
+ }
+
+ @Override
+ public int widthX() {
+ return this.widthX;
+ }
+
+ @Override
+ public int heightY() {
+ return this.heightY;
+ }
+
+ @Override
+ public int lengthZ() {
+ return this.lengthZ;
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/Mask.java b/src/api/java/baritone/api/schematic/mask/Mask.java
new file mode 100644
index 000000000..7df6f8f04
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/Mask.java
@@ -0,0 +1,60 @@
+/*
+ * 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.schematic.mask;
+
+import baritone.api.schematic.mask.operator.BinaryOperatorMask;
+import baritone.api.schematic.mask.operator.NotMask;
+import baritone.api.utils.BooleanBinaryOperators;
+import net.minecraft.block.state.IBlockState;
+
+/**
+ * @author Brady
+ */
+public interface Mask {
+
+ /**
+ * @param x The relative x position of the block
+ * @param y The relative y position of the block
+ * @param z The relative z position of the block
+ * @param currentState The current state of that block in the world, may be {@code null}
+ * @return Whether the given position is included in this mask
+ */
+ boolean partOfMask(int x, int y, int z, IBlockState currentState);
+
+ int widthX();
+
+ int heightY();
+
+ int lengthZ();
+
+ default Mask not() {
+ return new NotMask(this);
+ }
+
+ default Mask union(Mask other) {
+ return new BinaryOperatorMask(this, other, BooleanBinaryOperators.OR);
+ }
+
+ default Mask intersection(Mask other) {
+ return new BinaryOperatorMask(this, other, BooleanBinaryOperators.AND);
+ }
+
+ default Mask xor(Mask other) {
+ return new BinaryOperatorMask(this, other, BooleanBinaryOperators.XOR);
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/PreComputedMask.java b/src/api/java/baritone/api/schematic/mask/PreComputedMask.java
new file mode 100644
index 000000000..aed26cc94
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/PreComputedMask.java
@@ -0,0 +1,44 @@
+/*
+ * 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.schematic.mask;
+
+/**
+ * @author Brady
+ */
+final class PreComputedMask extends AbstractMask implements StaticMask {
+
+ private final boolean[][][] mask;
+
+ public PreComputedMask(StaticMask mask) {
+ super(mask.widthX(), mask.heightY(), mask.lengthZ());
+
+ this.mask = new boolean[this.heightY()][this.lengthZ()][this.widthX()];
+ for (int y = 0; y < this.heightY(); y++) {
+ for (int z = 0; z < this.lengthZ(); z++) {
+ for (int x = 0; x < this.widthX(); x++) {
+ this.mask[y][z][x] = mask.partOfMask(x, y, z);
+ }
+ }
+ }
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z) {
+ return this.mask[y][z][x];
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/StaticMask.java b/src/api/java/baritone/api/schematic/mask/StaticMask.java
new file mode 100644
index 000000000..220a94828
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/StaticMask.java
@@ -0,0 +1,82 @@
+/*
+ * 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.schematic.mask;
+
+import baritone.api.schematic.mask.operator.BinaryOperatorMask;
+import baritone.api.schematic.mask.operator.NotMask;
+import baritone.api.utils.BooleanBinaryOperators;
+import net.minecraft.block.state.IBlockState;
+
+/**
+ * A mask that is context-free. In other words, it doesn't require the current block state to determine if a relative
+ * position is a part of the mask.
+ *
+ * @author Brady
+ */
+public interface StaticMask extends Mask {
+
+ /**
+ * Determines if a given relative coordinate is included in this mask, without the need for the current block state.
+ *
+ * @param x The relative x position of the block
+ * @param y The relative y position of the block
+ * @param z The relative z position of the block
+ * @return Whether the given position is included in this mask
+ */
+ boolean partOfMask(int x, int y, int z);
+
+ /**
+ * Implements the parent {@link Mask#partOfMask partOfMask function} by calling the static function
+ * provided in this functional interface without needing the {@link IBlockState} argument. This {@code default}
+ * implementation should NOT be overriden.
+ *
+ * @param x The relative x position of the block
+ * @param y The relative y position of the block
+ * @param z The relative z position of the block
+ * @param currentState The current state of that block in the world, may be {@code null}
+ * @return Whether the given position is included in this mask
+ */
+ @Override
+ default boolean partOfMask(int x, int y, int z, IBlockState currentState) {
+ return this.partOfMask(x, y, z);
+ }
+
+ @Override
+ default StaticMask not() {
+ return new NotMask.Static(this);
+ }
+
+ default StaticMask union(StaticMask other) {
+ return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.OR);
+ }
+
+ default StaticMask intersection(StaticMask other) {
+ return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.AND);
+ }
+
+ default StaticMask xor(StaticMask other) {
+ return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.XOR);
+ }
+
+ /**
+ * Returns a pre-computed mask using {@code this} function, with the specified size parameters.
+ */
+ default StaticMask compute() {
+ return new PreComputedMask(this);
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java
new file mode 100644
index 000000000..e591c7873
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java
@@ -0,0 +1,71 @@
+/*
+ * 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.schematic.mask.operator;
+
+import baritone.api.schematic.mask.AbstractMask;
+import baritone.api.schematic.mask.Mask;
+import baritone.api.schematic.mask.StaticMask;
+import baritone.api.utils.BooleanBinaryOperator;
+import net.minecraft.block.state.IBlockState;
+
+/**
+ * @author Brady
+ */
+public final class BinaryOperatorMask extends AbstractMask {
+
+ private final Mask a;
+ private final Mask b;
+ private final BooleanBinaryOperator operator;
+
+ public BinaryOperatorMask(Mask a, Mask b, BooleanBinaryOperator operator) {
+ super(a.widthX(), a.heightY(), a.lengthZ());
+ this.a = a;
+ this.b = b;
+ this.operator = operator;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z, IBlockState currentState) {
+ return this.operator.applyAsBoolean(
+ this.a.partOfMask(x, y, z, currentState),
+ this.b.partOfMask(x, y, z, currentState)
+ );
+ }
+
+ public static final class Static extends AbstractMask implements StaticMask {
+
+ private final StaticMask a;
+ private final StaticMask b;
+ private final BooleanBinaryOperator operator;
+
+ public Static(StaticMask a, StaticMask b, BooleanBinaryOperator operator) {
+ super(a.widthX(), a.heightY(), a.lengthZ());
+ this.a = a;
+ this.b = b;
+ this.operator = operator;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z) {
+ return this.operator.applyAsBoolean(
+ this.a.partOfMask(x, y, z),
+ this.b.partOfMask(x, y, z)
+ );
+ }
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/operator/NotMask.java b/src/api/java/baritone/api/schematic/mask/operator/NotMask.java
new file mode 100644
index 000000000..f9f770b82
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/operator/NotMask.java
@@ -0,0 +1,56 @@
+/*
+ * 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.schematic.mask.operator;
+
+import baritone.api.schematic.mask.AbstractMask;
+import baritone.api.schematic.mask.Mask;
+import baritone.api.schematic.mask.StaticMask;
+import net.minecraft.block.state.IBlockState;
+
+/**
+ * @author Brady
+ */
+public final class NotMask extends AbstractMask {
+
+ private final Mask source;
+
+ public NotMask(Mask source) {
+ super(source.widthX(), source.heightY(), source.lengthZ());
+ this.source = source;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z, IBlockState currentState) {
+ return !this.source.partOfMask(x, y, z, currentState);
+ }
+
+ public static final class Static extends AbstractMask implements StaticMask {
+
+ private final StaticMask source;
+
+ public Static(StaticMask source) {
+ super(source.widthX(), source.heightY(), source.lengthZ());
+ this.source = source;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z) {
+ return !this.source.partOfMask(x, y, z);
+ }
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java b/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java
new file mode 100644
index 000000000..71b0d43c9
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java
@@ -0,0 +1,69 @@
+/*
+ * 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.schematic.mask.shape;
+
+import baritone.api.schematic.mask.AbstractMask;
+import baritone.api.schematic.mask.StaticMask;
+import net.minecraft.util.EnumFacing;
+
+/**
+ * @author Brady
+ */
+public final class CylinderMask extends AbstractMask implements StaticMask {
+
+ private final double centerA;
+ private final double centerB;
+ private final double radiusSqA;
+ private final double radiusSqB;
+ private final boolean filled;
+ private final EnumFacing.Axis alignment;
+
+ public CylinderMask(int widthX, int heightY, int lengthZ, boolean filled, EnumFacing.Axis alignment) {
+ super(widthX, heightY, lengthZ);
+ this.centerA = this.getA(widthX, heightY) / 2.0;
+ this.centerB = this.getB(heightY, lengthZ) / 2.0;
+ this.radiusSqA = (this.centerA - 1) * (this.centerA - 1);
+ this.radiusSqB = (this.centerB - 1) * (this.centerB - 1);
+ this.filled = filled;
+ this.alignment = alignment;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z) {
+ double da = Math.abs((this.getA(x, y) + 0.5) - this.centerA);
+ double db = Math.abs((this.getB(y, z) + 0.5) - this.centerB);
+ if (this.outside(da, db)) {
+ return false;
+ }
+ return this.filled
+ || this.outside(da + 1, db)
+ || this.outside(da, db + 1);
+ }
+
+ private boolean outside(double da, double db) {
+ return da * da / this.radiusSqA + db * db / this.radiusSqB > 1;
+ }
+
+ private int getA(int x, int y) {
+ return this.alignment == EnumFacing.Axis.X ? y : x;
+ }
+
+ private int getB(int y, int z) {
+ return this.alignment == EnumFacing.Axis.Z ? y : z;
+ }
+}
diff --git a/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java b/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java
new file mode 100644
index 000000000..d805c98a8
--- /dev/null
+++ b/src/api/java/baritone/api/schematic/mask/shape/SphereMask.java
@@ -0,0 +1,64 @@
+/*
+ * 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.schematic.mask.shape;
+
+import baritone.api.schematic.mask.AbstractMask;
+import baritone.api.schematic.mask.StaticMask;
+
+/**
+ * @author Brady
+ */
+public final class SphereMask extends AbstractMask implements StaticMask {
+
+ private final double centerX;
+ private final double centerY;
+ private final double centerZ;
+ private final double radiusSqX;
+ private final double radiusSqY;
+ private final double radiusSqZ;
+ private final boolean filled;
+
+ public SphereMask(int widthX, int heightY, int lengthZ, boolean filled) {
+ super(widthX, heightY, lengthZ);
+ this.centerX = widthX / 2.0;
+ this.centerY = heightY / 2.0;
+ this.centerZ = lengthZ / 2.0;
+ this.radiusSqX = this.centerX * this.centerX;
+ this.radiusSqY = this.centerY * this.centerY;
+ this.radiusSqZ = this.centerZ * this.centerZ;
+ this.filled = filled;
+ }
+
+ @Override
+ public boolean partOfMask(int x, int y, int z) {
+ double dx = Math.abs((x + 0.5) - this.centerX);
+ double dy = Math.abs((y + 0.5) - this.centerY);
+ double dz = Math.abs((z + 0.5) - this.centerZ);
+ if (this.outside(dx, dy, dz)) {
+ return false;
+ }
+ return this.filled
+ || this.outside(dx + 1, dy, dz)
+ || this.outside(dx, dy + 1, dz)
+ || this.outside(dx, dy, dz + 1);
+ }
+
+ private boolean outside(double dx, double dy, double dz) {
+ return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1;
+ }
+}
diff --git a/src/api/java/baritone/api/utils/BooleanBinaryOperator.java b/src/api/java/baritone/api/utils/BooleanBinaryOperator.java
new file mode 100644
index 000000000..cfb85e644
--- /dev/null
+++ b/src/api/java/baritone/api/utils/BooleanBinaryOperator.java
@@ -0,0 +1,27 @@
+/*
+ * 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;
+
+/**
+ * @author Brady
+ */
+@FunctionalInterface
+public interface BooleanBinaryOperator {
+
+ boolean applyAsBoolean(boolean a, boolean b);
+}
diff --git a/src/api/java/baritone/api/utils/BooleanBinaryOperators.java b/src/api/java/baritone/api/utils/BooleanBinaryOperators.java
new file mode 100644
index 000000000..11605c965
--- /dev/null
+++ b/src/api/java/baritone/api/utils/BooleanBinaryOperators.java
@@ -0,0 +1,38 @@
+/*
+ * 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;
+
+/**
+ * @author Brady
+ */
+public enum BooleanBinaryOperators implements BooleanBinaryOperator {
+ OR((a, b) -> a || b),
+ AND((a, b) -> a && b),
+ XOR((a, b) -> a ^ b);
+
+ private final BooleanBinaryOperator op;
+
+ BooleanBinaryOperators(BooleanBinaryOperator op) {
+ this.op = op;
+ }
+
+ @Override
+ public boolean applyAsBoolean(boolean a, boolean b) {
+ return this.op.applyAsBoolean(a, b);
+ }
+}
diff --git a/src/api/java/baritone/api/utils/Rotation.java b/src/api/java/baritone/api/utils/Rotation.java
index 54f63ebfa..8dab287de 100644
--- a/src/api/java/baritone/api/utils/Rotation.java
+++ b/src/api/java/baritone/api/utils/Rotation.java
@@ -26,12 +26,12 @@ public class Rotation {
/**
* The yaw angle of this Rotation
*/
- private float yaw;
+ private final float yaw;
/**
* The pitch angle of this Rotation
*/
- private float pitch;
+ private final float pitch;
public Rotation(float yaw, float pitch) {
this.yaw = yaw;
@@ -110,6 +110,10 @@ public class Rotation {
);
}
+ public Rotation withPitch(float pitch) {
+ return new Rotation(this.yaw, pitch);
+ }
+
/**
* Is really close to
*
diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java
index 39e68fd4f..1991ab878 100644
--- a/src/api/java/baritone/api/utils/RotationUtils.java
+++ b/src/api/java/baritone/api/utils/RotationUtils.java
@@ -134,14 +134,14 @@ public final class RotationUtils {
* @param ctx Context for the viewing entity
* @param pos The target block position
* @return The optional rotation
- * @see #reachable(EntityPlayerSP, BlockPos, double)
+ * @see #reachable(IPlayerContext, BlockPos, double)
*/
public static Optional reachable(IPlayerContext ctx, BlockPos pos) {
- return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
+ return reachable(ctx, pos, false);
}
public static Optional reachable(IPlayerContext ctx, BlockPos pos, boolean wouldSneak) {
- return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
+ return reachable(ctx, pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
}
/**
@@ -151,18 +151,17 @@ public final class RotationUtils {
* side that is reachable. The return type will be {@link Optional#empty()} if the entity is
* unable to reach any of the sides of the block.
*
- * @param entity The viewing entity
+ * @param ctx Context for the viewing entity
* @param pos The target block position
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
- public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
- return reachable(entity, pos, blockReachDistance, false);
+ public static Optional reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance) {
+ return reachable(ctx, pos, blockReachDistance, false);
}
- public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
- IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
- if (baritone.getPlayerContext().isLookingAt(pos)) {
+ public static Optional reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
+ if (ctx.isLookingAt(pos)) {
/*
* why add 0.0001?
* to indicate that we actually have a desired pitch
@@ -173,10 +172,10 @@ public final class RotationUtils {
*
* or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level
*/
- Rotation hypothetical = new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F);
+ Rotation hypothetical = ctx.playerRotations().add(new Rotation(0, 0.0001F));
if (wouldSneak) {
// the concern here is: what if we're looking at it now, but as soon as we start sneaking we no longer are
- RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, hypothetical, blockReachDistance, true);
+ RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), hypothetical, blockReachDistance, true);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(pos)) {
return Optional.of(hypothetical); // yes, if we sneaked we would still be looking at the block
}
@@ -184,19 +183,19 @@ public final class RotationUtils {
return Optional.of(hypothetical);
}
}
- Optional possibleRotation = reachableCenter(entity, pos, blockReachDistance, wouldSneak);
+ Optional possibleRotation = reachableCenter(ctx, pos, blockReachDistance, wouldSneak);
//System.out.println("center: " + possibleRotation);
if (possibleRotation.isPresent()) {
return possibleRotation;
}
- IBlockState state = entity.world.getBlockState(pos);
- AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
+ IBlockState state = ctx.world().getBlockState(pos);
+ AxisAlignedBB aabb = state.getBoundingBox(ctx.world(), pos);
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
- possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
+ possibleRotation = reachableOffset(ctx, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
if (possibleRotation.isPresent()) {
return possibleRotation;
}
@@ -209,12 +208,54 @@ public final class RotationUtils {
* the given offsetted position. The return type will be {@link Optional#empty()} if
* the entity is unable to reach the block with the offset applied.
*
- * @param entity The viewing entity
+ * @param ctx Context for the viewing entity
* @param pos The target block position
* @param offsetPos The position of the block with the offset applied.
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
+ public static Optional reachableOffset(IPlayerContext ctx, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) {
+ Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.player().getPositionEyes(1.0F);
+ Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, ctx.playerRotations());
+ RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rotation, blockReachDistance, wouldSneak);
+ //System.out.println(result);
+ if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
+ if (result.getBlockPos().equals(pos)) {
+ return Optional.of(rotation);
+ }
+ if (ctx.world().getBlockState(pos).getBlock() instanceof BlockFire && result.getBlockPos().equals(pos.down())) {
+ return Optional.of(rotation);
+ }
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Determines if the specified entity is able to reach the specified block where it is
+ * looking at the direct center of it's hitbox.
+ *
+ * @param ctx Context for the viewing entity
+ * @param pos The target block position
+ * @param blockReachDistance The block reach distance of the entity
+ * @return The optional rotation
+ */
+ public static Optional reachableCenter(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
+ return reachableOffset(ctx, pos, VecUtils.calculateBlockCenter(ctx.world(), pos), blockReachDistance, wouldSneak);
+ }
+
+ @Deprecated
+ public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
+ return reachable(entity, pos, blockReachDistance, false);
+ }
+
+ @Deprecated
+ public static Optional reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
+ IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
+ IPlayerContext ctx = baritone.getPlayerContext();
+ return reachable(ctx, pos, blockReachDistance, wouldSneak);
+ }
+
+ @Deprecated
public static Optional reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) {
Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(entity) : entity.getPositionEyes(1.0F);
Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
@@ -231,15 +272,7 @@ public final class RotationUtils {
return Optional.empty();
}
- /**
- * Determines if the specified entity is able to reach the specified block where it is
- * looking at the direct center of it's hitbox.
- *
- * @param entity The viewing entity
- * @param pos The target block position
- * @param blockReachDistance The block reach distance of the entity
- * @return The optional rotation
- */
+ @Deprecated
public static Optional reachableCenter(Entity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.world, pos), blockReachDistance, wouldSneak);
}
diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java
index 32e5c22f5..99e496e6f 100644
--- a/src/main/java/baritone/behavior/LookBehavior.java
+++ b/src/main/java/baritone/behavior/LookBehavior.java
@@ -20,40 +20,43 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.Settings;
import baritone.api.behavior.ILookBehavior;
+import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RotationMoveEvent;
+import baritone.api.event.events.WorldEvent;
+import baritone.api.utils.Helper;
+import baritone.api.utils.IPlayerContext;
import baritone.api.utils.Rotation;
+import net.minecraft.network.play.client.CPacketPlayer;
+
+import java.util.Optional;
public final class LookBehavior extends Behavior implements ILookBehavior {
/**
- * Target's values are as follows:
- *
- * getFirst() -> yaw
- * getSecond() -> pitch
+ * The current look target, may be {@code null}.
*/
- private Rotation target;
+ private Target target;
/**
- * Whether or not rotations are currently being forced
+ * The rotation known to the server. Returned by {@link #getEffectiveRotation()} for use in {@link IPlayerContext}.
*/
- private boolean force;
+ private Rotation serverRotation;
/**
- * The last player yaw angle. Used when free looking
+ * The last player rotation. Used when free looking
*
* @see Settings#freeLook
*/
- private float lastYaw;
+ private Rotation prevRotation;
public LookBehavior(Baritone baritone) {
super(baritone);
}
@Override
- public void updateTarget(Rotation target, boolean force) {
- this.target = target;
- this.force = force || !Baritone.settings().freeLook.value;
+ public void updateTarget(Rotation rotation, boolean blockInteract) {
+ this.target = new Target(rotation, blockInteract);
}
@Override
@@ -61,35 +64,48 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
if (this.target == null) {
return;
}
-
- // Whether or not we're going to silently set our angles
- boolean silent = Baritone.settings().antiCheatCompatibility.value && !this.force;
-
switch (event.getState()) {
case PRE: {
- if (this.force) {
- ctx.player().rotationYaw = this.target.getYaw();
- float oldPitch = ctx.player().rotationPitch;
- float desiredPitch = this.target.getPitch();
- ctx.player().rotationPitch = desiredPitch;
- ctx.player().rotationYaw += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
- ctx.player().rotationPitch += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
- if (desiredPitch == oldPitch && !Baritone.settings().freeLook.value) {
- nudgeToLevel();
- }
- this.target = null;
+ if (this.target.mode == Target.Mode.NONE) {
+ return;
}
- if (silent) {
- this.lastYaw = ctx.player().rotationYaw;
- ctx.player().rotationYaw = this.target.getYaw();
+ if (this.target.mode == Target.Mode.SERVER) {
+ this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch);
+ }
+
+ final float oldYaw = ctx.playerRotations().getYaw();
+ final float oldPitch = ctx.playerRotations().getPitch();
+
+ float desiredYaw = this.target.rotation.getYaw();
+ float desiredPitch = this.target.rotation.getPitch();
+
+ // In other words, the target doesn't care about the pitch, so it used playerRotations().getPitch()
+ // and it's safe to adjust it to a normal level
+ if (desiredPitch == oldPitch) {
+ desiredPitch = nudgeToLevel(desiredPitch);
+ }
+
+ desiredYaw += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
+ desiredPitch += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
+
+ ctx.player().rotationYaw = calculateMouseMove(oldYaw, desiredYaw);
+ ctx.player().rotationPitch = calculateMouseMove(oldPitch, desiredPitch);
+
+ if (this.target.mode == Target.Mode.CLIENT) {
+ // The target can be invalidated now since it won't be needed for RotationMoveEvent
+ this.target = null;
}
break;
}
case POST: {
- if (silent) {
- ctx.player().rotationYaw = this.lastYaw;
- this.target = null;
+ // 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();
+ this.prevRotation = null;
}
+ // The target is done being used for this game tick, so it can be invalidated
+ this.target = null;
break;
}
default:
@@ -97,34 +113,116 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
}
}
+ @Override
+ public void onSendPacket(PacketEvent event) {
+ if (!(event.getPacket() instanceof CPacketPlayer)) {
+ return;
+ }
+
+ final CPacketPlayer packet = (CPacketPlayer) event.getPacket();
+ if (packet instanceof CPacketPlayer.Rotation || packet instanceof CPacketPlayer.PositionRotation) {
+ this.serverRotation = new Rotation(packet.getYaw(0.0f), packet.getPitch(0.0f));
+ }
+ }
+
+ @Override
+ public void onWorldEvent(WorldEvent event) {
+ this.serverRotation = null;
+ this.target = null;
+ }
+
public void pig() {
if (this.target != null) {
- ctx.player().rotationYaw = this.target.getYaw();
+ ctx.player().rotationYaw = this.target.rotation.getYaw();
}
}
+ public Optional getEffectiveRotation() {
+ if (Baritone.settings().freeLook.value || Baritone.settings().blockFreeLook.value) {
+ return Optional.ofNullable(this.serverRotation);
+ }
+ // If neither of the freeLook settings are on, just defer to the player's actual rotations
+ return Optional.empty();
+ }
+
@Override
public void onPlayerRotationMove(RotationMoveEvent event) {
if (this.target != null) {
-
- event.setYaw(this.target.getYaw());
-
- // If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
- // Also the type has to be MOTION_UPDATE because that is called after JUMP
- if (!Baritone.settings().antiCheatCompatibility.value && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE && !this.force) {
- this.target = null;
- }
+ event.setYaw(this.target.rotation.getYaw());
}
}
/**
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
*/
- private void nudgeToLevel() {
- if (ctx.player().rotationPitch < -20) {
- ctx.player().rotationPitch++;
- } else if (ctx.player().rotationPitch > 10) {
- ctx.player().rotationPitch--;
+ private static float nudgeToLevel(float pitch) {
+ if (pitch < -20) {
+ return pitch + 1;
+ } else if (pitch > 10) {
+ return pitch - 1;
+ }
+ return pitch;
+ }
+
+ private static float calculateMouseMove(float current, float target) {
+ final float delta = target - current;
+ final int deltaPx = angleToMouse(delta);
+ return current + mouseToAngle(deltaPx);
+ }
+
+ private static int angleToMouse(float angleDelta) {
+ final float minAngleChange = mouseToAngle(1);
+ return Math.round(angleDelta / minAngleChange);
+ }
+
+ private static float mouseToAngle(int mouseDelta) {
+ final float f = Helper.mc.gameSettings.mouseSensitivity * 0.6f + 0.2f;
+ return mouseDelta * f * f * f * 8.0f * 0.15f;
+ }
+
+ private static class Target {
+
+ public final Rotation rotation;
+ public final Mode mode;
+
+ public Target(Rotation rotation, boolean blockInteract) {
+ this.rotation = rotation;
+ this.mode = Mode.resolve(blockInteract);
+ }
+
+ enum Mode {
+ /**
+ * Rotation will be set client-side and is visual to the player
+ */
+ CLIENT,
+
+ /**
+ * Rotation will be set server-side and is silent to the player
+ */
+ SERVER,
+
+ /**
+ * Rotation will remain unaffected on both the client and server
+ */
+ NONE;
+
+ static Mode resolve(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 (!freeLook && !blockFreeLook) 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.
+ if (antiCheat || blockInteract) return SERVER;
+
+ // Pathing regularly without antiCheatCompatibility, don't set the player rotation
+ return NONE;
+ }
}
}
}
diff --git a/src/main/java/baritone/command/defaults/GoalCommand.java b/src/main/java/baritone/command/defaults/GoalCommand.java
index 40822e057..a174ecad9 100644
--- a/src/main/java/baritone/command/defaults/GoalCommand.java
+++ b/src/main/java/baritone/command/defaults/GoalCommand.java
@@ -51,7 +51,7 @@ public class GoalCommand extends Command {
}
} else {
args.requireMax(3);
- BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
+ BetterBlockPos origin = ctx.playerFeet();
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
goalProcess.setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));
diff --git a/src/main/java/baritone/command/defaults/GotoCommand.java b/src/main/java/baritone/command/defaults/GotoCommand.java
index 896e3f5f8..333d7fa57 100644
--- a/src/main/java/baritone/command/defaults/GotoCommand.java
+++ b/src/main/java/baritone/command/defaults/GotoCommand.java
@@ -46,7 +46,7 @@ public class GotoCommand extends Command {
// is no need to handle the case of empty arguments.
if (args.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) {
args.requireMax(3);
- BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
+ BetterBlockPos origin = ctx.playerFeet();
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
logDirect(String.format("Going to: %s", goal.toString()));
baritone.getCustomGoalProcess().setGoalAndPath(goal);
diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java
index 5677eec3c..9abe417ac 100644
--- a/src/main/java/baritone/command/defaults/SelCommand.java
+++ b/src/main/java/baritone/command/defaults/SelCommand.java
@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
+import baritone.api.command.datatypes.ForAxis;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.datatypes.ForEnumFacing;
import baritone.api.command.datatypes.RelativeBlockPos;
@@ -31,6 +32,8 @@ import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.schematic.*;
+import baritone.api.schematic.mask.shape.CylinderMask;
+import baritone.api.schematic.mask.shape.SphereMask;
import baritone.api.selection.ISelection;
import baritone.api.selection.ISelectionManager;
import baritone.api.utils.BetterBlockPos;
@@ -50,6 +53,7 @@ import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.function.Function;
+import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class SelCommand extends Command {
@@ -72,7 +76,7 @@ public class SelCommand extends Command {
float lineWidth = Baritone.settings().selectionLineWidth.value;
boolean ignoreDepth = Baritone.settings().renderSelectionIgnoreDepth.value;
IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
- IRenderer.drawAABB(new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
+ IRenderer.emitAABB(new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
IRenderer.endLines(ignoreDepth);
}
});
@@ -117,11 +121,13 @@ public class SelCommand extends Command {
logDirect("Undid pos2");
}
}
- } else if (action == Action.SET || action == Action.WALLS || action == Action.SHELL || action == Action.CLEARAREA || action == Action.REPLACE) {
+ } else if (action.isFillAction()) {
BlockOptionalMeta type = action == Action.CLEARAREA
? new BlockOptionalMeta(Blocks.AIR)
: args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
- BlockOptionalMetaLookup replaces = null;
+
+ final BlockOptionalMetaLookup replaces; // Action.REPLACE
+ final EnumFacing.Axis alignment; // Action.(H)CYLINDER
if (action == Action.REPLACE) {
args.requireMin(1);
List replacesList = new ArrayList<>();
@@ -131,8 +137,15 @@ public class SelCommand extends Command {
}
type = args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0]));
+ alignment = null;
+ } else if (action == Action.CYLINDER || action == Action.HCYLINDER) {
+ args.requireMax(1);
+ alignment = args.hasAny() ? args.getDatatypeFor(ForAxis.INSTANCE) : EnumFacing.Axis.Y;
+ replaces = null;
} else {
args.requireMax(0);
+ replaces = null;
+ alignment = null;
}
ISelection[] selections = manager.getSelections();
if (selections.length == 0) {
@@ -151,14 +164,35 @@ public class SelCommand extends Command {
for (ISelection selection : selections) {
Vec3i size = selection.size();
BetterBlockPos min = selection.min();
- ISchematic schematic = new FillSchematic(size.getX(), size.getY(), size.getZ(), type);
- if (action == Action.WALLS) {
- schematic = new WallsSchematic(schematic);
- } else if (action == Action.SHELL) {
- schematic = new ShellSchematic(schematic);
- } else if (action == Action.REPLACE) {
- schematic = new ReplaceSchematic(schematic, replaces);
- }
+
+ // Java 8 so no switch expressions 😿
+ UnaryOperator create = fill -> {
+ final int w = fill.widthX();
+ final int h = fill.heightY();
+ final int l = fill.lengthZ();
+
+ switch (action) {
+ case WALLS:
+ return new WallsSchematic(fill);
+ case SHELL:
+ return new ShellSchematic(fill);
+ case REPLACE:
+ return new ReplaceSchematic(fill, replaces);
+ case SPHERE:
+ return MaskSchematic.create(fill, new SphereMask(w, h, l, true).compute());
+ case HSPHERE:
+ return MaskSchematic.create(fill, new SphereMask(w, h, l, false).compute());
+ case CYLINDER:
+ return MaskSchematic.create(fill, new CylinderMask(w, h, l, true, alignment).compute());
+ case HCYLINDER:
+ return MaskSchematic.create(fill, new CylinderMask(w, h, l, false, alignment).compute());
+ default:
+ // Silent fail
+ return fill;
+ }
+ };
+
+ ISchematic schematic = create.apply(new FillSchematic(size.getX(), size.getY(), size.getZ(), type));
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
}
baritone.getBuilderProcess().build("Fill", composite, origin);
@@ -254,12 +288,15 @@ public class SelCommand extends Command {
if (args.hasAtMost(3)) {
return args.tabCompleteDatatype(RelativeBlockPos.INSTANCE);
}
- } else if (action == Action.SET || action == Action.WALLS || action == Action.CLEARAREA || action == Action.REPLACE) {
+ } else if (action.isFillAction()) {
if (args.hasExactlyOne() || action == Action.REPLACE) {
while (args.has(2)) {
args.get();
}
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
+ } else if (args.hasExactly(2) && (action == Action.CYLINDER || action == Action.HCYLINDER)) {
+ args.get();
+ return args.tabCompleteDatatype(ForAxis.INSTANCE);
}
} else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) {
if (args.hasExactlyOne()) {
@@ -305,6 +342,10 @@ public class SelCommand extends Command {
"> sel set/fill/s/f [block] - Completely fill all selections with a block.",
"> sel walls/w [block] - Fill in the walls of the selection with a specified block.",
"> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.",
+ "> sel sphere/sph [block] - Fills the selection with a sphere bounded by the sides.",
+ "> sel hsphere/hsph [block] - The same as sphere, but hollow.",
+ "> sel cylinder/cyl [block] - Fills the selection with a cylinder bounded by the sides, oriented about the given axis. (default=y)",
+ "> sel hcylinder/hcyl [block] - The same as cylinder, but hollow.",
"> sel cleararea/ca - Basically 'set air'.",
"> sel replace/r - Replaces blocks with another block.",
"> sel copy/cp - Copy the selected area relative to the specified or your position.",
@@ -324,6 +365,10 @@ public class SelCommand extends Command {
SET("set", "fill", "s", "f"),
WALLS("walls", "w"),
SHELL("shell", "shl"),
+ SPHERE("sphere", "sph"),
+ HSPHERE("hsphere", "hsph"),
+ CYLINDER("cylinder", "cyl"),
+ HCYLINDER("hcylinder", "hcyl"),
CLEARAREA("cleararea", "ca"),
REPLACE("replace", "r"),
EXPAND("expand", "ex"),
@@ -355,6 +400,18 @@ public class SelCommand extends Command {
}
return names.toArray(new String[0]);
}
+
+ public final boolean isFillAction() {
+ return this == SET
+ || this == WALLS
+ || this == SHELL
+ || this == SPHERE
+ || this == HSPHERE
+ || this == CYLINDER
+ || this == HCYLINDER
+ || this == CLEARAREA
+ || this == REPLACE;
+ }
}
enum TransformTarget {
diff --git a/src/main/java/baritone/command/defaults/SurfaceCommand.java b/src/main/java/baritone/command/defaults/SurfaceCommand.java
index 842b8050c..5d914aded 100644
--- a/src/main/java/baritone/command/defaults/SurfaceCommand.java
+++ b/src/main/java/baritone/command/defaults/SurfaceCommand.java
@@ -38,13 +38,13 @@ public class SurfaceCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
- final BetterBlockPos playerPos = baritone.getPlayerContext().playerFeet();
- final int surfaceLevel = baritone.getPlayerContext().world().getSeaLevel();
- final int worldHeight = baritone.getPlayerContext().world().getActualHeight();
+ final BetterBlockPos playerPos = ctx.playerFeet();
+ final int surfaceLevel = ctx.world().getSeaLevel();
+ final int worldHeight = ctx.world().getActualHeight();
// Ensure this command will not run if you are above the surface level and the block above you is air
// As this would imply that your are already on the open surface
- if (playerPos.getY() > surfaceLevel && mc.world.getBlockState(playerPos.up()).getBlock() instanceof BlockAir) {
+ if (playerPos.getY() > surfaceLevel && ctx.world().getBlockState(playerPos.up()).getBlock() instanceof BlockAir) {
logDirect("Already at surface");
return;
}
diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java
index c46b24dea..5a17d26c5 100644
--- a/src/main/java/baritone/pathing/movement/Movement.java
+++ b/src/main/java/baritone/pathing/movement/Movement.java
@@ -164,7 +164,7 @@ public abstract class Movement implements IMovement, MovementHelper {
if (!MovementHelper.canWalkThrough(ctx, blockPos) && !(BlockStateInterface.getBlock(ctx, blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
somethingInTheWay = true;
MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, blockPos));
- Optional reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance());
+ Optional reachable = RotationUtils.reachable(ctx, blockPos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
Rotation rotTowardsBlock = reachable.get();
state.setTarget(new MovementState.MovementTarget(rotTowardsBlock, true));
diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java
index 575815ea2..b14b2d69c 100644
--- a/src/main/java/baritone/pathing/movement/MovementHelper.java
+++ b/src/main/java/baritone/pathing/movement/MovementHelper.java
@@ -599,9 +599,9 @@ public interface MovementHelper extends ActionCosts, Helper {
static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) {
state.setTarget(new MovementTarget(
- new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
+ RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(pos),
- ctx.playerRotations()).getYaw(), ctx.player().rotationPitch),
+ ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()),
false
)).setInput(Input.MOVE_FORWARD, true);
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
index d36843cdd..2d8180356 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
@@ -234,11 +234,10 @@ public class MovementDescend extends Movement {
if (safeMode()) {
double destX = (src.getX() + 0.5) * 0.17 + (dest.getX() + 0.5) * 0.83;
double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83;
- EntityPlayerSP player = ctx.player();
state.setTarget(new MovementState.MovementTarget(
- new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
+ RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
new Vec3d(destX, dest.getY(), destZ),
- new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
+ ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()),
false
)).setInput(Input.MOVE_FORWARD, true);
return state;
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
index cfa9d9260..0198b28fe 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
@@ -190,9 +190,9 @@ public class MovementPillar extends Movement {
boolean vine = fromDown.getBlock() == Blocks.VINE;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(positionToPlace),
- new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
+ ctx.playerRotations());
if (!ladder) {
- state.setTarget(new MovementState.MovementTarget(new Rotation(ctx.player().rotationYaw, rotation.getPitch()), true));
+ state.setTarget(new MovementState.MovementTarget(ctx.playerRotations().withPitch(rotation.getPitch()), true));
}
boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder;
@@ -251,7 +251,7 @@ public class MovementPillar extends Movement {
Block fr = frState.getBlock();
// TODO: Evaluate usage of getMaterial().isReplaceable()
if (!(fr instanceof BlockAir || frState.getMaterial().isReplaceable())) {
- RotationUtils.reachable(ctx.player(), src, ctx.playerController().getBlockReachDistance())
+ RotationUtils.reachable(ctx, src, ctx.playerController().getBlockReachDistance())
.map(rot -> new MovementState.MovementTarget(rot, true))
.ifPresent(state::setTarget);
state.setInput(Input.JUMP, false); // breaking is like 5x slower when you're jumping
diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java
index c7868a4a0..2d10bcd55 100644
--- a/src/main/java/baritone/process/BuilderProcess.java
+++ b/src/main/java/baritone/process/BuilderProcess.java
@@ -30,10 +30,7 @@ import baritone.api.schematic.ISchematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.SubstituteSchematic;
import baritone.api.schematic.format.ISchematicFormat;
-import baritone.api.utils.BetterBlockPos;
-import baritone.api.utils.RayTraceUtils;
-import baritone.api.utils.Rotation;
-import baritone.api.utils.RotationUtils;
+import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
@@ -283,7 +280,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
IBlockState curr = bcc.bsi.get0(x, y, z);
if (curr.getBlock() != Blocks.AIR && !(curr.getBlock() instanceof BlockLiquid) && !valid(curr, desired, false)) {
BetterBlockPos pos = new BetterBlockPos(x, y, z);
- Optional rot = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
+ Optional rot = RotationUtils.reachable(ctx, pos, ctx.playerController().getBlockReachDistance());
if (rot.isPresent()) {
return Optional.of(new Tuple<>(pos, rot.get()));
}
@@ -764,6 +761,20 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return primary.heuristic(x, y, z);
}
+ @Override
+ public boolean equals(Object o) {
+ if (this == o) {
+ return true;
+ }
+ if (o == null || getClass() != o.getClass()) {
+ return false;
+ }
+
+ JankyGoalComposite goal = (JankyGoalComposite) o;
+ return Objects.equals(primary, goal.primary)
+ && Objects.equals(fallback, goal.fallback);
+ }
+
@Override
public String toString() {
return "JankyComposite Primary: " + primary + " Fallback: " + fallback;
@@ -785,6 +796,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
// but any other adjacent works for breaking, including inside or below
return super.isInGoal(x, y, z);
}
+
+ @Override
+ public String toString() {
+ return String.format(
+ "GoalBreak{x=%s,y=%s,z=%s}",
+ SettingsUtil.maybeCensor(x),
+ SettingsUtil.maybeCensor(y),
+ SettingsUtil.maybeCensor(z)
+ );
+ }
}
private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
@@ -828,6 +849,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
this.allowSameLevel = allowSameLevel;
}
+ @Override
public boolean isInGoal(int x, int y, int z) {
if (x == this.x && y == this.y && z == this.z) {
return false;
@@ -844,10 +866,32 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return super.isInGoal(x, y, z);
}
+ @Override
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
+
+ @Override
+ public boolean equals(Object o) {
+ if (!super.equals(o)) {
+ return false;
+ }
+
+ GoalAdjacent goal = (GoalAdjacent) o;
+ return allowSameLevel == goal.allowSameLevel
+ && Objects.equals(no, goal.no);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "GoalAdjacent{x=%s,y=%s,z=%s}",
+ SettingsUtil.maybeCensor(x),
+ SettingsUtil.maybeCensor(y),
+ SettingsUtil.maybeCensor(z)
+ );
+ }
}
public static class GoalPlace extends GoalBlock {
@@ -856,10 +900,21 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
super(placeAt.up());
}
+ @Override
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
+
+ @Override
+ public String toString() {
+ return String.format(
+ "GoalPlace{x=%s,y=%s,z=%s}",
+ SettingsUtil.maybeCensor(x),
+ SettingsUtil.maybeCensor(y),
+ SettingsUtil.maybeCensor(z)
+ );
+ }
}
@Override
diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java
index a9188299c..1536bdb61 100644
--- a/src/main/java/baritone/process/FarmProcess.java
+++ b/src/main/java/baritone/process/FarmProcess.java
@@ -268,7 +268,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
both.addAll(openSoulsand);
for (BlockPos pos : both) {
boolean soulsand = openSoulsand.contains(pos);
- Optional rot = RotationUtils.reachableOffset(ctx.player(), pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
+ Optional rot = RotationUtils.reachableOffset(ctx, pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == EnumFacing.UP) {
@@ -286,7 +286,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
continue;
}
Vec3d faceCenter = new Vec3d(pos).add(0.5, 0.5, 0.5).add(new Vec3d(dir.getDirectionVec()).scale(0.5));
- Optional rot = RotationUtils.reachableOffset(ctx.player(), pos, faceCenter, ctx.playerController().getBlockReachDistance(), false);
+ Optional rot = RotationUtils.reachableOffset(ctx, pos, faceCenter, ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isCocoa)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == dir) {
diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java
index 16fc3dda5..7f8376b84 100644
--- a/src/main/java/baritone/process/GetToBlockProcess.java
+++ b/src/main/java/baritone/process/GetToBlockProcess.java
@@ -210,7 +210,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
private boolean rightClick() {
for (BlockPos pos : knownLocations) {
- Optional reachable = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
+ Optional reachable = RotationUtils.reachable(ctx, pos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
baritone.getLookBehavior().updateTarget(reachable.get(), true);
if (knownLocations.contains(ctx.getSelectedBlock().orElse(null))) {
diff --git a/src/main/java/baritone/process/InventoryPauserProcess.java b/src/main/java/baritone/process/InventoryPauserProcess.java
index ab210532b..9752912b9 100644
--- a/src/main/java/baritone/process/InventoryPauserProcess.java
+++ b/src/main/java/baritone/process/InventoryPauserProcess.java
@@ -34,14 +34,14 @@ public class InventoryPauserProcess extends BaritoneProcessHelper {
@Override
public boolean isActive() {
- if (mc.player == null || mc.world == null) {
+ if (ctx.player() == null || ctx.world() == null) {
return false;
}
return true;
}
private double motion() {
- return Math.sqrt(mc.player.motionX * mc.player.motionX + mc.player.motionZ * mc.player.motionZ);
+ return Math.sqrt(ctx.player().motionX * ctx.player().motionX + ctx.player().motionZ * ctx.player().motionZ);
}
private boolean stationaryNow() {
diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java
index 6880dd86c..777b48197 100644
--- a/src/main/java/baritone/process/MineProcess.java
+++ b/src/main/java/baritone/process/MineProcess.java
@@ -319,6 +319,21 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
int zDiff = z - this.z;
return GoalBlock.calculate(xDiff, yDiff < -1 ? yDiff + 2 : yDiff == -1 ? 0 : yDiff, zDiff);
}
+
+ @Override
+ public boolean equals(Object o) {
+ return super.equals(o);
+ }
+
+ @Override
+ public String toString() {
+ return String.format(
+ "GoalThreeBlocks{x=%s,y=%s,z=%s}",
+ SettingsUtil.maybeCensor(x),
+ SettingsUtil.maybeCensor(y),
+ SettingsUtil.maybeCensor(z)
+ );
+ }
}
public List droppedItemsScan() {
@@ -397,7 +412,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
// is an x-ray and it'll get caught
if (filter.has(bsi.get0(x, y, z))) {
BlockPos pos = new BlockPos(x, y, z);
- if ((Baritone.settings().legitMineIncludeDiagonals.value && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx.player(), pos, fakedBlockReachDistance).isPresent()) {
+ if ((Baritone.settings().legitMineIncludeDiagonals.value && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx, pos, fakedBlockReachDistance).isPresent()) {
knownOreLocations.add(pos);
}
}
diff --git a/src/main/java/baritone/selection/SelectionRenderer.java b/src/main/java/baritone/selection/SelectionRenderer.java
index 89104d030..b688e9670 100644
--- a/src/main/java/baritone/selection/SelectionRenderer.java
+++ b/src/main/java/baritone/selection/SelectionRenderer.java
@@ -23,27 +23,27 @@ public class SelectionRenderer implements IRenderer, AbstractGameEventListener {
boolean ignoreDepth = settings.renderSelectionIgnoreDepth.value;
float lineWidth = settings.selectionLineWidth.value;
- if (!settings.renderSelection.value) {
+ if (!settings.renderSelection.value || selections.length == 0) {
return;
}
IRenderer.startLines(settings.colorSelection.value, opacity, lineWidth, ignoreDepth);
for (ISelection selection : selections) {
- IRenderer.drawAABB(selection.aabb(), SELECTION_BOX_EXPANSION);
+ IRenderer.emitAABB(selection.aabb(), SELECTION_BOX_EXPANSION);
}
if (settings.renderSelectionCorners.value) {
IRenderer.glColor(settings.colorSelectionPos1.value, opacity);
for (ISelection selection : selections) {
- IRenderer.drawAABB(new AxisAlignedBB(selection.pos1(), selection.pos1().add(1, 1, 1)));
+ IRenderer.emitAABB(new AxisAlignedBB(selection.pos1(), selection.pos1().add(1, 1, 1)));
}
IRenderer.glColor(settings.colorSelectionPos2.value, opacity);
for (ISelection selection : selections) {
- IRenderer.drawAABB(new AxisAlignedBB(selection.pos2(), selection.pos2().add(1, 1, 1)));
+ IRenderer.emitAABB(new AxisAlignedBB(selection.pos2(), selection.pos2().add(1, 1, 1)));
}
}
diff --git a/src/main/java/baritone/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java
index e5a5ee907..26a7cf1ad 100644
--- a/src/main/java/baritone/utils/IRenderer.java
+++ b/src/main/java/baritone/utils/IRenderer.java
@@ -38,9 +38,14 @@ public interface IRenderer {
RenderManager renderManager = Helper.mc.getRenderManager();
Settings settings = BaritoneAPI.getSettings();
+ float[] color = new float[] {1.0F, 1.0F, 1.0F, 255.0F};
+
static void glColor(Color color, float alpha) {
float[] colorComponents = color.getColorComponents(null);
- GlStateManager.color(colorComponents[0], colorComponents[1], colorComponents[2], alpha);
+ IRenderer.color[0] = colorComponents[0];
+ IRenderer.color[1] = colorComponents[1];
+ IRenderer.color[2] = colorComponents[2];
+ IRenderer.color[3] = alpha;
}
static void startLines(Color color, float alpha, float lineWidth, boolean ignoreDepth) {
@@ -54,6 +59,7 @@ public interface IRenderer {
if (ignoreDepth) {
GlStateManager.disableDepth();
}
+ buffer.begin(GL_LINES, DefaultVertexFormats.POSITION_COLOR);
}
static void startLines(Color color, float lineWidth, boolean ignoreDepth) {
@@ -61,6 +67,7 @@ public interface IRenderer {
}
static void endLines(boolean ignoredDepth) {
+ tessellator.draw();
if (ignoredDepth) {
GlStateManager.enableDepth();
}
@@ -70,41 +77,45 @@ public interface IRenderer {
GlStateManager.disableBlend();
}
- static void drawAABB(AxisAlignedBB aabb) {
+ static void emitAABB(AxisAlignedBB aabb) {
AxisAlignedBB toDraw = aabb.offset(-renderManager.viewerPosX, -renderManager.viewerPosY, -renderManager.viewerPosZ);
- buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
// bottom
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
// top
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
// corners
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).endVertex();
- buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).endVertex();
- tessellator.draw();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.maxX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.minY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(toDraw.minX, toDraw.maxY, toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
}
- static void drawAABB(AxisAlignedBB aabb, double expand) {
- drawAABB(aabb.grow(expand, expand, expand));
+ static void emitAABB(AxisAlignedBB aabb, double expand) {
+ emitAABB(aabb.grow(expand, expand, expand));
+ }
+
+ static void drawAABB(AxisAlignedBB aabb) {
+ buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
+ emitAABB(aabb);
+ tessellator.draw();
}
}
diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java
index f4e9317b3..13a14f6dc 100644
--- a/src/main/java/baritone/utils/PathRenderer.java
+++ b/src/main/java/baritone/utils/PathRenderer.java
@@ -31,7 +31,6 @@ 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;
-import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.AxisAlignedBB;
@@ -40,6 +39,7 @@ import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
import java.awt.*;
+import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -79,7 +79,7 @@ public final class PathRenderer implements IRenderer {
}
if (goal != null && settings.renderGoal.value) {
- drawDankLitGoalBox(renderView, goal, partialTicks, settings.colorGoalBox.value);
+ drawGoal(renderView, goal, partialTicks, settings.colorGoalBox.value);
}
if (!settings.renderPath.value) {
@@ -172,28 +172,30 @@ public final class PathRenderer implements IRenderer {
IRenderer.glColor(color, alpha);
}
- drawLine(start.x, start.y, start.z, end.x, end.y, end.z);
-
- tessellator.draw();
+ emitLine(start.x, start.y, start.z, end.x, end.y, end.z);
}
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
}
- public static void drawLine(double x1, double y1, double z1, double x2, double y2, double z2) {
+ public 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;
boolean renderPathAsFrickinThingy = !settings.renderPathAsLine.value;
- buffer.begin(renderPathAsFrickinThingy ? GL_LINE_STRIP : GL_LINES, DefaultVertexFormats.POSITION);
- buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).endVertex();
- buffer.pos(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).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(x2 + 0.5D - vpX, y2 + 0.5D - vpY, z2 + 0.5D - vpZ).color(color[0], color[1], color[2], color[3]).endVertex();
if (renderPathAsFrickinThingy) {
- buffer.pos(x2 + 0.5D - vpX, y2 + 0.53D - vpY, z2 + 0.5D - vpZ).endVertex();
- buffer.pos(x1 + 0.5D - vpX, y1 + 0.53D - vpY, z1 + 0.5D - vpZ).endVertex();
- buffer.pos(x1 + 0.5D - vpX, y1 + 0.5D - vpY, z1 + 0.5D - vpZ).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(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 + 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(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();
}
}
@@ -213,13 +215,17 @@ public final class PathRenderer implements IRenderer {
toDraw = state.getSelectedBoundingBox(player.world, pos);
}
- IRenderer.drawAABB(toDraw, .002D);
+ IRenderer.emitAABB(toDraw, .002D);
});
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
}
- public static void drawDankLitGoalBox(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);
+ }
+
+ public static void drawGoal(Entity player, Goal goal, float partialTicks, Color color, boolean setupRender) {
double renderPosX = renderManager.viewerPosX;
double renderPosY = renderManager.viewerPosY;
double renderPosZ = renderManager.viewerPosZ;
@@ -251,6 +257,7 @@ public final class PathRenderer implements IRenderer {
y2 -= 0.5;
maxY--;
}
+ drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
} else if (goal instanceof GoalXZ) {
GoalXZ goalPos = (GoalXZ) goal;
@@ -292,14 +299,22 @@ public final class PathRenderer implements IRenderer {
y2 = 0;
minY = 0 - renderPosY;
maxY = 256 - renderPosY;
+ drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
} else if (goal instanceof GoalComposite) {
- for (Goal g : ((GoalComposite) goal).goals()) {
- drawDankLitGoalBox(player, g, partialTicks, color);
+ // Simple way to determine if goals can be batched, without having some sort of GoalRenderer
+ boolean batch = Arrays.stream(((GoalComposite) goal).goals()).allMatch(IGoalRenderPos.class::isInstance);
+
+ if (batch) {
+ IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
+ }
+ for (Goal g : ((GoalComposite) goal).goals()) {
+ drawGoal(player, g, partialTicks, color, !batch);
+ }
+ if (batch) {
+ IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
}
- return;
} else if (goal instanceof GoalInverted) {
- drawDankLitGoalBox(player, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
- return;
+ drawGoal(player, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
} else if (goal instanceof GoalYLevel) {
GoalYLevel goalpos = (GoalYLevel) goal;
minX = player.posX - settings.yLevelBoxSize.value - renderPosX;
@@ -310,37 +325,45 @@ public final class PathRenderer implements IRenderer {
maxY = minY + 2;
y1 = 1 + y + goalpos.level - renderPosY;
y2 = 1 - y + goalpos.level - renderPosY;
- } else {
- return;
+ drawDankLitGoalBox(color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
}
+ }
- IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
+ private static void drawDankLitGoalBox(Color colorIn, double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double y1, double y2, boolean setupRender) {
+ if (setupRender) {
+ IRenderer.startLines(colorIn, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
+ }
renderHorizontalQuad(minX, maxX, minZ, maxZ, y1);
renderHorizontalQuad(minX, maxX, minZ, maxZ, y2);
- buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
- buffer.pos(minX, minY, minZ).endVertex();
- buffer.pos(minX, maxY, minZ).endVertex();
- buffer.pos(maxX, minY, minZ).endVertex();
- buffer.pos(maxX, maxY, minZ).endVertex();
- buffer.pos(maxX, minY, maxZ).endVertex();
- buffer.pos(maxX, maxY, maxZ).endVertex();
- buffer.pos(minX, minY, maxZ).endVertex();
- buffer.pos(minX, maxY, maxZ).endVertex();
- tessellator.draw();
+ buffer.pos(minX, minY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(minX, maxY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, minY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, maxY, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, minY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, maxY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(minX, minY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(minX, maxY, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
- IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
+ if (setupRender) {
+ IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
+ }
}
private static void renderHorizontalQuad(double minX, double maxX, double minZ, double maxZ, double y) {
if (y != 0) {
- buffer.begin(GL_LINE_LOOP, DefaultVertexFormats.POSITION);
- buffer.pos(minX, y, minZ).endVertex();
- buffer.pos(maxX, y, minZ).endVertex();
- buffer.pos(maxX, y, maxZ).endVertex();
- buffer.pos(minX, y, maxZ).endVertex();
- tessellator.draw();
+ buffer.pos(minX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+
+ buffer.pos(maxX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(maxX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+
+ buffer.pos(maxX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(minX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+
+ buffer.pos(minX, y, maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
+ buffer.pos(minX, y, minZ).color(color[0], color[1], color[2], color[3]).endVertex();
}
}
}
diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java
index a83e53a1e..236e41cc6 100644
--- a/src/main/java/baritone/utils/PathingControlManager.java
+++ b/src/main/java/baritone/utils/PathingControlManager.java
@@ -160,7 +160,7 @@ public class PathingControlManager implements IPathingControlManager {
if (newGoal.isInGoal(current.getPath().getDest())) {
return false;
}
- return !newGoal.toString().equals(current.getPath().getGoal().toString());
+ return !newGoal.equals(current.getPath().getGoal());
}
return false;
}
diff --git a/src/main/java/baritone/utils/player/PrimaryPlayerContext.java b/src/main/java/baritone/utils/player/PrimaryPlayerContext.java
index 3cb498acd..02db73a5c 100644
--- a/src/main/java/baritone/utils/player/PrimaryPlayerContext.java
+++ b/src/main/java/baritone/utils/player/PrimaryPlayerContext.java
@@ -19,10 +19,8 @@ package baritone.utils.player;
import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldData;
-import baritone.api.utils.Helper;
-import baritone.api.utils.IPlayerContext;
-import baritone.api.utils.IPlayerController;
-import baritone.api.utils.RayTraceUtils;
+import baritone.api.utils.*;
+import baritone.behavior.LookBehavior;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
@@ -57,6 +55,12 @@ public enum PrimaryPlayerContext implements IPlayerContext, Helper {
return BaritoneAPI.getProvider().getPrimaryBaritone().getWorldProvider().getCurrentWorld();
}
+ @Override
+ public Rotation playerRotations() {
+ return ((LookBehavior) BaritoneAPI.getProvider().getPrimaryBaritone().getLookBehavior()).getEffectiveRotation()
+ .orElseGet(IPlayerContext.super::playerRotations);
+ }
+
@Override
public RayTraceResult objectMouseOver() {
return RayTraceUtils.rayTraceTowards(player(), playerRotations(), playerController().getBlockReachDistance());