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/IBaritoneProvider.java b/src/api/java/baritone/api/IBaritoneProvider.java
index 30f983c2a..6c2bfe44a 100644
--- a/src/api/java/baritone/api/IBaritoneProvider.java
+++ b/src/api/java/baritone/api/IBaritoneProvider.java
@@ -22,6 +22,7 @@ import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommand;
import baritone.api.command.ICommandSystem;
import baritone.api.schematic.ISchematicSystem;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import java.util.List;
@@ -59,7 +60,7 @@ public interface IBaritoneProvider {
* @return The {@link IBaritone} instance.
*/
default IBaritone getBaritoneForPlayer(EntityPlayerSP player) {
- for (IBaritone baritone : getAllBaritones()) {
+ for (IBaritone baritone : this.getAllBaritones()) {
if (Objects.equals(player, baritone.getPlayerContext().player())) {
return baritone;
}
@@ -68,8 +69,41 @@ public interface IBaritoneProvider {
}
/**
- * Returns the {@link IWorldScanner} instance. This is not a type returned by a
- * {@link IBaritone} implementation because it is not linked with {@link IBaritone}.
+ * Provides the {@link IBaritone} instance for a given {@link Minecraft}.
+ *
+ * @param minecraft The minecraft
+ * @return The {@link IBaritone} instance.
+ */
+ default IBaritone getBaritoneForMinecraft(Minecraft minecraft) {
+ for (IBaritone baritone : this.getAllBaritones()) {
+ if (Objects.equals(minecraft, baritone.getPlayerContext().minecraft())) {
+ return baritone;
+ }
+ }
+ return null;
+ }
+
+ /**
+ * Creates and registers a new {@link IBaritone} instance using the specified {@link Minecraft}. The existing
+ * instance is returned if already registered.
+ *
+ * @param minecraft The minecraft
+ * @return The {@link IBaritone} instance
+ */
+ IBaritone createBaritone(Minecraft minecraft);
+
+ /**
+ * Destroys and removes the specified {@link IBaritone} instance. If the specified instance is the
+ * {@link #getPrimaryBaritone() primary baritone}, this operation has no effect and will return {@code false}.
+ *
+ * @param baritone The baritone instance to remove
+ * @return Whether the baritone instance was removed
+ */
+ boolean destroyBaritone(IBaritone baritone);
+
+ /**
+ * Returns the {@link IWorldScanner} instance. This is not a type returned by
+ * {@link IBaritone} implementation, because it is not linked with {@link IBaritone}.
*
* @return The {@link IWorldScanner} instance.
*/
diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java
index b3bf9280c..b36aae48f 100644
--- a/src/api/java/baritone/api/Settings.java
+++ b/src/api/java/baritone/api/Settings.java
@@ -723,6 +723,18 @@ 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);
+
+ /**
+ * When true, the player will remain with its existing look direction as often as possible.
+ * Although, in some cases this can get it stuck, hence this setting to disable that behavior.
+ */
+ public final Setting remainWithExistingLookDirection = new Setting<>(true);
+
/**
* 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..d78e7f8b3 100644
--- a/src/api/java/baritone/api/behavior/ILookBehavior.java
+++ b/src/api/java/baritone/api/behavior/ILookBehavior.java
@@ -17,6 +17,8 @@
package baritone.api.behavior;
+import baritone.api.Settings;
+import baritone.api.behavior.look.IAimProcessor;
import baritone.api.utils.Rotation;
/**
@@ -26,14 +28,23 @@ 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}. It is not guaranteed that the
+ * rotations set by the caller will be the exact rotations expressed by the client (This is due to settings like
+ * {@link Settings#randomLooking}). If the rotations produced by this behavior are required, then the
+ * {@link #getAimProcessor() aim processor} should be used.
*
- * @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);
+
+ /**
+ * The aim processor instance for this {@link ILookBehavior}, which is responsible for applying additional,
+ * deterministic transformations to the target rotation set by {@link #updateTarget}.
+ *
+ * @return The aim processor
+ * @see IAimProcessor#fork
+ */
+ IAimProcessor getAimProcessor();
}
diff --git a/src/api/java/baritone/api/behavior/look/IAimProcessor.java b/src/api/java/baritone/api/behavior/look/IAimProcessor.java
new file mode 100644
index 000000000..c7c60f413
--- /dev/null
+++ b/src/api/java/baritone/api/behavior/look/IAimProcessor.java
@@ -0,0 +1,45 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.api.behavior.look;
+
+import baritone.api.utils.Rotation;
+
+/**
+ * @author Brady
+ */
+public interface IAimProcessor {
+
+ /**
+ * Returns the actual rotation that will be used when the desired rotation is requested. The returned rotation
+ * always reflects what would happen in the upcoming tick. In other words, it is a pure function, and no internal
+ * state changes. If simulation of the rotation states beyond the next tick is required, then a
+ * {@link IAimProcessor#fork fork} should be created.
+ *
+ * @param desired The desired rotation to set
+ * @return The actual rotation
+ */
+ Rotation peekRotation(Rotation desired);
+
+ /**
+ * Returns a copy of this {@link IAimProcessor} which has its own internal state and is manually tickable.
+ *
+ * @return The forked processor
+ * @see ITickableAimProcessor
+ */
+ ITickableAimProcessor fork();
+}
diff --git a/src/main/java/baritone/utils/player/PrimaryPlayerController.java b/src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java
similarity index 50%
rename from src/main/java/baritone/utils/player/PrimaryPlayerController.java
rename to src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java
index 1a4ddc2d0..e0a07ae57 100644
--- a/src/main/java/baritone/utils/player/PrimaryPlayerController.java
+++ b/src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java
@@ -15,24 +15,33 @@
* along with Baritone. If not, see .
*/
-package baritone.utils.player;
+package baritone.api.behavior.look;
-import baritone.api.utils.Helper;
-import baritone.api.utils.IPlayerController;
-import net.minecraft.client.multiplayer.PlayerControllerMP;
+import baritone.api.utils.Rotation;
/**
- * Implementation of {@link IPlayerController} that chains to the primary player controller's methods
- *
* @author Brady
- * @since 12/14/2018
*/
-public final class PrimaryPlayerController extends AbstractPlayerController implements Helper {
+public interface ITickableAimProcessor extends IAimProcessor {
- public static final PrimaryPlayerController INSTANCE = new PrimaryPlayerController();
+ /**
+ * Advances the internal state of this aim processor by a single tick.
+ */
+ void tick();
- @Override
- protected PlayerControllerMP getController() {
- return mc.playerController;
- }
+ /**
+ * Calls {@link #tick()} the specified number of times.
+ *
+ * @param ticks The number of calls
+ */
+ void advance(int ticks);
+
+ /**
+ * Returns the actual rotation as provided by {@link #peekRotation(Rotation)}, and then automatically advances the
+ * internal state by one {@link #tick() tick}.
+ *
+ * @param rotation The desired rotation to set
+ * @return The actual rotation
+ */
+ Rotation nextRotation(Rotation rotation);
}
diff --git a/src/api/java/baritone/api/cache/IWorldProvider.java b/src/api/java/baritone/api/cache/IWorldProvider.java
index 0e54ef469..b9ca149c7 100644
--- a/src/api/java/baritone/api/cache/IWorldProvider.java
+++ b/src/api/java/baritone/api/cache/IWorldProvider.java
@@ -17,6 +17,8 @@
package baritone.api.cache;
+import java.util.function.Consumer;
+
/**
* @author Brady
* @since 9/24/2018
@@ -29,4 +31,11 @@ public interface IWorldProvider {
* @return The current world data
*/
IWorldData getCurrentWorld();
+
+ default void ifWorldLoaded(Consumer callback) {
+ final IWorldData currentWorld = this.getCurrentWorld();
+ if (currentWorld != null) {
+ callback.accept(currentWorld);
+ }
+ }
}
diff --git a/src/api/java/baritone/api/command/datatypes/BlockById.java b/src/api/java/baritone/api/command/datatypes/BlockById.java
index 3702725e3..0efb738ca 100644
--- a/src/api/java/baritone/api/command/datatypes/BlockById.java
+++ b/src/api/java/baritone/api/command/datatypes/BlockById.java
@@ -23,11 +23,17 @@ import net.minecraft.block.Block;
import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation;
+import java.util.regex.Pattern;
import java.util.stream.Stream;
public enum BlockById implements IDatatypeFor {
INSTANCE;
+ /**
+ * Matches (domain:)?name? where domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ respectively.
+ */
+ private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?[a-z0-9/_.-]*");
+
@Override
public Block get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
@@ -40,13 +46,19 @@ public enum BlockById implements IDatatypeFor {
@Override
public Stream tabComplete(IDatatypeContext ctx) throws CommandException {
+ String arg = ctx.getConsumer().getString();
+
+ if (!PATTERN.matcher(arg).matches()) {
+ return Stream.empty();
+ }
+
return new TabCompleteHelper()
.append(
Block.REGISTRY.getKeys()
.stream()
.map(Object::toString)
)
- .filterPrefixNamespaced(ctx.getConsumer().getString())
+ .filterPrefixNamespaced(arg)
.sortAlphabetically()
.stream();
}
diff --git a/src/api/java/baritone/api/command/datatypes/ForBlockOptionalMeta.java b/src/api/java/baritone/api/command/datatypes/ForBlockOptionalMeta.java
index 978450a23..079ec03fd 100644
--- a/src/api/java/baritone/api/command/datatypes/ForBlockOptionalMeta.java
+++ b/src/api/java/baritone/api/command/datatypes/ForBlockOptionalMeta.java
@@ -18,20 +18,136 @@
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
+import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.utils.BlockOptionalMeta;
+import net.minecraft.block.Block;
+import net.minecraft.block.properties.IProperty;
+import net.minecraft.util.ResourceLocation;
+import java.util.Set;
+import java.util.regex.Pattern;
+import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum ForBlockOptionalMeta implements IDatatypeFor {
INSTANCE;
+ /**
+ * Matches (domain:)?name([(property=value)*])? but the input can be truncated at any position.
+ * domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ because that's what mc 1.13+ accepts.
+ * property and value use the same format as domain.
+ */
+ // Good luck reading this.
+ private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?(?:[a-z0-9/_.-]+(?:\\[(?:(?:[a-z0-9_.-]+=[a-z0-9_.-]+,)*(?:[a-z0-9_.-]+(?:=(?:[a-z0-9_.-]+(?:\\])?)?)?)?|\\])?)?)?");
+
@Override
public BlockOptionalMeta get(IDatatypeContext ctx) throws CommandException {
return new BlockOptionalMeta(ctx.getConsumer().getString());
}
@Override
- public Stream tabComplete(IDatatypeContext ctx) {
- return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
+ public Stream tabComplete(IDatatypeContext ctx) throws CommandException {
+ String arg = ctx.getConsumer().peekString();
+
+ if (!PATTERN.matcher(arg).matches()) {
+ // Invalid format; we can't complete this.
+ ctx.getConsumer().getString();
+ return Stream.empty();
+ }
+
+ if (arg.endsWith("]")) {
+ // We are already done.
+ ctx.getConsumer().getString();
+ return Stream.empty();
+ }
+
+ if (!arg.contains("[")) {
+ // no properties so we are completing the block id
+ return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
+ }
+
+ ctx.getConsumer().getString();
+
+ // destructuring assignment? Please?
+ String blockId, properties;
+ {
+ String[] parts = splitLast(arg, '[');
+ blockId = parts[0];
+ properties = parts[1];
+ }
+
+ Block block = Block.REGISTRY.getObject(new ResourceLocation(blockId));
+ if (block == null) {
+ // This block doesn't exist so there's no properties to complete.
+ return Stream.empty();
+ }
+
+ String leadingProperties, lastProperty;
+ {
+ String[] parts = splitLast(properties, ',');
+ leadingProperties = parts[0];
+ lastProperty = parts[1];
+ }
+
+ if (!lastProperty.contains("=")) {
+ // The last property-value pair doesn't have a value yet so we are completing its name
+ Set usedProps = Stream.of(leadingProperties.split(","))
+ .map(pair -> pair.split("=")[0])
+ .collect(Collectors.toSet());
+
+ String prefix = arg.substring(0, arg.length() - lastProperty.length());
+ return new TabCompleteHelper()
+ .append(
+ block.getBlockState()
+ .getProperties()
+ .stream()
+ .map(IProperty::getName)
+ )
+ .filter(prop -> !usedProps.contains(prop))
+ .filterPrefix(lastProperty)
+ .sortAlphabetically()
+ .map(prop -> prefix + prop)
+ .stream();
+ }
+
+ String lastName, lastValue;
+ {
+ String[] parts = splitLast(lastProperty, '=');
+ lastName = parts[0];
+ lastValue = parts[1];
+ }
+
+ // We are completing the value of a property
+ String prefix = arg.substring(0, arg.length() - lastValue.length());
+
+ IProperty> property = block.getBlockState().getProperty(lastName);
+ if (property == null) {
+ // The property does not exist so there's no values to complete
+ return Stream.empty();
+ }
+
+ return new TabCompleteHelper()
+ .append(getValues(property))
+ .filterPrefix(lastValue)
+ .sortAlphabetically()
+ .map(val -> prefix + val)
+ .stream();
+ }
+
+ /**
+ * Always returns exactly two strings.
+ * If the separator is not found the FIRST returned string is empty.
+ */
+ private static String[] splitLast(String string, char chr) {
+ int idx = string.lastIndexOf(chr);
+ if (idx == -1) {
+ return new String[]{"", string};
+ }
+ return new String[]{string.substring(0, idx), string.substring(idx + 1)};
+ }
+
+ // this shouldn't need to be a separate method?
+ private static > Stream getValues(IProperty property) {
+ return property.getAllowedValues().stream().map(property::getName);
}
}
diff --git a/src/api/java/baritone/api/command/datatypes/RelativeFile.java b/src/api/java/baritone/api/command/datatypes/RelativeFile.java
index 0bc3604ab..ec605c048 100644
--- a/src/api/java/baritone/api/command/datatypes/RelativeFile.java
+++ b/src/api/java/baritone/api/command/datatypes/RelativeFile.java
@@ -19,6 +19,8 @@ package baritone.api.command.datatypes;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
+import baritone.api.utils.Helper;
+import net.minecraft.client.Minecraft;
import java.io.File;
import java.io.IOException;
@@ -93,8 +95,13 @@ public enum RelativeFile implements IDatatypePost {
.filter(s -> !s.contains(" "));
}
+ @Deprecated
public static File gameDir() {
- File gameDir = HELPER.mc.gameDir.getAbsoluteFile();
+ return gameDir(Helper.mc);
+ }
+
+ public static File gameDir(Minecraft mc) {
+ File gameDir = mc.gameDir.getAbsoluteFile();
if (gameDir.getName().equals(".")) {
return gameDir.getParentFile();
}
diff --git a/src/api/java/baritone/api/event/events/RotationMoveEvent.java b/src/api/java/baritone/api/event/events/RotationMoveEvent.java
index 109061c7e..a2ab17ed6 100644
--- a/src/api/java/baritone/api/event/events/RotationMoveEvent.java
+++ b/src/api/java/baritone/api/event/events/RotationMoveEvent.java
@@ -17,6 +17,7 @@
package baritone.api.event.events;
+import baritone.api.utils.Rotation;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -31,14 +32,27 @@ public final class RotationMoveEvent {
*/
private final Type type;
+ private final Rotation original;
+
/**
* The yaw rotation
*/
private float yaw;
- public RotationMoveEvent(Type type, float yaw) {
+ /**
+ * The pitch rotation
+ */
+ private float pitch;
+
+ public RotationMoveEvent(Type type, float yaw, float pitch) {
this.type = type;
+ this.original = new Rotation(yaw, pitch);
this.yaw = yaw;
+ this.pitch = pitch;
+ }
+
+ public Rotation getOriginal() {
+ return this.original;
}
/**
@@ -46,21 +60,37 @@ public final class RotationMoveEvent {
*
* @param yaw Yaw rotation
*/
- public final void setYaw(float yaw) {
+ public void setYaw(float yaw) {
this.yaw = yaw;
}
/**
* @return The yaw rotation
*/
- public final float getYaw() {
+ public float getYaw() {
return this.yaw;
}
+ /**
+ * Set the pitch movement rotation
+ *
+ * @param pitch Pitch rotation
+ */
+ public void setPitch(float pitch) {
+ this.pitch = pitch;
+ }
+
+ /**
+ * @return The pitch rotation
+ */
+ public float getPitch() {
+ return pitch;
+ }
+
/**
* @return The type of the event
*/
- public final Type getType() {
+ public Type getType() {
return this.type;
}
diff --git a/src/api/java/baritone/api/pathing/goals/GoalAxis.java b/src/api/java/baritone/api/pathing/goals/GoalAxis.java
index ad8fb892e..6e2f84e7a 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalAxis.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalAxis.java
@@ -47,6 +47,11 @@ public class GoalAxis implements Goal {
return o.getClass() == GoalAxis.class;
}
+ @Override
+ public int hashCode() {
+ return 201385781;
+ }
+
@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 d76fdc7af..24faa9b34 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalBlock.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalBlock.java
@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -81,6 +82,11 @@ public class GoalBlock implements Goal, IGoalRenderPos {
&& z == goal.z;
}
+ @Override
+ public int hashCode() {
+ return (int) BetterBlockPos.longHash(x, y, z) * 905165533;
+ }
+
@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 d64f8e33e..8e13a86e4 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalComposite.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalComposite.java
@@ -80,6 +80,11 @@ public class GoalComposite implements Goal {
return Arrays.equals(goals, goal.goals);
}
+ @Override
+ public int hashCode() {
+ return Arrays.hashCode(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 b5caafa48..b8934a480 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalGetToBlock.java
@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -75,6 +76,11 @@ public class GoalGetToBlock implements Goal, IGoalRenderPos {
&& z == goal.z;
}
+ @Override
+ public int hashCode() {
+ return (int) BetterBlockPos.longHash(x, y, z) * -49639096;
+ }
+
@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 e559088ef..4a3f75315 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalInverted.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalInverted.java
@@ -65,6 +65,11 @@ public class GoalInverted implements Goal {
return Objects.equals(origin, goal.origin);
}
+ @Override
+ public int hashCode() {
+ return origin.hashCode() * 495796690;
+ }
+
@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 166138ff4..e211c0194 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalNear.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalNear.java
@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
@@ -102,6 +103,11 @@ public class GoalNear implements Goal, IGoalRenderPos {
&& rangeSq == goal.rangeSq;
}
+ @Override
+ public int hashCode() {
+ return (int) BetterBlockPos.longHash(x, y, z) + 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 166ad5a98..1e65d30f7 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java
@@ -140,6 +140,14 @@ public class GoalRunAway implements Goal {
&& Objects.equals(maintainY, goal.maintainY);
}
+ @Override
+ public int hashCode() {
+ int hash = Arrays.hashCode(from);
+ hash = hash * 1196803141 + distanceSq;
+ hash = hash * -2053788840 + maintainY;
+ return hash;
+ }
+
@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 b8e4b43b2..b6bf16b33 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalStrictDirection.java
@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
@@ -86,6 +87,14 @@ public class GoalStrictDirection implements Goal {
&& dz == goal.dz;
}
+ @Override
+ public int hashCode() {
+ int hash = (int) BetterBlockPos.longHash(x, y, z);
+ hash = hash * 630627507 + dx;
+ hash = hash * -283028380 + dz;
+ return hash;
+ }
+
@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 d6fff33a2..475d6e972 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalTwoBlocks.java
@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
+import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -87,6 +88,11 @@ public class GoalTwoBlocks implements Goal, IGoalRenderPos {
&& z == goal.z;
}
+ @Override
+ public int hashCode() {
+ return (int) BetterBlockPos.longHash(x, y, z) * 516508351;
+ }
+
@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 2c551d395..1c7535b38 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalXZ.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalXZ.java
@@ -77,6 +77,14 @@ public class GoalXZ implements Goal {
return x == goal.x && z == goal.z;
}
+ @Override
+ public int hashCode() {
+ int hash = 1791873246;
+ hash = hash * 222601791 + x;
+ hash = hash * -1331679453 + z;
+ return hash;
+ }
+
@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 37745e8de..442906ad1 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
@@ -71,6 +71,11 @@ public class GoalYLevel implements Goal, ActionCosts {
return level == goal.level;
}
+ @Override
+ public int hashCode() {
+ return level * 1271009915;
+ }
+
@Override
public String toString() {
return String.format(
diff --git a/src/api/java/baritone/api/process/IBuilderProcess.java b/src/api/java/baritone/api/process/IBuilderProcess.java
index c63113cdd..29d8968a7 100644
--- a/src/api/java/baritone/api/process/IBuilderProcess.java
+++ b/src/api/java/baritone/api/process/IBuilderProcess.java
@@ -51,6 +51,7 @@ public interface IBuilderProcess extends IBaritoneProcess {
*/
boolean build(String name, File schematic, Vec3i origin);
+ @Deprecated
default boolean build(String schematicFile, BlockPos origin) {
File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile);
return build(schematicFile, file, origin);
diff --git a/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java
index e591c7873..bcce96651 100644
--- a/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java
+++ b/src/api/java/baritone/api/schematic/mask/operator/BinaryOperatorMask.java
@@ -33,7 +33,7 @@ public final class BinaryOperatorMask extends AbstractMask {
private final BooleanBinaryOperator operator;
public BinaryOperatorMask(Mask a, Mask b, BooleanBinaryOperator operator) {
- super(a.widthX(), a.heightY(), a.lengthZ());
+ super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
this.a = a;
this.b = b;
this.operator = operator;
@@ -42,11 +42,15 @@ public final class BinaryOperatorMask extends AbstractMask {
@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)
+ partOfMask(a, x, y, z, currentState),
+ partOfMask(b, x, y, z, currentState)
);
}
+ private static boolean partOfMask(Mask mask, int x, int y, int z, IBlockState currentState) {
+ return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.partOfMask(x, y, z, currentState);
+ }
+
public static final class Static extends AbstractMask implements StaticMask {
private final StaticMask a;
@@ -54,7 +58,7 @@ public final class BinaryOperatorMask extends AbstractMask {
private final BooleanBinaryOperator operator;
public Static(StaticMask a, StaticMask b, BooleanBinaryOperator operator) {
- super(a.widthX(), a.heightY(), a.lengthZ());
+ super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
this.a = a;
this.b = b;
this.operator = operator;
@@ -63,9 +67,13 @@ public final class BinaryOperatorMask extends AbstractMask {
@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)
+ partOfMask(a, x, y, z),
+ partOfMask(b, x, y, z)
);
}
+
+ private static boolean partOfMask(StaticMask mask, int x, int y, int z) {
+ return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.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
index 71b0d43c9..790a9a05d 100644
--- a/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java
+++ b/src/api/java/baritone/api/schematic/mask/shape/CylinderMask.java
@@ -35,8 +35,8 @@ public final class CylinderMask extends AbstractMask implements StaticMask {
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.centerA = this.getA(widthX, heightY, alignment) / 2.0;
+ this.centerB = this.getB(heightY, lengthZ, alignment) / 2.0;
this.radiusSqA = (this.centerA - 1) * (this.centerA - 1);
this.radiusSqB = (this.centerB - 1) * (this.centerB - 1);
this.filled = filled;
@@ -45,8 +45,8 @@ public final class CylinderMask extends AbstractMask implements StaticMask {
@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);
+ double da = Math.abs((this.getA(x, y, this.alignment) + 0.5) - this.centerA);
+ double db = Math.abs((this.getB(y, z, this.alignment) + 0.5) - this.centerB);
if (this.outside(da, db)) {
return false;
}
@@ -59,11 +59,11 @@ public final class CylinderMask extends AbstractMask implements StaticMask {
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 static int getA(int x, int y, EnumFacing.Axis alignment) {
+ return alignment == EnumFacing.Axis.X ? y : x;
}
- private int getB(int y, int z) {
- return this.alignment == EnumFacing.Axis.Z ? y : z;
+ private static int getB(int y, int z, EnumFacing.Axis alignment) {
+ return alignment == EnumFacing.Axis.Z ? y : z;
}
}
diff --git a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java
index 6d236e90e..6479854bc 100644
--- a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java
+++ b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java
@@ -17,6 +17,7 @@
package baritone.api.utils;
+import baritone.api.utils.accessor.IItemStack;
import com.google.common.collect.ImmutableSet;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@@ -29,8 +30,9 @@ import java.util.Set;
import java.util.stream.Stream;
public class BlockOptionalMetaLookup {
- private final Set blockSet;
- private final Set blockStateSet;
+ private final ImmutableSet blockSet;
+ private final ImmutableSet blockStateSet;
+ private final ImmutableSet stackHashes;
private final BlockOptionalMeta[] boms;
public BlockOptionalMetaLookup(BlockOptionalMeta... boms) {
@@ -45,6 +47,7 @@ public class BlockOptionalMetaLookup {
}
this.blockSet = ImmutableSet.copyOf(blocks);
this.blockStateSet = ImmutableSet.copyOf(blockStates);
+ this.stackHashes = ImmutableSet.copyOf(stacks);
}
public BlockOptionalMetaLookup(Block... blocks) {
@@ -75,13 +78,9 @@ public class BlockOptionalMetaLookup {
}
public boolean has(ItemStack stack) {
- for (BlockOptionalMeta bom : boms) {
- if (bom.matches(stack)) {
- return true;
- }
- }
-
- return false;
+ int hash = ((IItemStack) (Object) stack).getBaritoneHash();
+ return stackHashes.contains(hash)
+ || stackHashes.contains(hash - stack.getItemDamage());
}
public List blocks() {
diff --git a/src/api/java/baritone/api/utils/Helper.java b/src/api/java/baritone/api/utils/Helper.java
index 9bed37383..b99074ae0 100755
--- a/src/api/java/baritone/api/utils/Helper.java
+++ b/src/api/java/baritone/api/utils/Helper.java
@@ -42,8 +42,10 @@ public interface Helper {
Helper HELPER = new Helper() {};
/**
- * Instance of the game
+ * The main game instance returned by {@link Minecraft#getMinecraft()}.
+ * Deprecated since {@link IPlayerContext#minecraft()} should be used instead (In the majority of cases).
*/
+ @Deprecated
Minecraft mc = Minecraft.getMinecraft();
static ITextComponent getPrefix() {
@@ -70,7 +72,7 @@ public interface Helper {
* @param message The message to display in the popup
*/
default void logToast(ITextComponent title, ITextComponent message) {
- mc.addScheduledTask(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
+ Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
}
/**
@@ -131,7 +133,7 @@ public interface Helper {
* @param error Whether to log as an error
*/
default void logNotificationDirect(String message, boolean error) {
- mc.addScheduledTask(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
+ Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
}
/**
@@ -168,7 +170,7 @@ public interface Helper {
if (logAsToast) {
logToast(getPrefix(), component);
} else {
- mc.addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
+ Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
}
}
diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java
index 9103fa95f..1e91672ec 100644
--- a/src/api/java/baritone/api/utils/IPlayerContext.java
+++ b/src/api/java/baritone/api/utils/IPlayerContext.java
@@ -19,6 +19,7 @@ package baritone.api.utils;
import baritone.api.cache.IWorldData;
import net.minecraft.block.BlockSlab;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
@@ -33,6 +34,8 @@ import java.util.Optional;
*/
public interface IPlayerContext {
+ Minecraft minecraft();
+
EntityPlayerSP player();
IPlayerController playerController();
@@ -74,6 +77,8 @@ public interface IPlayerContext {
return new Vec3d(player().posX, player().posY + player().getEyeHeight(), player().posZ);
}
+ BetterBlockPos viewerPos();
+
default Rotation playerRotations() {
return new Rotation(player().rotationYaw, player().rotationPitch);
}
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..9fc65df9f 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 (BaritoneAPI.getSettings().remainWithExistingLookDirection.value && 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,55 @@ 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());
+ Rotation actualRotation = BaritoneAPI.getProvider().getBaritoneForPlayer(ctx.player()).getLookBehavior().getAimProcessor().peekRotation(rotation);
+ RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), actualRotation, 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 +273,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/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java
index 0b9c64737..efc080cf5 100644
--- a/src/api/java/baritone/api/utils/SettingsUtil.java
+++ b/src/api/java/baritone/api/utils/SettingsUtil.java
@@ -20,6 +20,7 @@ package baritone.api.utils;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import net.minecraft.block.Block;
+import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.Vec3i;
@@ -44,8 +45,6 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
-import static net.minecraft.client.Minecraft.getMinecraft;
-
public class SettingsUtil {
public static final String SETTINGS_DEFAULT_NAME = "settings.txt";
@@ -105,7 +104,7 @@ public class SettingsUtil {
}
private static Path settingsByName(String name) {
- return getMinecraft().gameDir.toPath().resolve("baritone").resolve(name);
+ return Minecraft.getMinecraft().gameDir.toPath().resolve("baritone").resolve(name);
}
public static List modifiedSettings(Settings settings) {
diff --git a/src/api/java/baritone/api/utils/gui/BaritoneToast.java b/src/api/java/baritone/api/utils/gui/BaritoneToast.java
index eb6361478..9e9a6403c 100644
--- a/src/api/java/baritone/api/utils/gui/BaritoneToast.java
+++ b/src/api/java/baritone/api/utils/gui/BaritoneToast.java
@@ -17,6 +17,7 @@
package baritone.api.utils.gui;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.toasts.GuiToast;
import net.minecraft.client.gui.toasts.IToast;
import net.minecraft.client.renderer.GlStateManager;
@@ -73,6 +74,6 @@ public class BaritoneToast implements IToast {
}
public static void addOrUpdate(ITextComponent title, ITextComponent subtitle) {
- addOrUpdate(net.minecraft.client.Minecraft.getMinecraft().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
+ addOrUpdate(Minecraft.getMinecraft().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
}
}
diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
index 0fd2436c9..f8544dd2f 100644
--- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
+++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java
@@ -25,11 +25,14 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
+import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
+import java.util.Optional;
+
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
/**
@@ -42,11 +45,14 @@ public abstract class MixinEntityLivingBase extends Entity {
/**
* Event called to override the movement direction when jumping
*/
+ @Unique
private RotationMoveEvent jumpRotationEvent;
- public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) {
+ @Unique
+ private RotationMoveEvent elytraRotationEvent;
+
+ public MixinEntityLivingBase(World worldIn) {
super(worldIn);
- this.jumpRotationEvent = jumpRotationEvent;
}
@Inject(
@@ -54,14 +60,10 @@ public abstract class MixinEntityLivingBase extends Entity {
at = @At("HEAD")
)
private void preMoveRelative(CallbackInfo ci) {
- // noinspection ConstantConditions
- if (EntityPlayerSP.class.isInstance(this)) {
- IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
- if (baritone != null) {
- this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
- baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
- }
- }
+ this.getBaritone().ifPresent(baritone -> {
+ this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw, this.rotationPitch);
+ baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
+ });
}
@Redirect(
@@ -79,6 +81,38 @@ public abstract class MixinEntityLivingBase extends Entity {
return self.rotationYaw;
}
+ @Inject(
+ method = "travel",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/entity/EntityLivingBase.getLookVec()Lnet/minecraft/util/math/Vec3d;"
+ )
+ )
+ private void onPreElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) {
+ this.getBaritone().ifPresent(baritone -> {
+ this.elytraRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
+ baritone.getGameEventHandler().onPlayerRotationMove(this.elytraRotationEvent);
+ this.rotationYaw = this.elytraRotationEvent.getYaw();
+ this.rotationPitch = this.elytraRotationEvent.getPitch();
+ });
+ }
+
+ @Inject(
+ method = "travel",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/entity/EntityLivingBase.move(Lnet/minecraft/entity/MoverType;DDD)V",
+ shift = At.Shift.AFTER
+ )
+ )
+ private void onPostElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) {
+ if (this.elytraRotationEvent != null) {
+ this.rotationYaw = this.elytraRotationEvent.getOriginal().getYaw();
+ this.rotationPitch = this.elytraRotationEvent.getOriginal().getPitch();
+ this.elytraRotationEvent = null;
+ }
+ }
+
@Redirect(
method = "travel",
at = @At(
@@ -86,17 +120,32 @@ public abstract class MixinEntityLivingBase extends Entity {
target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
)
)
- private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
- // noinspection ConstantConditions
- if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) {
+ private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) {
+ Optional baritone = this.getBaritone();
+ if (!baritone.isPresent()) {
moveRelative(strafe, up, forward, friction);
return;
}
- RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
- BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
- float originalYaw = this.rotationYaw;
- this.rotationYaw = motionUpdateRotationEvent.getYaw();
+
+ RotationMoveEvent event = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
+ baritone.get().getGameEventHandler().onPlayerRotationMove(event);
+
+ this.rotationYaw = event.getYaw();
+ this.rotationPitch = event.getPitch();
+
this.moveRelative(strafe, up, forward, friction);
- this.rotationYaw = originalYaw;
+
+ this.rotationYaw = event.getOriginal().getYaw();
+ this.rotationPitch = event.getOriginal().getPitch();
+ }
+
+ @Unique
+ private Optional getBaritone() {
+ // noinspection ConstantConditions
+ if (EntityPlayerSP.class.isInstance(this)) {
+ return Optional.ofNullable(BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this));
+ } else {
+ return Optional.empty();
+ }
}
}
diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
index bee3354c9..b65604061 100644
--- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
+++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java
@@ -83,9 +83,8 @@ public class MixinEntityPlayerSP {
method = "onUpdate",
at = @At(
value = "INVOKE",
- target = "net/minecraft/client/entity/EntityPlayerSP.isRiding()Z",
- shift = At.Shift.BY,
- by = -3
+ target = "net/minecraft/client/entity/AbstractClientPlayer.onUpdate()V",
+ shift = At.Shift.AFTER
)
)
private void onPreUpdate(CallbackInfo ci) {
@@ -95,22 +94,6 @@ public class MixinEntityPlayerSP {
}
}
- @Inject(
- method = "onUpdate",
- at = @At(
- value = "INVOKE",
- target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
- shift = At.Shift.BY,
- by = 2
- )
- )
- private void onPostUpdate(CallbackInfo ci) {
- IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
- if (baritone != null) {
- baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
- }
- }
-
@Redirect(
method = "onLivingUpdate",
at = @At(
diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
index 097c72905..edc1e3fcc 100644
--- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
+++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
@@ -20,6 +20,7 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.BlockInteractEvent;
+import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
@@ -84,7 +85,21 @@ public class MixinMinecraft {
baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type));
}
+ }
+ @Inject(
+ method = "runTick",
+ at = @At(
+ value = "INVOKE",
+ target = "net/minecraft/client/multiplayer/WorldClient.updateEntities()V",
+ shift = At.Shift.AFTER
+ )
+ )
+ private void postUpdateEntities(CallbackInfo ci) {
+ IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(this.player);
+ if (baritone != null) {
+ baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
+ }
}
@Inject(
diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java
index 4ea193650..96c0a00ff 100755
--- a/src/main/java/baritone/Baritone.java
+++ b/src/main/java/baritone/Baritone.java
@@ -20,8 +20,9 @@ package baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
+import baritone.api.behavior.IBehavior;
import baritone.api.event.listener.IEventBus;
-import baritone.api.utils.Helper;
+import baritone.api.process.IBaritoneProcess;
import baritone.api.utils.IPlayerContext;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
@@ -34,15 +35,17 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.GuiClick;
import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
+import baritone.utils.player.BaritonePlayerContext;
import net.minecraft.client.Minecraft;
-import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
+import java.util.function.Function;
/**
* @author Brady
@@ -50,73 +53,73 @@ import java.util.concurrent.TimeUnit;
*/
public class Baritone implements IBaritone {
- private static ThreadPoolExecutor threadPool;
- private static File dir;
+ private static final ThreadPoolExecutor threadPool;
static {
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
-
- dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
- if (!Files.exists(dir.toPath())) {
- try {
- Files.createDirectories(dir.toPath());
- } catch (IOException ignored) {}
- }
}
- private GameEventHandler gameEventHandler;
+ private final Minecraft mc;
+ private final Path directory;
- private PathingBehavior pathingBehavior;
- private LookBehavior lookBehavior;
- private InventoryBehavior inventoryBehavior;
- private WaypointBehavior waypointBehavior;
- private InputOverrideHandler inputOverrideHandler;
+ private final GameEventHandler gameEventHandler;
- private FollowProcess followProcess;
- private MineProcess mineProcess;
- private GetToBlockProcess getToBlockProcess;
- private CustomGoalProcess customGoalProcess;
- private BuilderProcess builderProcess;
- private ExploreProcess exploreProcess;
- private BackfillProcess backfillProcess;
- private FarmProcess farmProcess;
- private InventoryPauserProcess inventoryPauserProcess;
+ private final PathingBehavior pathingBehavior;
+ private final LookBehavior lookBehavior;
+ private final InventoryBehavior inventoryBehavior;
+ private final InputOverrideHandler inputOverrideHandler;
- private PathingControlManager pathingControlManager;
- private SelectionManager selectionManager;
- private CommandManager commandManager;
+ private final FollowProcess followProcess;
+ private final MineProcess mineProcess;
+ private final GetToBlockProcess getToBlockProcess;
+ private final CustomGoalProcess customGoalProcess;
+ private final BuilderProcess builderProcess;
+ private final ExploreProcess exploreProcess;
+ private final FarmProcess farmProcess;
+ private final InventoryPauserProcess inventoryPauserProcess;
- private IPlayerContext playerContext;
- private WorldProvider worldProvider;
+ private final PathingControlManager pathingControlManager;
+ private final SelectionManager selectionManager;
+ private final CommandManager commandManager;
+
+ private final IPlayerContext playerContext;
+ private final WorldProvider worldProvider;
public BlockStateInterface bsi;
- public Baritone(IPlayerContext playerContext) {
+ Baritone(Minecraft mc) {
+ this.mc = mc;
this.gameEventHandler = new GameEventHandler(this);
+ this.directory = mc.gameDir.toPath().resolve("baritone");
+ if (!Files.exists(this.directory)) {
+ try {
+ Files.createDirectories(this.directory);
+ } catch (IOException ignored) {}
+ }
+
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
- this.playerContext = playerContext;
+ this.playerContext = new BaritonePlayerContext(this, mc);
{
- // the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
- pathingBehavior = new PathingBehavior(this);
- lookBehavior = new LookBehavior(this);
- inventoryBehavior = new InventoryBehavior(this);
- inputOverrideHandler = new InputOverrideHandler(this);
- waypointBehavior = new WaypointBehavior(this);
+ this.lookBehavior = this.registerBehavior(LookBehavior::new);
+ this.pathingBehavior = this.registerBehavior(PathingBehavior::new);
+ this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new);
+ this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new);
+ this.registerBehavior(WaypointBehavior::new);
}
this.pathingControlManager = new PathingControlManager(this);
{
- this.pathingControlManager.registerProcess(followProcess = new FollowProcess(this));
- this.pathingControlManager.registerProcess(mineProcess = new MineProcess(this));
- this.pathingControlManager.registerProcess(customGoalProcess = new CustomGoalProcess(this)); // very high iq
- this.pathingControlManager.registerProcess(getToBlockProcess = new GetToBlockProcess(this));
- this.pathingControlManager.registerProcess(builderProcess = new BuilderProcess(this));
- this.pathingControlManager.registerProcess(exploreProcess = new ExploreProcess(this));
- this.pathingControlManager.registerProcess(backfillProcess = new BackfillProcess(this));
- this.pathingControlManager.registerProcess(farmProcess = new FarmProcess(this));
- this.pathingControlManager.registerProcess(inventoryPauserProcess = new InventoryPauserProcess(this));
+ this.followProcess = this.registerProcess(FollowProcess::new);
+ this.mineProcess = this.registerProcess(MineProcess::new);
+ this.customGoalProcess = this.registerProcess(CustomGoalProcess::new); // very high iq
+ this.getToBlockProcess = this.registerProcess(GetToBlockProcess::new);
+ this.builderProcess = this.registerProcess(BuilderProcess::new);
+ this.exploreProcess = this.registerProcess(ExploreProcess::new);
+ this.farmProcess = this.registerProcess(FarmProcess::new);
+ this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new);
+ this.registerProcess(BackfillProcess::new);
}
this.worldProvider = new WorldProvider(this);
@@ -126,15 +129,27 @@ public class Baritone implements IBaritone {
new ExampleBaritoneControl(this);
}
+ public void registerBehavior(IBehavior behavior) {
+ this.gameEventHandler.registerEventListener(behavior);
+ }
+
+ public T registerBehavior(Function constructor) {
+ final T behavior = constructor.apply(this);
+ this.registerBehavior(behavior);
+ return behavior;
+ }
+
+ public T registerProcess(Function constructor) {
+ final T behavior = constructor.apply(this);
+ this.pathingControlManager.registerProcess(behavior);
+ return behavior;
+ }
+
@Override
public PathingControlManager getPathingControlManager() {
return this.pathingControlManager;
}
- public void registerBehavior(Behavior behavior) {
- this.gameEventHandler.registerEventListener(behavior);
- }
-
@Override
public InputOverrideHandler getInputOverrideHandler() {
return this.inputOverrideHandler;
@@ -174,6 +189,7 @@ public class Baritone implements IBaritone {
return this.lookBehavior;
}
+ @Override
public ExploreProcess getExploreProcess() {
return this.exploreProcess;
}
@@ -183,6 +199,7 @@ public class Baritone implements IBaritone {
return this.mineProcess;
}
+ @Override
public FarmProcess getFarmProcess() {
return this.farmProcess;
}
@@ -221,19 +238,19 @@ public class Baritone implements IBaritone {
new Thread(() -> {
try {
Thread.sleep(100);
- Helper.mc.addScheduledTask(() -> Helper.mc.displayGuiScreen(new GuiClick()));
+ mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiClick()));
} catch (Exception ignored) {}
}).start();
}
+ public Path getDirectory() {
+ return this.directory;
+ }
+
public static Settings settings() {
return BaritoneAPI.getSettings();
}
- public static File getDir() {
- return dir;
- }
-
public static Executor getExecutor() {
return threadPool;
}
diff --git a/src/main/java/baritone/BaritoneProvider.java b/src/main/java/baritone/BaritoneProvider.java
index aa899341b..e3dbb3baf 100644
--- a/src/main/java/baritone/BaritoneProvider.java
+++ b/src/main/java/baritone/BaritoneProvider.java
@@ -19,7 +19,6 @@ package baritone;
import baritone.api.IBaritone;
import baritone.api.IBaritoneProvider;
-import baritone.api.bot.IBaritoneUser;
import baritone.api.bot.IUserManager;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommandSystem;
@@ -27,11 +26,13 @@ import baritone.api.schematic.ISchematicSystem;
import baritone.bot.UserManager;
import baritone.cache.FasterWorldScanner;
import baritone.command.CommandSystem;
-import baritone.utils.player.PrimaryPlayerContext;
+import baritone.command.ExampleBaritoneControl;
import baritone.utils.schematic.SchematicSystem;
+import net.minecraft.client.Minecraft;
-import java.util.AbstractList;
+import java.util.Collections;
import java.util.List;
+import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author Brady
@@ -39,22 +40,40 @@ import java.util.List;
*/
public final class BaritoneProvider implements IBaritoneProvider {
- private final IBaritone primary;
private final List all;
+ private final List allView;
public BaritoneProvider() {
- this.primary = new Baritone(PrimaryPlayerContext.INSTANCE);
- this.all = this.new BaritoneList();
+ this.all = new CopyOnWriteArrayList<>();
+ this.allView = Collections.unmodifiableList(this.all);
+
+ // Setup chat control, just for the primary instance
+ final Baritone primary = (Baritone) this.createBaritone(Minecraft.getMinecraft());
+ primary.registerBehavior(ExampleBaritoneControl::new);
}
@Override
public IBaritone getPrimaryBaritone() {
- return this.primary;
+ return this.all.get(0);
}
@Override
public List getAllBaritones() {
- return this.all;
+ return this.allView;
+ }
+
+ @Override
+ public synchronized IBaritone createBaritone(Minecraft minecraft) {
+ IBaritone baritone = this.getBaritoneForMinecraft(minecraft);
+ if (baritone == null) {
+ this.all.add(baritone = new Baritone(minecraft));
+ }
+ return baritone;
+ }
+
+ @Override
+ public synchronized boolean destroyBaritone(IBaritone baritone) {
+ return baritone != this.getPrimaryBaritone() && this.all.remove(baritone);
}
@Override
@@ -76,27 +95,4 @@ public final class BaritoneProvider implements IBaritoneProvider {
public ISchematicSystem getSchematicSystem() {
return SchematicSystem.INSTANCE;
}
-
- private final class BaritoneList extends AbstractList {
-
- @Override
- public int size() {
- return 1 + this.getUsers().size();
- }
-
- @Override
- public IBaritone get(int index) {
- if (index < 0 || index >= this.size()) {
- throw new IndexOutOfBoundsException();
- }
- if (index == 0) {
- return BaritoneProvider.this.primary;
- }
- return this.getUsers().get(index - 1).getBaritone();
- }
-
- private List getUsers() {
- return BaritoneProvider.this.getUserManager().getUsers();
- }
- }
}
diff --git a/src/main/java/baritone/behavior/Behavior.java b/src/main/java/baritone/behavior/Behavior.java
index 36273c026..848beb298 100644
--- a/src/main/java/baritone/behavior/Behavior.java
+++ b/src/main/java/baritone/behavior/Behavior.java
@@ -35,6 +35,5 @@ public class Behavior implements IBehavior {
protected Behavior(Baritone baritone) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
- baritone.registerBehavior(this);
}
}
diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java
index 32e5c22f5..d438e8f85 100644
--- a/src/main/java/baritone/behavior/LookBehavior.java
+++ b/src/main/java/baritone/behavior/LookBehavior.java
@@ -20,40 +20,57 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.Settings;
import baritone.api.behavior.ILookBehavior;
-import baritone.api.event.events.PlayerUpdateEvent;
-import baritone.api.event.events.RotationMoveEvent;
+import baritone.api.behavior.look.IAimProcessor;
+import baritone.api.behavior.look.ITickableAimProcessor;
+import baritone.api.event.events.*;
+import baritone.api.utils.IPlayerContext;
import baritone.api.utils.Rotation;
+import baritone.behavior.look.ForkableRandom;
+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 to restore the player's angle when using free look.
*
* @see Settings#freeLook
*/
- private float lastYaw;
+ private Rotation prevRotation;
+
+ private final AimProcessor processor;
public LookBehavior(Baritone baritone) {
super(baritone);
+ this.processor = new AimProcessor(baritone.getPlayerContext());
}
@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
+ public IAimProcessor getAimProcessor() {
+ return this.processor;
+ }
+
+ @Override
+ public void onTick(TickEvent event) {
+ if (event.getType() == TickEvent.Type.IN) {
+ this.processor.tick();
+ }
}
@Override
@@ -61,35 +78,30 @@ 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) {
+ // Just return for PRE, we still want to set target to null on POST
+ 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 Rotation actual = this.processor.peekRotation(this.target.rotation);
+ ctx.player().rotationYaw = actual.getYaw();
+ ctx.player().rotationPitch = actual.getPitch();
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 +109,214 @@ 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();
+ final Rotation actual = this.processor.peekRotation(this.target.rotation);
+ ctx.player().rotationYaw = actual.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) {
+ final Rotation actual = this.processor.peekRotation(this.target.rotation);
+ event.setYaw(actual.getYaw());
+ event.setPitch(actual.getPitch());
+ }
+ }
- event.setYaw(this.target.getYaw());
+ private static final class AimProcessor extends AbstractAimProcessor {
- // 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;
+ public AimProcessor(final IPlayerContext ctx) {
+ super(ctx);
+ }
+
+ @Override
+ protected Rotation getPrevRotation() {
+ // Implementation will use LookBehavior.serverRotation
+ return ctx.playerRotations();
+ }
+ }
+
+ private static abstract class AbstractAimProcessor implements ITickableAimProcessor {
+
+ protected final IPlayerContext ctx;
+ private final ForkableRandom rand;
+ private double randomYawOffset;
+ private double randomPitchOffset;
+
+ public AbstractAimProcessor(IPlayerContext ctx) {
+ this.ctx = ctx;
+ this.rand = new ForkableRandom();
+ }
+
+ private AbstractAimProcessor(final AbstractAimProcessor source) {
+ this.ctx = source.ctx;
+ this.rand = source.rand.fork();
+ this.randomYawOffset = source.randomYawOffset;
+ this.randomPitchOffset = source.randomPitchOffset;
+ }
+
+ @Override
+ public final Rotation peekRotation(final Rotation rotation) {
+ final Rotation prev = this.getPrevRotation();
+
+ float desiredYaw = rotation.getYaw();
+ float desiredPitch = 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 == prev.getPitch()) {
+ desiredPitch = nudgeToLevel(desiredPitch);
+ }
+
+ desiredYaw += this.randomYawOffset;
+ desiredPitch += this.randomPitchOffset;
+
+ return new Rotation(
+ this.calculateMouseMove(prev.getYaw(), desiredYaw),
+ this.calculateMouseMove(prev.getPitch(), desiredPitch)
+ ).clamp();
+ }
+
+ @Override
+ public final void tick() {
+ this.randomYawOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
+ this.randomPitchOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
+ }
+
+ @Override
+ public final void advance(int ticks) {
+ for (int i = 0; i < ticks; i++) {
+ this.tick();
+ }
+ }
+
+ @Override
+ public Rotation nextRotation(final Rotation rotation) {
+ final Rotation actual = this.peekRotation(rotation);
+ this.tick();
+ return actual;
+ }
+
+ @Override
+ public final ITickableAimProcessor fork() {
+ return new AbstractAimProcessor(this) {
+
+ private Rotation prev = AbstractAimProcessor.this.getPrevRotation();
+
+ @Override
+ public Rotation nextRotation(final Rotation rotation) {
+ return (this.prev = super.nextRotation(rotation));
+ }
+
+ @Override
+ protected Rotation getPrevRotation() {
+ return this.prev;
+ }
+ };
+ }
+
+ protected abstract Rotation getPrevRotation();
+
+ /**
+ * Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
+ */
+ private float nudgeToLevel(float pitch) {
+ if (pitch < -20) {
+ return pitch + 1;
+ } else if (pitch > 10) {
+ return pitch - 1;
+ }
+ return pitch;
+ }
+
+ private float calculateMouseMove(float current, float target) {
+ final float delta = target - current;
+ final int deltaPx = angleToMouse(delta);
+ return current + mouseToAngle(deltaPx);
+ }
+
+ private int angleToMouse(float angleDelta) {
+ final float minAngleChange = mouseToAngle(1);
+ return Math.round(angleDelta / minAngleChange);
+ }
+
+ private float mouseToAngle(int mouseDelta) {
+ final float f = ctx.minecraft().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;
}
}
}
-
- /**
- * 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--;
- }
- }
}
diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java
index 33ef14ef2..31a884622 100644
--- a/src/main/java/baritone/behavior/PathingBehavior.java
+++ b/src/main/java/baritone/behavior/PathingBehavior.java
@@ -239,11 +239,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (current != null) {
switch (event.getState()) {
case PRE:
- lastAutoJump = mc.gameSettings.autoJump;
- mc.gameSettings.autoJump = false;
+ lastAutoJump = ctx.minecraft().gameSettings.autoJump;
+ ctx.minecraft().gameSettings.autoJump = false;
break;
case POST:
- mc.gameSettings.autoJump = lastAutoJump;
+ ctx.minecraft().gameSettings.autoJump = lastAutoJump;
break;
default:
break;
diff --git a/src/main/java/baritone/behavior/look/ForkableRandom.java b/src/main/java/baritone/behavior/look/ForkableRandom.java
new file mode 100644
index 000000000..5f5f942d2
--- /dev/null
+++ b/src/main/java/baritone/behavior/look/ForkableRandom.java
@@ -0,0 +1,85 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.behavior.look;
+
+import java.util.Arrays;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.LongSupplier;
+
+/**
+ * Implementation of Xoroshiro256++
+ *
+ * Extended to produce random double-precision floating point numbers, and allow copies to be spawned via {@link #fork},
+ * which share the same internal state as the source object.
+ *
+ * @author Brady
+ */
+public final class ForkableRandom {
+
+ private static final double DOUBLE_UNIT = 0x1.0p-53;
+
+ private final long[] s;
+
+ public ForkableRandom() {
+ this(System.nanoTime() ^ System.currentTimeMillis());
+ }
+
+ public ForkableRandom(long seedIn) {
+ final AtomicLong seed = new AtomicLong(seedIn);
+ final LongSupplier splitmix64 = () -> {
+ long z = seed.addAndGet(0x9e3779b97f4a7c15L);
+ z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
+ z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
+ return z ^ (z >>> 31);
+ };
+ this.s = new long[] {
+ splitmix64.getAsLong(),
+ splitmix64.getAsLong(),
+ splitmix64.getAsLong(),
+ splitmix64.getAsLong()
+ };
+ }
+
+ private ForkableRandom(long[] s) {
+ this.s = s;
+ }
+
+ public double nextDouble() {
+ return (this.next() >>> 11) * DOUBLE_UNIT;
+ }
+
+ public long next() {
+ final long result = rotl(this.s[0] + this.s[3], 23) + this.s[0];
+ final long t = this.s[1] << 17;
+ this.s[2] ^= this.s[0];
+ this.s[3] ^= this.s[1];
+ this.s[1] ^= this.s[2];
+ this.s[0] ^= this.s[3];
+ this.s[2] ^= t;
+ this.s[3] = rotl(this.s[3], 45);
+ return result;
+ }
+
+ public ForkableRandom fork() {
+ return new ForkableRandom(Arrays.copyOf(this.s, 4));
+ }
+
+ private static long rotl(long x, int k) {
+ return (x << k) | (x >>> (64 - k));
+ }
+}
diff --git a/src/main/java/baritone/bot/BotPlayerContext.java b/src/main/java/baritone/bot/BotPlayerContext.java
deleted file mode 100644
index 166cf68d4..000000000
--- a/src/main/java/baritone/bot/BotPlayerContext.java
+++ /dev/null
@@ -1,63 +0,0 @@
-/*
- * This file is part of Baritone.
- *
- * Baritone is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Baritone is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Baritone. If not, see .
- */
-
-package baritone.bot;
-
-import baritone.api.bot.IBaritoneUser;
-import baritone.api.cache.IWorldData;
-import baritone.api.utils.IPlayerContext;
-import baritone.api.utils.IPlayerController;
-import net.minecraft.client.entity.EntityPlayerSP;
-import net.minecraft.world.World;
-
-public final class BotPlayerContext implements IPlayerContext {
-
- /**
- * The backing {@link IBaritoneUser}
- */
- private final IBaritoneUser bot;
-
- public BotPlayerContext(IBaritoneUser bot) {
- this.bot = bot;
- }
-
- @Override
- public EntityPlayerSP player() {
- if (bot.getPlayer() == null) {
- return null;
- }
- return bot.getPlayer();
- }
-
- @Override
- public IPlayerController playerController() {
- if (bot.getPlayer() == null) {
- return null;
- }
- return bot.getPlayerController();
- }
-
- @Override
- public World world() {
- return bot.getWorld();
- }
-
- @Override
- public IWorldData worldData() {
- return bot.getBaritone().getWorldProvider().getCurrentWorld();
- }
-}
diff --git a/src/main/java/baritone/cache/WorldProvider.java b/src/main/java/baritone/cache/WorldProvider.java
index c47db787c..c55422970 100644
--- a/src/main/java/baritone/cache/WorldProvider.java
+++ b/src/main/java/baritone/cache/WorldProvider.java
@@ -18,114 +18,87 @@
package baritone.cache;
import baritone.Baritone;
+import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldProvider;
-import baritone.api.utils.Helper;
-import baritone.bot.BotPlayerContext;
+import baritone.api.utils.IPlayerContext;
import baritone.utils.accessor.IAnvilChunkLoader;
import baritone.utils.accessor.IChunkProviderServer;
-import net.minecraft.server.integrated.IntegratedServer;
+import net.minecraft.client.multiplayer.ServerData;
+import net.minecraft.util.Tuple;
import net.minecraft.world.World;
import net.minecraft.world.WorldServer;
import org.apache.commons.lang3.SystemUtils;
-import java.io.File;
-import java.io.FileOutputStream;
import java.io.IOException;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
-import java.util.function.Consumer;
+import java.util.Optional;
/**
* @author Brady
* @since 8/4/2018
*/
-public class WorldProvider implements IWorldProvider, Helper {
+public class WorldProvider implements IWorldProvider {
- private static final Map worldCache = new HashMap<>(); // this is how the bots have the same cached world
+ private static final Map worldCache = new HashMap<>();
- private Baritone baritone;
+ private final Baritone baritone;
+ private final IPlayerContext ctx;
private WorldData currentWorld;
- private World mcWorld; // this let's us detect a broken load/unload hook
+
+ /**
+ * This lets us detect a broken load/unload hook.
+ * @see #detectAndHandleBrokenLoading()
+ */
+ private World mcWorld;
public WorldProvider(Baritone baritone) {
this.baritone = baritone;
+ this.ctx = baritone.getPlayerContext();
}
@Override
public final WorldData getCurrentWorld() {
- detectAndHandleBrokenLoading();
+ this.detectAndHandleBrokenLoading();
return this.currentWorld;
}
/**
* Called when a new world is initialized to discover the
*
- * @param dimension The ID of the world's dimension
+ * @param world The new world
*/
- public final void initWorld(int dimension) {
- File directory;
- File readme;
+ public final void initWorld(World world) {
+ this.getSaveDirectories(world).ifPresent(dirs -> {
+ final Path worldDir = dirs.getFirst();
+ final Path readmeDir = dirs.getSecond();
- IntegratedServer integratedServer = mc.getIntegratedServer();
-
- // If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
- if (mc.isSingleplayer()) {
- WorldServer localServerWorld = integratedServer.getWorld(dimension);
- IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
- IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
- directory = loader.getChunkSaveLocation();
-
- // Gets the "depth" of this directory relative the the game's run directory, 2 is the location of the world
- if (directory.toPath().relativize(mc.gameDir.toPath()).getNameCount() != 2) {
- // subdirectory of the main save directory for this world
- directory = directory.getParentFile();
- }
-
- directory = new File(directory, "baritone");
- readme = directory;
- } else { // Otherwise, the server must be remote...
- String folderName;
- if (mc.getCurrentServerData() != null) {
- folderName = mc.getCurrentServerData().serverIP;
- } else {
- //replaymod causes null currentServerData and false singleplayer.
- System.out.println("World seems to be a replay. Not loading Baritone cache.");
- currentWorld = null;
- mcWorld = mc.world;
- return;
- }
- if (SystemUtils.IS_OS_WINDOWS) {
- folderName = folderName.replace(":", "_");
- }
- directory = new File(Baritone.getDir(), folderName);
- readme = Baritone.getDir();
- }
-
- // lol wtf is this baritone folder in my minecraft save?
- try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) {
- // good thing we have a readme
- out.write("https://github.com/cabaletta/baritone\n".getBytes());
- } catch (IOException ignored) {}
-
- if (this.baritone.getPlayerContext() instanceof BotPlayerContext) {
- directory = new File(directory, "bot");
- }
-
- // We will actually store the world data in a subfolder: "DIM"
- Path dir = new File(directory, "DIM" + dimension).toPath();
- if (!Files.exists(dir)) {
try {
- Files.createDirectories(dir);
+ // lol wtf is this baritone folder in my minecraft save?
+ // good thing we have a readme
+ Files.createDirectories(readmeDir);
+ Files.write(
+ readmeDir.resolve("readme.txt"),
+ "https://github.com/cabaletta/baritone\n".getBytes(StandardCharsets.US_ASCII)
+ );
} catch (IOException ignored) {}
- }
- System.out.println("Baritone world data dir: " + dir);
- synchronized (worldCache) {
- this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension));
- }
- this.mcWorld = mc.world;
+ // We will actually store the world data in a subfolder: "DIM"
+ final Path worldDataDir = this.getWorldDataDirectory(worldDir, world);
+ try {
+ Files.createDirectories(worldDataDir);
+ } catch (IOException ignored) {}
+
+ System.out.println("Baritone world data dir: " + worldDataDir);
+ synchronized (worldCache) {
+ final int dimension = world.provider.getDimensionType().getId();
+ this.currentWorld = worldCache.computeIfAbsent(worldDataDir, d -> new WorldData(d, dimension));
+ }
+ this.mcWorld = ctx.world();
+ });
}
public final void closeWorld() {
@@ -138,26 +111,79 @@ public class WorldProvider implements IWorldProvider, Helper {
world.onClose();
}
- public final void ifWorldLoaded(Consumer currentWorldConsumer) {
- detectAndHandleBrokenLoading();
- if (this.currentWorld != null) {
- currentWorldConsumer.accept(this.currentWorld);
- }
+ private Path getWorldDataDirectory(Path parent, World world) {
+ return parent.resolve("DIM" + world.provider.getDimensionType().getId());
}
- private final void detectAndHandleBrokenLoading() {
- if (this.mcWorld != mc.world) {
+ /**
+ * @param world The world
+ * @return An {@link Optional} containing the world's baritone dir and readme dir, or {@link Optional#empty()} if
+ * the world isn't valid for caching.
+ */
+ private Optional> getSaveDirectories(World world) {
+ Path worldDir;
+ Path readmeDir;
+
+ // If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
+ if (ctx.minecraft().isSingleplayer()) {
+ final int dimension = world.provider.getDimensionType().getId();
+ final WorldServer localServerWorld = ctx.minecraft().getIntegratedServer().getWorld(dimension);
+ final IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
+ final IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
+ worldDir = loader.getChunkSaveLocation().toPath();
+
+ // Gets the "depth" of this directory relative to the game's run directory, 2 is the location of the world
+ if (worldDir.relativize(ctx.minecraft().gameDir.toPath()).getNameCount() != 2) {
+ // subdirectory of the main save directory for this world
+ worldDir = worldDir.getParent();
+ }
+
+ worldDir = worldDir.resolve("baritone");
+ readmeDir = worldDir;
+ } else { // Otherwise, the server must be remote...
+ String folderName;
+ final ServerData serverData = ctx.minecraft().getCurrentServerData();
+ if (serverData != null) {
+ folderName = serverData.serverIP;
+ } else {
+ //replaymod causes null currentServerData and false singleplayer.
+ System.out.println("World seems to be a replay. Not loading Baritone cache.");
+ currentWorld = null;
+ mcWorld = ctx.world();
+ return Optional.empty();
+ }
+ if (SystemUtils.IS_OS_WINDOWS) {
+ folderName = folderName.replace(":", "_");
+ }
+ // TODO: This should probably be in "baritone/servers"
+ worldDir = baritone.getDirectory().resolve(folderName);
+ // Just write the readme to the baritone directory instead of each server save in it
+ readmeDir = baritone.getDirectory();
+ }
+
+ if (this.baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
+ worldDir = worldDir.resolve("bot");
+ }
+
+ return Optional.of(new Tuple<>(worldDir, readmeDir));
+ }
+
+ /**
+ * Why does this exist instead of fixing the event? Some mods break the event. Lol.
+ */
+ private void detectAndHandleBrokenLoading() {
+ if (this.mcWorld != ctx.world()) {
if (this.currentWorld != null) {
System.out.println("mc.world unloaded unnoticed! Unloading Baritone cache now.");
closeWorld();
}
- if (mc.world != null) {
+ if (ctx.world() != null) {
System.out.println("mc.world loaded unnoticed! Loading Baritone cache now.");
- initWorld(mc.world.provider.getDimensionType().getId());
+ initWorld(ctx.world());
}
- } else if (currentWorld == null && mc.world != null && (mc.isSingleplayer() || mc.getCurrentServerData() != null)) {
+ } else if (this.currentWorld == null && ctx.world() != null && (ctx.minecraft().isSingleplayer() || ctx.minecraft().getCurrentServerData() != null)) {
System.out.println("Retrying to load Baritone cache");
- initWorld(mc.world.provider.getDimensionType().getId());
+ initWorld(ctx.world());
}
}
}
diff --git a/src/main/java/baritone/command/ExampleBaritoneControl.java b/src/main/java/baritone/command/ExampleBaritoneControl.java
index 28ced07f4..1a7b69644 100644
--- a/src/main/java/baritone/command/ExampleBaritoneControl.java
+++ b/src/main/java/baritone/command/ExampleBaritoneControl.java
@@ -17,8 +17,8 @@
package baritone.command;
+import baritone.Baritone;
import baritone.api.BaritoneAPI;
-import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.command.argument.ICommandArgument;
import baritone.api.command.exception.CommandNotEnoughArgumentsException;
@@ -30,6 +30,7 @@ import baritone.api.event.events.TabCompleteEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.utils.Helper;
import baritone.api.utils.SettingsUtil;
+import baritone.behavior.Behavior;
import baritone.command.argument.ArgConsumer;
import baritone.command.argument.CommandArguments;
import baritone.command.manager.CommandManager;
@@ -49,14 +50,14 @@ import java.util.stream.Stream;
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
-public class ExampleBaritoneControl implements Helper, AbstractGameEventListener {
+public class ExampleBaritoneControl extends Behavior implements Helper {
private static final Settings settings = BaritoneAPI.getSettings();
private final ICommandManager manager;
- public ExampleBaritoneControl(IBaritone baritone) {
+ public ExampleBaritoneControl(Baritone baritone) {
+ super(baritone);
this.manager = baritone.getCommandManager();
- baritone.getGameEventHandler().registerEventListener(this);
}
@Override
@@ -100,7 +101,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
return false;
} else if (msg.trim().equalsIgnoreCase("orderpizza")) {
try {
- ((IGuiScreen) mc.currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/"));
+ ((IGuiScreen) ctx.minecraft().currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/"));
} catch (NullPointerException | URISyntaxException ignored) {}
return false;
}
diff --git a/src/main/java/baritone/command/argument/ArgConsumer.java b/src/main/java/baritone/command/argument/ArgConsumer.java
index 4a80681dd..42ac1e5a0 100644
--- a/src/main/java/baritone/command/argument/ArgConsumer.java
+++ b/src/main/java/baritone/command/argument/ArgConsumer.java
@@ -373,6 +373,8 @@ public class ArgConsumer implements IArgConsumer {
public Stream tabCompleteDatatype(T datatype) {
try {
return datatype.tabComplete(this.context);
+ } catch (CommandException ignored) {
+ // NOP
} catch (Exception e) {
e.printStackTrace();
}
diff --git a/src/main/java/baritone/command/defaults/BuildCommand.java b/src/main/java/baritone/command/defaults/BuildCommand.java
index 724582865..12f287955 100644
--- a/src/main/java/baritone/command/defaults/BuildCommand.java
+++ b/src/main/java/baritone/command/defaults/BuildCommand.java
@@ -26,7 +26,6 @@ import baritone.api.command.datatypes.RelativeFile;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.utils.BetterBlockPos;
-import net.minecraft.client.Minecraft;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
@@ -36,10 +35,11 @@ import java.util.stream.Stream;
public class BuildCommand extends Command {
- private static final File schematicsDir = new File(Minecraft.getMinecraft().gameDir, "schematics");
+ private final File schematicsDir;
public BuildCommand(IBaritone baritone) {
super(baritone, "build");
+ this.schematicsDir = new File(baritone.getPlayerContext().minecraft().gameDir, "schematics");
}
@Override
diff --git a/src/main/java/baritone/command/defaults/ComeCommand.java b/src/main/java/baritone/command/defaults/ComeCommand.java
index 5d3e3b829..b111ee1de 100644
--- a/src/main/java/baritone/command/defaults/ComeCommand.java
+++ b/src/main/java/baritone/command/defaults/ComeCommand.java
@@ -21,10 +21,7 @@ import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
-import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.pathing.goals.GoalBlock;
-import net.minecraft.entity.Entity;
-import net.minecraft.util.math.BlockPos;
import java.util.Arrays;
import java.util.List;
@@ -39,11 +36,7 @@ public class ComeCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
- Entity entity = mc.getRenderViewEntity();
- if (entity == null) {
- throw new CommandInvalidStateException("render view entity is null");
- }
- baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(new BlockPos(entity)));
+ baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(ctx.viewerPos()));
logDirect("Coming");
}
diff --git a/src/main/java/baritone/command/defaults/ExploreFilterCommand.java b/src/main/java/baritone/command/defaults/ExploreFilterCommand.java
index c2057551f..6f306a966 100644
--- a/src/main/java/baritone/command/defaults/ExploreFilterCommand.java
+++ b/src/main/java/baritone/command/defaults/ExploreFilterCommand.java
@@ -41,7 +41,7 @@ public class ExploreFilterCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(2);
- File file = args.getDatatypePost(RelativeFile.INSTANCE, mc.gameDir.getAbsoluteFile().getParentFile());
+ File file = args.getDatatypePost(RelativeFile.INSTANCE, ctx.minecraft().gameDir.getAbsoluteFile().getParentFile());
boolean invert = false;
if (args.hasAny()) {
if (args.getString().equalsIgnoreCase("invert")) {
@@ -65,7 +65,7 @@ public class ExploreFilterCommand extends Command {
@Override
public Stream tabComplete(String label, IArgConsumer args) throws CommandException {
if (args.hasExactlyOne()) {
- return RelativeFile.tabComplete(args, RelativeFile.gameDir());
+ return RelativeFile.tabComplete(args, RelativeFile.gameDir(ctx.minecraft()));
}
return Stream.empty();
}
diff --git a/src/main/java/baritone/command/defaults/GotoCommand.java b/src/main/java/baritone/command/defaults/GotoCommand.java
index 333d7fa57..c64d7fa00 100644
--- a/src/main/java/baritone/command/defaults/GotoCommand.java
+++ b/src/main/java/baritone/command/defaults/GotoCommand.java
@@ -20,7 +20,6 @@ package baritone.command.defaults;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
-import baritone.api.command.datatypes.BlockById;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.datatypes.RelativeCoordinate;
import baritone.api.command.datatypes.RelativeGoal;
@@ -61,7 +60,8 @@ public class GotoCommand extends Command {
public Stream tabComplete(String label, IArgConsumer args) throws CommandException {
// since it's either a goal or a block, I don't think we can tab complete properly?
// so just tab complete for the block variant
- return args.tabCompleteDatatype(BlockById.INSTANCE);
+ args.requireMax(1);
+ return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
}
@Override
diff --git a/src/main/java/baritone/command/defaults/MineCommand.java b/src/main/java/baritone/command/defaults/MineCommand.java
index 1ab5c3321..0f0f9bcb1 100644
--- a/src/main/java/baritone/command/defaults/MineCommand.java
+++ b/src/main/java/baritone/command/defaults/MineCommand.java
@@ -21,7 +21,6 @@ import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
-import baritone.api.command.datatypes.BlockById;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.exception.CommandException;
import baritone.api.utils.BlockOptionalMeta;
@@ -52,8 +51,12 @@ public class MineCommand extends Command {
}
@Override
- public Stream tabComplete(String label, IArgConsumer args) {
- return args.tabCompleteDatatype(BlockById.INSTANCE);
+ public Stream tabComplete(String label, IArgConsumer args) throws CommandException {
+ args.getAsOrDefault(Integer.class, 0);
+ while (args.has(2)) {
+ args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
+ }
+ return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
}
@Override
diff --git a/src/main/java/baritone/command/defaults/RenderCommand.java b/src/main/java/baritone/command/defaults/RenderCommand.java
index cc9803d16..ab4a9dbcd 100644
--- a/src/main/java/baritone/command/defaults/RenderCommand.java
+++ b/src/main/java/baritone/command/defaults/RenderCommand.java
@@ -37,8 +37,8 @@ public class RenderCommand extends Command {
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
BetterBlockPos origin = ctx.playerFeet();
- int renderDistance = (mc.gameSettings.renderDistanceChunks + 1) * 16;
- mc.renderGlobal.markBlockRangeForRenderUpdate(
+ int renderDistance = (ctx.minecraft().gameSettings.renderDistanceChunks + 1) * 16;
+ ctx.minecraft().renderGlobal.markBlockRangeForRenderUpdate(
origin.x - renderDistance,
0,
origin.z - renderDistance,
diff --git a/src/main/java/baritone/command/defaults/SelCommand.java b/src/main/java/baritone/command/defaults/SelCommand.java
index 9abe417ac..78035aa4e 100644
--- a/src/main/java/baritone/command/defaults/SelCommand.java
+++ b/src/main/java/baritone/command/defaults/SelCommand.java
@@ -92,7 +92,7 @@ public class SelCommand extends Command {
if (action == Action.POS2 && pos1 == null) {
throw new CommandInvalidStateException("Set pos1 first before using pos2");
}
- BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
+ BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
if (action == Action.POS1) {
@@ -198,7 +198,7 @@ public class SelCommand extends Command {
baritone.getBuilderProcess().build("Fill", composite, origin);
logDirect("Filling now");
} else if (action == Action.COPY) {
- BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
+ BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
ISelection[] selections = manager.getSelections();
@@ -239,7 +239,7 @@ public class SelCommand extends Command {
clipboardOffset = origin.subtract(pos);
logDirect("Selection copied");
} else if (action == Action.PASTE) {
- BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
+ BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
if (clipboard == null) {
diff --git a/src/main/java/baritone/command/defaults/SetCommand.java b/src/main/java/baritone/command/defaults/SetCommand.java
index dd6f1204b..4325cd625 100644
--- a/src/main/java/baritone/command/defaults/SetCommand.java
+++ b/src/main/java/baritone/command/defaults/SetCommand.java
@@ -22,12 +22,14 @@ import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
+import baritone.api.command.datatypes.RelativeFile;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.command.exception.CommandInvalidTypeException;
import baritone.api.command.helpers.Paginator;
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.utils.SettingsUtil;
+import net.minecraft.client.Minecraft;
import net.minecraft.util.text.ITextComponent;
import net.minecraft.util.text.TextComponentString;
import net.minecraft.util.text.TextFormatting;
@@ -221,6 +223,9 @@ public class SetCommand extends Command {
.addToggleableSettings()
.filterPrefix(args.getString())
.stream();
+ } else if (Arrays.asList("ld", "load").contains(arg.toLowerCase(Locale.US))) {
+ // settings always use the directory of the main Minecraft instance
+ return RelativeFile.tabComplete(args, Minecraft.getMinecraft().gameDir.toPath().resolve("baritone").toFile());
}
Settings.Setting setting = Baritone.settings().byLowerName.get(arg.toLowerCase(Locale.US));
if (setting != null) {
diff --git a/src/main/java/baritone/command/defaults/SurfaceCommand.java b/src/main/java/baritone/command/defaults/SurfaceCommand.java
index 5d914aded..9ab22bdc2 100644
--- a/src/main/java/baritone/command/defaults/SurfaceCommand.java
+++ b/src/main/java/baritone/command/defaults/SurfaceCommand.java
@@ -54,7 +54,7 @@ public class SurfaceCommand extends Command {
for (int currentIteratedY = startingYPos; currentIteratedY < worldHeight; currentIteratedY++) {
final BetterBlockPos newPos = new BetterBlockPos(playerPos.getX(), currentIteratedY, playerPos.getZ());
- if (!(mc.world.getBlockState(newPos).getBlock() instanceof BlockAir) && newPos.getY() > playerPos.getY()) {
+ if (!(ctx.world().getBlockState(newPos).getBlock() instanceof BlockAir) && newPos.getY() > playerPos.getY()) {
Goal goal = new GoalBlock(newPos.up());
logDirect(String.format("Going to: %s", goal.toString()));
baritone.getCustomGoalProcess().setGoalAndPath(goal);
diff --git a/src/main/java/baritone/command/manager/CommandManager.java b/src/main/java/baritone/command/manager/CommandManager.java
index e7d24eb33..35cad4541 100644
--- a/src/main/java/baritone/command/manager/CommandManager.java
+++ b/src/main/java/baritone/command/manager/CommandManager.java
@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.command.ICommand;
import baritone.api.command.argument.ICommandArgument;
+import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandUnhandledException;
import baritone.api.command.exception.ICommandException;
import baritone.api.command.helpers.TabCompleteHelper;
@@ -151,9 +152,12 @@ public class CommandManager implements ICommandManager {
private Stream tabComplete() {
try {
return this.command.tabComplete(this.label, this.args);
+ } catch (CommandException ignored) {
+ // NOP
} catch (Throwable t) {
- return Stream.empty();
+ t.printStackTrace();
}
+ return Stream.empty();
}
}
}
diff --git a/src/main/java/baritone/event/GameEventHandler.java b/src/main/java/baritone/event/GameEventHandler.java
index 8916f7f37..0b46eb5e1 100644
--- a/src/main/java/baritone/event/GameEventHandler.java
+++ b/src/main/java/baritone/event/GameEventHandler.java
@@ -114,7 +114,7 @@ public final class GameEventHandler implements IEventBus, Helper {
if (event.getState() == EventState.POST) {
cache.closeWorld();
if (event.getWorld() != null) {
- cache.initWorld(event.getWorld().provider.getDimensionType().getId());
+ cache.initWorld(event.getWorld());
}
}
diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java
index 177435ef1..129f00e20 100644
--- a/src/main/java/baritone/pathing/movement/CalculationContext.java
+++ b/src/main/java/baritone/pathing/movement/CalculationContext.java
@@ -91,8 +91,8 @@ public class CalculationContext {
this.baritone = baritone;
EntityPlayerSP player = baritone.getPlayerContext().player();
this.world = baritone.getPlayerContext().world();
- this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld();
- this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread);
+ this.worldData = (WorldData) baritone.getPlayerContext().worldData();
+ this.bsi = new BlockStateInterface(baritone.getPlayerContext(), forUseOnAnotherThread);
this.toolSet = new ToolSet(player);
this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway();
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
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..881bb6f15 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);
}
@@ -684,7 +684,8 @@ public interface MovementHelper extends ActionCosts, Helper {
double faceY = (placeAt.getY() + against1.getY() + 0.5D) * 0.5D;
double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D;
Rotation place = RotationUtils.calcRotationFromVec3d(wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations());
- RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance(), wouldSneak);
+ Rotation actual = baritone.getLookBehavior().getAimProcessor().peekRotation(place);
+ RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), actual, ctx.playerController().getBlockReachDistance(), wouldSneak);
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) {
state.setTarget(new MovementState.MovementTarget(place, true));
found = 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 69368282d..60066971e 100644
--- a/src/main/java/baritone/process/BuilderProcess.java
+++ b/src/main/java/baritone/process/BuilderProcess.java
@@ -280,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()));
}
@@ -351,9 +351,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z);
Rotation rot = RotationUtils.calcRotationFromVec3d(RayTraceUtils.inferSneakingEyePosition(ctx.player()), new Vec3d(placeX, placeY, placeZ), ctx.playerRotations());
- RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance(), true);
+ Rotation actualRot = baritone.getLookBehavior().getAimProcessor().peekRotation(rot);
+ RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), actualRot, ctx.playerController().getBlockReachDistance(), true);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
- OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);
+ OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, actualRot);
if (hotbar.isPresent()) {
return Optional.of(new Placement(hotbar.getAsInt(), placeAgainstPos, against.getOpposite(), rot));
}
@@ -688,7 +689,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
incorrectPositions.forEach(pos -> {
IBlockState state = bcc.bsi.get0(pos);
if (state.getBlock() instanceof BlockAir) {
- if (approxPlaceable.contains(bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
+ if (containsBlockState(approxPlaceable, bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
placeable.add(pos);
} else {
IBlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
@@ -775,6 +776,14 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
&& Objects.equals(fallback, goal.fallback);
}
+ @Override
+ public int hashCode() {
+ int hash = -1701079641;
+ hash = hash * 1196141026 + primary.hashCode();
+ hash = hash * -80327868 + fallback.hashCode();
+ return hash;
+ }
+
@Override
public String toString() {
return "JankyComposite Primary: " + primary + " Fallback: " + fallback;
@@ -806,6 +815,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
SettingsUtil.maybeCensor(z)
);
}
+
+ @Override
+ public int hashCode() {
+ return super.hashCode() * 1636324008;
+ }
}
private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
@@ -883,6 +897,15 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
&& Objects.equals(no, goal.no);
}
+ @Override
+ public int hashCode() {
+ int hash = 806368046;
+ hash = hash * 1412661222 + super.hashCode();
+ hash = hash * 1730799370 + (int) BetterBlockPos.longHash(no.getX(), no.getY(), no.getZ());
+ hash = hash * 260592149 + (allowSameLevel ? -1314802005 : 1565710265);
+ return hash;
+ }
+
@Override
public String toString() {
return String.format(
@@ -906,6 +929,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return this.y * 100 + super.heuristic(x, y, z);
}
+ @Override
+ public int hashCode() {
+ return super.hashCode() * 1910811835;
+ }
+
@Override
public String toString() {
return String.format(
@@ -977,6 +1005,15 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return true;
}
+ private boolean containsBlockState(Collection states, IBlockState state) {
+ for (IBlockState testee : states) {
+ if (sameBlockstate(testee, state)) {
+ return true;
+ }
+ }
+ return false;
+ }
+
private boolean valid(IBlockState current, IBlockState desired, boolean itemVerify) {
if (desired == null) {
return true;
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/MineProcess.java b/src/main/java/baritone/process/MineProcess.java
index 866dcc19d..8cd1a6cae 100644
--- a/src/main/java/baritone/process/MineProcess.java
+++ b/src/main/java/baritone/process/MineProcess.java
@@ -325,6 +325,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return super.equals(o);
}
+ @Override
+ public int hashCode() {
+ return super.hashCode() * 393857768;
+ }
+
@Override
public String toString() {
return String.format(
@@ -412,7 +417,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/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java
index 26e82cd78..c4ed11f0c 100644
--- a/src/main/java/baritone/utils/BlockBreakHelper.java
+++ b/src/main/java/baritone/utils/BlockBreakHelper.java
@@ -17,7 +17,6 @@
package baritone.utils;
-import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.RayTraceResult;
@@ -26,7 +25,7 @@ import net.minecraft.util.math.RayTraceResult;
* @author Brady
* @since 8/25/2018
*/
-public final class BlockBreakHelper implements Helper {
+public final class BlockBreakHelper {
private final IPlayerContext ctx;
private boolean didBreakLastTick;
diff --git a/src/main/java/baritone/utils/BlockPlaceHelper.java b/src/main/java/baritone/utils/BlockPlaceHelper.java
index 440bfb93d..69dea61b8 100644
--- a/src/main/java/baritone/utils/BlockPlaceHelper.java
+++ b/src/main/java/baritone/utils/BlockPlaceHelper.java
@@ -18,13 +18,12 @@
package baritone.utils;
import baritone.Baritone;
-import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.RayTraceResult;
-public class BlockPlaceHelper implements Helper {
+public class BlockPlaceHelper {
private final IPlayerContext ctx;
private int rightClickTimer;
diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java
index f451c2f1d..1d6dcaf79 100644
--- a/src/main/java/baritone/utils/BlockStateInterface.java
+++ b/src/main/java/baritone/utils/BlockStateInterface.java
@@ -27,7 +27,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
-import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
@@ -44,7 +43,6 @@ public class BlockStateInterface {
private final Long2ObjectMap loadedChunks;
private final WorldData worldData;
- protected final IBlockAccess world;
public final BlockPos.MutableBlockPos isPassableBlockPos;
public final IBlockAccess access;
public final BetterWorldBorder worldBorder;
@@ -61,13 +59,9 @@ public class BlockStateInterface {
}
public BlockStateInterface(IPlayerContext ctx, boolean copyLoadedChunks) {
- this(ctx.world(), (WorldData) ctx.worldData(), copyLoadedChunks);
- }
-
- public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) {
- this.world = world;
+ final World world = ctx.world();
this.worldBorder = new BetterWorldBorder(world.getWorldBorder());
- this.worldData = worldData;
+ this.worldData = (WorldData) ctx.worldData();
Long2ObjectMap worldLoaded = ((IChunkProviderClient) world.getChunkProvider()).loadedChunks();
if (copyLoadedChunks) {
this.loadedChunks = new Long2ObjectOpenHashMap<>(worldLoaded); // make a copy that we can safely access from another thread
@@ -75,11 +69,11 @@ public class BlockStateInterface {
this.loadedChunks = worldLoaded; // this will only be used on the main thread
}
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value;
- if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) {
+ if (!ctx.minecraft().isCallingFromMinecraftThread()) {
throw new IllegalStateException();
}
this.isPassableBlockPos = new BlockPos.MutableBlockPos();
- this.access = new BlockStateInterfaceAccessWrapper(this);
+ this.access = new BlockStateInterfaceAccessWrapper(this, world);
}
public boolean worldContainsLoadedChunk(int blockX, int blockZ) {
diff --git a/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java b/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java
index 6dded1dd5..7ebde5f23 100644
--- a/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java
+++ b/src/main/java/baritone/utils/BlockStateInterfaceAccessWrapper.java
@@ -37,9 +37,11 @@ import javax.annotation.Nullable;
public final class BlockStateInterfaceAccessWrapper implements IBlockAccess {
private final BlockStateInterface bsi;
+ private final IBlockAccess world;
- BlockStateInterfaceAccessWrapper(BlockStateInterface bsi) {
+ BlockStateInterfaceAccessWrapper(BlockStateInterface bsi, IBlockAccess world) {
this.bsi = bsi;
+ this.world = world;
}
@Nullable
@@ -76,6 +78,6 @@ public final class BlockStateInterfaceAccessWrapper implements IBlockAccess {
@Override
public WorldType getWorldType() {
- return this.bsi.world.getWorldType();
+ return this.world.getWorldType();
}
}
diff --git a/src/main/java/baritone/utils/GuiClick.java b/src/main/java/baritone/utils/GuiClick.java
index 1716d74b6..c378aca53 100644
--- a/src/main/java/baritone/utils/GuiClick.java
+++ b/src/main/java/baritone/utils/GuiClick.java
@@ -117,21 +117,11 @@ public class GuiClick extends GuiScreen {
// drawSingleSelectionBox WHEN?
PathRenderer.drawManySelectionBoxes(e, Collections.singletonList(currentMouseOver), Color.CYAN);
if (clickStart != null && !clickStart.equals(currentMouseOver)) {
- GlStateManager.enableBlend();
- GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
- GlStateManager.color(Color.RED.getColorComponents(null)[0], Color.RED.getColorComponents(null)[1], Color.RED.getColorComponents(null)[2], 0.4F);
- GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.value);
- GlStateManager.disableTexture2D();
- GlStateManager.depthMask(false);
- GlStateManager.disableDepth();
+ IRenderer.startLines(Color.RED, Baritone.settings().pathRenderLineWidthPixels.value, true);
BetterBlockPos a = new BetterBlockPos(currentMouseOver);
BetterBlockPos b = new BetterBlockPos(clickStart);
- IRenderer.drawAABB(new AxisAlignedBB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
- GlStateManager.enableDepth();
-
- GlStateManager.depthMask(true);
- GlStateManager.enableTexture2D();
- GlStateManager.disableBlend();
+ IRenderer.emitAABB(new AxisAlignedBB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
+ IRenderer.endLines(true);
}
}
}
diff --git a/src/main/java/baritone/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java
index 26a7cf1ad..680d7e380 100644
--- a/src/main/java/baritone/utils/IRenderer.java
+++ b/src/main/java/baritone/utils/IRenderer.java
@@ -19,11 +19,12 @@ package baritone.utils;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
-import baritone.api.utils.Helper;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.entity.RenderManager;
+import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.AxisAlignedBB;
@@ -35,7 +36,8 @@ public interface IRenderer {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
- RenderManager renderManager = Helper.mc.getRenderManager();
+ RenderManager renderManager = Minecraft.getMinecraft().getRenderManager();
+ TextureManager textureManager = Minecraft.getMinecraft().getTextureManager();
Settings settings = BaritoneAPI.getSettings();
float[] color = new float[] {1.0F, 1.0F, 1.0F, 255.0F};
@@ -114,7 +116,7 @@ public interface IRenderer {
}
static void drawAABB(AxisAlignedBB aabb) {
- buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
+ buffer.begin(GL_LINES, DefaultVertexFormats.POSITION_COLOR);
emitAABB(aabb);
tessellator.draw();
}
diff --git a/src/main/java/baritone/utils/InputOverrideHandler.java b/src/main/java/baritone/utils/InputOverrideHandler.java
index d1c4689a2..f110b9ce1 100755
--- a/src/main/java/baritone/utils/InputOverrideHandler.java
+++ b/src/main/java/baritone/utils/InputOverrideHandler.java
@@ -23,7 +23,6 @@ import baritone.api.event.events.TickEvent;
import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input;
import baritone.behavior.Behavior;
-import net.minecraft.client.Minecraft;
import net.minecraft.util.MovementInputFromOptions;
import java.util.HashMap;
@@ -100,7 +99,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
}
} else {
if (ctx.player().movementInput.getClass() == PlayerMovementInput.class) { // allow other movement inputs that aren't this one, e.g. for a freecam
- ctx.player().movementInput = new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
+ ctx.player().movementInput = new MovementInputFromOptions(ctx.minecraft().gameSettings);
}
}
// only set it if it was previously incorrect
diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java
index a32776f94..1378880c3 100644
--- a/src/main/java/baritone/utils/PathRenderer.java
+++ b/src/main/java/baritone/utils/PathRenderer.java
@@ -22,7 +22,7 @@ import baritone.api.event.events.RenderEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.*;
import baritone.api.utils.BetterBlockPos;
-import baritone.api.utils.Helper;
+import baritone.api.utils.IPlayerContext;
import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.behavior.PathingBehavior;
import baritone.pathing.path.PathExecutor;
@@ -52,27 +52,27 @@ public final class PathRenderer implements IRenderer {
private PathRenderer() {}
public static void render(RenderEvent event, PathingBehavior behavior) {
- float partialTicks = event.getPartialTicks();
- Goal goal = behavior.getGoal();
- if (behavior.baritone.getPlayerContext().world() == null) {
+ final IPlayerContext ctx = behavior.ctx;
+ if (ctx.world() == null) {
return;
}
-
- if (Helper.mc.currentScreen instanceof GuiClick && behavior.baritone == BaritoneAPI.getProvider().getPrimaryBaritone()) {
- ((GuiClick) Helper.mc.currentScreen).onRender();
+ if (ctx.minecraft().currentScreen instanceof GuiClick && behavior.baritone == BaritoneAPI.getProvider().getPrimaryBaritone()) {
+ ((GuiClick) ctx.minecraft().currentScreen).onRender();
}
- Entity renderView = Helper.mc.getRenderViewEntity();
+ final float partialTicks = event.getPartialTicks();
+ final Goal goal = behavior.getGoal();
- if (renderView.world != BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world()) {
- System.out.println("I have no idea what's going on");
- System.out.println("The primary baritone is in a different world than the render view entity");
- System.out.println("Not rendering the path");
+ final int thisPlayerDimension = ctx.world().provider.getDimensionType().getId();
+ final int currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().provider.getDimensionType().getId();
+
+ if (thisPlayerDimension != currentRenderViewDimension) {
+ // this is a path for a bot in a different dimension, don't render it
return;
}
if (goal != null && settings.renderGoal.value) {
- drawGoal(renderView, goal, partialTicks, settings.colorGoalBox.value);
+ drawGoal(ctx.player(), goal, partialTicks, settings.colorGoalBox.value);
}
if (!settings.renderPath.value) {
@@ -82,9 +82,9 @@ public final class PathRenderer implements IRenderer {
PathExecutor current = behavior.getCurrent(); // this should prevent most race conditions?
PathExecutor next = behavior.getNext(); // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
if (current != null && settings.renderSelectionBoxes.value) {
- drawManySelectionBoxes(renderView, current.toBreak(), settings.colorBlocksToBreak.value);
- drawManySelectionBoxes(renderView, current.toPlace(), settings.colorBlocksToPlace.value);
- drawManySelectionBoxes(renderView, current.toWalkInto(), settings.colorBlocksToWalkInto.value);
+ drawManySelectionBoxes(ctx.player(), current.toBreak(), settings.colorBlocksToBreak.value);
+ drawManySelectionBoxes(ctx.player(), current.toPlace(), settings.colorBlocksToPlace.value);
+ drawManySelectionBoxes(ctx.player(), current.toWalkInto(), settings.colorBlocksToWalkInto.value);
}
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
@@ -107,12 +107,12 @@ public final class PathRenderer implements IRenderer {
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
drawPath(mr, 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20);
- drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
+ drawManySelectionBoxes(ctx.player(), Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
});
});
}
- public static void drawPath(IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
+ private static void drawPath(IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
int fadeStart = fadeStart0 + startIndex;
@@ -155,7 +155,7 @@ public final class PathRenderer implements IRenderer {
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
}
- public static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) {
+ private static void emitLine(double x1, double y1, double z1, double x2, double y2, double z2) {
double vpX = renderManager.viewerPosX;
double vpY = renderManager.viewerPosY;
double vpZ = renderManager.viewerPosZ;
@@ -198,11 +198,11 @@ public final class PathRenderer implements IRenderer {
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
}
- public static void drawGoal(Entity player, Goal goal, float partialTicks, Color color) {
+ private 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) {
+ private 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;
@@ -241,7 +241,7 @@ public final class PathRenderer implements IRenderer {
if (settings.renderGoalXZBeacon.value) {
glPushAttrib(GL_LIGHTING_BIT);
- Helper.mc.getTextureManager().bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM);
+ textureManager.bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM);
if (settings.renderGoalIgnoreDepth.value) {
GlStateManager.disableDepth();
diff --git a/src/main/java/baritone/utils/player/PrimaryPlayerContext.java b/src/main/java/baritone/utils/player/BaritonePlayerContext.java
similarity index 50%
rename from src/main/java/baritone/utils/player/PrimaryPlayerContext.java
rename to src/main/java/baritone/utils/player/BaritonePlayerContext.java
index de49beaac..1a5008597 100644
--- a/src/main/java/baritone/utils/player/PrimaryPlayerContext.java
+++ b/src/main/java/baritone/utils/player/BaritonePlayerContext.java
@@ -17,12 +17,13 @@
package baritone.utils.player;
-import baritone.api.BaritoneAPI;
+import baritone.Baritone;
import baritone.api.cache.IWorldData;
-import baritone.api.utils.Helper;
-import baritone.api.utils.IPlayerContext;
-import baritone.api.utils.IPlayerController;
+import baritone.api.utils.*;
+import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.entity.Entity;
+import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
/**
@@ -31,27 +32,51 @@ import net.minecraft.world.World;
* @author Brady
* @since 11/12/2018
*/
-public enum PrimaryPlayerContext implements IPlayerContext, Helper {
+public final class BaritonePlayerContext implements IPlayerContext {
- INSTANCE;
+ private final Baritone baritone;
+ private final Minecraft mc;
+ private final IPlayerController playerController;
+
+ public BaritonePlayerContext(Baritone baritone, Minecraft mc) {
+ this.baritone = baritone;
+ this.mc = mc;
+ this.playerController = new BaritonePlayerController(mc);
+ }
+
+ @Override
+ public Minecraft minecraft() {
+ return this.mc;
+ }
@Override
public EntityPlayerSP player() {
- return mc.player;
+ return this.mc.player;
}
@Override
public IPlayerController playerController() {
- return PrimaryPlayerController.INSTANCE;
+ return this.playerController;
}
@Override
public World world() {
- return mc.world;
+ return this.mc.world;
}
@Override
public IWorldData worldData() {
- return BaritoneAPI.getProvider().getPrimaryBaritone().getWorldProvider().getCurrentWorld();
+ return this.baritone.getWorldProvider().getCurrentWorld();
+ }
+
+ @Override
+ public BetterBlockPos viewerPos() {
+ final Entity entity = this.mc.getRenderViewEntity();
+ return entity == null ? this.playerFeet() : BetterBlockPos.from(new BlockPos(entity));
+ }
+
+ @Override
+ public Rotation playerRotations() {
+ return this.baritone.getLookBehavior().getEffectiveRotation().orElseGet(IPlayerContext.super::playerRotations);
}
}
diff --git a/src/main/java/baritone/utils/player/BaritonePlayerController.java b/src/main/java/baritone/utils/player/BaritonePlayerController.java
new file mode 100644
index 000000000..1f42f8281
--- /dev/null
+++ b/src/main/java/baritone/utils/player/BaritonePlayerController.java
@@ -0,0 +1,104 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.utils.player;
+
+import baritone.api.utils.IPlayerController;
+import baritone.utils.accessor.IPlayerControllerMP;
+import net.minecraft.client.Minecraft;
+import net.minecraft.client.entity.EntityPlayerSP;
+import net.minecraft.client.multiplayer.WorldClient;
+import net.minecraft.entity.player.EntityPlayer;
+import net.minecraft.inventory.ClickType;
+import net.minecraft.item.ItemStack;
+import net.minecraft.util.EnumActionResult;
+import net.minecraft.util.EnumFacing;
+import net.minecraft.util.EnumHand;
+import net.minecraft.util.math.BlockPos;
+import net.minecraft.util.math.Vec3d;
+import net.minecraft.world.GameType;
+import net.minecraft.world.World;
+
+/**
+ * Implementation of {@link IPlayerController} that chains to the primary player controller's methods
+ *
+ * @author Brady
+ * @since 12/14/2018
+ */
+public final class BaritonePlayerController implements IPlayerController {
+
+ private final Minecraft mc;
+
+ public BaritonePlayerController(Minecraft mc) {
+ this.mc = mc;
+ }
+
+ @Override
+ public void syncHeldItem() {
+ ((IPlayerControllerMP) mc.playerController).callSyncCurrentPlayItem();
+ }
+
+ @Override
+ public boolean hasBrokenBlock() {
+ return ((IPlayerControllerMP) mc.playerController).getCurrentBlock().getY() == -1;
+ }
+
+ @Override
+ public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) {
+ return mc.playerController.onPlayerDamageBlock(pos, side);
+ }
+
+ @Override
+ public void resetBlockRemoving() {
+ mc.playerController.resetBlockRemoving();
+ }
+
+ @Override
+ public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) {
+ return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player);
+ }
+
+ @Override
+ public void setGameType(GameType type) {
+ mc.playerController.setGameType(type);
+ }
+
+ @Override
+ public GameType getGameType() {
+ return mc.playerController.getCurrentGameType();
+ }
+
+ @Override
+ public EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand) {
+ return mc.playerController.processRightClickBlock(player, (WorldClient) world, pos, direction, vec, hand);
+ }
+
+ @Override
+ public EnumActionResult processRightClick(EntityPlayerSP player, World world, EnumHand hand) {
+ return mc.playerController.processRightClick(player, world, hand);
+ }
+
+ @Override
+ public boolean clickBlock(BlockPos loc, EnumFacing face) {
+ return mc.playerController.clickBlock(loc, face);
+ }
+
+ @Override
+ public void setHittingBlock(boolean hittingBlock) {
+ ((IPlayerControllerMP) mc.playerController).setIsHittingBlock(hittingBlock);
+ }
+}