diff --git a/README.md b/README.md index 8ae8090d7..c6a90ff93 100644 --- a/README.md +++ b/README.md @@ -4,14 +4,16 @@

- Minecraft - Minecraft - Minecraft - Minecraft - Minecraft - Minecraft - Minecraft - Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft + Minecraft

@@ -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); + } +}