Compare commits
94 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
78b626af23 | ||
|
|
046de84360 | ||
|
|
ca48dabcc7 | ||
|
|
9880a4e948 | ||
|
|
cb589219d8 | ||
|
|
6fff4c5254 | ||
|
|
4049c116d9 | ||
|
|
b720742f53 | ||
|
|
c1af050fa6 | ||
|
|
39f415d4be | ||
|
|
4590b9f6da | ||
|
|
ee6e0b1784 | ||
|
|
820c108548 | ||
|
|
239bb14e3a | ||
|
|
1bd7c8455f | ||
|
|
6986f179cd | ||
|
|
28af41b789 | ||
|
|
36bdaa99ec | ||
|
|
1ee44024b2 | ||
|
|
cd926283b3 | ||
|
|
04d210bd8b | ||
|
|
38895beb5d | ||
|
|
3fdc4d6ee0 | ||
|
|
baf27363aa | ||
|
|
da137f35de | ||
|
|
feeeae5918 | ||
|
|
02a04773c6 | ||
|
|
7e7b9f4fdb | ||
|
|
85e4a57c76 | ||
|
|
6fd7b2a7f3 | ||
|
|
24be1d0ff3 | ||
|
|
2867e0626f | ||
|
|
f0c3e59a6f | ||
|
|
4e11d92d19 | ||
|
|
07eee481cb | ||
|
|
8f146d1a2b | ||
|
|
1cc03e3aca | ||
|
|
023822b5d9 | ||
|
|
41ffd4455d | ||
|
|
810b92fbad | ||
|
|
6db31cbe74 | ||
|
|
b55a102d37 | ||
|
|
f338cdd2e5 | ||
|
|
76365a4564 | ||
|
|
109cffc3de | ||
|
|
c67339dc42 | ||
|
|
f56766be26 | ||
|
|
b1e1cc43e0 | ||
|
|
13aaec07cd | ||
|
|
08b9eab9f3 | ||
|
|
09ac3c615c | ||
|
|
19ce1cf4a7 | ||
|
|
d58ad6f68f | ||
|
|
866648192b | ||
|
|
3184eaf595 | ||
|
|
b12c2ea62f | ||
|
|
bcb95c55c9 | ||
|
|
229739575c | ||
|
|
4b76af2487 | ||
|
|
c383186808 | ||
|
|
2f602f8718 | ||
|
|
015462eddb | ||
|
|
de6d6c8714 | ||
|
|
1b2304146b | ||
|
|
f28cdc531f | ||
|
|
2aa4770b45 | ||
|
|
1d931a4bb6 | ||
|
|
9094c712d6 | ||
|
|
40a3177ae7 | ||
|
|
8ef89a8c80 | ||
|
|
ceb9ad9aa8 | ||
|
|
dec1877123 | ||
|
|
34aa7cb6b5 | ||
|
|
730ebb0070 | ||
|
|
c4a3820c6a | ||
|
|
d4a846a672 | ||
|
|
a125170840 | ||
|
|
d5d1d65bf3 | ||
|
|
fb45d73406 | ||
|
|
5ec3971380 | ||
|
|
63b6169475 | ||
|
|
ab0d713882 | ||
|
|
19661cc99c | ||
|
|
d58656571a | ||
|
|
4900c76752 | ||
|
|
d899ff7f7b | ||
|
|
36651553fe | ||
|
|
d9596fcac9 | ||
|
|
aa7b77b413 | ||
|
|
b3f06c6fac | ||
|
|
3483be4bed | ||
|
|
d7a0d26fd2 | ||
|
|
90666cdfc1 | ||
|
|
3072de610c |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -2,6 +2,7 @@
|
||||
**/*.swp
|
||||
|
||||
run/
|
||||
autotest/
|
||||
|
||||
# Gradle
|
||||
build/
|
||||
|
||||
@@ -6,9 +6,7 @@ services:
|
||||
- docker
|
||||
|
||||
install:
|
||||
- sudo apt-get update
|
||||
- sudo apt-get install jshon
|
||||
- docker build -t cabaletta/baritone .
|
||||
- travis_retry docker build -t cabaletta/baritone .
|
||||
|
||||
script:
|
||||
- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; sh scripts/build.sh; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient"
|
||||
|
||||
@@ -15,10 +15,10 @@ RUN apt install -qq --force-yes mesa-utils libgl1-mesa-glx libxcursor1 libxrandr
|
||||
|
||||
RUN apt install -qq --force-yes unzip wget
|
||||
|
||||
ADD . /code
|
||||
|
||||
RUN echo "\nrunClient {\nargs \"--width\",\"128\",\"--height\",\"128\"\n}" >> /code/build.gradle
|
||||
COPY . /code
|
||||
|
||||
# this .deb is specially patched to support lwjgl
|
||||
# source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173
|
||||
RUN dpkg -i /code/scripts/xvfb_1.16.4-1_amd64.deb
|
||||
|
||||
WORKDIR /code
|
||||
|
||||
@@ -19,7 +19,7 @@ Baritone uses a modified version of A*.
|
||||
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment slightly, as a tiebreaker. 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>
|
||||
|
||||
# Configuring Baritone
|
||||
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/Settings.java">here</a>.
|
||||
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.
|
||||
|
||||
# Goals
|
||||
|
||||
@@ -11,9 +11,12 @@ There are some basic steps to getting Baritone setup with Impact.
|
||||
## Acquiring a build of Baritone
|
||||
There are 3 methods of acquiring a build of Baritone (While it is still in development)
|
||||
|
||||
### Official Build (Not always up to date)
|
||||
Download the "official" jar (as of commit <a href="https://github.com/cabaletta/baritone/commit/61cf103df451a5aafa6bfbe5ed089043212f0b42">61cf103</a>,
|
||||
built on September 24) from <a href="https://www.dropbox.com/s/imc6xwwpwsh3i0y/baritone-1.0.0.jar?dl=0">here</a>.
|
||||
### Official Release (Not always up to date)
|
||||
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`.
|
||||
|
||||
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`.
|
||||
|
||||
### Building Baritone yourself
|
||||
There are a few steps to this
|
||||
|
||||
@@ -3,12 +3,7 @@
|
||||
[](LICENSE)
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
|
||||
<!---
|
||||
Plutie's jenkins is dead right now, so here's the old badge that was used:
|
||||
[](https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/)
|
||||
--->
|
||||
|
||||
Unofficial Jenkins: []()
|
||||
Unofficial Jenkins: [](https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/)
|
||||
|
||||
A Minecraft pathfinder bot. 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 [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
@@ -73,4 +68,4 @@ Magic. (Hours of [Leijurv](https://github.com/leijurv) enduring excruciating pai
|
||||
|
||||
## Why is it called Baritone?
|
||||
|
||||
It's named for FitMC's deep sultry voice.
|
||||
It's named for FitMC's deep sultry voice.
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '0.0.3'
|
||||
version '0.0.6'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
||||
@@ -10,9 +10,11 @@ cat ../../scripts/proguard.pro | grep -v "this is the rt jar" | grep -v "\-injar
|
||||
echo "-libraryjars '$(java -verbose 2>/dev/null | sed -ne '1 s/\[Opened \(.*\)\]/\1/p')'" >> api.pro # insert correct rt.jar location
|
||||
tail api.pro # debug, print out what the previous two commands generated
|
||||
cat api.pro | grep -v "\-keep class baritone.api" > standalone.pro # standalone doesn't keep baritone api
|
||||
wget -nv https://www.dropbox.com/s/zmc2l3jnwdvzvak/tempLibraries.zip?dl=1 # i'm sorry
|
||||
mv tempLibraries.zip?dl=1 tempLibraries.zip
|
||||
unzip tempLibraries.zip
|
||||
|
||||
#instead of downloading these jars from my dropbox in a zip, just assume gradle's already got them for us
|
||||
mkdir -p tempLibraries
|
||||
cat ../../scripts/proguard.pro | grep tempLibraries | grep .jar | cut -d "/" -f 2- | cut -d "'" -f -1 | xargs -n1 -I{} bash -c "find ~/.gradle -name {}" | tee /dev/stderr | xargs -n1 -I{} cp {} tempLibraries
|
||||
|
||||
mkdir ../../dist
|
||||
java -jar ../../proguard6.0.3/lib/proguard.jar @api.pro
|
||||
mv Obfuscated/baritone-$VERSION.jar ../../dist/baritone-api-$VERSION.jar
|
||||
|
||||
29
scripts/proguard.pro
vendored
29
scripts/proguard.pro
vendored
@@ -1,4 +1,4 @@
|
||||
-injars baritone-0.0.2.jar
|
||||
-injars baritone-0.0.6.jar
|
||||
-outjars Obfuscated
|
||||
|
||||
|
||||
@@ -12,14 +12,12 @@
|
||||
-overloadaggressively
|
||||
-dontusemixedcaseclassnames
|
||||
|
||||
# instead of obfing to a, b, c, obf to baritone.a, baritone.b, baritone.c so as to not conflict with minecraft's obfd classes
|
||||
# instead of renaming to a, b, c, rename to baritone.a, baritone.b, baritone.c so as to not conflict with minecraft's obfd classes
|
||||
-flattenpackagehierarchy
|
||||
-repackageclasses 'baritone'
|
||||
|
||||
#-keep class baritone.behavior.** { *; }
|
||||
-keep class baritone.api.** { *; }
|
||||
#-keep class baritone.* { *; }
|
||||
#-keep class baritone.pathing.goals.** { *; }
|
||||
-keep class baritone.BaritoneProvider
|
||||
|
||||
# setting names are reflected from field names, so keep field names
|
||||
-keepclassmembers class baritone.api.Settings {
|
||||
@@ -32,7 +30,7 @@
|
||||
# copy all necessary libraries into tempLibraries to build
|
||||
-libraryjars '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/rt.jar' # this is the rt jar
|
||||
|
||||
-libraryjars 'tempLibraries/1.12.2.jar'
|
||||
-libraryjars 'tempLibraries/minecraft-1.12.2.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/authlib-1.5.25.jar'
|
||||
-libraryjars 'tempLibraries/codecjorbis-20101023.jar'
|
||||
@@ -48,22 +46,25 @@
|
||||
-libraryjars 'tempLibraries/httpclient-4.3.3.jar'
|
||||
-libraryjars 'tempLibraries/httpcore-4.3.2.jar'
|
||||
-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar'
|
||||
-libraryjars 'tempLibraries/java-objc-bridge-1.0.0-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/java-objc-bridge-1.0.0.jar'
|
||||
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
|
||||
-libraryjars 'tempLibraries/jinput-platform-2.0.5-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/jna-4.4.0.jar'
|
||||
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
|
||||
-libraryjars 'tempLibraries/jsr305-3.0.1-sources.jar'
|
||||
-libraryjars 'tempLibraries/jsr305-3.0.1.jar'
|
||||
-libraryjars 'tempLibraries/jutils-1.0.0.jar'
|
||||
-libraryjars 'tempLibraries/libraryjavasound-20101123.jar'
|
||||
-libraryjars 'tempLibraries/librarylwjglopenal-20100824.jar'
|
||||
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/log4j-core-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.jar'
|
||||
|
||||
# linux / travis
|
||||
-libraryjars 'tempLibraries/lwjgl-2.9.4-nightly-20150209.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl_util-2.9.4-nightly-20150209.jar'
|
||||
|
||||
# mac
|
||||
#-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.jar'
|
||||
#-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
|
||||
-libraryjars 'tempLibraries/oshi-core-1.1.jar'
|
||||
-libraryjars 'tempLibraries/patchy-1.1.jar'
|
||||
@@ -72,8 +73,8 @@
|
||||
-libraryjars 'tempLibraries/soundsystem-20120107.jar'
|
||||
-libraryjars 'tempLibraries/text2speech-1.10.3.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/mixin-0.7.8-SNAPSHOT.jar'
|
||||
-libraryjars 'tempLibraries/launchwrapper-1.12.jar'
|
||||
-libraryjars 'tempLibraries/mixin-0.7.11-SNAPSHOT.jar'
|
||||
-libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist?
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -20,6 +20,9 @@ package baritone.api;
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
|
||||
import java.util.Iterator;
|
||||
import java.util.ServiceLoader;
|
||||
|
||||
/**
|
||||
* API exposure for various things implemented in Baritone.
|
||||
* <p>
|
||||
@@ -28,37 +31,37 @@ import baritone.api.cache.IWorldProvider;
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public class BaritoneAPI {
|
||||
public final class BaritoneAPI {
|
||||
|
||||
// General
|
||||
private static final Settings settings = new Settings();
|
||||
private static IWorldProvider worldProvider;
|
||||
private final static IBaritoneProvider baritone;
|
||||
private final static Settings settings;
|
||||
|
||||
// Behaviors
|
||||
private static IFollowBehavior followBehavior;
|
||||
private static ILookBehavior lookBehavior;
|
||||
private static IMemoryBehavior memoryBehavior;
|
||||
private static IMineBehavior mineBehavior;
|
||||
private static IPathingBehavior pathingBehavior;
|
||||
static {
|
||||
ServiceLoader<IBaritoneProvider> baritoneLoader = ServiceLoader.load(IBaritoneProvider.class);
|
||||
Iterator<IBaritoneProvider> instances = baritoneLoader.iterator();
|
||||
baritone = instances.next();
|
||||
|
||||
settings = new Settings();
|
||||
}
|
||||
|
||||
public static IFollowBehavior getFollowBehavior() {
|
||||
return followBehavior;
|
||||
return baritone.getFollowBehavior();
|
||||
}
|
||||
|
||||
public static ILookBehavior getLookBehavior() {
|
||||
return lookBehavior;
|
||||
return baritone.getLookBehavior();
|
||||
}
|
||||
|
||||
public static IMemoryBehavior getMemoryBehavior() {
|
||||
return memoryBehavior;
|
||||
return baritone.getMemoryBehavior();
|
||||
}
|
||||
|
||||
public static IMineBehavior getMineBehavior() {
|
||||
return mineBehavior;
|
||||
return baritone.getMineBehavior();
|
||||
}
|
||||
|
||||
public static IPathingBehavior getPathingBehavior() {
|
||||
return pathingBehavior;
|
||||
return baritone.getPathingBehavior();
|
||||
}
|
||||
|
||||
public static Settings getSettings() {
|
||||
@@ -66,34 +69,6 @@ public class BaritoneAPI {
|
||||
}
|
||||
|
||||
public static IWorldProvider getWorldProvider() {
|
||||
return worldProvider;
|
||||
return baritone.getWorldProvider();
|
||||
}
|
||||
|
||||
/**
|
||||
* FOR INTERNAL USE ONLY
|
||||
*/
|
||||
public static void registerProviders(
|
||||
IWorldProvider worldProvider
|
||||
) {
|
||||
BaritoneAPI.worldProvider = worldProvider;
|
||||
}
|
||||
|
||||
/**
|
||||
* FOR INTERNAL USE ONLY
|
||||
*/
|
||||
// @formatter:off
|
||||
public static void registerDefaultBehaviors(
|
||||
IFollowBehavior followBehavior,
|
||||
ILookBehavior lookBehavior,
|
||||
IMemoryBehavior memoryBehavior,
|
||||
IMineBehavior mineBehavior,
|
||||
IPathingBehavior pathingBehavior
|
||||
) {
|
||||
BaritoneAPI.followBehavior = followBehavior;
|
||||
BaritoneAPI.lookBehavior = lookBehavior;
|
||||
BaritoneAPI.memoryBehavior = memoryBehavior;
|
||||
BaritoneAPI.mineBehavior = mineBehavior;
|
||||
BaritoneAPI.pathingBehavior = pathingBehavior;
|
||||
}
|
||||
// @formatter:on
|
||||
}
|
||||
|
||||
70
src/api/java/baritone/api/IBaritoneProvider.java
Normal file
70
src/api/java/baritone/api/IBaritoneProvider.java
Normal file
@@ -0,0 +1,70 @@
|
||||
/*
|
||||
* 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.api;
|
||||
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
*/
|
||||
public interface IBaritoneProvider {
|
||||
|
||||
/**
|
||||
* @see IFollowBehavior
|
||||
*
|
||||
* @return The {@link IFollowBehavior} instance
|
||||
*/
|
||||
IFollowBehavior getFollowBehavior();
|
||||
|
||||
/**
|
||||
* @see ILookBehavior
|
||||
*
|
||||
* @return The {@link ILookBehavior} instance
|
||||
*/
|
||||
ILookBehavior getLookBehavior();
|
||||
|
||||
/**
|
||||
* @see IMemoryBehavior
|
||||
*
|
||||
* @return The {@link IMemoryBehavior} instance
|
||||
*/
|
||||
IMemoryBehavior getMemoryBehavior();
|
||||
|
||||
/**
|
||||
* @see IMineBehavior
|
||||
*
|
||||
* @return The {@link IMineBehavior} instance
|
||||
*/
|
||||
IMineBehavior getMineBehavior();
|
||||
|
||||
/**
|
||||
* @see IPathingBehavior
|
||||
*
|
||||
* @return The {@link IPathingBehavior} instance
|
||||
*/
|
||||
IPathingBehavior getPathingBehavior();
|
||||
|
||||
/**
|
||||
* @see IWorldProvider
|
||||
*
|
||||
* @return The {@link IWorldProvider} instance
|
||||
*/
|
||||
IWorldProvider getWorldProvider();
|
||||
}
|
||||
@@ -56,6 +56,13 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
|
||||
|
||||
/**
|
||||
* This is just a tiebreaker to make it less likely to break blocks if it can avoid it.
|
||||
* For example, fire has a break cost of 0, this makes it nonzero, so all else being equal
|
||||
* it will take an otherwise equivalent route that doesn't require it to put out fire.
|
||||
*/
|
||||
public Setting<Double> blockBreakAdditionalPenalty = new Setting<>(2D);
|
||||
|
||||
/**
|
||||
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
|
||||
* Reliability: questionable.
|
||||
@@ -149,7 +156,7 @@ public class Settings {
|
||||
*
|
||||
* @see <a href="https://github.com/cabaletta/baritone/issues/18">Issue #18</a>
|
||||
*/
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9);
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.1);
|
||||
|
||||
/**
|
||||
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
|
||||
@@ -191,7 +198,19 @@ public class Settings {
|
||||
/**
|
||||
* Start planning the next path once the remaining movements tick estimates sum up to less than this value
|
||||
*/
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(100);
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
|
||||
|
||||
/**
|
||||
* Default size of the Long2ObjectOpenHashMap used in pathing
|
||||
*/
|
||||
public Setting<Integer> pathingMapDefaultSize = new Setting<>(1024);
|
||||
|
||||
/**
|
||||
* Load factor coefficient for the Long2ObjectOpenHashMap used in pathing
|
||||
* <p>
|
||||
* Decrease for faster map operations, but higher memory usage
|
||||
*/
|
||||
public Setting<Float> pathingMapLoadFactor = new Setting<>(0.75f);
|
||||
|
||||
/**
|
||||
* How far are you allowed to fall onto solid ground (without a water bucket)?
|
||||
@@ -392,6 +411,28 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Integer> followRadius = new Setting<>(3);
|
||||
|
||||
/**
|
||||
* Cached chunks (regardless of if they're in RAM or saved to disk) expire and are deleted after this number of seconds
|
||||
* -1 to disable
|
||||
* <p>
|
||||
* I would highly suggest leaving this setting disabled (-1).
|
||||
* <p>
|
||||
* The only valid reason I can think of enable this setting is if you are extremely low on disk space and you play on multiplayer,
|
||||
* and can't take (average) 300kb saved for every 512x512 area. (note that more complicated terrain is less compressible and will take more space)
|
||||
* <p>
|
||||
* However, simply discarding old chunks because they are old is inadvisable. Baritone is extremely good at correcting
|
||||
* itself and its paths as it learns new information, as new chunks load. There is no scenario in which having an
|
||||
* incorrect cache can cause Baritone to get stuck, take damage, or perform any action it wouldn't otherwise, everything
|
||||
* is rechecked once the real chunk is in range.
|
||||
* <p>
|
||||
* Having a robust cache greatly improves long distance pathfinding, as it's able to go around large scale obstacles
|
||||
* before they're in render distance. In fact, when the chunkCaching setting is disabled and Baritone starts anew
|
||||
* every time, or when you enter a completely new and very complicated area, it backtracks far more often because it
|
||||
* has to build up that cache from scratch. But after it's gone through an area just once, the next time will have zero
|
||||
* backtracking, since the entire area is now known and cached.
|
||||
*/
|
||||
public Setting<Long> cachedChunksExpirySeconds = new Setting<>(-1L);
|
||||
|
||||
/**
|
||||
* The function that is called when Baritone will log to chat. This function can be added to
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
|
||||
@@ -20,6 +20,8 @@ package baritone.api.behavior;
|
||||
import baritone.api.behavior.memory.IRememberedInventory;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
@@ -33,4 +35,11 @@ public interface IMemoryBehavior extends IBehavior {
|
||||
* @return The remembered inventory
|
||||
*/
|
||||
IRememberedInventory getInventoryByPos(BlockPos pos);
|
||||
|
||||
/**
|
||||
* Gets the map of all block positions to their remembered inventories.
|
||||
*
|
||||
* @return Map of block positions to their respective remembered inventories
|
||||
*/
|
||||
Map<BlockPos, IRememberedInventory> getRememberedInventories();
|
||||
}
|
||||
|
||||
@@ -23,21 +23,21 @@ public interface ActionCosts {
|
||||
* These costs are measured roughly in ticks btw
|
||||
*/
|
||||
double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633
|
||||
double WALK_ONE_IN_WATER_COST = 20 / 2.2;
|
||||
double WALK_ONE_IN_WATER_COST = 20 / 2.2; // 9.091
|
||||
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 2; // 0.4 in BlockSoulSand but effectively about half
|
||||
double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST * 0.75;
|
||||
double LADDER_UP_ONE_COST = 20 / 2.35;
|
||||
double LADDER_DOWN_ONE_COST = 20 / 3.0;
|
||||
double SNEAK_ONE_BLOCK_COST = 20 / 1.3;
|
||||
double LADDER_UP_ONE_COST = 20 / 2.35; // 8.511
|
||||
double LADDER_DOWN_ONE_COST = 20 / 3.0; // 6.667
|
||||
double SNEAK_ONE_BLOCK_COST = 20 / 1.3; // 15.385
|
||||
double SPRINT_ONE_BLOCK_COST = 20 / 5.612; // 3.564
|
||||
double SPRINT_MULTIPLIER = SPRINT_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST; // 0.769
|
||||
/**
|
||||
* To walk off an edge you need to walk 0.5 to the edge then 0.3 to start falling off
|
||||
*/
|
||||
double WALK_OFF_BLOCK_COST = WALK_ONE_BLOCK_COST * 0.8;
|
||||
double WALK_OFF_BLOCK_COST = WALK_ONE_BLOCK_COST * 0.8; // 3.706
|
||||
/**
|
||||
* To walk the rest of the way to be centered on the new block
|
||||
*/
|
||||
double CENTER_AFTER_FALL_COST = WALK_ONE_BLOCK_COST - WALK_OFF_BLOCK_COST;
|
||||
double CENTER_AFTER_FALL_COST = WALK_ONE_BLOCK_COST - WALK_OFF_BLOCK_COST; // 0.927
|
||||
|
||||
/**
|
||||
* don't make this Double.MAX_VALUE because it's added to other things, maybe other COST_INFs,
|
||||
|
||||
@@ -23,6 +23,7 @@ import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.WorldEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.utils.BaritoneAutoTest;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -39,6 +40,7 @@ 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 org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
/**
|
||||
@@ -59,11 +61,22 @@ public class MixinMinecraft {
|
||||
method = "init",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void init(CallbackInfo ci) {
|
||||
private void postInit(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "init",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/Minecraft.startTimerHackThread()V"
|
||||
)
|
||||
)
|
||||
private void preInit(CallbackInfo ci) {
|
||||
BaritoneAutoTest.INSTANCE.onPreInit();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
|
||||
@@ -88,8 +88,6 @@ public enum Baritone {
|
||||
// We might want to change this...
|
||||
this.settings = BaritoneAPI.getSettings();
|
||||
|
||||
BaritoneAPI.registerProviders(WorldProvider.INSTANCE);
|
||||
|
||||
this.behaviors = new ArrayList<>();
|
||||
{
|
||||
registerBehavior(PathingBehavior.INSTANCE);
|
||||
@@ -98,19 +96,9 @@ public enum Baritone {
|
||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||
registerBehavior(FollowBehavior.INSTANCE);
|
||||
registerBehavior(MineBehavior.INSTANCE);
|
||||
|
||||
// TODO: Clean this up
|
||||
// Maybe combine this call in someway with the registerBehavior calls?
|
||||
BaritoneAPI.registerDefaultBehaviors(
|
||||
FollowBehavior.INSTANCE,
|
||||
LookBehavior.INSTANCE,
|
||||
MemoryBehavior.INSTANCE,
|
||||
MineBehavior.INSTANCE,
|
||||
PathingBehavior.INSTANCE
|
||||
);
|
||||
}
|
||||
if (BaritoneAutoTest.ENABLE_AUTO_TEST && "true".equals(System.getenv("BARITONE_AUTO_TEST"))) {
|
||||
registerEventListener(new BaritoneAutoTest());
|
||||
if (BaritoneAutoTest.ENABLE_AUTO_TEST) {
|
||||
registerEventListener(BaritoneAutoTest.INSTANCE);
|
||||
}
|
||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
|
||||
61
src/main/java/baritone/BaritoneProvider.java
Normal file
61
src/main/java/baritone/BaritoneProvider.java
Normal file
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
import baritone.api.IBaritoneProvider;
|
||||
import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.behavior.*;
|
||||
import baritone.cache.WorldProvider;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
*/
|
||||
public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
@Override
|
||||
public IFollowBehavior getFollowBehavior() {
|
||||
return FollowBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILookBehavior getLookBehavior() {
|
||||
return LookBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryBehavior getMemoryBehavior() {
|
||||
return MemoryBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMineBehavior getMineBehavior() {
|
||||
return MineBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPathingBehavior getPathingBehavior() {
|
||||
return PathingBehavior.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldProvider getWorldProvider() {
|
||||
return WorldProvider.INSTANCE;
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,11 @@ package baritone.behavior;
|
||||
|
||||
import baritone.api.behavior.IMemoryBehavior;
|
||||
import baritone.api.behavior.memory.IRememberedInventory;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.Packet;
|
||||
@@ -43,15 +45,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
|
||||
public static MemoryBehavior INSTANCE = new MemoryBehavior();
|
||||
|
||||
/**
|
||||
* Possible future inventories that we will be able to remember
|
||||
*/
|
||||
private final List<FutureInventory> futureInventories = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The current remembered inventories
|
||||
*/
|
||||
private final Map<BlockPos, RememberedInventory> rememberedInventories = new HashMap<>();
|
||||
private final Map<IWorldData, WorldDataContainer> worldDataContainers = new HashMap<>();
|
||||
|
||||
private MemoryBehavior() {}
|
||||
|
||||
@@ -78,7 +72,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
TileEntityLockable lockable = (TileEntityLockable) tileEntity;
|
||||
int size = lockable.getSizeInventory();
|
||||
|
||||
this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
this.getCurrentContainer().futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -96,17 +90,19 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
if (p instanceof SPacketOpenWindow) {
|
||||
SPacketOpenWindow packet = event.cast();
|
||||
|
||||
// Remove any entries that were created over a second ago, this should make up for INSANE latency
|
||||
this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
|
||||
WorldDataContainer container = this.getCurrentContainer();
|
||||
|
||||
this.futureInventories.stream()
|
||||
// Remove any entries that were created over a second ago, this should make up for INSANE latency
|
||||
container.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
|
||||
|
||||
container.futureInventories.stream()
|
||||
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
|
||||
.findFirst().ifPresent(matched -> {
|
||||
// Remove the future inventory
|
||||
this.futureInventories.remove(matched);
|
||||
container.futureInventories.remove(matched);
|
||||
|
||||
// Setup the remembered inventory
|
||||
RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
|
||||
RememberedInventory inventory = container.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
|
||||
inventory.windowId = packet.getWindowId();
|
||||
inventory.size = packet.getSlotCount();
|
||||
});
|
||||
@@ -119,7 +115,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
}
|
||||
|
||||
private Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
|
||||
return this.rememberedInventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
|
||||
return this.getCurrentContainer().rememberedInventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
|
||||
}
|
||||
|
||||
private void updateInventory() {
|
||||
@@ -129,9 +125,31 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
});
|
||||
}
|
||||
|
||||
private WorldDataContainer getCurrentContainer() {
|
||||
return this.worldDataContainers.computeIfAbsent(WorldProvider.INSTANCE.getCurrentWorld(), data -> new WorldDataContainer());
|
||||
}
|
||||
|
||||
@Override
|
||||
public final RememberedInventory getInventoryByPos(BlockPos pos) {
|
||||
return this.rememberedInventories.get(pos);
|
||||
return this.getCurrentContainer().rememberedInventories.get(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Map<BlockPos, IRememberedInventory> getRememberedInventories() {
|
||||
return Collections.unmodifiableMap(this.getCurrentContainer().rememberedInventories);
|
||||
}
|
||||
|
||||
private static final class WorldDataContainer {
|
||||
|
||||
/**
|
||||
* Possible future inventories that we will be able to remember
|
||||
*/
|
||||
private final List<FutureInventory> futureInventories = new ArrayList<>();
|
||||
|
||||
/**
|
||||
* The current remembered inventories
|
||||
*/
|
||||
private final Map<BlockPos, RememberedInventory> rememberedInventories = new HashMap<>();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -170,7 +188,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
/**
|
||||
* An inventory that we are aware of.
|
||||
* <p>
|
||||
* Associated with a {@link BlockPos} in {@link MemoryBehavior#rememberedInventories}.
|
||||
* Associated with a {@link BlockPos} in {@link WorldDataContainer#rememberedInventories}.
|
||||
*/
|
||||
public static class RememberedInventory implements IRememberedInventory {
|
||||
|
||||
|
||||
@@ -24,10 +24,11 @@ import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
@@ -35,7 +36,6 @@ import baritone.utils.BlockBreakHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.PathRenderer;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -341,7 +341,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
}
|
||||
|
||||
// TODO simplify each individual goal in a GoalComposite
|
||||
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
|
||||
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
@@ -353,9 +352,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
} else {
|
||||
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
|
||||
}
|
||||
Optional<HashSet<Long>> favoredPositions = previous.map(IPath::positions).map(Collection::stream).map(x -> x.map(y -> y.hashCode)).map(x -> x.collect(Collectors.toList())).map(HashSet::new); // <-- okay this is EPIC
|
||||
Optional<HashSet<Long>> favoredPositions;
|
||||
if (Baritone.settings().backtrackCostFavoringCoefficient.get() == 1D) {
|
||||
favoredPositions = Optional.empty();
|
||||
} else {
|
||||
favoredPositions = previous.map(IPath::positions).map(Collection::stream).map(x -> x.map(BetterBlockPos::longHash)).map(x -> x.collect(Collectors.toList())).map(HashSet::new); // <-- okay this is EPIC
|
||||
}
|
||||
try {
|
||||
IPathFinder pf = new AStarPathFinder(start, goal, favoredPositions);
|
||||
IPathFinder pf = new AStarPathFinder(start.getX(), start.getY(), start.getZ(), goal, favoredPositions);
|
||||
return pf.calculate(timeout);
|
||||
} catch (Exception e) {
|
||||
logDebug("Pathing exception: " + e);
|
||||
@@ -368,15 +372,17 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (!Baritone.settings().cancelOnGoalInvalidation.get()) {
|
||||
return;
|
||||
}
|
||||
if (current == null || goal == null) {
|
||||
return;
|
||||
}
|
||||
Goal intended = current.getPath().getGoal();
|
||||
BlockPos end = current.getPath().getDest();
|
||||
if (intended.isInGoal(end) && !goal.isInGoal(end)) {
|
||||
// this path used to end in the goal
|
||||
// but the goal has changed, so there's no reason to continue...
|
||||
cancel();
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null || goal == null) {
|
||||
return;
|
||||
}
|
||||
Goal intended = current.getPath().getGoal();
|
||||
BlockPos end = current.getPath().getDest();
|
||||
if (intended.isInGoal(end) && !goal.isInGoal(end)) {
|
||||
// this path used to end in the goal
|
||||
// but the goal has changed, so there's no reason to continue...
|
||||
cancel();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -420,11 +426,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> {
|
||||
currentlyRunning.bestPathSoFar().ifPresent(p -> {
|
||||
PathRenderer.drawPath(p, 0, player(), partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
|
||||
});
|
||||
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
|
||||
|
||||
PathRenderer.drawPath(mr, 0, player(), partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
PathRenderer.drawManySelectionBoxes(player(), Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
|
||||
});
|
||||
PathRenderer.drawPath(mr, 0, player(), partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
PathRenderer.drawManySelectionBoxes(player(), Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
|
||||
});
|
||||
});
|
||||
//long end = System.nanoTime();
|
||||
|
||||
@@ -106,7 +106,9 @@ public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
|
||||
private final Map<String, List<BlockPos>> specialBlockLocations;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data, IBlockState[] overview, Map<String, List<BlockPos>> specialBlockLocations) {
|
||||
public final long cacheTimestamp;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data, IBlockState[] overview, Map<String, List<BlockPos>> specialBlockLocations, long cacheTimestamp) {
|
||||
validateSize(data);
|
||||
|
||||
this.x = x;
|
||||
@@ -115,6 +117,7 @@ public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
this.overview = overview;
|
||||
this.heightMap = new int[256];
|
||||
this.specialBlockLocations = specialBlockLocations;
|
||||
this.cacheTimestamp = cacheTimestamp;
|
||||
calculateHeightMap();
|
||||
}
|
||||
|
||||
|
||||
90
src/main/java/baritone/cache/CachedRegion.java
vendored
90
src/main/java/baritone/cache/CachedRegion.java
vendored
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.ICachedRegion;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -112,6 +113,7 @@ public final class CachedRegion implements ICachedRegion {
|
||||
if (!hasUnsavedChanges) {
|
||||
return;
|
||||
}
|
||||
removeExpired();
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path)) {
|
||||
@@ -129,8 +131,8 @@ public final class CachedRegion implements ICachedRegion {
|
||||
DataOutputStream out = new DataOutputStream(gzipOut)
|
||||
) {
|
||||
out.writeInt(CACHED_REGION_MAGIC);
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
CachedChunk chunk = this.chunks[x][z];
|
||||
if (chunk == null) {
|
||||
out.write(CHUNK_NOT_PRESENT);
|
||||
@@ -143,8 +145,8 @@ public final class CachedRegion implements ICachedRegion {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (chunks[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
out.writeUTF(ChunkPacker.blockToString(chunks[x][z].getOverview()[i].getBlock()));
|
||||
@@ -152,8 +154,8 @@ public final class CachedRegion implements ICachedRegion {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (chunks[x][z] != null) {
|
||||
Map<String, List<BlockPos>> locs = chunks[x][z].getRelativeBlocks();
|
||||
out.writeShort(locs.entrySet().size());
|
||||
@@ -168,10 +170,17 @@ public final class CachedRegion implements ICachedRegion {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (chunks[x][z] != null) {
|
||||
out.writeLong(chunks[x][z].cacheTimestamp);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
System.out.println("Saved region successfully");
|
||||
} catch (IOException ex) {
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
@@ -203,42 +212,42 @@ public final class CachedRegion implements ICachedRegion {
|
||||
// by switching on the magic value, and either loading it normally, or loading through a converter.
|
||||
throw new IOException("Bad magic value " + magic);
|
||||
}
|
||||
CachedChunk[][] tmpCached = new CachedChunk[32][32];
|
||||
boolean[][] present = new boolean[32][32];
|
||||
BitSet[][] bitSets = new BitSet[32][32];
|
||||
Map<String, List<BlockPos>>[][] location = new Map[32][32];
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
IBlockState[][][] overview = new IBlockState[32][32][];
|
||||
long[][] cacheTimestamp = new long[32][32];
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
int isChunkPresent = in.read();
|
||||
switch (isChunkPresent) {
|
||||
case CHUNK_PRESENT:
|
||||
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
|
||||
in.readFully(bytes);
|
||||
bitSets[x][z] = BitSet.valueOf(bytes);
|
||||
location[x][z] = new HashMap<>();
|
||||
int regionX = this.x;
|
||||
int regionZ = this.z;
|
||||
int chunkX = x + 32 * regionX;
|
||||
int chunkZ = z + 32 * regionZ;
|
||||
tmpCached[x][z] = new CachedChunk(chunkX, chunkZ, BitSet.valueOf(bytes), new IBlockState[256], location[x][z]);
|
||||
overview[x][z] = new IBlockState[256];
|
||||
present[x][z] = true;
|
||||
break;
|
||||
case CHUNK_NOT_PRESENT:
|
||||
tmpCached[x][z] = null;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Malformed stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (present[x][z]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
tmpCached[x][z].getOverview()[i] = ChunkPacker.stringToBlock(in.readUTF()).getDefaultState();
|
||||
overview[x][z][i] = ChunkPacker.stringToBlock(in.readUTF()).getDefaultState();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (present[x][z]) {
|
||||
// 16 * 16 * 256 = 65536 so a short is enough
|
||||
// ^ haha jokes on leijurv, java doesn't have unsigned types so that isn't correct
|
||||
// also why would you have more than 32767 special blocks in a chunk
|
||||
@@ -264,21 +273,52 @@ public final class CachedRegion implements ICachedRegion {
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (present[x][z]) {
|
||||
cacheTimestamp[x][z] = in.readLong();
|
||||
}
|
||||
}
|
||||
}
|
||||
// only if the entire file was uncorrupted do we actually set the chunks
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
this.chunks[x][z] = tmpCached[x][z];
|
||||
if (present[x][z]) {
|
||||
int regionX = this.x;
|
||||
int regionZ = this.z;
|
||||
int chunkX = x + 32 * regionX;
|
||||
int chunkZ = z + 32 * regionZ;
|
||||
this.chunks[x][z] = new CachedChunk(chunkX, chunkZ, bitSets[x][z], overview[x][z], location[x][z], cacheTimestamp[x][z]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
removeExpired();
|
||||
hasUnsavedChanges = false;
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
System.out.println("Loaded region successfully in " + (end - start) + "ms");
|
||||
} catch (IOException ex) {
|
||||
} catch (Exception ex) { // corrupted files can cause NullPointerExceptions as well as IOExceptions
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized final void removeExpired() {
|
||||
long expiry = Baritone.settings().cachedChunksExpirySeconds.get();
|
||||
if (expiry < 0) {
|
||||
return;
|
||||
}
|
||||
long now = System.currentTimeMillis();
|
||||
long oldestAcceptableAge = now - expiry * 1000L;
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (this.chunks[x][z] != null && this.chunks[x][z].cacheTimestamp < oldestAcceptableAge) {
|
||||
System.out.println("Removing chunk " + (x + 32 * this.x) + "," + (z + 32 * this.z) + " because it was cached " + (now - this.chunks[x][z].cacheTimestamp) / 1000L + " seconds ago, and max age is " + expiry);
|
||||
this.chunks[x][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
|
||||
@@ -142,6 +142,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
public final void save() {
|
||||
if (!Baritone.settings().chunkCaching.get()) {
|
||||
System.out.println("Not saving to disk; chunk caching is disabled.");
|
||||
allRegions().forEach(CachedRegion::removeExpired); // even if we aren't saving to disk, still delete expired old chunks from RAM
|
||||
return;
|
||||
}
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
|
||||
@@ -106,7 +106,7 @@ public final class ChunkPacker implements Helper {
|
||||
blocks[z << 4 | x] = Blocks.AIR.getDefaultState();
|
||||
}
|
||||
}
|
||||
return new CachedChunk(chunk.x, chunk.z, bitSet, blocks, specialBlocks);
|
||||
return new CachedChunk(chunk.x, chunk.z, bitSet, blocks, specialBlocks, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static String blockToString(Block block) {
|
||||
|
||||
@@ -26,8 +26,7 @@ import baritone.pathing.movement.Moves;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.MoveResult;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
@@ -41,14 +40,14 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
|
||||
private final Optional<HashSet<Long>> favoredPositions;
|
||||
|
||||
public AStarPathFinder(BlockPos start, Goal goal, Optional<HashSet<Long>> favoredPositions) {
|
||||
super(start, goal);
|
||||
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<HashSet<Long>> favoredPositions) {
|
||||
super(startX, startY, startZ, goal);
|
||||
this.favoredPositions = favoredPositions;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<IPath> calculate0(long timeout) {
|
||||
startNode = getNodeAtPosition(start.x, start.y, start.z);
|
||||
startNode = getNodeAtPosition(startX, startY, startZ, posHash(startX, startY, startZ));
|
||||
startNode.cost = 0;
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
|
||||
@@ -61,6 +60,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
bestSoFar[i] = startNode;
|
||||
}
|
||||
CalculationContext calcContext = new CalculationContext();
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
HashSet<Long> favored = favoredPositions.orElse(null);
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
long startTime = System.nanoTime() / 1000000L;
|
||||
@@ -105,24 +105,29 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
continue;
|
||||
}
|
||||
}
|
||||
MoveResult res = moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z);
|
||||
res.reset();
|
||||
moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res);
|
||||
numMovementsConsidered++;
|
||||
double actionCost = res.cost;
|
||||
if (actionCost >= ActionCosts.COST_INF) {
|
||||
continue;
|
||||
}
|
||||
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
|
||||
if (!moves.dynamicXZ && (res.destX != newX || res.destZ != newZ)) {
|
||||
throw new IllegalStateException(moves + " " + res.destX + " " + newX + " " + res.destZ + " " + newZ);
|
||||
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
|
||||
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
|
||||
}
|
||||
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
|
||||
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
|
||||
}
|
||||
if (actionCost <= 0) {
|
||||
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
|
||||
}
|
||||
if (favoring && favored.contains(posHash(res.destX, res.destY, res.destZ))) {
|
||||
long hashCode = posHash(res.x, res.y, res.z);
|
||||
if (favoring && favored.contains(hashCode)) {
|
||||
// see issue #18
|
||||
actionCost *= favorCoeff;
|
||||
}
|
||||
PathNode neighbor = getNodeAtPosition(res.destX, res.destY, res.destZ);
|
||||
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
|
||||
double tentativeCost = currentNode.cost + actionCost;
|
||||
if (tentativeCost < neighbor.cost) {
|
||||
if (tentativeCost < 0) {
|
||||
|
||||
@@ -17,11 +17,10 @@
|
||||
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -37,7 +36,9 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
*/
|
||||
private static AbstractNodeCostSearch currentlyRunning = null;
|
||||
|
||||
protected final BetterBlockPos start;
|
||||
protected final int startX;
|
||||
protected final int startY;
|
||||
protected final int startZ;
|
||||
|
||||
protected final Goal goal;
|
||||
|
||||
@@ -68,10 +69,12 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
*/
|
||||
protected final static double MIN_DIST_PATH = 5;
|
||||
|
||||
AbstractNodeCostSearch(BlockPos start, Goal goal) {
|
||||
this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
|
||||
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal) {
|
||||
this.startX = startX;
|
||||
this.startY = startY;
|
||||
this.startZ = startZ;
|
||||
this.goal = goal;
|
||||
this.map = new Long2ObjectOpenHashMap<>();
|
||||
this.map = new Long2ObjectOpenHashMap<>(Baritone.settings().pathingMapDefaultSize.value, Baritone.settings().pathingMapLoadFactor.get());
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
@@ -114,22 +117,21 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
* @return The distance, squared
|
||||
*/
|
||||
protected double getDistFromStartSq(PathNode n) {
|
||||
int xDiff = n.x - start.x;
|
||||
int yDiff = n.y - start.y;
|
||||
int zDiff = n.z - start.z;
|
||||
int xDiff = n.x - startX;
|
||||
int yDiff = n.y - startY;
|
||||
int zDiff = n.z - startZ;
|
||||
return xDiff * xDiff + yDiff * yDiff + zDiff * zDiff;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to search the {@link BlockPos} to {@link PathNode} map
|
||||
* Attempts to search the block position hashCode long to {@link PathNode} map
|
||||
* for the node mapped to the specified pos. If no node is found,
|
||||
* a new node is created.
|
||||
*
|
||||
* @return The associated node
|
||||
* @see <a href="https://github.com/cabaletta/baritone/issues/107">Issue #107</a>
|
||||
*/
|
||||
protected PathNode getNodeAtPosition(int x, int y, int z) {
|
||||
long hashCode = posHash(x, y, z);
|
||||
protected PathNode getNodeAtPosition(int x, int y, int z, long hashCode) {
|
||||
PathNode node = map.get(hashCode);
|
||||
if (node == null) {
|
||||
node = new PathNode(x, y, z, goal);
|
||||
@@ -140,7 +142,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
public static long posHash(int x, int y, int z) {
|
||||
/*
|
||||
* This is the hashcode implementation of Vec3i, the superclass of BlockPos
|
||||
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
|
||||
*
|
||||
* public int hashCode() {
|
||||
* return (this.getY() + this.getZ() * 31) * 31 + this.getX();
|
||||
@@ -220,11 +222,6 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
return goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final BlockPos getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() {
|
||||
return Optional.ofNullable(currentlyRunning);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package baritone.pathing.calc;
|
||||
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -30,8 +29,6 @@ import java.util.Optional;
|
||||
*/
|
||||
public interface IPathFinder {
|
||||
|
||||
BlockPos getStart();
|
||||
|
||||
Goal getGoal();
|
||||
|
||||
/**
|
||||
|
||||
@@ -86,11 +86,11 @@ class Path implements IPath {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
LinkedList<Movement> tempMovements = new LinkedList<>(); // Instead, do it into a linked list, then convert at the end
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
// Instead, do it into a linked list, then convert at the end
|
||||
while (!current.equals(start)) {
|
||||
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
|
||||
tempMovements.addFirst(runBackwards(current.previous, current));
|
||||
current = current.previous;
|
||||
}
|
||||
tempPath.addFirst(this.start);
|
||||
@@ -98,20 +98,6 @@ class Path implements IPath {
|
||||
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
||||
// to performantly do that conversion since it knows the length.
|
||||
path.addAll(tempPath);
|
||||
movements.addAll(tempMovements);
|
||||
}
|
||||
|
||||
private static Movement runBackwards(PathNode src0, PathNode dest0) { // TODO this is horrifying
|
||||
BetterBlockPos src = new BetterBlockPos(src0.x, src0.y, src0.z);
|
||||
BetterBlockPos dest = new BetterBlockPos(dest0.x, dest0.y, dest0.z);
|
||||
for (Moves moves : Moves.values()) {
|
||||
Movement move = moves.apply0(src);
|
||||
if (move.getDest().equals(dest)) {
|
||||
return move;
|
||||
}
|
||||
}
|
||||
// leave this as IllegalStateException; it's caught in AbstractNodeCostSearch
|
||||
throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -140,12 +126,34 @@ class Path implements IPath {
|
||||
}
|
||||
}
|
||||
|
||||
private void assembleMovements() {
|
||||
if (path.isEmpty() || !movements.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
movements.add(runBackwards(path.get(i), path.get(i + 1)));
|
||||
}
|
||||
}
|
||||
|
||||
private static Movement runBackwards(BetterBlockPos src, BetterBlockPos dest) { // TODO this is horrifying
|
||||
for (Moves moves : Moves.values()) {
|
||||
Movement move = moves.apply0(src);
|
||||
if (move.getDest().equals(dest)) {
|
||||
move.recalculateCost(); // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
|
||||
return move;
|
||||
}
|
||||
}
|
||||
// leave this as IllegalStateException; it's caught in AbstractNodeCostSearch
|
||||
throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess() {
|
||||
if (verified) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
verified = true;
|
||||
assembleMovements();
|
||||
// more post processing here
|
||||
movements.forEach(Movement::checkLoadedChunk);
|
||||
sanityCheck();
|
||||
|
||||
@@ -18,8 +18,10 @@
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -40,6 +42,8 @@ public class CalculationContext implements Helper {
|
||||
private final boolean allowBreak;
|
||||
private final int maxFallHeightNoWater;
|
||||
private final int maxFallHeightBucket;
|
||||
private final double waterWalkSpeed;
|
||||
private final double breakBlockAdditionalCost;
|
||||
|
||||
public CalculationContext() {
|
||||
this(new ToolSet());
|
||||
@@ -54,13 +58,20 @@ public class CalculationContext implements Helper {
|
||||
this.allowBreak = Baritone.settings().allowBreak.get();
|
||||
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
|
||||
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
|
||||
int depth = EnchantmentHelper.getDepthStriderModifier(player());
|
||||
if (depth > 3) {
|
||||
depth = 3;
|
||||
}
|
||||
float mult = depth / 3.0F;
|
||||
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult;
|
||||
this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.get();
|
||||
// why cache these things here, why not let the movements just get directly from settings?
|
||||
// because if some movements are calculated one way and others are calculated another way,
|
||||
// then you get a wildly inconsistent path that isn't optimal for either scenario.
|
||||
}
|
||||
|
||||
public ToolSet getToolSet() {
|
||||
return this.toolSet;
|
||||
return toolSet;
|
||||
}
|
||||
|
||||
public boolean hasWaterBucket() {
|
||||
@@ -91,4 +102,11 @@ public class CalculationContext implements Helper {
|
||||
return maxFallHeightBucket;
|
||||
}
|
||||
|
||||
public double waterWalkSpeed() {
|
||||
return waterWalkSpeed;
|
||||
}
|
||||
|
||||
public double breakBlockAdditionalCost() {
|
||||
return breakBlockAdditionalCost;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -187,6 +187,14 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean safeToCancel() {
|
||||
return safeToCancel(currentState);
|
||||
}
|
||||
|
||||
protected boolean safeToCancel(MovementState currentState) {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return (currentState.getStatus() != MovementStatus.RUNNING
|
||||
&& currentState.getStatus() != MovementStatus.PREPPING
|
||||
|
||||
@@ -374,6 +374,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
double result = m / strVsBlock;
|
||||
result += context.breakBlockAdditionalCost();
|
||||
if (includeFalling) {
|
||||
IBlockState above = BlockStateInterface.get(x, y + 1, z);
|
||||
if (above.getBlock() instanceof BlockFalling) {
|
||||
|
||||
@@ -19,7 +19,7 @@ package baritone.pathing.movement;
|
||||
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MoveResult;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
/**
|
||||
@@ -28,306 +28,326 @@ import net.minecraft.util.EnumFacing;
|
||||
* @author leijurv
|
||||
*/
|
||||
public enum Moves {
|
||||
DOWNWARD(0, 0) {
|
||||
DOWNWARD(0, -1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementDownward(src, src.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y - 1, z, MovementDownward.cost(context, x, y, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDownward.cost(context, x, y, z);
|
||||
}
|
||||
},
|
||||
|
||||
PILLAR(0, 0) {
|
||||
PILLAR(0, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementPillar(src, src.up());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y + 1, z, MovementPillar.cost(context, x, y, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementPillar.cost(context, x, y, z);
|
||||
}
|
||||
},
|
||||
|
||||
TRAVERSE_NORTH(0, -1) {
|
||||
TRAVERSE_NORTH(0, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.north());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y, z - 1, MovementTraverse.cost(context, x, y, z, x, z - 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementTraverse.cost(context, x, y, z, x, z - 1);
|
||||
}
|
||||
},
|
||||
|
||||
TRAVERSE_SOUTH(0, +1) {
|
||||
TRAVERSE_SOUTH(0, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.south());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y, z + 1, MovementTraverse.cost(context, x, y, z, x, z + 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementTraverse.cost(context, x, y, z, x, z + 1);
|
||||
}
|
||||
},
|
||||
|
||||
TRAVERSE_EAST(+1, 0) {
|
||||
TRAVERSE_EAST(+1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.east());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x + 1, y, z, MovementTraverse.cost(context, x, y, z, x + 1, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementTraverse.cost(context, x, y, z, x + 1, z);
|
||||
}
|
||||
},
|
||||
|
||||
TRAVERSE_WEST(-1, 0) {
|
||||
TRAVERSE_WEST(-1, 0, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementTraverse(src, src.west());
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x - 1, y, z, MovementTraverse.cost(context, x, y, z, x - 1, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementTraverse.cost(context, x, y, z, x - 1, z);
|
||||
}
|
||||
},
|
||||
|
||||
ASCEND_NORTH(0, -1) {
|
||||
ASCEND_NORTH(0, +1, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z - 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y + 1, z - 1, MovementAscend.cost(context, x, y, z, x, z - 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementAscend.cost(context, x, y, z, x, z - 1);
|
||||
}
|
||||
},
|
||||
|
||||
ASCEND_SOUTH(0, +1) {
|
||||
ASCEND_SOUTH(0, +1, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x, src.y + 1, src.z + 1));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x, y + 1, z + 1, MovementAscend.cost(context, x, y, z, x, z + 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementAscend.cost(context, x, y, z, x, z + 1);
|
||||
}
|
||||
},
|
||||
|
||||
ASCEND_EAST(+1, 0) {
|
||||
ASCEND_EAST(+1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x + 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x + 1, y + 1, z, MovementAscend.cost(context, x, y, z, x + 1, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementAscend.cost(context, x, y, z, x + 1, z);
|
||||
}
|
||||
},
|
||||
|
||||
ASCEND_WEST(-1, 0) {
|
||||
ASCEND_WEST(-1, +1, 0) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementAscend(src, new BetterBlockPos(src.x - 1, src.y + 1, src.z));
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x - 1, y + 1, z, MovementAscend.cost(context, x, y, z, x - 1, z));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementAscend.cost(context, x, y, z, x - 1, z);
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_EAST(+1, 0) {
|
||||
DESCEND_EAST(+1, 0, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z);
|
||||
if (res.destY == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDescend.cost(context, x, y, z, x + 1, z);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementDescend.cost(context, x, y, z, x + 1, z, result);
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_WEST(-1, 0) {
|
||||
DESCEND_WEST(-1, 0, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z);
|
||||
if (res.destY == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDescend.cost(context, x, y, z, x - 1, z);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementDescend.cost(context, x, y, z, x - 1, z, result);
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_NORTH(0, -1) {
|
||||
DESCEND_NORTH(0, 0, -1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z);
|
||||
if (res.destY == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDescend.cost(context, x, y, z, x, z - 1);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementDescend.cost(context, x, y, z, x, z - 1, result);
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_SOUTH(0, +1) {
|
||||
DESCEND_SOUTH(0, 0, +1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MoveResult res = apply(new CalculationContext(), src.x, src.y, src.z);
|
||||
if (res.destY == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
apply(new CalculationContext(), src.x, src.y, src.z, res);
|
||||
if (res.y == src.y - 1) {
|
||||
return new MovementDescend(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
} else {
|
||||
return new MovementFall(src, new BetterBlockPos(res.destX, res.destY, res.destZ));
|
||||
return new MovementFall(src, new BetterBlockPos(res.x, res.y, res.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDescend.cost(context, x, y, z, x, z + 1);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementDescend.cost(context, x, y, z, x, z + 1, result);
|
||||
}
|
||||
},
|
||||
|
||||
DIAGONAL_NORTHEAST(+1, -1) {
|
||||
DIAGONAL_NORTHEAST(+1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x + 1, y, z - 1, MovementDiagonal.cost(context, x, y, z, x + 1, z - 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDiagonal.cost(context, x, y, z, x + 1, z - 1);
|
||||
}
|
||||
},
|
||||
|
||||
DIAGONAL_NORTHWEST(-1, -1) {
|
||||
DIAGONAL_NORTHWEST(-1, 0, -1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.NORTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x - 1, y, z - 1, MovementDiagonal.cost(context, x, y, z, x - 1, z - 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDiagonal.cost(context, x, y, z, x - 1, z - 1);
|
||||
}
|
||||
},
|
||||
|
||||
DIAGONAL_SOUTHEAST(+1, +1) {
|
||||
DIAGONAL_SOUTHEAST(+1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x + 1, y, z + 1, MovementDiagonal.cost(context, x, y, z, x + 1, z + 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDiagonal.cost(context, x, y, z, x + 1, z + 1);
|
||||
}
|
||||
},
|
||||
|
||||
DIAGONAL_SOUTHWEST(-1, +1) {
|
||||
DIAGONAL_SOUTHWEST(-1, 0, +1) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return new MovementDiagonal(src, EnumFacing.SOUTH, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return new MoveResult(x - 1, y, z + 1, MovementDiagonal.cost(context, x, y, z, x - 1, z + 1));
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
return MovementDiagonal.cost(context, x, y, z, x - 1, z + 1);
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_NORTH(0, -4, true) {
|
||||
PARKOUR_NORTH(0, 0, -4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.NORTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementParkour.cost(context, x, y, z, EnumFacing.NORTH);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementParkour.cost(context, x, y, z, EnumFacing.NORTH, result);
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_SOUTH(0, +4, true) {
|
||||
PARKOUR_SOUTH(0, 0, +4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.SOUTH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementParkour.cost(context, x, y, z, EnumFacing.SOUTH, result);
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_EAST(+4, 0, true) {
|
||||
PARKOUR_EAST(+4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.EAST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementParkour.cost(context, x, y, z, EnumFacing.EAST);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementParkour.cost(context, x, y, z, EnumFacing.EAST, result);
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_WEST(-4, 0, true) {
|
||||
PARKOUR_WEST(-4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
return MovementParkour.cost(new CalculationContext(), src, EnumFacing.WEST);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MoveResult apply(CalculationContext context, int x, int y, int z) {
|
||||
return MovementParkour.cost(context, x, y, z, EnumFacing.WEST);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
MovementParkour.cost(context, x, y, z, EnumFacing.WEST, result);
|
||||
}
|
||||
};
|
||||
|
||||
public final boolean dynamicXZ;
|
||||
public final boolean dynamicY;
|
||||
|
||||
public final int xOffset;
|
||||
public final int yOffset;
|
||||
public final int zOffset;
|
||||
|
||||
Moves(int x, int z, boolean dynamicXZ) {
|
||||
Moves(int x, int y, int z, boolean dynamicXZ, boolean dynamicY) {
|
||||
this.xOffset = x;
|
||||
this.yOffset = y;
|
||||
this.zOffset = z;
|
||||
this.dynamicXZ = dynamicXZ;
|
||||
this.dynamicY = dynamicY;
|
||||
}
|
||||
|
||||
Moves(int x, int z) {
|
||||
this(x, z, false);
|
||||
Moves(int x, int y, int z) {
|
||||
this(x, y, z, false, false);
|
||||
}
|
||||
|
||||
public abstract Movement apply0(BetterBlockPos src);
|
||||
|
||||
public abstract MoveResult apply(CalculationContext context, int x, int y, int z);
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
if (dynamicXZ || dynamicY) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
result.x = x + xOffset;
|
||||
result.y = y + yOffset;
|
||||
result.z = z + zOffset;
|
||||
result.cost = cost(context, x, y, z);
|
||||
}
|
||||
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public class MovementAscend extends Movement {
|
||||
return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab
|
||||
}
|
||||
boolean hasToPlace = false;
|
||||
if (!MovementHelper.canWalkOn(destX, y, z, toPlace)) {
|
||||
if (!MovementHelper.canWalkOn(destX, y, destZ, toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
@@ -101,14 +101,15 @@ public class MovementAscend extends Movement {
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
if (!(BlockStateInterface.getBlock(x, y + 1, z) instanceof BlockFalling) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling)) {
|
||||
// if both of those are BlockFalling, that means that by standing on src
|
||||
if (MovementHelper.canWalkThrough(x, y + 1, z) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling)) {
|
||||
// if the lower one is can't walk through and the upper one is falling, that means that by standing on src
|
||||
// (the presupposition of this Movement)
|
||||
// we have necessarily already cleared the entire BlockFalling stack
|
||||
// on top of our head
|
||||
|
||||
// but if either of them aren't BlockFalling, that means we're still in suffocation danger
|
||||
// so don't do it
|
||||
// as in, if we have a block, then two BlockFallings on top of it
|
||||
// and that block is x, y+1, z, and we'd have to clear it to even start this movement
|
||||
// we don't need to worry about those BlockFallings because we've already cleared them
|
||||
return COST_INF;
|
||||
}
|
||||
// you may think we only need to check srcUp2, not srcUp
|
||||
|
||||
@@ -26,15 +26,13 @@ import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MoveResult;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import static baritone.utils.pathing.MoveResult.IMPOSSIBLE;
|
||||
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
private int numTicks = 0;
|
||||
@@ -51,31 +49,33 @@ public class MovementDescend extends Movement {
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
MoveResult result = cost(context, src.x, src.y, src.z, dest.x, dest.z);
|
||||
if (result.destY != dest.y) {
|
||||
MutableMoveResult result = new MutableMoveResult();
|
||||
cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
|
||||
if (result.y != dest.y) {
|
||||
return COST_INF; // doesn't apply to us, this position is a fall not a descend
|
||||
}
|
||||
return result.cost;
|
||||
}
|
||||
|
||||
public static MoveResult cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
Block fromDown = BlockStateInterface.get(x, y - 1, z).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
|
||||
double totalCost = 0;
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, false);
|
||||
IBlockState destDown = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y - 1, destZ, destDown, false);
|
||||
if (totalCost >= COST_INF) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y, destZ, false);
|
||||
if (totalCost >= COST_INF) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
totalCost += MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, true); // only the top block in the 3 we need to mine needs to consider the falling blocks above
|
||||
if (totalCost >= COST_INF) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
|
||||
// A
|
||||
@@ -90,12 +90,12 @@ public class MovementDescend extends Movement {
|
||||
|
||||
IBlockState below = BlockStateInterface.get(destX, y - 2, destZ);
|
||||
if (!MovementHelper.canWalkOn(destX, y - 2, destZ, below)) {
|
||||
return dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below);
|
||||
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
|
||||
return;
|
||||
}
|
||||
|
||||
Block tmp1 = BlockStateInterface.get(destX, y - 1, destZ).getBlock();
|
||||
if (tmp1 == Blocks.LADDER || tmp1 == Blocks.VINE) {
|
||||
return IMPOSSIBLE;
|
||||
if (destDown.getBlock() == Blocks.LADDER || destDown.getBlock() == Blocks.VINE) {
|
||||
return;
|
||||
}
|
||||
|
||||
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
|
||||
@@ -105,55 +105,72 @@ public class MovementDescend extends Movement {
|
||||
walk = WALK_ONE_OVER_SOUL_SAND_COST;
|
||||
}
|
||||
totalCost += walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST);
|
||||
return new MoveResult(destX, y - 1, destZ, totalCost);
|
||||
res.x = destX;
|
||||
res.y = y - 1;
|
||||
res.z = destZ;
|
||||
res.cost = totalCost;
|
||||
}
|
||||
|
||||
public static MoveResult dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below) {
|
||||
public static void dynamicFallCost(CalculationContext context, int x, int y, int z, int destX, int destZ, double frontBreak, IBlockState below, MutableMoveResult res) {
|
||||
if (frontBreak != 0 && BlockStateInterface.get(destX, y + 2, destZ).getBlock() instanceof BlockFalling) {
|
||||
// if frontBreak is 0 we can actually get through this without updating the falling block and making it actually fall
|
||||
// but if frontBreak is nonzero, we're breaking blocks in front, so don't let anything fall through this column,
|
||||
// and potentially replace the water we're going to fall into
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
int newY = y - fallHeight;
|
||||
if (newY < 0) {
|
||||
// when pathing in the end, where you could plausibly fall into the void
|
||||
// this check prevents it from getting the block at y=-1 and crashing
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ);
|
||||
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak;
|
||||
if (ontoBlock.getBlock() == Blocks.WATER && !BlockStateInterface.isFlowing(ontoBlock)) { // TODO flowing check required here?
|
||||
if (ontoBlock.getBlock() == Blocks.WATER && !BlockStateInterface.isFlowing(ontoBlock) && BlockStateInterface.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
|
||||
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
|
||||
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
|
||||
if (Baritone.settings().assumeWalkOnWater.get()) {
|
||||
return IMPOSSIBLE; // TODO fix
|
||||
return; // TODO fix
|
||||
}
|
||||
// found a fall into water
|
||||
return new MoveResult(destX, newY, destZ, tentativeCost); // TODO incorporate water swim up cost?
|
||||
res.x = destX;
|
||||
res.y = newY;
|
||||
res.z = destZ;
|
||||
res.cost = tentativeCost;// TODO incorporate water swim up cost?
|
||||
return;
|
||||
}
|
||||
if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(destX, newY, destZ, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(destX, newY, destZ, ontoBlock)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(ontoBlock)) {
|
||||
return IMPOSSIBLE; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
|
||||
return; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
|
||||
}
|
||||
if (context.hasWaterBucket() && fallHeight <= context.maxFallHeightBucket() + 1) {
|
||||
return new MoveResult(destX, newY + 1, destZ, tentativeCost + context.placeBlockCost()); // this is the block we're falling onto, so dest is +1
|
||||
res.x = destX;
|
||||
res.y = newY + 1;// this is the block we're falling onto, so dest is +1
|
||||
res.z = destZ;
|
||||
res.cost = tentativeCost + context.placeBlockCost();
|
||||
return;
|
||||
}
|
||||
if (fallHeight <= context.maxFallHeightNoWater() + 1) {
|
||||
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
|
||||
return new MoveResult(destX, newY + 1, destZ, tentativeCost);
|
||||
res.x = destX;
|
||||
res.y = newY + 1;
|
||||
res.z = destZ;
|
||||
res.cost = tentativeCost;
|
||||
return;
|
||||
} else {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,37 +85,54 @@ public class MovementDiagonal extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb0 = BlockStateInterface.get(x, y, destZ);
|
||||
IBlockState pb1 = BlockStateInterface.get(x, y + 1, destZ);
|
||||
IBlockState pb2 = BlockStateInterface.get(destX, y, z);
|
||||
IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, x, y, destZ, pb0, false) + MovementHelper.getMiningDurationTicks(context, x, y + 1, destZ, pb1, true);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, destX, y, z, pb2, false) + MovementHelper.getMiningDurationTicks(context, destX, y + 1, z, pb3, true);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, x, y, destZ, pb0, false);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, destX, y, z, pb2, false);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
// check these one at a time -- if pb0 and pb2 were nonzero, we already know that (optionA != 0 && optionB != 0)
|
||||
// so no need to check pb1 as well, might as well return early here
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb1 = BlockStateInterface.get(x, y + 1, destZ);
|
||||
optionA += MovementHelper.getMiningDurationTicks(context, x, y + 1, destZ, pb1, true);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
// same deal, if pb1 makes optionA nonzero and option B already was nonzero, pb3 can't affect the result
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z);
|
||||
if (optionA == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(pb2.getBlock()) || 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
|
||||
if ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER)) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
optionB += MovementHelper.getMiningDurationTicks(context, destX, y + 1, z, pb3, true);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
|
||||
return COST_INF;
|
||||
}
|
||||
if (optionB == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(pb0.getBlock()) || MovementHelper.avoidWalkingInto(pb1.getBlock())) {
|
||||
// and now that option B is fully calculated, see if we can edge around that way
|
||||
if ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER)) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
boolean water = false;
|
||||
if (BlockStateInterface.isWater(BlockStateInterface.getBlock(x, y, z)) || BlockStateInterface.isWater(destInto.getBlock())) {
|
||||
// Ignore previous multiplier
|
||||
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
|
||||
// Not even touching the blocks below
|
||||
multiplier = WALK_ONE_IN_WATER_COST;
|
||||
multiplier = context.waterWalkSpeed();
|
||||
water = true;
|
||||
}
|
||||
if (optionA != 0 || optionB != 0) {
|
||||
multiplier *= SQRT_2 - 0.001; // TODO tune
|
||||
}
|
||||
if (multiplier == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// If we aren't edging around anything, and we aren't in water or soul sand
|
||||
if (context.canSprint() && !water) {
|
||||
// If we aren't edging around anything, and we aren't in water
|
||||
// We can sprint =D
|
||||
multiplier = SPRINT_ONE_BLOCK_COST;
|
||||
// Don't check for soul sand, since we can sprint on that too
|
||||
multiplier *= SPRINT_MULTIPLIER;
|
||||
}
|
||||
return multiplier * SQRT_2;
|
||||
}
|
||||
|
||||
@@ -30,7 +30,7 @@ import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.RayTraceUtils;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MoveResult;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -49,8 +49,9 @@ public class MovementFall extends Movement {
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
MoveResult result = MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z);
|
||||
if (result.destY != dest.y) {
|
||||
MutableMoveResult result = new MutableMoveResult();
|
||||
MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
|
||||
if (result.y != dest.y) {
|
||||
return COST_INF; // doesn't apply to us, this position is a descend not a fall
|
||||
}
|
||||
return result.cost;
|
||||
@@ -111,6 +112,11 @@ public class MovementFall extends Movement {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean safeToCancel(MovementState state) {
|
||||
return state.getStatus() != MovementStatus.RUNNING;
|
||||
}
|
||||
|
||||
private static BetterBlockPos[] buildPositionsToBreak(BetterBlockPos src, BetterBlockPos dest) {
|
||||
BetterBlockPos[] toBreak;
|
||||
int diffX = src.getX() - dest.getX();
|
||||
|
||||
@@ -24,10 +24,12 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MoveResult;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -37,8 +39,6 @@ import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
import static baritone.utils.pathing.MoveResult.IMPOSSIBLE;
|
||||
|
||||
public class MovementParkour extends Movement {
|
||||
|
||||
private static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
|
||||
@@ -48,72 +48,81 @@ public class MovementParkour extends Movement {
|
||||
private final int dist;
|
||||
|
||||
private MovementParkour(BetterBlockPos src, int dist, EnumFacing dir) {
|
||||
super(src, src.offset(dir, dist), EMPTY);
|
||||
super(src, src.offset(dir, dist), EMPTY, src.offset(dir, dist).down());
|
||||
this.direction = dir;
|
||||
this.dist = dist;
|
||||
}
|
||||
|
||||
public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) {
|
||||
MoveResult res = cost(context, src.x, src.y, src.z, direction);
|
||||
int dist = Math.abs(res.destX - src.x) + Math.abs(res.destZ - src.z);
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
cost(context, src.x, src.y, src.z, direction, res);
|
||||
int dist = Math.abs(res.x - src.x) + Math.abs(res.z - src.z);
|
||||
return new MovementParkour(src, dist, direction);
|
||||
}
|
||||
|
||||
public static MoveResult cost(CalculationContext context, int x, int y, int z, EnumFacing dir) {
|
||||
public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
|
||||
if (!Baritone.settings().allowParkour.get()) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
int xDiff = dir.getXOffset();
|
||||
int zDiff = dir.getZOffset();
|
||||
IBlockState adj = BlockStateInterface.get(x + xDiff, y - 1, z + zDiff);
|
||||
if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.canWalkOn(x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y, z + zDiff)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y + 1, z + zDiff)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x + xDiff, y + 2, z + zDiff)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(x, y + 2, z)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
for (int i = 2; i <= (context.canSprint() ? 4 : 3); i++) {
|
||||
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
|
||||
for (int y2 = 0; y2 < 4; y2++) {
|
||||
if (!MovementHelper.fullyPassable(x + xDiff * i, y + y2, z + zDiff * i)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (MovementHelper.canWalkOn(x + xDiff * i, y - 1, z + zDiff * i)) {
|
||||
return new MoveResult(x + xDiff * i, y, z + zDiff * i, costFromJumpDistance(i));
|
||||
res.x = x + xDiff * i;
|
||||
res.y = y;
|
||||
res.z = z + zDiff * i;
|
||||
res.cost = costFromJumpDistance(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (!context.canSprint()) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!Baritone.settings().allowParkourPlace.get()) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (!Baritone.settings().allowPlace.get()) {
|
||||
Helper.HELPER.logDirect("allowParkourPlace enabled but allowPlace disabled?");
|
||||
return;
|
||||
}
|
||||
int destX = x + 4 * xDiff;
|
||||
int destZ = z + 4 * zDiff;
|
||||
IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
if (!context.hasThrowaway()) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
|
||||
return IMPOSSIBLE;
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
@@ -122,10 +131,13 @@ public class MovementParkour extends Movement {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(againstX, y - 1, againstZ)) {
|
||||
return new MoveResult(destX, y, destZ, costFromJumpDistance(i) + context.placeBlockCost());
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
res.cost = costFromJumpDistance(4) + context.placeBlockCost();
|
||||
return;
|
||||
}
|
||||
}
|
||||
return IMPOSSIBLE;
|
||||
}
|
||||
|
||||
private static double costFromJumpDistance(int dist) {
|
||||
@@ -137,15 +149,16 @@ public class MovementParkour extends Movement {
|
||||
case 4:
|
||||
return SPRINT_ONE_BLOCK_COST * 4;
|
||||
default:
|
||||
throw new IllegalStateException("LOL");
|
||||
throw new IllegalStateException("LOL " + dist);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
MoveResult res = cost(context, src.x, src.y, src.z, direction);
|
||||
if (res.destX != dest.x || res.destZ != dest.z) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
cost(context, src.x, src.y, src.z, direction, res);
|
||||
if (res.x != dest.x || res.z != dest.z) {
|
||||
return COST_INF;
|
||||
}
|
||||
return res.cost;
|
||||
@@ -162,7 +175,13 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
if (playerFeet().equals(dest)) {
|
||||
if (player().posY - playerFeet().getY() < 0.01) {
|
||||
Block d = BlockStateInterface.getBlock(dest);
|
||||
if (d == Blocks.VINE || d == Blocks.LADDER) {
|
||||
// it physically hurt me to add support for parkour jumping onto a vine
|
||||
// but i did it anyway
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
}
|
||||
if (player().posY - playerFeet().getY() < 0.094) { // lilypads
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
}
|
||||
} else if (!playerFeet().equals(src)) {
|
||||
|
||||
@@ -67,8 +67,10 @@ public class MovementTraverse extends Movement {
|
||||
Block srcDown = BlockStateInterface.getBlock(x, y - 1, z);
|
||||
if (MovementHelper.canWalkOn(destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
boolean water = false;
|
||||
if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) {
|
||||
WC = WALK_ONE_IN_WATER_COST;
|
||||
WC = context.waterWalkSpeed();
|
||||
water = true;
|
||||
} else {
|
||||
if (destOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
@@ -83,10 +85,11 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false);
|
||||
if (hardness1 == 0 && hardness2 == 0) {
|
||||
if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// If there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing
|
||||
if (!water && context.canSprint()) {
|
||||
// If there's nothing in the way, and this isn't water, and we aren't sneak placing
|
||||
// We can sprint =D
|
||||
WC = SPRINT_ONE_BLOCK_COST;
|
||||
// Don't check for soul sand, since we can sprint on that too
|
||||
WC *= SPRINT_MULTIPLIER;
|
||||
}
|
||||
return WC;
|
||||
}
|
||||
@@ -113,7 +116,7 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb1, true);
|
||||
|
||||
double WC = throughWater ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST;
|
||||
double WC = throughWater ? context.waterWalkSpeed() : WALK_ONE_BLOCK_COST;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
int againstX = destX + HORIZONTALS[i].getXOffset();
|
||||
int againstZ = destZ + HORIZONTALS[i].getZOffset();
|
||||
@@ -266,7 +269,7 @@ public class MovementTraverse extends Movement {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) {
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && (Minecraft.getMinecraft().player.isSneaking() || Baritone.settings().assumeSafeWalk.get())) {
|
||||
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
@@ -291,9 +294,17 @@ public class MovementTraverse extends Movement {
|
||||
double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D;
|
||||
// faceX, faceY, faceZ is the middle of the face between from and to
|
||||
BlockPos goalLook = src.down(); // this is the block we were just standing on, and the one we want to place against
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
Rotation backToFace = Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
|
||||
float pitch = backToFace.getPitch();
|
||||
double dist = Math.max(Math.abs(player().posX - faceX), Math.abs(player().posZ - faceZ));
|
||||
if (dist < 0.29) {
|
||||
float yaw = Utils.calcRotationFromVec3d(Utils.getBlockPosCenter(dest), playerHead(), playerRotations()).getYaw();
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(yaw, pitch), true));
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
} else {
|
||||
state.setTarget(new MovementState.MovementTarget(backToFace, true));
|
||||
}
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), goalLook)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); // wait to right click until we are able to place
|
||||
|
||||
@@ -20,11 +20,12 @@ package baritone.pathing.path;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.*;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.Tuple;
|
||||
@@ -110,7 +111,7 @@ public class PathExecutor implements Helper {
|
||||
for (int j = pathPosition; j <= previousPos; j++) {
|
||||
path.movements().get(j).reset();
|
||||
}
|
||||
clearKeys();
|
||||
onChangeInPathPosition();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -121,7 +122,7 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
System.out.println("Double skip sundae");
|
||||
pathPosition = i - 1;
|
||||
clearKeys();
|
||||
onChangeInPathPosition();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -217,12 +218,13 @@ public class PathExecutor implements Helper {
|
||||
System.out.println("Recalculating break and place took " + (end - start) + "ms");
|
||||
}
|
||||
Movement movement = path.movements().get(pathPosition);
|
||||
boolean canCancel = movement.safeToCancel();
|
||||
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
|
||||
costEstimateIndex = pathPosition;
|
||||
// do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now
|
||||
currentMovementOriginalCostEstimate = movement.getCost(null);
|
||||
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
|
||||
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF) {
|
||||
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF && canCancel) {
|
||||
logDebug("Something has changed in the world and a future movement has become impossible. Cancelling.");
|
||||
cancel();
|
||||
return true;
|
||||
@@ -230,12 +232,12 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
}
|
||||
double currentCost = movement.recalculateCost();
|
||||
if (currentCost >= ActionCosts.COST_INF) {
|
||||
if (currentCost >= ActionCosts.COST_INF && canCancel) {
|
||||
logDebug("Something has changed in the world and this movement has become impossible. Cancelling.");
|
||||
cancel();
|
||||
return true;
|
||||
}
|
||||
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get()) {
|
||||
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) {
|
||||
logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling.");
|
||||
cancel();
|
||||
return true;
|
||||
@@ -249,8 +251,7 @@ public class PathExecutor implements Helper {
|
||||
if (movementStatus == SUCCESS) {
|
||||
//System.out.println("Movement done, next path");
|
||||
pathPosition++;
|
||||
ticksOnCurrent = 0;
|
||||
clearKeys();
|
||||
onChangeInPathPosition();
|
||||
onTick(event);
|
||||
return true;
|
||||
} else {
|
||||
@@ -320,10 +321,20 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
|
||||
Movement next = path.movements().get(pathPosition + 1);
|
||||
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
|
||||
// a descend then an ascend in the same direction
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
pathPosition++;
|
||||
// okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric
|
||||
logDebug("Skipping descend to straight ascend");
|
||||
return;
|
||||
}
|
||||
if (canSprintInto(current, next)) {
|
||||
if (playerFeet().equals(current.getDest())) {
|
||||
pathPosition++;
|
||||
clearKeys();
|
||||
onChangeInPathPosition();
|
||||
}
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
@@ -332,6 +343,19 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
|
||||
}
|
||||
if (current instanceof MovementAscend && pathPosition != 0) {
|
||||
Movement prev = path.movements().get(pathPosition - 1);
|
||||
if (prev instanceof MovementDescend && prev.getDirection().up().equals(current.getDirection().down())) {
|
||||
BlockPos center = current.getSrc().up();
|
||||
if (player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.JUMP, false);
|
||||
if (!player().isSprinting()) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
player().setSprinting(false);
|
||||
}
|
||||
|
||||
@@ -352,6 +376,11 @@ public class PathExecutor implements Helper {
|
||||
return false;
|
||||
}
|
||||
|
||||
private void onChangeInPathPosition() {
|
||||
clearKeys();
|
||||
ticksOnCurrent = 0;
|
||||
}
|
||||
|
||||
private static void clearKeys() {
|
||||
// i'm just sick and tired of this snippet being everywhere lol
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
@@ -359,6 +388,7 @@ public class PathExecutor implements Helper {
|
||||
|
||||
private void cancel() {
|
||||
clearKeys();
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
pathPosition = path.length() + 3;
|
||||
failed = true;
|
||||
}
|
||||
|
||||
@@ -22,48 +22,102 @@ import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.client.tutorial.TutorialSteps;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.GameType;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
import net.minecraft.world.WorldType;
|
||||
|
||||
public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
public static final boolean ENABLE_AUTO_TEST = true;
|
||||
|
||||
public static final BaritoneAutoTest INSTANCE = new BaritoneAutoTest();
|
||||
|
||||
private BaritoneAutoTest() {}
|
||||
|
||||
public static final boolean ENABLE_AUTO_TEST = "true".equals(System.getenv("BARITONE_AUTO_TEST"));
|
||||
private static final long TEST_SEED = -928872506371745L;
|
||||
private static final BlockPos STARTING_POSITION = new BlockPos(50, 65, 50);
|
||||
private static final BlockPos STARTING_POSITION = new BlockPos(0, 65, 0);
|
||||
private static final Goal GOAL = new GoalBlock(69, 121, 420);
|
||||
private static final int MAX_TICKS = 3200;
|
||||
private static final int MAX_TICKS = 3500;
|
||||
|
||||
/**
|
||||
* Called right after the {@link GameSettings} object is created in the {@link Minecraft} instance.
|
||||
*/
|
||||
public void onPreInit() {
|
||||
if (!BaritoneAutoTest.ENABLE_AUTO_TEST) {
|
||||
return;
|
||||
}
|
||||
System.out.println("Optimizing Game Settings");
|
||||
|
||||
GameSettings s = mc.gameSettings;
|
||||
s.limitFramerate = 20;
|
||||
s.mipmapLevels = 0;
|
||||
s.particleSetting = 2;
|
||||
s.overrideWidth = 128;
|
||||
s.overrideHeight = 128;
|
||||
s.heldItemTooltips = false;
|
||||
s.entityShadows = false;
|
||||
s.chatScale = 0.0F;
|
||||
s.ambientOcclusion = 0;
|
||||
s.clouds = 0;
|
||||
s.fancyGraphics = false;
|
||||
s.tutorialStep = TutorialSteps.NONE;
|
||||
s.hideGUI = true;
|
||||
s.fovSetting = 30.0F;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (mc.currentScreen != null && mc.currentScreen instanceof GuiMainMenu) {
|
||||
|
||||
// If we're on the main menu then create the test world and launch the integrated server
|
||||
if (mc.currentScreen instanceof GuiMainMenu) {
|
||||
System.out.println("Beginning Baritone automatic test routine");
|
||||
mc.displayGuiScreen(null);
|
||||
WorldSettings worldsettings = new WorldSettings(TEST_SEED, GameType.getByName("survival"), true, false, WorldType.DEFAULT);
|
||||
worldsettings.setGeneratorOptions("");
|
||||
mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings);
|
||||
}
|
||||
|
||||
// If the integrated server is launched and the world has initialized, set the spawn point
|
||||
// to our defined starting position
|
||||
if (mc.getIntegratedServer() != null && mc.getIntegratedServer().worlds[0] != null) {
|
||||
mc.getIntegratedServer().worlds[0].setSpawnPoint(STARTING_POSITION);
|
||||
mc.getIntegratedServer().worlds[0].getGameRules().setOrCreateGameRule("spawnRadius", "0");
|
||||
}
|
||||
if (event.getType() == TickEvent.Type.IN) {
|
||||
|
||||
if (event.getType() == TickEvent.Type.IN) { // If we're in-game
|
||||
|
||||
// Force the integrated server to share the world to LAN so that
|
||||
// the ingame pause menu gui doesn't actually pause our game
|
||||
if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) {
|
||||
mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false);
|
||||
}
|
||||
if (event.getCount() < 100) {
|
||||
|
||||
// For the first 200 ticks, wait for the world to generate
|
||||
if (event.getCount() < 200) {
|
||||
System.out.println("Waiting for world to generate... " + event.getCount());
|
||||
return;
|
||||
}
|
||||
if (event.getCount() % 100 == 0) { // print only once every 5 seconds
|
||||
|
||||
// Print out an update of our position every 5 seconds
|
||||
if (event.getCount() % 100 == 0) {
|
||||
System.out.println(playerFeet() + " " + event.getCount());
|
||||
}
|
||||
|
||||
// Setup Baritone's pathing goal and (if needed) begin pathing
|
||||
PathingBehavior.INSTANCE.setGoal(GOAL);
|
||||
PathingBehavior.INSTANCE.path();
|
||||
|
||||
// If we have reached our goal, print a message and safely close the game
|
||||
if (GOAL.isInGoal(playerFeet())) {
|
||||
System.out.println("Successfully pathed to " + playerFeet() + " in " + event.getCount() + " ticks");
|
||||
mc.shutdown();
|
||||
}
|
||||
|
||||
// If we have exceeded the expected number of ticks to complete the pathing
|
||||
// task, then throw an IllegalStateException to cause the build to fail
|
||||
if (event.getCount() > MAX_TICKS) {
|
||||
throw new IllegalStateException("took too long");
|
||||
}
|
||||
|
||||
@@ -31,7 +31,10 @@ import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.movement.*;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.entity.Entity;
|
||||
@@ -198,7 +201,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.equals("cancel")) {
|
||||
if (msg.equals("cancel") || msg.equals("stop")) {
|
||||
MineBehavior.INSTANCE.cancel();
|
||||
FollowBehavior.INSTANCE.cancel();
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
@@ -477,5 +480,15 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.equals("pause")) {
|
||||
boolean enabled = PathingBehavior.INSTANCE.toggle();
|
||||
logDirect("Pathing Behavior has " + (enabled ? "resumed" : "paused") + ".");
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.equals("damn")) {
|
||||
logDirect("daniel");
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,8 +22,8 @@ import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalTwoBlocks;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -49,7 +49,7 @@ import static org.lwjgl.opengl.GL11.*;
|
||||
* @since 8/9/2018 4:39 PM
|
||||
*/
|
||||
public final class PathRenderer implements Helper {
|
||||
|
||||
|
||||
private static final Tessellator TESSELLATOR = Tessellator.getInstance();
|
||||
private static final BufferBuilder BUFFER = TESSELLATOR.getBuffer();
|
||||
|
||||
@@ -68,22 +68,24 @@ public final class PathRenderer implements Helper {
|
||||
int fadeStart = fadeStart0 + startIndex;
|
||||
int fadeEnd = fadeEnd0 + startIndex;
|
||||
for (int i = startIndex; i < positions.size() - 1; i = next) {
|
||||
BlockPos start = positions.get(i);
|
||||
BetterBlockPos start = positions.get(i);
|
||||
|
||||
next = i + 1;
|
||||
BlockPos end = positions.get(next);
|
||||
BetterBlockPos end = positions.get(next);
|
||||
|
||||
BlockPos direction = Utils.diff(start, end);
|
||||
while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && direction.equals(Utils.diff(end, positions.get(next + 1)))) {
|
||||
int dirX = end.x - start.x;
|
||||
int dirY = end.y - start.y;
|
||||
int dirZ = end.z - start.z;
|
||||
while (next + 1 < positions.size() && (!fadeOut || next + 1 < fadeStart) && (dirX == positions.get(next + 1).x - end.x && dirY == positions.get(next + 1).y - end.y && dirZ == positions.get(next + 1).z - end.z)) {
|
||||
next++;
|
||||
end = positions.get(next);
|
||||
}
|
||||
double x1 = start.getX();
|
||||
double y1 = start.getY();
|
||||
double z1 = start.getZ();
|
||||
double x2 = end.getX();
|
||||
double y2 = end.getY();
|
||||
double z2 = end.getZ();
|
||||
double x1 = start.x;
|
||||
double y1 = start.y;
|
||||
double z1 = start.z;
|
||||
double x2 = end.x;
|
||||
double y2 = end.y;
|
||||
double z2 = end.z;
|
||||
if (fadeOut) {
|
||||
|
||||
float alpha;
|
||||
|
||||
@@ -67,7 +67,14 @@ public class ToolSet implements Helper {
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public double getStrVsBlock(IBlockState state) {
|
||||
return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(getBestSlot(state), state));
|
||||
Double strength = this.breakStrengthCache.get(state.getBlock());
|
||||
if (strength != null) {
|
||||
// the function will take this path >99% of the time
|
||||
return strength;
|
||||
}
|
||||
double str = calculateStrVsBlock(getBestSlot(state), state);
|
||||
this.breakStrengthCache.put(state.getBlock(), str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -130,8 +130,4 @@ public final class Utils {
|
||||
public static double radToDeg(double rad) {
|
||||
return rad * RAD_TO_DEG;
|
||||
}
|
||||
|
||||
public static BlockPos diff(BlockPos a, BlockPos b) {
|
||||
return new BlockPos(a.getX() - b.getX(), a.getY() - b.getY(), a.getZ() - b.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,14 +36,12 @@ public final class BetterBlockPos extends BlockPos {
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
public final long hashCode;
|
||||
|
||||
public BetterBlockPos(int x, int y, int z) {
|
||||
super(x, y, z);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
this.hashCode = AbstractNodeCostSearch.posHash(x, y, z);
|
||||
}
|
||||
|
||||
public BetterBlockPos(double x, double y, double z) {
|
||||
@@ -56,7 +54,11 @@ public final class BetterBlockPos extends BlockPos {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) hashCode;
|
||||
return (int) AbstractNodeCostSearch.posHash(x, y, z);
|
||||
}
|
||||
|
||||
public static long longHash(BetterBlockPos pos) {
|
||||
return AbstractNodeCostSearch.posHash(pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -66,9 +68,6 @@ public final class BetterBlockPos extends BlockPos {
|
||||
}
|
||||
if (o instanceof BetterBlockPos) {
|
||||
BetterBlockPos oth = (BetterBlockPos) o;
|
||||
if (oth.hashCode != hashCode) {
|
||||
return false;
|
||||
}
|
||||
return oth.x == x && oth.y == y && oth.z == z;
|
||||
}
|
||||
// during path execution, like "if (whereShouldIBe.equals(whereAmI)) {"
|
||||
|
||||
@@ -17,24 +17,27 @@
|
||||
|
||||
package baritone.utils.pathing;
|
||||
|
||||
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
|
||||
/**
|
||||
* The result of a calculated movement, with destination x, y, z, and the cost of performing the movement
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class MoveResult {
|
||||
public static final MoveResult IMPOSSIBLE = new MoveResult(0, 0, 0, COST_INF);
|
||||
public final int destX;
|
||||
public final int destY;
|
||||
public final int destZ;
|
||||
public final double cost;
|
||||
public final class MutableMoveResult {
|
||||
public int x;
|
||||
public int y;
|
||||
public int z;
|
||||
public double cost;
|
||||
|
||||
public MoveResult(int x, int y, int z, double cost) {
|
||||
this.destX = x;
|
||||
this.destY = y;
|
||||
this.destZ = z;
|
||||
this.cost = cost;
|
||||
public MutableMoveResult() {
|
||||
reset();
|
||||
}
|
||||
|
||||
public final void reset() {
|
||||
x = 0;
|
||||
y = 0;
|
||||
z = 0;
|
||||
cost = ActionCosts.COST_INF;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1 @@
|
||||
baritone.BaritoneProvider
|
||||
Reference in New Issue
Block a user