diff --git a/.github/workflows/gradle_build.yml b/.github/workflows/gradle_build.yml
index 8f79f25f69..02fa9808eb 100644
--- a/.github/workflows/gradle_build.yml
+++ b/.github/workflows/gradle_build.yml
@@ -13,12 +13,12 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v4
with:
fetch-depth: 0
- name: Set up JDK 25
- uses: actions/setup-java@v5
+ uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'zulu'
@@ -31,13 +31,13 @@ jobs:
run: ./gradlew build -Pmod_version="$(git describe --always --tags --first-parent | cut -c2-)"
- name: Archive Artifacts
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@v4
with:
name: Artifacts
path: dist/
- name: Archive mapping.txt
- uses: actions/upload-artifact@v7
+ uses: actions/upload-artifact@v4
with:
name: Mappings
path: mapping/
diff --git a/.github/workflows/run_tests.yml b/.github/workflows/run_tests.yml
index 3637091872..459dca56ef 100644
--- a/.github/workflows/run_tests.yml
+++ b/.github/workflows/run_tests.yml
@@ -11,16 +11,15 @@ jobs:
runs-on: ubuntu-latest
steps:
- - uses: actions/checkout@v6
+ - uses: actions/checkout@v4
- name: Set up JDK 25
- uses: actions/setup-java@v5
+ uses: actions/setup-java@v4
with:
java-version: '25'
distribution: 'zulu'
-
+
- name: Grant execute permission for gradlew
run: chmod +x gradlew
- name: Executing tests
run: ./gradlew test
-
diff --git a/FEATURES.md b/FEATURES.md
index 612f700ab3..11f3563162 100644
--- a/FEATURES.md
+++ b/FEATURES.md
@@ -1,5 +1,4 @@
# Pathing features
-
- **Long distance pathing and splicing** Baritone calculates paths in segments, and precalculates the next segment when the current one is about to end, so that it's moving towards the goal at all times.
- **Chunk caching** Baritone simplifies chunks to a compacted internal 2-bit representation (AIR, SOLID, WATER, AVOID) and stores them in RAM for better very-long-distance pathing. There is also an option to save these cached chunks to disk. Example
- **Block breaking** Baritone considers breaking blocks as part of its path. It also takes into account your current tool set and hot bar. For example, if you have a Eff V diamond pick, it may choose to mine through a stone barrier, while if you only had a wood pick it might be faster to climb over it.
@@ -15,8 +14,7 @@
- **Pigs** It can sort of control pigs. I wouldn't rely on it though.
# Pathing method
-
-Baritone uses A*, with some modifications:
+Baritone uses A*, with some modifications:
- **Segmented calculation** Traditional A* calculates until the most promising node is in the goal, however in the environment of Minecraft with a limited render distance, we don't know the environment all the way to our goal. Baritone has three possible ways for path calculation to end: finding a path all the way to the goal, running out of time, or getting to the render distance. In the latter two scenarios, the selection of which segment to actually execute falls to the next item (incremental cost backoff). Whenever the path calculation thread finds that the best / most promising node is at the edge of loaded chunks, it increments a counter. If this happens more than 50 times (configurable), path calculation exits early. This happens with very low render distances. Otherwise, calculation continues until the timeout is hit (also configurable) or we find a path all the way to the goal.
- **Incremental cost backoff** When path calculation exits early without getting all the way to the goal, Baritone it needs to select a segment to execute first (assuming it will calculate the next segment at the end of this one). It uses incremental cost backoff to select the best node by varying metrics, then paths to that node. This is unchanged from MineBot and I made a write-up that still applies. In essence, it keeps track of the best node by various increasing coefficients, then picks the node with the least coefficient that goes at least 5 blocks from the starting position.
@@ -29,9 +27,7 @@ Baritone uses A*, with some modifications:
- [Baritone chat control usage](USAGE.md)
# Goals
-
The pathing goal can be set to any of these options:
-
- **GoalBlock** one specific block that the player should stand inside at foot level
- **GoalXZ** an X and a Z coordinate, used for long distance pathing
- **GoalYLevel** a Y coordinate
@@ -42,16 +38,14 @@ The pathing goal can be set to any of these options:
And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one of which satisfies the goal. For example, `mine diamond_ore` creates a `GoalComposite` of `GoalTwoBlocks`s for every diamond ore location it knows of.
-# Future features
+# Future features
Things it doesn't have yet
-
- Trapdoors
- Sprint jumping in a 1x2 corridor
See issues for more.
Things it may not ever have, from most likely to least likely =(
-
- Boats
- Horses (2x3 path instead of 1x2)
diff --git a/README.md b/README.md
index 65cbf9321d..a8f3b1f49f 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,4 @@
# Baritone
-
@@ -112,7 +111,7 @@ Here are some links to help to get started:
# API
The API is heavily documented, you can find the Javadocs for the latest release [here](https://baritone.leijurv.com/).
-Please note that usage of anything located outside of the `baritone.api` package is not supported by the API release
+Please note that usage of anything located outside of the ``baritone.api`` package is not supported by the API release
jar.
Below is an example of basic usage for changing some settings, and then pathing to an X/Z goal.
@@ -120,6 +119,7 @@ Below is an example of basic usage for changing some settings, and then pathing
```java
BaritoneAPI.getSettings().allowSprint.value = true;
BaritoneAPI.getSettings().primaryTimeoutMS.value = 2000L;
+
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalXZ(10000, 20000));
```
diff --git a/SETUP.md b/SETUP.md
index 88340b0c92..96991cea6c 100644
--- a/SETUP.md
+++ b/SETUP.md
@@ -6,21 +6,20 @@ The easiest way to install Baritone is to install it as Forge/Neoforge/Fabric mo
Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
## Prebuilt official releases
-
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)
The mapping between 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 | 1.21.4 | 1.21.5 | 1.21.6 - 1.21.8 |
|-------------------|------|------|------|------|------|------|------|------|-------|-------|--------|--------|------------------|
| Baritone version | v1.2 | v1.3 | v1.4 | v1.5 | v1.6 | v1.7 | v1.8 | v1.9 | v1.10 | v1.11 | v1.13 | v1.14 | v1.15 |
-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`.
+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 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 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).
@@ -32,7 +31,6 @@ If you want to report a bug and spare us some effort, you want `baritone-unoptim
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.
- **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.
@@ -43,7 +41,6 @@ Here's what the various qualifiers mean
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

@@ -51,11 +48,9 @@ If you build from source you will also find mapping files in the `dist` director
- Follow one of the instruction sets below, based on your preference
## Command Line
-
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
The recommended Java versions by Minecraft version are
-
| Minecraft version | Java version |
|-------------------------------|---------------|
| 1.12.2 - 1.16.5 | 8 |
@@ -63,7 +58,7 @@ The recommended Java versions by Minecraft version are
| 1.18.2 - 1.20.4 | 17 |
| 1.20.5 - 1.21.8 | 21 |
-Download java:
+Download java: https://adoptium.net/
To check which java version you are using do `java -version` in a command prompt or terminal.
@@ -80,13 +75,11 @@ and `gradlew build -Pbaritone.forge_build` / `gradlew build -Pbaritone.fabric_bu
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
## 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.
diff --git a/USAGE.md b/USAGE.md
index fe95dad9ab..46241e3fee 100644
--- a/USAGE.md
+++ b/USAGE.md
@@ -16,7 +16,7 @@ Try `#help` I promise it won't just send you back here =)
"wtf where is cleararea" -> look at `#help sel`
-"wtf where is goto death, goto waypoint" -> look at `#help wp`
+"wtf where is goto death, goto waypoint" -> look at `#help wp`
just look at `#help` lmao
@@ -33,7 +33,6 @@ Watch this [showcase video](https://youtu.be/CZkLXWo4Fg4)!
To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`.
Commands in Baritone:
-
- `thisway 1000` then `path` to go in the direction you're facing for a thousand blocks
- `goal x y z` or `goal x z` or `goal y`, then `path` to set a goal to a certain coordinate then path to it
- `goto x y z` or `goto x z` or `goto y` to go to a certain coordinate (in a single step, starts going immediately)
@@ -48,7 +47,7 @@ Commands in Baritone:
- `build` to build a schematic. `build blah.schematic` will load `schematics/blah.schematic` and build it with the origin being your player feet. `build blah.schematic x y z` to set the origin. Any of those can be relative to your player (`~ 69 ~-420` would build at x=player x, y=69, z=player z-420).
- `schematica` to build the schematic that is currently open in schematica
- `tunnel` to dig and make a tunnel, 1x2. It will only deviate from the straight line if necessary such as to avoid lava. For a dumber tunnel that is really just cleararea, you can `tunnel 3 2 100`, to clear an area 3 high, 2 wide, and 100 deep.
-- `farm` to automatically harvest, replant, or bone meal crops. Use `farm ` or `farm ` to limit the max distance from the starting point or a waypoint.
+- `farm` to automatically harvest, replant, or bone meal crops. Use `farm ` or `farm ` to limit the max distance from the starting point or a waypoint.
- `axis` to go to an axis or diagonal axis at y=120 (`axisHeight` is a configurable setting, defaults to 120).
- `explore x z` to explore the world from the origin of x,z. Leave out x and z to default to player feet. This will continually path towards the closest chunk to the origin that it's never seen before. `explorefilter filter.json` with optional invert can be used to load in a list of chunks to load.
- `invert` to invert the current goal and path. This gets as far away from it as possible, instead of as close as possible. For example, do `goal` then `invert` to run as far as possible from where you're standing at the start.
@@ -68,7 +67,6 @@ Commands in Baritone:
All the settings and documentation are here. If you find HTML easier to read than Javadoc, you can look here.
There are about a hundred settings, but here are some fun / interesting / important ones that you might want to look at changing in normal usage of Baritone. The documentation for each can be found at the above links.
-
- `allowBreak`
- `allowSprint`
- `allowPlace`
@@ -88,10 +86,12 @@ There are about a hundred settings, but here are some fun / interesting / import
- `mineScanDroppedItems`
- `allowDiagonalAscend`
+
+
+
# Troubleshooting / common issues
## Why doesn't Baritone respond to any of my chat commands?
-
This could be one of many things.
First, make sure it's actually installed. An easy way to check is seeing if it created the folder `baritone` in your Minecraft folder.
@@ -101,7 +101,7 @@ Second, make sure that you're using the prefix properly, and that chat control i
For example, Impact disables direct chat control. (i.e. anything typed in chat without a prefix will be ignored and sent publicly). **This is a saved setting**, so if you run Impact once, `chatControl` will be off from then on, **even in other clients**.
So you'll need to use the `#` prefix or edit `baritone/settings.txt` in your Minecraft folder to undo that (specifically, remove the line `chatControl false` then restart your client).
-## Why can I do `.goto x z` in Impact but nowhere else? Why can I do `-path to x z` in KAMI but nowhere else?
+## Why can I do `.goto x z` in Impact but nowhere else? Why can I do `-path to x z` in KAMI but nowhere else?
These are custom commands that they added; those aren't from Baritone.
The equivalent you're looking for is `goto x z`.
diff --git a/build.gradle b/build.gradle
index cbf845e625..c507b5f28f 100755
--- a/build.gradle
+++ b/build.gradle
@@ -20,11 +20,9 @@ allprojects {
apply plugin: "xyz.wagyourtail.unimined"
apply plugin: "maven-publish"
- base {
- archivesName = rootProject.archives_base_name
- }
+ archivesBaseName = rootProject.archives_base_name
- def vers = ""
+ /*def vers = ""
try {
vers = 'git describe --always --tags --first-parent --dirty'.execute().text.trim()
} catch (Exception e) {
@@ -36,11 +34,14 @@ allprojects {
} else {
version = vers.substring(1)
println "Detected version " + version
- }
+ }*/
+
+ version = rootProject.mod_version
group = rootProject.maven_group
+ sourceCompatibility = targetCompatibility = JavaVersion.toVersion(project.java_version)
+
java {
- sourceCompatibility = JavaVersion.toVersion(project.java_version)
toolchain {
languageVersion.set(JavaLanguageVersion.of(sourceCompatibility.majorVersion.toInteger()))
}
@@ -95,6 +96,8 @@ allprojects {
mappings {
mojmap()
+
+ devFallbackNamespace "official"
}
}
@@ -113,9 +116,7 @@ unimined.minecraft {
defaultRemapJar = false
}
-base {
- archivesName = archivesName.get() + "-common"
-}
+archivesBaseName = archivesBaseName + "-common"
sourceSets {
api {
diff --git a/buildSrc/build.gradle b/buildSrc/build.gradle
index 97a701f4a8..abc2e5bdb9 100644
--- a/buildSrc/build.gradle
+++ b/buildSrc/build.gradle
@@ -18,12 +18,12 @@
repositories {
mavenLocal()
maven {
- name = 'WagYourMaven'
- url = 'https://maven.wagyourtail.xyz/releases'
+ name = 'WagYourMavenSnapshots'
+ url = 'https://maven.wagyourtail.xyz/snapshots'
}
maven {
- name = 'WagYourMaven Snapshots'
- url = 'https://maven.wagyourtail.xyz/snapshots'
+ name = 'WagYourMaven'
+ url = 'https://maven.wagyourtail.xyz/releases'
}
maven {
name = 'ForgeMaven'
@@ -44,6 +44,7 @@ dependencies {
implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'
implementation group: 'commons-io', name: 'commons-io', version: '2.7'
+ // TODO: pin to a stable Unimined release once published.
implementation group: 'xyz.wagyourtail.unimined', name: 'xyz.wagyourtail.unimined.gradle.plugin', version: '1.4.2-SNAPSHOT'
implementation group: 'xyz.wagyourtail.unimined.mapping', name: 'unimined-mapping-library-jvm', version: '1.2.2'
-}
+}
\ No newline at end of file
diff --git a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java
index 2d98533d62..5fd69ccff8 100644
--- a/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java
+++ b/buildSrc/src/main/java/baritone/gradle/task/ProguardTask.java
@@ -18,19 +18,22 @@
package baritone.gradle.task;
import baritone.gradle.util.Determinizer;
-import org.gradle.api.plugins.JavaPluginExtension;
+import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.SourceSetContainer;
import org.gradle.api.tasks.TaskAction;
+import org.gradle.api.tasks.TaskCollection;
+import org.gradle.api.tasks.compile.ForkOptions;
+import org.gradle.api.tasks.compile.JavaCompile;
+import org.gradle.internal.jvm.Jvm;
import org.gradle.jvm.toolchain.JavaLanguageVersion;
import org.gradle.jvm.toolchain.JavaLauncher;
import org.gradle.jvm.toolchain.JavaToolchainService;
import xyz.wagyourtail.unimined.api.UniminedExtension;
import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig;
-import java.io.File;
-import java.io.IOException;
-import java.net.URI;
+import java.io.*;
+import java.net.URL;
import java.nio.file.Files;
import java.nio.file.Path;
import java.nio.file.StandardCopyOption;
@@ -94,8 +97,7 @@ private void processArtifact() throws Exception {
private void downloadProguard() throws Exception {
Path proguardZip = getTemporaryFile(String.format(PROGUARD_ZIP, proguardVersion));
if (!Files.exists(proguardZip)) {
- String downloadAddress = String.format("https://github.com/Guardsquare/proguard/releases/download/v%s/proguard-%s.zip", proguardVersion, proguardVersion);
- write(new URI(downloadAddress).toURL().openStream(), proguardZip);
+ write(new URL(String.format("https://github.com/Guardsquare/proguard/releases/download/v%s/proguard-%s.zip", proguardVersion, proguardVersion)).openStream(), proguardZip);
}
}
@@ -173,7 +175,7 @@ private void generateConfigs() throws Exception {
}
private Stream acquireDependencies() {
- return getProject().getExtensions().getByType(JavaPluginExtension.class).getSourceSets().findByName("main").getCompileClasspath().getFiles()
+ return getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName("main").getCompileClasspath().getFiles()
.stream()
.filter(File::isFile);
}
diff --git a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java
index f95db38460..04bd74947b 100644
--- a/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java
+++ b/buildSrc/src/main/java/baritone/gradle/util/Determinizer.java
@@ -65,7 +65,7 @@ public static void determinize(String inputPath, String outputPath, List t
clone.setTime(42069);
jos.putNextEntry(clone);
if (entry.getName().endsWith(".refmap.json")) {
- JsonElement json = JsonParser.parseReader(new InputStreamReader(jarFile.getInputStream(entry)));
+ JsonElement json = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry)));
jos.write(writeSorted(json).getBytes());
} else if (entry.getName().equals("META-INF/MANIFEST.MF") && doForgeReplacementOfMetaInf) { // only replace for forge jar
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
diff --git a/fabric/build.gradle b/fabric/build.gradle
index 876f0bad08..299e13f061 100644
--- a/fabric/build.gradle
+++ b/fabric/build.gradle
@@ -19,12 +19,10 @@ import baritone.gradle.task.CreateDistTask
import baritone.gradle.task.ProguardTask
plugins {
- id "com.github.johnrengelman.shadow" version "8.1.1"
+ id "com.github.johnrengelman.shadow" version "8.0.0"
}
-base {
- archivesName = archivesName.get() + "-fabric"
-}
+archivesBaseName = archivesBaseName + "-fabric"
unimined.minecraft {
fabric {
@@ -80,7 +78,7 @@ components.java {
}
task proguard(type: ProguardTask) {
- proguardVersion "7.9.1"
+ proguardVersion "7.8.2"
compType "fabric"
}
@@ -88,18 +86,36 @@ task createDist(type: CreateDistTask, dependsOn: proguard) {
compType "fabric"
}
+task sourcesJar(type: Jar, dependsOn: classes) {
+ from rootProject.sourceSets.main.allJava
+ from rootProject.sourceSets.api.allJava
+ archiveClassifier.set("sources")
+}
+
build.finalizedBy(createDist)
publishing {
publications {
- mavenFabric(MavenPublication) {
- artifactId = rootProject.archives_base_name + "-" + project.name
- from components.java
+ maven(MavenPublication) {
+ groupId "meteordevelopment"
+ artifactId "baritone"
+ artifact "../dist/baritone-api-fabric-" + version + ".jar"
+ artifact sourcesJar
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
- // Add repositories to publish to here.
+ maven {
+ name = "meteor-maven"
+ url = "https://maven.meteordev.org/snapshots"
+ credentials {
+ username = System.getenv("MAVEN_METEOR_ALIAS")
+ password = System.getenv("MAVEN_METEOR_TOKEN")
+ }
+ authentication {
+ basic(BasicAuthentication)
+ }
+ }
}
}
diff --git a/fabric/src/main/java/baritone/launch/FabricMixinPlugin.java b/fabric/src/main/java/baritone/launch/FabricMixinPlugin.java
new file mode 100644
index 0000000000..816998e86e
--- /dev/null
+++ b/fabric/src/main/java/baritone/launch/FabricMixinPlugin.java
@@ -0,0 +1,71 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.launch;
+
+import net.fabricmc.loader.api.FabricLoader;
+import org.objectweb.asm.tree.ClassNode;
+import org.spongepowered.asm.mixin.extensibility.IMixinConfigPlugin;
+import org.spongepowered.asm.mixin.extensibility.IMixinInfo;
+
+import java.util.List;
+import java.util.Set;
+
+public class FabricMixinPlugin implements IMixinConfigPlugin {
+ private static final String mixinPackage = "baritone.launch.mixins";
+
+ private static boolean loaded;
+
+ private static boolean isBaritonePresent;
+
+ @Override
+ public void onLoad(String mixinPackage) {
+ if (loaded) return;
+
+ isBaritonePresent = FabricLoader.getInstance().isModLoaded("baritone");
+
+ loaded = true;
+ }
+
+ @Override
+ public String getRefMapperConfig() {
+ return null;
+ }
+
+ @Override
+ public boolean shouldApplyMixin(String targetClassName, String mixinClassName) {
+ if (!mixinClassName.startsWith(mixinPackage)) {
+ throw new RuntimeException("Mixin " + mixinClassName + " is not in the mixin package");
+ } else {
+ return !isBaritonePresent;
+ }
+ }
+
+ @Override
+ public void acceptTargets(Set myTargets, Set otherTargets) {}
+
+ @Override
+ public List getMixins() {
+ return null;
+ }
+
+ @Override
+ public void preApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
+
+ @Override
+ public void postApply(String targetClassName, ClassNode targetClass, String mixinClassName, IMixinInfo mixinInfo) {}
+}
\ No newline at end of file
diff --git a/fabric/src/main/resources/fabric.mod.json b/fabric/src/main/resources/fabric.mod.json
index 1dc97cfd3c..d3dfbee36e 100644
--- a/fabric/src/main/resources/fabric.mod.json
+++ b/fabric/src/main/resources/fabric.mod.json
@@ -1,6 +1,6 @@
{
"schemaVersion": 1,
- "id": "baritone",
+ "id": "baritone-meteor",
"version": "${version}",
"name": "Baritone",
@@ -21,11 +21,11 @@
"entrypoints": {
},
"mixins": [
- "mixins.baritone.json"
+ "mixins.baritone-meteor.json"
],
"depends": {
"fabricloader": ">=0.19.3",
- "minecraft": ["26.1.*"]
+ "minecraft": ["26.2"]
},
"custom": {
"modmenu": {
diff --git a/forge/build.gradle b/forge/build.gradle
index 6f8ca38f80..12bd82db17 100644
--- a/forge/build.gradle
+++ b/forge/build.gradle
@@ -19,12 +19,10 @@ import baritone.gradle.task.CreateDistTask
import baritone.gradle.task.ProguardTask
plugins {
- id "com.github.johnrengelman.shadow" version "8.1.1"
+ id "com.github.johnrengelman.shadow" version "8.0.0"
}
-base {
- archivesName = archivesName.get() + "-forge"
-}
+archivesBaseName = archivesBaseName + "-forge"
unimined.minecraft {
minecraftForge {
@@ -97,7 +95,7 @@ components.java {
}
task proguard(type: ProguardTask) {
- proguardVersion "7.9.1"
+ proguardVersion "7.8.2"
compType "forge"
}
diff --git a/forge/src/main/resources/META-INF/mods.toml b/forge/src/main/resources/META-INF/mods.toml
index 6a91b27cdc..5328e7bbf4 100644
--- a/forge/src/main/resources/META-INF/mods.toml
+++ b/forge/src/main/resources/META-INF/mods.toml
@@ -35,6 +35,6 @@ A Minecraft pathfinder bot.
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
-versionRange="[26.1, 26.1.2]"
+versionRange="[26.2]"
ordering="NONE"
side="BOTH"
diff --git a/gradle.properties b/gradle.properties
index 49f2113429..d419bc9ed6 100644
--- a/gradle.properties
+++ b/gradle.properties
@@ -1,22 +1,22 @@
org.gradle.jvmargs=-Xmx4G
-available_loaders=fabric,forge,neoforge,tweaker
+available_loaders=fabric
-mod_version=1.18.0
+mod_version=26.2-SNAPSHOT
maven_group=baritone
archives_base_name=baritone
java_version=25
-minecraft_version=26.1.2
+minecraft_version=26.2
-forge_version=64.0.11
+forge_version=65.0.1
-neoforge_version=78
+neoforge_version=7-beta
fabric_version=0.19.3
-nether_pathfinder_version=1.6
+nether_pathfinder_version=1.4.1
// These dependencies are used for common and tweaker
// while mod loaders usually ship their own version
diff --git a/gradle/wrapper/gradle-wrapper.jar b/gradle/wrapper/gradle-wrapper.jar
index 1b33c55baa..e708b1c023 100755
Binary files a/gradle/wrapper/gradle-wrapper.jar and b/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties
index aaaabb3cb9..03b32a2e37 100755
--- a/gradle/wrapper/gradle-wrapper.properties
+++ b/gradle/wrapper/gradle-wrapper.properties
@@ -1,7 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.14.4-bin.zip
-networkTimeout=10000
-validateDistributionUrl=true
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
diff --git a/gradlew b/gradlew
index 23d15a9367..744e882ed5 100755
--- a/gradlew
+++ b/gradlew
@@ -1,7 +1,7 @@
-#!/bin/sh
+#!/usr/bin/env sh
#
-# Copyright © 2015-2021 the original authors.
+# Copyright 2015 the original author or authors.
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
@@ -15,115 +15,81 @@
# See the License for the specific language governing permissions and
# limitations under the License.
#
-# SPDX-License-Identifier: Apache-2.0
-#
##############################################################################
-#
-# Gradle start up script for POSIX generated by Gradle.
-#
-# Important for running:
-#
-# (1) You need a POSIX-compliant shell to run this script. If your /bin/sh is
-# noncompliant, but you have some other compliant shell such as ksh or
-# bash, then to run this script, type that shell name before the whole
-# command line, like:
-#
-# ksh Gradle
-#
-# Busybox and similar reduced shells will NOT work, because this script
-# requires all of these POSIX shell features:
-# * functions;
-# * expansions «$var», «${var}», «${var:-default}», «${var+SET}»,
-# «${var#prefix}», «${var%suffix}», and «$( cmd )»;
-# * compound commands having a testable exit status, especially «case»;
-# * various built-in commands including «command», «set», and «ulimit».
-#
-# Important for patching:
-#
-# (2) This script targets any POSIX shell, so it avoids extensions provided
-# by Bash, Ksh, etc; in particular arrays are avoided.
-#
-# The "traditional" practice of packing multiple parameters into a
-# space-separated string is a well documented source of bugs and security
-# problems, so this is (mostly) avoided, by progressively accumulating
-# options in "$@", and eventually passing that to Java.
-#
-# Where the inherited environment variables (DEFAULT_JVM_OPTS, JAVA_OPTS,
-# and GRADLE_OPTS) rely on word-splitting, this is performed explicitly;
-# see the in-line comments for details.
-#
-# There are tweaks for specific operating systems such as AIX, CygWin,
-# Darwin, MinGW, and NonStop.
-#
-# (3) This script is generated from the Groovy template
-# https://github.com/gradle/gradle/blob/HEAD/platforms/jvm/plugins-application/src/main/resources/org/gradle/api/internal/plugins/unixStartScript.txt
-# within the Gradle project.
-#
-# You can find Gradle at https://github.com/gradle/gradle/.
-#
+##
+## Gradle start up script for UN*X
+##
##############################################################################
# Attempt to set APP_HOME
-
# Resolve links: $0 may be a link
-app_path=$0
-
-# Need this for daisy-chained symlinks.
-while
- APP_HOME=${app_path%"${app_path##*/}"} # leaves a trailing /; empty if no leading path
- [ -h "$app_path" ]
-do
- ls=$( ls -ld "$app_path" )
- link=${ls#*' -> '}
- case $link in #(
- /*) app_path=$link ;; #(
- *) app_path=$APP_HOME$link ;;
- esac
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
-# This is normally unused
-# shellcheck disable=SC2034
-APP_BASE_NAME=${0##*/}
-# Discard cd standard output in case $CDPATH is set (https://github.com/gradle/gradle/issues/25036)
-APP_HOME=$( cd -P "${APP_HOME:-./}" > /dev/null && printf '%s\n' "$PWD" ) || exit
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
# Use the maximum available, or set MAX_FD != -1 to use that value.
-MAX_FD=maximum
+MAX_FD="maximum"
warn () {
echo "$*"
-} >&2
+}
die () {
echo
echo "$*"
echo
exit 1
-} >&2
+}
# OS specific support (must be 'true' or 'false').
cygwin=false
msys=false
darwin=false
nonstop=false
-case "$( uname )" in #(
- CYGWIN* ) cygwin=true ;; #(
- Darwin* ) darwin=true ;; #(
- MSYS* | MINGW* ) msys=true ;; #(
- NONSTOP* ) nonstop=true ;;
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MSYS* | MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
esac
-CLASSPATH="\\\"\\\""
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
# Determine the Java command to use to start the JVM.
if [ -n "$JAVA_HOME" ] ; then
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
# IBM's JDK on AIX uses strange locations for the executables
- JAVACMD=$JAVA_HOME/jre/sh/java
+ JAVACMD="$JAVA_HOME/jre/sh/java"
else
- JAVACMD=$JAVA_HOME/bin/java
+ JAVACMD="$JAVA_HOME/bin/java"
fi
if [ ! -x "$JAVACMD" ] ; then
die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
@@ -132,120 +98,88 @@ Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
fi
else
- JAVACMD=java
- if ! command -v java >/dev/null 2>&1
- then
- die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
Please set the JAVA_HOME variable in your environment to match the
location of your Java installation."
- fi
fi
# Increase the maximum file descriptors if we can.
-if ! "$cygwin" && ! "$darwin" && ! "$nonstop" ; then
- case $MAX_FD in #(
- max*)
- # In POSIX sh, ulimit -H is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- MAX_FD=$( ulimit -H -n ) ||
- warn "Could not query maximum file descriptor limit"
- esac
- case $MAX_FD in #(
- '' | soft) :;; #(
- *)
- # In POSIX sh, ulimit -n is undefined. That's why the result is checked to see if it worked.
- # shellcheck disable=SC2039,SC3045
- ulimit -n "$MAX_FD" ||
- warn "Could not set maximum file descriptor limit to $MAX_FD"
- esac
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
fi
-# Collect all arguments for the java command, stacking in reverse order:
-# * args from the command line
-# * the main class name
-# * -classpath
-# * -D...appname settings
-# * --module-path (only if needed)
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and GRADLE_OPTS environment variables.
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
# For Cygwin or MSYS, switch paths to Windows format before running java
-if "$cygwin" || "$msys" ; then
- APP_HOME=$( cygpath --path --mixed "$APP_HOME" )
- CLASSPATH=$( cygpath --path --mixed "$CLASSPATH" )
-
- JAVACMD=$( cygpath --unix "$JAVACMD" )
-
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
# Now convert the arguments - kludge to limit ourselves to /bin/sh
- for arg do
- if
- case $arg in #(
- -*) false ;; # don't mess with options #(
- /?*) t=${arg#/} t=/${t%%/*} # looks like a POSIX filepath
- [ -e "$t" ] ;; #(
- *) false ;;
- esac
- then
- arg=$( cygpath --path --ignore --mixed "$arg" )
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
fi
- # Roll the args list around exactly as many times as the number of
- # args, so each arg winds up back in the position where it started, but
- # possibly modified.
- #
- # NB: a `for` loop captures its iteration list before it begins, so
- # changing the positional parameters here affects neither the number of
- # iterations, nor the values presented in `arg`.
- shift # remove old arg
- set -- "$@" "$arg" # push replacement arg
+ i=`expr $i + 1`
done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
fi
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
-# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
-DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
-
-# Collect all arguments for the java command:
-# * DEFAULT_JVM_OPTS, JAVA_OPTS, and optsEnvironmentVar are not allowed to contain shell fragments,
-# and any embedded shellness will be escaped.
-# * For example: A user cannot expect ${Hostname} to be expanded, as it is an environment variable and will be
-# treated as '${Hostname}' itself on the command line.
-
-set -- \
- "-Dorg.gradle.appname=$APP_BASE_NAME" \
- -classpath "$CLASSPATH" \
- -jar "$APP_HOME/gradle/wrapper/gradle-wrapper.jar" \
- "$@"
-
-# Stop when "xargs" is not available.
-if ! command -v xargs >/dev/null 2>&1
-then
- die "xargs is not available"
-fi
-
-# Use "xargs" to parse quoted args.
-#
-# With -n1 it outputs one arg per line, with the quotes and backslashes removed.
-#
-# In Bash we could simply go:
-#
-# readarray ARGS < <( xargs -n1 <<<"$var" ) &&
-# set -- "${ARGS[@]}" "$@"
-#
-# but POSIX shell has neither arrays nor command substitution, so instead we
-# post-process each arg (as a line of input to sed) to backslash-escape any
-# character that might be a shell metacharacter, then use eval to reverse
-# that process (while maintaining the separation between arguments), and wrap
-# the whole thing up as a single "set" statement.
-#
-# This will of course break if any of these variables contains a newline or
-# an unmatched quote.
-#
-
-eval "set -- $(
- printf '%s\n' "$DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS" |
- xargs -n1 |
- sed ' s~[^-[:alnum:]+,./:=@_]~\\&~g; ' |
- tr '\n' ' '
- )" '"$@"'
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
exec "$JAVACMD" "$@"
diff --git a/gradlew.bat b/gradlew.bat
index db3a6ac207..107acd32c4 100755
--- a/gradlew.bat
+++ b/gradlew.bat
@@ -13,10 +13,8 @@
@rem See the License for the specific language governing permissions and
@rem limitations under the License.
@rem
-@rem SPDX-License-Identifier: Apache-2.0
-@rem
-@if "%DEBUG%"=="" @echo off
+@if "%DEBUG%" == "" @echo off
@rem ##########################################################################
@rem
@rem Gradle startup script for Windows
@@ -27,8 +25,7 @@
if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0
-if "%DIRNAME%"=="" set DIRNAME=.
-@rem This is normally unused
+if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME%
@@ -43,13 +40,13 @@ if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1
-if %ERRORLEVEL% equ 0 goto execute
+if "%ERRORLEVEL%" == "0" goto execute
-echo. 1>&2
-echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
goto fail
@@ -59,34 +56,32 @@ set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto execute
-echo. 1>&2
-echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% 1>&2
-echo. 1>&2
-echo Please set the JAVA_HOME variable in your environment to match the 1>&2
-echo location of your Java installation. 1>&2
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
goto fail
:execute
@rem Setup the command line
-set CLASSPATH=
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle
-"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" -jar "%APP_HOME%\gradle\wrapper\gradle-wrapper.jar" %*
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
:end
@rem End local scope for the variables with windows NT shell
-if %ERRORLEVEL% equ 0 goto mainEnd
+if "%ERRORLEVEL%"=="0" goto mainEnd
:fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code!
-set EXIT_CODE=%ERRORLEVEL%
-if %EXIT_CODE% equ 0 set EXIT_CODE=1
-if not ""=="%GRADLE_EXIT_CONSOLE%" exit %EXIT_CODE%
-exit /b %EXIT_CODE%
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
:mainEnd
if "%OS%"=="Windows_NT" endlocal
diff --git a/neoforge/build.gradle b/neoforge/build.gradle
index d3f6ee2630..6567964d66 100644
--- a/neoforge/build.gradle
+++ b/neoforge/build.gradle
@@ -105,7 +105,7 @@ components.java {
}
task proguard(type: ProguardTask) {
- proguardVersion "7.9.1"
+ proguardVersion "7.8.2"
compType "neoforge"
}
diff --git a/neoforge/src/main/resources/META-INF/neoforge.mods.toml b/neoforge/src/main/resources/META-INF/neoforge.mods.toml
index 6500a18ec7..4eec7768ea 100644
--- a/neoforge/src/main/resources/META-INF/neoforge.mods.toml
+++ b/neoforge/src/main/resources/META-INF/neoforge.mods.toml
@@ -35,7 +35,7 @@ A Minecraft pathfinder bot.
modId="minecraft"
type="required"
# This version range declares a minimum of the current minecraft version up to but not including the next major version
-versionRange="[26.1, 26.1.2]"
+versionRange="[26.2]"
ordering="NONE"
side="BOTH"
diff --git a/scripts/proguard.pro b/scripts/proguard.pro
index 627fb5f53b..dd63b216ba 100644
--- a/scripts/proguard.pro
+++ b/scripts/proguard.pro
@@ -1,3 +1,8 @@
+# Meteor
+-keep class *
+
+
+
-keepattributes Signature
-keepattributes *Annotation*
-keepattributes InnerClasses
diff --git a/settings.gradle b/settings.gradle
index 6876f21fb0..a62ce1e56d 100755
--- a/settings.gradle
+++ b/settings.gradle
@@ -41,6 +41,7 @@ pluginManagement {
rootProject.name = 'baritone'
+include("tweaker")
for (platform in available_loaders.split(",")) {
- include(platform)
+ include(platform)
}
diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java
index 57a375fa2f..7cb0aa996a 100644
--- a/src/api/java/baritone/api/Settings.java
+++ b/src/api/java/baritone/api/Settings.java
@@ -23,9 +23,11 @@
import baritone.api.utils.TypeUtils;
import baritone.api.utils.gui.BaritoneToast;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.components.ChatComponent;
import net.minecraft.client.multiplayer.chat.GuiMessageTag;
import net.minecraft.core.Vec3i;
import net.minecraft.network.chat.Component;
+import net.minecraft.network.chat.MessageSignature;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
@@ -682,7 +684,7 @@ public final class Settings {
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
* something else
*/
- public final Setting chatControl = new Setting<>(true);
+ public final Setting chatControl = new Setting<>(false);
/**
* Some clients like Impact try to force chatControl to off, so here's a second setting to do it anyway
@@ -985,11 +987,6 @@ public final class Settings {
*/
public final Setting replantNetherWart = new Setting<>(false);
- /**
- * When enabled, farming will be restricted to the current selection.
- */
- public final Setting farmUsingSelection = new Setting<>(false);
-
/**
* Farming will scan for at most this many blocks.
*/
@@ -1281,7 +1278,12 @@ public final class Settings {
public final Setting> logger = new Setting<>((msg) -> {
try {
final GuiMessageTag tag = useMessageTag.value ? Helper.MESSAGE_TAG : null;
- Minecraft.getInstance().gui.getChat().addPlayerMessage(msg, null, tag);
+ final ChatComponent chat = Minecraft.getInstance().gui.hud.getChat();
+ if (tag != null) {
+ chat.addPlayerMessage(msg, new MessageSignature(new byte[MessageSignature.BYTES]), tag);
+ } else {
+ chat.addClientSystemMessage(msg);
+ }
} catch (Throwable t) {
LOGGER.warn("Failed to log message to chat: " + msg.getString(), t);
}
@@ -1547,36 +1549,6 @@ public final class Settings {
*/
public final Setting elytraChatSpam = new Setting<>(false);
- /**
- * May reduce memory usage by using a custom allocator for pathfinding
- */
- public final Setting elytraCustomAllocator = new Setting<>(true);
-
- /**
- * Allow the pathfinder to attempt flight in tighter spaces, useful in caves but can be dangerous.
- */
- public final Setting elytraAllowTightSpaces = new Setting<>(false);
-
- /**
- * Allow the pathfinder to fly above y 128 in the nether.
- */
- public final Setting elytraAllowAboveRoof = new Setting<>(false);
-
- /**
- * Allow the pathfinder to access the baritone cache to improve pathing
- */
- public final Setting elytraUseCache = new Setting<>(true);
-
- /**
- * Allow the pathfinder to fly above the build limit in the overworld and end.
- */
- public final Setting elytraAllowAboveBuildLimit = new Setting<>(true);
-
- /**
- * Minimum distance in blocks of an elytra trip before the pathfinder will try to fly above build limit. (Minimum: 32). Requires {@link #elytraAllowAboveBuildLimit} to be enabled.
- */
- public final Setting elytraLongDistanceThreshold = new Setting<>(500);
-
/**
* Sneak when magma blocks are under feet
*/
diff --git a/src/api/java/baritone/api/behavior/ILookBehavior.java b/src/api/java/baritone/api/behavior/ILookBehavior.java
index d78e7f8b33..b6604ada77 100644
--- a/src/api/java/baritone/api/behavior/ILookBehavior.java
+++ b/src/api/java/baritone/api/behavior/ILookBehavior.java
@@ -39,6 +39,18 @@ public interface ILookBehavior extends IBehavior {
*/
void updateTarget(Rotation rotation, boolean blockInteract);
+ /**
+ * Updates the current look target and supplies the distance to the interaction target. Aim processors can use this
+ * to keep randomized looking within a roughly constant world-space displacement instead of a constant angle.
+ *
+ * @param rotation The target rotations
+ * @param blockInteract Whether the target rotations are needed for a block interaction
+ * @param targetDistance The distance from the player's eyes to the interaction target
+ */
+ default void updateTarget(Rotation rotation, boolean blockInteract, double targetDistance) {
+ updateTarget(rotation, 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}.
diff --git a/src/api/java/baritone/api/behavior/look/IAimProcessor.java b/src/api/java/baritone/api/behavior/look/IAimProcessor.java
index c7c60f4134..a5c60efba4 100644
--- a/src/api/java/baritone/api/behavior/look/IAimProcessor.java
+++ b/src/api/java/baritone/api/behavior/look/IAimProcessor.java
@@ -35,6 +35,18 @@ public interface IAimProcessor {
*/
Rotation peekRotation(Rotation desired);
+ /**
+ * Returns the actual rotation for an interaction target at the supplied distance. Implementations may use the
+ * distance to convert angular aim variation into a roughly constant world-space displacement.
+ *
+ * @param desired The desired rotation to set
+ * @param targetDistance The distance from the player's eyes to the interaction target
+ * @return The actual rotation
+ */
+ default Rotation peekRotation(Rotation desired, double targetDistance) {
+ return peekRotation(desired);
+ }
+
/**
* Returns a copy of this {@link IAimProcessor} which has its own internal state and is manually tickable.
*
diff --git a/src/api/java/baritone/api/command/datatypes/ItemById.java b/src/api/java/baritone/api/command/datatypes/ItemById.java
index 3cc898def8..791f06c93a 100644
--- a/src/api/java/baritone/api/command/datatypes/ItemById.java
+++ b/src/api/java/baritone/api/command/datatypes/ItemById.java
@@ -42,7 +42,7 @@ public Item get(IDatatypeContext ctx) throws CommandException {
public Stream tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(
- BuiltInRegistries.ITEM.keySet()
+ BuiltInRegistries.BLOCK.keySet()
.stream()
.map(Identifier::toString)
)
diff --git a/src/api/java/baritone/api/command/manager/ICommandManager.java b/src/api/java/baritone/api/command/manager/ICommandManager.java
index 3f2d81f244..1430d2538e 100644
--- a/src/api/java/baritone/api/command/manager/ICommandManager.java
+++ b/src/api/java/baritone/api/command/manager/ICommandManager.java
@@ -21,7 +21,7 @@
import baritone.api.command.ICommand;
import baritone.api.command.argument.ICommandArgument;
import baritone.api.command.registry.Registry;
-import net.minecraft.util.Tuple;
+import baritone.api.utils.Pair;
import java.util.List;
import java.util.stream.Stream;
@@ -44,9 +44,9 @@ public interface ICommandManager {
boolean execute(String string);
- boolean execute(Tuple> expanded);
+ boolean execute(Pair> expanded);
- Stream tabComplete(Tuple> expanded);
+ Stream tabComplete(Pair> expanded);
Stream tabComplete(String prefix);
}
diff --git a/src/api/java/baritone/api/process/IElytraProcess.java b/src/api/java/baritone/api/process/IElytraProcess.java
index ce03e8d620..28328f901a 100644
--- a/src/api/java/baritone/api/process/IElytraProcess.java
+++ b/src/api/java/baritone/api/process/IElytraProcess.java
@@ -18,11 +18,8 @@
package baritone.api.process;
import baritone.api.pathing.goals.Goal;
-import baritone.api.utils.BetterBlockPos;
import net.minecraft.core.BlockPos;
-import java.util.List;
-
public interface IElytraProcess extends IBaritoneProcess {
void repackChunks();
@@ -32,11 +29,6 @@ public interface IElytraProcess extends IBaritoneProcess {
*/
BlockPos currentDestination();
- /**
- * @return Current active path, empty if not active or no path has been calculated yet
- */
- List getPath();
-
void pathTo(BlockPos destination);
void pathTo(Goal destination);
diff --git a/src/api/java/baritone/api/utils/BlockOptionalMeta.java b/src/api/java/baritone/api/utils/BlockOptionalMeta.java
index a9cc2caa56..9118e3a34d 100644
--- a/src/api/java/baritone/api/utils/BlockOptionalMeta.java
+++ b/src/api/java/baritone/api/utils/BlockOptionalMeta.java
@@ -236,7 +236,7 @@ private static synchronized List- drops(Block b) {
.withParameter(LootContextParams.BLOCK_STATE, b.defaultBlockState())
.withParameter(LootContextParams.TOOL, new ItemStack(Items.NETHERITE_PICKAXE, 1));
getDrops(block, lv5).stream().map(ItemStack::getItem).forEach(items::add);
- } catch (Throwable e) {
+ } catch (Exception e) {
e.printStackTrace();
}
return items;
@@ -281,9 +281,6 @@ public static ServerLevelStub fastCreate() {
@Override
public RegistryAccess registryAccess() {
- if (client.level != null) {
- return client.level.registryAccess();
- }
return registryAccess.join();
}
@@ -315,14 +312,15 @@ public static CompletableFuture load() {
baseLayeredRegistry.getAccessForLoading(RegistryLayer.WORLDGEN),
pendingTags
);
+ RegistryAccess.Frozen worldgenRegistries = RegistryDataLoader.load(
+ closeableResourceManager,
+ worldGenRegistryLookupList,
+ RegistryDataLoader.WORLDGEN_REGISTRIES,
+ ForkJoinPool.commonPool()
+ ).join();
LayeredRegistryAccess layeredRegistryAccess = baseLayeredRegistry.replaceFrom(
RegistryLayer.WORLDGEN,
- RegistryDataLoader.load(
- closeableResourceManager,
- worldGenRegistryLookupList,
- RegistryDataLoader.WORLDGEN_REGISTRIES,
- ForkJoinPool.commonPool()
- ).join()
+ worldgenRegistries
);
return ReloadableServerRegistries.reload(
layeredRegistryAccess,
diff --git a/src/api/java/baritone/api/utils/Helper.java b/src/api/java/baritone/api/utils/Helper.java
index 1aee893032..41c62fc869 100755
--- a/src/api/java/baritone/api/utils/Helper.java
+++ b/src/api/java/baritone/api/utils/Helper.java
@@ -20,8 +20,8 @@
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import net.minecraft.ChatFormatting;
-import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.chat.GuiMessageTag;
+import net.minecraft.client.Minecraft;
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.MutableComponent;
@@ -53,7 +53,7 @@ public interface Helper {
/**
* The tag to assign to chat messages when {@link Settings#useMessageTag} is {@code true}.
*/
- GuiMessageTag MESSAGE_TAG = new GuiMessageTag(0xFF55FF, null, Component.literal("Baritone message."), "Baritone");
+ GuiMessageTag MESSAGE_TAG = new GuiMessageTag(0xFF55FF, GuiMessageTag.Icon.CHAT_MODIFIED, Component.literal("Baritone message."), "Baritone");
static Component getPrefix() {
// Inner text component
diff --git a/src/api/java/baritone/api/utils/IPlayerController.java b/src/api/java/baritone/api/utils/IPlayerController.java
index 2c098e9aee..8da397f2dd 100644
--- a/src/api/java/baritone/api/utils/IPlayerController.java
+++ b/src/api/java/baritone/api/utils/IPlayerController.java
@@ -43,7 +43,7 @@ public interface IPlayerController {
void resetBlockRemoving();
- void windowClick(int windowId, int slotId, int mouseButton, ContainerInput type, Player player);
+ void windowClick(int windowId, int slotId, int mouseButton, ContainerInput input, Player player);
GameType getGameType();
diff --git a/src/api/java/baritone/api/utils/RotationUtils.java b/src/api/java/baritone/api/utils/RotationUtils.java
index 5eef8b45c8..6e310bb1c8 100644
--- a/src/api/java/baritone/api/utils/RotationUtils.java
+++ b/src/api/java/baritone/api/utils/RotationUtils.java
@@ -175,10 +175,6 @@ public static Optional reachable(IPlayerContext ctx, BlockPos pos, dou
}
public static Optional reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
- // Prevent BetterBlockPos from leaking into Minecraft's block entity map
- if (pos instanceof BetterBlockPos) {
- pos = new BlockPos(pos.getX(), pos.getY(), pos.getZ());
- }
if (BaritoneAPI.getSettings().remainWithExistingLookDirection.value && ctx.isLookingAt(pos)) {
/*
* why add 0.0001?
diff --git a/src/api/java/baritone/api/utils/VecUtils.java b/src/api/java/baritone/api/utils/VecUtils.java
index 7037afcfce..4ea94b95af 100644
--- a/src/api/java/baritone/api/utils/VecUtils.java
+++ b/src/api/java/baritone/api/utils/VecUtils.java
@@ -43,10 +43,6 @@ private VecUtils() {}
* @see #getBlockPosCenter(BlockPos)
*/
public static Vec3 calculateBlockCenter(Level world, BlockPos pos) {
- // Prevent BetterBlockPos from leaking into Minecraft's block entity map
- if (pos instanceof BetterBlockPos) {
- pos = new BlockPos(pos.getX(), pos.getY(), pos.getZ());
- }
BlockState b = world.getBlockState(pos);
VoxelShape shape = b.getCollisionShape(world, pos);
if (shape.isEmpty()) {
diff --git a/src/api/java/baritone/api/utils/gui/BaritoneToast.java b/src/api/java/baritone/api/utils/gui/BaritoneToast.java
index effa0b8046..25e1318c99 100644
--- a/src/api/java/baritone/api/utils/gui/BaritoneToast.java
+++ b/src/api/java/baritone/api/utils/gui/BaritoneToast.java
@@ -24,6 +24,6 @@
public class BaritoneToast {
private static final SystemToast.SystemToastId BARITONE_TOAST_ID = new SystemToast.SystemToastId(5000L);
public static void addOrUpdate(Component title, Component subtitle) {
- SystemToast.addOrUpdate(Minecraft.getInstance().getToastManager(), BARITONE_TOAST_ID, title, subtitle);
+ SystemToast.addOrUpdate(Minecraft.getInstance().gui.toastManager(), BARITONE_TOAST_ID, title, subtitle);
}
}
diff --git a/src/launch/java/baritone/launch/mixins/MixinFireworkRocketEntity.java b/src/launch/java/baritone/launch/mixins/MixinFireworkRocketEntity.java
index b4c8e05b67..b79564a235 100644
--- a/src/launch/java/baritone/launch/mixins/MixinFireworkRocketEntity.java
+++ b/src/launch/java/baritone/launch/mixins/MixinFireworkRocketEntity.java
@@ -21,6 +21,7 @@
import net.minecraft.network.syncher.EntityDataAccessor;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.EntityType;
+import net.minecraft.world.entity.EntityTypes;
import net.minecraft.world.entity.LivingEntity;
import net.minecraft.world.entity.projectile.FireworkRocketEntity;
import net.minecraft.world.level.Level;
@@ -44,7 +45,7 @@ public abstract class MixinFireworkRocketEntity extends Entity implements IFirew
public abstract boolean isAttachedToEntity();
private MixinFireworkRocketEntity(Level level) {
- super(EntityType.FIREWORK_ROCKET, level);
+ super(EntityTypes.FIREWORK_ROCKET, level);
}
@Override
diff --git a/src/launch/java/baritone/launch/mixins/MixinItemStack.java b/src/launch/java/baritone/launch/mixins/MixinItemStack.java
index e593c695e2..831a272017 100644
--- a/src/launch/java/baritone/launch/mixins/MixinItemStack.java
+++ b/src/launch/java/baritone/launch/mixins/MixinItemStack.java
@@ -30,18 +30,18 @@
@Mixin(ItemStack.class)
public abstract class MixinItemStack implements IItemStack {
+ @Shadow
+ public abstract Item getItem();
+
@Unique
private int baritoneHash;
@Shadow
public abstract int getDamageValue();
- @Shadow
- public abstract Item getItem();
-
private void recalculateHash() {
- Item item = getItem();
- baritoneHash = item == null ? -1 : item.hashCode() + getDamageValue();
+ Item it = getItem();
+ baritoneHash = it == null ? -1 : it.hashCode() + getDamageValue();
}
@Inject(
diff --git a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
index 7a1c16c526..3eb68d0037 100644
--- a/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
+++ b/src/launch/java/baritone/launch/mixins/MixinMinecraft.java
@@ -24,6 +24,7 @@
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.Minecraft;
+import net.minecraft.client.gui.Gui;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.client.player.LocalPlayer;
@@ -65,18 +66,10 @@ private void postInit(CallbackInfo ci) {
@Inject(
method = "tick",
at = @At(
- value = "FIELD",
- opcode = Opcodes.GETFIELD,
- target = "net/minecraft/client/Minecraft.screen:Lnet/minecraft/client/gui/screens/Screen;",
+ value = "INVOKE",
+ target = "Lnet/minecraft/client/gui/Gui;tick()V",
ordinal = 0,
shift = At.Shift.BEFORE
- ),
- slice = @Slice(
- from = @At(
- value = "FIELD",
- opcode = Opcodes.PUTFIELD,
- target = "net/minecraft/client/Minecraft.missTime:I"
- )
)
)
private void runTick(CallbackInfo ci) {
@@ -165,27 +158,17 @@ private void postLoadWorld(final ClientLevel world, final CallbackInfo ci) {
@Redirect(
method = "tick",
at = @At(
- value = "FIELD",
- opcode = Opcodes.GETFIELD,
- target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;"
- ),
- slice = @Slice(
- from = @At(
- value = "INVOKE",
- target = "Lnet/minecraft/client/gui/components/DebugScreenOverlay;showDebugScreen()Z"
- ),
- to = @At(
- value = "CONSTANT",
- args = "stringValue=Keybindings"
- )
+ value = "INVOKE",
+ target = "Lnet/minecraft/client/gui/Gui;screen()Lnet/minecraft/client/gui/screens/Screen;",
+ ordinal = 1
)
)
- private Screen passEvents(Minecraft instance) {
+ private Screen passEvents(Gui instance) {
// allow user input is only the primary baritone
if (BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().isPathing() && player != null) {
return null;
}
- return instance.screen;
+ return instance.screen();
}
// TODO
diff --git a/src/launch/java/baritone/launch/mixins/MixinWorldRenderer.java b/src/launch/java/baritone/launch/mixins/MixinWorldRenderer.java
index 1384e41eb2..81921603e3 100644
--- a/src/launch/java/baritone/launch/mixins/MixinWorldRenderer.java
+++ b/src/launch/java/baritone/launch/mixins/MixinWorldRenderer.java
@@ -27,6 +27,7 @@
import net.minecraft.client.renderer.LevelRenderer;
import net.minecraft.client.renderer.chunk.ChunkSectionsToRender;
import net.minecraft.client.renderer.state.level.CameraRenderState;
+import org.joml.Matrix4f;
import org.joml.Matrix4fc;
import org.joml.Vector4f;
import org.spongepowered.asm.mixin.Mixin;
@@ -42,14 +43,15 @@
public class MixinWorldRenderer {
@Inject(
- method = "renderLevel",
+ method = "render",
at = @At("RETURN")
)
- private void onStartHand(final GraphicsResourceAllocator allocator, final DeltaTracker deltaTracker, final boolean outline, final CameraRenderState camera, final Matrix4fc modelViewMatrix, final GpuBufferSlice fog, final Vector4f fogColor, final boolean sky, final ChunkSectionsToRender chunkSectionsToRender, final CallbackInfo ci) {
+ private void onStartHand(final GraphicsResourceAllocator graphicsResourceAllocator, final DeltaTracker deltaTracker, final boolean bl, final CameraRenderState cameraRenderState, final Matrix4fc worldMatrix, final GpuBufferSlice gpuBufferSlice, final Vector4f vector4f, final boolean bl2, final CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
PoseStack poseStack = new PoseStack();
- poseStack.mulPose(modelViewMatrix);
- ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(deltaTracker.getGameTimeDeltaPartialTick(false), poseStack, camera.projectionMatrix));
+ poseStack.mulPose(worldMatrix);
+ Matrix4f projection = new Matrix4f(cameraRenderState.projectionMatrix);
+ ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(deltaTracker.getGameTimeDeltaPartialTick(false), poseStack, projection));
}
}
}
diff --git a/src/launch/resources/mixins.baritone.json b/src/launch/resources/mixins.baritone-meteor.json
similarity index 93%
rename from src/launch/resources/mixins.baritone.json
rename to src/launch/resources/mixins.baritone-meteor.json
index 8a71428f3c..f3118a9529 100644
--- a/src/launch/resources/mixins.baritone.json
+++ b/src/launch/resources/mixins.baritone-meteor.json
@@ -31,5 +31,6 @@
"MixinWorldRenderer"
],
"mixins": [
- ]
+ ],
+ "plugin": "baritone.launch.FabricMixinPlugin"
}
diff --git a/src/main/java/baritone/Baritone.java b/src/main/java/baritone/Baritone.java
index ad68714137..53f2bd3e0a 100755
--- a/src/main/java/baritone/Baritone.java
+++ b/src/main/java/baritone/Baritone.java
@@ -245,7 +245,7 @@ public void openClick() {
new Thread(() -> {
try {
Thread.sleep(100);
- mc.execute(() -> mc.setScreen(new GuiClick()));
+ mc.execute(() -> mc.gui.setScreen(new GuiClick()));
} catch (Exception ignored) {}
}).start();
}
diff --git a/src/main/java/baritone/behavior/LookBehavior.java b/src/main/java/baritone/behavior/LookBehavior.java
index 98e12aeff3..bc94a1224c 100644
--- a/src/main/java/baritone/behavior/LookBehavior.java
+++ b/src/main/java/baritone/behavior/LookBehavior.java
@@ -25,6 +25,7 @@
import baritone.api.event.events.*;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.Rotation;
+import baritone.api.utils.RotationUtils;
import baritone.behavior.look.ForkableRandom;
import net.minecraft.network.protocol.game.ServerboundMovePlayerPacket;
@@ -65,7 +66,12 @@ public LookBehavior(Baritone baritone) {
@Override
public void updateTarget(Rotation rotation, boolean blockInteract) {
- this.target = new Target(rotation, Target.Mode.resolve(ctx, blockInteract));
+ this.target = new Target(rotation, Target.Mode.resolve(ctx, blockInteract), Double.NaN);
+ }
+
+ @Override
+ public void updateTarget(Rotation rotation, boolean blockInteract, double targetDistance) {
+ this.target = new Target(rotation, Target.Mode.resolve(ctx, blockInteract), targetDistance);
}
@Override
@@ -95,7 +101,7 @@ public void onPlayerUpdate(PlayerUpdateEvent event) {
}
this.prevRotation = new Rotation(ctx.player().getYRot(), ctx.player().getXRot());
- final Rotation actual = this.processor.peekRotation(this.target.rotation);
+ final Rotation actual = this.processor.peekRotation(this.target.rotation, this.target.targetDistance);
ctx.player().setYRot(actual.getYaw());
ctx.player().setXRot(actual.getPitch());
break;
@@ -153,7 +159,7 @@ public void onWorldEvent(WorldEvent event) {
public void pig() {
if (this.target != null) {
- final Rotation actual = this.processor.peekRotation(this.target.rotation);
+ final Rotation actual = this.processor.peekRotation(this.target.rotation, this.target.targetDistance);
ctx.player().setYRot(actual.getYaw());
}
}
@@ -169,7 +175,7 @@ public Optional getEffectiveRotation() {
@Override
public void onPlayerRotationMove(RotationMoveEvent event) {
if (this.target != null) {
- final Rotation actual = this.processor.peekRotation(this.target.rotation);
+ final Rotation actual = this.processor.peekRotation(this.target.rotation, this.target.targetDistance);
event.setYaw(actual.getYaw());
event.setPitch(actual.getPitch());
}
@@ -209,6 +215,11 @@ private AbstractAimProcessor(final AbstractAimProcessor source) {
@Override
public final Rotation peekRotation(final Rotation rotation) {
+ return this.peekRotation(rotation, Double.NaN);
+ }
+
+ @Override
+ public final Rotation peekRotation(final Rotation rotation, final double targetDistance) {
final Rotation prev = this.getPrevRotation();
float desiredYaw = rotation.getYaw();
@@ -220,8 +231,8 @@ public final Rotation peekRotation(final Rotation rotation) {
desiredPitch = nudgeToLevel(desiredPitch);
}
- desiredYaw += this.randomYawOffset;
- desiredPitch += this.randomPitchOffset;
+ desiredYaw += distanceScaledAngle(this.randomYawOffset, targetDistance);
+ desiredPitch += distanceScaledAngle(this.randomPitchOffset, targetDistance);
return new Rotation(
this.calculateMouseMove(prev.getYaw(), desiredYaw),
@@ -307,14 +318,29 @@ private float mouseToAngle(double mouseDelta) {
}
}
+ /**
+ * Treats the random angle at one block away as the desired world-space offset, then converts that offset back
+ * into an angle at the actual target distance. Distances below one block are clamped so close targets never
+ * receive more variation than before.
+ */
+ static double distanceScaledAngle(double angle, double targetDistance) {
+ if (!Double.isFinite(targetDistance) || targetDistance <= 1.0D || angle == 0.0D) {
+ return angle;
+ }
+ double worldOffset = Math.tan(angle * RotationUtils.DEG_TO_RAD);
+ return Math.atan(worldOffset / targetDistance) * RotationUtils.RAD_TO_DEG;
+ }
+
private static class Target {
public final Rotation rotation;
public final Mode mode;
+ public final double targetDistance;
- public Target(Rotation rotation, Mode mode) {
+ public Target(Rotation rotation, Mode mode, double targetDistance) {
this.rotation = rotation;
this.mode = mode;
+ this.targetDistance = targetDistance;
}
enum Mode {
diff --git a/src/main/java/baritone/cache/CachedChunk.java b/src/main/java/baritone/cache/CachedChunk.java
index 86a849e5a6..7a7aa45e66 100644
--- a/src/main/java/baritone/cache/CachedChunk.java
+++ b/src/main/java/baritone/cache/CachedChunk.java
@@ -50,22 +50,23 @@ public final class CachedChunk {
Blocks.SPAWNER,
Blocks.BARRIER,
Blocks.OBSERVER,
- Blocks.WHITE_SHULKER_BOX,
- Blocks.ORANGE_SHULKER_BOX,
- Blocks.MAGENTA_SHULKER_BOX,
- Blocks.LIGHT_BLUE_SHULKER_BOX,
- Blocks.YELLOW_SHULKER_BOX,
- Blocks.LIME_SHULKER_BOX,
- Blocks.PINK_SHULKER_BOX,
- Blocks.GRAY_SHULKER_BOX,
- Blocks.LIGHT_GRAY_SHULKER_BOX,
- Blocks.CYAN_SHULKER_BOX,
- Blocks.PURPLE_SHULKER_BOX,
- Blocks.BLUE_SHULKER_BOX,
- Blocks.BROWN_SHULKER_BOX,
- Blocks.GREEN_SHULKER_BOX,
- Blocks.RED_SHULKER_BOX,
- Blocks.BLACK_SHULKER_BOX,
+ Blocks.SHULKER_BOX,
+ Blocks.DYED_SHULKER_BOX.white(),
+ Blocks.DYED_SHULKER_BOX.orange(),
+ Blocks.DYED_SHULKER_BOX.magenta(),
+ Blocks.DYED_SHULKER_BOX.lightBlue(),
+ Blocks.DYED_SHULKER_BOX.yellow(),
+ Blocks.DYED_SHULKER_BOX.lime(),
+ Blocks.DYED_SHULKER_BOX.pink(),
+ Blocks.DYED_SHULKER_BOX.gray(),
+ Blocks.DYED_SHULKER_BOX.lightGray(),
+ Blocks.DYED_SHULKER_BOX.cyan(),
+ Blocks.DYED_SHULKER_BOX.purple(),
+ Blocks.DYED_SHULKER_BOX.blue(),
+ Blocks.DYED_SHULKER_BOX.brown(),
+ Blocks.DYED_SHULKER_BOX.green(),
+ Blocks.DYED_SHULKER_BOX.red(),
+ Blocks.DYED_SHULKER_BOX.black(),
Blocks.NETHER_PORTAL,
Blocks.HOPPER,
Blocks.BEACON,
@@ -87,22 +88,22 @@ public final class CachedChunk {
Blocks.WITHER_SKELETON_WALL_SKULL,
Blocks.ENCHANTING_TABLE,
Blocks.ANVIL,
- Blocks.WHITE_BED,
- Blocks.ORANGE_BED,
- Blocks.MAGENTA_BED,
- Blocks.LIGHT_BLUE_BED,
- Blocks.YELLOW_BED,
- Blocks.LIME_BED,
- Blocks.PINK_BED,
- Blocks.GRAY_BED,
- Blocks.LIGHT_GRAY_BED,
- Blocks.CYAN_BED,
- Blocks.PURPLE_BED,
- Blocks.BLUE_BED,
- Blocks.BROWN_BED,
- Blocks.GREEN_BED,
- Blocks.RED_BED,
- Blocks.BLACK_BED,
+ Blocks.BED.white(),
+ Blocks.BED.orange(),
+ Blocks.BED.magenta(),
+ Blocks.BED.lightBlue(),
+ Blocks.BED.yellow(),
+ Blocks.BED.lime(),
+ Blocks.BED.pink(),
+ Blocks.BED.gray(),
+ Blocks.BED.lightGray(),
+ Blocks.BED.cyan(),
+ Blocks.BED.purple(),
+ Blocks.BED.blue(),
+ Blocks.BED.brown(),
+ Blocks.BED.green(),
+ Blocks.BED.red(),
+ Blocks.BED.black(),
Blocks.DRAGON_EGG,
Blocks.JUKEBOX,
Blocks.END_GATEWAY,
diff --git a/src/main/java/baritone/cache/WorldProvider.java b/src/main/java/baritone/cache/WorldProvider.java
index f503a07990..28b2d94f11 100644
--- a/src/main/java/baritone/cache/WorldProvider.java
+++ b/src/main/java/baritone/cache/WorldProvider.java
@@ -20,9 +20,9 @@
import baritone.Baritone;
import baritone.api.cache.IWorldProvider;
import baritone.api.utils.IPlayerContext;
+import baritone.api.utils.Pair;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.resources.Identifier;
-import net.minecraft.util.Tuple;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.storage.LevelResource;
import org.apache.commons.lang3.SystemUtils;
@@ -71,8 +71,8 @@ public final WorldData getCurrentWorld() {
*/
public final void initWorld(Level world) {
this.getSaveDirectories(world).ifPresent(dirs -> {
- final Path worldDir = dirs.getA();
- final Path readmeDir = dirs.getB();
+ final Path worldDir = dirs.first();
+ final Path readmeDir = dirs.second();
try {
// lol wtf is this baritone folder in my minecraft save?
@@ -119,7 +119,7 @@ private Path getWorldDataDirectory(Path parent, Level world) {
* @return An {@link Optional} containing the world's baritone dir and readme dir, or {@link Optional#empty()} if
* the world isn't valid for caching.
*/
- private Optional> getSaveDirectories(Level world) {
+ private Optional> getSaveDirectories(Level world) {
Path worldDir;
Path readmeDir;
@@ -156,7 +156,7 @@ private Optional> getSaveDirectories(Level world) {
readmeDir = baritone.getDirectory();
}
- return Optional.of(new Tuple<>(worldDir, readmeDir));
+ return Optional.of(new Pair<>(worldDir, readmeDir));
}
/**
diff --git a/src/main/java/baritone/cache/WorldScanner.java b/src/main/java/baritone/cache/WorldScanner.java
index c9431038bf..ae9d928769 100644
--- a/src/main/java/baritone/cache/WorldScanner.java
+++ b/src/main/java/baritone/cache/WorldScanner.java
@@ -29,6 +29,7 @@
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.chunk.LevelChunkSection;
+import net.minecraft.world.level.chunk.status.ChunkStatus;
import net.minecraft.world.level.chunk.PalettedContainer;
import java.util.*;
@@ -96,7 +97,7 @@ public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filt
}
ClientChunkCache chunkProvider = (ClientChunkCache) ctx.world().getChunkSource();
- LevelChunk chunk = chunkProvider.getChunk(pos.x(), pos.z(), null, false);
+ LevelChunk chunk = chunkProvider.getChunk(pos.x(), pos.z(), ChunkStatus.FULL, false);
int playerY = ctx.playerFeet().getY();
if (chunk == null || chunk.isEmpty()) {
diff --git a/src/main/java/baritone/command/ExampleBaritoneControl.java b/src/main/java/baritone/command/ExampleBaritoneControl.java
index bb9681e97d..82f1cc57c3 100644
--- a/src/main/java/baritone/command/ExampleBaritoneControl.java
+++ b/src/main/java/baritone/command/ExampleBaritoneControl.java
@@ -28,6 +28,7 @@
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.TabCompleteEvent;
import baritone.api.utils.Helper;
+import baritone.api.utils.Pair;
import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior;
import baritone.command.argument.ArgConsumer;
@@ -38,7 +39,6 @@
import net.minecraft.network.chat.Component;
import net.minecraft.network.chat.HoverEvent;
import net.minecraft.network.chat.MutableComponent;
-import net.minecraft.util.Tuple;
import net.minecraft.util.Util;
import java.util.List;
@@ -66,7 +66,7 @@ public void onSendChatMessage(ChatEvent event) {
event.cancel();
String commandStr = msg.substring(forceRun ? FORCE_COMMAND_PREFIX.length() : prefix.length());
if (!runCommand(commandStr) && !commandStr.trim().isEmpty()) {
- new CommandNotFoundException(CommandManager.expand(commandStr).getA()).handle(null, null);
+ new CommandNotFoundException(CommandManager.expand(commandStr).first()).handle(null, null);
}
} else if ((settings.chatControl.value || settings.chatControlAnyway.value) && runCommand(msg)) {
event.cancel();
@@ -103,10 +103,10 @@ public boolean runCommand(String msg) {
if (msg.isEmpty()) {
return this.runCommand("help");
}
- Tuple> pair = CommandManager.expand(msg);
- String command = pair.getA();
- String rest = msg.substring(pair.getA().length());
- ArgConsumer argc = new ArgConsumer(this.manager, pair.getB());
+ Pair> pair = CommandManager.expand(msg);
+ String command = pair.first();
+ String rest = msg.substring(pair.first().length());
+ ArgConsumer argc = new ArgConsumer(this.manager, pair.second());
if (!argc.hasAny()) {
Settings.Setting setting = settings.byLowerName.get(command.toLowerCase(Locale.US));
if (setting != null) {
@@ -123,7 +123,7 @@ public boolean runCommand(String msg) {
if (setting.isJavaOnly()) {
continue;
}
- if (setting.getName().equalsIgnoreCase(pair.getA())) {
+ if (setting.getName().equalsIgnoreCase(pair.first())) {
logRanCommand(command, rest);
try {
this.manager.execute(String.format("set %s %s", setting.getName(), argc.getString()));
@@ -134,7 +134,7 @@ public boolean runCommand(String msg) {
}
// If the command exists, then handle echoing the input
- if (this.manager.getCommand(pair.getA()) != null) {
+ if (this.manager.getCommand(pair.first()) != null) {
logRanCommand(command, rest);
}
diff --git a/src/main/java/baritone/command/defaults/ElytraCommand.java b/src/main/java/baritone/command/defaults/ElytraCommand.java
index 771d6c1e7b..448931e6a6 100644
--- a/src/main/java/baritone/command/defaults/ElytraCommand.java
+++ b/src/main/java/baritone/command/defaults/ElytraCommand.java
@@ -71,6 +71,9 @@ public void execute(String label, IArgConsumer args) throws CommandException {
if (iGoal == null) {
throw new CommandInvalidStateException("No goal has been set");
}
+ if (ctx.world().dimension() != Level.NETHER) {
+ throw new CommandInvalidStateException("Only works in the nether");
+ }
try {
elytra.pathTo(iGoal);
} catch (IllegalArgumentException ex) {
@@ -82,11 +85,7 @@ public void execute(String label, IArgConsumer args) throws CommandException {
final String action = args.getString();
switch (action) {
case "reset": {
- try {
- elytra.resetState();
- } catch (IllegalArgumentException ex) {
- throw new CommandInvalidStateException(ex.getMessage());
- }
+ elytra.resetState();
logDirect("Reset state but still flying to same goal");
break;
}
@@ -129,26 +128,22 @@ private Component suggest2b2tSeeds() {
private void gatekeep() {
MutableComponent gatekeep = Component.literal("");
gatekeep.append("To disable this message, enable the setting elytraTermsAccepted\n");
- gatekeep.append("Baritone Elytra is an experimental feature. It is intended for long distance travel in the Nether but will also work in the Overworld, using fireworks for vanilla boost. It will not work with any other mods (\"hacks\") for non-vanilla boost. ");
+ gatekeep.append("Baritone Elytra is an experimental feature. It is only intended for long distance travel in the Nether using fireworks for vanilla boost. It will not work with any other mods (\"hacks\") for non-vanilla boost. ");
MutableComponent gatekeep2 = Component.literal("If you want Baritone to attempt to take off from the ground for you, you can enable the elytraAutoJump setting (not advisable on laggy servers!). ");
gatekeep2.setStyle(gatekeep2.getStyle().withHoverEvent(new HoverEvent.ShowText(Component.literal(Baritone.settings().prefix.value + "set elytraAutoJump true"))));
gatekeep.append(gatekeep2);
MutableComponent gatekeep3 = Component.literal("If you want Baritone to go slower, enable the elytraConserveFireworks setting and/or decrease the elytraFireworkSpeed setting. ");
gatekeep3.setStyle(gatekeep3.getStyle().withHoverEvent(new HoverEvent.ShowText(Component.literal(Baritone.settings().prefix.value + "set elytraConserveFireworks true\n" + Baritone.settings().prefix.value + "set elytraFireworkSpeed 0.6\n(the 0.6 number is just an example, tweak to your liking)"))));
gatekeep.append(gatekeep3);
- MutableComponent gatekeep4 = Component.literal("Baritone Elytra for use in the ");
- MutableComponent red1 = Component.literal("Nether");
- red1.setStyle(red1.getStyle().withColor(ChatFormatting.RED).withUnderlined(true).withBold(true));
- gatekeep4.append(red1);
- gatekeep4.append(", ");
- MutableComponent red2 = Component.literal("wants to know the seed");
- red2.setStyle(red2.getStyle().withColor(ChatFormatting.RED).withUnderlined(true).withBold(true));
- gatekeep4.append(red2);
+ MutableComponent gatekeep4 = Component.literal("Baritone Elytra ");
+ MutableComponent red = Component.literal("wants to know the seed");
+ red.setStyle(red.getStyle().withColor(ChatFormatting.RED).withUnderlined(true).withBold(true));
+ gatekeep4.append(red);
gatekeep4.append(" of the world you are in. If it doesn't have the correct seed, it will frequently backtrack. It uses the seed to generate terrain far beyond what you can see, since terrain obstacles in the Nether can be much larger than your render distance. ");
gatekeep.append(gatekeep4);
gatekeep.append("\n");
if (detectOn2b2t()) {
- MutableComponent gatekeep5 = Component.literal("It looks like you're on 2b2t. Terrain prediction can be used but new nether terrain can not be predicted on 2b2t. ");
+ MutableComponent gatekeep5 = Component.literal("It looks like you're on 2b2t. ");
gatekeep5.append(suggest2b2tSeeds());
if (!Baritone.settings().elytraPredictTerrain.value) {
gatekeep5.append(Baritone.settings().prefix.value + "elytraPredictTerrain is currently disabled. ");
diff --git a/src/main/java/baritone/command/defaults/PathCommand.java b/src/main/java/baritone/command/defaults/PathCommand.java
index 1a98b0c27a..b2021adf62 100644
--- a/src/main/java/baritone/command/defaults/PathCommand.java
+++ b/src/main/java/baritone/command/defaults/PathCommand.java
@@ -38,10 +38,6 @@ public PathCommand(IBaritone baritone) {
public void execute(String label, IArgConsumer args) throws CommandException {
ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
args.requireMax(0);
- if (customGoalProcess.getGoal() == null) {
- logDirect("No goal set");
- return;
- }
BaritoneAPI.getProvider().getWorldScanner().repack(ctx);
customGoalProcess.path();
logDirect("Now pathing");
diff --git a/src/main/java/baritone/command/defaults/RenderCommand.java b/src/main/java/baritone/command/defaults/RenderCommand.java
index 37d70b42b8..a8a35948b0 100644
--- a/src/main/java/baritone/command/defaults/RenderCommand.java
+++ b/src/main/java/baritone/command/defaults/RenderCommand.java
@@ -38,7 +38,7 @@ public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
BetterBlockPos origin = ctx.playerFeet();
int renderDistance = (ctx.minecraft().options.renderDistance().get() + 1) * 16;
- ctx.minecraft().levelRenderer.setBlocksDirty(
+ ctx.minecraft().levelExtractor.setBlocksDirty(
origin.x - renderDistance,
ctx.world().getMinY(),
origin.z - renderDistance,
diff --git a/src/main/java/baritone/command/manager/CommandManager.java b/src/main/java/baritone/command/manager/CommandManager.java
index 8712165f14..813c2dfd73 100644
--- a/src/main/java/baritone/command/manager/CommandManager.java
+++ b/src/main/java/baritone/command/manager/CommandManager.java
@@ -27,10 +27,10 @@
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.command.manager.ICommandManager;
import baritone.api.command.registry.Registry;
+import baritone.api.utils.Pair;
import baritone.command.argument.ArgConsumer;
import baritone.command.argument.CommandArguments;
import baritone.command.defaults.DefaultCommands;
-import net.minecraft.util.Tuple;
import java.util.List;
import java.util.Locale;
@@ -79,7 +79,7 @@ public boolean execute(String string) {
}
@Override
- public boolean execute(Tuple> expanded) {
+ public boolean execute(Pair> expanded) {
ExecutionWrapper execution = this.from(expanded);
if (execution != null) {
execution.execute();
@@ -88,16 +88,16 @@ public boolean execute(Tuple> expanded) {
}
@Override
- public Stream tabComplete(Tuple> expanded) {
+ public Stream tabComplete(Pair> expanded) {
ExecutionWrapper execution = this.from(expanded);
return execution == null ? Stream.empty() : execution.tabComplete();
}
@Override
public Stream tabComplete(String prefix) {
- Tuple> pair = expand(prefix, true);
- String label = pair.getA();
- List args = pair.getB();
+ Pair> pair = expand(prefix, true);
+ String label = pair.first();
+ List args = pair.second();
if (args.isEmpty()) {
return new TabCompleteHelper()
.addCommands(this.baritone.getCommandManager())
@@ -108,21 +108,21 @@ public Stream tabComplete(String prefix) {
}
}
- private ExecutionWrapper from(Tuple> expanded) {
- String label = expanded.getA();
- ArgConsumer args = new ArgConsumer(this, expanded.getB());
+ private ExecutionWrapper from(Pair> expanded) {
+ String label = expanded.first();
+ ArgConsumer args = new ArgConsumer(this, expanded.second());
ICommand command = this.getCommand(label);
return command == null ? null : new ExecutionWrapper(command, label, args);
}
- private static Tuple> expand(String string, boolean preserveEmptyLast) {
+ private static Pair> expand(String string, boolean preserveEmptyLast) {
String label = string.split("\\s", 2)[0];
List args = CommandArguments.from(string.substring(label.length()), preserveEmptyLast);
- return new Tuple<>(label, args);
+ return new Pair<>(label, args);
}
- public static Tuple> expand(String string) {
+ public static Pair> expand(String string) {
return expand(string, false);
}
diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java
index 739c8ee894..a59e5aeaec 100644
--- a/src/main/java/baritone/pathing/movement/Movement.java
+++ b/src/main/java/baritone/pathing/movement/Movement.java
@@ -135,7 +135,8 @@ public MovementStatus update() {
currentState.getTarget().getRotation().ifPresent(rotation ->
baritone.getLookBehavior().updateTarget(
rotation,
- currentState.getTarget().hasToForceRotations()));
+ currentState.getTarget().hasToForceRotations(),
+ currentState.getTarget().getTargetDistance()));
baritone.getInputOverrideHandler().clearAllKeys();
currentState.getInputStates().forEach((input, forced) -> {
baritone.getInputOverrideHandler().setInputForceState(input, forced);
@@ -165,7 +166,10 @@ protected boolean prepared(MovementState state) {
Optional reachable = RotationUtils.reachable(ctx, blockPos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
Rotation rotTowardsBlock = reachable.get();
- state.setTarget(new MovementState.MovementTarget(rotTowardsBlock, true));
+ state.setTarget(new MovementState.MovementTarget(
+ rotTowardsBlock,
+ true,
+ ctx.playerHead().distanceTo(VecUtils.getBlockPosCenter(blockPos))));
if (ctx.isLookingAt(blockPos) || ctx.playerRotations().isReallyCloseTo(rotTowardsBlock)) {
state.setInput(Input.CLICK_LEFT, true);
}
@@ -176,7 +180,8 @@ protected boolean prepared(MovementState state) {
//i dont care if theres snow in the way!!!!!!!
//you dont own me!!!!
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
- VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true)
+ VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true,
+ ctx.playerHead().distanceTo(VecUtils.getBlockPosCenter(blockPos)))
);
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
state.setInput(Input.CLICK_LEFT, true);
diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java
index 51a23577ba..9d83779f70 100644
--- a/src/main/java/baritone/pathing/movement/MovementHelper.java
+++ b/src/main/java/baritone/pathing/movement/MovementHelper.java
@@ -322,6 +322,11 @@ static boolean isReplaceable(int x, int y, int z, BlockState state, BlockStateIn
return state.canBeReplaced();
}
+ @Deprecated
+ static boolean isReplacable(int x, int y, int z, BlockState state, BlockStateInterface bsi) {
+ return isReplaceable(x, y, z, state, bsi);
+ }
+
static boolean isDoorPassable(IPlayerContext ctx, BlockPos doorPos, BlockPos playerPos) {
if (playerPos.equals(doorPos)) {
return false;
@@ -413,7 +418,7 @@ static Ternary canWalkOnBlockState(BlockState state) {
if (block instanceof AzaleaBlock) {
return YES;
}
- if (block == Blocks.LADDER || (isClimbable(block) && Baritone.settings().allowVines.value)) { // TODO reconsider this
+ if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
return YES;
}
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH || block == Blocks.SOUL_SAND) {
@@ -527,7 +532,7 @@ static boolean canUseFrostWalker(IPlayerContext ctx, BlockPos pos) {
*/
static boolean mustBeSolidToWalkOn(CalculationContext context, int x, int y, int z, BlockState state) {
Block block = state.getBlock();
- if (isClimbable(block)) {
+ if (block == Blocks.LADDER || block == Blocks.VINE) {
return false;
}
if (!state.getFluidState().isEmpty()) {
@@ -586,20 +591,6 @@ static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, Blo
return isBlockNormalCube(state) || state.getBlock() == Blocks.GLASS || state.getBlock() instanceof StainedGlassBlock;
}
- /**
- * Can we climb up this block by pressing space while inside it?
- * Also doubles as "If I start a movement on this, can weird things happen?"
- * because movements can end/start on these blocks despite them not being canWalkOn.
- */
- static boolean isClimbable(Block block) {
- return block == Blocks.LADDER
- || block == Blocks.VINE
- || block == Blocks.WEEPING_VINES
- || block == Blocks.WEEPING_VINES_PLANT
- || block == Blocks.TWISTING_VINES
- || block == Blocks.TWISTING_VINES_PLANT;
- }
-
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
return getMiningDurationTicks(context, x, y, z, context.get(x, y, z), includeFalling);
}
diff --git a/src/main/java/baritone/pathing/movement/MovementState.java b/src/main/java/baritone/pathing/movement/MovementState.java
index 73539698a6..54eba038db 100644
--- a/src/main/java/baritone/pathing/movement/MovementState.java
+++ b/src/main/java/baritone/pathing/movement/MovementState.java
@@ -72,13 +72,23 @@ public static class MovementTarget {
*/
private boolean forceRotations;
+ /**
+ * Distance from the player's eyes to an interaction target, or {@link Double#NaN} when not applicable.
+ */
+ private double targetDistance;
+
public MovementTarget() {
- this(null, false);
+ this(null, false, Double.NaN);
}
public MovementTarget(Rotation rotation, boolean forceRotations) {
+ this(rotation, forceRotations, Double.NaN);
+ }
+
+ public MovementTarget(Rotation rotation, boolean forceRotations, double targetDistance) {
this.rotation = rotation;
this.forceRotations = forceRotations;
+ this.targetDistance = targetDistance;
}
public final Optional getRotation() {
@@ -88,5 +98,9 @@ public final Optional getRotation() {
public boolean hasToForceRotations() {
return this.forceRotations;
}
+
+ public double getTargetDistance() {
+ return this.targetDistance;
+ }
}
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java
index 1b9fedea5f..2ecd9d7238 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementAscend.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementAscend.java
@@ -112,7 +112,7 @@ public static double cost(CalculationContext context, int x, int y, int z, int d
// and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us
}
BlockState srcDown = context.get(x, y - 1, z);
- if (MovementHelper.isClimbable(srcDown.getBlock())) {
+ if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) {
return COST_INF;
}
// we can jump from soul sand, but not from a bottom slab
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
index 0052efed2c..41c20be3e0 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementDescend.java
@@ -94,7 +94,7 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
}
Block fromDown = context.get(x, y - 1, z).getBlock();
- if (MovementHelper.isClimbable(fromDown)) {
+ if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
return;
}
@@ -186,7 +186,7 @@ public static boolean dynamicFallCost(CalculationContext context, int x, int y,
res.cost = tentativeCost;
return false;
}
- if (unprotectedFallHeight <= 11 && MovementHelper.isClimbable(ontoBlock.getBlock())) {
+ if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) {
// if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know
// this effectively "resets" our falling speed
costSoFar += FALL_N_BLOCKS_COST[unprotectedFallHeight - 1];// we fall until the top of this block (not including this block)
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
index 8be1047582..e7d74f03ef 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementDiagonal.java
@@ -152,7 +152,7 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
multiplier += context.walkOnWaterOnePenalty * SQRT_2;
}
Block fromDownBlock = fromDown.getBlock();
- if (MovementHelper.isClimbable(fromDownBlock)) {
+ if (fromDownBlock == Blocks.LADDER || fromDownBlock == Blocks.VINE) {
return;
}
if (fromDownBlock == Blocks.SOUL_SAND) {
@@ -235,7 +235,7 @@ public static void cost(CalculationContext context, int x, int y, int z, int des
}
if (optionA != 0 || optionB != 0) {
multiplier *= SQRT_2 - 0.001; // TODO tune
- if (MovementHelper.isClimbable(startIn)) {
+ if (startIn == Blocks.LADDER || startIn == Blocks.VINE) {
// edging around doesn't work if doing so would climb a ladder or vine instead of moving sideways
return;
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
index a3ebc796f7..900da79c14 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementParkour.java
@@ -91,7 +91,7 @@ public static void cost(CalculationContext context, int x, int y, int z, Directi
return;
}
BlockState standingOn = context.get(x, y - 1, z);
- if (MovementHelper.isClimbable(standingOn.getBlock()) || standingOn.getBlock() instanceof StairBlock || MovementHelper.isBottomSlab(standingOn)) {
+ if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof StairBlock || MovementHelper.isBottomSlab(standingOn)) {
return;
}
// we can't jump from (frozen) water with assumeWalkOnWater because we can't be sure it will be frozen
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
index dc6f6b3e2e..33493c1c97 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementPillar.java
@@ -58,16 +58,19 @@ protected Set calculateValidPositions() {
public static double cost(CalculationContext context, int x, int y, int z) {
BlockState fromState = context.get(x, y, z);
Block from = fromState.getBlock();
- boolean ladder = MovementHelper.isClimbable(from);
+ boolean ladder = from == Blocks.LADDER || from == Blocks.VINE;
BlockState fromDown = context.get(x, y - 1, z);
if (!ladder) {
- if (MovementHelper.isClimbable(fromDown.getBlock())) {
+ if (fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE) {
return COST_INF; // can't pillar from a ladder or vine onto something that isn't also climbable
}
if (fromDown.getBlock() instanceof SlabBlock && fromDown.getValue(SlabBlock.TYPE) == SlabType.BOTTOM) {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
}
}
+ if (from == Blocks.VINE && !hasAgainst(context, x, y, z)) { // TODO this vine can't be climbed, but we could place a pillar still since vines are replacable, no? perhaps the pillar jump would be impossible because of the slowdown actually.
+ return COST_INF;
+ }
BlockState toBreak = context.get(x, y + 2, z);
Block toBreakBlock = toBreak.getBlock();
if (toBreakBlock instanceof FenceGateBlock) { // see issue #172
@@ -106,7 +109,7 @@ public static double cost(CalculationContext context, int x, int y, int z) {
return COST_INF;
}
if (hardness != 0) {
- if (MovementHelper.isClimbable(toBreakBlock)) {
+ if (toBreakBlock == Blocks.LADDER || toBreakBlock == Blocks.VINE) {
hardness = 0; // we won't actually need to break the ladder / vine because we're going to use it
} else {
BlockState check = context.get(x, y + 3, z); // the block on top of the one we're going to break, could it fall on us?
@@ -135,6 +138,29 @@ public static double cost(CalculationContext context, int x, int y, int z) {
}
}
+ public static boolean hasAgainst(CalculationContext context, int x, int y, int z) {
+ return MovementHelper.isBlockNormalCube(context.get(x + 1, y, z)) ||
+ MovementHelper.isBlockNormalCube(context.get(x - 1, y, z)) ||
+ MovementHelper.isBlockNormalCube(context.get(x, y, z + 1)) ||
+ MovementHelper.isBlockNormalCube(context.get(x, y, z - 1));
+ }
+
+ public static BlockPos getAgainst(CalculationContext context, BetterBlockPos vine) {
+ if (MovementHelper.isBlockNormalCube(context.get(vine.north()))) {
+ return vine.north();
+ }
+ if (MovementHelper.isBlockNormalCube(context.get(vine.south()))) {
+ return vine.south();
+ }
+ if (MovementHelper.isBlockNormalCube(context.get(vine.east()))) {
+ return vine.east();
+ }
+ if (MovementHelper.isBlockNormalCube(context.get(vine.west()))) {
+ return vine.west();
+ }
+ return null;
+ }
+
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
@@ -159,8 +185,8 @@ public MovementState updateState(MovementState state) {
}
return state;
}
- boolean ladder = MovementHelper.isClimbable(fromDown.getBlock());
-
+ boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE;
+ boolean vine = fromDown.getBlock() == Blocks.VINE;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(positionToPlace),
ctx.playerRotations());
@@ -170,12 +196,25 @@ public MovementState updateState(MovementState state) {
boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder;
if (ladder) {
- if (ctx.playerFeet().equals(dest)) {
+ BlockPos against = vine ? getAgainst(new CalculationContext(baritone), src) : src.relative(fromDown.getValue(LadderBlock.FACING).getOpposite());
+ if (against == null) {
+ logDirect("Unable to climb vines. Consider disabling allowVines.");
+ return state.setStatus(MovementStatus.UNREACHABLE);
+ }
+
+ if (ctx.playerFeet().equals(against.above()) || ctx.playerFeet().equals(dest)) {
return state.setStatus(MovementStatus.SUCCESS);
}
+ if (MovementHelper.isBottomSlab(BlockStateInterface.get(ctx, src.below()))) {
+ state.setInput(Input.JUMP, true);
+ }
+ /*
+ if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) {
+ Baritone.moveTowardsBlock(from);
+ }
+ */
- MovementHelper.moveTowards(ctx, state, dest);
- state.setInput(Input.JUMP, true);
+ MovementHelper.moveTowards(ctx, state, against);
return state;
} else {
// Get ready to place a throwaway block
@@ -234,7 +273,7 @@ public MovementState updateState(MovementState state) {
protected boolean prepared(MovementState state) {
if (ctx.playerFeet().equals(src) || ctx.playerFeet().equals(src.below())) {
Block block = BlockStateInterface.getBlock(ctx, src.below());
- if (MovementHelper.isClimbable(block)) {
+ if (block == Blocks.LADDER || block == Blocks.VINE) {
state.setInput(Input.SNEAK, true);
}
}
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
index 1be82777f3..122c6bfe96 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
@@ -118,13 +118,13 @@ public static double cost(CalculationContext context, int x, int y, int z, int d
}
return WC;
}
- if (MovementHelper.isClimbable(srcDownBlock)) {
+ if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) {
hardness1 *= 5;
hardness2 *= 5;
}
return WC + hardness1 + hardness2;
} else {//this is a bridge, so we need to place a block
- if (MovementHelper.isClimbable(srcDownBlock)) {
+ if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) {
return COST_INF;
}
if (MovementHelper.isReplaceable(destX, y - 1, destZ, destOn, context.bsi)) {
@@ -218,7 +218,7 @@ public MovementState updateState(MovementState state) {
}
Block fd = BlockStateInterface.get(ctx, src.below()).getBlock();
- boolean ladder = MovementHelper.isClimbable(fd);
+ boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE;
//sneak may have been set to true in the PREPPING state while mining an adjacent block, but we still want it to be true if the player is about to go on magma
state.setInput(Input.SNEAK, Baritone.settings().allowWalkOnMagmaBlocks.value && MovementHelper.steppingOnBlocks(ctx).stream().anyMatch(block -> ctx.world().getBlockState(block).is(Blocks.MAGMA_BLOCK)));
@@ -265,7 +265,7 @@ public MovementState updateState(MovementState state) {
}
Block low = BlockStateInterface.get(ctx, src).getBlock();
Block high = BlockStateInterface.get(ctx, src.above()).getBlock();
- if (ctx.player().position().y > src.y + 0.1D && !ctx.player().onGround() && (MovementHelper.isClimbable(low) || MovementHelper.isClimbable(high))) {
+ if (ctx.player().position().y > src.y + 0.1D && !ctx.player().onGround() && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) {
// hitting W could cause us to climb the ladder instead of going forward
// wait until we're on the ground
return state;
@@ -278,10 +278,15 @@ public MovementState updateState(MovementState state) {
}
BlockState destDown = BlockStateInterface.get(ctx, dest.below());
- if (feet.getY() != dest.getY() && ladder && MovementHelper.isClimbable(destDown.getBlock())) {
- state.setInput(Input.JUMP, true);
+ BlockPos against = positionsToBreak[0];
+ if (feet.getY() != dest.getY() && ladder && (destDown.getBlock() == Blocks.VINE || destDown.getBlock() == Blocks.LADDER)) {
+ against = destDown.getBlock() == Blocks.VINE ? MovementPillar.getAgainst(new CalculationContext(baritone), dest.below()) : dest.relative(destDown.getValue(LadderBlock.FACING).getOpposite());
+ if (against == null) {
+ logDirect("Unable to climb vines. Consider disabling allowVines.");
+ return state.setStatus(MovementStatus.UNREACHABLE);
+ }
}
- MovementHelper.moveTowards(ctx, state, positionsToBreak[0]);
+ MovementHelper.moveTowards(ctx, state, against);
return state;
} else {
wasTheBridgeBlockAlwaysThere = false;
@@ -368,7 +373,7 @@ public boolean safeToCancel(MovementState state) {
protected boolean prepared(MovementState state) {
if (ctx.playerFeet().equals(src) || ctx.playerFeet().equals(src.below())) {
Block block = BlockStateInterface.getBlock(ctx, src.below());
- if (MovementHelper.isClimbable(block)) {
+ if (block == Blocks.LADDER || block == Blocks.VINE) {
state.setInput(Input.SNEAK, true);
}
}
diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java
index 8a5359b5bd..04afddfcd7 100644
--- a/src/main/java/baritone/pathing/path/PathExecutor.java
+++ b/src/main/java/baritone/pathing/path/PathExecutor.java
@@ -34,7 +34,6 @@
import baritone.utils.BlockStateInterface;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
-import net.minecraft.util.Tuple;
import net.minecraft.world.phys.Vec3;
import java.util.*;
@@ -125,10 +124,10 @@ public boolean onTick() {
}
}
}
- Tuple status = closestPathPos(path);
+ Pair status = closestPathPos(path);
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
ticksAway++;
- System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getA() + ". Threshold: " + MAX_DIST_FROM_PATH);
+ System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.first() + ". Threshold: " + MAX_DIST_FROM_PATH);
if (ticksAway > MAX_TICKS_AWAY) {
logDebug("Too far away from path for too long, cancelling path");
cancel();
@@ -252,7 +251,7 @@ public boolean onTick() {
return canCancel; // movement is in progress, but if it reports cancellable, PathingBehavior is good to cut onto the next path
}
- private Tuple closestPathPos(IPath path) {
+ private Pair closestPathPos(IPath path) {
double best = -1;
BlockPos bestPos = null;
for (IMovement movement : path.movements()) {
@@ -264,7 +263,7 @@ private Tuple closestPathPos(IPath path) {
}
}
}
- return new Tuple<>(best, bestPos);
+ return new Pair<>(best, bestPos);
}
private boolean shouldPause() {
@@ -300,8 +299,8 @@ private boolean shouldPause() {
return positions.contains(ctx.playerFeet());
}
- private boolean possiblyOffPath(Tuple status, double leniency) {
- double distanceFromPath = status.getA();
+ private boolean possiblyOffPath(Pair status, double leniency) {
+ double distanceFromPath = status.first();
if (distanceFromPath > leniency) {
// when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path
if (path.movements().get(pathPosition) instanceof MovementFall) {
@@ -451,9 +450,9 @@ private boolean shouldSprintNextTick() {
}
}
if (current instanceof MovementFall) {
- Tuple data = overrideFall((MovementFall) current);
+ Pair data = overrideFall((MovementFall) current);
if (data != null) {
- BetterBlockPos fallDest = new BetterBlockPos(data.getB());
+ BetterBlockPos fallDest = new BetterBlockPos(data.second());
if (!path.positions().contains(fallDest)) {
throw new IllegalStateException(String.format(
"Fall override at %s %s %s returned illegal destination %s %s %s",
@@ -466,7 +465,7 @@ private boolean shouldSprintNextTick() {
return true;
}
clearKeys();
- behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getA(), ctx.playerRotations()), false);
+ behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.first(), ctx.playerRotations()), false);
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
return true;
}
@@ -474,7 +473,7 @@ private boolean shouldSprintNextTick() {
return false;
}
- private Tuple overrideFall(MovementFall movement) {
+ private Pair overrideFall(MovementFall movement) {
Vec3i dir = movement.getDirection();
if (dir.getY() < -3) {
return null;
@@ -508,7 +507,7 @@ private Tuple overrideFall(MovementFall movement) {
return null; // no valid extension exists
}
double len = i - pathPosition - 0.4;
- return new Tuple<>(
+ return new Pair<>(
new Vec3(flatDir.getX() * len + movement.getDest().x + 0.5, movement.getDest().y, flatDir.getZ() * len + movement.getDest().z + 0.5),
movement.getDest().offset(flatDir.getX() * (i - pathPosition), 0, flatDir.getZ() * (i - pathPosition)));
}
diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java
index 83356d782d..ee0157ceaf 100644
--- a/src/main/java/baritone/process/BuilderProcess.java
+++ b/src/main/java/baritone/process/BuilderProcess.java
@@ -46,7 +46,6 @@
import net.minecraft.core.BlockPos;
import net.minecraft.core.Direction;
import net.minecraft.core.Vec3i;
-import net.minecraft.util.Tuple;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.item.BlockItem;
import net.minecraft.world.item.ItemStack;
@@ -203,10 +202,10 @@ private ISchematic applyMapArtAndSelection(Vec3i origin, IStaticSchematic parsed
@Override
public void buildOpenSchematic() {
if (SchematicaHelper.isSchematicaPresent()) {
- Optional> schematic = SchematicaHelper.getOpenSchematic();
+ Optional> schematic = SchematicaHelper.getOpenSchematic();
if (schematic.isPresent()) {
- IStaticSchematic raw = schematic.get().getA();
- BlockPos origin = schematic.get().getB();
+ IStaticSchematic raw = schematic.get().first();
+ BlockPos origin = schematic.get().second();
ISchematic schem = applyMapArtAndSelection(origin, raw);
this.build(raw.toString(), schem, origin);
} else {
@@ -222,10 +221,10 @@ public void buildOpenLitematic(int i) {
if (LitematicaHelper.isLitematicaPresent()) {
//if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager
if (LitematicaHelper.hasLoadedSchematic(i)) {
- Tuple schematic = LitematicaHelper.getSchematic(i);
- Vec3i correctedOrigin = schematic.getB();
- ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA());
- build(schematic.getA().toString(), schematic2, correctedOrigin);
+ Pair schematic = LitematicaHelper.getSchematic(i);
+ Vec3i correctedOrigin = schematic.second();
+ ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.first());
+ build(schematic.first().toString(), schematic2, correctedOrigin);
} else {
logDirect(String.format("List of placements has no entry %s", i + 1));
}
@@ -266,7 +265,7 @@ public BlockState placeAt(int x, int y, int z, BlockState current) {
return state;
}
- private Optional> toBreakNearPlayer(BuilderCalculationContext bcc) {
+ private Optional> toBreakNearPlayer(BuilderCalculationContext bcc) {
BetterBlockPos center = ctx.playerFeet();
BetterBlockPos pathStart = baritone.getPathingBehavior().pathStart();
for (int dx = -5; dx <= 5; dx++) {
@@ -287,7 +286,7 @@ private Optional> toBreakNearPlayer(BuilderCalcu
BetterBlockPos pos = new BetterBlockPos(x, y, z);
Optional rot = RotationUtils.reachable(ctx, pos, ctx.playerController().getBlockReachDistance());
if (rot.isPresent()) {
- return Optional.of(new Tuple<>(pos, rot.get()));
+ return Optional.of(new Pair<>(pos, rot.get()));
}
}
}
@@ -531,12 +530,12 @@ public int lengthZ() {
trim();
}
- Optional> toBreak = toBreakNearPlayer(bcc);
+ Optional> toBreak = toBreakNearPlayer(bcc);
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround()) {
// we'd like to pause to break this block
// only change look direction if it's safe (don't want to fuck up an in progress parkour for example
- Rotation rot = toBreak.get().getB();
- BetterBlockPos pos = toBreak.get().getA();
+ Rotation rot = toBreak.get().second();
+ BetterBlockPos pos = toBreak.get().first();
baritone.getLookBehavior().updateTarget(rot, true);
MovementHelper.switchToBestToolFor(ctx, bcc.get(pos));
if (ctx.player().isCrouching()) {
@@ -1037,8 +1036,10 @@ private static boolean sameBlockstate(BlockState first, BlockState second) {
if (!ignoreDirection && ignoredProps.isEmpty()) {
return first.equals(second); // early return if no properties are being ignored
}
- for (Property> prop : first.getProperties()) {
- if (first.getValue(prop) != second.getValue(prop)
+ Map, Comparable>> map1 = first.getValues().collect(Collectors.toMap(Property.Value::property, v -> (Comparable>) v.value()));
+ Map, Comparable>> map2 = second.getValues().collect(Collectors.toMap(Property.Value::property, v -> (Comparable>) v.value()));
+ for (Property> prop : map1.keySet()) {
+ if (map1.get(prop) != map2.get(prop)
&& !(ignoreDirection && ORIENTATION_PROPS.contains(prop))
&& !ignoredProps.contains(prop.getName())) {
return false;
diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java
index bb32fb0456..296fb5028a 100644
--- a/src/main/java/baritone/process/CustomGoalProcess.java
+++ b/src/main/java/baritone/process/CustomGoalProcess.java
@@ -23,7 +23,6 @@
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.utils.BaritoneProcessHelper;
-import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.network.chat.Component;
@@ -60,11 +59,7 @@ public void setGoal(Goal goal) {
this.goal = goal;
this.mostRecentGoal = goal;
if (baritone.getElytraProcess().isActive()) {
- try {
- baritone.getElytraProcess().pathTo(goal);
- } catch (IllegalArgumentException e) {
- logDirect("Failed to update elytra goal because: " + e.getMessage(), ChatFormatting.RED);
- }
+ baritone.getElytraProcess().pathTo(goal);
}
if (this.state == State.NONE) {
this.state = State.GOAL_SET;
diff --git a/src/main/java/baritone/process/ElytraProcess.java b/src/main/java/baritone/process/ElytraProcess.java
index b3420a0d56..e06cb03379 100644
--- a/src/main/java/baritone/process/ElytraProcess.java
+++ b/src/main/java/baritone/process/ElytraProcess.java
@@ -38,11 +38,12 @@
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.movements.MovementFall;
-import baritone.process.elytra.*;
+import baritone.process.elytra.ElytraBehavior;
+import baritone.process.elytra.NetherPathfinderContext;
+import baritone.process.elytra.NullElytraProcess;
import baritone.utils.BaritoneProcessHelper;
import baritone.utils.PathingCommandContext;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
-import net.minecraft.ChatFormatting;
import net.minecraft.client.multiplayer.ClientLevel;
import net.minecraft.core.BlockPos;
import net.minecraft.core.NonNullList;
@@ -55,15 +56,9 @@
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
-import net.minecraft.world.level.chunk.ChunkSource;
-import net.minecraft.world.level.chunk.LevelChunk;
-import net.minecraft.world.level.dimension.DimensionType;
-import net.minecraft.world.level.levelgen.Heightmap;
import net.minecraft.world.phys.Vec3;
import java.util.*;
-import java.util.concurrent.Semaphore;
-import java.util.concurrent.TimeUnit;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
@@ -74,36 +69,16 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro
private boolean reachedGoal; // this basically just prevents potential notification spam
private Goal goal;
private ElytraBehavior behavior;
- private NetherPathfinderContext npfContext;
private boolean predictingTerrain;
- private boolean allowTight;
- private boolean allowAboveBuildLimit;
- private boolean allowAboveRoof;
- private final Semaphore npfSema = new Semaphore(1);
-
- private static final int SHORT_LANDING_COLUMN_HEIGHT = 15;
- private static final int LONG_LANDING_COLUMN_HEIGHT = 39;
- private static final long LANDING_SEARCH_BUDGET_NANOS = TimeUnit.MILLISECONDS.toNanos(25); // half a tick
- private int landingColumnHeight = SHORT_LANDING_COLUMN_HEIGHT;
- private Set badLandingSpots = new HashSet<>();
- private LandingSearchState landingSearchState;
@Override
public void onLostControl() {
- onLostControl(true);
- }
-
- public void onLostControl(boolean destroyNpf) {
this.state = State.START_FLYING; // TODO: null state?
this.goingToLandingSpot = false;
this.landingSpot = null;
- this.landingSearchState = null;
this.reachedGoal = false;
this.goal = null;
destroyBehaviorAsync();
- if (destroyNpf) {
- destroyNpfContextAsync();
- }
}
private ElytraProcess(Baritone baritone) {
@@ -136,35 +111,15 @@ public void resetState() {
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
- try {
- final long seedSetting = Baritone.settings().elytraNetherSeed.value;
- if (seedSetting != this.behavior.npfContext.getSeed()) {
- logDirect("Nether seed changed, recalculating path");
- this.resetState();
- }
- if (predictingTerrain != Baritone.settings().elytraPredictTerrain.value && ctx.player().level().dimension() == Level.NETHER) {
- logDirect("elytraPredictTerrain setting changed, recalculating path from scratch");
- predictingTerrain = Baritone.settings().elytraPredictTerrain.value;
- this.resetState();
- }
- if (allowTight != Baritone.settings().elytraAllowTightSpaces.value) {
- logDirect("elytraAllowTightSpaces setting changed, recalculating path from scratch");
- allowTight = Baritone.settings().elytraAllowTightSpaces.value;
- this.resetState();
- }
- if (allowAboveBuildLimit != Baritone.settings().elytraAllowAboveBuildLimit.value) {
- logDirect("elytraAllowAboveBuildLimit setting changed, recalculating path from scratch");
- allowAboveBuildLimit = Baritone.settings().elytraAllowAboveBuildLimit.value;
- this.resetState();
- }
- if (allowAboveRoof != Baritone.settings().elytraAllowAboveRoof.value && ctx.player().level().dimension() == Level.NETHER) {
- logDirect("elytraAllowAboveRoof setting changed, recalculating path from scratch");
- allowAboveRoof = Baritone.settings().elytraAllowAboveRoof.value;
- this.resetState();
- }
- } catch (IllegalArgumentException e) {
- logDirect(e.getMessage(), ChatFormatting.RED);
- return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
+ final long seedSetting = Baritone.settings().elytraNetherSeed.value;
+ if (seedSetting != this.behavior.context.getSeed()) {
+ logDirect("Nether seed changed, recalculating path");
+ this.resetState();
+ }
+ if (predictingTerrain != Baritone.settings().elytraPredictTerrain.value) {
+ logDirect("elytraPredictTerrain setting changed, recalculating path");
+ predictingTerrain = Baritone.settings().elytraPredictTerrain.value;
+ this.resetState();
}
this.behavior.onTick();
@@ -186,23 +141,18 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
}
if (ctx.player().isFallFlying() && this.state != State.LANDING && (this.behavior.pathManager.isComplete() || safetyLanding)) {
final BetterBlockPos last = this.behavior.pathManager.path.getLast();
- if (last != null && (ctx.player().position().distanceToSqr(last.getCenter()) < (48 * 48) || safetyLanding) && (!goingToLandingSpot || (safetyLanding && this.landingSpot == null))) {
- if (this.landingSearchState == null) {
- logDirect("Path complete, searching for safe landing spot...");
- }
+ if (last != null && (last.distToCenterSqr(ctx.player().position()) < (48 * 48) || safetyLanding) && (!goingToLandingSpot || (safetyLanding && this.landingSpot == null))) {
+ logDirect("Path complete, picking a nearby safe landing spot...");
BetterBlockPos landingSpot = findSafeLandingSpot(ctx.playerFeet());
// if this fails we will just keep orbiting the last node until we run out of rockets or the user intervenes
if (landingSpot != null) {
- logDirect("Found potential landing spot.");
this.pathTo0(landingSpot, true);
this.landingSpot = landingSpot;
- this.goingToLandingSpot = true;
- } else {
- this.goingToLandingSpot = false;
}
+ this.goingToLandingSpot = true;
}
- if (last != null && ctx.player().position().distanceToSqr(last.getCenter()) < 1) {
+ if (last != null && last.distToCenterSqr(ctx.player().position()) < 1) {
if (Baritone.settings().notificationOnPathComplete.value && !reachedGoal) {
logNotification("Pathing complete", false);
}
@@ -217,7 +167,7 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
reachedGoal = true;
// we are goingToLandingSpot and we are in the last node of the path
- if (this.goingToLandingSpot && landingSpot != null) {
+ if (this.goingToLandingSpot) {
this.state = State.LANDING;
logDirect("Above the landing spot, landing...");
}
@@ -232,7 +182,7 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
Rotation rotation = RotationUtils.calcRotationFromVec3d(from, to, ctx.playerRotations());
baritone.getLookBehavior().updateTarget(new Rotation(rotation.getYaw(), 0), false); // this will be overwritten, probably, by behavior tick
- if (ctx.player().position().y < endPos.y - this.landingColumnHeight) {
+ if (ctx.player().position().y < endPos.y - LANDING_COLUMN_HEIGHT) {
logDirect("bad landing spot, trying again...");
landingSpotIsBad(endPos);
}
@@ -243,13 +193,7 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
behavior.landingMode = this.state == State.LANDING;
this.goal = null;
baritone.getInputOverrideHandler().clearAllKeys();
- if (this.behavior.npfContext.tryAcquireReadLock()) {
- try {
- behavior.tick();
- } finally {
- this.behavior.npfContext.releaseReadLock();
- }
- }
+ behavior.tick();
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} else if (this.state == State.LANDING) {
if (ctx.playerMotion().multiply(1, 0, 1).length() > 0.001) {
@@ -345,7 +289,6 @@ public void landingSpotIsBad(BetterBlockPos endPos) {
badLandingSpots.add(endPos);
goingToLandingSpot = false;
this.landingSpot = null;
- this.landingSearchState = null;
this.state = State.FLYING;
}
@@ -353,9 +296,7 @@ private void destroyBehaviorAsync() {
ElytraBehavior behavior = this.behavior;
if (behavior != null) {
this.behavior = null;
- Baritone.getExecutor().execute(() -> {
- behavior.destroy();
- });
+ Baritone.getExecutor().execute(behavior::destroy);
}
}
@@ -371,27 +312,8 @@ public String displayName0() {
@Override
public void repackChunks() {
- if (this.npfContext == null) return;
-
- ChunkSource chunkProvider = ctx.world().getChunkSource();
- BetterBlockPos playerPos = ctx.playerFeet();
-
- int playerChunkX = playerPos.getX() >> 4;
- int playerChunkZ = playerPos.getZ() >> 4;
-
- int minX = playerChunkX - 40;
- int minZ = playerChunkZ - 40;
- int maxX = playerChunkX + 40;
- int maxZ = playerChunkZ + 40;
-
- for (int x = minX; x <= maxX; x++) {
- for (int z = minZ; z <= maxZ; z++) {
- LevelChunk chunk = chunkProvider.getChunk(x, z, false);
-
- if (chunk != null && !chunk.isEmpty()) {
- npfContext.queueForPacking(chunk);
- }
- }
+ if (this.behavior != null) {
+ this.behavior.repackChunks();
}
}
@@ -400,37 +322,20 @@ public BlockPos currentDestination() {
return this.behavior != null ? this.behavior.destination : null;
}
- @Override
- public List getPath() {
- return this.behavior != null ? behavior.pathManager.getPath() : Collections.emptyList();
- }
-
@Override
public void pathTo(BlockPos destination) {
- if (!isSupportedPos(destination)) {
- throw new IllegalArgumentException("The goal must be within bounds to use elytra flight.");
- }
-
- if (ctx.player() != null && !isSupportedPos(ctx.playerFeet())) {
- throw new IllegalArgumentException("The player must be within bounds to use elytra flight.");
- }
-
this.pathTo0(destination, false);
}
private void pathTo0(BlockPos destination, boolean appendDestination) {
- if (ctx.player() == null) {
+ if (ctx.player() == null || ctx.player().level().dimension() != Level.NETHER) {
return;
}
- this.onLostControl(false);
- this.predictingTerrain = ctx.player().level().dimension() == Level.NETHER && Baritone.settings().elytraPredictTerrain.value;
- this.allowTight = Baritone.settings().elytraAllowTightSpaces.value;
- this.allowAboveBuildLimit = Baritone.settings().elytraAllowAboveBuildLimit.value;
- this.allowAboveRoof = Baritone.settings().elytraAllowAboveRoof.value;
- this.behavior = new ElytraBehavior(this.baritone, this, getNpfContext(), destination, appendDestination);
-
+ this.onLostControl();
+ this.predictingTerrain = Baritone.settings().elytraPredictTerrain.value;
+ this.behavior = new ElytraBehavior(this.baritone, this, destination, appendDestination);
if (ctx.world() != null) {
- this.repackChunks();
+ this.behavior.repackChunks();
}
this.behavior.pathTo();
}
@@ -443,7 +348,6 @@ public void pathTo(Goal iGoal) {
if (iGoal instanceof GoalXZ) {
GoalXZ goal = (GoalXZ) iGoal;
x = goal.getX();
- // ElytraBehavior will automatically change the destination height depending on if we're above or below the roof
y = 64;
z = goal.getZ();
} else if (iGoal instanceof GoalBlock) {
@@ -454,25 +358,10 @@ public void pathTo(Goal iGoal) {
} else {
throw new IllegalArgumentException("The goal must be a GoalXZ or GoalBlock");
}
-
- this.pathTo((new BlockPos(x, y, z)));
- }
-
- private boolean isSupportedPos(BlockPos pos) {
- final boolean isNether = ctx.world().dimension() == Level.NETHER;
- final int minY = ctx.world().dimensionType().minY();
- final int maxY = (isNether && !Baritone.settings().elytraAllowAboveRoof.value) ? 127 : Math.min(minY + 384, ctx.world().dimensionType().height() + minY);
-
- final boolean aboveRoof = Baritone.settings().elytraAllowAboveRoof.value;
- final boolean aboveBuild = Baritone.settings().elytraAllowAboveBuildLimit.value;
-
- final boolean enforceMaxY = isNether ? !(aboveRoof && aboveBuild) : !aboveBuild;
-
- if (pos.getY() < minY) {
- return false;
+ if (y <= 0 || y >= 128) {
+ throw new IllegalArgumentException("The y of the goal is not between 0 and 128");
}
-
- return !enforceMaxY || pos.getY() < maxY;
+ this.pathTo(new BlockPos(x, y, z));
}
private boolean shouldLandForSafety() {
@@ -582,20 +471,12 @@ public double placeBucketCost() {
}
}
- private static boolean isInBounds(Level dim, BlockPos pos) {
- DimensionType dimType = dim.dimensionType();
- int minY = dimType.minY();
- int maxY = (dim.dimension() == Level.NETHER && !Baritone.settings().elytraAllowAboveRoof.value) ? 127 : Math.min(minY + 384, dimType.height() + minY);
- return pos.getY() >= minY && pos.getY() < maxY;
+ private static boolean isInBounds(BlockPos pos) {
+ return pos.getY() >= 0 && pos.getY() < 128;
}
private boolean isSafeBlock(Block block) {
- return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || block == Blocks.SOUL_SAND || block == Blocks.SOUL_SOIL || (block == Blocks.NETHER_BRICKS && Baritone.settings().elytraAllowLandOnNetherFortress.value)
- || block == Blocks.STONE || block == Blocks.DEEPSLATE || block == Blocks.GRASS_BLOCK || block == Blocks.SAND || block == Blocks.RED_SAND || block == Blocks.TERRACOTTA
- || block == Blocks.SNOW || block == Blocks.ICE || block == Blocks.MYCELIUM || block == Blocks.PODZOL
- || block == Blocks.DARK_OAK_LEAVES || block == Blocks.JUNGLE_LEAVES
- || block == Blocks.END_STONE || block == Blocks.BEDROCK
- || block == Blocks.OBSIDIAN || block == Blocks.COBBLESTONE;
+ return block == Blocks.NETHERRACK || block == Blocks.GRAVEL || (block == Blocks.NETHER_BRICKS && Baritone.settings().elytraAllowLandOnNetherFortress.value);
}
private boolean isSafeBlock(BlockPos pos) {
@@ -645,7 +526,7 @@ private boolean hasAirBubble(BlockPos pos) {
private BetterBlockPos checkLandingSpot(BlockPos pos, LongOpenHashSet checkedSpots) {
BlockPos.MutableBlockPos mut = new BlockPos.MutableBlockPos(pos.getX(), pos.getY(), pos.getZ());
- while (mut.getY() >= ctx.world().dimensionType().minY()) {
+ while (mut.getY() >= 0) {
if (checkedSpots.contains(mut.asLong())) {
return null;
}
@@ -665,131 +546,30 @@ private BetterBlockPos checkLandingSpot(BlockPos pos, LongOpenHashSet checkedSpo
return null; // void
}
- private BetterBlockPos findSafeLandingSpot(BetterBlockPos start) {
- final boolean useHeightmap = ctx.player().getY() > ctx.world().getHeight(Heightmap.Types.MOTION_BLOCKING, start.getX(), start.getZ());
- if (this.landingSearchState == null || !this.landingSearchState.isCompatible(start, useHeightmap)) {
- this.landingSearchState = new LandingSearchState(start, this.behavior.destination, useHeightmap);
- } else {
- this.landingSearchState.updateStartPosition(start);
- }
-
- BetterBlockPos landingSpot = this.landingSearchState.advance();
- if (landingSpot != null || this.landingSearchState.exhausted) {
- this.landingSearchState = null;
- }
- return landingSpot;
- }
-
- private boolean isChunkLoaded(BetterBlockPos pos) {
- return ctx.world().getChunkSource().hasChunk(pos.x >> 4, pos.z >> 4);
- }
-
- private final class LandingSearchState {
- private final BetterBlockPos origin;
- private final boolean useHeightmap;
- private final Queue queue;
- private final Set visited = new HashSet<>();
- private final LongOpenHashSet checkedPositions = new LongOpenHashSet();
- private boolean exhausted;
-
- private LandingSearchState(BetterBlockPos origin, BetterBlockPos dest, boolean useHeightmap) {
- this.origin = origin;
- this.useHeightmap = useHeightmap;
-
- final BetterBlockPos target = isChunkLoaded(dest) ? dest : origin;
- this.queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x - target.x) * (pos.x - target.x) + (pos.z - target.z) * (pos.z - target.z)).thenComparingInt(pos -> -pos.y));
- this.queue.add(target);
- }
-
- private boolean isCompatible(BetterBlockPos start, boolean useHeightmap) {
- // Restart if we've moved more than a chunk so the priority adjusts and newly loaded chunks get revisited
- return this.useHeightmap == useHeightmap && this.origin.distanceSq(start) <= (16 * 16);
- }
-
- private void updateStartPosition(BetterBlockPos start) {
- if (this.visited.add(start)) {
- this.queue.add(start);
- }
- }
-
- private BetterBlockPos advance() {
- final long deadline = System.nanoTime() + LANDING_SEARCH_BUDGET_NANOS;
- while (!this.queue.isEmpty()) {
- if (System.nanoTime() >= deadline) {
- return null;
- }
- BetterBlockPos qPos = this.queue.poll();
- if (!isChunkLoaded(qPos)) {
- continue;
- }
- BetterBlockPos landing = this.useHeightmap ? this.advanceHeightmap(qPos) : this.advanceUnderground(qPos);
- if (landing != null) {
- return landing;
- }
- }
- this.exhausted = true;
- return null;
- }
+ private static final int LANDING_COLUMN_HEIGHT = 15;
+ private Set badLandingSpots = new HashSet<>();
- private BetterBlockPos advanceUnderground(BetterBlockPos pos) {
- if (isInBounds(ctx.world(), pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) {
- BetterBlockPos actualLandingSpot = checkLandingSpot(pos, this.checkedPositions);
- if (actualLandingSpot != null) {
- landingColumnHeight = SHORT_LANDING_COLUMN_HEIGHT;
- if (isColumnAir(actualLandingSpot, landingColumnHeight) && hasAirBubble(actualLandingSpot.above(landingColumnHeight)) && !badLandingSpots.contains(actualLandingSpot.above(landingColumnHeight))) {
- return actualLandingSpot.above(landingColumnHeight);
- }
- }
- if (this.visited.add(pos.north())) this.queue.add(pos.north());
- if (this.visited.add(pos.east())) this.queue.add(pos.east());
- if (this.visited.add(pos.south())) this.queue.add(pos.south());
- if (this.visited.add(pos.west())) this.queue.add(pos.west());
- if (this.visited.add(pos.above())) this.queue.add(pos.above());
- if (this.visited.add(pos.below())) this.queue.add(pos.below());
- }
- return null;
- }
-
- private BetterBlockPos advanceHeightmap(BetterBlockPos qPos) {
- int height = ctx.world().getHeight(Heightmap.Types.MOTION_BLOCKING, qPos.getX(), qPos.getZ());
- BetterBlockPos pos = new BetterBlockPos(qPos.getX(), height + 1, qPos.getZ());
- if (isInBounds(ctx.world(), pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) {
- BetterBlockPos actualLandingSpot = checkLandingSpot(pos, this.checkedPositions);
- if (actualLandingSpot != null) {
- landingColumnHeight = ctx.playerFeet().y - actualLandingSpot.y < LONG_LANDING_COLUMN_HEIGHT ? SHORT_LANDING_COLUMN_HEIGHT : LONG_LANDING_COLUMN_HEIGHT;
- if (hasAirBubble(actualLandingSpot.above(landingColumnHeight)) && !badLandingSpots.contains(actualLandingSpot.above(landingColumnHeight))) {
- return actualLandingSpot.above(landingColumnHeight);
- }
+ private BetterBlockPos findSafeLandingSpot(BetterBlockPos start) {
+ Queue queue = new PriorityQueue<>(Comparator.comparingInt(pos -> (pos.x - start.x) * (pos.x - start.x) + (pos.z - start.z) * (pos.z - start.z)).thenComparingInt(pos -> -pos.y));
+ Set visited = new HashSet<>();
+ LongOpenHashSet checkedPositions = new LongOpenHashSet();
+ queue.add(start);
+
+ while (!queue.isEmpty()) {
+ BetterBlockPos pos = queue.poll();
+ if (ctx.world().isLoaded(pos) && isInBounds(pos) && ctx.world().getBlockState(pos).getBlock() == Blocks.AIR) {
+ BetterBlockPos actualLandingSpot = checkLandingSpot(pos, checkedPositions);
+ if (actualLandingSpot != null && isColumnAir(actualLandingSpot, LANDING_COLUMN_HEIGHT) && hasAirBubble(actualLandingSpot.above(LANDING_COLUMN_HEIGHT)) && !badLandingSpots.contains(actualLandingSpot.above(LANDING_COLUMN_HEIGHT))) {
+ return actualLandingSpot.above(LANDING_COLUMN_HEIGHT);
}
- if (this.visited.add(pos.north())) this.queue.add(pos.north());
- if (this.visited.add(pos.east())) this.queue.add(pos.east());
- if (this.visited.add(pos.south())) this.queue.add(pos.south());
- if (this.visited.add(pos.west())) this.queue.add(pos.west());
+ if (visited.add(pos.north())) queue.add(pos.north());
+ if (visited.add(pos.east())) queue.add(pos.east());
+ if (visited.add(pos.south())) queue.add(pos.south());
+ if (visited.add(pos.west())) queue.add(pos.west());
+ if (visited.add(pos.above())) queue.add(pos.above());
+ if (visited.add(pos.below())) queue.add(pos.below());
}
- return null;
- }
- }
-
- private NetherPathfinderContext getNpfContext() {
- if(this.npfContext == null) {
- npfSema.acquireUninterruptibly();
- this.npfContext = new NetherPathfinderContext(
- Baritone.settings().elytraNetherSeed.value,
- Baritone.settings().elytraUseCache.value ? baritone.getWorldProvider().getCurrentWorld().directory.resolve("cache") : null,
- ctx.world()
- );
- }
- return this.npfContext;
- }
-
- private void destroyNpfContextAsync() {
- NetherPathfinderContext npf = this.npfContext;
- if (npf != null) {
- this.npfContext = null;
- Baritone.getExecutor().execute(() -> {
- npf.destroy();
- npfSema.release();
- });
}
+ return null;
}
}
diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java
index fbb7f66a2c..c854c656d9 100644
--- a/src/main/java/baritone/process/FarmProcess.java
+++ b/src/main/java/baritone/process/FarmProcess.java
@@ -26,7 +26,6 @@
import baritone.api.process.IFarmProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
-import baritone.api.selection.ISelection;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
@@ -221,12 +220,6 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (locations == null) {
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
- if (Baritone.settings().farmUsingSelection.value) {
- ISelection selection = baritone.getSelectionManager().getLastSelection();
- if (selection != null) {
- locations.removeIf(pos -> !selection.aabb().contains(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5));
- }
- }
List toBreak = new ArrayList<>();
List openFarmland = new ArrayList<>();
List bonemealable = new ArrayList<>();
diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java
index 31aa16afa0..c74b956b69 100644
--- a/src/main/java/baritone/process/MineProcess.java
+++ b/src/main/java/baritone/process/MineProcess.java
@@ -126,7 +126,10 @@ public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (!MovementHelper.avoidBreaking(baritone.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) {
Optional rot = RotationUtils.reachable(ctx, pos);
if (rot.isPresent() && isSafeToCancel) {
- baritone.getLookBehavior().updateTarget(rot.get(), true);
+ baritone.getLookBehavior().updateTarget(
+ rot.get(),
+ true,
+ ctx.playerHead().distanceTo(VecUtils.getBlockPosCenter(pos)));
MovementHelper.switchToBestToolFor(ctx, ctx.world().getBlockState(pos));
if (ctx.isLookingAt(pos) || ctx.playerRotations().isReallyCloseTo(rot.get())) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
diff --git a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java
index 52fdfdd66d..7db0e2d648 100644
--- a/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java
+++ b/src/main/java/baritone/process/elytra/BlockStateOctreeInterface.java
@@ -19,7 +19,6 @@
import dev.babbaj.pathfinder.NetherPathfinder;
import dev.babbaj.pathfinder.Octree;
-import net.minecraft.world.level.dimension.DimensionType;
/**
* @author Brady
@@ -28,7 +27,6 @@ public final class BlockStateOctreeInterface {
private final NetherPathfinderContext context;
private final long contextPtr;
- private final int minY;
transient long chunkPtr;
// Guarantee that the first lookup will fetch the context by setting MAX_VALUE
@@ -38,12 +36,10 @@ public final class BlockStateOctreeInterface {
public BlockStateOctreeInterface(final NetherPathfinderContext context) {
this.context = context;
this.contextPtr = context.context;
- this.minY = context.minY;
}
public boolean get0(final int x, final int y, final int z) {
- final int adjustedY = y - this.minY;
- if (adjustedY < 0 || adjustedY > 383) {
+ if ((y | (127 - y)) < 0) {
return false;
}
final int chunkX = x >> 4;
@@ -51,8 +47,8 @@ public boolean get0(final int x, final int y, final int z) {
if (this.chunkPtr == 0 | ((chunkX ^ this.prevChunkX) | (chunkZ ^ this.prevChunkZ)) != 0) {
this.prevChunkX = chunkX;
this.prevChunkZ = chunkZ;
- this.chunkPtr = NetherPathfinder.getChunkOrDefault(this.contextPtr, chunkX, chunkZ, true);
+ this.chunkPtr = NetherPathfinder.getOrCreateChunk(this.contextPtr, chunkX, chunkZ);
}
- return Octree.getBlock(this.chunkPtr, x & 0xF, adjustedY, z & 0xF);
+ return Octree.getBlock(this.chunkPtr, x & 0xF, y & 0x7F, z & 0xF);
}
}
diff --git a/src/main/java/baritone/process/elytra/BuildLimitPathFinder.java b/src/main/java/baritone/process/elytra/BuildLimitPathFinder.java
deleted file mode 100644
index e074f0b809..0000000000
--- a/src/main/java/baritone/process/elytra/BuildLimitPathFinder.java
+++ /dev/null
@@ -1,299 +0,0 @@
-/*
- * This file is part of Baritone.
- *
- * Baritone is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Baritone is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Baritone. If not, see .
- */
-
-package baritone.process.elytra;
-
-import baritone.Baritone;
-import baritone.api.utils.BetterBlockPos;
-import baritone.api.utils.IPlayerContext;
-import net.minecraft.core.BlockPos;
-import net.minecraft.core.Vec3i;
-import net.minecraft.util.Tuple;
-import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.levelgen.Heightmap;
-
-import java.util.LinkedList;
-import java.util.List;
-import java.util.concurrent.CompletableFuture;
-import java.util.concurrent.ExecutionException;
-
-public class BuildLimitPathFinder implements IElytraPathFinder {
- final int flightLevel;
- final IPlayerContext playerCtx;
- final NetherPathfinderContext netherCtx;
-
- public BuildLimitPathFinder(IPlayerContext ctx, NetherPathfinderContext netherCtx) {
- if (ctx == null) {
- throw new IllegalArgumentException("IPlayerContext cannot be null");
- }
- this.playerCtx = ctx;
-
- if (netherCtx == null) {
- throw new IllegalArgumentException("NetherPathfinderContext cannot be null");
- }
-
- this.flightLevel = ctx.world().getMaxY() + 16;
- this.netherCtx = netherCtx;
-
- if(netherCtx.getMaxHeight() + ctx.world().getMinY() < ctx.world().getMaxY()) {
- throw new IllegalStateException("Nether pathfinder max height is below world build limit, cannot proceed");
- }
- }
-
- /**
- * Generates a direct path from the start to the destination at a fixed y-level above build limit
- * @param start
- * @param destination
- * @param bufferDistance Distance from the destination to halt the direct path
- * @param maxPathSize Maximum number of nodes in the returned path
- * @return A tuple containing the path as a list of BetterBlockPos and a boolean indicating if the path is complete
- */
- public Tuple
, Boolean> generateDirectPath(BetterBlockPos start, BetterBlockPos destination, int bufferDistance, int maxPathSize) {
- final LinkedList path = new LinkedList<>();
- final int stepDistance = 32;
-
- final BetterBlockPos startFixed = start.y == flightLevel ? start : new BetterBlockPos(start.getX(), flightLevel, start.getZ());
- final BetterBlockPos destinationFixed = destination.y == flightLevel ? destination : new BetterBlockPos(destination.getX(), flightLevel, destination.getZ());
-
- BetterBlockPos cur = startFixed;
- path.add(cur);
-
- while (path.size() < maxPathSize) {
- double deltaX = destinationFixed.getX() - cur.getX();
- double deltaZ = destinationFixed.getZ() - cur.getZ();
- double remainingDistance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
- double remainingDistanceSq = deltaX * deltaX + deltaZ * deltaZ;
-
- if(remainingDistanceSq <= bufferDistance * bufferDistance) {
- // We are within the buffer distance, so we can stop here
- return new Tuple<>(path, true);
- } else if (remainingDistance <= stepDistance) {
- path.add(destinationFixed);
- return new Tuple<>(path, true);
- }
-
- double stepRatio = stepDistance / remainingDistance;
- int nextX = (int) Math.round(cur.getX() + deltaX * stepRatio);
- int nextZ = (int) Math.round(cur.getZ() + deltaZ * stepRatio);
-
- cur = new BetterBlockPos(nextX, flightLevel, nextZ);
- path.add(cur);
- }
-
- return new Tuple<>(path, false);
- }
-
- /**
- * Attempts to find an open spot in the sky to transition up above the build limit so a simple direct path can be followed
- * @param start
- * @param destination
- * @return A tuple containing the path that transitions above build limit and a boolean indicating if a transition was found
- */
- public Tuple,Boolean> generateTransitionUp(BetterBlockPos start, BetterBlockPos destination) {
- final double deltaX = destination.getX() - start.getX();
- final double deltaZ = destination.getZ() - start.getZ();
- final double distance = Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
-
- final double scale = 8 / distance;
- final double stepX = deltaX * scale;
- final double stepZ = deltaZ * scale;
-
- final int netherMaxHeight = netherCtx.getMaxHeight() + playerCtx.world().getMinY() - 1;
-
- final ChunkPos startChunk = new ChunkPos(start.x >> 4, start.z >> 4);
-
- if(!isSkyClear(startChunk, start.y)) {
- return new Tuple<>(new LinkedList<>(), false);
- }
-
- LinkedList path = new LinkedList<>();
-
- // Start with the middle block so the transition doesn't leave the only chunk we can confirm is clear
- final BlockPos middlePos = startChunk.getMiddleBlockPosition(netherMaxHeight+4);
-
- for(int i = 2; i <= 2; i++) {
- BetterBlockPos next = new BetterBlockPos(
- (int) (middlePos.getX() + (stepX * i)),
- netherMaxHeight + (i * 8),
- (int) (middlePos.getZ() + (stepZ * i))
- );
- path.add(next);
- }
-
- return new Tuple<>(path, true);
- }
-
- /**
- * Attempts to find an open spot in the sky to transition down to a flight level the nether pathfinder can navigiate at.
- * @param start
- * @return A tuple containing the path (single point) and a boolean indicating if a transition point was found
- */
- public Tuple,Boolean> generateTransitionDown(BetterBlockPos start) {
- final int netherMaxHeight = netherCtx.getMaxHeight() + playerCtx.world().getMinY() - 1;
- final ChunkPos startChunk = new ChunkPos(start.x >> 4, start.z >> 4);
-
- LinkedList path = new LinkedList<>();
-
- if(!isSkyClear(new ChunkPos(start.x >> 4, start.z >> 4), netherMaxHeight-16)) {
- return new Tuple<>(new LinkedList<>(), false);
- }
-
- path.add(new BetterBlockPos(startChunk.getMiddleBlockPosition(netherMaxHeight-8)));
- return new Tuple<>(path, true);
- }
-
- public boolean isSkyClear(ChunkPos pos, int y) {
- if(!playerCtx.world().getChunkSource().hasChunk(pos.x(), pos.z())) {
- return false;
- }
-
- for (int x = 0; x < 16; x++) {
- for (int z = 0; z < 16; z++) {
- BlockPos blockPos = pos.getBlockAt(x, y, z);
- int height = playerCtx.world().getHeight(Heightmap.Types.MOTION_BLOCKING, blockPos.getX(), blockPos.getZ());
- if (height > y) {
- return false;
- }
- }
- }
- return true;
- }
-
-
- public CompletableFuture pathFindAsync(BlockPos src, BlockPos dst) {
- final int netherMaxHeight = netherCtx.getMaxHeight() + playerCtx.world().getMinY() - 1;
- final int maxDirectPathSize = 500;
-
- // There can be some navigation issues around failed transitions if the threshold distance isn't large enough
- final double maxDistance = Baritone.settings().elytraLongDistanceThreshold.value >= 32 ? (double) Baritone.settings().elytraLongDistanceThreshold.value : Double.POSITIVE_INFINITY;
-
- final double distanceXZ = src.distSqr(new Vec3i(dst.getX(), src.getY(), dst.getZ()));
- final boolean isLongDistance = distanceXZ > maxDistance * maxDistance;
- final boolean srcAboveSupportedHeight = src.getY() >= netherMaxHeight;
- final boolean dstAboveSupportedHeight = dst.getY() >= netherMaxHeight;
-
- if(srcAboveSupportedHeight && dstAboveSupportedHeight) {
- var path = generateDirectPath(new BetterBlockPos(src), new BetterBlockPos(dst), 0, maxDirectPathSize);
- return CompletableFuture.completedFuture(new UnpackedSegment(path.getA().stream(), path.getB()));
- }
-
- if(isLongDistance) {
- if(srcAboveSupportedHeight) {
- var directPath = generateDirectPath(new BetterBlockPos(src), new BetterBlockPos(dst), (int)maxDistance, maxDirectPathSize);
- return CompletableFuture.completedFuture(
- new UnpackedSegment(
- directPath.getA().stream(),
- dstAboveSupportedHeight ? directPath.getB() : false
- )
- );
- } else {
- var transition = generateTransitionUp(new BetterBlockPos(src), new BetterBlockPos(dst));
- var path = transition.getA();
- var success = transition.getB();
-
- if(success) {
- var directPath = generateDirectPath(path.get(path.size()-1), new BetterBlockPos(dst), (int)maxDistance, maxDirectPathSize);
- path.addAll(directPath.getA());
-
- return CompletableFuture.completedFuture(
- new UnpackedSegment(
- path.stream(),
- dstAboveSupportedHeight? directPath.getB() : false
- )
- );
- }
- }
-
- // Failed to find a transition point so navigate a bit in the right direction and try
- final double deltaX = dst.getX() - src.getX();
- final double deltaZ = dst.getZ() - src.getZ();
- final double scale = (maxDistance/2) / Math.sqrt(deltaX * deltaX + deltaZ * deltaZ);
- final double stepX = deltaX * scale;
- final double stepZ = deltaZ * scale;
- final BlockPos midDst = new BlockPos((int)(src.getX() + stepX), netherMaxHeight, (int)(src.getZ() + stepZ));
-
- return incompletePathfind(src, midDst);
- } else {
- if(srcAboveSupportedHeight) {
- var transition = generateTransitionDown(new BetterBlockPos(src));
- List path = transition.getA();
- boolean success = transition.getB();
-
- if(!success) {
- BetterBlockPos newDest = distanceXZ > 32 ? new BetterBlockPos(dst) : new BetterBlockPos(dst.getX(), playerCtx.world().getMaxY(), dst.getZ());
- var directPath = generateDirectPath(new BetterBlockPos(src), newDest, 0, 2);
- return CompletableFuture.completedFuture(new UnpackedSegment(directPath.getA().stream(), directPath.getB()));
- }
-
- return CompletableFuture.supplyAsync(() -> {
- var np = blockingPathFind(path.get(path.size() - 1), dst);
- path.addAll(np.collect());
- return new UnpackedSegment(path.stream(), np.isFinished());
- });
- }
-
-
- if(dstAboveSupportedHeight) {
- var transition = generateTransitionUp(new BetterBlockPos(src), new BetterBlockPos(dst));
- var path = transition.getA();
- var success = transition.getB();
-
- if(success) {
- var directPath = generateDirectPath(path.get(path.size() - 1), new BetterBlockPos(dst), 0, maxDirectPathSize);
- path.addAll(directPath.getA());
- return CompletableFuture.completedFuture(new UnpackedSegment(path.stream(), directPath.getB()));
- }
-
- return netherCtx.pathFindAsync(src, new BetterBlockPos(dst.getX(), netherMaxHeight, dst.getZ()));
- }
-
- return netherCtx.pathFindAsync(src, dst);
- }
- }
-
- /**
- * A wrapper for a nether pathfinder call but the returned path will always indicate it is incomplete
- * @param src
- * @param dst
- * @return a CompletableFuture containing an UnpackedSegment with isFinished always false
- */
- private CompletableFuture incompletePathfind(BlockPos src, BlockPos dst) {
- return CompletableFuture.supplyAsync(() -> {
- UnpackedSegment packed = blockingPathFind(src, dst);
- return new UnpackedSegment(
- packed.collect().stream(),
- false
- );
- });
- }
-
- private UnpackedSegment blockingPathFind(BlockPos src, BlockPos dst) {
- try {
- return netherCtx.pathFindAsync(src, dst).get();
- } catch (InterruptedException e) {
- Thread.currentThread().interrupt();
- throw new RuntimeException(e);
- } catch (ExecutionException e) {
- final Throwable cause = e.getCause();
- if (cause instanceof PathCalculationException) {
- throw (PathCalculationException) cause;
- }
- throw new RuntimeException(e);
- }
- }
-
-}
diff --git a/src/main/java/baritone/process/elytra/ElytraBehavior.java b/src/main/java/baritone/process/elytra/ElytraBehavior.java
index ca08fc15c4..ad4e7d6738 100644
--- a/src/main/java/baritone/process/elytra/ElytraBehavior.java
+++ b/src/main/java/baritone/process/elytra/ElytraBehavior.java
@@ -48,7 +48,6 @@
import net.minecraft.world.item.component.Fireworks;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ClipContext;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.AirBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkSource;
@@ -79,9 +78,7 @@ public final class ElytraBehavior implements Helper {
private List visiblePath;
// :sunglasses:
- public NetherPathfinderContext npfContext;
- public IElytraPathFinder pathFinder;
-
+ public final NetherPathfinderContext context;
public final PathManager pathManager;
private final ElytraProcess process;
@@ -108,6 +105,7 @@ public final class ElytraBehavior implements Helper {
private final int[] nextTickBoostCounter;
private BlockStateInterface bsi;
+ private final BlockStateOctreeInterface boi;
public final BetterBlockPos destination;
private final boolean appendDestination;
@@ -122,7 +120,7 @@ public final class ElytraBehavior implements Helper {
private int invTickCountdown = 0;
private final Queue invTransactionQueue = new LinkedList<>();
- public ElytraBehavior(Baritone baritone, ElytraProcess process, NetherPathfinderContext npf, BlockPos destination, boolean appendDestination) {
+ public ElytraBehavior(Baritone baritone, ElytraProcess process, BlockPos destination, boolean appendDestination) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
this.clearLines = new CopyOnWriteArrayList<>();
@@ -134,15 +132,8 @@ public ElytraBehavior(Baritone baritone, ElytraProcess process, NetherPathfinder
this.solverExecutor = Executors.newSingleThreadExecutor();
this.nextTickBoostCounter = new int[2];
- this.npfContext = npf;
-
- if(ctx.world().dimension() == Level.NETHER) {
- this.pathFinder = Baritone.settings().elytraAllowAboveRoof.value && Baritone.settings().elytraAllowAboveBuildLimit.value
- ? new BuildLimitPathFinder(ctx, npfContext)
- : npfContext;
- } else {
- this.pathFinder = Baritone.settings().elytraAllowAboveBuildLimit.value ? new BuildLimitPathFinder(ctx, npfContext) : npfContext;
- }
+ this.context = new NetherPathfinderContext(Baritone.settings().elytraNetherSeed.value);
+ this.boi = new BlockStateOctreeInterface(context);
}
public final class PathManager {
@@ -172,18 +163,9 @@ public void tick() {
this.ticksNearUnchanged = 0;
}
- int minY = ctx.world().dimensionType().minY();
- int y = ctx.playerFeet().y;
-
- npfContext.acquireReadLock();
- try {
- // Obstacles are more important than an incomplete path, handle those first.
- this.pathfindAroundObstacles();
- } finally {
- npfContext.releaseReadLock();
- }
+ // Obstacles are more important than an incomplete path, handle those first.
+ this.pathfindAroundObstacles();
this.attemptNextSegment();
-
}
public CompletableFuture pathToDestination() {
@@ -192,7 +174,7 @@ public CompletableFuture pathToDestination() {
public CompletableFuture pathToDestination(final BlockPos from) {
final long start = System.nanoTime();
- return this.path0(from, destinationFixed(), UnaryOperator.identity())
+ return this.path0(from, ElytraBehavior.this.destination, UnaryOperator.identity())
.thenRun(() -> {
final double distance = this.path.get(0).distanceTo(this.path.get(this.path.size() - 1));
if (this.completePath) {
@@ -223,7 +205,7 @@ public CompletableFuture pathRecalcSegment(final OptionalInt upToIncl) {
final List after = upToIncl.isPresent() ? this.path.subList(upToIncl.getAsInt() + 1, this.path.size()) : Collections.emptyList();
final boolean complete = this.completePath;
- return this.path0(ctx.playerFeet(), upToIncl.isPresent() ? fixDestination(this.path.get(upToIncl.getAsInt())) : destinationFixed(), segment -> segment.append(after.stream(), complete || (segment.isFinished() && !upToIncl.isPresent())))
+ return this.path0(ctx.playerFeet(), upToIncl.isPresent() ? this.path.get(upToIncl.getAsInt()) : ElytraBehavior.this.destination, segment -> segment.append(after.stream(), complete || (segment.isFinished() && !upToIncl.isPresent())))
.whenComplete((result, ex) -> {
this.recalculating = false;
if (ex != null) {
@@ -247,10 +229,10 @@ public void pathNextSegment(final int afterIncl) {
final long start = System.nanoTime();
final BetterBlockPos pathStart = this.path.get(afterIncl);
- this.path0(pathStart, destinationFixed(), segment -> segment.prepend(before.stream()))
+ this.path0(pathStart, ElytraBehavior.this.destination, segment -> segment.prepend(before.stream()))
.thenRun(() -> {
final int recompute = this.path.size() - before.size() - 1;
- final double distance = recompute > 0 ? this.path.get(0).distanceTo(this.path.get(recompute)) : 0;
+ final double distance = this.path.get(0).distanceTo(this.path.get(recompute));
if (this.completePath) {
logVerbose(String.format("Computed path (%.1f blocks in %.4f seconds)", distance, (System.nanoTime() - start) / 1e9d));
@@ -264,7 +246,7 @@ public void pathNextSegment(final int afterIncl) {
final Throwable cause = ex.getCause();
if (cause instanceof PathCalculationException) {
logDirect("Failed to compute next segment");
- if (ctx.player().distanceToSqr(pathStart.getCenter()) < 16 * 16) {
+ if (pathStart.distToCenterSqr(ctx.player().position()) < 16 * 16) {
logVerbose("Player is near the segment start, therefore repeating this calculation is pointless. Marking as complete");
completePath = true;
}
@@ -287,13 +269,13 @@ public void clear() {
private void setPath(final UnpackedSegment segment) {
List path = segment.collect();
if (ElytraBehavior.this.appendDestination) {
- BlockPos dest = destinationFixed();
+ BlockPos dest = ElytraBehavior.this.destination;
BlockPos last = !path.isEmpty() ? path.get(path.size() - 1) : null;
if (last != null && ElytraBehavior.this.clearView(Vec3.atLowerCornerOf(dest), Vec3.atLowerCornerOf(last), false)) {
path.add(new BetterBlockPos(dest));
} else {
- logDirect("unable to land at " + dest);
- process.landingSpotIsBad(new BetterBlockPos(dest));
+ logDirect("unable to land at " + ElytraBehavior.this.destination);
+ process.landingSpotIsBad(new BetterBlockPos(ElytraBehavior.this.destination));
}
}
this.path = new NetherPath(path);
@@ -313,12 +295,12 @@ public int getNear() {
// mickey resigned
private CompletableFuture path0(BlockPos src, BlockPos dst, UnaryOperator operator) {
- return ElytraBehavior.this.pathFinder.pathFindAsync(src, dst)
+ return ElytraBehavior.this.context.pathFindAsync(src, dst)
+ .thenApply(UnpackedSegment::from)
.thenApply(operator)
.thenAcceptAsync(this::setPath, ctx.minecraft()::execute);
}
- // required read lock to be held
private void pathfindAroundObstacles() {
if (this.recalculating) {
return;
@@ -326,7 +308,7 @@ private void pathfindAroundObstacles() {
int rangeStartIncl = playerNear;
int rangeEndExcl = playerNear;
- while (rangeEndExcl < path.size() && npfContext.hasChunk(ChunkPos.containing(path.get(rangeEndExcl)))) {
+ while (rangeEndExcl < path.size() && context.hasChunk(ChunkPos.containing(path.get(rangeEndExcl)))) {
rangeEndExcl++;
}
// rangeEndExcl now represents an index either not in the path, or just outside render distance
@@ -358,8 +340,7 @@ private void pathfindAroundObstacles() {
// obstacle. where do we return to pathing?
// if the end of render distance is closer to goal, then that's fine, otherwise we'd be "digging our hole deeper" and making an already bad backtrack worse
OptionalInt rejoinMainPathAt;
- var dest = destinationFixed();
- if (this.path.get(rangeEndExcl - 1).distanceSq(dest) < ctx.playerFeet().distanceSq(dest)) {
+ if (this.path.get(rangeEndExcl - 1).distanceSq(ElytraBehavior.this.destination) < ctx.playerFeet().distanceSq(ElytraBehavior.this.destination)) {
rejoinMainPathAt = OptionalInt.of(rangeEndExcl - 1); // rejoin after current render distance
} else {
rejoinMainPathAt = OptionalInt.empty(); // large backtrack detected. ignore render distance, rejoin later on
@@ -393,9 +374,7 @@ private void attemptNextSegment() {
}
final int last = this.path.size() - 1;
- final BetterBlockPos lastPos = this.path.get(this.path.size() - 1);
- // `ctx.world().isLoaded` cannot be used here as it returns false is the y-value is beyond the build limits.
- if (!this.completePath && ctx.world().getChunkSource().hasChunk(lastPos.x >> 4,lastPos.z >> 4)) {
+ if (!this.completePath && ctx.world().isLoaded(this.path.get(last))) {
this.pathNextSegment(last);
}
}
@@ -471,14 +450,14 @@ public void onRenderPass(RenderEvent event) {
}
public void onChunkEvent(ChunkEvent event) {
- if (event.isPostPopulate() && this.npfContext != null) {
+ if (event.isPostPopulate() && this.context != null) {
final LevelChunk chunk = ctx.world().getChunk(event.getX(), event.getZ());
- npfContext.queueForPacking(chunk);
+ this.context.queueForPacking(chunk);
}
}
public void onBlockChange(BlockChangeEvent event) {
- npfContext.queueBlockUpdate(event);
+ this.context.queueBlockUpdate(event);
}
public void onReceivePacket(PacketEvent event) {
@@ -505,19 +484,40 @@ public void destroy() {
} catch (InterruptedException e) {
e.printStackTrace();
}
+ this.context.destroy();
}
- public void onTick() {
- if (npfContext.tryAcquireReadLock()) {
- try {
- this.onTick0();
- } finally {
- npfContext.releaseReadLock();
+ public void repackChunks() {
+ ChunkSource chunkProvider = ctx.world().getChunkSource();
+
+ BetterBlockPos playerPos = ctx.playerFeet();
+
+ int playerChunkX = playerPos.getX() >> 4;
+ int playerChunkZ = playerPos.getZ() >> 4;
+
+ int minX = playerChunkX - 40;
+ int minZ = playerChunkZ - 40;
+ int maxX = playerChunkX + 40;
+ int maxZ = playerChunkZ + 40;
+
+ for (int x = minX; x <= maxX; x++) {
+ for (int z = minZ; z <= maxZ; z++) {
+ LevelChunk chunk = chunkProvider.getChunk(x, z, false);
+
+ if (chunk != null && !chunk.isEmpty()) {
+ this.context.queueForPacking(chunk);
+ }
}
}
+ }
+
+ public void onTick() {
+ synchronized (this.context.cullingLock) {
+ this.onTick0();
+ }
final long now = System.currentTimeMillis();
if ((now - this.timeLastCacheCull) / 1000 > Baritone.settings().elytraTimeBetweenCacheCullSecs.value) {
- npfContext.queueCacheCulling(ctx.player().chunkPosition().x(), ctx.player().chunkPosition().z(), Baritone.settings().elytraCacheCullDistance.value);
+ this.context.queueCacheCulling(ctx.player().chunkPosition().x(), ctx.player().chunkPosition().z(), Baritone.settings().elytraCacheCullDistance.value, this.boi);
this.timeLastCacheCull = now;
}
}
@@ -526,17 +526,11 @@ private void onTick0() {
// Fetch the previous solution, regardless of if it's going to be used
this.pendingSolution = null;
if (this.solver != null) {
- if (this.solver.isDone()) {
- try {
- this.pendingSolution = this.solver.get();
- } catch (Exception ignored) {
- // it doesn't matter if get() fails since the solution can just be recalculated synchronously
- } finally {
- this.solver = null;
- }
- } else {
- // avoid wasting more cycles on a hard solution, we'll do the work synchronously
- this.solver.cancel(true);
+ try {
+ this.pendingSolution = this.solver.get();
+ } catch (Exception ignored) {
+ // it doesn't matter if get() fails since the solution can just be recalculated synchronously
+ } finally {
this.solver = null;
}
}
@@ -564,7 +558,7 @@ private void onTick0() {
final List path = this.pathManager.getPath();
if (path.isEmpty()) {
return;
- } else if (this.destination == null) { // null check why????
+ } else if (this.destination == null) {
this.pathManager.clear();
return;
}
@@ -587,6 +581,7 @@ public void tick() {
if (this.pathManager.getPath().isEmpty()) {
return;
}
+
trySwapElytra();
if (ctx.player().horizontalCollision) {
@@ -601,10 +596,10 @@ public void tick() {
// If there's no previously calculated solution to use, or the context used at the end of last tick doesn't match this tick
final Solution solution;
- if (this.pendingSolution != null && this.pendingSolution.context.equals(solverContext)) {
- solution = this.pendingSolution;
- } else {
+ if (this.pendingSolution == null || !this.pendingSolution.context.equals(solverContext)) {
solution = this.solveAngles(solverContext);
+ } else {
+ solution = this.pendingSolution;
}
if (this.deployedFireworkLastTick) {
@@ -646,19 +641,11 @@ public void onPostTick(TickEvent event) {
this.pathManager.updatePlayerNear();
final SolverContext context = this.new SolverContext(true);
- this.solver = this.solverExecutor.submit(() -> {
- npfContext.acquireReadLock();
- try {
- return this.solveAngles(context);
- } finally {
- npfContext.releaseReadLock();
- }
- });
+ this.solver = this.solverExecutor.submit(() -> this.solveAngles(context));
this.solveNextTick = false;
}
}
- // calls passable which requires a read lock
private Solution solveAngles(final SolverContext context) {
final NetherPath path = context.path;
final int playerNear = landingMode ? path.size() - 1 : context.playerNear;
@@ -672,7 +659,6 @@ private Solution solveAngles(final SolverContext context) {
int minStep = playerNear;
for (int i = Math.min(playerNear + 20, path.size() - 1); i >= minStep; i--) {
- if (Thread.interrupted()) return null; // cancelled by the game thread
final List> candidates = new ArrayList<>();
for (int dy : heights) {
if (relaxation == 0 || i == minStep) {
@@ -1014,15 +1000,14 @@ private boolean isHitboxClear(final SolverContext context, final Vec3 dest, fina
return clear;
}
-
- return raytrace(8, src, dst, NetherPathfinderContext.Visibility.ALL);
+ return this.context.raytrace(8, src, dst, NetherPathfinderContext.Visibility.ALL);
}
public boolean clearView(Vec3 start, Vec3 dest, boolean ignoreLava) {
final boolean clear;
if (!ignoreLava) {
// if start == dest then the cpp raytracer dies
- clear = start.equals(dest) || raytrace(start, dest);
+ clear = start.equals(dest) || this.context.raytrace(start, dest);
} else {
clear = ctx.world().clip(new ClipContext(start, dest, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, ctx.player())).getType() == HitResult.Type.MISS;
}
@@ -1205,10 +1190,7 @@ private List simulate(final SolverContext context, final Vec3 goalDelta, f
delta = delta.subtract(motion);
// Collision box while the player is in motion, with additional padding for safety
- // Use expandTowards for directional swept volume (fixes #5049)
- // expandTowards handles negative vectors correctly (unlike inflate)
- // and provides full swept volume coverage (unlike move)
- final AABB inMotion = hitbox.expandTowards(motion.x, motion.y, motion.z).inflate(0.01);
+ final AABB inMotion = hitbox.inflate(motion.x, motion.y, motion.z).inflate(0.01);
int xmin = fastFloor(inMotion.minX);
int xmax = fastCeil(inMotion.maxX);
@@ -1281,13 +1263,12 @@ private static Vec3 step(final Vec3 motion, final Vec3 lookDirection, final floa
return new Vec3(motionX, motionY, motionZ);
}
- // any call to this must be done with the lock held
private boolean passable(int x, int y, int z, boolean ignoreLava) {
if (ignoreLava) {
final BlockState state = this.bsi.get0(x, y, z);
return state.getBlock() instanceof AirBlock || MovementHelper.isLava(state);
} else {
- return passable(x, y, z);
+ return !this.boi.get0(x, y, z);
}
}
@@ -1302,8 +1283,8 @@ private void tickInventoryTransactions() {
if (invTickCountdown > 0) invTickCountdown--;
}
- private void queueWindowClick(int windowId, int slotId, int button, ContainerInput type) {
- invTransactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, type, ctx.player()));
+ private void queueWindowClick(int windowId, int slotId, int button, ContainerInput input) {
+ invTransactionQueue.add(() -> ctx.playerController().windowClick(windowId, slotId, button, input, ctx.player()));
}
private int findGoodElytra() {
@@ -1343,80 +1324,4 @@ void logVerbose(String message) {
logDebug(message);
}
}
-
- // so we don't get stuck trying to pathfind through the roof
- private BetterBlockPos fixDestination(BetterBlockPos dst) {
- if (ctx.world().dimension() == Level.NETHER) {
- if (ctx.player().getY() >= 128 && dst.y < 128) {
- return new BetterBlockPos(dst.x, 128, dst.z);
- }
- else if (ctx.player().getY() < 128 && dst.y >= 128) {
- return new BetterBlockPos(dst.x, 64, dst.z);
- }
- }
- return dst;
- }
-
- private BetterBlockPos destinationFixed() {
- return fixDestination(this.destination);
- }
-
- public boolean raytrace(double startX, double startY, double startZ, double endX, double endY, double endZ) {
- final int maxHeight = npfContext.getMaxHeight() + ctx.world().getMinY();
- final int minHeight = ctx.world().getMinY();
- final boolean isOOB = startY >= maxHeight || endY >= maxHeight || startY < minHeight || endY < minHeight;
- if (isOOB) {
- Vec3 start = new Vec3(startX, startY, startZ);
- Vec3 end = new Vec3(endX, endY, endZ);
- return ctx.world().clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, ctx.player())).getType() == HitResult.Type.MISS;
- }
-
- return npfContext.raytrace(startX, startY, startZ, endX, endY, endZ);
- }
-
- public boolean raytrace(Vec3 start, Vec3 end) {
- final int maxHeight = npfContext.getMaxHeight() + ctx.world().getMinY();
- final int minHeight = ctx.world().getMinY();
- final boolean isOOB = start.y >= maxHeight || end.y >= maxHeight || start.y < minHeight || end.y < minHeight;
- if (isOOB) {
- return ctx.world().clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, ctx.player())).getType() == HitResult.Type.MISS;
- }
- return npfContext.raytrace(start.x, start.y, start.z, end.x, end.y, end.z);
- }
-
- public boolean raytrace(int count, double[] src, double[] dst, int visibility) {
- if (src.length != count * 3 || src.length != dst.length) {
- throw new IllegalArgumentException("Expected source and dst to have length of " + (count * 3));
- }
- final int maxHeight = npfContext.getMaxHeight() + ctx.world().getMinY();
-
- boolean isOOB = false;
- for(int i = 1; i < src.length; i += 3) {
- if (src[i] >= maxHeight || src[i] < ctx.world().getMinY() ||
- dst[i] >= maxHeight || dst[i] < ctx.world().getMinY()) {
- isOOB = true;
- break;
- }
- }
-
- if(isOOB) {
- for (int i = 0; i < count; i++) {
- Vec3 start = new Vec3(src[i * 3], src[i * 3 + 1], src[i * 3 + 2]);
- Vec3 end = new Vec3(dst[i * 3], dst[i * 3 + 1], dst[i * 3 + 2]);
- if (ctx.world().clip(new ClipContext(start, end, ClipContext.Block.COLLIDER, ClipContext.Fluid.NONE, ctx.player())).getType() != HitResult.Type.MISS) {
- return false;
- }
- }
- return true;
- }
-
- return npfContext.raytrace(count, src, dst, visibility);
- }
-
- public boolean passable(int x, int y, int z) {
- if(y >= ctx.world().getMaxY() || y < ctx.world().getMinY()) {
- return true;
- }
- return npfContext.passable(x, y, z);
- }
}
diff --git a/src/main/java/baritone/process/elytra/IElytraPathFinder.java b/src/main/java/baritone/process/elytra/IElytraPathFinder.java
deleted file mode 100644
index d8148b334f..0000000000
--- a/src/main/java/baritone/process/elytra/IElytraPathFinder.java
+++ /dev/null
@@ -1,26 +0,0 @@
-/*
- * This file is part of Baritone.
- *
- * Baritone is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Baritone is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Baritone. If not, see .
- */
-
-package baritone.process.elytra;
-
-import net.minecraft.core.BlockPos;
-
-import java.util.concurrent.CompletableFuture;
-
-public interface IElytraPathFinder {
- CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst);
-}
diff --git a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java
index 280366d980..b5373d6a32 100644
--- a/src/main/java/baritone/process/elytra/NetherPathfinderContext.java
+++ b/src/main/java/baritone/process/elytra/NetherPathfinderContext.java
@@ -24,10 +24,8 @@
import dev.babbaj.pathfinder.Octree;
import dev.babbaj.pathfinder.PathSegment;
import net.minecraft.core.BlockPos;
-import net.minecraft.resources.ResourceKey;
import net.minecraft.util.BitStorage;
import net.minecraft.world.level.ChunkPos;
-import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.LevelChunk;
@@ -35,154 +33,90 @@
import net.minecraft.world.level.chunk.PaletteResize;
import net.minecraft.world.level.chunk.PalettedContainer;
import net.minecraft.world.phys.Vec3;
-import sun.misc.Unsafe;
import java.lang.ref.SoftReference;
-import java.lang.reflect.Field;
-import java.nio.file.Path;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
-import java.util.concurrent.locks.Lock;
-import java.util.concurrent.locks.ReentrantReadWriteLock;
-
-import static net.minecraft.world.level.chunk.LevelChunkSection.SECTION_SIZE;
/**
* @author Brady
*/
-public final class NetherPathfinderContext implements IElytraPathFinder {
+public final class NetherPathfinderContext {
- private static final Unsafe UNSAFE;
- static {
- try {
- Field f = Unsafe.class.getDeclaredField("theUnsafe");
- f.setAccessible(true);
- UNSAFE = (Unsafe) f.get(null);
- } catch (Exception ex) {
- throw new RuntimeException(ex);
- }
- }
private static final BlockState AIR_BLOCK_STATE = Blocks.AIR.defaultBlockState();
// This lock must be held while there are active pointers to chunks in java,
// but we just hold it for the entire tick so we don't have to think much about it.
- public final ReentrantReadWriteLock rwl = new ReentrantReadWriteLock();
- public final ReentrantReadWriteLock.ReadLock readLock = rwl.readLock();
- public final ReentrantReadWriteLock.WriteLock writeLock = rwl.writeLock();
- private final int maxHeight;
+ public final Object cullingLock = new Object();
// Visible for access in BlockStateOctreeInterface
final long context;
private final long seed;
- // write locked operations
- private final ExecutorService writeExecutor = Executors.newSingleThreadExecutor();
- // operations that don't make changes to the chunk cache. could use multiple threads but i'm not sure if it would cause problems.
- private final ExecutorService readExecutor = Executors.newSingleThreadExecutor();
- private final ResourceKey dimension;
- final int minY;
- private final BlockStateOctreeInterface boi;
+ private final ExecutorService executor;
- public NetherPathfinderContext(long seed, Path cache, Level world) {
- this.dimension = world.dimension();
- this.minY = world.dimensionType().minY();
- final int dim;
- if (this.dimension == Level.NETHER) dim = NetherPathfinder.DIMENSION_NETHER;
- else if (this.dimension == Level.END) dim = NetherPathfinder.DIMENSION_END;
- else dim = NetherPathfinder.DIMENSION_OVERWORLD;
- int height = Math.min(world.dimensionType().height(), 384);
- if (!Baritone.settings().elytraAllowAboveRoof.value && dim == NetherPathfinder.DIMENSION_NETHER) height = Math.min(height, 128);
- this.maxHeight = height;
- this.context = NetherPathfinder.newContext(seed, cache != null ? cache.toString() : null, dim, height, Baritone.settings().elytraCustomAllocator.value);
+ public NetherPathfinderContext(long seed) {
+ this.context = NetherPathfinder.newContext(seed);
this.seed = seed;
- this.boi = new BlockStateOctreeInterface(this);
+ this.executor = Executors.newSingleThreadExecutor();
}
public boolean hasChunk(ChunkPos pos) {
return NetherPathfinder.hasChunkFromJava(this.context, pos.x(), pos.z());
}
- public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks) {
- this.writeExecutor.execute(() -> {
- writeLock.lock();
- try {
- this.boi.chunkPtr = 0L;
+ public void queueCacheCulling(int chunkX, int chunkZ, int maxDistanceBlocks, BlockStateOctreeInterface boi) {
+ this.executor.execute(() -> {
+ synchronized (this.cullingLock) {
+ boi.chunkPtr = 0L;
NetherPathfinder.cullFarChunks(this.context, chunkX, chunkZ, maxDistanceBlocks);
- } finally {
- writeLock.unlock();
}
});
}
public void queueForPacking(final LevelChunk chunkIn) {
final SoftReference ref = new SoftReference<>(chunkIn);
- this.writeExecutor.execute(() -> {
+ this.executor.execute(() -> {
// TODO: Prioritize packing recent chunks and/or ones that the path goes through,
// and prune the oldest chunks per chunkPackerQueueMaxSize
final LevelChunk chunk = ref.get();
if (chunk != null) {
- writeLock.lock();
- try {
- // we might free this chunk
- this.boi.chunkPtr = 0L;
- long ptr = NetherPathfinder.allocateAndInsertChunk(this.context, chunk.getPos().x(), chunk.getPos().z());
- writeChunkData(chunk, ptr);
- } finally {
- writeLock.unlock();
- }
+ long ptr = NetherPathfinder.getOrCreateChunk(this.context, chunk.getPos().x(), chunk.getPos().z());
+ writeChunkData(chunk, ptr);
}
});
}
public void queueBlockUpdate(BlockChangeEvent event) {
- this.writeExecutor.execute(() -> {
+ this.executor.execute(() -> {
ChunkPos chunkPos = event.getChunkPos();
- // not inserting or deleting from the cache hashmap but it would still be bad for this function to race with itself
- writeLock.lock();
- try {
- long ptr = NetherPathfinder.getChunk(this.context, chunkPos.x(), chunkPos.z());
- if (ptr == 0) return; // this shouldn't ever happen
- event.getBlocks().forEach(pair -> {
- BlockPos pos = pair.first().below(minY);
- if (pos.getY() < 0 || pos.getY() >= 384) return;
- boolean isSolid = pair.second() != AIR_BLOCK_STATE;
- Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid);
- });
- } finally {
- writeLock.unlock();
- }
+ long ptr = NetherPathfinder.getChunkPointer(this.context, chunkPos.x(), chunkPos.z());
+ if (ptr == 0) return; // this shouldn't ever happen
+ event.getBlocks().forEach(pair -> {
+ BlockPos pos = pair.first();
+ if (pos.getY() >= 128) return;
+ boolean isSolid = pair.second() != AIR_BLOCK_STATE;
+ Octree.setBlock(ptr, pos.getX() & 15, pos.getY(), pos.getZ() & 15, isSolid);
+ });
});
}
- public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) {
- final BlockPos adjustedSrc = src.below(minY);
- final BlockPos adjustedDst = dst.below(minY);
- boolean generate = Baritone.settings().elytraPredictTerrain.value && this.dimension == Level.NETHER;
- Lock l = generate ? writeLock : readLock;
- ExecutorService exec = generate ? writeExecutor : readExecutor;
+ public CompletableFuture pathFindAsync(final BlockPos src, final BlockPos dst) {
return CompletableFuture.supplyAsync(() -> {
- l.lock();
- try {
- final PathSegment segment = NetherPathfinder.pathFind(
- this.context,
- adjustedSrc.getX(), adjustedSrc.getY(), adjustedSrc.getZ(),
- adjustedDst.getX(), adjustedDst.getY(), adjustedDst.getZ(),
- !Baritone.settings().elytraAllowTightSpaces.value, // atleastX4
- false, // refine
- 10000, // timeoutMs
- !generate, // useAirIfChunkNotLoaded
- // TODO: Determine appropriate cost value
- 8.0 // fakeChunkCost
- );
- if (segment == null) {
- throw new PathCalculationException("Path calculation failed");
- }
-
- return new UnpackedSegment(UnpackedSegment.from(segment).collect().stream().map(pos -> pos.above(minY)), segment.finished);
- } finally {
- l.unlock();
+ final PathSegment segment = NetherPathfinder.pathFind(
+ this.context,
+ src.getX(), src.getY(), src.getZ(),
+ dst.getX(), dst.getY(), dst.getZ(),
+ true,
+ false,
+ 10000,
+ !Baritone.settings().elytraPredictTerrain.value
+ );
+ if (segment == null) {
+ throw new PathCalculationException("Path calculation failed");
}
- }, exec);
+ return segment;
+ }, this.executor);
}
/**
@@ -199,9 +133,7 @@ public CompletableFuture pathFindAsync(final BlockPos src, fina
*/
public boolean raytrace(final double startX, final double startY, final double startZ,
final double endX, final double endY, final double endZ) {
- final double adjustedStartY = startY - this.minY;
- final double adjustedEndY = endY - this.minY;
- return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, startX, adjustedStartY, startZ, endX, adjustedEndY, endZ);
+ return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, startX, startY, startZ, endX, endY, endZ);
}
/**
@@ -213,21 +145,10 @@ public boolean raytrace(final double startX, final double startY, final double s
* @return {@code true} if there is visibility between the points
*/
public boolean raytrace(final Vec3 start, final Vec3 end) {
- final Vec3 adjustedStart = start.subtract(0, this.minY, 0);
- final Vec3 adjustedEnd = end.subtract(0, this.minY, 0);
- return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, adjustedStart.x, adjustedStart.y, adjustedStart.z, adjustedEnd.x, adjustedEnd.y, adjustedEnd.z);
+ return NetherPathfinder.isVisible(this.context, NetherPathfinder.CACHE_MISS_SOLID, start.x, start.y, start.z, end.x, end.y, end.z);
}
public boolean raytrace(final int count, final double[] src, final double[] dst, final int visibility) {
- if (src.length != count * 3 || dst.length != count * 3) {
- throw new IllegalArgumentException("Bad array lengths");
- }
-
- for(int i = 1; i < src.length; i+= 3) {
- src[i] -= this.minY;
- dst[i] -= this.minY;
- }
-
switch (visibility) {
case Visibility.ALL:
return NetherPathfinder.isVisibleMulti(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, false) == -1;
@@ -241,22 +162,9 @@ public boolean raytrace(final int count, final double[] src, final double[] dst,
}
public void raytrace(final int count, final double[] src, final double[] dst, final boolean[] hitsOut, final double[] hitPosOut) {
- if (src.length != count * 3 || dst.length != count * 3) {
- throw new IllegalArgumentException("Bad array lengths");
- }
-
- for(int i = 1; i < src.length; i+= 3) {
- src[i] -= this.minY;
- dst[i] -= this.minY;
- }
-
NetherPathfinder.raytrace(this.context, NetherPathfinder.CACHE_MISS_SOLID, count, src, dst, hitsOut, hitPosOut);
}
- public boolean passable(int x, int y, int z) {
- return !this.boi.get0(x, y, z);
- }
-
public void cancel() {
NetherPathfinder.cancel(this.context);
}
@@ -264,12 +172,10 @@ public void cancel() {
public void destroy() {
this.cancel();
// Ignore anything that was queued up, just shutdown the executor
- this.readExecutor.shutdownNow();
- this.writeExecutor.shutdownNow();
+ this.executor.shutdownNow();
try {
- while (!this.readExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {}
- while (!this.writeExecutor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {}
+ while (!this.executor.awaitTermination(Long.MAX_VALUE, TimeUnit.NANOSECONDS)) {}
} catch (InterruptedException e) {
e.printStackTrace();
}
@@ -281,51 +187,19 @@ public long getSeed() {
return this.seed;
}
- public void acquireReadLock() {
- this.readLock.lock();
- }
-
- public boolean tryAcquireReadLock() {
- return this.readLock.tryLock();
- }
-
- public void releaseReadLock() {
- this.readLock.unlock();
- }
-
- public int getMaxHeight() {
- return this.maxHeight;
- }
-
- private static void writeChunkData(LevelChunk chunk, long chunkPtr) {
+ private static void writeChunkData(LevelChunk chunk, long ptr) {
try {
LevelChunkSection[] chunkInternalStorageArray = chunk.getSections();
- final int maxSections = Math.min(chunkInternalStorageArray.length, 24); // pathfinder support stops at 384/16 sections
- for (int y0 = 0; y0 < maxSections; y0++) {
+ for (int y0 = 0; y0 < 8; y0++) {
final LevelChunkSection extendedblockstorage = chunkInternalStorageArray[y0];
- if (extendedblockstorage == null || extendedblockstorage.hasOnlyAir()) {
+ if (extendedblockstorage == null) {
continue;
}
final PalettedContainer bsc = extendedblockstorage.getStates();
IPalettedContainer iPalettedContainer = (IPalettedContainer) bsc;
- var palette = iPalettedContainer.getPalette();
- // Mushrooms spawn on the roof and writing them as solid will cause pages to be unnecessarily allocated.
- // idFor can't be used because it may update the palette
int airId = -1;
- int caveAirId = -1;
- int redMushroomId = -1;
- int brownMushroomId = -1;
- for (int i = 0; i < palette.getSize(); i++) {
- BlockState bs = palette.valueFor(i);
- if (bs == Blocks.AIR.defaultBlockState()) airId = i;
- else if (bs == Blocks.CAVE_AIR.defaultBlockState()) caveAirId = i;
- else if (bs == Blocks.RED_MUSHROOM.defaultBlockState()) redMushroomId = i;
- else if (bs == Blocks.BROWN_MUSHROOM.defaultBlockState()) brownMushroomId = i;
- }
- if (airId == -1 & caveAirId == -1) {
- final long bytesInSection = SECTION_SIZE / 8;
- UNSAFE.setMemory(chunkPtr + (y0 * bytesInSection), bytesInSection, (byte) 0xFF);
- continue;
+ if (iPalettedContainer.getPalette().maybeHas(state -> state.equals(AIR_BLOCK_STATE))) {
+ airId = iPalettedContainer.getPalette().idFor(AIR_BLOCK_STATE, PaletteResize.noResizeExpected());
}
// pasted from FasterWorldScanner
final BitStorage array = iPalettedContainer.getStorage();
@@ -343,28 +217,27 @@ private static void writeChunkData(LevelChunk chunk, long chunkPtr) {
int x = (idx & 15);
int y = yReal + (idx >> 8);
int z = ((idx >> 4) & 15);
-
- // Avoid unnecessary writes that may trigger a page allocation
- if (!(value == airId | value == caveAirId) & value != redMushroomId & value != brownMushroomId) {
- Octree.setBlock(chunkPtr, x, y, z, true);
- }
+ Octree.setBlock(ptr, x, y, z, value != airId);
}
}
}
+ Octree.setIsFromJava(ptr);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException(e);
}
}
- public static boolean isSupported() {
- return NetherPathfinder.isThisSystemSupported();
- }
-
public static final class Visibility {
+
public static final int ALL = 0;
public static final int NONE = 1;
public static final int ANY = 2;
+
private Visibility() {}
}
+
+ public static boolean isSupported() {
+ return NetherPathfinder.isThisSystemSupported();
+ }
}
diff --git a/src/main/java/baritone/process/elytra/NullElytraProcess.java b/src/main/java/baritone/process/elytra/NullElytraProcess.java
index a0f0ff1efb..07d5fde0e1 100644
--- a/src/main/java/baritone/process/elytra/NullElytraProcess.java
+++ b/src/main/java/baritone/process/elytra/NullElytraProcess.java
@@ -21,13 +21,9 @@
import baritone.api.pathing.goals.Goal;
import baritone.api.process.IElytraProcess;
import baritone.api.process.PathingCommand;
-import baritone.api.utils.BetterBlockPos;
import baritone.utils.BaritoneProcessHelper;
import net.minecraft.core.BlockPos;
-import java.util.Collections;
-import java.util.List;
-
/**
* @author Brady
*/
@@ -47,11 +43,6 @@ public BlockPos currentDestination() {
return null;
}
- @Override
- public List getPath() {
- return Collections.emptyList();
- }
-
@Override
public void pathTo(BlockPos destination) {
throw new UnsupportedOperationException("Called pathTo() on NullElytraBehavior");
@@ -96,6 +87,4 @@ public boolean isLoaded() {
public boolean isSafeToCancel() {
return true;
}
-
-
}
diff --git a/src/main/java/baritone/utils/BlockBreakHelper.java b/src/main/java/baritone/utils/BlockBreakHelper.java
index 0c5cf6f000..bd68916bf8 100644
--- a/src/main/java/baritone/utils/BlockBreakHelper.java
+++ b/src/main/java/baritone/utils/BlockBreakHelper.java
@@ -20,6 +20,8 @@
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import baritone.utils.accessor.IPlayerControllerMP;
+import net.minecraft.core.BlockPos;
+import net.minecraft.core.Direction;
import net.minecraft.world.InteractionHand;
import net.minecraft.world.phys.BlockHitResult;
import net.minecraft.world.phys.HitResult;
@@ -35,6 +37,8 @@ public final class BlockBreakHelper {
private final IPlayerContext ctx;
private boolean wasHitting;
private int breakDelayTimer = 0;
+ private BlockPos activeBlock;
+ private Direction activeFace;
BlockBreakHelper(IPlayerContext ctx) {
this.ctx = ctx;
@@ -47,6 +51,8 @@ public void stopBreakingBlock() {
ctx.playerController().resetBlockRemoving();
wasHitting = false;
}
+ activeBlock = null;
+ activeFace = null;
}
public void tick(boolean isLeftClick) {
@@ -54,17 +60,38 @@ public void tick(boolean isLeftClick) {
breakDelayTimer--;
return;
}
- HitResult trace = ctx.objectMouseOver();
- boolean isBlockTrace = trace != null && trace.getType() == HitResult.Type.BLOCK;
+ if (!isLeftClick) {
+ wasHitting = false;
+ activeBlock = null;
+ activeFace = null;
+ return;
+ }
+
+ if (!canContinueActiveTarget()) {
+ if (wasHitting) {
+ ctx.playerController().resetBlockRemoving();
+ }
+ wasHitting = false;
+ activeBlock = null;
+ activeFace = null;
- if (isLeftClick && isBlockTrace) {
+ HitResult trace = ctx.objectMouseOver();
+ if (trace == null || trace.getType() != HitResult.Type.BLOCK) {
+ return;
+ }
+ BlockHitResult blockTrace = (BlockHitResult) trace;
+ activeBlock = blockTrace.getBlockPos().immutable();
+ activeFace = blockTrace.getDirection();
+ }
+
+ if (activeBlock != null) {
ctx.playerController().setHittingBlock(wasHitting);
if (ctx.playerController().hasBrokenBlock()) {
ctx.playerController().syncHeldItem();
- ctx.playerController().clickBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection());
+ ctx.playerController().clickBlock(activeBlock, activeFace);
ctx.player().swing(InteractionHand.MAIN_HAND);
} else {
- if (ctx.playerController().onPlayerDamageBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection())) {
+ if (ctx.playerController().onPlayerDamageBlock(activeBlock, activeFace)) {
ctx.player().swing(InteractionHand.MAIN_HAND);
}
if (ctx.playerController().hasBrokenBlock()) { // block broken this tick
@@ -76,12 +103,29 @@ public void tick(boolean isLeftClick) {
}
// if true, we're breaking a block. if false, we broke the block this tick
wasHitting = !ctx.playerController().hasBrokenBlock();
+ if (!wasHitting) {
+ activeBlock = null;
+ activeFace = null;
+ }
// this value will be reset by the MC client handling mouse keys
// since we're not spoofing the click keybind to the client, the client will stop the break if isDestroyingBlock is true
// we store and restore this value on the next tick to determine if we're breaking a block
ctx.playerController().setHittingBlock(false);
- } else {
- wasHitting = false;
}
}
+
+ private boolean canContinueActiveTarget() {
+ if (!wasHitting || activeBlock == null || ctx.world().getBlockState(activeBlock).isAir()) {
+ return false;
+ }
+
+ double eyeX = ctx.player().getX();
+ double eyeY = ctx.player().getY() + ctx.player().getEyeHeight();
+ double eyeZ = ctx.player().getZ();
+ double dx = Math.max(Math.max(activeBlock.getX() - eyeX, 0.0D), eyeX - activeBlock.getX() - 1.0D);
+ double dy = Math.max(Math.max(activeBlock.getY() - eyeY, 0.0D), eyeY - activeBlock.getY() - 1.0D);
+ double dz = Math.max(Math.max(activeBlock.getZ() - eyeZ, 0.0D), eyeZ - activeBlock.getZ() - 1.0D);
+ double reach = ctx.playerController().getBlockReachDistance();
+ return dx * dx + dy * dy + dz * dz <= reach * reach;
+ }
}
diff --git a/src/main/java/baritone/utils/GuiClick.java b/src/main/java/baritone/utils/GuiClick.java
index 11685c909d..06d344baf8 100644
--- a/src/main/java/baritone/utils/GuiClick.java
+++ b/src/main/java/baritone/utils/GuiClick.java
@@ -64,7 +64,7 @@ public boolean isPauseScreen() {
}
@Override
- public void extractRenderState(GuiGraphicsExtractor grapics, int mouseX, int mouseY, float partialTicks) {
+ public void extractRenderState(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTick) {
double mx = mc.mouseHandler.xpos();
double my = mc.mouseHandler.ypos();
@@ -82,10 +82,11 @@ public void extractRenderState(GuiGraphicsExtractor grapics, int mouseX, int mou
currentMouseOver = ((BlockHitResult) result).getBlockPos();
}
}
+ super.extractRenderState(guiGraphics, mouseX, mouseY, partialTick);
}
@Override
- public void extractBackground(GuiGraphicsExtractor grapics, int mouseX, int mouseY, float partialTicks) {
+ public void extractBackground(GuiGraphicsExtractor guiGraphics, int mouseX, int mouseY, float partialTick) {
// Prevent default background rendering
}
diff --git a/src/main/java/baritone/utils/IRenderer.java b/src/main/java/baritone/utils/IRenderer.java
index 1c9b639854..050c98b816 100644
--- a/src/main/java/baritone/utils/IRenderer.java
+++ b/src/main/java/baritone/utils/IRenderer.java
@@ -22,17 +22,19 @@
import baritone.utils.accessor.IEntityRenderManager;
import baritone.utils.accessor.IRenderPipelines;
import baritone.utils.accessor.IRenderType;
-import com.mojang.blaze3d.pipeline.BlendFunction;
-import com.mojang.blaze3d.pipeline.ColorTargetState;
-import com.mojang.blaze3d.pipeline.DepthStencilState;
-import com.mojang.blaze3d.pipeline.RenderPipeline;
+import com.mojang.blaze3d.IndexType;
+import com.mojang.blaze3d.PrimitiveTopology;
+import com.mojang.blaze3d.buffers.GpuBuffer;
+import com.mojang.blaze3d.pipeline.*;
+import com.mojang.blaze3d.platform.BlendFactor;
import com.mojang.blaze3d.platform.CompareOp;
-import com.mojang.blaze3d.platform.DestFactor;
-import com.mojang.blaze3d.platform.SourceFactor;
+import com.mojang.blaze3d.systems.RenderSystem;
import com.mojang.blaze3d.vertex.*;
+import java.nio.ByteBuffer;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.RenderPipelines;
import net.minecraft.client.renderer.blockentity.BeaconRenderer;
+import net.minecraft.client.renderer.feature.RenderTypeFeatureRenderer;
import net.minecraft.client.renderer.rendertype.RenderSetup;
import net.minecraft.client.renderer.rendertype.RenderType;
import net.minecraft.client.renderer.rendertype.RenderTypes;
@@ -50,27 +52,35 @@ public interface IRenderer {
Tesselator tessellator = Tesselator.getInstance();
IEntityRenderManager renderManager = (IEntityRenderManager) Minecraft.getInstance().getEntityRenderDispatcher();
Settings settings = BaritoneAPI.getSettings();
+ BlendFunction BARITONE_LINES_BLEND = new BlendFunction(
+ BlendFactor.SRC_ALPHA,
+ BlendFactor.ONE_MINUS_SRC_ALPHA,
+ BlendFactor.ONE,
+ BlendFactor.ZERO
+ );
+
RenderPipeline.Snippet BARITONE_LINES_SNIPPET = RenderPipeline.builder(((IRenderPipelines) new RenderPipelines()).getLinesSnippet())
- .withColorTargetState(new ColorTargetState(new BlendFunction(
- SourceFactor.SRC_ALPHA,
- DestFactor.ONE_MINUS_SRC_ALPHA,
- SourceFactor.ONE,
- DestFactor.ZERO
- )))
+ .withColorTargetState(new ColorTargetState(BARITONE_LINES_BLEND))
.withDepthStencilState(new DepthStencilState(CompareOp.LESS_THAN_OR_EQUAL, false))
.withCull(false)
.buildSnippet();
+ BindGroupLayout BARITONE_BEACON_BEAM_SNIPPET_LAYOUT = BindGroupLayout.builder()
+ .withSampler("Sampler0")
+ .build();
+
RenderPipeline.Snippet BARITONE_BEACON_BEAM_SNIPPET = RenderPipeline.builder(((IRenderPipelines) new RenderPipelines()).getMatricesFogSnippet())
.withVertexShader("core/rendertype_beacon_beam")
.withFragmentShader("core/rendertype_beacon_beam")
- .withSampler("Sampler0")
- .withVertexFormat(DefaultVertexFormat.BLOCK, VertexFormat.Mode.QUADS)
+ .withVertexBinding(0, DefaultVertexFormat.BLOCK)
+ .withBindGroupLayout(BARITONE_BEACON_BEAM_SNIPPET_LAYOUT)
.buildSnippet();
RenderPipeline BEACON_BEAM_OPAQUE = ((IRenderPipelines) new RenderPipelines()).baritone$registerPipeline(RenderPipeline.builder(BARITONE_BEACON_BEAM_SNIPPET)
.withLocation("pipeline/baritone_beacon_beam_opaque")
+ .withColorTargetState(ColorTargetState.DEFAULT)
.withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false))
+ .withPrimitiveTopology(PrimitiveTopology.QUADS)
.withCull(true)
.build());
@@ -78,6 +88,7 @@ public interface IRenderer {
.withLocation("pipeline/baritone_beacon_beam_translucent")
.withColorTargetState(new ColorTargetState(BlendFunction.TRANSLUCENT))
.withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false))
+ .withPrimitiveTopology(PrimitiveTopology.QUADS)
.withCull(true)
.build());
@@ -87,7 +98,6 @@ public interface IRenderer {
.withLocation("pipelines/baritone_lines_with_depth")
.withDepthStencilState(new DepthStencilState(CompareOp.LESS_THAN_OR_EQUAL, false))
.build())
- .bufferSize(256)
.createRenderSetup()
);
RenderType linesNoDepthRenderType = ((IRenderType) RenderTypes.lines()).createRenderType(
@@ -96,7 +106,6 @@ public interface IRenderer {
.withLocation("pipelines/baritone_lines_no_depth")
.withDepthStencilState(new DepthStencilState(CompareOp.ALWAYS_PASS, false))
.build())
- .bufferSize(256)
.createRenderSetup()
);
@@ -122,7 +131,7 @@ static void glColor(Color color, float alpha) {
static BufferBuilder startLines(Color color, float alpha) {
glColor(color, alpha);
- return tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH);
+ return tessellator.begin(PrimitiveTopology.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL_LINE_WIDTH);
}
static BufferBuilder startLines(Color color) {
@@ -132,22 +141,58 @@ static BufferBuilder startLines(Color color) {
static void endLines(BufferBuilder bufferBuilder, boolean ignoredDepth) {
MeshData meshData = bufferBuilder.build();
if (meshData != null) {
- if (ignoredDepth) {
- linesNoDepthRenderType.draw(meshData);
- } else {
- linesWithDepthRenderType.draw(meshData);
+ try (meshData) {
+ ByteBuffer vertexData = meshData.vertexBuffer();
+ int indexCount = meshData.drawState().indexCount();
+ IndexType indexType = meshData.drawState().indexType();
+ PrimitiveTopology topology = meshData.drawState().primitiveTopology();
+
+ GpuBuffer vertexBuffer = RenderSystem.getDevice().createBuffer(
+ () -> "baritone_lines",
+ GpuBuffer.USAGE_VERTEX | GpuBuffer.USAGE_COPY_DST,
+ vertexData
+ );
+
+ RenderSystem.AutoStorageIndexBuffer autoIndices = RenderSystem.getSequentialBuffer(topology);
+ GpuBuffer indexBuffer = autoIndices.getBuffer(indexCount);
+
+ if (ignoredDepth) {
+ linesNoDepthRenderType.prepare().drawFromBuffer(vertexBuffer, indexBuffer, indexType, 0, 0, indexCount);
+ } else {
+ linesWithDepthRenderType.prepare().drawFromBuffer(vertexBuffer, indexBuffer, indexType, 0, 0, indexCount);
+ }
+
+ vertexBuffer.close();
}
}
}
static BufferBuilder startBlockQuads() {
- return tessellator.begin(VertexFormat.Mode.QUADS, DefaultVertexFormat.BLOCK);
+ return tessellator.begin(PrimitiveTopology.QUADS, DefaultVertexFormat.BLOCK);
}
static void endBuffer(BufferBuilder bufferBuilder, RenderType renderType) {
MeshData meshData = bufferBuilder.build();
if (meshData != null) {
- renderType.draw(meshData);
+ try (meshData) {
+ ByteBuffer vertexData = meshData.vertexBuffer();
+ int indexCount = meshData.drawState().indexCount();
+ IndexType indexType = meshData.drawState().indexType();
+ PrimitiveTopology topology = meshData.drawState().primitiveTopology();
+
+ GpuBuffer vertexBuffer = RenderSystem.getDevice().createBuffer(
+ () -> "baritone_beacon_beam",
+ GpuBuffer.USAGE_VERTEX | GpuBuffer.USAGE_COPY_DST,
+ vertexData
+ );
+
+ RenderSystem.AutoStorageIndexBuffer autoIndices = RenderSystem.getSequentialBuffer(topology);
+ GpuBuffer indexBuffer = autoIndices.getBuffer(indexCount);
+
+ renderType.prepare().drawFromBuffer(vertexBuffer, indexBuffer, indexType, 0, 0, indexCount);
+
+ vertexBuffer.close();
+ }
}
}
diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java
index 95506ab5ce..b61960004e 100644
--- a/src/main/java/baritone/utils/PathRenderer.java
+++ b/src/main/java/baritone/utils/PathRenderer.java
@@ -69,13 +69,17 @@ public static double posZ() {
return renderManager.renderPosZ();
}
+ static {
+ Tesselator.init();
+ }
+
public static void render(RenderEvent event, PathingBehavior behavior) {
final IPlayerContext ctx = behavior.ctx;
if (ctx.world() == null) {
return;
}
- if (ctx.minecraft().screen instanceof GuiClick) {
- ((GuiClick) ctx.minecraft().screen).onRender(event.getModelViewStack(), event.getProjectionMatrix());
+ if (ctx.minecraft().gui.screen() instanceof GuiClick) {
+ ((GuiClick) ctx.minecraft().gui.screen()).onRender(event.getModelViewStack(), event.getProjectionMatrix());
}
final float partialTicks = event.getPartialTicks();
diff --git a/src/main/java/baritone/utils/Tesselator.java b/src/main/java/baritone/utils/Tesselator.java
new file mode 100644
index 0000000000..0d317652e1
--- /dev/null
+++ b/src/main/java/baritone/utils/Tesselator.java
@@ -0,0 +1,60 @@
+/*
+ * This file is part of Baritone.
+ *
+ * Baritone is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU Lesser General Public License as published by
+ * the Free Software Foundation, either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Baritone is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with Baritone. If not, see .
+ */
+
+package baritone.utils;
+
+import com.mojang.blaze3d.PrimitiveTopology;
+import com.mojang.blaze3d.vertex.BufferBuilder;
+import com.mojang.blaze3d.vertex.ByteBufferBuilder;
+import com.mojang.blaze3d.vertex.VertexFormat;
+import org.jspecify.annotations.Nullable;
+
+public class Tesselator {
+ private static final int MAX_BYTES = 786432;
+ private final ByteBufferBuilder buffer;
+ private static @Nullable Tesselator instance;
+
+ public static void init() {
+ if (instance != null) {
+ throw new IllegalStateException("Tesselator has already been initialized");
+ }
+ instance = new Tesselator();
+ }
+
+ public static Tesselator getInstance() {
+ if (instance == null) {
+ throw new IllegalStateException("Tesselator has not been initialized");
+ }
+ return instance;
+ }
+
+ public Tesselator(int size) {
+ this.buffer = new ByteBufferBuilder(size);
+ }
+
+ public Tesselator() {
+ this(786432);
+ }
+
+ public BufferBuilder begin(PrimitiveTopology mode, VertexFormat format) {
+ return new BufferBuilder(this.buffer, mode, format);
+ }
+
+ public void clear() {
+ this.buffer.clear();
+ }
+}
diff --git a/src/main/java/baritone/utils/ToolSet.java b/src/main/java/baritone/utils/ToolSet.java
index eca79d90bf..80981174d7 100644
--- a/src/main/java/baritone/utils/ToolSet.java
+++ b/src/main/java/baritone/utils/ToolSet.java
@@ -153,7 +153,7 @@ possible, this lets us make pathing depend on the actual tool to be used (if aut
BlockState blockState = b.defaultBlockState();
for (int i = 0; i < 9; i++) {
ItemStack itemStack = player.getInventory().getItem(i);
- if (!Baritone.settings().useSwordToMine.value && itemStack.is(ItemTags.SWORDS)) {
+ if (!Baritone.settings().useSwordToMine.value && itemStack.getItem().components().has(DataComponents.WEAPON)) {
continue;
}
diff --git a/src/main/java/baritone/utils/player/BaritonePlayerController.java b/src/main/java/baritone/utils/player/BaritonePlayerController.java
index 61ed357b3f..0a871b5e8a 100644
--- a/src/main/java/baritone/utils/player/BaritonePlayerController.java
+++ b/src/main/java/baritone/utils/player/BaritonePlayerController.java
@@ -67,8 +67,8 @@ public void resetBlockRemoving() {
}
@Override
- public void windowClick(int windowId, int slotId, int mouseButton, ContainerInput type, Player player) {
- mc.gameMode.handleContainerInput(windowId, slotId, mouseButton, type, player);
+ public void windowClick(int windowId, int slotId, int mouseButton, ContainerInput input, Player player) {
+ mc.gameMode.handleContainerInput(windowId, slotId, mouseButton, input, player);
}
@Override
diff --git a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java
index febe985d23..a4b806f15b 100644
--- a/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java
+++ b/src/main/java/baritone/utils/schematic/litematica/LitematicaHelper.java
@@ -19,6 +19,7 @@
import baritone.api.schematic.CompositeSchematic;
import baritone.api.schematic.IStaticSchematic;
+import baritone.api.utils.Pair;
import baritone.utils.schematic.StaticSchematic;
import fi.dy.masa.litematica.Litematica;
import fi.dy.masa.litematica.data.DataManager;
@@ -28,7 +29,6 @@
import fi.dy.masa.litematica.world.WorldSchematic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
-import net.minecraft.util.Tuple;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
@@ -93,7 +93,7 @@ private static Vec3i transform(Vec3i in, Mirror mirror, Rotation rotation) {
* @param i index of the Schematic in the schematic placement list.
* @return The transformed schematic and the position of its minimum corner
*/
- public static Tuple getSchematic(int i) {
+ public static Pair getSchematic(int i) {
SchematicPlacement placement = getPlacement(i);
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
@@ -129,7 +129,7 @@ public static Tuple getSchematic(int i) {
Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ);
composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ());
}
- return new Tuple<>(composite, placement.getOrigin().offset(minX, minY, minZ));
+ return new Pair<>(composite, placement.getOrigin().offset(minX, minY, minZ));
}
private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic {
diff --git a/src/main/java/baritone/utils/schematic/schematica/SchematicaHelper.java b/src/main/java/baritone/utils/schematic/schematica/SchematicaHelper.java
index 35b11c8e1d..44b493680e 100644
--- a/src/main/java/baritone/utils/schematic/schematica/SchematicaHelper.java
+++ b/src/main/java/baritone/utils/schematic/schematica/SchematicaHelper.java
@@ -18,10 +18,10 @@
package baritone.utils.schematic.schematica;
import baritone.api.schematic.IStaticSchematic;
+import baritone.api.utils.Pair;
import com.github.lunatrius.schematica.Schematica;
import com.github.lunatrius.schematica.proxy.ClientProxy;
import net.minecraft.core.BlockPos;
-import net.minecraft.util.Tuple;
import java.util.Optional;
public enum SchematicaHelper {
@@ -36,9 +36,9 @@ public static boolean isSchematicaPresent() {
}
}
- public static Optional> getOpenSchematic() {
+ public static Optional> getOpenSchematic() {
return Optional.ofNullable(ClientProxy.schematic)
- .map(world -> new Tuple<>(new SchematicAdapter(world), world.position));
+ .map(world -> new Pair<>(new SchematicAdapter(world), world.position));
}
}
diff --git a/src/test/java/baritone/behavior/LookBehaviorTest.java b/src/test/java/baritone/behavior/LookBehaviorTest.java
new file mode 100644
index 0000000000..ddf3ad4c48
--- /dev/null
+++ b/src/test/java/baritone/behavior/LookBehaviorTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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;
+
+import baritone.api.utils.RotationUtils;
+import org.junit.Test;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+public class LookBehaviorTest {
+
+ @Test
+ public void distanceScalingPreservesWorldOffset() {
+ double originalAngle = 1.0D;
+ double targetDistance = 4.5D;
+ double scaledAngle = LookBehavior.distanceScaledAngle(originalAngle, targetDistance);
+
+ double originalOffset = Math.tan(originalAngle * RotationUtils.DEG_TO_RAD);
+ double scaledOffset = Math.tan(scaledAngle * RotationUtils.DEG_TO_RAD) * targetDistance;
+
+ assertTrue(Math.abs(scaledAngle) < Math.abs(originalAngle));
+ assertEquals(originalOffset, scaledOffset, 1.0E-12D);
+ assertEquals(-scaledAngle, LookBehavior.distanceScaledAngle(-originalAngle, targetDistance), 1.0E-12D);
+ }
+
+ @Test
+ public void distanceScalingDoesNotAmplifyCloseOrUnknownTargets() {
+ double angle = 1.0D;
+
+ assertEquals(angle, LookBehavior.distanceScaledAngle(angle, 1.0D), 0.0D);
+ assertEquals(angle, LookBehavior.distanceScaledAngle(angle, 0.5D), 0.0D);
+ assertEquals(angle, LookBehavior.distanceScaledAngle(angle, Double.NaN), 0.0D);
+ assertEquals(0.0D, LookBehavior.distanceScaledAngle(0.0D, 4.5D), 0.0D);
+ }
+}
diff --git a/src/test/java/baritone/process/elytra/ElytraHitboxTest.java b/src/test/java/baritone/process/elytra/ElytraHitboxTest.java
deleted file mode 100644
index 83f8dbf2d4..0000000000
--- a/src/test/java/baritone/process/elytra/ElytraHitboxTest.java
+++ /dev/null
@@ -1,155 +0,0 @@
-/*
- * This file is part of Baritone.
- *
- * Baritone is free software: you can redistribute it and/or modify
- * it under the terms of the GNU Lesser General Public License as published by
- * the Free Software Foundation, either version 3 of the License, or
- * (at your option) any later version.
- *
- * Baritone is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with Baritone. If not, see .
- */
-
-package baritone.process.elytra;
-
-import net.minecraft.world.phys.AABB;
-import org.junit.Test;
-
-import static org.junit.Assert.assertTrue;
-
-/**
- * Tests for AABB collision volume behavior in elytra flight simulation.
- * Verifies that expandTowards produces correct swept volumes for all
- * motion vector directions, preventing both tunneling (#5049) and
- * hitbox collapse (#5047).
- */
-public class ElytraHitboxTest {
-
- /**
- * Test swept volume with positive motion vectors.
- * expandTowards(2, 0, 3) should extend the AABB in +X and +Z directions.
- */
- @Test
- public void testPositiveMotionVectors() {
- AABB hitbox = new AABB(0, 0, 0, 0.6, 1.8, 0.6);
- AABB expanded = hitbox.expandTowards(2, 0, 3);
-
- // Expanded box should cover start and end positions
- assertTrue("minX should be at or below start", expanded.minX <= hitbox.minX);
- assertTrue("maxX should be at or above end", expanded.maxX >= hitbox.maxX + 2);
- assertTrue("minZ should be at or below start", expanded.minZ <= hitbox.minZ);
- assertTrue("maxZ should be at or above end", expanded.maxZ >= hitbox.maxZ + 3);
-
- // Y should remain unchanged (zero motion)
- assertTrue("minY should be unchanged", expanded.minY == hitbox.minY);
- assertTrue("maxY should be unchanged", expanded.maxY == hitbox.maxY);
-
- // AABB invariants must hold
- assertTrue("minX < maxX", expanded.minX < expanded.maxX);
- assertTrue("minY < maxY", expanded.minY < expanded.maxY);
- assertTrue("minZ < maxZ", expanded.minZ < expanded.maxZ);
- }
-
- /**
- * Test swept volume with zero motion on one axis.
- * expandTowards(2, 0, 0) should only extend X, not Y or Z.
- */
- @Test
- public void testZeroMotionAxis() {
- AABB hitbox = new AABB(0, 0, 0, 0.6, 1.8, 0.6);
- AABB expanded = hitbox.expandTowards(2, 0, 0);
-
- // X should extend
- assertTrue("maxX should extend", expanded.maxX >= hitbox.maxX + 2);
-
- // Y and Z should remain unchanged
- assertTrue("minY unchanged", expanded.minY == hitbox.minY);
- assertTrue("maxY unchanged", expanded.maxY == hitbox.maxY);
- assertTrue("minZ unchanged", expanded.minZ == hitbox.minZ);
- assertTrue("maxZ unchanged", expanded.maxZ == hitbox.maxZ);
-
- // AABB invariants
- assertTrue("minX < maxX", expanded.minX < expanded.maxX);
- assertTrue("minY < maxY", expanded.minY < expanded.maxY);
- assertTrue("minZ < maxZ", expanded.minZ < expanded.maxZ);
- }
-
- /**
- * Test swept volume with negative motion vectors.
- * expandTowards(-2, -1, -3) should extend toward negative coordinates
- * without collapsing. This is the regression test for #5047.
- */
- @Test
- public void testNegativeMotionVectors() {
- AABB hitbox = new AABB(5, 10, 5, 5.6, 11.8, 5.6);
- AABB expanded = hitbox.expandTowards(-2, -1, -3);
-
- // Should extend toward negative
- assertTrue("minX should decrease", expanded.minX < hitbox.minX);
- assertTrue("minY should decrease", expanded.minY < hitbox.minY);
- assertTrue("minZ should decrease", expanded.minZ < hitbox.minZ);
-
- // AABB invariants MUST hold — this is the critical regression test
- assertTrue("minX < maxX (no collapse)", expanded.minX < expanded.maxX);
- assertTrue("minY < maxY (no collapse)", expanded.minY < expanded.maxY);
- assertTrue("minZ < maxZ (no collapse)", expanded.minZ < expanded.maxZ);
- }
-
- /**
- * Test swept volume with mixed positive/negative motion.
- * expandTowards(2, -1, 0) should handle mixed axes correctly.
- */
- @Test
- public void testMixedMotionVectors() {
- AABB hitbox = new AABB(0, 5, 0, 0.6, 6.8, 0.6);
- AABB expanded = hitbox.expandTowards(2, -1, 0);
-
- // X extends positive
- assertTrue("maxX extends positive", expanded.maxX >= hitbox.maxX + 2);
-
- // Y extends negative
- assertTrue("minY extends negative", expanded.minY < hitbox.minY);
-
- // Z unchanged
- assertTrue("minZ unchanged", expanded.minZ == hitbox.minZ);
- assertTrue("maxZ unchanged", expanded.maxZ == hitbox.maxZ);
-
- // AABB invariants
- assertTrue("minX < maxX", expanded.minX < expanded.maxX);
- assertTrue("minY < maxY", expanded.minY < expanded.maxY);
- assertTrue("minZ < maxZ", expanded.minZ < expanded.maxZ);
- }
-
- /**
- * Test that expandTowards with the inflate(0.01) safety padding
- * produces valid AABBs for all motion directions.
- * This matches the actual usage in ElytraBehavior.simulate().
- */
- @Test
- public void testExpandTowardsWithSafetyPadding() {
- AABB hitbox = new AABB(0, 0, 0, 0.6, 1.8, 0.6);
-
- // Positive motion
- AABB posMotion = hitbox.expandTowards(2, 0, 3).inflate(0.01);
- assertTrue("Positive: minX < maxX", posMotion.minX < posMotion.maxX);
- assertTrue("Positive: minY < maxY", posMotion.minY < posMotion.maxY);
- assertTrue("Positive: minZ < maxZ", posMotion.minZ < posMotion.maxZ);
-
- // Negative motion
- AABB negMotion = hitbox.expandTowards(-2, -1, -3).inflate(0.01);
- assertTrue("Negative: minX < maxX", negMotion.minX < negMotion.maxX);
- assertTrue("Negative: minY < maxY", negMotion.minY < negMotion.maxY);
- assertTrue("Negative: minZ < maxZ", negMotion.minZ < negMotion.maxZ);
-
- // Zero motion
- AABB zeroMotion = hitbox.expandTowards(0, 0, 0).inflate(0.01);
- assertTrue("Zero: minX < maxX", zeroMotion.minX < zeroMotion.maxX);
- assertTrue("Zero: minY < maxY", zeroMotion.minY < zeroMotion.maxY);
- assertTrue("Zero: minZ < maxZ", zeroMotion.minZ < zeroMotion.maxZ);
- }
-}
diff --git a/tweaker/build.gradle b/tweaker/build.gradle
index 105c9d99b2..d82bd6cac3 100644
--- a/tweaker/build.gradle
+++ b/tweaker/build.gradle
@@ -20,14 +20,14 @@ import baritone.gradle.task.ProguardTask
//import baritone.gradle.task.TweakerJsonAssembler
plugins {
- id "com.github.johnrengelman.shadow" version "8.1.1"
+ id "com.github.johnrengelman.shadow" version "8.0.0"
}
unimined.minecraft {
runs {
config("client") {
- mainClass = "net.minecraft.launchwrapper.Launch"
- args.addAll(["--tweakClass", "baritone.launch.tweaker.BaritoneTweaker"])
+ mainClass.set("net.minecraft.launchwrapper.Launch")
+ args("--tweakClass", "baritone.launch.tweaker.BaritoneTweaker")
}
}
}
@@ -97,7 +97,7 @@ jar {
}
task proguard(type: ProguardTask) {
- proguardVersion "7.9.1"
+ proguardVersion "7.8.2"
}
task createDist(type: CreateDistTask, dependsOn: proguard)
@@ -116,4 +116,4 @@ publishing {
repositories {
// Add repositories to publish to here.
}
-}
+}
\ No newline at end of file
diff --git a/tweaker/src/main/java/baritone/launch/tweaker/BaritoneTweaker.java b/tweaker/src/main/java/baritone/launch/tweaker/BaritoneTweaker.java
index 694aef5334..69fc89fe16 100644
--- a/tweaker/src/main/java/baritone/launch/tweaker/BaritoneTweaker.java
+++ b/tweaker/src/main/java/baritone/launch/tweaker/BaritoneTweaker.java
@@ -50,6 +50,6 @@ public void injectIntoClassLoader(LaunchClassLoader classLoader) {
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(obfuscation);
- Mixins.addConfiguration("mixins.baritone.json");
+ Mixins.addConfiguration("mixins.baritone-meteor.json");
}
}