Merge branch 'master' into builder

This commit is contained in:
Leijurv 2019-02-06 12:54:03 -08:00
commit 311cf81e8a
No known key found for this signature in database
GPG Key ID: 44A3EA646EADAC6A
35 changed files with 708 additions and 234 deletions

View File

@ -22,9 +22,9 @@ Baritone uses A*, with some modifications:
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment. The cost is decreased heavily, but is still positive (this won't cause it to backtrack if it doesn't need to). This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a> - **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment. The cost is decreased heavily, but is still positive (this won't cause it to backtrack if it doesn't need to). This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a>
- **Backtrack detection and pausing** While path calculation happens on a separate thread, the main game thread has access to the latest node considered, and the best path so far (those are rendered light blue and dark blue respectively). When the current best path (rendered dark blue) passes through the player's current position on the current path segment, path execution is paused (if it's safe to do so), because there's no point continuing forward if we're about to turn around and go back that same way. Note that the current best path as reported by the path calculation thread takes into account the incremental cost backoff system, so it's accurate to what the path calculation thread will actually pick once it finishes. - **Backtrack detection and pausing** While path calculation happens on a separate thread, the main game thread has access to the latest node considered, and the best path so far (those are rendered light blue and dark blue respectively). When the current best path (rendered dark blue) passes through the player's current position on the current path segment, path execution is paused (if it's safe to do so), because there's no point continuing forward if we're about to turn around and go back that same way. Note that the current best path as reported by the path calculation thread takes into account the incremental cost backoff system, so it's accurate to what the path calculation thread will actually pick once it finishes.
# Configuring Baritone # Chat control
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>.
To change 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 `pathTimeoutMS 250`). It's case insensitive. - [Baritone chat control usage](USAGE.md)
# Goals # Goals
The pathing goal can be set to any of these options: The pathing goal can be set to any of these options:

View File

