Compare commits

...

94 Commits

Author SHA1 Message Date
Leijurv
78b626af23 v0.0.6 2018-10-05 15:42:02 -07:00
Leijurv
046de84360 that should really default to true 2018-10-05 14:39:17 -07:00
Leijurv
ca48dabcc7 change sneak-backplace behavior, fixes #208 2018-10-05 13:49:47 -07:00
Leijurv
9880a4e948 when asusmeSafeWalk is on, we don't sneak in the first place 2018-10-05 13:11:09 -07:00
Leijurv
cb589219d8 use mutable move result to avoid instantianing ten million move result objects 2018-10-05 12:32:42 -07:00
Leijurv
6fff4c5254 reduce repetition in Moves 2018-10-05 10:17:58 -07:00
Leijurv
4049c116d9 dynamicY and yOffset 2018-10-05 10:10:24 -07:00
Leijurv
b720742f53 render the goal block, fixes #166 2018-10-04 21:28:34 -07:00
leijurv
c1af050fa6 fix lilypad fall cost, fixes #207 2018-10-04 16:01:27 -07:00
Leijurv
39f415d4be allowplace and allowparkourplace 2018-10-03 19:00:58 -07:00
Leijurv
4590b9f6da they say you are what you eat, but i don't remember eating a minecraft damn daniel mod 2018-10-03 13:45:43 -07:00
Brady
ee6e0b1784 Add message and actually cancel event 2018-10-03 12:45:57 -05:00
Brady
820c108548 Add pause "command" in ExampleBaritoneControl 2018-10-03 12:44:28 -05:00
Leijurv
239bb14e3a add blockBreakAdditionalPenalty 2018-10-03 08:20:24 -07:00
Leijurv
1bd7c8455f crucial performance optimization 2018-10-03 08:14:15 -07:00
Leijurv
6986f179cd it's not much of an improvement, but it won't make it slower 2018-10-03 08:12:57 -07:00
Leijurv
28af41b789 defer movement propagation and assembly to postprocessing 2018-10-03 08:04:30 -07:00
Leijurv
36bdaa99ec DAE BlockPos bad? 2018-10-03 07:57:24 -07:00
Leijurv
1ee44024b2 don't construct favored positions hashset if the coefficient renders it useless 2018-10-03 07:52:17 -07:00
Leijurv
cd926283b3 avoid synthetic lambda creation 2018-10-03 07:48:26 -07:00
Leijurv
04d210bd8b no need to calculate the hash on contstruction anymore 2018-10-03 07:43:45 -07:00
Leijurv
38895beb5d remove width and height override part 2: electric boogaloo 2018-10-02 17:15:00 -07:00
Leijurv
3fdc4d6ee0 parkour jumping onto a vine, sort of 2018-10-02 15:34:46 -07:00
Leijurv
baf27363aa fix movement ascend x z cardinal asymmetry, fixes #204 2018-10-02 15:02:27 -07:00
Leijurv
da137f35de fix parkour jumps ending on lilypads, fixes #203 2018-10-02 14:04:24 -07:00
Brady
feeeae5918 Add autotest directory to gitignore
If you're not using "autotest" as ur auto test "testing" directory, you SHOULD.
2018-10-02 15:28:20 -05:00
Brady
02a04773c6 bad javadocs 2018-10-02 15:27:25 -05:00
Brady
7e7b9f4fdb Make MemoryBehavior store data by world 2018-10-02 15:25:58 -05:00
Leijurv
85e4a57c76 no longer needed since goal is in api which in unobfed 2018-10-02 10:19:14 -07:00
Leijurv
6fd7b2a7f3 fix proguard for service provider 2018-10-02 10:17:56 -07:00
Leijurv
24be1d0ff3 lookahead a little more 2018-10-02 10:01:54 -07:00
Leijurv
2867e0626f reenable diagonal through water 2018-10-02 09:59:07 -07:00
Leijurv
f0c3e59a6f move from todo to issue 2018-10-01 22:50:51 -07:00
Leijurv
4e11d92d19 fix parkour cost calculation 2018-10-01 19:23:13 -07:00
Leijurv
07eee481cb fix failure on repeated descend 2018-10-01 15:42:16 -07:00
Leijurv
8f146d1a2b increase degree of backtrack cost favoring 2018-10-01 15:35:18 -07:00
Leijurv
1cc03e3aca it doesn't actually have to be falling, it just has to be solid 2018-10-01 15:20:52 -07:00
Leijurv
023822b5d9 stop breaking block on cancel, even if not requested by player 2018-10-01 15:11:52 -07:00
Leijurv
41ffd4455d don't cancel for any reason while doing a water bucket fall, fixes #98, fixes #123 2018-10-01 14:50:20 -07:00
Leijurv
810b92fbad Merge pull request #193 from cabaletta/service-loader
Service loader
2018-10-01 14:37:15 -07:00
Leijurv
6db31cbe74 now that that's fixed, we can tighten the maximum time again 2018-10-01 14:37:01 -07:00
Leijurv
b55a102d37 take depth strider into acocunt for water speed, fixes #101 2018-10-01 14:26:55 -07:00
Leijurv
f338cdd2e5 clear all keys including sprint in the next movement, fixes #194 2018-10-01 14:26:08 -07:00
Leijurv
76365a4564 sprint on soul sand, fixes #120 2018-10-01 10:05:04 -07:00
Leijurv
109cffc3de rearrange blockstate lookups 2018-10-01 09:57:47 -07:00
Leijurv
c67339dc42 Merge branch 'master' into service-loader 2018-10-01 09:53:03 -07:00
Leijurv
f56766be26 maybe it just needs more time 2018-10-01 09:51:43 -07:00
Leijurv
b1e1cc43e0 simplify properly even when obfuscated 2018-09-30 21:43:07 -07:00
Leijurv
13aaec07cd draw most recent node considered even if there is no valid best 2018-09-30 21:42:34 -07:00
Leijurv
08b9eab9f3 draw most recent node considered even if there is no valid best 2018-09-30 21:32:13 -07:00
Leijurv
09ac3c615c more time maybe 2018-09-30 09:14:23 -07:00
Leijurv
19ce1cf4a7 Merge branch 'master' into service-loader 2018-09-30 08:08:46 -07:00
Leijurv
d58ad6f68f finalize 2018-09-30 08:03:33 -07:00
Leijurv
866648192b readd width and height override 2018-09-30 07:58:44 -07:00
Brady
3184eaf595 Remove IBaritoneProvider#getSettings 2018-09-29 23:59:32 -05:00
Brady
b12c2ea62f UTILIZE Service Loaders
https://i.imgur.com/kAm0xd3.png
2018-09-29 23:52:01 -05:00
Leijurv
bcb95c55c9 allow a bit more time, it's a little flaky on travis right now 2018-09-29 07:43:34 -07:00
Leijurv
229739575c BaritoneAutoTest overrides width and height on its own 2018-09-29 07:32:58 -07:00
Leijurv
4b76af2487 update settings link 2018-09-29 07:30:56 -07:00
Leijurv
c383186808 sprint through descend then ascend in the same direction, fixes #115 2018-09-28 18:55:04 -07:00
Leijurv
2f602f8718 no stop dont 2018-09-27 16:11:55 -07:00
Leijurv
015462eddb beg people not to disable chunk caching 2018-09-27 15:37:22 -07:00
Leijurv
de6d6c8714 cached chunks expiration setting, fixes #181 2018-09-27 15:19:55 -07:00
Leijurv
1b2304146b reorganized diagonal 2018-09-26 17:25:18 -07:00
Leijurv
f28cdc531f this will really help performance a lot 2018-09-26 15:34:06 -07:00
Leijurv
2aa4770b45 add settings for pathing hashmap 2018-09-26 15:01:14 -07:00
Brady
1d931a4bb6 lol epic 2018-09-26 16:21:53 -05:00
Leijurv
9094c712d6 only optimize game settings if we are going to be auto testing 2018-09-26 13:46:08 -07:00
Leijurv
40a3177ae7 no need to get that twice 2018-09-26 13:05:36 -07:00
Leijurv
8ef89a8c80 bump mixin 2018-09-26 12:43:00 -07:00
Leijurv
ceb9ad9aa8 retry failed dependency downloads 2018-09-26 12:40:53 -07:00
Leijurv
dec1877123 bump lwjgl 2018-09-26 12:36:07 -07:00
Leijurv
34aa7cb6b5 only 1.11 exists 2018-09-26 11:22:06 -07:00
Leijurv
730ebb0070 remove sources 2018-09-26 11:09:25 -07:00
Leijurv
c4a3820c6a Try in other order 2018-09-26 10:46:42 -07:00
Leijurv
d4a846a672 maybe fix 2018-09-26 10:18:08 -07:00
Leijurv
a125170840 fix proguard path 2018-09-26 10:12:23 -07:00
Leijurv
d5d1d65bf3 fix build failure on repeated runs 2018-09-26 10:07:44 -07:00
Leijurv
fb45d73406 fetch jars from gradle instead of dropbox, fixes #189 2018-09-26 10:06:52 -07:00
Leijurv
5ec3971380 should match build.gradle 2018-09-26 09:51:25 -07:00
Leijurv
63b6169475 renamed 1.12.2 to minecraft 1.12.2 2018-09-26 09:50:24 -07:00
Leijurv
ab0d713882 THX 0x22 2018-09-25 22:18:19 -07:00
Leijurv
19661cc99c it takes more time to go a longer distance what a wild concept 2018-09-25 22:07:51 -07:00
Leijurv
d58656571a thx 0x22 2018-09-25 21:58:22 -07:00
Leijurv
4900c76752 merge 2018-09-25 21:57:00 -07:00
Brady
d899ff7f7b 2 iq 2018-09-25 23:24:48 -05:00
Brady
36651553fe Increase max ticks accordingly
See last commit
2018-09-25 23:17:15 -05:00
Brady
d9596fcac9 Travis may actually take 10 seconds to load in 2018-09-25 23:16:20 -05:00
Leijurv
aa7b77b413 can't pause on lost focus in xvfb 2018-09-25 18:57:50 -07:00
Brady
b3f06c6fac Allow pause on lost focus 2018-09-25 20:54:33 -05:00
Brady
3483be4bed Sync framerate limit with tps in auto test 2018-09-25 20:43:49 -05:00
Brady
d7a0d26fd2 Optimize game settings for better travis performance 2018-09-25 20:31:54 -05:00
Brady
90666cdfc1 Plutie's Jenkins is back 2018-09-25 19:04:34 -05:00
Leijurv
3072de610c add release link 2018-09-25 16:17:32 -07:00
46 changed files with 896 additions and 441 deletions

