From e00e0032b49ac2f0c29f3cf3f6e70ec1ceaccd01 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sat, 17 Jun 2023 01:40:19 +0200 Subject: [PATCH 01/21] Actually use stack hashes --- .../api/utils/BlockOptionalMetaLookup.java | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) 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() { From 6aeb73b5bd30f74a8f39271e2cd0b4fc96ec3f22 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 18 Jun 2023 19:18:46 +0200 Subject: [PATCH 02/21] Fix `CylinderMask` with horizontal alignment --- .../api/schematic/mask/shape/CylinderMask.java | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) 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; } } From 5fd915ab8acf41ed379f9f05431ff24a39b96f32 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Sun, 18 Jun 2023 19:50:58 +0200 Subject: [PATCH 03/21] Tab complete the file argument for `#settings load` --- src/main/java/baritone/command/defaults/SetCommand.java | 5 +++++ 1 file changed, 5 insertions(+) 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) { From 6c8f2698d697c3ffaca7022f29644c6317435494 Mon Sep 17 00:00:00 2001 From: Leijurv Date: Sun, 18 Jun 2023 19:31:51 -0700 Subject: [PATCH 04/21] cherry pick remainWithExistingLookDirection from fork --- src/api/java/baritone/api/Settings.java | 6 ++++++ src/api/java/baritone/api/utils/RotationUtils.java | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index bcd3eaa63..824dfd7e2 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -729,6 +729,12 @@ public final class Settings { */ public final Setting 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/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java index 1991ab878..b3b67d9ca 100644 --- a/src/api/java/baritone/api/utils/RotationUtils.java +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -161,7 +161,7 @@ public final class RotationUtils { } public static Optional reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) { - if (ctx.isLookingAt(pos)) { + if (BaritoneAPI.getSettings().remainWithExistingLookDirection.value && ctx.isLookingAt(pos)) { /* * why add 0.0001? * to indicate that we actually have a desired pitch From 1de2d5596594f3684e6e42b2279eb6c2c6ad42ee Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:05:46 +0200 Subject: [PATCH 05/21] Tab complete block properties --- .../api/command/datatypes/BlockById.java | 122 +++++++++++++++++- 1 file changed, 116 insertions(+), 6 deletions(-) diff --git a/src/api/java/baritone/api/command/datatypes/BlockById.java b/src/api/java/baritone/api/command/datatypes/BlockById.java index 3702725e3..8df3e0658 100644 --- a/src/api/java/baritone/api/command/datatypes/BlockById.java +++ b/src/api/java/baritone/api/command/datatypes/BlockById.java @@ -19,15 +19,28 @@ package baritone.api.command.datatypes; import baritone.api.command.exception.CommandException; import baritone.api.command.helpers.TabCompleteHelper; + import net.minecraft.block.Block; +import net.minecraft.block.properties.IProperty; import net.minecraft.init.Blocks; 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 BlockById 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 Block get(IDatatypeContext ctx) throws CommandException { ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString()); @@ -40,14 +53,111 @@ public enum BlockById implements IDatatypeFor { @Override public Stream tabComplete(IDatatypeContext ctx) throws CommandException { + String arg = ctx.getConsumer().getString(); + + if (!PATTERN.matcher(arg).matches()) { + // Invalid format; we can't complete this. + return Stream.empty(); + } + + if (arg.endsWith("]")) { + // We are already done. + return Stream.empty(); + } + + if (!arg.contains("[")) { + // no properties so we are completing the block id + return new TabCompleteHelper() + .append( + Block.REGISTRY.getKeys() + .stream() + .map(Object::toString) + ) + .filterPrefixNamespaced(arg) + .sortAlphabetically() + .stream(); + } + + // 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( - Block.REGISTRY.getKeys() - .stream() - .map(Object::toString) - ) - .filterPrefixNamespaced(ctx.getConsumer().getString()) + .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); + } } From e43200865cbdb305d11c913aae3cb90ea48ae4ab Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:44:22 +0200 Subject: [PATCH 06/21] Move this to the right place --- .../api/command/datatypes/BlockById.java | 122 +----------------- .../datatypes/ForBlockOptionalMeta.java | 120 ++++++++++++++++- 2 files changed, 124 insertions(+), 118 deletions(-) diff --git a/src/api/java/baritone/api/command/datatypes/BlockById.java b/src/api/java/baritone/api/command/datatypes/BlockById.java index 8df3e0658..3702725e3 100644 --- a/src/api/java/baritone/api/command/datatypes/BlockById.java +++ b/src/api/java/baritone/api/command/datatypes/BlockById.java @@ -19,28 +19,15 @@ package baritone.api.command.datatypes; import baritone.api.command.exception.CommandException; import baritone.api.command.helpers.TabCompleteHelper; - import net.minecraft.block.Block; -import net.minecraft.block.properties.IProperty; import net.minecraft.init.Blocks; 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 BlockById 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 Block get(IDatatypeContext ctx) throws CommandException { ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString()); @@ -53,111 +40,14 @@ public enum BlockById implements IDatatypeFor { @Override public Stream tabComplete(IDatatypeContext ctx) throws CommandException { - String arg = ctx.getConsumer().getString(); - - if (!PATTERN.matcher(arg).matches()) { - // Invalid format; we can't complete this. - return Stream.empty(); - } - - if (arg.endsWith("]")) { - // We are already done. - return Stream.empty(); - } - - if (!arg.contains("[")) { - // no properties so we are completing the block id - return new TabCompleteHelper() - .append( - Block.REGISTRY.getKeys() - .stream() - .map(Object::toString) - ) - .filterPrefixNamespaced(arg) - .sortAlphabetically() - .stream(); - } - - // 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) + .append( + Block.REGISTRY.getKeys() + .stream() + .map(Object::toString) + ) + .filterPrefixNamespaced(ctx.getConsumer().getString()) .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/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); } } From f55f7f19b4bb6ad6d36bdaeabe0eb6bcc6b84748 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Mon, 19 Jun 2023 23:50:42 +0200 Subject: [PATCH 07/21] Tab complete the datatype which will be parsed --- src/main/java/baritone/command/defaults/GotoCommand.java | 3 +-- src/main/java/baritone/command/defaults/MineCommand.java | 3 +-- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/src/main/java/baritone/command/defaults/GotoCommand.java b/src/main/java/baritone/command/defaults/GotoCommand.java index 333d7fa57..fc43026bb 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,7 @@ 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); + 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..52e9e0e67 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; @@ -53,7 +52,7 @@ public class MineCommand extends Command { @Override public Stream tabComplete(String label, IArgConsumer args) { - return args.tabCompleteDatatype(BlockById.INSTANCE); + return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE); } @Override From 13742df877ac734eb393df5d8a2dcd6336b3bdb5 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 00:00:52 +0200 Subject: [PATCH 08/21] Complete the last argument, not the first one --- src/main/java/baritone/command/defaults/MineCommand.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/main/java/baritone/command/defaults/MineCommand.java b/src/main/java/baritone/command/defaults/MineCommand.java index 52e9e0e67..0f0f9bcb1 100644 --- a/src/main/java/baritone/command/defaults/MineCommand.java +++ b/src/main/java/baritone/command/defaults/MineCommand.java @@ -51,7 +51,11 @@ public class MineCommand extends Command { } @Override - public Stream tabComplete(String label, IArgConsumer args) { + 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); } From 84777c2437cb72a028a9f59148187a5c503807c0 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 00:01:33 +0200 Subject: [PATCH 09/21] Don't complete more than what's supported --- src/main/java/baritone/command/defaults/GotoCommand.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/command/defaults/GotoCommand.java b/src/main/java/baritone/command/defaults/GotoCommand.java index fc43026bb..c64d7fa00 100644 --- a/src/main/java/baritone/command/defaults/GotoCommand.java +++ b/src/main/java/baritone/command/defaults/GotoCommand.java @@ -60,6 +60,7 @@ 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 + args.requireMax(1); return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE); } From b111fd2f3ef610dfebc5c3b41e1d4021ff829213 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 00:02:56 +0200 Subject: [PATCH 10/21] Don't construct malformed `ResourceLocation`s Later mc versions throw an exception when you construct a malformed `ResourceLocation`. --- .../baritone/api/command/datatypes/BlockById.java | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) 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(); } From f7a20a3acf49fb1c4b6a9553d1b9d02d2bfd2e49 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 01:32:18 +0200 Subject: [PATCH 11/21] Don't swallow random exceptions, don't bother with CommandExceptions --- src/main/java/baritone/command/argument/ArgConsumer.java | 2 ++ src/main/java/baritone/command/manager/CommandManager.java | 5 ++++- 2 files changed, 6 insertions(+), 1 deletion(-) 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/manager/CommandManager.java b/src/main/java/baritone/command/manager/CommandManager.java index e7d24eb33..26f369df9 100644 --- a/src/main/java/baritone/command/manager/CommandManager.java +++ b/src/main/java/baritone/command/manager/CommandManager.java @@ -151,9 +151,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(); } } } From 31c9072970685e1a16ee191a8a94d8429c694634 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 01:36:09 +0200 Subject: [PATCH 12/21] Forgot to git add --- src/main/java/baritone/command/manager/CommandManager.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/command/manager/CommandManager.java b/src/main/java/baritone/command/manager/CommandManager.java index 26f369df9..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; From d87d1ab9b55cee52abeb18b702b32573fd384006 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 02:00:08 +0200 Subject: [PATCH 13/21] Don't call `partOfMask` out of bounds --- .../mask/operator/BinaryOperatorMask.java | 20 +++++++++++++------ 1 file changed, 14 insertions(+), 6 deletions(-) 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); + } } } From 30278a1c5254713e135c8a2a2bbf302b0fc4a2f1 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 02:44:29 +0200 Subject: [PATCH 14/21] Implement `hashCode` for goals --- .../baritone/api/pathing/goals/GoalAxis.java | 5 ++++ .../baritone/api/pathing/goals/GoalBlock.java | 6 +++++ .../api/pathing/goals/GoalComposite.java | 5 ++++ .../api/pathing/goals/GoalGetToBlock.java | 6 +++++ .../api/pathing/goals/GoalInverted.java | 5 ++++ .../baritone/api/pathing/goals/GoalNear.java | 6 +++++ .../api/pathing/goals/GoalRunAway.java | 8 ++++++ .../pathing/goals/GoalStrictDirection.java | 9 +++++++ .../api/pathing/goals/GoalTwoBlocks.java | 6 +++++ .../baritone/api/pathing/goals/GoalXZ.java | 8 ++++++ .../api/pathing/goals/GoalYLevel.java | 5 ++++ .../java/baritone/process/BuilderProcess.java | 26 +++++++++++++++++++ .../java/baritone/process/MineProcess.java | 5 ++++ 13 files changed, 100 insertions(+) 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/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index ac12471a3..62f865899 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -775,6 +775,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 +814,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 +896,14 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil && Objects.equals(no, goal.no); } + @Override + public int hashCode() { + int hash = 806368046; + 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 +927,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( diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 777b48197..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( From 41d730fb04f1058d8bab6e57b3d04cd77926b577 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Tue, 20 Jun 2023 03:20:44 +0200 Subject: [PATCH 15/21] Forgot to include target pos --- src/main/java/baritone/process/BuilderProcess.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 62f865899..bd14d09a7 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -899,6 +899,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil @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; From 367ce5fa177cb6806937f37983932076bcd38172 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 14 Jun 2023 16:11:11 -0500 Subject: [PATCH 16/21] cherry pick Allow freeLook when using elytra --- .../api/event/events/RotationMoveEvent.java | 38 ++++++++- .../launch/mixins/MixinEntityLivingBase.java | 85 +++++++++++++++---- .../launch/mixins/MixinEntityPlayerSP.java | 16 ---- .../launch/mixins/MixinMinecraft.java | 15 ++++ .../java/baritone/behavior/LookBehavior.java | 1 + 5 files changed, 117 insertions(+), 38 deletions(-) diff --git a/src/api/java/baritone/api/event/events/RotationMoveEvent.java b/src/api/java/baritone/api/event/events/RotationMoveEvent.java index 109061c7e..a2ab17ed6 100644 --- a/src/api/java/baritone/api/event/events/RotationMoveEvent.java +++ b/src/api/java/baritone/api/event/events/RotationMoveEvent.java @@ -17,6 +17,7 @@ package baritone.api.event.events; +import baritone.api.utils.Rotation; import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; @@ -31,14 +32,27 @@ public final class RotationMoveEvent { */ private final Type type; + private final Rotation original; + /** * The yaw rotation */ private float yaw; - public RotationMoveEvent(Type type, float yaw) { + /** + * The pitch rotation + */ + private float pitch; + + public RotationMoveEvent(Type type, float yaw, float pitch) { this.type = type; + this.original = new Rotation(yaw, pitch); this.yaw = yaw; + this.pitch = pitch; + } + + public Rotation getOriginal() { + return this.original; } /** @@ -46,21 +60,37 @@ public final class RotationMoveEvent { * * @param yaw Yaw rotation */ - public final void setYaw(float yaw) { + public void setYaw(float yaw) { this.yaw = yaw; } /** * @return The yaw rotation */ - public final float getYaw() { + public float getYaw() { return this.yaw; } + /** + * Set the pitch movement rotation + * + * @param pitch Pitch rotation + */ + public void setPitch(float pitch) { + this.pitch = pitch; + } + + /** + * @return The pitch rotation + */ + public float getPitch() { + return pitch; + } + /** * @return The type of the event */ - public final Type getType() { + public Type getType() { return this.type; } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java index 0fd2436c9..f8544dd2f 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityLivingBase.java @@ -25,11 +25,14 @@ import net.minecraft.entity.Entity; import net.minecraft.entity.EntityLivingBase; import net.minecraft.world.World; import org.spongepowered.asm.mixin.Mixin; +import org.spongepowered.asm.mixin.Unique; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Redirect; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; +import java.util.Optional; + import static org.spongepowered.asm.lib.Opcodes.GETFIELD; /** @@ -42,11 +45,14 @@ public abstract class MixinEntityLivingBase extends Entity { /** * Event called to override the movement direction when jumping */ + @Unique private RotationMoveEvent jumpRotationEvent; - public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) { + @Unique + private RotationMoveEvent elytraRotationEvent; + + public MixinEntityLivingBase(World worldIn) { super(worldIn); - this.jumpRotationEvent = jumpRotationEvent; } @Inject( @@ -54,14 +60,10 @@ public abstract class MixinEntityLivingBase extends Entity { at = @At("HEAD") ) private void preMoveRelative(CallbackInfo ci) { - // noinspection ConstantConditions - if (EntityPlayerSP.class.isInstance(this)) { - IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this); - if (baritone != null) { - this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw); - baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent); - } - } + this.getBaritone().ifPresent(baritone -> { + this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw, this.rotationPitch); + baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent); + }); } @Redirect( @@ -79,6 +81,38 @@ public abstract class MixinEntityLivingBase extends Entity { return self.rotationYaw; } + @Inject( + method = "travel", + at = @At( + value = "INVOKE", + target = "net/minecraft/entity/EntityLivingBase.getLookVec()Lnet/minecraft/util/math/Vec3d;" + ) + ) + private void onPreElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) { + this.getBaritone().ifPresent(baritone -> { + this.elytraRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch); + baritone.getGameEventHandler().onPlayerRotationMove(this.elytraRotationEvent); + this.rotationYaw = this.elytraRotationEvent.getYaw(); + this.rotationPitch = this.elytraRotationEvent.getPitch(); + }); + } + + @Inject( + method = "travel", + at = @At( + value = "INVOKE", + target = "net/minecraft/entity/EntityLivingBase.move(Lnet/minecraft/entity/MoverType;DDD)V", + shift = At.Shift.AFTER + ) + ) + private void onPostElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) { + if (this.elytraRotationEvent != null) { + this.rotationYaw = this.elytraRotationEvent.getOriginal().getYaw(); + this.rotationPitch = this.elytraRotationEvent.getOriginal().getPitch(); + this.elytraRotationEvent = null; + } + } + @Redirect( method = "travel", at = @At( @@ -86,17 +120,32 @@ public abstract class MixinEntityLivingBase extends Entity { target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V" ) ) - private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) { - // noinspection ConstantConditions - if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) { + private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) { + Optional baritone = this.getBaritone(); + if (!baritone.isPresent()) { moveRelative(strafe, up, forward, friction); return; } - RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw); - BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent); - float originalYaw = this.rotationYaw; - this.rotationYaw = motionUpdateRotationEvent.getYaw(); + + RotationMoveEvent event = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch); + baritone.get().getGameEventHandler().onPlayerRotationMove(event); + + this.rotationYaw = event.getYaw(); + this.rotationPitch = event.getPitch(); + this.moveRelative(strafe, up, forward, friction); - this.rotationYaw = originalYaw; + + this.rotationYaw = event.getOriginal().getYaw(); + this.rotationPitch = event.getOriginal().getPitch(); + } + + @Unique + private Optional getBaritone() { + // noinspection ConstantConditions + if (EntityPlayerSP.class.isInstance(this)) { + return Optional.ofNullable(BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this)); + } else { + return Optional.empty(); + } } } diff --git a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java index 4f6031d78..281ff96f5 100644 --- a/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java +++ b/src/launch/java/baritone/launch/mixins/MixinEntityPlayerSP.java @@ -72,22 +72,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/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 67aa45e39..d3c514ac2 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -149,6 +149,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null) { event.setYaw(this.target.rotation.getYaw()); + event.setPitch(this.target.rotation.getPitch()); } } From 7e426bd2e8ad15ba571b9775fdf779fc09390318 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 17:35:47 -0500 Subject: [PATCH 17/21] AimProcessor API --- .../baritone/api/behavior/ILookBehavior.java | 19 +- .../api/behavior/look/IAimProcessor.java | 44 ++++ .../java/baritone/behavior/LookBehavior.java | 188 +++++++++++++----- .../behavior/look/ForkableRandom.java | 85 ++++++++ 4 files changed, 283 insertions(+), 53 deletions(-) create mode 100644 src/api/java/baritone/api/behavior/look/IAimProcessor.java create mode 100644 src/main/java/baritone/behavior/look/ForkableRandom.java diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java index 218e8b59a..eb7c992b8 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; /** @@ -27,10 +29,25 @@ public interface ILookBehavior extends IBehavior { /** * 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}. + * 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 blockInteract Whether the target rotations are needed for a block interaction */ 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}. Whenever {@link IAimProcessor#nextRotation(Rotation)} + * is called on the instance returned by this method, the returned value 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(int) fork} should be created. + * + * @return The aim processor + * @see IAimProcessor#fork(int) + */ + 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..72a4c681d --- /dev/null +++ b/src/api/java/baritone/api/behavior/look/IAimProcessor.java @@ -0,0 +1,44 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.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. This is not guaranteed to + * return the same value for a given input. + * + * @param desired The desired rotation to set + * @return The actual rotation + */ + Rotation nextRotation(Rotation desired); + + /** + * Returns a copy of this {@link IAimProcessor} which has its own internal state and updates on each call to + * {@link #nextRotation(Rotation)}. + * + * @param ticksAdvanced The number of ticks to advance ahead of time + * @return The forked processor + */ + IAimProcessor fork(int ticksAdvanced); +} diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index d3c514ac2..aeb694181 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -20,13 +20,11 @@ package baritone.behavior; import baritone.Baritone; import baritone.api.Settings; import baritone.api.behavior.ILookBehavior; -import baritone.api.event.events.PacketEvent; -import baritone.api.event.events.PlayerUpdateEvent; -import baritone.api.event.events.RotationMoveEvent; -import baritone.api.event.events.WorldEvent; -import baritone.api.utils.Helper; +import baritone.api.behavior.look.IAimProcessor; +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; @@ -44,14 +42,17 @@ public final class LookBehavior extends Behavior implements ILookBehavior { private Rotation serverRotation; /** - * The last player rotation. Used when free looking + * The last player rotation. Used to restore the player's angle when using free look. * * @see Settings#freeLook */ private Rotation prevRotation; + private final AimProcessor processor; + public LookBehavior(Baritone baritone) { super(baritone); + this.processor = new AimProcessor(baritone.getPlayerContext()); } @Override @@ -59,6 +60,19 @@ public final class LookBehavior extends Behavior implements ILookBehavior { 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) { + // Unlike forked AimProcessors, the root one needs to be manually updated each game tick + this.processor.tick(); + } + } + @Override public void onPlayerUpdate(PlayerUpdateEvent event) { if (this.target == null) { @@ -67,34 +81,16 @@ public final class LookBehavior extends Behavior implements ILookBehavior { switch (event.getState()) { case PRE: { if (this.target.mode == Target.Mode.NONE) { + // Just return for PRE, we still want to set target to null on POST return; } if (this.target.mode == Target.Mode.SERVER) { this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch); } - final float oldYaw = ctx.playerRotations().getYaw(); - final float oldPitch = ctx.playerRotations().getPitch(); - - float desiredYaw = this.target.rotation.getYaw(); - float desiredPitch = this.target.rotation.getPitch(); - - // In other words, the target doesn't care about the pitch, so it used playerRotations().getPitch() - // and it's safe to adjust it to a normal level - if (desiredPitch == oldPitch) { - desiredPitch = nudgeToLevel(desiredPitch); - } - - desiredYaw += (Math.random() - 0.5) * Baritone.settings().randomLooking.value; - desiredPitch += (Math.random() - 0.5) * Baritone.settings().randomLooking.value; - - ctx.player().rotationYaw = calculateMouseMove(oldYaw, desiredYaw); - ctx.player().rotationPitch = calculateMouseMove(oldPitch, desiredPitch); - - if (this.target.mode == Target.Mode.CLIENT) { - // The target can be invalidated now since it won't be needed for RotationMoveEvent - this.target = null; - } + final Rotation actual = this.processor.nextRotation(this.target.rotation); + ctx.player().rotationYaw = actual.getYaw(); + ctx.player().rotationPitch = actual.getPitch(); break; } case POST: { @@ -133,7 +129,8 @@ public final class LookBehavior extends Behavior implements ILookBehavior { public void pig() { if (this.target != null) { - ctx.player().rotationYaw = this.target.rotation.getYaw(); + final Rotation actual = this.processor.nextRotation(this.target.rotation); + ctx.player().rotationYaw = actual.getYaw(); } } @@ -148,37 +145,124 @@ public final class LookBehavior extends Behavior implements ILookBehavior { @Override public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null) { - event.setYaw(this.target.rotation.getYaw()); - event.setPitch(this.target.rotation.getPitch()); + final Rotation actual = this.target.rotation; + event.setYaw(actual.getYaw()); + event.setPitch(actual.getPitch()); } } - /** - * Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1}) - */ - private static float nudgeToLevel(float pitch) { - if (pitch < -20) { - return pitch + 1; - } else if (pitch > 10) { - return pitch - 1; + private static final class AimProcessor extends AbstractAimProcessor { + + public AimProcessor(final IPlayerContext ctx) { + super(ctx); + } + + @Override + protected Rotation getPrevRotation() { + // Implementation will use LookBehavior.serverRotation + return ctx.playerRotations(); } - return pitch; } - private float calculateMouseMove(float current, float target) { - final float delta = target - current; - final int deltaPx = angleToMouse(delta); - return current + mouseToAngle(deltaPx); - } + private static abstract class AbstractAimProcessor implements IAimProcessor { - private int angleToMouse(float angleDelta) { - final float minAngleChange = mouseToAngle(1); - return Math.round(angleDelta / minAngleChange); - } + protected final IPlayerContext ctx; + private final ForkableRandom rand; + private double randomYawOffset; + private double randomPitchOffset; - 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; + 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; + } + + public 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 Rotation nextRotation(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) + ); + } + + @Override + public final IAimProcessor fork(final int ticksAdvanced) { + final AbstractAimProcessor fork = new AbstractAimProcessor(this) { + + private Rotation prev = AbstractAimProcessor.this.getPrevRotation(); + + @Override + public Rotation nextRotation(Rotation rotation) { + final Rotation actual = super.nextRotation(rotation); + this.tick(); + return (this.prev = actual); + } + + @Override + protected Rotation getPrevRotation() { + return this.prev; + } + }; + for (int i = 0; i < ticksAdvanced; i++) { + fork.tick(); + } + return fork; + } + + 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 { 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)); + } +} From 0682e6370713961c31a56871bc32b924120556f3 Mon Sep 17 00:00:00 2001 From: Brady Date: Wed, 21 Jun 2023 17:39:04 -0500 Subject: [PATCH 18/21] Apply processor to RotationMoveEvent --- src/main/java/baritone/behavior/LookBehavior.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index aeb694181..57dfd206c 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -145,7 +145,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { @Override public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null) { - final Rotation actual = this.target.rotation; + final Rotation actual = this.processor.nextRotation(this.target.rotation); event.setYaw(actual.getYaw()); event.setPitch(actual.getPitch()); } From bfae100cb91b28ab41a4378997cbbc32d85f5217 Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 20:35:22 -0500 Subject: [PATCH 19/21] Create `ITickableAimProcessor` --- .../baritone/api/behavior/ILookBehavior.java | 9 ++-- .../api/behavior/look/IAimProcessor.java | 15 +++--- .../behavior/look/ITickableAimProcessor.java | 47 +++++++++++++++++ .../java/baritone/behavior/LookBehavior.java | 51 +++++++++++-------- 4 files changed, 88 insertions(+), 34 deletions(-) create mode 100644 src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java index eb7c992b8..d78e7f8b3 100644 --- a/src/api/java/baritone/api/behavior/ILookBehavior.java +++ b/src/api/java/baritone/api/behavior/ILookBehavior.java @@ -40,14 +40,11 @@ public interface ILookBehavior extends IBehavior { 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}. Whenever {@link IAimProcessor#nextRotation(Rotation)} - * is called on the instance returned by this method, the returned value 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(int) fork} should be created. + * 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(int) + * @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 index 72a4c681d..c7c60f413 100644 --- a/src/api/java/baritone/api/behavior/look/IAimProcessor.java +++ b/src/api/java/baritone/api/behavior/look/IAimProcessor.java @@ -25,20 +25,21 @@ import baritone.api.utils.Rotation; public interface IAimProcessor { /** - * Returns the actual rotation that will be used when the desired rotation is requested. This is not guaranteed to - * return the same value for a given input. + * 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 nextRotation(Rotation desired); + Rotation peekRotation(Rotation desired); /** - * Returns a copy of this {@link IAimProcessor} which has its own internal state and updates on each call to - * {@link #nextRotation(Rotation)}. + * Returns a copy of this {@link IAimProcessor} which has its own internal state and is manually tickable. * - * @param ticksAdvanced The number of ticks to advance ahead of time * @return The forked processor + * @see ITickableAimProcessor */ - IAimProcessor fork(int ticksAdvanced); + ITickableAimProcessor fork(); } diff --git a/src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java b/src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java new file mode 100644 index 000000000..e0a07ae57 --- /dev/null +++ b/src/api/java/baritone/api/behavior/look/ITickableAimProcessor.java @@ -0,0 +1,47 @@ +/* + * 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 ITickableAimProcessor extends IAimProcessor { + + /** + * Advances the internal state of this aim processor by a single tick. + */ + void tick(); + + /** + * 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/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java index 57dfd206c..4ea0274d7 100644 --- a/src/main/java/baritone/behavior/LookBehavior.java +++ b/src/main/java/baritone/behavior/LookBehavior.java @@ -21,6 +21,7 @@ import baritone.Baritone; import baritone.api.Settings; import baritone.api.behavior.ILookBehavior; 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; @@ -68,7 +69,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior { @Override public void onTick(TickEvent event) { if (event.getType() == TickEvent.Type.IN) { - // Unlike forked AimProcessors, the root one needs to be manually updated each game tick this.processor.tick(); } } @@ -88,7 +88,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch); } - final Rotation actual = this.processor.nextRotation(this.target.rotation); + final Rotation actual = this.processor.peekRotation(this.target.rotation); ctx.player().rotationYaw = actual.getYaw(); ctx.player().rotationPitch = actual.getPitch(); break; @@ -129,7 +129,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { public void pig() { if (this.target != null) { - final Rotation actual = this.processor.nextRotation(this.target.rotation); + final Rotation actual = this.processor.peekRotation(this.target.rotation); ctx.player().rotationYaw = actual.getYaw(); } } @@ -145,7 +145,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { @Override public void onPlayerRotationMove(RotationMoveEvent event) { if (this.target != null) { - final Rotation actual = this.processor.nextRotation(this.target.rotation); + final Rotation actual = this.processor.peekRotation(this.target.rotation); event.setYaw(actual.getYaw()); event.setPitch(actual.getPitch()); } @@ -164,7 +164,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior { } } - private static abstract class AbstractAimProcessor implements IAimProcessor { + private static abstract class AbstractAimProcessor implements ITickableAimProcessor { protected final IPlayerContext ctx; private final ForkableRandom rand; @@ -183,13 +183,8 @@ public final class LookBehavior extends Behavior implements ILookBehavior { this.randomPitchOffset = source.randomPitchOffset; } - public 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 Rotation nextRotation(final Rotation rotation) { + public final Rotation peekRotation(final Rotation rotation) { final Rotation prev = this.getPrevRotation(); float desiredYaw = rotation.getYaw(); @@ -211,16 +206,34 @@ public final class LookBehavior extends Behavior implements ILookBehavior { } @Override - public final IAimProcessor fork(final int ticksAdvanced) { - final AbstractAimProcessor fork = new AbstractAimProcessor(this) { + 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(Rotation rotation) { - final Rotation actual = super.nextRotation(rotation); - this.tick(); - return (this.prev = actual); + public Rotation nextRotation(final Rotation rotation) { + return (this.prev = super.nextRotation(rotation)); } @Override @@ -228,10 +241,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior { return this.prev; } }; - for (int i = 0; i < ticksAdvanced; i++) { - fork.tick(); - } - return fork; } protected abstract Rotation getPrevRotation(); From c9a18caf492f6ccba6cb04223573e9aeb41da7cd Mon Sep 17 00:00:00 2001 From: Brady Date: Thu, 22 Jun 2023 20:38:00 -0500 Subject: [PATCH 20/21] Register `LookBehavior` first Since there's no event priority system, this is necessary to ensure anything else listening to the PRE `TickEvent` can accurately simulate rotations. --- src/main/java/baritone/Baritone.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java index 776e646af..957421970 100755 --- a/src/main/java/baritone/Baritone.java +++ b/src/main/java/baritone/Baritone.java @@ -101,8 +101,8 @@ public class Baritone implements IBaritone { this.playerContext = new BaritonePlayerContext(this, mc); { - this.pathingBehavior = this.registerBehavior(PathingBehavior::new); 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); From e3a1ac85cce9605f99f2d0db97f7a852ca768f30 Mon Sep 17 00:00:00 2001 From: ZacSharp <68165024+ZacSharp@users.noreply.github.com> Date: Fri, 23 Jun 2023 02:28:52 +0200 Subject: [PATCH 21/21] Fix waiting for impossible rotations --- src/api/java/baritone/api/utils/RotationUtils.java | 3 ++- src/main/java/baritone/pathing/movement/MovementHelper.java | 3 ++- src/main/java/baritone/process/BuilderProcess.java | 5 +++-- 3 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java index b3b67d9ca..9fc65df9f 100644 --- a/src/api/java/baritone/api/utils/RotationUtils.java +++ b/src/api/java/baritone/api/utils/RotationUtils.java @@ -217,7 +217,8 @@ public final class RotationUtils { public static Optional reachableOffset(IPlayerContext ctx, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) { Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.player().getPositionEyes(1.0F); Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, ctx.playerRotations()); - RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rotation, blockReachDistance, wouldSneak); + 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)) { diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java index b14b2d69c..881bb6f15 100644 --- a/src/main/java/baritone/pathing/movement/MovementHelper.java +++ b/src/main/java/baritone/pathing/movement/MovementHelper.java @@ -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/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index bd14d09a7..60066971e 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -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)); }