@ -1,7 +1,9 @@
# Integration between Baritone and Impact # Integration between Baritone and Impact
Impact 4.4 has Baritone included. Impact 4.4 has Baritone included.
These instructions apply to Impact 4.3 (and potentially other "hacked clients"). These instructions apply to Impact 4.3.
For Forge follow the instructions in [Setup](SETUP.md).
To run Baritone on Vanilla, just follow the instructions in the README (it's `./gradlew runClient`). To run Baritone on Vanilla, just follow the instructions in the README (it's `./gradlew runClient`).
@ -18,11 +20,11 @@ There are two methods of acquiring a build of Baritone
### Official Release (Not always up to date) ### Official Release (Not always up to date)
https://github.com/cabaletta/baritone/releases https://github.com/cabaletta/baritone/releases
For Impact 4.3, there is no Baritone integration yet, so you will want `baritone-standalone-X.Y.Z.jar`. For Impact 4.3, there is no Baritone integration yet, so you will want `baritone-standalone-X.Y.Z.jar`. **For the rest of this guide, replace `X.Y.Z` with the actual numeric version you are using.**
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`. Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone . && docker run --rm cabaletta/baritone cat /code/dist/checksums.txt` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too). The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
### Building Baritone yourself ### Building Baritone yourself
You can either build Baritone through a command line or through IntelliJ's UI, information on that can be found [here](SETUP.md#building). You can either build Baritone through a command line or through IntelliJ's UI, information on that can be found [here](SETUP.md#building).
@ -36,7 +38,7 @@ putting baritone.
- ``cabaletta`` - ``cabaletta``
- ``baritone`` - ``baritone``
- ``X.Y.Z`` - ``X.Y.Z``
- Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder - Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder, renamed like so:
- The full path should look like ``<Minecraft>/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar`` - The full path should look like ``<Minecraft>/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar``
## Modifying the Impact Profile JSON to run baritone ## Modifying the Impact Profile JSON to run baritone
@ -79,10 +81,10 @@ The final step is "registering" the Baritone library with Impact, so that it loa
``` ```
- Now find the ``"minecraftArguments": "..."`` text near the top. - Now find the ``"minecraftArguments": "..."`` text near the top.
- At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like: - At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like:
- ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine"`` - ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweaker"``
- If you didn't close your launcher for this step, restart it now. - If you didn't close your launcher for this step, restart it now.
- You can now launch Impact 4.3 as normal, and Baritone should start up - You can now launch Impact 4.3 as normal, and Baritone should start up
## How to use Baritone ## How to use Baritone
Instructions on how to use Baritone are limited, and you may have to read a little bit of code (Really nothing much
just plain English), you can view that <a href="https://github.com/cabaletta/baritone#chat-control">here</a>. - [Baritone chat control usage](USAGE.md)

View File

@ -28,6 +28,8 @@ Baritone is the pathfinding system used in [Impact](https://impactdevelopment.gi
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/), This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths). the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Have committed at least once a day for the last 6 months =D 🦀
Here are some links to help to get started: Here are some links to help to get started:
- [Features](FEATURES.md) - [Features](FEATURES.md)
@ -39,9 +41,8 @@ Here are some links to help to get started:
- [Javadocs](https://baritone.leijurv.com/) - [Javadocs](https://baritone.leijurv.com/)
# Chat control # Chat control
[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java)
Quick start example: `thisway 1000` or `goal 70` to set the goal, `path` to actually start pathing. Also try `mine diamond_ore`. `cancel` to cancel. - [Baritone chat control usage](USAGE.md)
# API example # API example

View File

@ -1,5 +1,32 @@
# Setup # Setup
## Prebuilt
(not always completely up to date with latest features)
Download from the [Releases](https://github.com/cabaletta/baritone/releases)
The Forge releases can simply be added as a Forge mod.
If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar`
Previously (Baritone v1.1.2 and below), it was not fully compatible with the latest version of Forge. `freeLook` was broken in Forge 14.23.4.2744. Forge 14.23.4.2743 or **older** worked with Baritone v1.1.2 and lower. Newer versions of Forge "worked", sort of, but Baritone's movement became unreliable and `freeLook` must be off.
## Artifacts
Building Baritone will result in 5 artifacts created in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
- **Forge API**: Same as API, but packaged for Forge. This should be used where another mod has a Baritone integration.
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
- **Forge Standalone**: Same as Standalone, but packaged for Forge. This should be used when Baritone is your only Forge mod, or none of your other Forge mods integrate with Baritone.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
## More Info
To replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
Impact 4.4 **only** works with builds from the quite outdated `impact4.4-compat` branch. If you must have the latest Baritone features with Impact, and can't wait for 4.5, consider creating a standalone (non forge) build then adding it to Impact 4.**3** via the instructions in [Install](INSTALL.md).
## Build it yourself
- Clone or download Baritone - Clone or download Baritone
![Image](https://i.imgur.com/kbqBtoN.png) ![Image](https://i.imgur.com/kbqBtoN.png)
@ -65,15 +92,4 @@ $ gradlew build
![Image](https://i.imgur.com/PE6r9iN.png) ![Image](https://i.imgur.com/PE6r9iN.png)
- Right click on **build** and press **Run** - Double click on **build** to run it
## Artifacts
Building Baritone will result in 3 artifacts created in the ``dist`` directory.
- **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. This should be used in environments where there are no other mods present that would like to use Baritone's features.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
## More Info
To replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).

79
USAGE.md Normal file
View File

@ -0,0 +1,79 @@
(assuming you already have Baritone [set up](SETUP.md))
# Prefix
Baritone commands can by default be typed in the chatbox. However if you make a typo, like typing "gola 10000 10000" instead of goal it goes into public chat, which is bad.
Therefore you can use a prefix before your messages.
On Baritone v1.1.0 and newer: The prefix is `#` by default. Anything beginning with `#` isn't sent, and is only interpreted by Baritone.
For older than v1.1.0, `#` must be enabled by toggling on the `prefix` setting.
**Only** in Impact 4.4 is `.b` also a valid prefix. In 4.4, `#` does **not** work, neither does saying the commands directly in chat.
Other clients like Kami and Asuna have their own custom things (like `-path`), and can disable direct chat control entirely.
# Commands
**All** of these commands may need a prefix before them, as above ^.
`help` for (rudimentary) help. You can see what it says [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java#L53).
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.
Some common examples:
- `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 go to a certain coordinate
- `goal` to set the goal to your player's feet
- `goal clear` to clear the goal
- `cancel` or `stop` to stop everything
- `goto portal` or `goto ender_chest` or `goto block_type` to go to a block. (in Impact, `.goto` is an alias for `.b goto` for the most part)
- `mine diamond_ore` to mine diamond ore (turn on the setting `legitMine` to only mine ores that it can actually see. It will explore randomly around y=11 until it finds them.)
- `follow playerName` to follow a player. `follow` to follow the entity you're looking at (only works if it hitting range). `followplayers` to follow any players in range (combine with Kill Aura for a fun time).
- `save waypointName` to save a waypoint. `goto waypointName` to go to it.
- `axis` to go to an axis or diagonal axis at y=120 (`axisHeight` is a configurable setting, defaults to 120).
- `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.
- `render` to rerender the world in case `renderCachedChunks` is being glitchy
- `damn` daniel
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java).
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/">here</a> and navigate to Settings in the left sidebar.
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`
- `allowParkour`
- `allowParkourPlace`
- `renderCachedChunks` (and `cachedChunksOpacity`) <-- very fun but you need a beefy computer
- `avoidance`
- `legitMine`
- `followRadius`
# Troubleshooting / common issues
## Baritone highlights a block in green but gets completely stuck? Also I'm using Baritone with Future?
Baritone is trying to right click to place a block there, but it can't since there's a conflicting mixin. Baritone can't force click right click when Future is also installed. Left click **does work** on recent Baritone even with Future, however. For now, turn off `allowPlace` and Baritone will only search for paths that don't require placing blocks to complete. `allowBreak` can remain on.
## 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.
Second, make sure that you're using the prefix properly, and that chat control is enabled in the way you expect.
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?
These are custom commands that they added; those aren't from Baritone.
The equivalent you're looking for is `goal x z` then `path`.

View File

@ -16,7 +16,7 @@
*/ */
group 'baritone' group 'baritone'
version '1.0.0-hotfix-2' version '1.1.3'
buildscript { buildscript {
repositories { repositories {
@ -48,6 +48,7 @@ apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = '1.8'
compileJava { compileJava {
sourceCompatibility = targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = '1.8'
options.encoding = "UTF-8" // allow emoji in comments :^)
} }
sourceSets { sourceSets {
@ -94,13 +95,14 @@ dependencies {
} }
mixin { mixin {
defaultObfuscationEnv notch defaultObfuscationEnv searge
add sourceSets.launch, 'mixins.baritone.refmap.json' add sourceSets.launch, 'mixins.baritone.refmap.json'
} }
javadoc { javadoc {
options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error
options.linkSource true options.linkSource true
options.encoding "UTF-8" // allow emoji in comments :^)
source += sourceSets.api.allJava source += sourceSets.api.allJava
classpath += sourceSets.api.compileClasspath classpath += sourceSets.api.compileClasspath
} }
@ -111,6 +113,17 @@ jar {
reproducibleFileOrder = true reproducibleFileOrder = true
} }
jar {
manifest {
attributes(
'MixinConfigs': 'mixins.baritone.json',
'Implementation-Title': 'Baritone',
'Implementation-Version': version
)
}
}
task proguard(type: ProguardTask) { task proguard(type: ProguardTask) {
url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip' url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip'
extract 'proguard6.0.3/lib/proguard.jar' extract 'proguard6.0.3/lib/proguard.jar'

View File

@ -34,8 +34,6 @@ import java.util.List;
*/ */
class BaritoneGradleTask extends DefaultTask { class BaritoneGradleTask extends DefaultTask {
protected static final JsonParser PARSER = new JsonParser();
protected static final String protected static final String
PROGUARD_ZIP = "proguard.zip", PROGUARD_ZIP = "proguard.zip",
PROGUARD_JAR = "proguard.jar", PROGUARD_JAR = "proguard.jar",
@ -45,26 +43,28 @@ class BaritoneGradleTask extends DefaultTask {
PROGUARD_STANDALONE_CONFIG = "standalone.pro", PROGUARD_STANDALONE_CONFIG = "standalone.pro",
PROGUARD_EXPORT_PATH = "proguard_out.jar", PROGUARD_EXPORT_PATH = "proguard_out.jar",
VERSION_MANIFEST = "version_manifest.json",
TEMP_LIBRARY_DIR = "tempLibraries/", TEMP_LIBRARY_DIR = "tempLibraries/",
ARTIFACT_STANDARD = "%s-%s.jar", ARTIFACT_STANDARD = "%s-%s.jar",
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar", ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
ARTIFACT_API = "%s-api-%s.jar", ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar"; ARTIFACT_STANDALONE = "%s-standalone-%s.jar",
ARTIFACT_FORGE_API = "%s-api-forge-%s.jar",
ARTIFACT_FORGE_STANDALONE = "%s-standalone-forge-%s.jar";
protected String artifactName, artifactVersion; protected String artifactName, artifactVersion;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut; protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, artifactForgeApiPath, artifactForgeStandalonePath, proguardOut;
protected void verifyArtifacts() throws IllegalStateException { protected void verifyArtifacts() throws IllegalStateException {
this.artifactName = getProject().getName(); this.artifactName = getProject().getName();
this.artifactVersion = getProject().getVersion().toString(); this.artifactVersion = getProject().getVersion().toString();
this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD)); this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD));
this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED)); this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API)); this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE)); this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API));
this.artifactForgeStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_STANDALONE));
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH); this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
@ -95,8 +95,4 @@ class BaritoneGradleTask extends DefaultTask {
protected Path getBuildFile(String file) { protected Path getBuildFile(String file) {
return getRelativeFile("build/libs/" + file); return getRelativeFile("build/libs/" + file);
} }
protected JsonElement readJson(List<String> lines) {
return PARSER.parse(String.join("\n", lines));
}
} }

View File

@ -42,9 +42,11 @@ public class CreateDistTask extends BaritoneGradleTask {
super.verifyArtifacts(); super.verifyArtifacts();
// Define the distribution file paths // Define the distribution file paths
Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API)); Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE)); Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED)); Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
Path forgeApi = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_API));
Path forgeStandalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_STANDALONE));
// NIO will not automatically create directories // NIO will not automatically create directories
Path dir = getRelativeFile("dist/"); Path dir = getRelativeFile("dist/");
@ -53,12 +55,14 @@ public class CreateDistTask extends BaritoneGradleTask {
} }
// Copy build jars to dist/ // Copy build jars to dist/
Files.copy(this.artifactApiPath, api, REPLACE_EXISTING); Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING); Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING); Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
Files.copy(this.artifactForgeApiPath, forgeApi, REPLACE_EXISTING);
Files.copy(this.artifactForgeStandalonePath, forgeStandalone, REPLACE_EXISTING);
// Calculate all checksums and format them like "shasum" // Calculate all checksums and format them like "shasum"
List<String> shasum = Stream.of(api, standalone, unoptimized) List<String> shasum = Stream.of(api, forgeApi, standalone, forgeStandalone, unoptimized)
.map(path -> sha1(path) + " " + path.getFileName().toString()) .map(path -> sha1(path) + " " + path.getFileName().toString())
.collect(Collectors.toList()); .collect(Collectors.toList());

View File

@ -59,6 +59,8 @@ public class ProguardTask extends BaritoneGradleTask {
private List<String> requiredLibraries; private List<String> requiredLibraries;
private File mixin;
@TaskAction @TaskAction
protected void exec() throws Exception { protected void exec() throws Exception {
super.verifyArtifacts(); super.verifyArtifacts();
@ -79,7 +81,7 @@ public class ProguardTask extends BaritoneGradleTask {
Files.delete(this.artifactUnoptimizedPath); Files.delete(this.artifactUnoptimizedPath);
} }
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString()); Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Optional.empty());
} }
private void downloadProguard() throws Exception { private void downloadProguard() throws Exception {
@ -173,10 +175,16 @@ public class ProguardTask extends BaritoneGradleTask {
// Find the library jar file, and copy it to tempLibraries // Find the library jar file, and copy it to tempLibraries
for (File file : pair.getLeft().files(pair.getRight())) { for (File file : pair.getLeft().files(pair.getRight())) {
if (file.getName().startsWith(lib)) { if (file.getName().startsWith(lib)) {
if (lib.contains("mixin")) {
mixin = file;
}
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING); Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
} }
} }
} }
if (mixin == null) {
throw new IllegalStateException("Unable to find mixin jar");
}
} }
// a bunch of epic stuff to get the path to the cached jar // a bunch of epic stuff to get the path to the cached jar
@ -264,12 +272,14 @@ public class ProguardTask extends BaritoneGradleTask {
private void proguardApi() throws Exception { private void proguardApi() throws Exception {
runProguard(getTemporaryFile(PROGUARD_API_CONFIG)); runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString()); Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Optional.of(mixin));
} }
private void proguardStandalone() throws Exception { private void proguardStandalone() throws Exception {
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG)); runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString()); Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Optional.of(mixin));
} }
private void cleanup() { private void cleanup() {
@ -298,8 +308,8 @@ public class ProguardTask extends BaritoneGradleTask {
.start(); .start();
// We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this // We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
this.printOutputLog(p.getInputStream()); this.printOutputLog(p.getInputStream(), System.out);
this.printOutputLog(p.getErrorStream()); this.printOutputLog(p.getErrorStream(), System.err);
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception // Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
int exitCode = p.waitFor(); int exitCode = p.waitFor();
@ -308,12 +318,12 @@ public class ProguardTask extends BaritoneGradleTask {
} }
} }
private void printOutputLog(InputStream stream) { private void printOutputLog(InputStream stream, PrintStream outerr) {
new Thread(() -> { new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
System.out.println(line); outerr.println(line);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();

View File

@ -22,10 +22,7 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
@ -39,7 +36,7 @@ import java.util.stream.Collectors;
*/ */
public class Determinizer { public class Determinizer {
public static void determinize(String inputPath, String outputPath) throws IOException { public static void determinize(String inputPath, String outputPath, Optional<File> toInclude) throws IOException {
System.out.println("Running Determinizer"); System.out.println("Running Determinizer");
System.out.println(" Input path: " + inputPath); System.out.println(" Input path: " + inputPath);
System.out.println(" Output path: " + outputPath); System.out.println(" Output path: " + outputPath);
@ -66,10 +63,30 @@ public class Determinizer {
if (entry.getName().endsWith(".refmap.json")) { if (entry.getName().endsWith(".refmap.json")) {
JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject(); JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
jos.write(writeSorted(object).getBytes()); jos.write(writeSorted(object).getBytes());
} else if (entry.getName().equals("META-INF/MANIFEST.MF") && toInclude.isPresent()) { // only replace for forge jar
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
copy(jarFile.getInputStream(entry), cancer);
String manifest = new String(cancer.toByteArray());
if (!manifest.contains("baritone.launch.BaritoneTweaker")) {
throw new IllegalStateException("unable to replace");
}
manifest = manifest.replace("baritone.launch.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
jos.write(manifest.getBytes());
} else { } else {
copy(jarFile.getInputStream(entry), jos); copy(jarFile.getInputStream(entry), jos);
} }
} }
if (toInclude.isPresent()) {
try (JarFile mixin = new JarFile(toInclude.get())) {
for (JarEntry entry : mixin.stream().sorted(Comparator.comparing(JarEntry::getName)).collect(Collectors.toList())) {
if (entry.getName().startsWith("META-INF") && !entry.getName().startsWith("META-INF/services")) {
continue;
}
jos.putNextEntry(entry);
copy(mixin.getInputStream(entry), jos);
}
}
}
jos.finish(); jos.finish();
} }
} }

View File

@ -12,6 +12,9 @@
-flattenpackagehierarchy -flattenpackagehierarchy
-repackageclasses 'baritone' -repackageclasses 'baritone'
# lwjgl is weird
-dontwarn org.lwjgl.opengl.GL14
-keep class baritone.api.** { *; } # this is the keep api -keep class baritone.api.** { *; } # this is the keep api
# service provider needs these class names # service provider needs these class names

View File

@ -459,10 +459,34 @@ public final class Settings {
*/ */
public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false); public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
/**
* 😎 Render cached chunks as semitransparent. Doesn't work with OptiFine 😭
* <p>
* Can be very useful on servers with low render distance. After enabling, you may need to reload the world in order for it to have an effect
* (e.g. disconnect and reconnect, enter then exit the nether, die and respawn, etc). This may literally kill your FPS and CPU because
* every chunk gets recompiled twice as much as normal, since the cached version comes into range, then the normal one comes from the server for real.
* <p>
* Note that flowing water is cached as AVOID, which is rendered as lava. As you get closer, you may therefore see lava falls being replaced with water falls.
* <p>
* SOLID is rendered as stone in the overworld, netherrack in the nether, and end stone in the end
*/
public Setting<Boolean> renderCachedChunks = new Setting<>(false);
/**
* 0.0f = not visible, fully transparent
* 1.0f = fully opaque
*/
public Setting<Float> cachedChunksOpacity = new Setting<>(0.5f);
/**
* If true, Baritone will not allow you to left or right click while pathing
*/
public Setting<Boolean> suppressClicks = new Setting<>(false);
/** /**
* Whether or not to use the "#" command prefix * Whether or not to use the "#" command prefix
*/ */
public final Setting<Boolean> prefix = new Setting<>(false); public final Setting<Boolean> prefixControl = new Setting<>(true);
/** /**
* Don't stop walking forward when you need to break blocks in your way * Don't stop walking forward when you need to break blocks in your way
@ -485,6 +509,11 @@ public final class Settings {
*/ */
public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5); public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
/**
* When GetToBlock doesn't know any locations for the desired block, explore randomly instead of giving up.
*/
public final Setting<Boolean> exploreForBlocks = new Setting<>(true);
/** /**
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)? * While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
*/ */
@ -638,7 +667,7 @@ public final class Settings {
} }
} }
public class Setting<T> { public final class Setting<T> {
public T value; public T value;
public final T defaultValue; public final T defaultValue;
private String name; private String name;

View File

@ -38,11 +38,24 @@ public interface IPathingBehavior extends IBehavior {
* @return The estimated remaining ticks in the current segment. * @return The estimated remaining ticks in the current segment.
*/ */
default Optional<Double> ticksRemainingInSegment() { default Optional<Double> ticksRemainingInSegment() {
return ticksRemainingInSegment(true);
}
/**
* Returns the estimated remaining ticks in the current pathing
* segment. Given that the return type is an optional, {@link Optional#empty()}
* will be returned in the case that there is no current segment being pathed.
*
* @param includeCurrentMovement whether or not to include the entirety of the cost of the currently executing movement in the total
* @return The estimated remaining ticks in the current segment.
*/
default Optional<Double> ticksRemainingInSegment(boolean includeCurrentMovement) {
IPathExecutor current = getCurrent(); IPathExecutor current = getCurrent();
if (current == null) { if (current == null) {
return Optional.empty(); return Optional.empty();
} }
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); int start = includeCurrentMovement ? current.getPosition() : current.getPosition() + 1;
return Optional.of(current.getPath().ticksRemainingFrom(start));
} }
/** /**

View File

@ -0,0 +1,48 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ChunkRenderContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.chunk.RenderChunk;
import org.lwjgl.opengl.GL14;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*;
@Mixin(ChunkRenderContainer.class)
public class MixinChunkRenderContainer {
@Inject(
method = "preRenderChunk",
at = @At("HEAD")
)
private void preRenderChunk(RenderChunk renderChunkIn, CallbackInfo ci) {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.get());
GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
}
}
}

View File

@ -0,0 +1,56 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ChunkRenderWorker.class)
public abstract class MixinChunkRenderWorker {
@Shadow
protected abstract boolean isChunkExisting(BlockPos pos, World worldIn);
@Redirect(
method = "processTask",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/ChunkRenderWorker.isChunkExisting(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/World;)Z"
)
)
private boolean isChunkExisting(ChunkRenderWorker worker, BlockPos pos, World world) {
if (Baritone.settings().renderCachedChunks.get()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.isLoaded(pos.getX(), pos.getZ()) || this.isChunkExisting(pos, world);
}
}
return this.isChunkExisting(pos, world);
}
}

View File

@ -1,74 +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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.RotationMoveEvent;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
/**
* @author Brady
* @since 8/21/2018
*/
@Mixin(Entity.class)
public class MixinEntity {
@Shadow
public float rotationYaw;
/**
* Event called to override the movement direction when walking
*/
private RotationMoveEvent motionUpdateRotationEvent;
@Inject(
method = "moveRelative",
at = @At("HEAD")
)
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
// noinspection ConstantConditions
if (EntityPlayerSP.class.isInstance(this)) {
this.motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.motionUpdateRotationEvent);
}
}
@Redirect(
method = "moveRelative",
at = @At(
value = "FIELD",
opcode = GETFIELD,
target = "net/minecraft/entity/Entity.rotationYaw:F"
)
)
private float overrideYaw(Entity self) {
if (self instanceof EntityPlayerSP) {
return this.motionUpdateRotationEvent.getYaw();
}
return self.rotationYaw;
}
}

View File

@ -74,4 +74,25 @@ public abstract class MixinEntityLivingBase extends Entity {
} }
return self.rotationYaw; return self.rotationYaw;
} }
@Redirect(
method = "travel",
at = @At(
value = "INVOKE",
target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
)
)
private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
// noinspection ConstantConditions
if (!EntityPlayerSP.class.isInstance(this)) {
moveRelative(strafe, up, forward, friction);
return;
}
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
float originalYaw = this.rotationYaw;
this.rotationYaw = motionUpdateRotationEvent.getYaw();
this.moveRelative(strafe, up, forward, friction);
this.rotationYaw = originalYaw;
}
} }

View File

@ -18,6 +18,7 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.behavior.IPathingBehavior; import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.ChatEvent; import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.PlayerUpdateEvent;
@ -100,8 +101,16 @@ public class MixinEntityPlayerSP {
) )
private boolean isKeyDown(KeyBinding keyBinding) { private boolean isKeyDown(KeyBinding keyBinding) {
SprintStateEvent event = new SprintStateEvent(); SprintStateEvent event = new SprintStateEvent();
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
return event.getState() == null ? keyBinding.isKeyDown() : event.getState(); baritone.getGameEventHandler().onPlayerSprintState(event);
if (event.getState() != null) {
return event.getState();
}
if (baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
// hitting control shouldn't make all bots sprint
return false;
}
return keyBinding.isKeyDown();
} }
@Inject( @Inject(

View File

@ -17,6 +17,7 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
@ -45,6 +46,9 @@ public class MixinKeyBinding {
// only the primary baritone forces keys // only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this); Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null) { if (force != null) {
if (!force && !Baritone.settings().suppressClicks.get()) {
return;
}
cir.setReturnValue(force); // :sunglasses: cir.setReturnValue(force); // :sunglasses:
} }
} }
@ -57,9 +61,10 @@ public class MixinKeyBinding {
private void isPressed(CallbackInfoReturnable<Boolean> cir) { private void isPressed(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys // only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this); Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null && !force) { // <-- cursed if (force != null && !force && Baritone.settings().suppressClicks.get()) { // <-- cursed
if (pressTime > 0) { if (pressTime > 0) {
Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you"); Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you.");
Helper.HELPER.logDirect("Turn off the suppressClicks setting to allow clicking while pathing.");
pressTime--; pressTime--;
} }
cir.setReturnValue(force); // :sunglasses: cir.setReturnValue(force); // :sunglasses:

View File

@ -0,0 +1,88 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 1/29/2019
*/
@Mixin(RenderChunk.class)
public class MixinRenderChunk {
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.isEmpty()Z"
)
)
private boolean isEmpty(ChunkCache chunkCache) {
if (!chunkCache.isEmpty()) {
return false;
}
if (Baritone.settings().renderCachedChunks.get()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
BlockPos position = ((RenderChunk) (Object) this).getPosition();
// RenderChunk extends from -1,-1,-1 to +16,+16,+16
// then the constructor of ChunkCache extends it one more (presumably to get things like the connected status of fences? idk)
// so if ANY of the adjacent chunks are loaded, we are unempty
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (baritone.bsi.isLoaded(16 * dx + position.getX(), 16 * dz + position.getZ())) {
return false;
}
}
}
}
}
return true;
}
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
)
)
private IBlockState getBlockState(ChunkCache chunkCache, BlockPos pos) {
if (Baritone.settings().renderCachedChunks.get()) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.get0(pos);
}
}
return chunkCache.getBlockState(pos);
}
}

View File

@ -0,0 +1,46 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*;
@Mixin(RenderList.class)
public class MixinRenderList {
@Inject(
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void renderChunkLayer(CallbackInfo info) {
if (Baritone.settings().renderCachedChunks.get()) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
}
}

View File

@ -0,0 +1,46 @@
/*
* 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 <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.VboRenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.lwjgl.opengl.GL11.*;
@Mixin(VboRenderList.class)
public class MixinVboRenderList {
@Inject(
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void renderChunkLayer(CallbackInfo info) {
if (Baritone.settings().renderCachedChunks.get()) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
}
}

View File

@ -12,7 +12,8 @@
"MixinBlockPos", "MixinBlockPos",
"MixinChunkProviderClient", "MixinChunkProviderClient",
"MixinChunkProviderServer", "MixinChunkProviderServer",
"MixinEntity", "MixinChunkRenderContainer",
"MixinChunkRenderWorker",
"MixinEntityLivingBase", "MixinEntityLivingBase",
"MixinEntityPlayerSP", "MixinEntityPlayerSP",
"MixinEntityRenderer", "MixinEntityRenderer",
@ -20,6 +21,9 @@
"MixinMinecraft", "MixinMinecraft",
"MixinNetHandlerPlayClient", "MixinNetHandlerPlayClient",
"MixinNetworkManager", "MixinNetworkManager",
"MixinRenderChunk",
"MixinRenderList",
"MixinVboRenderList",
"MixinWorldClient" "MixinWorldClient"
] ]
} }

View File

@ -26,10 +26,7 @@ import baritone.behavior.*;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.event.GameEventHandler; import baritone.event.GameEventHandler;
import baritone.process.*; import baritone.process.*;
import baritone.utils.BaritoneAutoTest; import baritone.utils.*;
import baritone.utils.ExampleBaritoneControl;
import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
import baritone.utils.player.PrimaryPlayerContext; import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@ -88,6 +85,8 @@ public class Baritone implements IBaritone {
private IPlayerContext playerContext; private IPlayerContext playerContext;
private WorldProvider worldProvider; private WorldProvider worldProvider;
public BlockStateInterface bsi;
Baritone() { Baritone() {
this.gameEventHandler = new GameEventHandler(this); this.gameEventHandler = new GameEventHandler(this);
} }

View File

@ -155,7 +155,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
synchronized (pathCalcLock) { synchronized (pathCalcLock) {
if (inProgress != null) { if (inProgress != null) {
// we are calculating // we are calculating
// are we calculating the right thing though? // are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart(); BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good // if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing // but if current just failed, we should discard this calculation since it doesn't start from where we're standing
@ -201,8 +201,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// and this path doesn't get us all the way there // and this path doesn't get us all the way there
return; return;
} }
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 7.5 seconds or less left // and this path has 7.5 seconds or less left
// don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up
// if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own
logDebug("Path almost over. Planning ahead..."); logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false, context); findPathInNewThread(current.getPath().getDest(), false, context);

View File

@ -124,12 +124,13 @@ public final class ChunkPacker {
private static PathingBlockType getPathingBlockType(IBlockState state) { private static PathingBlockType getPathingBlockType(IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) { if ((block == Blocks.WATER || block == Blocks.FLOWING_WATER) && !MovementHelper.isFlowing(state)) {
// only water source blocks are plausibly usable, flowing water should be avoid // only water source blocks are plausibly usable, flowing water should be avoid
// FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
return PathingBlockType.WATER; return PathingBlockType.WATER;
} }
if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) { if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
return PathingBlockType.AVOID; return PathingBlockType.AVOID;
} }
// We used to do an AABB check here // We used to do an AABB check here

View File

@ -23,6 +23,7 @@ import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.event.listener.IGameEventListener; import baritone.api.event.listener.IGameEventListener;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
@ -46,6 +47,13 @@ public final class GameEventHandler implements IEventBus, Helper {
@Override @Override
public final void onTick(TickEvent event) { public final void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.IN) {
try {
baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true);
} catch (Exception ex) {}
} else {
baritone.bsi = null;
}
listeners.forEach(l -> l.onTick(event)); listeners.forEach(l -> l.onTick(event));
} }

View File

@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder; import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring; import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
@ -37,7 +36,7 @@ import java.util.Optional;
* *
* @author leijurv * @author leijurv
*/ */
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper { public final class AStarPathFinder extends AbstractNodeCostSearch {
private final Favoring favoring; private final Favoring favoring;
private final CalculationContext calcContext; private final CalculationContext calcContext;
@ -55,14 +54,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
startNode.combinedCost = startNode.estimatedCostToGoal; startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet(); BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode); openSet.insert(startNode);
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];
for (int i = 0; i < bestHeuristicSoFar.length; i++) { for (int i = 0; i < bestHeuristicSoFar.length; i++) {
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal; bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode; bestSoFar[i] = startNode;
} }
MutableMoveResult res = new MutableMoveResult(); MutableMoveResult res = new MutableMoveResult();
Favoring favored = favoring;
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder()); BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.get(); boolean slowPath = Baritone.settings().slowPath.get();
@ -75,10 +72,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int numNodes = 0; int numNodes = 0;
int numMovementsConsidered = 0; int numMovementsConsidered = 0;
int numEmptyChunk = 0; int numEmptyChunk = 0;
boolean favoring = !favored.isEmpty(); boolean isFavoring = !favoring.isEmpty();
int timeCheckInterval = 1 << 6; int timeCheckInterval = 1 << 6;
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get(); double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0;
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) { while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond) if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds) long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
@ -136,21 +133,13 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset)); throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
} }
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z); long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (favoring) { if (isFavoring) {
// see issue #18 // see issue #18
actionCost *= favored.calculate(hashCode); actionCost *= favoring.calculate(hashCode);
} }
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode); PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost; double tentativeCost = currentNode.cost + actionCost;
if (tentativeCost < neighbor.cost) { if (neighbor.cost - tentativeCost > minimumImprovement) {
double improvementBy = neighbor.cost - tentativeCost;
// there are floating point errors caused by random combinations of traverse and diagonal over a flat area
// that means that sometimes there's a cost improvement of like 10 ^ -16
// it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
if (improvementBy < 0.01 && minimumImprovementRepropagation) {
// who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
continue;
}
neighbor.previous = currentNode; neighbor.previous = currentNode;
neighbor.cost = tentativeCost; neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
@ -159,15 +148,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} else { } else {
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
} }
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < COEFFICIENTS.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (heuristic < bestHeuristicSoFar[i]) { if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
continue;
}
bestHeuristicSoFar[i] = heuristic; bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor; bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) { if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false; failing = false;
} }
} }
@ -182,28 +168,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
System.out.println("Open set size: " + openSet.size()); System.out.println("Open set size: " + openSet.size());
System.out.println("PathNode map size: " + mapSize()); System.out.println("PathNode map size: " + mapSize());
System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second"); System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
double bestDist = 0; Optional<IPath> result = bestSoFar(true, numNodes);
for (int i = 0; i < bestSoFar.length; i++) { if (result.isPresent()) {
if (bestSoFar[i] == null) { logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
continue;
}
double dist = getDistFromStartSq(bestSoFar[i]);
if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, calcContext));
}
} }
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks"); return result;
logDebug("No path found =(");
return Optional.empty();
} }
} }

View File

@ -34,7 +34,7 @@ import java.util.Optional;
* *
* @author leijurv * @author leijurv
*/ */
public abstract class AbstractNodeCostSearch implements IPathFinder { public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
protected final int startX; protected final int startX;
protected final int startY; protected final int startY;
@ -53,7 +53,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
protected PathNode mostRecentConsidered; protected PathNode mostRecentConsidered;
protected PathNode[] bestSoFar; protected final PathNode[] bestSoFar = new PathNode[COEFFICIENTS.length];
private volatile boolean isFinished; private volatile boolean isFinished;
@ -63,13 +63,23 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so * This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts). * long it was easier as a Google Doc (because I could insert charts).
* *
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a> * @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">here</a>
*/ */
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10};
/** /**
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering. * If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
*/ */
protected final static double MIN_DIST_PATH = 5; protected static final double MIN_DIST_PATH = 5;
/**
* there are floating point errors caused by random combinations of traverse and diagonal over a flat area
* that means that sometimes there's a cost improvement of like 10 ^ -16
* it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
* <p>
* who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
*/
protected static final double MIN_IMPROVEMENT = 0.01;
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) { AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
this.startX = startX; this.startX = startX;
@ -170,25 +180,43 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context)); return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
} }
protected int mapSize() { @Override
return map.size(); public Optional<IPath> bestPathSoFar() {
return bestSoFar(false, 0);
} }
@Override protected Optional<IPath> bestSoFar(boolean logInfo, int numNodes) {
public Optional<IPath> bestPathSoFar() { // TODO cleanup code duplication between here and AStarPathFinder
if (startNode == null || bestSoFar == null) { if (startNode == null || bestSoFar == null) {
return Optional.empty(); return Optional.empty();
} }
for (int i = 0; i < bestSoFar.length; i++) { double bestDist = 0;
for (int i = 0; i < COEFFICIENTS.length; i++) {
if (bestSoFar[i] == null) { if (bestSoFar[i] == null) {
continue; continue;
} }
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared double dist = getDistFromStartSq(bestSoFar[i]);
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context)); if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
if (logInfo) {
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
logDebug("A* cost coefficient " + COEFFICIENTS[i]);
}
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context));
} }
} }
// instead of returning bestSoFar[0], be less misleading // instead of returning bestSoFar[0], be less misleading
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen // if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
if (logInfo) {
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
logDebug("No path found =(");
}
return Optional.empty(); return Optional.empty();
} }
@ -205,4 +233,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public BetterBlockPos getStart() { public BetterBlockPos getStart() {
return new BetterBlockPos(startX, startY, startZ); return new BetterBlockPos(startX, startY, startZ);
} }
protected int mapSize() {
return map.size();
}
} }

View File

@ -114,7 +114,7 @@ public class MovementDiagonal extends Movement {
return; return;
} }
IBlockState pb3 = context.get(destX, y + 1, z); IBlockState pb3 = context.get(destX, y + 1, z);
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) { if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3.getBlock()))) {
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction // at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
return; return;
} }
@ -123,7 +123,7 @@ public class MovementDiagonal extends Movement {
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible // and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
return; return;
} }
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) { if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1.getBlock()))) {
// and now that option B is fully calculated, see if we can edge around that way // and now that option B is fully calculated, see if we can edge around that way
return; return;
} }

View File

@ -189,6 +189,11 @@ public class MovementParkour extends Movement {
logDebug("Pausing parkour since hand is active"); logDebug("Pausing parkour since hand is active");
return state; return state;
} }
if (ctx.playerFeet().y < src.y) {
// we have fallen
logDebug("sorry");
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (dist >= 4) { if (dist >= 4) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }

View File

@ -282,6 +282,8 @@ public class MovementTraverse extends Movement {
} }
return state; return state;
} }
default:
break;
} }
if (whereAmI.equals(dest)) { if (whereAmI.equals(dest)) {
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of // If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of

View File

@ -249,6 +249,8 @@ public class PathExecutor implements IPathExecutor, Helper {
return true; return true;
} }
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) { if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) {
// don't do this if the movement was calculated while loaded
// that means that this isn't a cache error, it's just part of the path interfering with a later part
logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling."); logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling.");
cancel(); cancel();
return true; return true;
@ -377,21 +379,21 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
private boolean shouldSprintNextTick() { private boolean shouldSprintNextTick() {
boolean requested = behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT);
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint // first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint) { if (!new CalculationContext(behavior.baritone).canSprint) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return false; return false;
} }
// if the movement requested sprinting, then we're done // if the movement requested sprinting, then we're done
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) { if (requested) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return true; return true;
} }
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it // however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
IMovement current = path.movements().get(pathPosition); IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend) { if (current instanceof MovementDescend) {

View File

@ -18,10 +18,7 @@
package baritone.process; package baritone.process;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.*;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.process.IGetToBlockProcess; import baritone.api.process.IGetToBlockProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
@ -44,6 +41,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
private Block gettingTo; private Block gettingTo;
private List<BlockPos> knownLocations; private List<BlockPos> knownLocations;
private BlockPos start;
private int tickCount = 0; private int tickCount = 0;
@ -55,6 +53,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
public void getToBlock(Block block) { public void getToBlock(Block block) {
onLostControl(); onLostControl();
gettingTo = block; gettingTo = block;
start = ctx.playerFeet();
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
@ -69,6 +68,14 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
if (knownLocations.isEmpty()) { if (knownLocations.isEmpty()) {
if (Baritone.settings().exploreForBlocks.get()) {
return new PathingCommand(new GoalRunAway(1, start) {
@Override
public boolean isInGoal(int x, int y, int z) {
return false;
}
}, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
}
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock"); logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
if (isSafeToCancel) { if (isSafeToCancel) {
onLostControl(); onLostControl();
@ -106,6 +113,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
public void onLostControl() { public void onLostControl() {
gettingTo = null; gettingTo = null;
knownLocations = null; knownLocations = null;
start = null;
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
} }

View File

@ -24,6 +24,7 @@ import baritone.api.cache.IWaypoint;
import baritone.api.event.events.ChatEvent; import baritone.api.event.events.ChatEvent;
import baritone.api.pathing.goals.*; import baritone.api.pathing.goals.*;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil; import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior; import baritone.behavior.Behavior;
import baritone.behavior.PathingBehavior; import baritone.behavior.PathingBehavior;
@ -36,6 +37,7 @@ import baritone.process.CustomGoalProcess;
import baritone.utils.pathing.SegmentedCalculator; import baritone.utils.pathing.SegmentedCalculator;
import baritone.utils.schematic.AirSchematic; import baritone.utils.schematic.AirSchematic;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@ -86,21 +88,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
@Override @Override
public void onSendChatMessage(ChatEvent event) { public void onSendChatMessage(ChatEvent event) {
String msg = event.getMessage();
if (Baritone.settings().prefixControl.get() && msg.startsWith(COMMAND_PREFIX)) {
if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
logDirect("Invalid command");
}
event.cancel(); // always cancel if using prefixControl
return;
}
if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) { if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) {
return; return;
} }
String msg = event.getMessage(); if (runCommand(msg)) {
if (Baritone.settings().prefix.get()) { event.cancel();
if (msg.startsWith(COMMAND_PREFIX)) {
if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
logDirect("Invalid command");
}
event.cancel(); // always cancel if using prefix
}
} else {
if (runCommand(msg)) {
event.cancel();
}
} }
} }
@ -228,6 +228,15 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
return true; return true;
} }
if (msg.equals("version")) {
String version = ExampleBaritoneControl.class.getPackage().getImplementationVersion();
if (version == null) {
logDirect("No version detected. Either dev environment or broken install.");
} else {
logDirect("You are using Baritone v" + version);
}
return true;
}
if (msg.equals("repack") || msg.equals("rescan")) { if (msg.equals("repack") || msg.equals("rescan")) {
ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider(); ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider();
int playerChunkX = ctx.playerFeet().getX() >> 4; int playerChunkX = ctx.playerFeet().getX() >> 4;
@ -325,6 +334,12 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("Baritone settings reset"); logDirect("Baritone settings reset");
return true; return true;
} }
if (msg.equals("render")) {
BetterBlockPos pf = ctx.playerFeet();
Minecraft.getMinecraft().renderGlobal.markBlockRangeForRenderUpdate(pf.x - 500, pf.y - 500, pf.z - 500, pf.x + 500, pf.y + 500, pf.z + 500);
logDirect("okay");
return true;
}
if (msg.equals("echest")) { if (msg.equals("echest")) {
Optional<List<ItemStack>> contents = baritone.getMemoryBehavior().echest(); Optional<List<ItemStack>> contents = baritone.getMemoryBehavior().echest();
if (contents.isPresent()) { if (contents.isPresent()) {