diff --git a/SETUP.md b/SETUP.md index 1daeb9f89..1bf6e5dbd 100644 --- a/SETUP.md +++ b/SETUP.md @@ -1,78 +1,87 @@ # Installation -The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone. - -You can also use a custom version json for Minecraft, with the [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1) version or the [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1) version or the [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1) version. +The easiest way to install Baritone is to install it as Forge/Neoforge/Fabric mod, but if you know how you can also use with a custom `version.json` +(Examples: [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1), [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1), [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1)). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it. ## Prebuilt official releases -These releases are not always completely up to date with latest features, and are only released from `master`. (so if you want `backfill-2` branch for example, you'll have to build it yourself) +Releases are made rarely and are not always up to date with the latest features and bug fixes. Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases) -v1.2.* is for 1.12.2, v1.3.* is for 1.13.2, v1.4.* is for 1.14.4, v1.5.* is for 1.15.2, v1.6.* is for 1.16.5, v1.7.* is for 1.17.1, v1.8.* is for 1.18.1 +The mapping between major Minecraft versions and major Baritone versions is as follows +| Minecraft version | 1.12 | 1.13 | 1.14 | 1.15 | 1.16 | 1.17 | 1.18 | 1.19 | 1.20 | 1.21 | +|-------------------|------|------|------|------|------|------|------|------|-------|-------| +| Baritone version | v1.2 | v1.3 | v1.4 | v1.5 | v1.6 | v1.7 | v1.8 | v1.9 | v1.10 | v1.11 | Any official release will be GPG signed by leijurv (44A3EA646EADAC6A). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by that public keys of `checksums.txt`. -The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too). +The build is fully deterministic and reproducible, and you can verify that by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too). ## Artifacts -Building Baritone will result in 5 artifacts created in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases). +Building Baritone will create the final artifacts in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases). -**The Forge and Fabric releases can simply be added as a Forge/Fabric mods.** +**The Forge, NeoForge and Fabric releases can simply be added as a Forge/Neoforge/Fabric mods.** -If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar` +If another one of your other mods has a Baritone integration, you want `baritone-api-*-VERSION.jar`. +If you want to report a bug and spare us some effort, you want `baritone-unoptimized-*-VERSION.jar`. +Otherwise, you want `baritone-standalone-*-VERSION.jar` +Here's what the various qualifiers mean - **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features. -- **Forge/Fabric API**: Same as API, but packaged for Forge/Fabric. This should be used where another mod has a Baritone integration. -- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features. -- **Forge/Fabric Standalone**: Same as Standalone, but packaged for Forge/Fabric. This should be used when Baritone is your only Forge/Fabric mod, or none of your other Forge/Fabric mods integrate with Baritone. -- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production. -- **Forge/Fabric Unoptimized**: Same as Unoptimized, but packaged for Forge/Fabric. +- **Standalone**: Everything is obfuscated. Other mods cannot use Baritone, but you get a bit of extra performance. +- **Unoptimized**: Nothing is obfuscated. This shouldn't be used in production, but is really helpful for crash reports. + +- **No loader**: Loadable as a launchwrapper tweaker against vanilla Minecraft using a custom `version.json`. +- **Forge/Neoforge/Fabric**: Loadable as a standard mod using the respective loader. The fabric build may or may not work on Quilt. + +If you build from source you will also find mapping files in the `dist` directory. These contain the renamings done by ProGuard and are useful if you want to read obfuscated stack traces. ## Build it yourself - Clone or download Baritone ![Image](https://i.imgur.com/kbqBtoN.png) - - If you choose to download, make sure you extract the ZIP archive. + - If you choose to download, make sure you download the correct branch and extract the ZIP archive. - Follow one of the instruction sets below, based on your preference ## Command Line On Mac OSX and Linux, use `./gradlew` instead of `gradlew`. -If you have errors with a package missing please make sure you have setup your environment, and are using Oracle JDK 8 for 1.12.2-1.16.5, JDK 16+ for 1.17.1, and JDK 17+ for 1.18.1. - -To check which java you are using do -`java -version` in a command prompt or terminal. -If you are using anything above OpenJDK 8 for 1.12.2-1.16.5, it might not work because the Java distributions above JDK 8 using may not have the needed javax classes. +The recommended Java versions by Minecraft version are +| Minecraft version | Java version | +|-------------------------------|---------------| +| 1.12.2 - 1.16.5 | 8 | +| 1.17.1 | 16 | +| 1.18.2 - 1.20.4 | 17 | +| 1.20.5 - 1.21.4 | 21 | Download java: https://adoptium.net/ -#### macOS guide -In order to get JDK 8, Try running the following command: -`% /usr/libexec/java_home -V` -If it doesn't work try this guide: https://stackoverflow.com/questions/46513639/how-to-downgrade-java-from-9-to-8-on-a-macos-eclipse-is-not-running-with-java-9 -If you see something like - -`% 1.8.0_VERSION, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_VERSION.jdk/Contents/Home` - -in the list then you've got JDK 8 installed. -In order to get JDK 8 running in the **current terminal window** you will have to run this command: - -`% export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)` - -To add OpenJDK 8 to your PATH add the export line to the end of your `.zshrc / .bashrc` if you want it to apply to each new terminal. If you're using bash change the .bachrc and if you're using zsh change the .zshrc +To check which java version you are using do `java -version` in a command prompt or terminal. ### Building Baritone These tasks depend on the minecraft version, but are (for the most part) standard for building mods. -for more details, see [the build ci action](/.github/workflows/gradle_build.yml) +For more details, see [the build ci action](/.github/workflows/gradle_build.yml) of the branch you want to build. + +For most branches `gradlew build` should build everything, but there are exceptions and this file might be out of date. + +More specifically, on older branches the setup used to be that `gradlew build` builds the tweaker jar +and `gradlew build -Pbaritone.forge_build` / `gradlew build -Pbaritone.fabric_build` are needed to build +for Forge/Fabric instead. And you might have to run `setupDecompWorkspace` first. ## IntelliJ - Open the project in IntelliJ as a Gradle project - Refresh the Gradle project (or, to be safe, just restart IntelliJ) -- depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working \ No newline at end of file +- Depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working + +## Github Actions +Most branches have a CI workflow at `.github/workflows/gradle_build.yml`. If you fork this repository and enable actions for your fork +you can push a dummy commit to trigger it and have GitHub build Baritone for you. + +If the commit you want to build is less than 90 days old, you can also find the corresponding workflow run in +[this list](https://github.com/cabaletta/baritone/actions/workflows/gradle_build.yml) and download the artifacts from there. diff --git a/build.gradle b/build.gradle index 45531e2cb..8030b570d 100755 --- a/build.gradle +++ b/build.gradle @@ -38,7 +38,7 @@ allprojects { group = rootProject.maven_group sourceCompatibility = targetCompatibility = JavaVersion.toVersion(project.java_version) - + java { toolchain { languageVersion.set(JavaLanguageVersion.of(sourceCompatibility.majorVersion.toInteger())) diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json index d4bf5e0b8..1aff9a0c8 100644 --- a/fabric/src/main/resources/fabric.mod.json +++ b/fabric/src/main/resources/fabric.mod.json @@ -10,7 +10,8 @@ ], "contact": { "homepage": "https://github.com/cabaletta/baritone", - "sources": "https://github.com/cabaletta/baritone" + "sources": "https://github.com/cabaletta/baritone", + "issues": "https://github.com/cabaletta/baritone/issues" }, "license": "LGPL-3.0", @@ -26,5 +27,12 @@ "depends": { "fabricloader": ">=0.14.22", "minecraft": ["1.21","1.21.1"] + }, + "custom": { + "modmenu": { + "links": { + "modmenu.discord": "https://discord.gg/s6fRBAUpmr" + } + } } } diff --git a/scripts/proguard.pro b/scripts/proguard.pro index 34b76170f..0b764e4d9 100644 --- a/scripts/proguard.pro +++ b/scripts/proguard.pro @@ -54,6 +54,11 @@ -dontwarn baritone.utils.schematic.schematica.** -dontwarn baritone.utils.schematic.litematica.** +# nether-pathfinder uses JNI to acess its own classes +# and some of our builds include it before running proguard +# conservatively keep all of it, even though only PathSegment. is needed +-keep,allowoptimization class dev.babbaj.pathfinder.** { *; } + # Keep - Applications. Keep all application classes, along with their 'main' # methods. -keepclasseswithmembers public class * { diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index d9cb501ef..44dabae2a 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -77,6 +77,16 @@ public final class Settings { */ public final Setting allowPlace = new Setting<>(true); + /** + * Allow Baritone to place blocks in fluid source blocks + */ + public final Setting allowPlaceInFluidsSource = new Setting<>(true); + + /** + * Allow Baritone to place blocks in flowing fluid + */ + public final Setting allowPlaceInFluidsFlow = new Setting<>(true); + /** * Allow Baritone to move items in your inventory to your hotbar */ @@ -1225,6 +1235,11 @@ public final class Settings { */ public final Setting followRadius = new Setting<>(3); + /** + * The maximum distance to the entity you're following + */ + public final Setting followTargetMaxDistance = new Setting<>(0); + /** * Turn this on if your exploration filter is enormous, you don't want it to check if it's done, * and you are just fine with it just hanging on completion diff --git a/src/api/java/baritone/api/command/datatypes/BlockById.java b/src/api/java/baritone/api/command/datatypes/BlockById.java index 67c04ebb0..c0f05eed4 100644 --- a/src/api/java/baritone/api/command/datatypes/BlockById.java +++ b/src/api/java/baritone/api/command/datatypes/BlockById.java @@ -23,17 +23,11 @@ import net.minecraft.core.registries.BuiltInRegistries; import net.minecraft.resources.ResourceLocation; import net.minecraft.world.level.block.Block; -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 = ResourceLocation.parse(ctx.getConsumer().getString()); @@ -48,10 +42,6 @@ public enum BlockById implements IDatatypeFor { public Stream tabComplete(IDatatypeContext ctx) throws CommandException { String arg = ctx.getConsumer().getString(); - if (!PATTERN.matcher(arg).matches()) { - return Stream.empty(); - } - return new TabCompleteHelper() .append( BuiltInRegistries.BLOCK.keySet() diff --git a/src/api/java/baritone/api/command/datatypes/ItemById.java b/src/api/java/baritone/api/command/datatypes/ItemById.java new file mode 100644 index 000000000..2c238f495 --- /dev/null +++ b/src/api/java/baritone/api/command/datatypes/ItemById.java @@ -0,0 +1,53 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.api.command.datatypes; + +import baritone.api.command.exception.CommandException; +import baritone.api.command.helpers.TabCompleteHelper; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; + +import java.util.stream.Stream; + +public enum ItemById implements IDatatypeFor { + INSTANCE; + + @Override + public Item get(IDatatypeContext ctx) throws CommandException { + ResourceLocation id = ResourceLocation.parse(ctx.getConsumer().getString()); + Item item; + if ((item = BuiltInRegistries.ITEM.getOptional(id).orElse(null)) == null) { + throw new IllegalArgumentException("No item found by that id"); + } + return item; + } + + @Override + public Stream tabComplete(IDatatypeContext ctx) throws CommandException { + return new TabCompleteHelper() + .append( + BuiltInRegistries.BLOCK.keySet() + .stream() + .map(ResourceLocation::toString) + ) + .filterPrefixNamespaced(ctx.getConsumer().getString()) + .sortAlphabetically() + .stream(); + } +} diff --git a/src/api/java/baritone/api/command/helpers/TabCompleteHelper.java b/src/api/java/baritone/api/command/helpers/TabCompleteHelper.java index e11c7dd82..88f603205 100644 --- a/src/api/java/baritone/api/command/helpers/TabCompleteHelper.java +++ b/src/api/java/baritone/api/command/helpers/TabCompleteHelper.java @@ -212,7 +212,12 @@ public class TabCompleteHelper { * @return This {@link TabCompleteHelper} */ public TabCompleteHelper filterPrefixNamespaced(String prefix) { - return filterPrefix(ResourceLocation.parse(prefix).toString()); + ResourceLocation loc = ResourceLocation.tryParse(prefix); + if (loc == null) { + stream = Stream.empty(); + return this; + } + return filterPrefix(loc.toString()); } /** diff --git a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java index 49b6f708d..1a1b6e50c 100644 --- a/src/api/java/baritone/api/pathing/goals/GoalRunAway.java +++ b/src/api/java/baritone/api/pathing/goals/GoalRunAway.java @@ -44,7 +44,7 @@ public class GoalRunAway implements Goal { public GoalRunAway(double distance, Integer maintainY, BlockPos... from) { if (from.length == 0) { - throw new IllegalArgumentException(); + throw new IllegalArgumentException("Positions to run away from must not be empty"); } this.from = from; this.distanceSq = (int) (distance * distance); diff --git a/src/api/java/baritone/api/process/IFollowProcess.java b/src/api/java/baritone/api/process/IFollowProcess.java index 6f7f0a239..e3ed73006 100644 --- a/src/api/java/baritone/api/process/IFollowProcess.java +++ b/src/api/java/baritone/api/process/IFollowProcess.java @@ -17,9 +17,11 @@ package baritone.api.process; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.item.ItemStack; + import java.util.List; import java.util.function.Predicate; -import net.minecraft.world.entity.Entity; /** * @author Brady @@ -34,6 +36,13 @@ public interface IFollowProcess extends IBaritoneProcess { */ void follow(Predicate filter); + /** + * Try to pick up any items matching this predicate + * + * @param filter the predicate + */ + void pickup(Predicate filter); + /** * @return The entities that are currently being followed. null if not currently following, empty if nothing matches the predicate */ diff --git a/src/api/java/baritone/api/schematic/ISchematicSystem.java b/src/api/java/baritone/api/schematic/ISchematicSystem.java index c8f039070..385cc0514 100644 --- a/src/api/java/baritone/api/schematic/ISchematicSystem.java +++ b/src/api/java/baritone/api/schematic/ISchematicSystem.java @@ -21,6 +21,7 @@ import baritone.api.command.registry.Registry; import baritone.api.schematic.format.ISchematicFormat; import java.io.File; +import java.util.List; import java.util.Optional; /** @@ -41,4 +42,9 @@ public interface ISchematicSystem { * @return The corresponding format for the file, {@link Optional#empty()} if no candidates were found. */ Optional getByFile(File file); + + /** + * @return A list of file extensions used by supported formats + */ + List getFileExtensions(); } diff --git a/src/api/java/baritone/api/schematic/format/ISchematicFormat.java b/src/api/java/baritone/api/schematic/format/ISchematicFormat.java index 3fe045bcf..0ccf059b0 100644 --- a/src/api/java/baritone/api/schematic/format/ISchematicFormat.java +++ b/src/api/java/baritone/api/schematic/format/ISchematicFormat.java @@ -23,6 +23,7 @@ import baritone.api.schematic.IStaticSchematic; import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.util.List; /** * The base of a {@link ISchematic} file format @@ -42,4 +43,9 @@ public interface ISchematicFormat { * @return Whether or not the specified file matches this schematic format */ boolean isFileType(File file); + + /** + * @return A list of file extensions used by this format + */ + List getFileExtensions(); } diff --git a/src/api/java/baritone/api/utils/IPlayerContext.java b/src/api/java/baritone/api/utils/IPlayerContext.java index a97475a5b..de6d7cd58 100644 --- a/src/api/java/baritone/api/utils/IPlayerContext.java +++ b/src/api/java/baritone/api/utils/IPlayerContext.java @@ -99,6 +99,14 @@ public interface IPlayerContext { return new Rotation(player().getYRot(), player().getXRot()); } + /** + * Returns the player's eye height, taking into account whether or not the player is sneaking. + * + * @param ifSneaking Whether or not the player is sneaking + * @return The player's eye height + * @deprecated Use entity.getEyeHeight(Pose.CROUCHING) instead + */ + @Deprecated static double eyeHeight(boolean ifSneaking) { return ifSneaking ? 1.27 : 1.62; } diff --git a/src/api/java/baritone/api/utils/RayTraceUtils.java b/src/api/java/baritone/api/utils/RayTraceUtils.java index 5541f562b..354f9c87d 100644 --- a/src/api/java/baritone/api/utils/RayTraceUtils.java +++ b/src/api/java/baritone/api/utils/RayTraceUtils.java @@ -18,6 +18,7 @@ package baritone.api.utils; import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.Pose; import net.minecraft.world.level.ClipContext; import net.minecraft.world.phys.HitResult; import net.minecraft.world.phys.Vec3; @@ -62,6 +63,6 @@ public final class RayTraceUtils { } public static Vec3 inferSneakingEyePosition(Entity entity) { - return new Vec3(entity.getX(), entity.getY() + IPlayerContext.eyeHeight(true), entity.getZ()); + return new Vec3(entity.getX(), entity.getY() + entity.getEyeHeight(Pose.CROUCHING), entity.getZ()); } } diff --git a/src/launch/java/baritone/launch/mixins/MixinScreen.java b/src/launch/java/baritone/launch/mixins/MixinScreen.java index e87fef061..d7219121e 100644 --- a/src/launch/java/baritone/launch/mixins/MixinScreen.java +++ b/src/launch/java/baritone/launch/mixins/MixinScreen.java @@ -21,17 +21,19 @@ import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.event.events.ChatEvent; import baritone.utils.accessor.IGuiScreen; +import net.minecraft.client.gui.screens.Screen; import net.minecraft.network.chat.ClickEvent; import net.minecraft.network.chat.Style; import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.gen.Invoker; - -import java.net.URI; -import net.minecraft.client.gui.screens.Screen; import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; +import java.net.URI; + +import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX; + @Mixin(Screen.class) public abstract class MixinScreen implements IGuiScreen { @@ -42,9 +44,13 @@ public abstract class MixinScreen implements IGuiScreen { if (clickEvent == null) { return; } + String command = clickEvent.getValue(); + if (command == null || !command.startsWith(FORCE_COMMAND_PREFIX)) { + return; + } IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone(); if (baritone != null) { - baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(clickEvent.getValue())); + baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(command)); } cir.setReturnValue(true); cir.cancel(); diff --git a/src/main/java/baritone/command/defaults/BuildCommand.java b/src/main/java/baritone/command/defaults/BuildCommand.java index bb34254ae..f9ddd33ef 100644 --- a/src/main/java/baritone/command/defaults/BuildCommand.java +++ b/src/main/java/baritone/command/defaults/BuildCommand.java @@ -26,11 +26,13 @@ import baritone.api.command.datatypes.RelativeFile; import baritone.api.command.exception.CommandException; import baritone.api.command.exception.CommandInvalidStateException; import baritone.api.utils.BetterBlockPos; +import baritone.utils.schematic.SchematicSystem; import org.apache.commons.io.FilenameUtils; import java.io.File; import java.util.Arrays; import java.util.List; +import java.util.StringJoiner; import java.util.stream.Stream; public class BuildCommand extends Command { @@ -44,10 +46,29 @@ public class BuildCommand extends Command { @Override public void execute(String label, IArgConsumer args) throws CommandException { - File file = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile(); + final File file0 = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile(); + File file = file0; if (FilenameUtils.getExtension(file.getAbsolutePath()).isEmpty()) { file = new File(file.getAbsolutePath() + "." + Baritone.settings().schematicFallbackExtension.value); } + if (!file.exists()) { + if (file0.exists()) { + throw new CommandInvalidStateException(String.format( + "Cannot load %s because I do not know which schematic format" + + " that is. Please rename the file to include the correct" + + " file extension.", + file)); + } + throw new CommandInvalidStateException("Cannot find " + file); + } + if (!SchematicSystem.INSTANCE.getByFile(file).isPresent()) { + StringJoiner formats = new StringJoiner(", "); + SchematicSystem.INSTANCE.getFileExtensions().forEach(formats::add); + throw new CommandInvalidStateException(String.format( + "Unsupported schematic format. Reckognized file extensions are: %s", + formats + )); + } BetterBlockPos origin = ctx.playerFeet(); BetterBlockPos buildOrigin; if (args.hasAny()) { @@ -59,7 +80,7 @@ public class BuildCommand extends Command { } boolean success = baritone.getBuilderProcess().build(file.getName(), file, buildOrigin); if (!success) { - throw new CommandInvalidStateException("Couldn't load the schematic. Make sure to use the FULL file name, including the extension (e.g. blah.schematic)."); + throw new CommandInvalidStateException("Couldn't load the schematic. Either your schematic is corrupt or this is a bug."); } logDirect(String.format("Successfully loaded schematic for building\nOrigin: %s", buildOrigin)); } diff --git a/src/main/java/baritone/command/defaults/DefaultCommands.java b/src/main/java/baritone/command/defaults/DefaultCommands.java index c810d07c1..5228a7ae1 100644 --- a/src/main/java/baritone/command/defaults/DefaultCommands.java +++ b/src/main/java/baritone/command/defaults/DefaultCommands.java @@ -53,6 +53,7 @@ public final class DefaultCommands { new RenderCommand(baritone), new FarmCommand(baritone), new FollowCommand(baritone), + new PickupCommand(baritone), new ExploreFilterCommand(baritone), new ReloadAllCommand(baritone), new SaveAllCommand(baritone), diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java index 3f7b6bfd6..2f5eff352 100644 --- a/src/main/java/baritone/command/defaults/ElytraCommand.java +++ b/src/main/java/baritone/command/defaults/ElytraCommand.java @@ -216,7 +216,7 @@ public class ElytraCommand extends Command { final String osArch = System.getProperty("os.arch"); final String osName = System.getProperty("os.name"); return String.format( - "Legacy architectures are not supported. Your CPU is %s and your operating system is %s. " + + "Failed loading native library. Your CPU is %s and your operating system is %s. " + "Supported architectures are 64 bit x86, and 64 bit ARM. Supported operating systems are Windows, " + "Linux, and Mac", osArch, osName diff --git a/src/main/java/baritone/command/defaults/PickupCommand.java b/src/main/java/baritone/command/defaults/PickupCommand.java new file mode 100644 index 000000000..7967dd023 --- /dev/null +++ b/src/main/java/baritone/command/defaults/PickupCommand.java @@ -0,0 +1,82 @@ +/* + * This file is part of Baritone. + * + * Baritone is free software: you can redistribute it and/or modify + * it under the terms of the GNU Lesser General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Baritone is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with Baritone. If not, see . + */ + +package baritone.command.defaults; + +import baritone.api.IBaritone; +import baritone.api.command.Command; +import baritone.api.command.argument.IArgConsumer; +import baritone.api.command.datatypes.ItemById; +import baritone.api.command.exception.CommandException; +import net.minecraft.core.registries.BuiltInRegistries; +import net.minecraft.resources.ResourceLocation; +import net.minecraft.world.item.Item; + +import java.util.Arrays; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Stream; + +public class PickupCommand extends Command { + + public PickupCommand(IBaritone baritone) { + super(baritone, "pickup"); + } + + @Override + public void execute(String label, IArgConsumer args) throws CommandException { + Set collecting = new HashSet<>(); + while (args.hasAny()) { + Item item = args.getDatatypeFor(ItemById.INSTANCE); + collecting.add(item); + } + if (collecting.isEmpty()) { + baritone.getFollowProcess().pickup(stack -> true); + logDirect("Picking up all items"); + } else { + baritone.getFollowProcess().pickup(stack -> collecting.contains(stack.getItem())); + logDirect("Picking up these items:"); + collecting.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).forEach(this::logDirect); + } + } + + @Override + public Stream tabComplete(String label, IArgConsumer args) throws CommandException { + while (args.has(2)) { + if (args.peekDatatypeOrNull(ItemById.INSTANCE) == null) { + return Stream.empty(); + } + args.get(); + } + return args.tabCompleteDatatype(ItemById.INSTANCE); + } + + @Override + public String getShortDesc() { + return "Pickup items"; + } + + @Override + public List getLongDesc() { + return Arrays.asList( + "Usage:", + "> pickup - Pickup anything", + "> pickup <...> - Pickup certain items" + ); + } +} diff --git a/src/main/java/baritone/pathing/calc/AStarPathFinder.java b/src/main/java/baritone/pathing/calc/AStarPathFinder.java index 0537eac5f..1c58cbf20 100644 --- a/src/main/java/baritone/pathing/calc/AStarPathFinder.java +++ b/src/main/java/baritone/pathing/calc/AStarPathFinder.java @@ -22,6 +22,7 @@ import baritone.api.pathing.calc.IPath; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.movement.ActionCosts; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.SettingsUtil; import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.Moves; @@ -122,17 +123,39 @@ public final class AStarPathFinder extends AbstractNodeCostSearch { continue; } if (actionCost <= 0 || Double.isNaN(actionCost)) { - throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); + throw new IllegalStateException(String.format( + "%s from %s %s %s calculated implausible cost %s", + moves, + SettingsUtil.maybeCensor(currentNode.x), + SettingsUtil.maybeCensor(currentNode.y), + SettingsUtil.maybeCensor(currentNode.z), + actionCost)); } - // check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation + // check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218 continue; } if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) { - throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ); + throw new IllegalStateException(String.format( + "%s from %s %s %s ended at x z %s %s instead of %s %s", + moves, + SettingsUtil.maybeCensor(currentNode.x), + SettingsUtil.maybeCensor(currentNode.y), + SettingsUtil.maybeCensor(currentNode.z), + SettingsUtil.maybeCensor(res.x), + SettingsUtil.maybeCensor(res.z), + SettingsUtil.maybeCensor(newX), + SettingsUtil.maybeCensor(newZ))); } if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) { - throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset)); + throw new IllegalStateException(String.format( + "%s from %s %s %s ended at y %s instead of %s", + moves, + SettingsUtil.maybeCensor(currentNode.x), + SettingsUtil.maybeCensor(currentNode.y), + SettingsUtil.maybeCensor(currentNode.z), + SettingsUtil.maybeCensor(res.y), + SettingsUtil.maybeCensor(currentNode.y + moves.yOffset))); } long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z); if (isFavoring) { diff --git a/src/main/java/baritone/pathing/calc/Path.java b/src/main/java/baritone/pathing/calc/Path.java index 8f5dd52c2..eba408058 100644 --- a/src/main/java/baritone/pathing/calc/Path.java +++ b/src/main/java/baritone/pathing/calc/Path.java @@ -112,7 +112,7 @@ class Path extends PathBase { private boolean assembleMovements() { if (path.isEmpty() || !movements.isEmpty()) { - throw new IllegalStateException(); + throw new IllegalStateException("Path must not be empty"); } for (int i = 0; i < path.size() - 1; i++) { double cost = nodes.get(i + 1).cost - nodes.get(i).cost; @@ -145,7 +145,7 @@ class Path extends PathBase { @Override public IPath postProcess() { if (verified) { - throw new IllegalStateException(); + throw new IllegalStateException("Path must not be verified twice"); } verified = true; boolean failed = assembleMovements(); @@ -154,7 +154,7 @@ class Path extends PathBase { if (failed) { // at least one movement became impossible during calculation CutoffPath res = new CutoffPath(this, movements().size()); if (res.movements().size() != movements.size()) { - throw new IllegalStateException(); + throw new IllegalStateException("Path has wrong size after cutoff"); } return res; } @@ -166,7 +166,8 @@ class Path extends PathBase { @Override public List movements() { if (!verified) { - throw new IllegalStateException(); + // edge case note: this is called during verification + throw new IllegalStateException("Path not yet verified"); } return Collections.unmodifiableList(movements); } diff --git a/src/main/java/baritone/pathing/calc/PathNode.java b/src/main/java/baritone/pathing/calc/PathNode.java index 2b693338a..0911c6c04 100644 --- a/src/main/java/baritone/pathing/calc/PathNode.java +++ b/src/main/java/baritone/pathing/calc/PathNode.java @@ -20,6 +20,7 @@ package baritone.pathing.calc; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.movement.ActionCosts; import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.SettingsUtil; /** * A node in the path, containing the cost and steps to get to it. @@ -68,7 +69,12 @@ public final class PathNode { this.cost = ActionCosts.COST_INF; this.estimatedCostToGoal = goal.heuristic(x, y, z); if (Double.isNaN(estimatedCostToGoal)) { - throw new IllegalStateException(goal + " calculated implausible heuristic"); + throw new IllegalStateException(String.format( + "%s calculated implausible heuristic NaN at %s %s %s", + goal, + SettingsUtil.maybeCensor(x), + SettingsUtil.maybeCensor(y), + SettingsUtil.maybeCensor(z))); } this.heapPosition = -1; this.x = x; diff --git a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java index 33f077b9d..1da8ed7e5 100644 --- a/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java +++ b/src/main/java/baritone/pathing/calc/openset/BinaryHeapOpenSet.java @@ -92,7 +92,7 @@ public final class BinaryHeapOpenSet implements IOpenSet { @Override public final PathNode removeLowest() { if (size == 0) { - throw new IllegalStateException(); + throw new IllegalStateException("Cannot remove from empty heap"); } PathNode result = array[1]; PathNode val = array[size]; diff --git a/src/main/java/baritone/pathing/movement/CalculationContext.java b/src/main/java/baritone/pathing/movement/CalculationContext.java index 0d6ec1640..ad4cd5390 100644 --- a/src/main/java/baritone/pathing/movement/CalculationContext.java +++ b/src/main/java/baritone/pathing/movement/CalculationContext.java @@ -189,6 +189,12 @@ public class CalculationContext { if (!worldBorder.canPlaceAt(x, z)) { return COST_INF; } + if (!Baritone.settings().allowPlaceInFluidsSource.value && current.getFluidState().isSource()) { + return COST_INF; + } + if (!Baritone.settings().allowPlaceInFluidsFlow.value && !current.getFluidState().isEmpty() && !current.getFluidState().isSource()) { + return COST_INF; + } return placeBlockCost; } diff --git a/src/main/java/baritone/pathing/movement/Moves.java b/src/main/java/baritone/pathing/movement/Moves.java index 87b5db6ac..312c8957c 100644 --- a/src/main/java/baritone/pathing/movement/Moves.java +++ b/src/main/java/baritone/pathing/movement/Moves.java @@ -347,7 +347,7 @@ public enum Moves { public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) { if (dynamicXZ || dynamicY) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("Movements with dynamic offset must override `apply`"); } result.x = x + xOffset; result.y = y + yOffset; @@ -356,6 +356,6 @@ public enum Moves { } public double cost(CalculationContext context, int x, int y, int z) { - throw new UnsupportedOperationException(); + throw new UnsupportedOperationException("Movements must override `cost` or `apply`"); } } diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java index d760f3a38..8a5359b5b 100644 --- a/src/main/java/baritone/pathing/path/PathExecutor.java +++ b/src/main/java/baritone/pathing/path/PathExecutor.java @@ -455,7 +455,9 @@ public class PathExecutor implements IPathExecutor, Helper { if (data != null) { BetterBlockPos fallDest = new BetterBlockPos(data.getB()); if (!path.positions().contains(fallDest)) { - throw new IllegalStateException(); + throw new IllegalStateException(String.format( + "Fall override at %s %s %s returned illegal destination %s %s %s", + current.getSrc(), fallDest)); } if (ctx.playerFeet().equals(fallDest)) { pathPosition = path.positions().indexOf(fallDest); @@ -603,7 +605,9 @@ public class PathExecutor implements IPathExecutor, Helper { } return SplicedPath.trySplice(path, next.path, false).map(path -> { if (!path.getDest().equals(next.getPath().getDest())) { - throw new IllegalStateException(); + throw new IllegalStateException(String.format( + "Path has end %s instead of %s after splicing", + path.getDest(), next.getPath().getDest())); } PathExecutor ret = new PathExecutor(behavior, path); ret.pathPosition = pathPosition; @@ -619,7 +623,9 @@ public class PathExecutor implements IPathExecutor, Helper { int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.value; CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1); if (!newPath.getDest().equals(path.getDest())) { - throw new IllegalStateException(); + throw new IllegalStateException(String.format( + "Path has end %s instead of %s after trimming its start", + newPath.getDest(), path.getDest())); } logDebug("Discarding earliest segment movements, length cut from " + path.length() + " to " + newPath.length()); PathExecutor ret = new PathExecutor(behavior, newPath); diff --git a/src/main/java/baritone/pathing/path/SplicedPath.java b/src/main/java/baritone/pathing/path/SplicedPath.java index 1ba497d81..7f083a662 100644 --- a/src/main/java/baritone/pathing/path/SplicedPath.java +++ b/src/main/java/baritone/pathing/path/SplicedPath.java @@ -92,7 +92,7 @@ public class SplicedPath extends PathBase { } int positionInSecond = second.positions().indexOf(first.positions().get(firstPositionInSecond)); if (!allowOverlapCutoff && positionInSecond != 0) { - throw new IllegalStateException(); + throw new IllegalStateException("Paths to be spliced are overlapping incorrectly"); } List positions = new ArrayList<>(); List movements = new ArrayList<>(); diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java index 7ecb211f5..4c3182b52 100644 --- a/src/main/java/baritone/process/BuilderProcess.java +++ b/src/main/java/baritone/process/BuilderProcess.java @@ -441,7 +441,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil double z = side.getStepZ() == 0 ? 0.5 : (1 + side.getStepZ()) / 2D; return new Vec3[]{new Vec3(x, 0.25, z), new Vec3(x, 0.75, z)}; default: // null - throw new IllegalStateException(); + throw new IllegalStateException("Unexpected side " + side); } } diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java index d0dca9cbf..e101df74f 100644 --- a/src/main/java/baritone/process/CustomGoalProcess.java +++ b/src/main/java/baritone/process/CustomGoalProcess.java @@ -114,7 +114,7 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC } return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); default: - throw new IllegalStateException(); + throw new IllegalStateException("Unexpected state " + this.state); } } diff --git a/src/main/java/baritone/process/ExploreProcess.java b/src/main/java/baritone/process/ExploreProcess.java index 23fe7c23a..514a110e6 100644 --- a/src/main/java/baritone/process/ExploreProcess.java +++ b/src/main/java/baritone/process/ExploreProcess.java @@ -118,7 +118,9 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl int dz = (mult * 2 - 1) * zval; // dz can be either -zval or zval int trueDist = Math.abs(dx) + Math.abs(dz); if (trueDist != dist) { - throw new IllegalStateException(); + throw new IllegalStateException(String.format( + "Offset %s %s has distance %s, expected %s", + dx, dz, trueDist, dist)); } switch (filter.isAlreadyExplored(chunkX + dx, chunkZ + dz)) { case UNKNOWN: diff --git a/src/main/java/baritone/process/FollowProcess.java b/src/main/java/baritone/process/FollowProcess.java index b123216a6..0be7a4e80 100644 --- a/src/main/java/baritone/process/FollowProcess.java +++ b/src/main/java/baritone/process/FollowProcess.java @@ -19,6 +19,7 @@ package baritone.process; import baritone.Baritone; import baritone.api.pathing.goals.Goal; +import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalComposite; import baritone.api.pathing.goals.GoalNear; import baritone.api.pathing.goals.GoalXZ; @@ -27,11 +28,14 @@ import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommandType; import baritone.api.utils.BetterBlockPos; import baritone.utils.BaritoneProcessHelper; +import net.minecraft.core.BlockPos; +import net.minecraft.world.entity.Entity; +import net.minecraft.world.entity.item.ItemEntity; +import net.minecraft.world.item.ItemStack; + import java.util.List; import java.util.function.Predicate; import java.util.stream.Collectors; -import net.minecraft.core.BlockPos; -import net.minecraft.world.entity.Entity; /** * Follow an entity @@ -42,6 +46,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo private Predicate filter; private List cache; + private boolean into; // walk straight into the target, regardless of settings public FollowProcess(Baritone baritone) { super(baritone); @@ -56,12 +61,15 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo private Goal towards(Entity following) { BlockPos pos; - if (Baritone.settings().followOffsetDistance.value == 0) { + if (Baritone.settings().followOffsetDistance.value == 0 || into) { pos = following.blockPosition(); } else { GoalXZ g = GoalXZ.fromDirection(following.position(), Baritone.settings().followOffsetDirection.value, Baritone.settings().followOffsetDistance.value); pos = new BetterBlockPos(g.getX(), following.position().y, g.getZ()); } + if (into) { + return new GoalBlock(pos); + } return new GoalNear(pos, Baritone.settings().followRadius.value); } @@ -76,6 +84,10 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo if (entity.equals(ctx.player())) { return false; } + int maxDist = Baritone.settings().followTargetMaxDistance.value; + if (maxDist != 0 && entity.distanceToSqr(ctx.player()) > maxDist * maxDist) { + return false; + } return ctx.entitiesStream().anyMatch(entity::equals); } @@ -110,6 +122,13 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo @Override public void follow(Predicate filter) { this.filter = filter; + this.into = false; + } + + @Override + public void pickup(Predicate filter) { + this.filter = e -> e instanceof ItemEntity && filter.test(((ItemEntity) e).getItem()); + this.into = true; } @Override diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 6428cef5e..9a7a18f49 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -77,7 +77,6 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro int curr = ctx.player().getInventory().items.stream() .filter(stack -> filter.has(stack)) .mapToInt(ItemStack::getCount).sum(); - System.out.println("Currently have " + curr + " valid items"); if (curr >= desiredQuantity) { logDirect("Have " + curr + " valid items"); cancel(); @@ -119,7 +118,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro .filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ()) .filter(pos -> pos.getY() >= ctx.playerFeet().getY()) .filter(pos -> !(BlockStateInterface.get(ctx, pos).getBlock() instanceof AirBlock)) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =( - .min(Comparator.comparingDouble(ctx.playerFeet()::distSqr)); + .min(Comparator.comparingDouble(ctx.playerFeet().above()::distSqr)); baritone.getInputOverrideHandler().clearAllKeys(); if (shaft.isPresent() && ctx.player().onGround()) { BlockPos pos = shaft.get(); @@ -486,7 +485,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro public static boolean plausibleToBreak(CalculationContext ctx, BlockPos pos) { - if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), ctx.bsi.get0(pos), true) >= COST_INF) { + BlockState state = ctx.bsi.get0(pos); + if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), state, true) >= COST_INF) { + return false; + } + if (MovementHelper.avoidBreaking(ctx.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) { return false; } diff --git a/src/main/java/baritone/utils/BlockStateInterface.java b/src/main/java/baritone/utils/BlockStateInterface.java index 9708f40bc..1a1941584 100644 --- a/src/main/java/baritone/utils/BlockStateInterface.java +++ b/src/main/java/baritone/utils/BlockStateInterface.java @@ -70,7 +70,7 @@ public class BlockStateInterface { } this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value; if (!ctx.minecraft().isSameThread()) { - throw new IllegalStateException(); + throw new IllegalStateException("BlockStateInterface must be constructed on the main thread"); } this.isPassableBlockPos = new BlockPos.MutableBlockPos(); this.access = new BlockStateInterfaceAccessWrapper(this); diff --git a/src/main/java/baritone/utils/PathingControlManager.java b/src/main/java/baritone/utils/PathingControlManager.java index 3566cd23a..2205d62e7 100644 --- a/src/main/java/baritone/utils/PathingControlManager.java +++ b/src/main/java/baritone/utils/PathingControlManager.java @@ -68,7 +68,7 @@ public class PathingControlManager implements IPathingControlManager { for (IBaritoneProcess proc : processes) { proc.onLostControl(); if (proc.isActive() && !proc.isTemporary()) { // it's okay only for a temporary thing (like combat pause) to maintain control even if you say to cancel - throw new IllegalStateException(proc.displayName()); + throw new IllegalStateException(proc.displayName() + " stayed active after being cancelled"); } } } @@ -121,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager { } break; default: - throw new IllegalStateException(); + throw new IllegalStateException("Unexpected command type " + command.commandType); } } diff --git a/src/main/java/baritone/utils/schematic/SchematicSystem.java b/src/main/java/baritone/utils/schematic/SchematicSystem.java index 8afafa8c3..ec6e7f626 100644 --- a/src/main/java/baritone/utils/schematic/SchematicSystem.java +++ b/src/main/java/baritone/utils/schematic/SchematicSystem.java @@ -24,6 +24,7 @@ import baritone.utils.schematic.format.DefaultSchematicFormats; import java.io.File; import java.util.Arrays; +import java.util.List; import java.util.Optional; /** @@ -48,4 +49,9 @@ public enum SchematicSystem implements ISchematicSystem { public Optional getByFile(File file) { return this.registry.stream().filter(format -> format.isFileType(file)).findFirst(); } + + @Override + public List getFileExtensions() { + return this.registry.stream().map(ISchematicFormat::getFileExtensions).flatMap(List::stream).toList(); + } } diff --git a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java index f51eb371d..dde2c9939 100644 --- a/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java +++ b/src/main/java/baritone/utils/schematic/format/DefaultSchematicFormats.java @@ -22,14 +22,16 @@ import baritone.api.schematic.format.ISchematicFormat; import baritone.utils.schematic.format.defaults.LitematicaSchematic; import baritone.utils.schematic.format.defaults.MCEditSchematic; import baritone.utils.schematic.format.defaults.SpongeSchematic; +import net.minecraft.nbt.CompoundTag; import net.minecraft.nbt.NbtAccounter; +import net.minecraft.nbt.NbtIo; import org.apache.commons.io.FilenameUtils; import java.io.File; import java.io.IOException; import java.io.InputStream; -import net.minecraft.nbt.CompoundTag; -import net.minecraft.nbt.NbtIo; +import java.util.Collections; +import java.util.List; /** * Default implementations of {@link ISchematicFormat} @@ -101,4 +103,9 @@ public enum DefaultSchematicFormats implements ISchematicFormat { public boolean isFileType(File file) { return this.extension.equalsIgnoreCase(FilenameUtils.getExtension(file.getAbsolutePath())); } + + @Override + public List getFileExtensions() { + return Collections.singletonList(this.extension); + } } diff --git a/tweaker/build.gradle b/tweaker/build.gradle index 7bad8747f..766bbc82c 100644 --- a/tweaker/build.gradle +++ b/tweaker/build.gradle @@ -47,6 +47,7 @@ dependencies { implementation "org.ow2.asm:asm-util:${project.asm_version}" implementation "org.ow2.asm:asm-analysis:${project.asm_version}" + implementation 'com.github.ImpactDevelopment:SimpleTweaker:1.2' implementation('net.minecraft:launchwrapper:of-2.3') { exclude module: 'lwjgl'