1
.gitignore vendored
View File

@@ -2,6 +2,7 @@
**/*.swp
run/
autotest/
# Gradle
build/

View File

@@ -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"

View File

@@ -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

View File

@@ -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

View File

@@ -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

View File

@@ -3,12 +3,7 @@
[![License](https://img.shields.io/github/license/cabaletta/baritone.svg)](LICENSE)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/7150d8ccf6094057b1782aa7a8f92d7d)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade)
<!---
Plutie's jenkins is dead right now, so here's the old badge that was used:
[![Build Status](https://plutiejenkins.leijurv.com/job/baritone/badge/icon)](https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/)
--->
Unofficial Jenkins: [![Jenkins Status](https://img.shields.io/badge/jenkins-offline-red.svg)]()
Unofficial Jenkins: [![Build Status](https://plutiejenkins.leijurv.com/job/baritone/badge/icon)](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.

View File

@@ -16,7 +16,7 @@
*/
group 'baritone'
version '0.0.3'
version '0.0.6'
buildscript {
repositories {

View File

@@ -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
View File

@@ -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?

View File

@@ -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
}

View 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();
}

View File

@@ -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

View File

@@ -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();
}

View File

@@ -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,

View File

@@ -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(

View File

@@ -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())) {

View 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;
}
}

View File

@@ -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 {

View File

@@ -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();

View File

@@ -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();
}

View File

@@ -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
*/

View File

@@ -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;

View File

@@ -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) {

View File

@@ -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) {

View File

@@ -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);
}

View File

@@ -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();
/**

View File

@@ -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();

View File

@@ -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;
}
}

View File

@@ -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

View File

@@ -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) {

View File

@@ -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();
}
}

View File

@@ -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

View File

@@ -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;
}
}
}

View File

@@ -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;
}

View File

@@ -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();

View File

@@ -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)) {

View File

@@ -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

View File

@@ -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;
}

View File

@@ -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");
}

View File

@@ -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;
}
}
}

View File

@@ -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;

View File

@@ -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;
}
/**

View File

@@ -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());
}
}

View File

@@ -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)) {"

View File

@@ -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;
}
}

View File

@@ -0,0 +1 @@
baritone.BaritoneProvider