Compare commits
167 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| e661330fb6 | |||
| 9b13380b29 | |||
| b48444da8c | |||
| 11a4225eaf | |||
| 0611e3088e | |||
| 73628f09c1 | |||
| a907746f53 | |||
| 8189e90569 | |||
| 9f83677df9 | |||
| 5265c46f60 | |||
| 6d37e14b0e | |||
| fbecff52af | |||
| 4af14cf0a6 | |||
| 16a201255e | |||
| 22bb9f0ec8 | |||
| 654ac1075a | |||
| ffc050668b | |||
| 80f65452e1 | |||
| c614d7ec6a | |||
| c37a5ba956 | |||
| da5969c2fd | |||
| 990107a1fa | |||
| 42eb86b624 | |||
| b65a199e54 | |||
| 88e3bcdf63 | |||
| 0fbfa32e6b | |||
| 20405716bc | |||
| 8da7406e8f | |||
| 97fd3df8f7 | |||
| b9b33b5351 | |||
| 19ecb1bbb3 | |||
| f6043f4ac6 | |||
| ed1941abdb | |||
| 24d24728dc | |||
| 77db4cd19f | |||
| adbb03e5cb | |||
| f0226f1ea7 | |||
| be5df2677b | |||
| 3d4a856bb2 | |||
| 1b1233d26a | |||
| c4b0e0a810 | |||
| 1dee8ef355 | |||
| 8cee173f92 | |||
| 19e0e6d962 | |||
| ef8fd70475 | |||
| 6df05f4b7f | |||
| 4e1491a0cc | |||
| 55091154c4 | |||
| a0b1cb2993 | |||
| 7617081637 | |||
| 96e7f37799 | |||
| a0bf22de86 | |||
| 9a1aecc002 | |||
| ad941fcbb2 | |||
| e5ca30dc26 | |||
| a23eadf5cf | |||
| 82417f4f85 | |||
| af788133c2 | |||
| a6dc156a79 | |||
| 25bebdc172 | |||
| b55d96169f | |||
| 1a809fa7a3 | |||
| 313a5fddbe | |||
| 732d806820 | |||
| 11ed8a2f21 | |||
| 3aa8f51015 | |||
| 85b038dada | |||
| dd25527a62 | |||
| ac372bc6fc | |||
| 63ce4fe0bd | |||
| 398169f68e | |||
| 46a24af373 | |||
| 0cd9bb658f | |||
| b0678fd259 | |||
| 9cb4a1779e | |||
| 3cb4700b16 | |||
| 94921fe03f | |||
| 0202865837 | |||
| b9b911eb3b | |||
| 54fb2c5f81 | |||
| 2df97ff986 | |||
| 4374619ba2 | |||
| 6b6ebd6968 | |||
| b41fdc2bbd | |||
| 3cac37d1a5 | |||
| 2f7259714a | |||
| c1076461e2 | |||
| 6fdf845349 | |||
| c80b855dab | |||
| 83fc11e75b | |||
| 9654892e54 | |||
| b46fad1442 | |||
| ff652dbe40 | |||
| 897483884a | |||
| ba68990ef8 | |||
| de29a6532f | |||
| 9045791e7f | |||
| ab2fa0ba88 | |||
| 56b67cbc47 | |||
| b6a1608e73 | |||
| 6277c20e4c | |||
| 2fc282477d | |||
| 917f393f7a | |||
| 045504ecf7 | |||
| 7efc0ae8ca | |||
| 3958dce341 | |||
| d1a9012deb | |||
| dbde993a76 | |||
| 96c66d2809 | |||
| df1633b2a1 | |||
| 24f18f0ac2 | |||
| 416fea2aa5 | |||
| 93286a646f | |||
| 8fba36c05e | |||
| b443be1795 | |||
| 4892192c6c | |||
| 6b7a8e2bd3 | |||
| c5f5445f4b | |||
| 8a65f43a0b | |||
| 76e4a1a649 | |||
| 5167c0c886 | |||
| 9d3d8f6c82 | |||
| 7e4a1169af | |||
| 773ad89951 | |||
| c2adcdb051 | |||
| b75bc6d03d | |||
| e3b80f11ad | |||
| f33a2ef11b | |||
| 130b21f738 | |||
| ee954d6a4e | |||
| 54215bdb18 | |||
| 0db18a7caf | |||
| a1c0f4dbb4 | |||
| db7d3184c9 | |||
| 7dfe6ac3ca | |||
| 8fd921c60e | |||
| fec29d03fd | |||
| 9bd205f190 | |||
| 089037663e | |||
| 8c0bc3e2ef | |||
| db21045cfb | |||
| fbf0f2271c | |||
| 7e78ed2139 | |||
| 5676acbba6 | |||
| 43b155d7b8 | |||
| 93158226b6 | |||
| d3bf4ef198 | |||
| fc9d13a03c | |||
| 22d2036657 | |||
| 9e15960581 | |||
| 738ce25ff0 | |||
| 5da9347e2c | |||
| 771e892b31 | |||
| 9df5f942de | |||
| 0fb5f3233f | |||
| f17ce87e45 | |||
| a497a944a6 | |||
| 2e69bbe371 | |||
| 875f01c358 | |||
| 6a4a8ab2d9 | |||
| 8278576227 | |||
| 7d0aa4d7a5 | |||
| 2b4512ee3f | |||
| e23a9c976a | |||
| 1449edb8af | |||
| d177db5a35 | |||
| 1245e222a7 |
@@ -3,6 +3,7 @@
|
||||
|
||||
run/
|
||||
autotest/
|
||||
dist/
|
||||
|
||||
# Gradle
|
||||
build/
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ install:
|
||||
- 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"
|
||||
- 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; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient"
|
||||
- docker cp baritone:/code/dist dist
|
||||
- ls dist
|
||||
- cat dist/checksums.txt
|
||||
|
||||
+4
-6
@@ -13,14 +13,12 @@ RUN apt install --target-release jessie-backports \
|
||||
|
||||
RUN apt install -qq --force-yes mesa-utils libgl1-mesa-glx libxcursor1 libxrandr2 libxxf86vm1 x11-xserver-utils xfonts-base xserver-common
|
||||
|
||||
RUN apt install -qq --force-yes unzip wget
|
||||
|
||||
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
|
||||
|
||||
# this .deb is specially patched to support lwjgl
|
||||
# source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173
|
||||
RUN dpkg -i scripts/xvfb_1.16.4-1_amd64.deb
|
||||
|
||||
RUN ./gradlew build
|
||||
@@ -1,91 +1 @@
|
||||
# Integration between Baritone and Impact
|
||||
Impact 4.4 will have Baritone included on release, however, if you're impatient, you can install Baritone into Impact 4.3 right now!
|
||||
|
||||
## An Introduction
|
||||
There are some basic steps to getting Baritone setup with Impact.
|
||||
- Acquiring a build of Baritone
|
||||
- Placing Baritone in the libraries directory
|
||||
- Modifying the Impact Profile JSON to run baritone
|
||||
- How to use Baritone
|
||||
|
||||
## Acquiring a build of Baritone
|
||||
There are 3 methods of acquiring a build of Baritone (While it is still in development)
|
||||
|
||||
### 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`.
|
||||
|
||||
The build for `baritone-unoptimized-X.Y.Z.jar` is deterministic, and you can verify Travis did it properly by running `scripts/build.sh` yourself and comparing the shasum. The proguarded files (api and standalone) aren't yet reproducible, because proguard annoyingly includes the current timestamp into the final jar.
|
||||
|
||||
### Building Baritone yourself
|
||||
There are a few steps to this
|
||||
- Clone this repository
|
||||
- Setup the project as instructed in the README
|
||||
- Run the ``build`` gradle task. You can either do this using IntelliJ's gradle UI or through a
|
||||
command line
|
||||
- Windows: ``gradlew build``
|
||||
- Mac/Linux: ``./gradlew build``
|
||||
- The build should be exported into ``/build/libs/baritone-X.Y.Z.jar``
|
||||
|
||||
### Cutting Edge Release
|
||||
If you want to trust @Plutie#9079, you can download an automatically generated build of the latest commit
|
||||
from his Jenkins server, found <a href="https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/">here</a>.
|
||||
|
||||
## Placing Baritone in the libraries directory
|
||||
``/libraries`` is a neat directory in your <a href="https://minecraft.gamepedia.com/.minecraft">Minecraft Installation Directory</a>
|
||||
that contains all of the dependencies that are required from the game and some mods. This is where we will be
|
||||
putting baritone.
|
||||
- Locate the ``libraries`` folder, it should be in the Minecraft Installation Directory
|
||||
- Create 3 new subdirectories starting from ``libraries``
|
||||
- ``cabaletta``
|
||||
- ``baritone``
|
||||
- ``X.Y.Z``
|
||||
- Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder
|
||||
- The full path should look like ``<Minecraft>/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar``
|
||||
|
||||
## Modifying the Impact Profile JSON to run baritone
|
||||
The final step is "registering" the Baritone library with Impact, so that it loads on launch.
|
||||
- Ensure your Minecraft launcher is closed
|
||||
- Navigate back to the Minecraft Installation Directory
|
||||
- Find the ``versions`` directory, and open in
|
||||
- In here there should be a ``1.12.2-Impact_4.3`` folder.
|
||||
- If you don't have any Impact folder or have a version older than 4.3, you can download Impact <a href="https://impactdevelopment.github.io">here</a>.
|
||||
- Open the folder and inside there should be a file called ``1.12.2-Impact_4.3.json``
|
||||
- Open the JSON file with a text editor that supports your system's line endings
|
||||
- For example, Notepad on Windows likely will NOT work for this. You should instead use a Text Editor like
|
||||
<a href="https://notepad-plus-plus.org/">Notepad++</a> if you're on Windows. (For other systems, I'm not sure
|
||||
what would work the best so you may have to do some research.)
|
||||
- Find the ``libraries`` array in the JSON. It should look something like this.
|
||||
```
|
||||
"libraries": [
|
||||
{
|
||||
"name": "net.minecraft:launchwrapper:1.12"
|
||||
},
|
||||
{
|
||||
"name": "com.github.ImpactDevelopment:Impact:4.3-1.12.2",
|
||||
"url": "https://impactdevelopment.github.io/maven/"
|
||||
},
|
||||
{
|
||||
"name": "com.github.ImpactDeveloment:ClientAPI:3.0.2",
|
||||
"url": "https://impactdevelopment.github.io/maven/"
|
||||
},
|
||||
...
|
||||
```
|
||||
- Create a new object in the array, between the ``Impact`` and ``ClientAPI`` dependencies preferably.
|
||||
```
|
||||
{
|
||||
"name": "cabaletta:baritone:X.Y.Z"
|
||||
},
|
||||
```
|
||||
- Now find the ``"minecraftArguments": "..."`` text near the top.
|
||||
- At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like:
|
||||
- ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine"``
|
||||
- If you didn't close your launcher for this step, restart it now.
|
||||
- You can now launch Impact 4.3 as normal, and Baritone should start up
|
||||
|
||||
## How to use Baritone
|
||||
Instructions on how to use Baritone are limited, and you may have to read a little bit of code (Really nothing much
|
||||
just plain English), you can view that <a href="https://github.com/cabaletta/baritone#chat-control">here</a>.
|
||||
Impact 4.4 is out. See <a href="INSTALL.md">INSTALL.md</a>
|
||||
+96
@@ -0,0 +1,96 @@
|
||||
# Integration between Baritone and Impact
|
||||
Impact 4.4 has Baritone included.
|
||||
|
||||
These instructions apply to Impact 4.3 (and potentially other hacked clients).
|
||||
|
||||
To run Baritone on Vanilla, just follow the instructions in the README (it's `./gradlew runClient`).
|
||||
|
||||
|
||||
## An Introduction
|
||||
There are some basic steps to getting Baritone setup with Impact.
|
||||
- Acquiring a build of Baritone
|
||||
- Placing Baritone in the libraries directory
|
||||
- Modifying the Impact Profile JSON to run baritone
|
||||
- How to use Baritone
|
||||
|
||||
## Acquiring a build of Baritone
|
||||
There are two methods of acquiring a build of Baritone
|
||||
|
||||
### 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`.
|
||||
|
||||
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone . && docker run --rm cabaletta/baritone cat /code/dist/checksums.txt` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
|
||||
|
||||
### Building Baritone yourself
|
||||
There are a few steps to this
|
||||
- Clone this repository
|
||||
- Setup the project as instructed in the README
|
||||
- Run the ``build`` gradle task. You can either do this using IntelliJ's gradle UI or through a
|
||||
command line
|
||||
- Windows: ``gradlew build``
|
||||
- Mac/Linux: ``./gradlew build``
|
||||
- The build should be exported into ``/build/libs/baritone-X.Y.Z.jar``
|
||||
|
||||
## Placing Baritone in the libraries directory
|
||||
``/libraries`` is a neat directory in your <a href="https://minecraft.gamepedia.com/.minecraft">Minecraft Installation Directory</a>
|
||||
that contains all of the dependencies that are required from the game and some mods. This is where we will be
|
||||
putting baritone.
|
||||
- Locate the ``libraries`` folder, it should be in the Minecraft Installation Directory
|
||||
- Create 3 new subdirectories starting from ``libraries``
|
||||
- ``cabaletta``
|
||||
- ``baritone``
|
||||
- ``X.Y.Z``
|
||||
- Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder
|
||||
- The full path should look like ``<Minecraft>/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar``
|
||||
|
||||
## Modifying the Impact Profile JSON to run baritone
|
||||
The final step is "registering" the Baritone library with Impact, so that it loads on launch.
|
||||
- Ensure your Minecraft launcher is closed
|
||||
- Navigate back to the Minecraft Installation Directory
|
||||
- Find the ``versions`` directory, and open in
|
||||
- In here there should be a ``1.12.2-Impact_4.3`` folder.
|
||||
- If you don't have any Impact folder or have a version older than 4.3, you can download Impact <a href="https://impactdevelopment.github.io">here</a>.
|
||||
- Open the folder and inside there should be a file called ``1.12.2-Impact_4.3.json``
|
||||
- Open the JSON file with a text editor that supports your system's line endings
|
||||
- For example, Notepad on Windows likely will NOT work for this. You should instead use a Text Editor like
|
||||
<a href="https://notepad-plus-plus.org/">Notepad++</a> if you're on Windows. (For other systems, I'm not sure
|
||||
what would work the best so you may have to do some research.)
|
||||
- Find the ``libraries`` array in the JSON. It should look something like this.
|
||||
```
|
||||
"libraries": [
|
||||
{
|
||||
"name": "net.minecraft:launchwrapper:1.12"
|
||||
},
|
||||
{
|
||||
"name": "com.github.ImpactDevelopment:Impact:4.3-1.12.2",
|
||||
"url": "https://impactdevelopment.github.io/maven/"
|
||||
},
|
||||
{
|
||||
"name": "com.github.ImpactDeveloment:ClientAPI:3.0.2",
|
||||
"url": "https://impactdevelopment.github.io/maven/"
|
||||
},
|
||||
...
|
||||
```
|
||||
- Create two new objects in the array, between the ``Impact`` and ``ClientAPI`` dependencies preferably.
|
||||
```
|
||||
{
|
||||
"name": "cabaletta:baritone:X.Y.Z"
|
||||
},
|
||||
{
|
||||
"name": "com.github.ImpactDevelopment:SimpleTweaker:1.2",
|
||||
"url": "https://impactdevelopment.github.io/maven/"
|
||||
},
|
||||
```
|
||||
- Now find the ``"minecraftArguments": "..."`` text near the top.
|
||||
- At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like:
|
||||
- ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine"``
|
||||
- If you didn't close your launcher for this step, restart it now.
|
||||
- You can now launch Impact 4.3 as normal, and Baritone should start up
|
||||
|
||||
## How to use Baritone
|
||||
Instructions on how to use Baritone are limited, and you may have to read a little bit of code (Really nothing much
|
||||
just plain English), you can view that <a href="https://github.com/cabaletta/baritone#chat-control">here</a>.
|
||||
@@ -1,46 +1,51 @@
|
||||
# Baritone
|
||||
[](https://travis-ci.com/cabaletta/baritone)
|
||||
[](https://github.com/cabaletta/baritone/releases)
|
||||
[](LICENSE)
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
|
||||
Unofficial Jenkins: [](https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/)
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
[](http://hits.dwyl.com/cabaletta/baritone)
|
||||
[](https://github.com/cabaletta/baritone/issues)
|
||||
[](https://minecraft.gamepedia.com/1.12.2)
|
||||
|
||||
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).
|
||||
|
||||
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
|
||||
|
||||
Here are some links to help to get started:
|
||||
|
||||
- [Features](FEATURES.md)
|
||||
|
||||
- [Baritone + Impact](IMPACT.md)
|
||||
- [Installation](INSTALL.md)
|
||||
|
||||
There's also some useful information down below
|
||||
|
||||
# Setup
|
||||
|
||||
## IntelliJ's Gradle UI
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle task `setupDecompWorkspace`
|
||||
- Run the Gradle task `genIntellijRuns`
|
||||
- Refresh the Gradle project (or just restart IntelliJ)
|
||||
- Select the "Minecraft Client" launch config and run
|
||||
|
||||
## Command Line
|
||||
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
|
||||
|
||||
Running Baritone:
|
||||
|
||||
```
|
||||
$ gradlew run
|
||||
$ gradlew runClient
|
||||
```
|
||||
|
||||
Setting up for IntelliJ:
|
||||
Building Baritone:
|
||||
```
|
||||
$ gradlew setupDecompWorkspace
|
||||
$ gradlew --refresh-dependencies
|
||||
$ gradlew genIntellijRuns
|
||||
$ gradlew build
|
||||
```
|
||||
|
||||
For example, to replace out Impact 4.4's Baritone build with a customized one, build Baritone as above then copy `dist/baritone-api-$VERSION.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
|
||||
|
||||
## IntelliJ's Gradle UI
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle task `setupDecompWorkspace`
|
||||
- Run the Gradle task `genIntellijRuns`
|
||||
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
|
||||
- Select the "Minecraft Client" launch config
|
||||
- In `Edit Configurations...` you may need to select `baritone_launch` for `Use classpath of module:`.
|
||||
|
||||
# Chat control
|
||||
[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java)
|
||||
|
||||
|
||||
+21
-33
@@ -1,7 +1,3 @@
|
||||
import java.util.jar.JarEntry
|
||||
import java.util.jar.JarFile
|
||||
import java.util.jar.JarOutputStream
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
@@ -20,7 +16,7 @@ import java.util.jar.JarOutputStream
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '0.0.7'
|
||||
version '1.0.0-hotfix-4'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
@@ -41,6 +37,10 @@ buildscript {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import baritone.gradle.task.CreateDistTask
|
||||
import baritone.gradle.task.ProguardTask
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
@@ -61,7 +61,9 @@ minecraft {
|
||||
mappings = 'snapshot_20180731'
|
||||
tweakClass = 'baritone.launch.BaritoneTweaker'
|
||||
runDir = 'run'
|
||||
makeObfSourceJar = false
|
||||
|
||||
// The sources jar should use SRG names not MCP to ensure compatibility with all mappings
|
||||
makeObfSourceJar = true
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -71,9 +73,15 @@ repositories {
|
||||
name = 'spongepowered-repo'
|
||||
url = 'http://repo.spongepowered.org/maven/'
|
||||
}
|
||||
|
||||
maven {
|
||||
name = 'impactdevelopment-repo'
|
||||
url = 'https://impactdevelopment.github.io/maven/'
|
||||
}
|
||||
}
|
||||
|
||||
dependencies {
|
||||
runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2')
|
||||
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
exclude module: 'launchwrapper'
|
||||
@@ -96,32 +104,12 @@ jar {
|
||||
reproducibleFileOrder = true
|
||||
}
|
||||
|
||||
build {
|
||||
// while "jar" supports preserveFileTimestamps false
|
||||
// reobfJar doesn't, it just sets all the last modified times to that instant where it runs the reobfuscator
|
||||
// so we have to set all those last modified times back to zero
|
||||
doLast {
|
||||
File jarFile = new File("build/libs/baritone-" + version + ".jar")
|
||||
JarFile jf = new JarFile(jarFile)
|
||||
JarOutputStream jos = new JarOutputStream(new FileOutputStream(new File("temp.jar")))
|
||||
jf.entries().unique { it.name }.sort { it.name }.each {
|
||||
if (it.name != "META-INF/fml_cache_annotation.json" && it.name != "META-INF/fml_cache_class_versions.json") {
|
||||
JarEntry clone = new JarEntry(it)
|
||||
clone.time = 0
|
||||
jos.putNextEntry(clone)
|
||||
copy(jf.getInputStream(it), jos)
|
||||
}
|
||||
}
|
||||
jos.finish()
|
||||
jf.close()
|
||||
file("temp.jar").renameTo(jarFile)
|
||||
}
|
||||
task proguard(type: ProguardTask) {
|
||||
url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip'
|
||||
extract 'proguard6.0.3/lib/proguard.jar'
|
||||
versionManifest 'https://launchermeta.mojang.com/mc/game/version_manifest.json'
|
||||
}
|
||||
|
||||
void copy(InputStream is, OutputStream os) {
|
||||
byte[] buffer = new byte[1024]
|
||||
int len = 0
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len)
|
||||
}
|
||||
}
|
||||
task createDist(type: CreateDistTask, dependsOn: proguard)
|
||||
|
||||
build.finalizedBy(createDist)
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
build/
|
||||
.gradle/
|
||||
out/
|
||||
@@ -0,0 +1,25 @@
|
||||
/*
|
||||
* 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/>.
|
||||
*/
|
||||
|
||||
repositories {
|
||||
mavenCentral()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
compile group: 'com.google.code.gson', name: 'gson', version: '2.8.5'
|
||||
compile group: 'commons-io', name: 'commons-io', version: '2.6'
|
||||
}
|
||||
@@ -0,0 +1,102 @@
|
||||
/*
|
||||
* 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.gradle.task;
|
||||
|
||||
import com.google.gson.JsonElement;
|
||||
import com.google.gson.JsonParser;
|
||||
import org.gradle.api.DefaultTask;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.InputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/12/2018
|
||||
*/
|
||||
class BaritoneGradleTask extends DefaultTask {
|
||||
|
||||
protected static final JsonParser PARSER = new JsonParser();
|
||||
|
||||
protected static final String
|
||||
PROGUARD_ZIP = "proguard.zip",
|
||||
PROGUARD_JAR = "proguard.jar",
|
||||
PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro",
|
||||
PROGUARD_CONFIG_DEST = "template.pro",
|
||||
PROGUARD_API_CONFIG = "api.pro",
|
||||
PROGUARD_STANDALONE_CONFIG = "standalone.pro",
|
||||
PROGUARD_EXPORT_PATH = "proguard_out.jar",
|
||||
|
||||
VERSION_MANIFEST = "version_manifest.json",
|
||||
|
||||
TEMP_LIBRARY_DIR = "tempLibraries/",
|
||||
|
||||
ARTIFACT_STANDARD = "%s-%s.jar",
|
||||
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
|
||||
ARTIFACT_API = "%s-api-%s.jar",
|
||||
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
|
||||
|
||||
protected String artifactName, artifactVersion;
|
||||
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
|
||||
|
||||
protected void verifyArtifacts() throws IllegalStateException {
|
||||
this.artifactName = getProject().getName();
|
||||
this.artifactVersion = getProject().getVersion().toString();
|
||||
|
||||
this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD));
|
||||
this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
|
||||
this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
|
||||
this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
|
||||
|
||||
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
|
||||
|
||||
if (!Files.exists(this.artifactPath)) {
|
||||
throw new IllegalStateException("Artifact not found! Run build first!");
|
||||
}
|
||||
}
|
||||
|
||||
protected void write(InputStream stream, Path file) throws Exception {
|
||||
if (Files.exists(file)) {
|
||||
Files.delete(file);
|
||||
}
|
||||
Files.copy(stream, file);
|
||||
}
|
||||
|
||||
protected String formatVersion(String string) {
|
||||
return String.format(string, this.artifactName, this.artifactVersion);
|
||||
}
|
||||
|
||||
protected Path getRelativeFile(String file) {
|
||||
return Paths.get(new File(file).getAbsolutePath());
|
||||
}
|
||||
|
||||
protected Path getTemporaryFile(String file) {
|
||||
return Paths.get(new File(getTemporaryDir(), file).getAbsolutePath());
|
||||
}
|
||||
|
||||
protected Path getBuildFile(String file) {
|
||||
return getRelativeFile("build/libs/" + file);
|
||||
}
|
||||
|
||||
protected JsonElement readJson(List<String> lines) {
|
||||
return PARSER.parse(String.join("\n", lines));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.gradle.task;
|
||||
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
|
||||
import javax.xml.bind.DatatypeConverter;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.security.MessageDigest;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/12/2018
|
||||
*/
|
||||
public class CreateDistTask extends BaritoneGradleTask {
|
||||
|
||||
private static MessageDigest SHA1_DIGEST;
|
||||
|
||||
@TaskAction
|
||||
protected void exec() throws Exception {
|
||||
super.verifyArtifacts();
|
||||
|
||||
// Define the distribution file paths
|
||||
Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
|
||||
Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
|
||||
Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
|
||||
|
||||
// NIO will not automatically create directories
|
||||
Path dir = getRelativeFile("dist/");
|
||||
if (!Files.exists(dir)) {
|
||||
Files.createDirectory(dir);
|
||||
}
|
||||
|
||||
// Copy build jars to dist/
|
||||
Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
|
||||
|
||||
// Calculate all checksums and format them like "shasum"
|
||||
List<String> shasum = Stream.of(api, standalone, unoptimized)
|
||||
.map(path -> sha1(path) + " " + path.getFileName().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
shasum.forEach(System.out::println);
|
||||
|
||||
// Write the checksums to a file
|
||||
Files.write(getRelativeFile("dist/checksums.txt"), shasum);
|
||||
}
|
||||
|
||||
private static synchronized String sha1(Path path) {
|
||||
try {
|
||||
if (SHA1_DIGEST == null) {
|
||||
SHA1_DIGEST = MessageDigest.getInstance("SHA-1");
|
||||
}
|
||||
return DatatypeConverter.printHexBinary(SHA1_DIGEST.digest(Files.readAllBytes(path))).toLowerCase();
|
||||
} catch (Exception e) {
|
||||
// haha no thanks
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,260 @@
|
||||
/*
|
||||
* 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.gradle.task;
|
||||
|
||||
import baritone.gradle.util.Determinizer;
|
||||
import com.google.gson.*;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.internal.Pair;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/11/2018
|
||||
*/
|
||||
public class ProguardTask extends BaritoneGradleTask {
|
||||
|
||||
private static final Pattern TEMP_LIBRARY_PATTERN = Pattern.compile("-libraryjars 'tempLibraries\\/([a-zA-Z0-9/_\\-\\.]+)\\.jar'");
|
||||
|
||||
@Input
|
||||
private String url;
|
||||
|
||||
@Input
|
||||
private String extract;
|
||||
|
||||
@Input
|
||||
private String versionManifest;
|
||||
|
||||
private Map<String, String> versionDownloadMap;
|
||||
private List<String> requiredLibraries;
|
||||
|
||||
@TaskAction
|
||||
protected void exec() throws Exception {
|
||||
super.verifyArtifacts();
|
||||
|
||||
// "Haha brady why don't you make separate tasks"
|
||||
processArtifact();
|
||||
downloadProguard();
|
||||
extractProguard();
|
||||
generateConfigs();
|
||||
downloadVersionManifest();
|
||||
acquireDependencies();
|
||||
proguardApi();
|
||||
proguardStandalone();
|
||||
cleanup();
|
||||
}
|
||||
|
||||
private void processArtifact() throws Exception {
|
||||
if (Files.exists(this.artifactUnoptimizedPath)) {
|
||||
Files.delete(this.artifactUnoptimizedPath);
|
||||
}
|
||||
|
||||
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString());
|
||||
}
|
||||
|
||||
private void downloadProguard() throws Exception {
|
||||
Path proguardZip = getTemporaryFile(PROGUARD_ZIP);
|
||||
if (!Files.exists(proguardZip)) {
|
||||
write(new URL(this.url).openStream(), proguardZip);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractProguard() throws Exception {
|
||||
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
|
||||
if (!Files.exists(proguardJar)) {
|
||||
ZipFile zipFile = new ZipFile(getTemporaryFile(PROGUARD_ZIP).toFile());
|
||||
ZipEntry zipJarEntry = zipFile.getEntry(this.extract);
|
||||
write(zipFile.getInputStream(zipJarEntry), proguardJar);
|
||||
zipFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void generateConfigs() throws Exception {
|
||||
Files.copy(getRelativeFile(PROGUARD_CONFIG_TEMPLATE), getTemporaryFile(PROGUARD_CONFIG_DEST), REPLACE_EXISTING);
|
||||
|
||||
// Setup the template that will be used to derive the API and Standalone configs
|
||||
List<String> template = Files.readAllLines(getTemporaryFile(PROGUARD_CONFIG_DEST));
|
||||
template.add(0, "-injars " + this.artifactPath.toString());
|
||||
template.add(1, "-outjars " + this.getTemporaryFile(PROGUARD_EXPORT_PATH));
|
||||
|
||||
// Acquire the RT jar using "java -verbose". This doesn't work on Java 9+
|
||||
Process p = new ProcessBuilder("java", "-verbose").start();
|
||||
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
|
||||
template.add(2, "-libraryjars '" + out + "'");
|
||||
|
||||
// API config doesn't require any changes from the changes that we made to the template
|
||||
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
|
||||
|
||||
// For the Standalone config, don't keep the API package
|
||||
List<String> standalone = new ArrayList<>(template);
|
||||
standalone.removeIf(s -> s.contains("# this is the keep api"));
|
||||
Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
|
||||
|
||||
// Discover all of the libraries that we will need to acquire from gradle
|
||||
this.requiredLibraries = new ArrayList<>();
|
||||
template.forEach(line -> {
|
||||
if (!line.startsWith("#")) {
|
||||
Matcher m = TEMP_LIBRARY_PATTERN.matcher(line);
|
||||
if (m.find()) {
|
||||
this.requiredLibraries.add(m.group(1));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void downloadVersionManifest() throws Exception {
|
||||
Path manifestJson = getTemporaryFile(VERSION_MANIFEST);
|
||||
write(new URL(this.versionManifest).openStream(), manifestJson);
|
||||
|
||||
// Place all the versions in the map with their download URL
|
||||
this.versionDownloadMap = new HashMap<>();
|
||||
JsonObject json = readJson(Files.readAllLines(manifestJson)).getAsJsonObject();
|
||||
JsonArray versions = json.getAsJsonArray("versions");
|
||||
versions.forEach(element -> {
|
||||
JsonObject object = element.getAsJsonObject();
|
||||
this.versionDownloadMap.put(object.get("id").getAsString(), object.get("url").getAsString());
|
||||
});
|
||||
}
|
||||
|
||||
private void acquireDependencies() throws Exception {
|
||||
|
||||
// Create a map of all of the dependencies that we are able to access in this project
|
||||
// Likely a better way to do this, I just pair the dependency with the first valid configuration
|
||||
Map<String, Pair<Configuration, Dependency>> dependencyLookupMap = new HashMap<>();
|
||||
getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config ->
|
||||
config.getAllDependencies().forEach(dependency ->
|
||||
dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency))));
|
||||
|
||||
// Create the directory if it doesn't already exist
|
||||
Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR);
|
||||
if (!Files.exists(tempLibraries)) {
|
||||
Files.createDirectory(tempLibraries);
|
||||
}
|
||||
|
||||
// Iterate the required libraries to copy them to tempLibraries
|
||||
for (String lib : this.requiredLibraries) {
|
||||
// Download the version jar from the URL acquired from the version manifest
|
||||
if (lib.startsWith("minecraft")) {
|
||||
String version = lib.split("-")[1];
|
||||
Path versionJar = getTemporaryFile("tempLibraries/" + lib + ".jar");
|
||||
if (!Files.exists(versionJar)) {
|
||||
JsonObject versionJson = PARSER.parse(new InputStreamReader(new URL(this.versionDownloadMap.get(version)).openStream())).getAsJsonObject();
|
||||
String url = versionJson.getAsJsonObject("downloads").getAsJsonObject("client").getAsJsonPrimitive("url").getAsString();
|
||||
write(new URL(url).openStream(), versionJar);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find a configuration/dependency pair that matches the desired library
|
||||
Pair<Configuration, Dependency> pair = null;
|
||||
for (Map.Entry<String, Pair<Configuration, Dependency>> entry : dependencyLookupMap.entrySet()) {
|
||||
if (entry.getKey().startsWith(lib)) {
|
||||
pair = entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
// The pair must be non-null
|
||||
Objects.requireNonNull(pair);
|
||||
|
||||
// Find the library jar file, and copy it to tempLibraries
|
||||
for (File file : pair.getLeft().files(pair.getRight())) {
|
||||
if (file.getName().startsWith(lib)) {
|
||||
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void proguardApi() throws Exception {
|
||||
runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString());
|
||||
}
|
||||
|
||||
private void proguardStandalone() throws Exception {
|
||||
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString());
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
try {
|
||||
Files.delete(this.proguardOut);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
public void setExtract(String extract) {
|
||||
this.extract = extract;
|
||||
}
|
||||
|
||||
public void setVersionManifest(String versionManifest) {
|
||||
this.versionManifest = versionManifest;
|
||||
}
|
||||
|
||||
private void runProguard(Path config) throws Exception {
|
||||
// Delete the existing proguard output file. Proguard probably handles this already, but why not do it ourselves
|
||||
if (Files.exists(this.proguardOut)) {
|
||||
Files.delete(this.proguardOut);
|
||||
}
|
||||
|
||||
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
|
||||
Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString())
|
||||
.directory(getTemporaryFile("").toFile()) // Set the working directory to the temporary folder]
|
||||
.start();
|
||||
|
||||
// We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
|
||||
this.printOutputLog(p.getInputStream());
|
||||
this.printOutputLog(p.getErrorStream());
|
||||
|
||||
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
|
||||
int exitCode = p.waitFor();
|
||||
if (exitCode != 0) {
|
||||
throw new IllegalStateException("Proguard exited with code " + exitCode);
|
||||
}
|
||||
}
|
||||
|
||||
private void printOutputLog(InputStream stream) {
|
||||
new Thread(() -> {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
System.out.println(line);
|
||||
}
|
||||
} catch (final Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,143 @@
|
||||
/*
|
||||
* 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.gradle.util;
|
||||
|
||||
import com.google.gson.*;
|
||||
import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Make a .jar file deterministic by sorting all entries by name, and setting all the last modified times to 42069.
|
||||
* This makes the build 100% reproducible since the timestamp when you built it no longer affects the final file.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Determinizer {
|
||||
|
||||
public static void determinize(String inputPath, String outputPath) throws IOException {
|
||||
System.out.println("Running Determinizer");
|
||||
System.out.println(" Input path: " + inputPath);
|
||||
System.out.println(" Output path: " + outputPath);
|
||||
|
||||
try (
|
||||
JarFile jarFile = new JarFile(new File(inputPath));
|
||||
JarOutputStream jos = new JarOutputStream(new FileOutputStream(new File(outputPath)))
|
||||
) {
|
||||
|
||||
List<JarEntry> entries = jarFile.stream()
|
||||
.sorted(Comparator.comparing(JarEntry::getName))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
for (JarEntry entry : entries) {
|
||||
if (entry.getName().equals("META-INF/fml_cache_annotation.json")) {
|
||||
continue;
|
||||
}
|
||||
if (entry.getName().equals("META-INF/fml_cache_class_versions.json")) {
|
||||
continue;
|
||||
}
|
||||
JarEntry clone = new JarEntry(entry.getName());
|
||||
clone.setTime(42069);
|
||||
jos.putNextEntry(clone);
|
||||
if (entry.getName().endsWith(".refmap.json")) {
|
||||
JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
|
||||
jos.write(writeSorted(object).getBytes());
|
||||
} else {
|
||||
copy(jarFile.getInputStream(entry), jos);
|
||||
}
|
||||
}
|
||||
jos.finish();
|
||||
}
|
||||
}
|
||||
|
||||
private static void copy(InputStream is, OutputStream os) throws IOException {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = is.read(buffer)) != -1) {
|
||||
os.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
private static String writeSorted(JsonObject in) throws IOException {
|
||||
StringWriter writer = new StringWriter();
|
||||
JsonWriter jw = new JsonWriter(writer);
|
||||
ORDERED_JSON_WRITER.write(jw, in);
|
||||
return writer.toString() + "\n";
|
||||
}
|
||||
|
||||
/**
|
||||
* All credits go to GSON and its contributors. GSON is licensed under the Apache 2.0 License.
|
||||
* This implementation has been modified to write {@link JsonObject} keys in order.
|
||||
*
|
||||
* @see <a href="https://github.com/google/gson/blob/master/LICENSE">GSON License</a>
|
||||
* @see <a href="https://github.com/google/gson/blob/master/gson/src/main/java/com/google/gson/internal/bind/TypeAdapters.java#L698">Original Source</a>
|
||||
*/
|
||||
private static final TypeAdapter<JsonElement> ORDERED_JSON_WRITER = new TypeAdapter<JsonElement>() {
|
||||
|
||||
@Override
|
||||
public JsonElement read(JsonReader in) {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void write(JsonWriter out, JsonElement value) throws IOException {
|
||||
if (value == null || value.isJsonNull()) {
|
||||
out.nullValue();
|
||||
} else if (value.isJsonPrimitive()) {
|
||||
JsonPrimitive primitive = value.getAsJsonPrimitive();
|
||||
if (primitive.isNumber()) {
|
||||
out.value(primitive.getAsNumber());
|
||||
} else if (primitive.isBoolean()) {
|
||||
out.value(primitive.getAsBoolean());
|
||||
} else {
|
||||
out.value(primitive.getAsString());
|
||||
}
|
||||
|
||||
} else if (value.isJsonArray()) {
|
||||
out.beginArray();
|
||||
for (JsonElement e : value.getAsJsonArray()) {
|
||||
write(out, e);
|
||||
}
|
||||
out.endArray();
|
||||
|
||||
} else if (value.isJsonObject()) {
|
||||
out.beginObject();
|
||||
|
||||
List<Map.Entry<String, JsonElement>> entries = new ArrayList<>(value.getAsJsonObject().entrySet());
|
||||
entries.sort(Comparator.comparing(Map.Entry::getKey));
|
||||
for (Map.Entry<String, JsonElement> e : entries) {
|
||||
out.name(e.getKey());
|
||||
write(out, e.getValue());
|
||||
}
|
||||
out.endObject();
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException("Couldn't write " + value.getClass());
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
@@ -1,26 +0,0 @@
|
||||
set -e # this makes the whole script fail immediately if any one of these commands fails
|
||||
./gradlew build
|
||||
export VERSION=$(cat build.gradle | grep "version '" | cut -d "'" -f 2-2)
|
||||
|
||||
wget -nv https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip
|
||||
unzip proguard6.0.3.zip 2>&1 > /dev/null
|
||||
cd build/libs
|
||||
echo "-injars 'baritone-$VERSION.jar'" >> api.pro # insert current version
|
||||
cat ../../scripts/proguard.pro | grep -v "this is the rt jar" | grep -v "\-injars" >> api.pro # remove default rt jar and injar lines
|
||||
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
|
||||
|
||||
#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
|
||||
java -jar ../../proguard6.0.3/lib/proguard.jar @standalone.pro
|
||||
mv Obfuscated/baritone-$VERSION.jar ../../dist/baritone-standalone-$VERSION.jar
|
||||
mv baritone-$VERSION.jar ../../dist/baritone-unoptimized-$VERSION.jar
|
||||
cd ../../dist
|
||||
shasum * | tee checksums.txt
|
||||
cd ..
|
||||
Vendored
+13
-14
@@ -1,7 +1,3 @@
|
||||
-injars baritone-0.0.7.jar
|
||||
-outjars Obfuscated
|
||||
|
||||
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
|
||||
@@ -16,8 +12,14 @@
|
||||
-flattenpackagehierarchy
|
||||
-repackageclasses 'baritone'
|
||||
|
||||
-keep class baritone.api.** { *; }
|
||||
-keep class baritone.api.** { *; } # this is the keep api
|
||||
|
||||
# service provider needs these class names
|
||||
-keep class baritone.BaritoneProvider
|
||||
-keep class baritone.api.IBaritoneProvider
|
||||
|
||||
# hack
|
||||
-keep class baritone.utils.ExampleBaritoneControl { *; }
|
||||
|
||||
# setting names are reflected from field names, so keep field names
|
||||
-keepclassmembers class baritone.api.Settings {
|
||||
@@ -28,10 +30,11 @@
|
||||
-keep class baritone.launch.** { *; }
|
||||
|
||||
# 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/minecraft-1.12.2.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/SimpleTweaker-1.2.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/authlib-1.5.25.jar'
|
||||
-libraryjars 'tempLibraries/codecjorbis-20101023.jar'
|
||||
-libraryjars 'tempLibraries/codecwav-20101023.jar'
|
||||
@@ -46,7 +49,6 @@
|
||||
-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.jar'
|
||||
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
|
||||
-libraryjars 'tempLibraries/jna-4.4.0.jar'
|
||||
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
|
||||
@@ -57,13 +59,10 @@
|
||||
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/log4j-core-2.8.1.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'
|
||||
# startsWith is used to check the library, and mac/linux differ in which version they use
|
||||
# this is FINE
|
||||
-libraryjars 'tempLibraries/lwjgl-.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl_util-.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
|
||||
-libraryjars 'tempLibraries/oshi-core-1.1.jar'
|
||||
|
||||
@@ -36,8 +36,8 @@ import java.util.ServiceLoader;
|
||||
*/
|
||||
public final class BaritoneAPI {
|
||||
|
||||
private final static IBaritoneProvider baritone;
|
||||
private final static Settings settings;
|
||||
private static final IBaritoneProvider baritone;
|
||||
private static final Settings settings;
|
||||
|
||||
static {
|
||||
ServiceLoader<IBaritoneProvider> baritoneLoader = ServiceLoader.load(IBaritoneProvider.class);
|
||||
|
||||
@@ -156,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.1);
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.5);
|
||||
|
||||
/**
|
||||
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
|
||||
@@ -307,6 +307,16 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Ignore depth when rendering the selection boxes (to break, to place, to walk into)
|
||||
*/
|
||||
public Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Ignore depth when rendering the path
|
||||
*/
|
||||
public Setting<Boolean> renderPathIgnoreDepth = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Line width of the path when rendered, in pixels
|
||||
*/
|
||||
@@ -366,6 +376,11 @@ public class Settings {
|
||||
*/
|
||||
public Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
|
||||
|
||||
/**
|
||||
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
|
||||
*/
|
||||
public Setting<Boolean> mineScanDroppedItems = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore.
|
||||
* <p>
|
||||
@@ -379,13 +394,25 @@ public class Settings {
|
||||
* <p>
|
||||
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
|
||||
*/
|
||||
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
|
||||
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
|
||||
*/
|
||||
public Setting<Integer> axisHeight = new Setting<>(120);
|
||||
|
||||
/**
|
||||
* Allow MineBehavior to use X-Ray to see where the ores are. Turn this option off to force it to mine "legit"
|
||||
* where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player
|
||||
* couldn't. If you don't want it to look like you're X-Raying, turn this off
|
||||
*/
|
||||
public Setting<Boolean> legitMine = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* What Y level to go to for legit strip mining
|
||||
*/
|
||||
public Setting<Integer> legitMineYLevel = new Setting<>(11);
|
||||
|
||||
/**
|
||||
* When mining block of a certain type, try to mine two at once instead of one.
|
||||
* If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks
|
||||
@@ -531,7 +558,7 @@ public class Settings {
|
||||
|
||||
// here be dragons
|
||||
|
||||
{
|
||||
Settings() {
|
||||
Field[] temp = getClass().getFields();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
@@ -566,6 +593,4 @@ public class Settings {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Settings() { }
|
||||
}
|
||||
|
||||
@@ -17,7 +17,10 @@
|
||||
|
||||
package baritone.api.behavior;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.path.IPathExecutor;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -65,4 +68,30 @@ public interface IPathingBehavior extends IBehavior {
|
||||
* Cancels the pathing behavior or the current path calculation.
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* Returns the current path, from the current path executor, if there is one.
|
||||
*
|
||||
* @return The current path
|
||||
*/
|
||||
default Optional<IPath> getPath() {
|
||||
return Optional.ofNullable(getCurrent()).map(IPathExecutor::getPath);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current path finder being executed
|
||||
*/
|
||||
Optional<IPathFinder> getPathFinder();
|
||||
|
||||
/**
|
||||
* @return The current path executor
|
||||
*/
|
||||
IPathExecutor getCurrent();
|
||||
|
||||
/**
|
||||
* Returns the next path executor, created when planning ahead.
|
||||
*
|
||||
* @return The next path executor
|
||||
*/
|
||||
IPathExecutor getNext();
|
||||
}
|
||||
|
||||
+1
-1
@@ -38,5 +38,5 @@ public interface IWorldScanner {
|
||||
* @param maxSearchRadius The maximum chunk search radius
|
||||
* @return The matching block positions
|
||||
*/
|
||||
List<BlockPos> scanLoadedChunks(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius);
|
||||
List<BlockPos> scanChunkRadius(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,8 @@ package baritone.api.event.events;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Called when the local player interacts with a block, can be either {@link Type#BREAK} or {@link Type#USE}.
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
|
||||
@@ -17,20 +17,22 @@
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.Cancellable;
|
||||
import baritone.api.event.events.type.ManagedPlayerEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:39 PM
|
||||
*/
|
||||
public final class ChatEvent extends Cancellable {
|
||||
public final class ChatEvent extends ManagedPlayerEvent.Cancellable {
|
||||
|
||||
/**
|
||||
* The message being sent
|
||||
*/
|
||||
private final String message;
|
||||
|
||||
public ChatEvent(String message) {
|
||||
public ChatEvent(EntityPlayerSP player, String message) {
|
||||
super(player);
|
||||
this.message = message;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
/**
|
||||
@@ -26,15 +27,22 @@ import net.minecraft.network.Packet;
|
||||
*/
|
||||
public final class PacketEvent {
|
||||
|
||||
private final NetworkManager networkManager;
|
||||
|
||||
private final EventState state;
|
||||
|
||||
private final Packet<?> packet;
|
||||
|
||||
public PacketEvent(EventState state, Packet<?> packet) {
|
||||
public PacketEvent(NetworkManager networkManager, EventState state, Packet<?> packet) {
|
||||
this.networkManager = networkManager;
|
||||
this.state = state;
|
||||
this.packet = packet;
|
||||
}
|
||||
|
||||
public final NetworkManager getNetworkManager() {
|
||||
return this.networkManager;
|
||||
}
|
||||
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
}
|
||||
|
||||
@@ -18,19 +18,22 @@
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.ManagedPlayerEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public final class PlayerUpdateEvent {
|
||||
public final class PlayerUpdateEvent extends ManagedPlayerEvent {
|
||||
|
||||
/**
|
||||
* The state of the event
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public PlayerUpdateEvent(EventState state) {
|
||||
public PlayerUpdateEvent(EntityPlayerSP player, EventState state) {
|
||||
super(player);
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
|
||||
@@ -18,6 +18,8 @@
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.ManagedPlayerEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
|
||||
@@ -25,7 +27,7 @@ import net.minecraft.entity.EntityLivingBase;
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public final class RotationMoveEvent {
|
||||
public final class RotationMoveEvent extends ManagedPlayerEvent {
|
||||
|
||||
/**
|
||||
* The type of event
|
||||
@@ -37,7 +39,8 @@ public final class RotationMoveEvent {
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public RotationMoveEvent(EventState state, Type type) {
|
||||
public RotationMoveEvent(EntityPlayerSP player, EventState state, Type type) {
|
||||
super(player);
|
||||
this.state = state;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
@@ -21,23 +21,19 @@ package baritone.api.event.events.type;
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:41 PM
|
||||
*/
|
||||
public class Cancellable {
|
||||
public class Cancellable implements ICancellable {
|
||||
|
||||
/**
|
||||
* Whether or not this event has been cancelled
|
||||
*/
|
||||
private boolean cancelled;
|
||||
|
||||
/**
|
||||
* Cancels this event
|
||||
*/
|
||||
@Override
|
||||
public final void cancel() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Whether or not this event has been cancelled
|
||||
*/
|
||||
@Override
|
||||
public final boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
|
||||
+12
-11
@@ -15,20 +15,21 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
package baritone.api.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:10 PM
|
||||
* @since 10/11/2018
|
||||
*/
|
||||
public class BaritoneTweakerOptifine extends BaritoneTweaker {
|
||||
public interface ICancellable {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
/**
|
||||
* Cancels this event
|
||||
*/
|
||||
void cancel();
|
||||
|
||||
/**
|
||||
* @return Whether or not this event has been cancelled
|
||||
*/
|
||||
boolean isCancelled();
|
||||
}
|
||||
@@ -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.api.event.events.type;
|
||||
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
/**
|
||||
* An event that has a reference to a locally managed player.
|
||||
*
|
||||
* @author Brady
|
||||
* @since 10/11/2018
|
||||
*/
|
||||
public class ManagedPlayerEvent {
|
||||
|
||||
protected final EntityPlayerSP player;
|
||||
|
||||
public ManagedPlayerEvent(EntityPlayerSP player) {
|
||||
this.player = player;
|
||||
}
|
||||
|
||||
public final EntityPlayerSP getPlayer() {
|
||||
return this.player;
|
||||
}
|
||||
|
||||
public static class Cancellable extends ManagedPlayerEvent implements ICancellable {
|
||||
|
||||
/**
|
||||
* Whether or not this event has been cancelled
|
||||
*/
|
||||
private boolean cancelled;
|
||||
|
||||
public Cancellable(EntityPlayerSP player) {
|
||||
super(player);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void cancel() {
|
||||
this.cancelled = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isCancelled() {
|
||||
return this.cancelled;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* 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.pathing.calc;
|
||||
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author leijurv, Brady
|
||||
*/
|
||||
public interface IPath {
|
||||
|
||||
/**
|
||||
* Ordered list of movements to carry out.
|
||||
* movements.get(i).getSrc() should equal positions.get(i)
|
||||
* movements.get(i).getDest() should equal positions.get(i+1)
|
||||
* movements.size() should equal positions.size()-1
|
||||
*
|
||||
* @return All of the movements to carry out
|
||||
*/
|
||||
List<IMovement> movements();
|
||||
|
||||
/**
|
||||
* All positions along the way.
|
||||
* Should begin with the same as getSrc and end with the same as getDest
|
||||
*
|
||||
* @return All of the positions along this path
|
||||
*/
|
||||
List<BetterBlockPos> positions();
|
||||
|
||||
/**
|
||||
* This path is actually going to be executed in the world. Do whatever additional processing is required.
|
||||
* (as opposed to Path objects that are just constructed every frame for rendering)
|
||||
*/
|
||||
default void postProcess() {}
|
||||
|
||||
/**
|
||||
* Returns the number of positions in this path. Equivalent to {@code positions().size()}.
|
||||
*
|
||||
* @return Number of positions in this path
|
||||
*/
|
||||
default int length() {
|
||||
return positions().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The goal that this path was calculated towards
|
||||
*/
|
||||
Goal getGoal();
|
||||
|
||||
/**
|
||||
* Returns the number of nodes that were considered during calculation before
|
||||
* this path was found.
|
||||
*
|
||||
* @return The number of nodes that were considered before finding this path
|
||||
*/
|
||||
int getNumNodesConsidered();
|
||||
|
||||
/**
|
||||
* Returns the start position of this path. This is the first element in the
|
||||
* {@link List} that is returned by {@link IPath#positions()}.
|
||||
*
|
||||
* @return The start position of this path
|
||||
*/
|
||||
default BetterBlockPos getSrc() {
|
||||
return positions().get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the end position of this path. This is the last element in the
|
||||
* {@link List} that is returned by {@link IPath#positions()}.
|
||||
*
|
||||
* @return The end position of this path.
|
||||
*/
|
||||
default BetterBlockPos getDest() {
|
||||
List<BetterBlockPos> pos = positions();
|
||||
return pos.get(pos.size() - 1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the estimated number of ticks to complete the path from the given node index.
|
||||
*
|
||||
* @param pathPosition The index of the node we're calculating from
|
||||
* @return The estimated number of ticks remaining frm the given position
|
||||
*/
|
||||
default double ticksRemainingFrom(int pathPosition) {
|
||||
double sum = 0;
|
||||
//this is fast because we aren't requesting recalculation, it's just cached
|
||||
List<IMovement> movements = movements();
|
||||
for (int i = pathPosition; i < movements.size(); i++) {
|
||||
sum += movements.get(i).getCost();
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts off this path at the loaded chunk border, and returns the resulting path. Default
|
||||
* implementation just returns this path, without the intended functionality.
|
||||
*
|
||||
* @return The result of this cut-off operation
|
||||
*/
|
||||
default IPath cutoffAtLoadedChunks() {
|
||||
return this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Cuts off this path using the min length and cutoff factor settings, and returns the resulting path.
|
||||
* Default implementation just returns this path, without the intended functionality.
|
||||
*
|
||||
* @see Settings#pathCutoffMinimumLength
|
||||
* @see Settings#pathCutoffFactor
|
||||
*
|
||||
* @return The result of this cut-off operation
|
||||
*/
|
||||
default IPath staticCutoff(Goal destination) {
|
||||
return this;
|
||||
}
|
||||
}
|
||||
+1
-2
@@ -15,10 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.calc;
|
||||
package baritone.api.pathing.calc;
|
||||
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -0,0 +1,67 @@
|
||||
/*
|
||||
* 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.pathing.movement;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/8/2018
|
||||
*/
|
||||
public interface IMovement {
|
||||
|
||||
double getCost();
|
||||
|
||||
MovementStatus update();
|
||||
|
||||
/**
|
||||
* Resets the current state status to {@link MovementStatus#PREPPING}
|
||||
*/
|
||||
void reset();
|
||||
|
||||
/**
|
||||
* Resets the cache for special break, place, and walk into blocks
|
||||
*/
|
||||
void resetBlockCache();
|
||||
|
||||
/**
|
||||
* @return Whether or not it is safe to cancel the current movement state
|
||||
*/
|
||||
boolean safeToCancel();
|
||||
|
||||
double recalculateCost();
|
||||
|
||||
double calculateCostWithoutCaching();
|
||||
|
||||
boolean calculatedWhileLoaded();
|
||||
|
||||
BetterBlockPos getSrc();
|
||||
|
||||
BetterBlockPos getDest();
|
||||
|
||||
BlockPos getDirection();
|
||||
|
||||
List<BlockPos> toBreak();
|
||||
|
||||
List<BlockPos> toPlace();
|
||||
|
||||
List<BlockPos> toWalkInto();
|
||||
}
|
||||
@@ -0,0 +1,74 @@
|
||||
/*
|
||||
* 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.pathing.movement;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/8/2018
|
||||
*/
|
||||
public enum MovementStatus {
|
||||
|
||||
/**
|
||||
* We are preparing the movement to be executed. This is when any blocks obstructing the destination are broken.
|
||||
*/
|
||||
PREPPING(false),
|
||||
|
||||
/**
|
||||
* We are waiting for the movement to begin, after {@link MovementStatus#PREPPING}.
|
||||
*/
|
||||
WAITING(false),
|
||||
|
||||
/**
|
||||
* The movement is currently in progress, after {@link MovementStatus#WAITING}
|
||||
*/
|
||||
RUNNING(false),
|
||||
|
||||
/**
|
||||
* The movement has been completed and we are at our destination
|
||||
*/
|
||||
SUCCESS(true),
|
||||
|
||||
/**
|
||||
* There was a change in state between calculation and actual
|
||||
* movement execution, and the movement has now become impossible.
|
||||
*/
|
||||
UNREACHABLE(true),
|
||||
|
||||
/**
|
||||
* Unused
|
||||
*/
|
||||
FAILED(true),
|
||||
|
||||
/**
|
||||
* "Unused"
|
||||
*/
|
||||
CANCELED(true);
|
||||
|
||||
/**
|
||||
* Whether or not this status indicates a complete movement.
|
||||
*/
|
||||
private final boolean complete;
|
||||
|
||||
MovementStatus(boolean complete) {
|
||||
this.complete = complete;
|
||||
}
|
||||
|
||||
public final boolean isComplete() {
|
||||
return this.complete;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
* 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.pathing.path;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/8/2018
|
||||
*/
|
||||
public interface IPathExecutor {
|
||||
|
||||
IPath getPath();
|
||||
}
|
||||
+22
-4
@@ -15,9 +15,8 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
@@ -54,11 +53,30 @@ public final class BetterBlockPos extends BlockPos {
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) AbstractNodeCostSearch.posHash(x, y, z);
|
||||
return (int) longHash(x, y, z);
|
||||
}
|
||||
|
||||
public static long longHash(BetterBlockPos pos) {
|
||||
return AbstractNodeCostSearch.posHash(pos.x, pos.y, pos.z);
|
||||
return longHash(pos.x, pos.y, pos.z);
|
||||
}
|
||||
|
||||
public static long longHash(int x, int y, int z) {
|
||||
/*
|
||||
* 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();
|
||||
* }
|
||||
*
|
||||
* That is terrible and has tons of collisions and makes the HashMap terribly inefficient.
|
||||
*
|
||||
* That's why we grab out the X, Y, Z and calculate our own hashcode
|
||||
*/
|
||||
long hash = 3241;
|
||||
hash = 3457689L * hash + x;
|
||||
hash = 8734625L * hash + y;
|
||||
hash = 2873465L * hash + z;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
+36
-6
@@ -15,19 +15,25 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import static baritone.behavior.LookBehaviorUtils.calcVec3dFromRotation;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
public final class RayTraceUtils implements Helper {
|
||||
public final class RayTraceUtils {
|
||||
/**
|
||||
* The {@link Minecraft} instance
|
||||
*/
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private RayTraceUtils() {}
|
||||
|
||||
@@ -39,7 +45,7 @@ public final class RayTraceUtils implements Helper {
|
||||
* thing to achieve the desired outcome (whether it is hitting and entity or placing
|
||||
* a block) can be done just by modifying user input.
|
||||
*
|
||||
* @param yaw The yaw to raytrace with
|
||||
* @param yaw The yaw to raytrace with
|
||||
* @param pitch The pitch to raytrace with
|
||||
* @return The calculated raytrace result
|
||||
*/
|
||||
@@ -72,7 +78,7 @@ public final class RayTraceUtils implements Helper {
|
||||
public static RayTraceResult rayTraceTowards(Rotation rotation) {
|
||||
double blockReachDistance = mc.playerController.getBlockReachDistance();
|
||||
Vec3d start = mc.player.getPositionEyes(1.0F);
|
||||
Vec3d direction = calcVec3dFromRotation(rotation);
|
||||
Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
direction.y * blockReachDistance,
|
||||
@@ -80,4 +86,28 @@ public final class RayTraceUtils implements Helper {
|
||||
);
|
||||
return mc.world.rayTraceBlocks(start, end, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the block that the crosshair is currently placed over. Updated once per render tick.
|
||||
*
|
||||
* @return The position of the highlighted block
|
||||
*/
|
||||
public static Optional<BlockPos> getSelectedBlock() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
return Optional.of(mc.objectMouseOver.getBlockPos());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity that the crosshair is currently placed over. Updated once per render tick.
|
||||
*
|
||||
* @return The entity
|
||||
*/
|
||||
public static Optional<Entity> getSelectedEntity() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(mc.objectMouseOver.entityHit);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -17,12 +17,47 @@
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/25/2018
|
||||
*/
|
||||
public final class RotationUtils {
|
||||
|
||||
/**
|
||||
* The {@link Minecraft} instance
|
||||
*/
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
/**
|
||||
* Constant that a degree value is multiplied by to get the equivalent radian value
|
||||
*/
|
||||
public static final double DEG_TO_RAD = Math.PI / 180.0;
|
||||
|
||||
/**
|
||||
* Constant that a radian value is multiplied by to get the equivalent degree value
|
||||
*/
|
||||
public static final double RAD_TO_DEG = 180.0 / Math.PI;
|
||||
|
||||
/**
|
||||
* Offsets from the root block position to the center of each side.
|
||||
*/
|
||||
private static final Vec3d[] BLOCK_SIDE_MULTIPLIERS = new Vec3d[]{
|
||||
new Vec3d(0.5, 0, 0.5), // Down
|
||||
new Vec3d(0.5, 1, 0.5), // Up
|
||||
new Vec3d(0.5, 0.5, 0), // North
|
||||
new Vec3d(0.5, 0.5, 1), // South
|
||||
new Vec3d(0, 0.5, 0.5), // West
|
||||
new Vec3d(1, 0.5, 0.5) // East
|
||||
};
|
||||
|
||||
private RotationUtils() {}
|
||||
|
||||
/**
|
||||
@@ -51,4 +86,156 @@ public final class RotationUtils {
|
||||
}
|
||||
return newYaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rotation from BlockPos<sub>dest</sub> to BlockPos<sub>orig</sub>
|
||||
*
|
||||
* @param orig The origin position
|
||||
* @param dest The destination position
|
||||
* @return The rotation from the origin to the destination
|
||||
*/
|
||||
public static Rotation calcRotationFromCoords(BlockPos orig, BlockPos dest) {
|
||||
return calcRotationFromVec3d(new Vec3d(orig), new Vec3d(dest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Wraps the target angles to a relative value from the current angles. This is done by
|
||||
* subtracting the current from the target, normalizing it, and then adding the current
|
||||
* angles back to it.
|
||||
*
|
||||
* @param current The current angles
|
||||
* @param target The target angles
|
||||
* @return The wrapped angles
|
||||
*/
|
||||
public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) {
|
||||
return target.subtract(current).normalize().add(current);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rotation from Vec<sub>dest</sub> to Vec<sub>orig</sub> and makes the
|
||||
* return value relative to the specified current rotations.
|
||||
*
|
||||
* @param orig The origin position
|
||||
* @param dest The destination position
|
||||
* @param current The current rotations
|
||||
* @return The rotation from the origin to the destination
|
||||
* @see #wrapAnglesToRelative(Rotation, Rotation)
|
||||
*/
|
||||
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest, Rotation current) {
|
||||
return wrapAnglesToRelative(current, calcRotationFromVec3d(orig, dest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the rotation from Vec<sub>dest</sub> to Vec<sub>orig</sub>
|
||||
*
|
||||
* @param orig The origin position
|
||||
* @param dest The destination position
|
||||
* @return The rotation from the origin to the destination
|
||||
*/
|
||||
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
|
||||
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
|
||||
double yaw = MathHelper.atan2(delta[0], -delta[2]);
|
||||
double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
|
||||
double pitch = MathHelper.atan2(delta[1], dist);
|
||||
return new Rotation(
|
||||
(float) (yaw * RAD_TO_DEG),
|
||||
(float) (pitch * RAD_TO_DEG)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the look vector for the specified yaw/pitch rotations.
|
||||
*
|
||||
* @param rotation The input rotation
|
||||
* @return Look vector for the rotation
|
||||
*/
|
||||
public static Vec3d calcVec3dFromRotation(Rotation rotation) {
|
||||
float f = MathHelper.cos(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI);
|
||||
float f1 = MathHelper.sin(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI);
|
||||
float f2 = -MathHelper.cos(-rotation.getPitch() * (float) DEG_TO_RAD);
|
||||
float f3 = MathHelper.sin(-rotation.getPitch() * (float) DEG_TO_RAD);
|
||||
return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2));
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified entity is able to reach the center of any of the sides
|
||||
* of the specified block. It first checks if the block center is reachable, and if so,
|
||||
* that rotation will be returned. If not, it will return the first center of a given
|
||||
* side that is reachable. The return type will be {@link Optional#empty()} if the entity is
|
||||
* unable to reach any of the sides of the block.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param pos The target block position
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachable(Entity entity, BlockPos pos) {
|
||||
if (pos.equals(RayTraceUtils.getSelectedBlock().orElse(null))) {
|
||||
/*
|
||||
* why add 0.0001?
|
||||
* to indicate that we actually have a desired pitch
|
||||
* the way we indicate that the pitch can be whatever and we only care about the yaw
|
||||
* is by setting the desired pitch to the current pitch
|
||||
* setting the desired pitch to the current pitch + 0.0001 means that we do have a desired pitch, it's
|
||||
* just what it currently is
|
||||
*
|
||||
* or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level
|
||||
*/
|
||||
return Optional.of(new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F));
|
||||
}
|
||||
Optional<Rotation> possibleRotation = reachableCenter(entity, pos);
|
||||
//System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
|
||||
IBlockState state = mc.world.getBlockState(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
|
||||
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
|
||||
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff));
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified entity is able to reach the specified block with
|
||||
* the given offsetted position. The return type will be {@link Optional#empty()} if
|
||||
* the entity is unable to reach the block with the offset applied.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param pos The target block position
|
||||
* @param offsetPos The position of the block with the offset applied.
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos) {
|
||||
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
|
||||
//System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
if (entity.world.getBlockState(pos).getBlock() instanceof BlockFire && result.getBlockPos().equals(pos.down())) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified entity is able to reach the specified block where it is
|
||||
* looking at the direct center of it's hitbox.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param pos The target block position
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos) {
|
||||
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(pos));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -31,6 +31,7 @@ import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SettingsUtil {
|
||||
|
||||
private static final File settingsFile = new File(new File(Minecraft.getMinecraft().gameDir, "baritone"), "settings.txt");
|
||||
|
||||
private static final Map<Class<?>, SettingsIO> map;
|
||||
|
||||
@@ -0,0 +1,119 @@
|
||||
/*
|
||||
* 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.utils;
|
||||
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 10/13/2018
|
||||
*/
|
||||
public final class VecUtils {
|
||||
/**
|
||||
* The {@link Minecraft} instance
|
||||
*/
|
||||
private static final Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
private VecUtils() {}
|
||||
|
||||
/**
|
||||
* Calculates the center of the block at the specified position's bounding box
|
||||
*
|
||||
* @param pos The block position
|
||||
* @return The center of the block's bounding box
|
||||
* @see #getBlockPosCenter(BlockPos)
|
||||
*/
|
||||
public static Vec3d calculateBlockCenter(BlockPos pos) {
|
||||
IBlockState b = mc.world.getBlockState(pos);
|
||||
AxisAlignedBB bbox = b.getBoundingBox(mc.world, pos);
|
||||
double xDiff = (bbox.minX + bbox.maxX) / 2;
|
||||
double yDiff = (bbox.minY + bbox.maxY) / 2;
|
||||
double zDiff = (bbox.minZ + bbox.maxZ) / 2;
|
||||
if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out
|
||||
yDiff = 0;
|
||||
}
|
||||
return new Vec3d(
|
||||
pos.getX() + xDiff,
|
||||
pos.getY() + yDiff,
|
||||
pos.getZ() + zDiff
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the assumed center position of the given block position.
|
||||
* This is done by adding 0.5 to the X, Y, and Z axes.
|
||||
* <p>
|
||||
* TODO: We may want to consider replacing many usages of this method with #calculateBlockCenter(BlockPos)
|
||||
*
|
||||
* @param pos The block position
|
||||
* @return The assumed center of the position
|
||||
* @see #calculateBlockCenter(BlockPos)
|
||||
*/
|
||||
public static Vec3d getBlockPosCenter(BlockPos pos) {
|
||||
return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance from the specified position to the assumed center of the specified block position.
|
||||
*
|
||||
* @param pos The block position
|
||||
* @param x The x pos
|
||||
* @param y The y pos
|
||||
* @param z The z pos
|
||||
* @return The distance from the assumed block center to the position
|
||||
* @see #getBlockPosCenter(BlockPos)
|
||||
*/
|
||||
public static double distanceToCenter(BlockPos pos, double x, double y, double z) {
|
||||
double xdiff = pos.getX() + 0.5 - x;
|
||||
double ydiff = pos.getY() + 0.5 - y;
|
||||
double zdiff = pos.getZ() + 0.5 - z;
|
||||
return Math.sqrt(xdiff * xdiff + ydiff * ydiff + zdiff * zdiff);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance from the specified entity's position to the assumed
|
||||
* center of the specified block position.
|
||||
*
|
||||
* @param entity The entity
|
||||
* @param pos The block position
|
||||
* @return The distance from the entity to the block's assumed center
|
||||
* @see #getBlockPosCenter(BlockPos)
|
||||
*/
|
||||
public static double entityDistanceToCenter(Entity entity, BlockPos pos) {
|
||||
return distanceToCenter(pos, entity.posX, entity.posY, entity.posZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the distance from the specified entity's position to the assumed
|
||||
* center of the specified block position, ignoring the Y axis.
|
||||
*
|
||||
* @param entity The entity
|
||||
* @param pos The block position
|
||||
* @return The horizontal distance from the entity to the block's assumed center
|
||||
* @see #getBlockPosCenter(BlockPos)
|
||||
*/
|
||||
public static double entityFlatDistanceToCenter(Entity entity, BlockPos pos) {
|
||||
return distanceToCenter(pos, entity.posX, pos.getY() + 0.5, entity.posZ);
|
||||
}
|
||||
}
|
||||
@@ -17,61 +17,39 @@
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import io.github.impactdevelopment.simpletweaker.SimpleTweaker;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 9:59 PM
|
||||
*/
|
||||
public class BaritoneTweaker implements ITweaker {
|
||||
|
||||
List<String> args;
|
||||
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>(args);
|
||||
if (gameDir != null) {
|
||||
addArg("gameDir", gameDir.getAbsolutePath());
|
||||
}
|
||||
if (assetsDir != null) {
|
||||
addArg("assetsDir", assetsDir.getAbsolutePath());
|
||||
}
|
||||
if (profile != null) {
|
||||
addArg("version", profile);
|
||||
}
|
||||
}
|
||||
public class BaritoneTweaker extends SimpleTweaker {
|
||||
|
||||
@Override
|
||||
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
|
||||
MixinBootstrap.init();
|
||||
|
||||
// noinspection unchecked
|
||||
List<String> tweakClasses = (List<String>) Launch.blackboard.get("TweakClasses");
|
||||
|
||||
String obfuscation = ObfuscationServiceMCP.NOTCH;
|
||||
if (tweakClasses.stream().anyMatch(s -> s.contains("net.minecraftforge.fml.common.launcher"))) {
|
||||
obfuscation = ObfuscationServiceMCP.SEARGE;
|
||||
}
|
||||
|
||||
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(obfuscation);
|
||||
|
||||
Mixins.addConfiguration("mixins.baritone.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLaunchTarget() {
|
||||
return "net.minecraft.client.main.Main";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getLaunchArguments() {
|
||||
return this.args.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void addArg(String label, String value) {
|
||||
if (!args.contains("--" + label) && value != null) {
|
||||
this.args.add("--" + label);
|
||||
this.args.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:09 PM
|
||||
*/
|
||||
public class BaritoneTweakerForge extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
|
||||
}
|
||||
}
|
||||
@@ -20,7 +20,7 @@ package baritone.launch.mixins;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RotationMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -40,8 +40,8 @@ public class MixinEntity {
|
||||
)
|
||||
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -50,7 +50,7 @@ public class MixinEntity {
|
||||
)
|
||||
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,8 +20,7 @@ package baritone.launch.mixins;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RotationMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -40,9 +39,11 @@ public class MixinEntityLivingBase {
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preJump(CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.JUMP));
|
||||
EntityLivingBase _this = (EntityLivingBase) (Object) this;
|
||||
// This uses Class.isInstance instead of instanceof since proguard optimizes out the instanceof (since MixinEntityLivingBase could never be instanceof EntityLivingBase in normal java)
|
||||
// but proguard isn't smart enough to optimize out this Class.isInstance =)
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.JUMP));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -50,8 +51,9 @@ public class MixinEntityLivingBase {
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postJump(CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.JUMP));
|
||||
EntityLivingBase _this = (EntityLivingBase) (Object) this;
|
||||
// See above
|
||||
if (EntityPlayerSP.class.isInstance(_this))
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.JUMP));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,10 +21,13 @@ import baritone.Baritone;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.player.PlayerCapabilities;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
@@ -40,7 +43,7 @@ public class MixinEntityPlayerSP {
|
||||
cancellable = true
|
||||
)
|
||||
private void sendChatMessage(String msg, CallbackInfo ci) {
|
||||
ChatEvent event = new ChatEvent(msg);
|
||||
ChatEvent event = new ChatEvent((EntityPlayerSP) (Object) this, msg);
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendChatMessage(event);
|
||||
if (event.isCancelled()) {
|
||||
ci.cancel();
|
||||
@@ -57,7 +60,7 @@ public class MixinEntityPlayerSP {
|
||||
)
|
||||
)
|
||||
private void onPreUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.PRE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -70,6 +73,18 @@ public class MixinEntityPlayerSP {
|
||||
)
|
||||
)
|
||||
private void onPostUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.POST));
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "onLivingUpdate",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z"
|
||||
)
|
||||
)
|
||||
private boolean isAllowFlying(PlayerCapabilities capabilities) {
|
||||
PathingBehavior pathingBehavior = Baritone.INSTANCE.getPathingBehavior();
|
||||
return (!pathingBehavior.isEnabled() || !pathingBehavior.isPathing()) && capabilities.allowFlying;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,9 +22,7 @@ import baritone.api.event.events.BlockInteractEvent;
|
||||
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;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
@@ -40,7 +38,6 @@ 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;
|
||||
|
||||
/**
|
||||
@@ -50,8 +47,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow
|
||||
private int leftClickCounter;
|
||||
@Shadow
|
||||
public EntityPlayerSP player;
|
||||
@Shadow
|
||||
@@ -63,7 +58,6 @@ public class MixinMinecraft {
|
||||
)
|
||||
private void postInit(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -148,7 +142,7 @@ public class MixinMinecraft {
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && Baritone.INSTANCE.getPathingBehavior().isEnabled() && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
||||
@@ -54,7 +54,7 @@ public class MixinNetworkManager {
|
||||
)
|
||||
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
|
||||
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket));
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, inPacket));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,7 +64,7 @@ public class MixinNetworkManager {
|
||||
)
|
||||
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
|
||||
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket));
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent((NetworkManager) (Object) this, EventState.POST, inPacket));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ public class MixinNetworkManager {
|
||||
)
|
||||
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet));}
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet));}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -86,7 +86,7 @@ public class MixinNetworkManager {
|
||||
)
|
||||
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
if (this.channel.isOpen() && this.direction == EnumPacketDirection.CLIENTBOUND) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.POST, packet));
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.POST, packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,11 +18,15 @@
|
||||
package baritone;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritoneProvider;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.behavior.*;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.event.GameEventHandler;
|
||||
import baritone.utils.BaritoneAutoTest;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
@@ -40,7 +44,7 @@ import java.util.concurrent.TimeUnit;
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:50 PM
|
||||
*/
|
||||
public enum Baritone {
|
||||
public enum Baritone implements IBaritoneProvider {
|
||||
|
||||
/**
|
||||
* Singleton instance of this class
|
||||
@@ -55,10 +59,16 @@ public enum Baritone {
|
||||
private GameEventHandler gameEventHandler;
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
private Settings settings;
|
||||
private List<Behavior> behaviors;
|
||||
private File dir;
|
||||
private ThreadPoolExecutor threadPool;
|
||||
|
||||
private List<Behavior> behaviors;
|
||||
private PathingBehavior pathingBehavior;
|
||||
private LookBehavior lookBehavior;
|
||||
private MemoryBehavior memoryBehavior;
|
||||
private FollowBehavior followBehavior;
|
||||
private MineBehavior mineBehavior;
|
||||
|
||||
/**
|
||||
* Whether or not Baritone is active
|
||||
*/
|
||||
@@ -81,12 +91,13 @@ public enum Baritone {
|
||||
|
||||
this.behaviors = new ArrayList<>();
|
||||
{
|
||||
registerBehavior(PathingBehavior.INSTANCE);
|
||||
registerBehavior(LookBehavior.INSTANCE);
|
||||
registerBehavior(MemoryBehavior.INSTANCE);
|
||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||
registerBehavior(FollowBehavior.INSTANCE);
|
||||
registerBehavior(MineBehavior.INSTANCE);
|
||||
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
|
||||
pathingBehavior = new PathingBehavior(this);
|
||||
lookBehavior = new LookBehavior(this);
|
||||
memoryBehavior = new MemoryBehavior(this);
|
||||
followBehavior = new FollowBehavior(this);
|
||||
mineBehavior = new MineBehavior(this);
|
||||
new ExampleBaritoneControl(this);
|
||||
}
|
||||
if (BaritoneAutoTest.ENABLE_AUTO_TEST) {
|
||||
registerEventListener(BaritoneAutoTest.INSTANCE);
|
||||
@@ -127,6 +138,42 @@ public enum Baritone {
|
||||
this.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public FollowBehavior getFollowBehavior() {
|
||||
return followBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public LookBehavior getLookBehavior() {
|
||||
return lookBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MemoryBehavior getMemoryBehavior() {
|
||||
return memoryBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MineBehavior getMineBehavior() {
|
||||
return mineBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingBehavior getPathingBehavior() {
|
||||
return pathingBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldProvider getWorldProvider() {
|
||||
return WorldProvider.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public WorldScanner getWorldScanner() {
|
||||
return WorldScanner.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void registerEventListener(IGameEventListener listener) {
|
||||
this.gameEventHandler.registerEventListener(listener);
|
||||
}
|
||||
|
||||
@@ -22,11 +22,12 @@ import baritone.api.behavior.*;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.behavior.*;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
|
||||
/**
|
||||
* todo fix this cancer
|
||||
*
|
||||
* @author Brady
|
||||
* @since 9/29/2018
|
||||
*/
|
||||
@@ -34,27 +35,27 @@ public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
@Override
|
||||
public IFollowBehavior getFollowBehavior() {
|
||||
return FollowBehavior.INSTANCE;
|
||||
return Baritone.INSTANCE.getFollowBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public ILookBehavior getLookBehavior() {
|
||||
return LookBehavior.INSTANCE;
|
||||
return Baritone.INSTANCE.getLookBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMemoryBehavior getMemoryBehavior() {
|
||||
return MemoryBehavior.INSTANCE;
|
||||
return Baritone.INSTANCE.getMemoryBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IMineBehavior getMineBehavior() {
|
||||
return MineBehavior.INSTANCE;
|
||||
return Baritone.INSTANCE.getMineBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPathingBehavior getPathingBehavior() {
|
||||
return PathingBehavior.INSTANCE;
|
||||
return Baritone.INSTANCE.getPathingBehavior();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.behavior.IBehavior;
|
||||
|
||||
/**
|
||||
@@ -27,11 +28,18 @@ import baritone.api.behavior.IBehavior;
|
||||
*/
|
||||
public class Behavior implements IBehavior {
|
||||
|
||||
public final Baritone baritone;
|
||||
|
||||
/**
|
||||
* Whether or not this behavior is enabled
|
||||
*/
|
||||
private boolean enabled = true;
|
||||
|
||||
protected Behavior(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
baritone.registerBehavior(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Toggles the enabled state of this {@link Behavior}.
|
||||
*
|
||||
|
||||
@@ -33,11 +33,11 @@ import net.minecraft.util.math.BlockPos;
|
||||
*/
|
||||
public final class FollowBehavior extends Behavior implements IFollowBehavior, Helper {
|
||||
|
||||
public static final FollowBehavior INSTANCE = new FollowBehavior();
|
||||
|
||||
private Entity following;
|
||||
|
||||
private FollowBehavior() {}
|
||||
public FollowBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
@@ -56,9 +56,9 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H
|
||||
GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get());
|
||||
pos = new BlockPos(g.getX(), following.posY, g.getZ());
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalNear(pos, Baritone.settings().followRadius.get()));
|
||||
PathingBehavior.INSTANCE.revalidateGoal();
|
||||
PathingBehavior.INSTANCE.path();
|
||||
baritone.getPathingBehavior().setGoal(new GoalNear(pos, Baritone.settings().followRadius.get()));
|
||||
((PathingBehavior) baritone.getPathingBehavior()).revalidateGoal();
|
||||
baritone.getPathingBehavior().path();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -73,7 +73,7 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
baritone.getPathingBehavior().cancel();
|
||||
follow(null);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,53 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.BlockBed;
|
||||
|
||||
/**
|
||||
* A collection of event methods that are used to interact with Baritone's
|
||||
* waypoint system. This class probably needs a better name.
|
||||
*
|
||||
* @see Waypoint
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
public final class LocationTrackingBehavior extends Behavior implements Helper {
|
||||
|
||||
public static final LocationTrackingBehavior INSTANCE = new LocationTrackingBehavior();
|
||||
|
||||
private LocationTrackingBehavior() {}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
}
|
||||
}
|
||||
@@ -26,9 +26,6 @@ import baritone.api.utils.Rotation;
|
||||
import baritone.utils.Helper;
|
||||
|
||||
public final class LookBehavior extends Behavior implements ILookBehavior, Helper {
|
||||
|
||||
public static final LookBehavior INSTANCE = new LookBehavior();
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
@@ -49,7 +46,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior, Helpe
|
||||
*/
|
||||
private float lastYaw;
|
||||
|
||||
private LookBehavior() {}
|
||||
public LookBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTarget(Rotation target, boolean force) {
|
||||
|
||||
@@ -1,139 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.RayTraceUtils;
|
||||
import baritone.utils.Utils;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.utils.Utils.DEG_TO_RAD;
|
||||
|
||||
public final class LookBehaviorUtils implements Helper {
|
||||
|
||||
/**
|
||||
* Offsets from the root block position to the center of each side.
|
||||
*/
|
||||
private static final Vec3d[] BLOCK_SIDE_MULTIPLIERS = new Vec3d[]{
|
||||
new Vec3d(0.5, 0, 0.5), // Down
|
||||
new Vec3d(0.5, 1, 0.5), // Up
|
||||
new Vec3d(0.5, 0.5, 0), // North
|
||||
new Vec3d(0.5, 0.5, 1), // South
|
||||
new Vec3d(0, 0.5, 0.5), // West
|
||||
new Vec3d(1, 0.5, 0.5) // East
|
||||
};
|
||||
|
||||
/**
|
||||
* Calculates a vector given a rotation array
|
||||
*
|
||||
* @param rotation {@link LookBehavior#target}
|
||||
* @return vector of the rotation
|
||||
*/
|
||||
public static Vec3d calcVec3dFromRotation(Rotation rotation) {
|
||||
float f = MathHelper.cos(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI);
|
||||
float f1 = MathHelper.sin(-rotation.getYaw() * (float) DEG_TO_RAD - (float) Math.PI);
|
||||
float f2 = -MathHelper.cos(-rotation.getPitch() * (float) DEG_TO_RAD);
|
||||
float f3 = MathHelper.sin(-rotation.getPitch() * (float) DEG_TO_RAD);
|
||||
return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2));
|
||||
}
|
||||
|
||||
public static Optional<Rotation> reachable(BlockPos pos) {
|
||||
if (pos.equals(getSelectedBlock().orElse(null))) {
|
||||
/*
|
||||
* why add 0.0001?
|
||||
* to indicate that we actually have a desired pitch
|
||||
* the way we indicate that the pitch can be whatever and we only care about the yaw
|
||||
* is by setting the desired pitch to the current pitch
|
||||
* setting the desired pitch to the current pitch + 0.0001 means that we do have a desired pitch, it's
|
||||
* just what it currently is
|
||||
*/
|
||||
return Optional.of(new Rotation(mc.player.rotationYaw, mc.player.rotationPitch + 0.0001f));
|
||||
}
|
||||
Optional<Rotation> possibleRotation = reachableCenter(pos);
|
||||
//System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(mc.world, pos);
|
||||
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
|
||||
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(pos, new Vec3d(pos).add(xDiff, yDiff, zDiff));
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if coordinate is reachable with the given block-face rotation offset
|
||||
*
|
||||
* @param pos
|
||||
* @param offsetPos
|
||||
* @return
|
||||
*/
|
||||
protected static Optional<Rotation> reachableOffset(BlockPos pos, Vec3d offsetPos) {
|
||||
Rotation rotation = Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), offsetPos);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
|
||||
System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
if (BlockStateInterface.get(pos).getBlock() instanceof BlockFire) {
|
||||
if (result.getBlockPos().equals(pos.down())) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if center of block at coordinate is reachable
|
||||
*
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
protected static Optional<Rotation> reachableCenter(BlockPos pos) {
|
||||
return reachableOffset(pos, Utils.calcCenterFromCoords(pos, mc.world));
|
||||
}
|
||||
|
||||
/**
|
||||
* The currently highlighted block.
|
||||
* Updated once a tick by Minecraft.
|
||||
*
|
||||
* @return the position of the highlighted block
|
||||
*/
|
||||
public static Optional<BlockPos> getSelectedBlock() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
return Optional.of(mc.objectMouseOver.getBlockPos());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
@@ -17,14 +17,19 @@
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.behavior.IMemoryBehavior;
|
||||
import baritone.api.behavior.memory.IRememberedInventory;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.BlockBed;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.client.CPacketCloseWindow;
|
||||
@@ -43,11 +48,11 @@ import java.util.*;
|
||||
*/
|
||||
public final class MemoryBehavior extends Behavior implements IMemoryBehavior, Helper {
|
||||
|
||||
public static MemoryBehavior INSTANCE = new MemoryBehavior();
|
||||
|
||||
private final Map<IWorldData, WorldDataContainer> worldDataContainers = new HashMap<>();
|
||||
|
||||
private MemoryBehavior() {}
|
||||
public MemoryBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
@@ -114,6 +119,18 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
}
|
||||
|
||||
private Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
|
||||
return this.getCurrentContainer().rememberedInventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
|
||||
}
|
||||
|
||||
@@ -19,23 +19,24 @@ package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.behavior.IMineBehavior;
|
||||
import baritone.api.event.events.PathEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.*;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.cache.CachedChunk;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalTwoBlocks;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.*;
|
||||
@@ -47,14 +48,15 @@ import java.util.stream.Collectors;
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class MineBehavior extends Behavior implements IMineBehavior, Helper {
|
||||
|
||||
public static final MineBehavior INSTANCE = new MineBehavior();
|
||||
|
||||
public static final int ORE_LOCATIONS_COUNT = 64;
|
||||
private List<Block> mining;
|
||||
private List<BlockPos> locationsCache;
|
||||
private int quantity;
|
||||
private List<BlockPos> knownOreLocations;
|
||||
private BlockPos branchPoint;
|
||||
private int desiredQuantity;
|
||||
|
||||
private MineBehavior() {}
|
||||
public MineBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
@@ -65,75 +67,125 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
if (quantity > 0) {
|
||||
if (desiredQuantity > 0) {
|
||||
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0);
|
||||
int curr = player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum();
|
||||
System.out.println("Currently have " + curr + " " + item);
|
||||
if (curr >= quantity) {
|
||||
if (curr >= desiredQuantity) {
|
||||
logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1)));
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
}
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
|
||||
if (mineGoalUpdateInterval != 0) {
|
||||
if (event.getCount() % mineGoalUpdateInterval == 0) {
|
||||
Baritone.INSTANCE.getExecutor().execute(this::updateGoal);
|
||||
}
|
||||
if (mineGoalUpdateInterval != 0 && event.getCount() % mineGoalUpdateInterval == 0) {
|
||||
Baritone.INSTANCE.getExecutor().execute(this::rescan);
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
addNearby();
|
||||
}
|
||||
PathingBehavior.INSTANCE.revalidateGoal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
updateGoal();
|
||||
baritone.getPathingBehavior().revalidateGoal();
|
||||
}
|
||||
|
||||
private void updateGoal() {
|
||||
if (mining == null) {
|
||||
if (mining == null || world() == null || player() == null) {
|
||||
return;
|
||||
}
|
||||
if (!locationsCache.isEmpty()) {
|
||||
locationsCache = prune(new ArrayList<>(locationsCache), mining, 64);
|
||||
PathingBehavior.INSTANCE.setGoal(coalesce(locationsCache));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
List<BlockPos> locs = knownOreLocations;
|
||||
if (!locs.isEmpty()) {
|
||||
List<BlockPos> locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, world());
|
||||
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new)));
|
||||
knownOreLocations = locs2;
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = scanFor(mining, 64);
|
||||
// we don't know any ore locations at the moment
|
||||
if (!Baritone.settings().legitMine.get()) {
|
||||
return;
|
||||
}
|
||||
// only in non-Xray mode (aka legit mode) do we do this
|
||||
if (branchPoint == null) {
|
||||
int y = Baritone.settings().legitMineYLevel.get();
|
||||
if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
||||
// cool, path is over and we are at desired y
|
||||
branchPoint = playerFeet();
|
||||
} else {
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalYLevel(y));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
if (playerFeet().equals(branchPoint)) {
|
||||
// TODO mine 1x1 shafts to either side
|
||||
branchPoint = branchPoint.north(10);
|
||||
}
|
||||
baritone.getPathingBehavior().setGoalAndPath(new GoalBlock(branchPoint));
|
||||
}
|
||||
|
||||
private void rescan() {
|
||||
if (mining == null || world() == null || player() == null) {
|
||||
return;
|
||||
}
|
||||
if (Baritone.settings().legitMine.get()) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world());
|
||||
locs.addAll(droppedItemsScan(mining, world()));
|
||||
if (locs.isEmpty()) {
|
||||
logDebug("No locations for " + mining + " known, cancelling");
|
||||
cancel();
|
||||
mine(0, (String[]) null);
|
||||
return;
|
||||
}
|
||||
locationsCache = locs;
|
||||
PathingBehavior.INSTANCE.setGoal(coalesce(locs));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
knownOreLocations = locs;
|
||||
}
|
||||
|
||||
public GoalComposite coalesce(List<BlockPos> locs) {
|
||||
return new GoalComposite(locs.stream().map(loc -> {
|
||||
if (!Baritone.settings().forceInternalMining.get()) {
|
||||
private static Goal coalesce(BlockPos loc, List<BlockPos> locs) {
|
||||
if (!Baritone.settings().forceInternalMining.get()) {
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
|
||||
boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR);
|
||||
boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR);
|
||||
if (upwardGoal) {
|
||||
if (downwardGoal) {
|
||||
return new GoalTwoBlocks(loc);
|
||||
} else {
|
||||
return new GoalBlock(loc);
|
||||
}
|
||||
} else {
|
||||
if (downwardGoal) {
|
||||
return new GoalBlock(loc.down());
|
||||
} else {
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
|
||||
boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR);
|
||||
boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(loc.up()) == Blocks.AIR);
|
||||
if (upwardGoal) {
|
||||
if (downwardGoal) {
|
||||
return new GoalTwoBlocks(loc);
|
||||
} else {
|
||||
return new GoalBlock(loc);
|
||||
}
|
||||
} else {
|
||||
if (downwardGoal) {
|
||||
return new GoalBlock(loc.down());
|
||||
} else {
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
}
|
||||
}).toArray(Goal[]::new));
|
||||
}
|
||||
}
|
||||
|
||||
public List<BlockPos> scanFor(List<Block> mining, int max) {
|
||||
public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) {
|
||||
if (!Baritone.settings().mineScanDroppedItems.get()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Item> searchingFor = new HashSet<>();
|
||||
for (Block block : mining) {
|
||||
Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0);
|
||||
Item ore = Item.getItemFromBlock(block);
|
||||
searchingFor.add(drop);
|
||||
searchingFor.add(ore);
|
||||
}
|
||||
List<BlockPos> ret = new ArrayList<>();
|
||||
for (Entity entity : world.loadedEntityList) {
|
||||
if (entity instanceof EntityItem) {
|
||||
EntityItem ei = (EntityItem) entity;
|
||||
if (searchingFor.contains(ei.getItem().getItem())) {
|
||||
ret.add(entity.getPosition());
|
||||
}
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<Block> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
@@ -150,46 +202,79 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
|
||||
}
|
||||
if (!uninteresting.isEmpty()) {
|
||||
//long before = System.currentTimeMillis();
|
||||
locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max, 10, 26));
|
||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26));
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
return prune(locs, mining, max);
|
||||
return prune(locs, mining, max, world);
|
||||
}
|
||||
|
||||
public List<BlockPos> prune(List<BlockPos> locs, List<Block> mining, int max) {
|
||||
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
|
||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
||||
public void addNearby() {
|
||||
BlockPos playerFeet = playerFeet();
|
||||
int searchDist = 4;//why four? idk
|
||||
for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) {
|
||||
for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) {
|
||||
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
|
||||
BlockPos pos = new BlockPos(x, y, z);
|
||||
if (mining.contains(BlockStateInterface.getBlock(pos)) && RotationUtils.reachable(player(), pos).isPresent()) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught
|
||||
knownOreLocations.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT, world());
|
||||
}
|
||||
|
||||
public static List<BlockPos> prune(List<BlockPos> locs2, List<Block> mining, int max, World world) {
|
||||
List<BlockPos> dropped = droppedItemsScan(mining, world);
|
||||
List<BlockPos> locs = locs2
|
||||
.stream()
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
.filter(pos -> world.getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()) || dropped.contains(pos))
|
||||
|
||||
// remove any that are implausible to mine (encased in bedrock, or touching lava)
|
||||
.filter(MineBehavior::plausibleToBreak)
|
||||
|
||||
.sorted(Comparator.comparingDouble(Helper.HELPER.playerFeet()::distanceSq))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
locs.removeAll(locs.stream()
|
||||
.filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk))
|
||||
.filter(pos -> !mining.contains(BlockStateInterface.get(pos).getBlock()))
|
||||
.collect(Collectors.toList()));
|
||||
if (locs.size() > max) {
|
||||
return locs.subList(0, max);
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
|
||||
public static boolean plausibleToBreak(BlockPos pos) {
|
||||
if (MovementHelper.avoidBreaking(pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(pos))) {
|
||||
return false;
|
||||
}
|
||||
// bedrock above and below makes it implausible, otherwise we're good
|
||||
return !(BlockStateInterface.getBlock(pos.up()) == Blocks.BEDROCK && BlockStateInterface.getBlock(pos.down()) == Blocks.BEDROCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mine(int quantity, String... blocks) {
|
||||
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList());
|
||||
this.quantity = quantity;
|
||||
this.locationsCache = new ArrayList<>();
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
this.branchPoint = null;
|
||||
rescan();
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mine(int quantity, Block... blocks) {
|
||||
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks);
|
||||
this.quantity = quantity;
|
||||
this.locationsCache = new ArrayList<>();
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
this.branchPoint = null;
|
||||
rescan();
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
mine(0, (String[]) null);
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
baritone.getPathingBehavior().cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,33 +23,32 @@ import baritone.api.event.events.PathEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.IPathFinder;
|
||||
import baritone.pathing.calc.CutoffPath;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BlockBreakHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.PathRenderer;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.init.Blocks;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
public final class PathingBehavior extends Behavior implements IPathingBehavior, Helper {
|
||||
|
||||
public static final PathingBehavior INSTANCE = new PathingBehavior();
|
||||
|
||||
private PathExecutor current;
|
||||
private PathExecutor next;
|
||||
|
||||
@@ -62,29 +61,46 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
|
||||
private boolean lastAutoJump;
|
||||
|
||||
private PathingBehavior() {}
|
||||
private final LinkedBlockingQueue<PathEvent> toDispatch = new LinkedBlockingQueue<>();
|
||||
|
||||
private void dispatchPathEvent(PathEvent event) {
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event));
|
||||
public PathingBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
private void queuePathEvent(PathEvent event) {
|
||||
toDispatch.add(event);
|
||||
}
|
||||
|
||||
private void dispatchEvents() {
|
||||
ArrayList<PathEvent> curr = new ArrayList<>();
|
||||
toDispatch.drainTo(curr);
|
||||
for (PathEvent event : curr) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPathEvent(event);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
dispatchEvents();
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
this.cancel();
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
mc.playerController.setPlayerCapabilities(mc.player);
|
||||
tickPath();
|
||||
dispatchEvents();
|
||||
}
|
||||
|
||||
private void tickPath() {
|
||||
if (current == null) {
|
||||
return;
|
||||
}
|
||||
boolean safe = current.onTick(event);
|
||||
boolean safe = current.onTick();
|
||||
synchronized (pathPlanLock) {
|
||||
if (current.failed() || current.finished()) {
|
||||
current = null;
|
||||
if (goal == null || goal.isInGoal(playerFeet())) {
|
||||
logDebug("All done. At " + goal);
|
||||
dispatchPathEvent(PathEvent.AT_GOAL);
|
||||
queuePathEvent(PathEvent.AT_GOAL);
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
@@ -96,41 +112,38 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
// but if we fail in the middle of current
|
||||
// we're nowhere close to our planned ahead path
|
||||
// so need to discard it sadly.
|
||||
dispatchPathEvent(PathEvent.DISCARD_NEXT);
|
||||
queuePathEvent(PathEvent.DISCARD_NEXT);
|
||||
next = null;
|
||||
}
|
||||
if (next != null) {
|
||||
logDebug("Continuing on to planned next path");
|
||||
dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
|
||||
queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
|
||||
current = next;
|
||||
next = null;
|
||||
current.onTick();
|
||||
return;
|
||||
}
|
||||
// at this point, current just ended, but we aren't in the goal and have no plan for the future
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
dispatchPathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
|
||||
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
|
||||
// if we aren't calculating right now
|
||||
return;
|
||||
}
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
queuePathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
}
|
||||
return;
|
||||
}
|
||||
// at this point, we know current is in progress
|
||||
if (safe) {
|
||||
// a movement just ended
|
||||
if (next != null) {
|
||||
if (next.getPath().positions().contains(playerFeet())) {
|
||||
// jump directly onto the next path
|
||||
logDebug("Splicing into planned next path early...");
|
||||
dispatchPathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
|
||||
current = next;
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (safe && next != null && player().onGround && next.snipsnapifpossible()) {
|
||||
// a movement just ended; jump directly onto the next path
|
||||
logDebug("Splicing into planned next path early...");
|
||||
queuePathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
|
||||
current = next;
|
||||
next = null;
|
||||
current.onTick();
|
||||
return;
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
@@ -148,7 +161,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
|
||||
// and this path has 5 seconds or less left
|
||||
logDebug("Path almost over. Planning ahead...");
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
|
||||
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
|
||||
findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath()));
|
||||
}
|
||||
}
|
||||
@@ -185,24 +198,29 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public boolean setGoalAndPath(Goal goal) {
|
||||
setGoal(goal);
|
||||
return path();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathExecutor getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathExecutor getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
// TODO: Expose this method in the API?
|
||||
// In order to do so, we'd need to move over IPath which has a whole lot of references to other
|
||||
// things that may not need to be exposed necessarily, so we'll need to figure that out.
|
||||
public Optional<IPath> getPath() {
|
||||
return Optional.ofNullable(current).map(PathExecutor::getPath);
|
||||
@Override
|
||||
public Optional<IPathFinder> getPathFinder() {
|
||||
return Optional.ofNullable(AbstractNodeCostSearch.currentlyRunning());
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -212,7 +230,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
|
||||
@Override
|
||||
public void cancel() {
|
||||
dispatchPathEvent(PathEvent.CANCELED);
|
||||
queuePathEvent(PathEvent.CANCELED);
|
||||
current = null;
|
||||
next = null;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
@@ -245,7 +263,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (isPathCalcInProgress) {
|
||||
return false;
|
||||
}
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
queuePathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
return true;
|
||||
}
|
||||
@@ -253,12 +271,46 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #209
|
||||
*
|
||||
* @return The starting {@link BlockPos} for a new path
|
||||
*/
|
||||
private BlockPos pathStart() {
|
||||
public BlockPos pathStart() {
|
||||
BetterBlockPos feet = playerFeet();
|
||||
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) {
|
||||
return feet.down();
|
||||
if (!MovementHelper.canWalkOn(feet.down())) {
|
||||
if (player().onGround) {
|
||||
double playerX = player().posX;
|
||||
double playerZ = player().posZ;
|
||||
ArrayList<BetterBlockPos> closest = new ArrayList<>();
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
closest.add(new BetterBlockPos(feet.x + dx, feet.y, feet.z + dz));
|
||||
}
|
||||
}
|
||||
closest.sort(Comparator.comparingDouble(pos -> ((pos.x + 0.5D) - playerX) * ((pos.x + 0.5D) - playerX) + ((pos.z + 0.5D) - playerZ) * ((pos.z + 0.5D) - playerZ)));
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BetterBlockPos possibleSupport = closest.get(i);
|
||||
double xDist = Math.abs((possibleSupport.x + 0.5D) - playerX);
|
||||
double zDist = Math.abs((possibleSupport.z + 0.5D) - playerZ);
|
||||
if (xDist > 0.8 && zDist > 0.8) {
|
||||
// can't possibly be sneaking off of this one, we're too far away
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canWalkOn(possibleSupport.down()) && MovementHelper.canWalkThrough(possibleSupport) && MovementHelper.canWalkThrough(possibleSupport.up())) {
|
||||
// this is plausible
|
||||
logDebug("Faking path start assuming player is standing off the edge of a block");
|
||||
return possibleSupport;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
// !onGround
|
||||
// we're in the middle of a jump
|
||||
if (MovementHelper.canWalkOn(feet.down().down())) {
|
||||
logDebug("Faking path start assuming player is midair and falling");
|
||||
return feet.down();
|
||||
}
|
||||
}
|
||||
}
|
||||
return feet;
|
||||
}
|
||||
@@ -276,31 +328,53 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
isPathCalcInProgress = true;
|
||||
}
|
||||
CalculationContext context = new CalculationContext(); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> {
|
||||
if (talkAboutIt) {
|
||||
logDebug("Starting to search for path from " + start + " to " + goal);
|
||||
}
|
||||
|
||||
Optional<IPath> path = findPath(start, previous);
|
||||
Optional<IPath> path = findPath(start, previous, context);
|
||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||
path = path.map(IPath::cutoffAtLoadedChunks);
|
||||
path = path.map(p -> {
|
||||
IPath result = p.cutoffAtLoadedChunks();
|
||||
|
||||
if (result instanceof CutoffPath) {
|
||||
logDebug("Cutting off path at edge of loaded chunks");
|
||||
logDebug("Length decreased by " + (p.length() - result.length()));
|
||||
} else {
|
||||
logDebug("Path ends within loaded chunks");
|
||||
}
|
||||
|
||||
return result;
|
||||
});
|
||||
}
|
||||
Optional<PathExecutor> executor = path.map(p -> p.staticCutoff(goal)).map(PathExecutor::new);
|
||||
|
||||
Optional<PathExecutor> executor = path.map(p -> {
|
||||
IPath result = p.staticCutoff(goal);
|
||||
|
||||
if (result instanceof CutoffPath) {
|
||||
logDebug("Static cutoff " + p.length() + " to " + result.length());
|
||||
}
|
||||
|
||||
return result;
|
||||
}).map(PathExecutor::new);
|
||||
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
current = executor.get();
|
||||
} else {
|
||||
dispatchPathEvent(PathEvent.CALC_FAILED);
|
||||
queuePathEvent(PathEvent.CALC_FAILED);
|
||||
}
|
||||
} else {
|
||||
if (next == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
|
||||
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
|
||||
next = executor.get();
|
||||
} else {
|
||||
dispatchPathEvent(PathEvent.NEXT_CALC_FAILED);
|
||||
queuePathEvent(PathEvent.NEXT_CALC_FAILED);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("I have no idea what to do with this path");
|
||||
@@ -328,19 +402,15 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
* @param start
|
||||
* @return
|
||||
*/
|
||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
|
||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
|
||||
Goal goal = this.goal;
|
||||
if (goal == null) {
|
||||
logDebug("no goal");
|
||||
return Optional.empty();
|
||||
}
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
|
||||
BlockPos pos = null;
|
||||
if (goal instanceof IGoalRenderPos) {
|
||||
pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
}
|
||||
|
||||
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
|
||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
if (world().getChunk(pos) instanceof EmptyChunk) {
|
||||
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
@@ -351,14 +421,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
} else {
|
||||
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
|
||||
}
|
||||
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
|
||||
Optional<LongOpenHashSet> favoredPositions = Optional.empty();
|
||||
if (Baritone.settings().backtrackCostFavoringCoefficient.get() != 1D && previous.isPresent()) {
|
||||
LongOpenHashSet tmp = new LongOpenHashSet();
|
||||
previous.get().positions().forEach(pos -> tmp.add(BetterBlockPos.longHash(pos)));
|
||||
favoredPositions = Optional.of(tmp);
|
||||
}
|
||||
try {
|
||||
IPathFinder pf = new AStarPathFinder(start.getX(), start.getY(), start.getZ(), goal, favoredPositions);
|
||||
IPathFinder pf = new AStarPathFinder(start.getX(), start.getY(), start.getZ(), goal, favoredPositions, context);
|
||||
return pf.calculate(timeout);
|
||||
} catch (Exception e) {
|
||||
logDebug("Pathing exception: " + e);
|
||||
|
||||
+55
-33
@@ -33,40 +33,62 @@ import java.util.*;
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess, Helper {
|
||||
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(new HashSet<Block>() {{
|
||||
add(Blocks.DIAMOND_ORE);
|
||||
add(Blocks.DIAMOND_BLOCK);
|
||||
//add(Blocks.COAL_ORE);
|
||||
add(Blocks.COAL_BLOCK);
|
||||
//add(Blocks.IRON_ORE);
|
||||
add(Blocks.IRON_BLOCK);
|
||||
//add(Blocks.GOLD_ORE);
|
||||
add(Blocks.GOLD_BLOCK);
|
||||
add(Blocks.EMERALD_ORE);
|
||||
add(Blocks.EMERALD_BLOCK);
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF;
|
||||
|
||||
add(Blocks.ENDER_CHEST);
|
||||
add(Blocks.FURNACE);
|
||||
add(Blocks.CHEST);
|
||||
add(Blocks.END_PORTAL);
|
||||
add(Blocks.END_PORTAL_FRAME);
|
||||
add(Blocks.MOB_SPAWNER);
|
||||
// TODO add all shulker colors
|
||||
add(Blocks.PORTAL);
|
||||
add(Blocks.HOPPER);
|
||||
add(Blocks.BEACON);
|
||||
add(Blocks.BREWING_STAND);
|
||||
add(Blocks.SKULL);
|
||||
add(Blocks.ENCHANTING_TABLE);
|
||||
add(Blocks.ANVIL);
|
||||
add(Blocks.LIT_FURNACE);
|
||||
add(Blocks.BED);
|
||||
add(Blocks.DRAGON_EGG);
|
||||
add(Blocks.JUKEBOX);
|
||||
add(Blocks.END_GATEWAY);
|
||||
add(Blocks.WEB);
|
||||
add(Blocks.NETHER_WART);
|
||||
}});
|
||||
static {
|
||||
HashSet<Block> temp = new HashSet<>();
|
||||
temp.add(Blocks.DIAMOND_ORE);
|
||||
temp.add(Blocks.DIAMOND_BLOCK);
|
||||
//temp.add(Blocks.COAL_ORE);
|
||||
temp.add(Blocks.COAL_BLOCK);
|
||||
//temp.add(Blocks.IRON_ORE);
|
||||
temp.add(Blocks.IRON_BLOCK);
|
||||
//temp.add(Blocks.GOLD_ORE);
|
||||
temp.add(Blocks.GOLD_BLOCK);
|
||||
temp.add(Blocks.EMERALD_ORE);
|
||||
temp.add(Blocks.EMERALD_BLOCK);
|
||||
|
||||
temp.add(Blocks.ENDER_CHEST);
|
||||
temp.add(Blocks.FURNACE);
|
||||
temp.add(Blocks.CHEST);
|
||||
temp.add(Blocks.TRAPPED_CHEST);
|
||||
temp.add(Blocks.END_PORTAL);
|
||||
temp.add(Blocks.END_PORTAL_FRAME);
|
||||
temp.add(Blocks.MOB_SPAWNER);
|
||||
temp.add(Blocks.BARRIER);
|
||||
temp.add(Blocks.OBSERVER);
|
||||
temp.add(Blocks.WHITE_SHULKER_BOX);
|
||||
temp.add(Blocks.ORANGE_SHULKER_BOX);
|
||||
temp.add(Blocks.MAGENTA_SHULKER_BOX);
|
||||
temp.add(Blocks.LIGHT_BLUE_SHULKER_BOX);
|
||||
temp.add(Blocks.YELLOW_SHULKER_BOX);
|
||||
temp.add(Blocks.LIME_SHULKER_BOX);
|
||||
temp.add(Blocks.PINK_SHULKER_BOX);
|
||||
temp.add(Blocks.GRAY_SHULKER_BOX);
|
||||
temp.add(Blocks.SILVER_SHULKER_BOX);
|
||||
temp.add(Blocks.CYAN_SHULKER_BOX);
|
||||
temp.add(Blocks.PURPLE_SHULKER_BOX);
|
||||
temp.add(Blocks.BLUE_SHULKER_BOX);
|
||||
temp.add(Blocks.BROWN_SHULKER_BOX);
|
||||
temp.add(Blocks.GREEN_SHULKER_BOX);
|
||||
temp.add(Blocks.RED_SHULKER_BOX);
|
||||
temp.add(Blocks.BLACK_SHULKER_BOX);
|
||||
temp.add(Blocks.PORTAL);
|
||||
temp.add(Blocks.HOPPER);
|
||||
temp.add(Blocks.BEACON);
|
||||
temp.add(Blocks.BREWING_STAND);
|
||||
temp.add(Blocks.SKULL);
|
||||
temp.add(Blocks.ENCHANTING_TABLE);
|
||||
temp.add(Blocks.ANVIL);
|
||||
temp.add(Blocks.LIT_FURNACE);
|
||||
temp.add(Blocks.BED);
|
||||
temp.add(Blocks.DRAGON_EGG);
|
||||
temp.add(Blocks.JUKEBOX);
|
||||
temp.add(Blocks.END_GATEWAY);
|
||||
temp.add(Blocks.WEB);
|
||||
temp.add(Blocks.NETHER_WART);
|
||||
BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp);
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
|
||||
+15
@@ -319,6 +319,21 @@ public final class CachedRegion implements ICachedRegion {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized final CachedChunk mostRecentlyModified() {
|
||||
CachedChunk recent = null;
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (this.chunks[x][z] == null) {
|
||||
continue;
|
||||
}
|
||||
if (recent == null || this.chunks[x][z].cacheTimestamp > recent.cacheTimestamp) {
|
||||
recent = this.chunks[x][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
return recent;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
|
||||
+48
@@ -147,6 +147,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
region.removeExpired();
|
||||
}
|
||||
}); // even if we aren't saving to disk, still delete expired old chunks from RAM
|
||||
prune();
|
||||
return;
|
||||
}
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
@@ -157,6 +158,53 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
});
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
System.out.println("World save took " + (now - start) + "ms");
|
||||
prune();
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete regions that are too far from the player
|
||||
*/
|
||||
private synchronized void prune() {
|
||||
BlockPos pruneCenter = guessPosition();
|
||||
for (CachedRegion region : allRegions()) {
|
||||
if (region == null) {
|
||||
continue;
|
||||
}
|
||||
int distX = (region.getX() * 512 + 256) - pruneCenter.getX();
|
||||
int distZ = (region.getZ() * 512 + 256) - pruneCenter.getZ();
|
||||
double dist = Math.sqrt(distX * distX + distZ * distZ);
|
||||
if (dist > 1024) {
|
||||
logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
|
||||
cachedRegions.remove(getRegionID(region.getX(), region.getZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we are still in this world and dimension, return player feet, otherwise return most recently modified chunk
|
||||
*/
|
||||
private BlockPos guessPosition() {
|
||||
WorldData data = WorldProvider.INSTANCE.getCurrentWorld();
|
||||
if (data != null && data.getCachedWorld() == this) {
|
||||
return playerFeet();
|
||||
}
|
||||
CachedChunk mostRecentlyModified = null;
|
||||
for (CachedRegion region : allRegions()) {
|
||||
if (region == null) {
|
||||
continue;
|
||||
}
|
||||
CachedChunk ch = region.mostRecentlyModified();
|
||||
if (ch == null) {
|
||||
continue;
|
||||
}
|
||||
if (mostRecentlyModified == null || mostRecentlyModified.cacheTimestamp < ch.cacheTimestamp) {
|
||||
mostRecentlyModified = ch;
|
||||
}
|
||||
}
|
||||
if (mostRecentlyModified == null) {
|
||||
return new BlockPos(0, 0, 0);
|
||||
}
|
||||
return new BlockPos(mostRecentlyModified.x * 16 + 8, 0, mostRecentlyModified.z * 16 + 8);
|
||||
}
|
||||
|
||||
private synchronized List<CachedRegion> allRegions() {
|
||||
|
||||
+6
-3
@@ -40,6 +40,8 @@ import java.util.*;
|
||||
*/
|
||||
public final class ChunkPacker implements Helper {
|
||||
|
||||
private static final Map<String, Block> resourceCache = new HashMap<>();
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
public static CachedChunk pack(Chunk chunk) {
|
||||
@@ -93,7 +95,8 @@ public final class ChunkPacker implements Helper {
|
||||
|
||||
for (int z = 0; z < 16; z++) {
|
||||
// @formatter:off
|
||||
https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
|
||||
https:
|
||||
//www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
|
||||
// @formatter:on
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 255; y >= 0; y--) {
|
||||
@@ -120,12 +123,12 @@ public final class ChunkPacker implements Helper {
|
||||
}
|
||||
|
||||
public static Block stringToBlock(String name) {
|
||||
return Block.getBlockFromName(name.contains(":") ? name : "minecraft:" + name);
|
||||
return resourceCache.computeIfAbsent(name, n -> Block.getBlockFromName(n.contains(":") ? n : "minecraft:" + n));
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block.equals(Blocks.WATER)) {
|
||||
if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) {
|
||||
// only water source blocks are plausibly usable, flowing water should be avoid
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
+1
-1
@@ -42,7 +42,7 @@ public class WorldData implements IWorldData {
|
||||
this.waypoints = new Waypoints(directory.resolve("waypoints"));
|
||||
}
|
||||
|
||||
void onClose() {
|
||||
public void onClose() {
|
||||
Baritone.INSTANCE.getExecutor().execute(() -> {
|
||||
System.out.println("Started saving the world in a new thread");
|
||||
cache.save();
|
||||
|
||||
+1
-1
@@ -35,7 +35,7 @@ public enum WorldScanner implements IWorldScanner, Helper {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public List<BlockPos> scanLoadedChunks(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) {
|
||||
public List<BlockPos> scanChunkRadius(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) {
|
||||
if (blocks.contains(null)) {
|
||||
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString());
|
||||
}
|
||||
|
||||
@@ -18,17 +18,19 @@
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -38,16 +40,18 @@ import java.util.Optional;
|
||||
*/
|
||||
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
|
||||
private final Optional<HashSet<Long>> favoredPositions;
|
||||
private final Optional<LongOpenHashSet> favoredPositions;
|
||||
private final CalculationContext calcContext;
|
||||
|
||||
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<HashSet<Long>> favoredPositions) {
|
||||
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<LongOpenHashSet> favoredPositions, CalculationContext context) {
|
||||
super(startX, startY, startZ, goal);
|
||||
this.favoredPositions = favoredPositions;
|
||||
this.calcContext = context;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<IPath> calculate0(long timeout) {
|
||||
startNode = getNodeAtPosition(startX, startY, startZ, posHash(startX, startY, startZ));
|
||||
startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
|
||||
startNode.cost = 0;
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
|
||||
@@ -59,10 +63,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
|
||||
bestSoFar[i] = startNode;
|
||||
}
|
||||
CalculationContext calcContext = new CalculationContext();
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
HashSet<Long> favored = favoredPositions.orElse(null);
|
||||
BetterWorldBorder worldBorder = new BetterWorldBorder(world().getWorldBorder());
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
LongOpenHashSet favored = favoredPositions.orElse(null);
|
||||
long startTime = System.nanoTime() / 1000000L;
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
if (slowPath) {
|
||||
@@ -96,14 +100,18 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
for (Moves moves : Moves.values()) {
|
||||
int newX = currentNode.x + moves.xOffset;
|
||||
int newZ = currentNode.z + moves.zOffset;
|
||||
if (newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) {
|
||||
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !BlockStateInterface.isLoaded(newX, newZ)) {
|
||||
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
|
||||
if (!BlockStateInterface.isLoaded(newX, newZ)) {
|
||||
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
|
||||
numEmptyChunk++;
|
||||
}
|
||||
continue;
|
||||
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
|
||||
numEmptyChunk++;
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) {
|
||||
continue;
|
||||
}
|
||||
if (currentNode.y + moves.yOffset > 256 || currentNode.y + moves.yOffset < 0) {
|
||||
continue;
|
||||
}
|
||||
res.reset();
|
||||
moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res);
|
||||
@@ -112,17 +120,20 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
|
||||
if (actionCost >= ActionCosts.COST_INF) {
|
||||
continue;
|
||||
}
|
||||
if (actionCost <= 0) {
|
||||
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
|
||||
}
|
||||
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
|
||||
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.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);
|
||||
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
|
||||
}
|
||||
if (actionCost <= 0) {
|
||||
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
|
||||
}
|
||||
long hashCode = posHash(res.x, res.y, res.z);
|
||||
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
|
||||
if (favoring && favored.contains(hashCode)) {
|
||||
// see issue #18
|
||||
actionCost *= favorCoeff;
|
||||
|
||||
@@ -18,8 +18,9 @@
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -88,7 +89,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
this.cancelRequested = false;
|
||||
try {
|
||||
Optional<IPath> path = calculate0(timeout);
|
||||
path.ifPresent(IPath::postprocess);
|
||||
path.ifPresent(IPath::postProcess);
|
||||
isFinished = true;
|
||||
return path;
|
||||
} finally {
|
||||
@@ -140,25 +141,6 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
return node;
|
||||
}
|
||||
|
||||
public static long posHash(int x, int y, int z) {
|
||||
/*
|
||||
* 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();
|
||||
* }
|
||||
*
|
||||
* That is terrible and has tons of collisions and makes the HashMap terribly inefficient.
|
||||
*
|
||||
* That's why we grab out the X, Y, Z and calculate our own hashcode
|
||||
*/
|
||||
long hash = 3241;
|
||||
hash = 3457689L * hash + x;
|
||||
hash = 8734625L * hash + y;
|
||||
hash = 2873465L * hash + z;
|
||||
return hash;
|
||||
}
|
||||
|
||||
public static void forceCancel() {
|
||||
currentlyRunning = null;
|
||||
}
|
||||
@@ -225,4 +207,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() {
|
||||
return Optional.ofNullable(currentlyRunning);
|
||||
}
|
||||
|
||||
public static AbstractNodeCostSearch currentlyRunning() {
|
||||
return currentlyRunning;
|
||||
}
|
||||
}
|
||||
|
||||
+7
-6
@@ -15,11 +15,12 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
@@ -28,13 +29,13 @@ public class CutoffPath implements IPath {
|
||||
|
||||
private final List<BetterBlockPos> path;
|
||||
|
||||
private final List<Movement> movements;
|
||||
private final List<IMovement> movements;
|
||||
|
||||
private final int numNodes;
|
||||
|
||||
private final Goal goal;
|
||||
|
||||
public CutoffPath(IPath prev, int lastPositionToInclude) {
|
||||
CutoffPath(IPath prev, int lastPositionToInclude) {
|
||||
path = prev.positions().subList(0, lastPositionToInclude + 1);
|
||||
movements = prev.movements().subList(0, lastPositionToInclude + 1);
|
||||
numNodes = prev.getNumNodesConsidered();
|
||||
@@ -47,7 +48,7 @@ public class CutoffPath implements IPath {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Movement> movements() {
|
||||
public List<IMovement> movements() {
|
||||
return Collections.unmodifiableList(movements);
|
||||
}
|
||||
|
||||
@@ -17,12 +17,16 @@
|
||||
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -149,7 +153,7 @@ class Path implements IPath {
|
||||
}
|
||||
|
||||
@Override
|
||||
public void postprocess() {
|
||||
public void postProcess() {
|
||||
if (verified) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -161,7 +165,7 @@ class Path implements IPath {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<Movement> movements() {
|
||||
public List<IMovement> movements() {
|
||||
if (!verified) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -187,4 +191,28 @@ class Path implements IPath {
|
||||
public BetterBlockPos getDest() {
|
||||
return end;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath cutoffAtLoadedChunks() {
|
||||
for (int i = 0; i < positions().size(); i++) {
|
||||
BlockPos pos = positions().get(i);
|
||||
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return new CutoffPath(this, i);
|
||||
}
|
||||
}
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath staticCutoff(Goal destination) {
|
||||
if (length() < BaritoneAPI.getSettings().pathCutoffMinimumLength.get()) {
|
||||
return this;
|
||||
}
|
||||
if (destination == null || destination.isInGoal(getDest())) {
|
||||
return this;
|
||||
}
|
||||
double factor = BaritoneAPI.getSettings().pathCutoffFactor.get();
|
||||
int newLength = (int) (length() * factor);
|
||||
return new CutoffPath(this, newLength);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -19,6 +19,7 @@ package baritone.pathing.calc;
|
||||
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
|
||||
/**
|
||||
* A node in the path, containing the cost and steps to get to it.
|
||||
@@ -30,20 +31,20 @@ public final class PathNode {
|
||||
/**
|
||||
* The position of this node
|
||||
*/
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
public final int x;
|
||||
public final int y;
|
||||
public final int z;
|
||||
|
||||
/**
|
||||
* Cached, should always be equal to goal.heuristic(pos)
|
||||
*/
|
||||
final double estimatedCostToGoal;
|
||||
public final double estimatedCostToGoal;
|
||||
|
||||
/**
|
||||
* Total cost of getting from start to here
|
||||
* Mutable and changed by PathFinder
|
||||
*/
|
||||
double cost;
|
||||
public double cost;
|
||||
|
||||
/**
|
||||
* Should always be equal to estimatedCosttoGoal + cost
|
||||
@@ -55,13 +56,13 @@ public final class PathNode {
|
||||
* In the graph search, what previous node contributed to the cost
|
||||
* Mutable and changed by PathFinder
|
||||
*/
|
||||
PathNode previous;
|
||||
public PathNode previous;
|
||||
|
||||
/**
|
||||
* Is this a member of the open set in A*? (only used during pathfinding)
|
||||
* Instead of doing a costly member check in the open set, cache membership in each node individually too.
|
||||
*/
|
||||
boolean isOpen;
|
||||
public boolean isOpen;
|
||||
|
||||
/**
|
||||
* Where is this node in the array flattenization of the binary heap? Needed for decrease-key operations.
|
||||
@@ -85,7 +86,7 @@ public final class PathNode {
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) AbstractNodeCostSearch.posHash(x, y, z);
|
||||
return (int) BetterBlockPos.longHash(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
@@ -44,13 +45,10 @@ public class CalculationContext implements Helper {
|
||||
private final int maxFallHeightBucket;
|
||||
private final double waterWalkSpeed;
|
||||
private final double breakBlockAdditionalCost;
|
||||
private final BetterWorldBorder worldBorder;
|
||||
|
||||
public CalculationContext() {
|
||||
this(new ToolSet());
|
||||
}
|
||||
|
||||
public CalculationContext(ToolSet toolSet) {
|
||||
this.toolSet = toolSet;
|
||||
this.toolSet = new ToolSet();
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();
|
||||
this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6;
|
||||
@@ -68,6 +66,29 @@ public class CalculationContext implements Helper {
|
||||
// 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.
|
||||
this.worldBorder = new BetterWorldBorder(world().getWorldBorder());
|
||||
}
|
||||
|
||||
public boolean canPlaceThrowawayAt(int x, int y, int z) {
|
||||
if (!hasThrowaway()) { // only true if allowPlace is true, see constructor
|
||||
return false;
|
||||
}
|
||||
if (isPossiblyProtected(x, y, z)) {
|
||||
return false;
|
||||
}
|
||||
return worldBorder.canPlaceAt(x, z); // TODO perhaps MovementHelper.canPlaceAgainst could also use this?
|
||||
}
|
||||
|
||||
public boolean canBreakAt(int x, int y, int z) {
|
||||
if (!allowBreak()) {
|
||||
return false;
|
||||
}
|
||||
return !isPossiblyProtected(x, y, z);
|
||||
}
|
||||
|
||||
public boolean isPossiblyProtected(int x, int y, int z) {
|
||||
// TODO more protection logic here; see #220
|
||||
return false;
|
||||
}
|
||||
|
||||
public ToolSet getToolSet() {
|
||||
|
||||
@@ -18,13 +18,15 @@
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.behavior.LookBehavior;
|
||||
import baritone.behavior.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.utils.BlockBreakHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
@@ -32,11 +34,12 @@ import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.utils.InputOverrideHandler.Input;
|
||||
|
||||
public abstract class Movement implements Helper, MovementHelper {
|
||||
public abstract class Movement implements IMovement, Helper, MovementHelper {
|
||||
|
||||
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
|
||||
|
||||
@@ -77,24 +80,27 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
this(src, dest, toBreak, null);
|
||||
}
|
||||
|
||||
public double getCost(CalculationContext context) {
|
||||
@Override
|
||||
public double getCost() {
|
||||
if (cost == null) {
|
||||
cost = calculateCost(context != null ? context : new CalculationContext());
|
||||
cost = calculateCost(new CalculationContext());
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
protected abstract double calculateCost(CalculationContext context);
|
||||
|
||||
@Override
|
||||
public double recalculateCost() {
|
||||
cost = null;
|
||||
return getCost(null);
|
||||
return getCost();
|
||||
}
|
||||
|
||||
protected void override(double cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double calculateCostWithoutCaching() {
|
||||
return calculateCost(new CalculationContext());
|
||||
}
|
||||
@@ -105,16 +111,20 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
*
|
||||
* @return Status
|
||||
*/
|
||||
@Override
|
||||
public MovementStatus update() {
|
||||
player().capabilities.allowFlying = false;
|
||||
player().capabilities.isFlying = false;
|
||||
MovementState latestState = updateState(currentState);
|
||||
if (BlockStateInterface.isLiquid(playerFeet())) {
|
||||
if (MovementHelper.isLiquid(playerFeet())) {
|
||||
latestState.setInput(Input.JUMP, true);
|
||||
}
|
||||
if (player().isEntityInsideOpaqueBlock()) {
|
||||
latestState.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
|
||||
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
|
||||
latestState.getTarget().getRotation().ifPresent(rotation ->
|
||||
LookBehavior.INSTANCE.updateTarget(
|
||||
Baritone.INSTANCE.getLookBehavior().updateTarget(
|
||||
rotation,
|
||||
latestState.getTarget().hasToForceRotations()));
|
||||
|
||||
@@ -147,7 +157,8 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
|
||||
currentState = latestState;
|
||||
|
||||
if (isFinished()) {
|
||||
// If the current status indicates a completed movement
|
||||
if (currentState.getStatus().isComplete()) {
|
||||
onFinish(latestState);
|
||||
}
|
||||
|
||||
@@ -162,19 +173,24 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
for (BetterBlockPos blockPos : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(blockPos) && !(BlockStateInterface.getBlock(blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
|
||||
somethingInTheWay = true;
|
||||
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
||||
Optional<Rotation> reachable = RotationUtils.reachable(player(), blockPos);
|
||||
if (reachable.isPresent()) {
|
||||
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true));
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), blockPos) || BlockStateInterface.getBlock(blockPos) == Blocks.FIRE) {
|
||||
state.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
//get rekt minecraft
|
||||
//i'm doing it anyway
|
||||
//i dont care if theres snow in the way!!!!!!!
|
||||
//you dont own me!!!!
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(blockPos)), true)
|
||||
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(player().getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(blockPos)), true)
|
||||
);
|
||||
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -187,6 +203,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean safeToCancel() {
|
||||
return safeToCancel(currentState);
|
||||
}
|
||||
@@ -195,16 +212,12 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean isFinished() {
|
||||
return (currentState.getStatus() != MovementStatus.RUNNING
|
||||
&& currentState.getStatus() != MovementStatus.PREPPING
|
||||
&& currentState.getStatus() != MovementStatus.WAITING);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetterBlockPos getSrc() {
|
||||
return src;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetterBlockPos getDest() {
|
||||
return dest;
|
||||
}
|
||||
@@ -223,6 +236,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
currentState.setStatus(MovementStatus.CANCELED);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
}
|
||||
@@ -247,6 +261,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getDirection() {
|
||||
return getDest().subtract(getSrc());
|
||||
}
|
||||
@@ -255,10 +270,19 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean calculatedWhileLoaded() {
|
||||
return calculatedWhileLoaded;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void resetBlockCache() {
|
||||
toBreakCached = null;
|
||||
toPlaceCached = null;
|
||||
toWalkIntoCached = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> toBreak() {
|
||||
if (toBreakCached != null) {
|
||||
return toBreakCached;
|
||||
@@ -273,6 +297,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> toPlace() {
|
||||
if (toPlaceCached != null) {
|
||||
return toPlaceCached;
|
||||
@@ -285,6 +310,7 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> toWalkInto() { // overridden by movementdiagonal
|
||||
if (toWalkIntoCached == null) {
|
||||
toWalkIntoCached = new ArrayList<>();
|
||||
|
||||
@@ -19,27 +19,25 @@ package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.behavior.LookBehaviorUtils;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemPickaxe;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
*
|
||||
@@ -47,10 +45,6 @@ import java.util.Optional;
|
||||
*/
|
||||
public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(BetterBlockPos pos, IBlockState state) {
|
||||
return avoidBreaking(pos.x, pos.y, pos.z, state);
|
||||
}
|
||||
|
||||
static boolean avoidBreaking(int x, int y, int z, IBlockState state) {
|
||||
Block b = state.getBlock();
|
||||
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
@@ -73,10 +67,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkThrough(pos.x, pos.y, pos.z, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(BetterBlockPos pos, IBlockState state) {
|
||||
return canWalkThrough(pos.x, pos.y, pos.z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(int x, int y, int z) {
|
||||
return canWalkThrough(x, y, z, BlockStateInterface.get(x, y, z));
|
||||
}
|
||||
@@ -86,7 +76,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block == Blocks.AIR) { // early return for most common case
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL) {
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA) {
|
||||
return false;
|
||||
}
|
||||
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
|
||||
@@ -106,14 +96,20 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
if (snow) {
|
||||
return state.getValue(BlockSnow.LAYERS) < 5; // see BlockSnow.isPassable
|
||||
// the check in BlockSnow.isPassable is layers < 5
|
||||
// while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling
|
||||
if (state.getValue(BlockSnow.LAYERS) >= 3) {
|
||||
return false;
|
||||
}
|
||||
// ok, it's low enough we could walk through it, but is it supported?
|
||||
return canWalkOn(x, y - 1, z);
|
||||
}
|
||||
if (trapdoor) {
|
||||
return !state.getValue(BlockTrapDoor.OPEN); // see BlockTrapDoor.isPassable
|
||||
}
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
if (isFlowing(state)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
@@ -138,10 +134,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean fullyPassable(BlockPos pos) {
|
||||
return fullyPassable(BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean fullyPassable(int x, int y, int z) {
|
||||
return fullyPassable(BlockStateInterface.get(x, y, z));
|
||||
}
|
||||
@@ -157,6 +149,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|| block == Blocks.WEB
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.LADDER
|
||||
|| block == Blocks.COCOA
|
||||
|| block instanceof BlockDoor
|
||||
|| block instanceof BlockFenceGate
|
||||
|| block instanceof BlockSnow
|
||||
@@ -169,10 +162,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return block.isPassable(null, null);
|
||||
}
|
||||
|
||||
static boolean isReplacable(BlockPos pos, IBlockState state) {
|
||||
return isReplacable(pos.getX(), pos.getY(), pos.getZ(), state);
|
||||
}
|
||||
|
||||
static boolean isReplacable(int x, int y, int z, IBlockState state) {
|
||||
// for MovementTraverse and MovementAscend
|
||||
// block double plant defaults to true when the block doesn't match, so don't need to check that case
|
||||
@@ -196,7 +185,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
BlockDoublePlant.EnumPlantType kek = state.getValue(BlockDoublePlant.VARIANT);
|
||||
return kek == BlockDoublePlant.EnumPlantType.FERN || kek == BlockDoublePlant.EnumPlantType.GRASS;
|
||||
}
|
||||
return state.getBlock().isReplaceable(null, null);
|
||||
return state.getMaterial().isReplaceable();
|
||||
}
|
||||
|
||||
static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) {
|
||||
@@ -242,7 +231,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
|
||||
return facing == playerFacing == open;
|
||||
return (facing == playerFacing) == open;
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
@@ -270,9 +259,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return false;
|
||||
}
|
||||
if (state.isBlockNormalCube()) {
|
||||
if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this
|
||||
@@ -284,22 +270,22 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
if (isWater(block)) {
|
||||
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
|
||||
Block up = BlockStateInterface.get(x, y + 1, z).getBlock();
|
||||
if (up == Blocks.WATERLILY) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state) || block == Blocks.FLOWING_WATER) {
|
||||
if (isFlowing(state) || block == Blocks.FLOWING_WATER) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
return isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
|
||||
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
@@ -311,10 +297,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockStairs) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
return block instanceof BlockStairs;
|
||||
}
|
||||
|
||||
static boolean canWalkOn(BetterBlockPos pos, IBlockState state) {
|
||||
@@ -342,15 +325,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return state.isBlockNormalCube();
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BetterBlockPos position, boolean includeFalling) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position.x, position.y, position.z, state, includeFalling);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BetterBlockPos position, IBlockState state, boolean includeFalling) {
|
||||
return getMiningDurationTicks(context, position.x, position.y, position.z, state, includeFalling);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
|
||||
return getMiningDurationTicks(context, x, y, z, BlockStateInterface.get(x, y, z), includeFalling);
|
||||
}
|
||||
@@ -358,7 +332,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(x, y, z, state)) {
|
||||
if (!context.allowBreak()) {
|
||||
if (!context.canBreakAt(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (avoidBreaking(x, y, z, state)) {
|
||||
@@ -396,23 +370,11 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return isBottomSlab(BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* The entity the player is currently looking at
|
||||
*
|
||||
* @return the entity object
|
||||
*/
|
||||
static Optional<Entity> whatEntityAmILookingAt() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(mc.objectMouseOver.entityHit);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool
|
||||
*/
|
||||
static void switchToBestTool() {
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(pos -> {
|
||||
RayTraceUtils.getSelectedBlock().ifPresent(pos -> {
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
if (state.getBlock().equals(Blocks.AIR)) {
|
||||
return;
|
||||
@@ -437,7 +399,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @param ts previously calculated ToolSet
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
||||
mc.player.inventory.currentItem = ts.getBestSlot(b);
|
||||
mc.player.inventory.currentItem = ts.getBestSlot(b.getBlock());
|
||||
}
|
||||
|
||||
static boolean throwaway(boolean select) {
|
||||
@@ -457,15 +419,73 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (Baritone.settings().acceptableThrowawayItems.get().contains(p.inventory.offHandInventory.get(0).getItem())) {
|
||||
// main hand takes precedence over off hand
|
||||
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
|
||||
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
|
||||
// so we need to select in the main hand something that doesn't right click
|
||||
// so not a shovel, not a hoe, not a block, etc
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void moveTowards(MovementState state, BlockPos pos) {
|
||||
state.setTarget(new MovementTarget(
|
||||
new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(pos),
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getYaw(), mc.player.rotationPitch),
|
||||
false
|
||||
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified block is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param b The block
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(Block b) {
|
||||
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the block at the specified pos is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param bp The block pos
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(BlockPos bp) {
|
||||
return isWater(BlockStateInterface.getBlock(bp));
|
||||
}
|
||||
|
||||
static boolean isLava(Block b) {
|
||||
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified pos has a liquid
|
||||
*
|
||||
* @param p The pos
|
||||
* @return Whether or not the block is a liquid
|
||||
*/
|
||||
static boolean isLiquid(BlockPos p) {
|
||||
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
static boolean isFlowing(IBlockState state) {
|
||||
// Will be IFluidState in 1.13
|
||||
return state.getBlock() instanceof BlockLiquid
|
||||
&& state.getValue(BlockLiquid.LEVEL) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.utils.InputOverrideHandler.Input;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -72,10 +73,6 @@ public class MovementState {
|
||||
return this.inputState;
|
||||
}
|
||||
|
||||
public enum MovementStatus {
|
||||
PREPPING, WAITING, RUNNING, SUCCESS, UNREACHABLE, FAILED, CANCELED
|
||||
}
|
||||
|
||||
public static class MovementTarget {
|
||||
|
||||
/**
|
||||
@@ -87,9 +84,6 @@ public class MovementState {
|
||||
|
||||
/**
|
||||
* Yaw and pitch angles that must be matched
|
||||
* <p>
|
||||
* getFirst() -> YAW
|
||||
* getSecond() -> PITCH
|
||||
*/
|
||||
public Rotation rotation;
|
||||
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
@@ -148,7 +148,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_EAST(+1, 0, 0, false, true) {
|
||||
DESCEND_EAST(+1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
@@ -166,7 +166,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_WEST(-1, 0, 0, false, true) {
|
||||
DESCEND_WEST(-1, -1, 0, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
@@ -184,7 +184,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_NORTH(0, 0, -1, false, true) {
|
||||
DESCEND_NORTH(0, -1, -1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
@@ -202,7 +202,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
DESCEND_SOUTH(0, 0, +1, false, true) {
|
||||
DESCEND_SOUTH(0, -1, +1, false, true) {
|
||||
@Override
|
||||
public Movement apply0(BetterBlockPos src) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
|
||||
@@ -18,16 +18,16 @@
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.LookBehaviorUtils;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.RayTraceUtils;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -72,10 +72,10 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
boolean hasToPlace = false;
|
||||
if (!MovementHelper.canWalkOn(destX, y, destZ, toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
if (!context.canPlaceThrowawayAt(destX, y, destZ)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
|
||||
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
@@ -97,21 +97,19 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
}
|
||||
IBlockState srcUp2 = null;
|
||||
if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us
|
||||
if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(x, y + 1, z) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
|
||||
// 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 (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
|
||||
// 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
|
||||
|
||||
// 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;
|
||||
}
|
||||
// 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
|
||||
// however, in the scenario where glitchy world gen where unsupported sand / gravel generates
|
||||
// it's possible srcUp is AIR from the start, and srcUp2 is falling
|
||||
@@ -181,10 +179,10 @@ public class MovementAscend extends Movement {
|
||||
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
RayTraceUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionToPlace)) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
@@ -198,7 +196,7 @@ public class MovementAscend extends Movement {
|
||||
} else {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); // break whatever replaceable block is in the way
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
|
||||
//System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
|
||||
});
|
||||
return state;
|
||||
}
|
||||
@@ -206,10 +204,8 @@ public class MovementAscend extends Movement {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto)) {
|
||||
if (!MovementHelper.isBottomSlab(src.down())) {
|
||||
return state; // don't jump while walking from a non double slab into a bottom slab
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(src.down())) {
|
||||
return state; // don't jump while walking from a non double slab into a bottom slab
|
||||
}
|
||||
|
||||
if (Baritone.settings().assumeStep.get()) {
|
||||
|
||||
@@ -18,14 +18,14 @@
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
@@ -130,7 +130,7 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
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) && BlockStateInterface.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
|
||||
if (ontoBlock.getBlock() == Blocks.WATER && !MovementHelper.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()) {
|
||||
@@ -183,13 +183,12 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
if (playerFeet.equals(dest)) {
|
||||
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads
|
||||
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
} else {
|
||||
System.out.println(player().posY + " " + playerFeet.getY() + " " + (player().posY - playerFeet.getY()));
|
||||
}
|
||||
if (playerFeet.equals(dest) && (MovementHelper.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094)) { // lilypads
|
||||
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
/* else {
|
||||
// System.out.println(player().posY + " " + playerFeet.getY() + " " + (player().posY - playerFeet.getY()));
|
||||
}*/
|
||||
}
|
||||
double diffX = player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = player().posZ - (dest.getZ() + 0.5);
|
||||
|
||||
@@ -17,13 +17,14 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -77,11 +78,11 @@ public class MovementDiagonal extends Movement {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
Block cuttingOver1 = BlockStateInterface.get(x, y - 1, destZ).getBlock();
|
||||
if (cuttingOver1 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver1)) {
|
||||
if (cuttingOver1 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver1)) {
|
||||
return COST_INF;
|
||||
}
|
||||
Block cuttingOver2 = BlockStateInterface.get(destX, y - 1, z).getBlock();
|
||||
if (cuttingOver2 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver2)) {
|
||||
if (cuttingOver2 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver2)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb0 = BlockStateInterface.get(x, y, destZ);
|
||||
@@ -100,25 +101,22 @@ public class MovementDiagonal extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z);
|
||||
if (optionA == 0) {
|
||||
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) {
|
||||
// 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;
|
||||
}
|
||||
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 (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) {
|
||||
// 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;
|
||||
}
|
||||
return COST_INF;
|
||||
}
|
||||
boolean water = false;
|
||||
if (BlockStateInterface.isWater(BlockStateInterface.getBlock(x, y, z)) || BlockStateInterface.isWater(destInto.getBlock())) {
|
||||
Block startIn = BlockStateInterface.getBlock(x, y, z);
|
||||
if (MovementHelper.isWater(startIn) || MovementHelper.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
|
||||
@@ -127,6 +125,10 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
if (optionA != 0 || optionB != 0) {
|
||||
multiplier *= SQRT_2 - 0.001; // TODO tune
|
||||
if (startIn == Blocks.LADDER || startIn == Blocks.VINE) {
|
||||
// edging around doesn't work if doing so would climb a ladder or vine instead of moving sideways
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (context.canSprint() && !water) {
|
||||
// If we aren't edging around anything, and we aren't in water
|
||||
@@ -140,15 +142,15 @@ public class MovementDiagonal extends Movement {
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
if (!MovementHelper.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
|
||||
@@ -17,12 +17,13 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -64,12 +65,12 @@ public class MovementDownward extends Movement {
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
double diffX = player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = player().posZ - (dest.getZ() + 0.5);
|
||||
|
||||
@@ -18,18 +18,14 @@
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.RayTraceUtils;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
@@ -66,7 +62,7 @@ public class MovementFall extends Movement {
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
Rotation targetRotation = null;
|
||||
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!MovementHelper.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
|
||||
if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
@@ -85,10 +81,10 @@ public class MovementFall extends Movement {
|
||||
if (targetRotation != null) {
|
||||
state.setTarget(new MovementTarget(targetRotation, true));
|
||||
} else {
|
||||
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false));
|
||||
state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
|
||||
}
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || BlockStateInterface.isWater(dest))) { // 0.094 because lilypads
|
||||
if (BlockStateInterface.isWater(dest)) {
|
||||
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || MovementHelper.isWater(dest))) { // 0.094 because lilypads
|
||||
if (MovementHelper.isWater(dest)) {
|
||||
if (InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
|
||||
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
|
||||
if (player().motionY >= 0) {
|
||||
@@ -105,8 +101,8 @@ public class MovementFall extends Movement {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
}
|
||||
Vec3d destCenter = Utils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder)
|
||||
if (Math.abs(player().posX - destCenter.x) > 0.2 || Math.abs(player().posZ - destCenter.z) > 0.2) {
|
||||
Vec3d destCenter = VecUtils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder)
|
||||
if (Math.abs(player().posX - destCenter.x) > 0.15 || Math.abs(player().posZ - destCenter.z) > 0.15) {
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
return state;
|
||||
|
||||
@@ -18,16 +18,21 @@
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.RayTraceUtils;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.behavior.LookBehaviorUtils;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockStairs;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -64,7 +69,7 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn)) {
|
||||
return;
|
||||
}
|
||||
int xDiff = dir.getXOffset();
|
||||
@@ -117,10 +122,10 @@ public class MovementParkour extends Movement {
|
||||
int destX = x + 4 * xDiff;
|
||||
int destZ = z + 4 * zDiff;
|
||||
IBlockState toPlace = BlockStateInterface.get(destX, y - 1, destZ);
|
||||
if (!context.hasThrowaway()) {
|
||||
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
|
||||
return;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
|
||||
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
@@ -168,13 +173,17 @@ public class MovementParkour extends Movement {
|
||||
// once this movement is instantiated, the state is default to PREPPING
|
||||
// but once it's ticked for the first time it changes to RUNNING
|
||||
// since we don't really know anything about momentum, it suffices to say Parkour can only be canceled on the 0th tick
|
||||
return state.getStatus() != MovementState.MovementStatus.RUNNING;
|
||||
return state.getStatus() != MovementStatus.RUNNING;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
if (player().isHandActive()) {
|
||||
logDebug("Pausing parkour since hand is active");
|
||||
return state;
|
||||
}
|
||||
if (dist >= 4) {
|
||||
@@ -186,15 +195,15 @@ public class MovementParkour extends Movement {
|
||||
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);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (player().posY - playerFeet().getY() < 0.094) { // lilypads
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
} else if (!playerFeet().equals(src)) {
|
||||
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
|
||||
|
||||
if (!MovementHelper.canWalkOn(dest.down())) {
|
||||
if (!MovementHelper.canWalkOn(dest.down()) && !player().onGround) {
|
||||
BlockPos positionToPlace = dest.down();
|
||||
for (int i = 0; i < 5; i++) {
|
||||
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
|
||||
@@ -203,17 +212,17 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + against1.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
Rotation place = Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
|
||||
Rotation place = RotationUtils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
|
||||
RayTraceResult res = RayTraceUtils.rayTraceTowards(place);
|
||||
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(dest.down())) {
|
||||
state.setTarget(new MovementState.MovementTarget(place, true));
|
||||
}
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
RayTraceUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(selectedBlock, against1) && selectedBlock.offset(side).equals(dest.down())) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
@@ -222,9 +231,17 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (dist == 3) { // this is a 2 block gap, dest = src + direction * 3
|
||||
double xDiff = (src.x + 0.5) - player().posX;
|
||||
double zDiff = (src.z + 0.5) - player().posZ;
|
||||
double distFromStart = Math.max(Math.abs(xDiff), Math.abs(zDiff));
|
||||
if (distFromStart < 0.7) {
|
||||
return state;
|
||||
}
|
||||
}
|
||||
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
} else if(!playerFeet().equals(dest.offset(direction, -1))) {
|
||||
} else if (!playerFeet().equals(dest.offset(direction, -1))) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, false);
|
||||
if (playerFeet().equals(src.offset(direction, -1))) {
|
||||
MovementHelper.moveTowards(state, src);
|
||||
|
||||
@@ -17,15 +17,17 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.VecUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -34,18 +36,11 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
public class MovementPillar extends Movement {
|
||||
private int numTicks = 0;
|
||||
|
||||
public MovementPillar(BetterBlockPos start, BetterBlockPos end) {
|
||||
super(start, end, new BetterBlockPos[]{start.up(2)}, start);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
return cost(context, src.x, src.y, src.z);
|
||||
@@ -59,16 +54,12 @@ public class MovementPillar extends Movement {
|
||||
if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (fromDownDown.getBlock() instanceof BlockSlab) {
|
||||
if (!((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
|
||||
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
|
||||
}
|
||||
if (fromDownDown.getBlock() instanceof BlockSlab && !((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
|
||||
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
|
||||
}
|
||||
}
|
||||
if (fromDown instanceof BlockVine) {
|
||||
if (!hasAgainst(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (fromDown instanceof BlockVine && !hasAgainst(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState toBreak = BlockStateInterface.get(x, y + 2, z);
|
||||
Block toBreakBlock = toBreak.getBlock();
|
||||
@@ -76,13 +67,13 @@ public class MovementPillar extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
Block srcUp = null;
|
||||
if (BlockStateInterface.isWater(toBreakBlock) && BlockStateInterface.isWater(fromDown)) {
|
||||
if (MovementHelper.isWater(toBreakBlock) && MovementHelper.isWater(fromDown)) {
|
||||
srcUp = BlockStateInterface.get(x, y + 1, z).getBlock();
|
||||
if (BlockStateInterface.isWater(srcUp)) {
|
||||
if (MovementHelper.isWater(srcUp)) {
|
||||
return LADDER_UP_ONE_COST;
|
||||
}
|
||||
}
|
||||
if (!context.hasThrowaway() && !ladder) {
|
||||
if (!ladder && !context.canPlaceThrowawayAt(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double hardness = MovementHelper.getMiningDurationTicks(context, x, y + 2, z, toBreak, true);
|
||||
@@ -148,29 +139,30 @@ public class MovementPillar extends Movement {
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
IBlockState fromDown = BlockStateInterface.get(src);
|
||||
if (BlockStateInterface.isWater(fromDown.getBlock()) && BlockStateInterface.isWater(dest)) {
|
||||
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(dest)) {
|
||||
// stay centered while swimming up a water column
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false));
|
||||
Vec3d destCenter = Utils.getBlockPosCenter(dest);
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
|
||||
Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
|
||||
if (Math.abs(player().posX - destCenter.x) > 0.2 || Math.abs(player().posZ - destCenter.z) > 0.2) {
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine;
|
||||
boolean vine = fromDown.getBlock() instanceof BlockVine;
|
||||
Rotation rotation = RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
VecUtils.getBlockPosCenter(positionToPlace),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch));
|
||||
if (!ladder) {
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(positionToPlace),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(mc.player.rotationYaw, rotation.getPitch()), true));
|
||||
}
|
||||
|
||||
boolean blockIsThere = MovementHelper.canWalkOn(src) || ladder;
|
||||
@@ -178,11 +170,11 @@ public class MovementPillar extends Movement {
|
||||
BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
if (against == null) {
|
||||
logDebug("Unable to climb vines");
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(src.down())) {
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
@@ -198,34 +190,35 @@ public class MovementPillar extends Movement {
|
||||
} else {
|
||||
// Get ready to place a throwaway block
|
||||
if (!MovementHelper.throwaway(true)) {
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
numTicks++;
|
||||
// If our Y coordinate is above our goal, stop jumping
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, player().posY < dest.getY());
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, player().posY > dest.getY()); // delay placement by 1 tick for ncp compatibility
|
||||
// since (lower down) we only right click once player.isSneaking, and that happens the tick after we request to sneak
|
||||
|
||||
// Otherwise jump
|
||||
if (numTicks > 20) {
|
||||
double diffX = player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = player().posZ - (dest.getZ() + 0.5);
|
||||
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
|
||||
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
|
||||
//and 0.17 is reasonably less than 0.2
|
||||
double diffX = player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = player().posZ - (dest.getZ() + 0.5);
|
||||
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
|
||||
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
|
||||
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
|
||||
//and 0.17 is reasonably less than 0.2
|
||||
|
||||
// If it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
// If it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
|
||||
// revise our target to both yaw and pitch if we're going to be moving forward
|
||||
state.setTarget(new MovementState.MovementTarget(rotation, true));
|
||||
}
|
||||
|
||||
|
||||
if (!blockIsThere) {
|
||||
Block fr = BlockStateInterface.get(src).getBlock();
|
||||
if (!(fr instanceof BlockAir || fr.isReplaceable(Minecraft.getMinecraft().world, src))) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
blockIsThere = false;
|
||||
} else if (Minecraft.getMinecraft().player.isSneaking()) {
|
||||
} else if (Minecraft.getMinecraft().player.isSneaking()) { // 1 tick after we're able to place
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
@@ -233,7 +226,7 @@ public class MovementPillar extends Movement {
|
||||
|
||||
// If we are at our goal and the block below us is placed
|
||||
if (playerFeet().equals(dest) && blockIsThere) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
return state;
|
||||
@@ -247,7 +240,7 @@ public class MovementPillar extends Movement {
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.isWater(dest.up())) {
|
||||
if (MovementHelper.isWater(dest.up())) {
|
||||
return true;
|
||||
}
|
||||
return super.prepared(state);
|
||||
|
||||
@@ -18,16 +18,14 @@
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.behavior.LookBehaviorUtils;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
@@ -68,7 +66,7 @@ public class MovementTraverse extends Movement {
|
||||
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())) {
|
||||
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
|
||||
WC = context.waterWalkSpeed();
|
||||
water = true;
|
||||
} else {
|
||||
@@ -103,18 +101,18 @@ public class MovementTraverse extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(destX, y - 1, destZ, destOn)) {
|
||||
boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock());
|
||||
if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) {
|
||||
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
|
||||
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!context.hasThrowaway()) {
|
||||
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb0, false);
|
||||
double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false);
|
||||
if (hardness1 >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb1, true);
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true);
|
||||
|
||||
double WC = throughWater ? context.waterWalkSpeed() : WALK_ONE_BLOCK_COST;
|
||||
for (int i = 0; i < 4; i++) {
|
||||
@@ -144,13 +142,13 @@ public class MovementTraverse extends Movement {
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
// if the setting is enabled
|
||||
if (!Baritone.settings().walkWhileBreaking.get()) {
|
||||
return state;
|
||||
}
|
||||
// and if we're prepping (aka mining the block in front)
|
||||
if (state.getStatus() != MovementState.MovementStatus.PREPPING) {
|
||||
if (state.getStatus() != MovementStatus.PREPPING) {
|
||||
return state;
|
||||
}
|
||||
// and if it's fine to walk into the blocks in front
|
||||
@@ -168,7 +166,7 @@ public class MovementTraverse extends Movement {
|
||||
|
||||
// combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break
|
||||
// it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw
|
||||
float yawToDest = Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(dest, world())).getYaw();
|
||||
float yawToDest = RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.calculateBlockCenter(dest)).getYaw();
|
||||
float pitchToBreak = state.getTarget().getRotation().get().getPitch();
|
||||
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true));
|
||||
@@ -191,11 +189,9 @@ public class MovementTraverse extends Movement {
|
||||
} else if (pb1.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(dest, src)) {
|
||||
isDoorActuallyBlockingUs = true;
|
||||
}
|
||||
if (isDoorActuallyBlockingUs) {
|
||||
if (!(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
|
||||
return state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(positionsToBreak[0], world())), true))
|
||||
.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
|
||||
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.calculateBlockCenter(positionsToBreak[0])), true))
|
||||
.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -208,7 +204,7 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
|
||||
if (blocked != null) {
|
||||
return state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.calcCenterFromCoords(blocked, world())), true))
|
||||
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.calculateBlockCenter(blocked)), true))
|
||||
.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
@@ -225,9 +221,9 @@ public class MovementTraverse extends Movement {
|
||||
|
||||
if (isTheBridgeBlockThere) {
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
|
||||
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
|
||||
@@ -248,7 +244,7 @@ public class MovementTraverse extends Movement {
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block
|
||||
logDebug("bb pls get me some blocks. dirt or cobble");
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
if (!Baritone.settings().assumeSafeWalk.get()) {
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
@@ -266,16 +262,13 @@ public class MovementTraverse extends Movement {
|
||||
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + against1.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.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() || Baritone.settings().assumeSafeWalk.get())) {
|
||||
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
// wrong side?
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), against1) && (Minecraft.getMinecraft().player.isSneaking() || Baritone.settings().assumeSafeWalk.get()) && RayTraceUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
System.out.println("Trying to look at " + against1 + ", actually looking at" + LookBehaviorUtils.getSelectedBlock());
|
||||
//System.out.println("Trying to look at " + against1 + ", actually looking at" + RayTraceUtils.getSelectedBlock());
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
}
|
||||
}
|
||||
@@ -287,7 +280,7 @@ public class MovementTraverse extends Movement {
|
||||
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
|
||||
if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block
|
||||
logDebug("bb pls get me some blocks. dirt or cobble");
|
||||
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D;
|
||||
@@ -295,18 +288,18 @@ public class MovementTraverse extends Movement {
|
||||
// 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
|
||||
|
||||
Rotation backToFace = Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
|
||||
Rotation backToFace = RotationUtils.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();
|
||||
float yaw = RotationUtils.calcRotationFromVec3d(VecUtils.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)) {
|
||||
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), goalLook)) {
|
||||
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true); // wait to right click until we are able to place
|
||||
}
|
||||
// Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt());
|
||||
@@ -324,7 +317,7 @@ public class MovementTraverse extends Movement {
|
||||
// if we're in the process of breaking blocks before walking forwards
|
||||
// or if this isn't a sneak place (the block is already there)
|
||||
// then it's safe to cancel this
|
||||
return state.getStatus() != MovementState.MovementStatus.RUNNING || MovementHelper.canWalkOn(dest.down());
|
||||
return state.getStatus() != MovementStatus.RUNNING || MovementHelper.canWalkOn(dest.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -1,138 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.path;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.Utils;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author leijurv
|
||||
*/
|
||||
public interface IPath extends Helper {
|
||||
|
||||
/**
|
||||
* Ordered list of movements to carry out.
|
||||
* movements.get(i).getSrc() should equal positions.get(i)
|
||||
* movements.get(i).getDest() should equal positions.get(i+1)
|
||||
* movements.size() should equal positions.size()-1
|
||||
*/
|
||||
List<Movement> movements();
|
||||
|
||||
/**
|
||||
* All positions along the way.
|
||||
* Should begin with the same as getSrc and end with the same as getDest
|
||||
*/
|
||||
List<BetterBlockPos> positions();
|
||||
|
||||
/**
|
||||
* This path is actually going to be executed in the world. Do whatever additional processing is required.
|
||||
* (as opposed to Path objects that are just constructed every frame for rendering)
|
||||
*/
|
||||
default void postprocess() {}
|
||||
|
||||
/**
|
||||
* Number of positions in this path
|
||||
*
|
||||
* @return Number of positions in this path
|
||||
*/
|
||||
default int length() {
|
||||
return positions().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* What goal was this path calculated towards?
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
Goal getGoal();
|
||||
|
||||
default Tuple<Double, BlockPos> closestPathPos() {
|
||||
double best = -1;
|
||||
BlockPos bestPos = null;
|
||||
for (BlockPos pos : positions()) {
|
||||
double dist = Utils.playerDistanceToCenter(pos);
|
||||
if (dist < best || best == -1) {
|
||||
best = dist;
|
||||
bestPos = pos;
|
||||
}
|
||||
}
|
||||
return new Tuple<>(best, bestPos);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where does this path start
|
||||
*/
|
||||
default BetterBlockPos getSrc() {
|
||||
return positions().get(0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Where does this path end
|
||||
*/
|
||||
default BetterBlockPos getDest() {
|
||||
List<BetterBlockPos> pos = positions();
|
||||
return pos.get(pos.size() - 1);
|
||||
}
|
||||
|
||||
default double ticksRemainingFrom(int pathPosition) {
|
||||
double sum = 0;
|
||||
//this is fast because we aren't requesting recalculation, it's just cached
|
||||
for (int i = pathPosition; i < movements().size(); i++) {
|
||||
sum += movements().get(i).getCost(null);
|
||||
}
|
||||
return sum;
|
||||
}
|
||||
|
||||
int getNumNodesConsidered();
|
||||
|
||||
default IPath cutoffAtLoadedChunks() {
|
||||
for (int i = 0; i < positions().size(); i++) {
|
||||
BlockPos pos = positions().get(i);
|
||||
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
|
||||
logDebug("Cutting off path at edge of loaded chunks");
|
||||
logDebug("Length decreased by " + (positions().size() - i - 1));
|
||||
return new CutoffPath(this, i);
|
||||
}
|
||||
}
|
||||
logDebug("Path ends within loaded chunks");
|
||||
return this;
|
||||
}
|
||||
|
||||
default IPath staticCutoff(Goal destination) {
|
||||
if (length() < Baritone.settings().pathCutoffMinimumLength.get()) {
|
||||
return this;
|
||||
}
|
||||
if (destination == null || destination.isInGoal(getDest())) {
|
||||
return this;
|
||||
}
|
||||
double factor = Baritone.settings().pathCutoffFactor.get();
|
||||
int newLength = (int) (length() * factor);
|
||||
logDebug("Static cutoff " + length() + " to " + newLength);
|
||||
return new CutoffPath(this, newLength);
|
||||
}
|
||||
}
|
||||
@@ -18,23 +18,28 @@
|
||||
package baritone.pathing.path;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.pathing.path.IPathExecutor;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.VecUtils;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
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.*;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import baritone.utils.BlockBreakHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
import static baritone.pathing.movement.MovementState.MovementStatus.*;
|
||||
import static baritone.api.pathing.movement.MovementStatus.*;
|
||||
|
||||
/**
|
||||
* Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching
|
||||
@@ -42,7 +47,7 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class PathExecutor implements Helper {
|
||||
public class PathExecutor implements IPathExecutor, Helper {
|
||||
private static final double MAX_MAX_DIST_FROM_PATH = 3;
|
||||
private static final double MAX_DIST_FROM_PATH = 2;
|
||||
|
||||
@@ -75,14 +80,10 @@ public class PathExecutor implements Helper {
|
||||
/**
|
||||
* Tick this executor
|
||||
*
|
||||
* @param event
|
||||
* @return True if a movement just finished (and the player is therefore in a "stable" state, like,
|
||||
* not sneaking out over lava), false otherwise
|
||||
*/
|
||||
public boolean onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
public boolean onTick() {
|
||||
if (pathPosition == path.length() - 1) {
|
||||
pathPosition++;
|
||||
}
|
||||
@@ -120,7 +121,7 @@ public class PathExecutor implements Helper {
|
||||
if (i - pathPosition > 2) {
|
||||
logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i);
|
||||
}
|
||||
System.out.println("Double skip sundae");
|
||||
//System.out.println("Double skip sundae");
|
||||
pathPosition = i - 1;
|
||||
onChangeInPathPosition();
|
||||
return false;
|
||||
@@ -128,7 +129,7 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
Tuple<Double, BlockPos> status = path.closestPathPos();
|
||||
Tuple<Double, BlockPos> status = closestPathPos(path);
|
||||
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
|
||||
ticksAway++;
|
||||
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH);
|
||||
@@ -182,13 +183,11 @@ public class PathExecutor implements Helper {
|
||||
if (i < 0 || i >= path.movements().size()) {
|
||||
continue;
|
||||
}
|
||||
Movement m = path.movements().get(i);
|
||||
IMovement m = path.movements().get(i);
|
||||
HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak());
|
||||
HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace());
|
||||
HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto());
|
||||
m.toBreakCached = null;
|
||||
m.toPlaceCached = null;
|
||||
m.toWalkIntoCached = null;
|
||||
m.resetBlockCache();
|
||||
if (!prevBreak.equals(new HashSet<>(m.toBreak()))) {
|
||||
recalcBP = true;
|
||||
}
|
||||
@@ -217,12 +216,12 @@ public class PathExecutor implements Helper {
|
||||
if (end - start > 0) {
|
||||
System.out.println("Recalculating break and place took " + (end - start) + "ms");
|
||||
}*/
|
||||
Movement movement = path.movements().get(pathPosition);
|
||||
IMovement 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);
|
||||
currentMovementOriginalCostEstimate = movement.getCost();
|
||||
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 && canCancel) {
|
||||
logDebug("Something has changed in the world and a future movement has become impossible. Cancelling.");
|
||||
@@ -244,9 +243,10 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
if (shouldPause()) {
|
||||
logDebug("Pausing since current best path is a backtrack");
|
||||
clearKeys();
|
||||
return true;
|
||||
}
|
||||
MovementState.MovementStatus movementStatus = movement.update();
|
||||
MovementStatus movementStatus = movement.update();
|
||||
if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
|
||||
logDebug("Movement returns status " + movementStatus);
|
||||
cancel();
|
||||
@@ -256,7 +256,7 @@ public class PathExecutor implements Helper {
|
||||
//System.out.println("Movement done, next path");
|
||||
pathPosition++;
|
||||
onChangeInPathPosition();
|
||||
onTick(event);
|
||||
onTick();
|
||||
return true;
|
||||
} else {
|
||||
sprintIfRequested();
|
||||
@@ -271,7 +271,20 @@ public class PathExecutor implements Helper {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false; // movement is in progress
|
||||
return canCancel; // movement is in progress, but if it reports cancellable, PathingBehavior is good to cut onto the next path
|
||||
}
|
||||
|
||||
private Tuple<Double, BlockPos> closestPathPos(IPath path) {
|
||||
double best = -1;
|
||||
BlockPos bestPos = null;
|
||||
for (BlockPos pos : path.positions()) {
|
||||
double dist = VecUtils.entityDistanceToCenter(player(), pos);
|
||||
if (dist < best || best == -1) {
|
||||
best = dist;
|
||||
bestPos = pos;
|
||||
}
|
||||
}
|
||||
return new Tuple<>(best, bestPos);
|
||||
}
|
||||
|
||||
private boolean shouldPause() {
|
||||
@@ -313,10 +326,7 @@ public class PathExecutor implements Helper {
|
||||
// when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path
|
||||
if (path.movements().get(pathPosition) instanceof MovementFall) {
|
||||
BlockPos fallDest = path.positions().get(pathPosition + 1); // .get(pathPosition) is the block we fell off of
|
||||
if (Utils.playerFlatDistanceToCenter(fallDest) < leniency) { // ignore Y by using flat distance
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return VecUtils.entityFlatDistanceToCenter(player(), fallDest) >= leniency; // ignore Y by using flat distance
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
@@ -325,11 +335,24 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Regardless of current path position, snap to the current player feet if possible
|
||||
*/
|
||||
public boolean snipsnapifpossible() {
|
||||
int index = path.positions().indexOf(playerFeet());
|
||||
if (index == -1) {
|
||||
return false;
|
||||
}
|
||||
pathPosition = index;
|
||||
clearKeys();
|
||||
return true;
|
||||
}
|
||||
|
||||
private void sprintIfRequested() {
|
||||
|
||||
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
|
||||
if (!new CalculationContext().canSprint()) {
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT,false);
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT, false);
|
||||
player().setSprinting(false);
|
||||
return;
|
||||
}
|
||||
@@ -343,10 +366,10 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
|
||||
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT,false);
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT, false);
|
||||
|
||||
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
|
||||
Movement current = path.movements().get(pathPosition);
|
||||
IMovement current = path.movements().get(pathPosition);
|
||||
if (current instanceof MovementDescend && pathPosition < path.length() - 2) {
|
||||
|
||||
// (dest - src) + dest is offset 1 more in the same direction
|
||||
@@ -361,7 +384,7 @@ public class PathExecutor implements Helper {
|
||||
}
|
||||
}
|
||||
|
||||
Movement next = path.movements().get(pathPosition + 1);
|
||||
IMovement 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()) {
|
||||
@@ -385,7 +408,7 @@ 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);
|
||||
IMovement 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
|
||||
@@ -400,21 +423,14 @@ public class PathExecutor implements Helper {
|
||||
player().setSprinting(false);
|
||||
}
|
||||
|
||||
private static boolean canSprintInto(Movement current, Movement next) {
|
||||
if (next instanceof MovementDescend) {
|
||||
if (next.getDirection().equals(current.getDirection())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementTraverse) {
|
||||
if (next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) {
|
||||
private static boolean canSprintInto(IMovement current, IMovement next) {
|
||||
if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
|
||||
return true;
|
||||
}
|
||||
return next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get();
|
||||
}
|
||||
|
||||
private void onChangeInPathPosition() {
|
||||
@@ -438,6 +454,7 @@ public class PathExecutor implements Helper {
|
||||
return pathPosition;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IPath getPath() {
|
||||
return path;
|
||||
}
|
||||
|
||||
@@ -17,11 +17,11 @@
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
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;
|
||||
@@ -35,8 +35,6 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
|
||||
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(0, 65, 0);
|
||||
@@ -107,8 +105,8 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
}
|
||||
|
||||
// Setup Baritone's pathing goal and (if needed) begin pathing
|
||||
PathingBehavior.INSTANCE.setGoal(GOAL);
|
||||
PathingBehavior.INSTANCE.path();
|
||||
Baritone.INSTANCE.getPathingBehavior().setGoal(GOAL);
|
||||
Baritone.INSTANCE.getPathingBehavior().path();
|
||||
|
||||
// If we have reached our goal, print a message and safely close the game
|
||||
if (GOAL.isInGoal(playerFeet())) {
|
||||
@@ -123,4 +121,6 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private BaritoneAutoTest() {}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,6 @@ import baritone.cache.CachedRegion;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.cache.WorldProvider;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -38,7 +37,7 @@ public class BlockStateInterface implements Helper {
|
||||
private static Chunk prev = null;
|
||||
private static CachedRegion prevCached = null;
|
||||
|
||||
private static IBlockState AIR = Blocks.AIR.getDefaultState();
|
||||
private static final IBlockState AIR = Blocks.AIR.getDefaultState();
|
||||
|
||||
public static IBlockState get(BlockPos pos) {
|
||||
return get(pos.getX(), pos.getY(), pos.getZ());
|
||||
@@ -128,47 +127,4 @@ public class BlockStateInterface implements Helper {
|
||||
public static Block getBlock(int x, int y, int z) {
|
||||
return get(x, y, z).getBlock();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified block is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param b The block
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
public static boolean isWater(Block b) {
|
||||
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the block at the specified pos is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param bp The block pos
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
public static boolean isWater(BlockPos bp) {
|
||||
return isWater(BlockStateInterface.getBlock(bp));
|
||||
}
|
||||
|
||||
public static boolean isLava(Block b) {
|
||||
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified pos has a liquid
|
||||
*
|
||||
* @param p The pos
|
||||
* @return Whether or not the block is a liquid
|
||||
*/
|
||||
public static boolean isLiquid(BlockPos p) {
|
||||
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
public static boolean isFlowing(IBlockState state) {
|
||||
// Will be IFluidState in 1.13
|
||||
return state.getBlock() instanceof BlockLiquid
|
||||
&& state.getPropertyKeys().contains(BlockLiquid.LEVEL)
|
||||
&& state.getValue(BlockLiquid.LEVEL) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,18 +23,15 @@ import baritone.api.cache.IWaypoint;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.api.pathing.goals.*;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.utils.RayTraceUtils;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.FollowBehavior;
|
||||
import baritone.behavior.MineBehavior;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
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;
|
||||
@@ -49,47 +46,83 @@ import java.util.stream.Stream;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
|
||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||
public static ExampleBaritoneControl INSTANCE; // compatibility with impact 4.4
|
||||
|
||||
private ExampleBaritoneControl() {
|
||||
private static final String HELP_MSG =
|
||||
"baritone - Output settings into chat\n" +
|
||||
"settings - Same as baritone\n" +
|
||||
"goal - Create a goal (one number is '<Y>', two is '<X> <Z>', three is '<X> <Y> <Z>, 'clear' to clear)\n" +
|
||||
"path - Go towards goal\n" +
|
||||
"repack - (debug) Repacks chunk cache\n" +
|
||||
"rescan - (debug) Same as repack\n" +
|
||||
"axis - Paths towards the closest axis or diagonal axis, at y=120\n" +
|
||||
"cancel - Cancels current path\n" +
|
||||
"forcecancel - sudo cancel (only use if very glitched, try toggling 'pause' first)\n" +
|
||||
"gc - Calls System.gc();\n" +
|
||||
"invert - Runs away from the goal instead of towards it\n" +
|
||||
"follow - Follows a player 'follow username'\n" +
|
||||
"reloadall - (debug) Reloads chunk cache\n" +
|
||||
"saveall - (debug) Saves chunk cache\n" +
|
||||
"find - (debug) outputs how many blocks of a certain type are within the cache\n" +
|
||||
"mine - Paths to and mines specified blocks 'mine x_ore y_ore ...'\n" +
|
||||
"thisway - Creates a goal X blocks where you're facing\n" +
|
||||
"list - Lists waypoints under a category\n" +
|
||||
"get - Same as list\n" +
|
||||
"show - Same as list\n" +
|
||||
"save - Saves a waypoint (works but don't try to make sense of it)\n" +
|
||||
"goto - Paths towards specified block or waypoint\n" +
|
||||
"spawn - Paths towards world spawn or your most recent bed right-click\n" +
|
||||
"sethome - Sets \"home\"\n" +
|
||||
"home - Paths towards \"home\" \n" +
|
||||
"costs - (debug) all movement costs from current location\n" +
|
||||
"pause - Toggle pause\n" +
|
||||
"damn - Daniel ";
|
||||
|
||||
}
|
||||
|
||||
public void initAndRegister() {
|
||||
Baritone.INSTANCE.registerBehavior(this);
|
||||
public ExampleBaritoneControl(Baritone baritone) {
|
||||
super(baritone);
|
||||
INSTANCE = this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
if (!Baritone.settings().chatControl.get()) {
|
||||
if (!Baritone.settings().removePrefix.get()) {
|
||||
return;
|
||||
}
|
||||
if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) {
|
||||
return;
|
||||
}
|
||||
String msg = event.getMessage().toLowerCase(Locale.US);
|
||||
String msg = event.getMessage();
|
||||
if (Baritone.settings().prefix.get()) {
|
||||
if (!msg.startsWith("#")) {
|
||||
return;
|
||||
}
|
||||
msg = msg.substring(1);
|
||||
}
|
||||
if (runCommand(msg)) {
|
||||
event.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
public boolean runCommand(String msg0) {
|
||||
String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL
|
||||
PathingBehavior pathingBehavior = baritone.getPathingBehavior();
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getAllValuesByType(Boolean.class);
|
||||
for (Settings.Setting<Boolean> setting : toggleable) {
|
||||
if (msg.equalsIgnoreCase(setting.getName())) {
|
||||
setting.value ^= true;
|
||||
event.cancel();
|
||||
logDirect("Toggled " + setting.getName() + " to " + setting.value);
|
||||
SettingsUtil.save(Baritone.settings());
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (msg.equals("baritone") || msg.equals("settings")) {
|
||||
for (Settings.Setting<?> setting : Baritone.settings().allSettings) {
|
||||
logDirect(setting.toString());
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("") || msg.equals("help") || msg.equals("?")) {
|
||||
for (String line : HELP_MSG.split("\n")) {
|
||||
logDirect(line);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
if (msg.contains(" ")) {
|
||||
String[] data = msg.split(" ");
|
||||
@@ -111,25 +144,21 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
} catch (NumberFormatException e) {
|
||||
logDirect("Unable to parse " + data[1]);
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
SettingsUtil.save(Baritone.settings());
|
||||
logDirect(setting.toString());
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (Baritone.settings().byLowerName.containsKey(msg)) {
|
||||
Settings.Setting<?> setting = Baritone.settings().byLowerName.get(msg);
|
||||
logDirect(setting.toString());
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
if (msg.startsWith("goal")) {
|
||||
event.cancel();
|
||||
String[] params = msg.substring(4).trim().split(" ");
|
||||
if (params[0].equals("")) {
|
||||
params = new String[]{};
|
||||
@@ -155,30 +184,29 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
break;
|
||||
default:
|
||||
logDirect("unable to understand lol");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
logDirect("unable to parse integer " + ex);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
pathingBehavior.setGoal(goal);
|
||||
logDirect("Goal: " + goal);
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("path")) {
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
if (PathingBehavior.INSTANCE.getGoal() == null) {
|
||||
if (!pathingBehavior.path()) {
|
||||
if (pathingBehavior.getGoal() == null) {
|
||||
logDirect("No goal.");
|
||||
} else {
|
||||
if (PathingBehavior.INSTANCE.getGoal().isInGoal(playerFeet())) {
|
||||
if (pathingBehavior.getGoal().isInGoal(playerFeet())) {
|
||||
logDirect("Already in goal");
|
||||
} else {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
}
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("repack") || msg.equals("rescan")) {
|
||||
ChunkProviderClient cli = world().getChunkProvider();
|
||||
@@ -195,41 +223,36 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
}
|
||||
}
|
||||
logDirect("Queued " + count + " chunks for repacking");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("axis")) {
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalAxis());
|
||||
PathingBehavior.INSTANCE.path();
|
||||
event.cancel();
|
||||
return;
|
||||
pathingBehavior.setGoal(new GoalAxis());
|
||||
pathingBehavior.path();
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("cancel") || msg.equals("stop")) {
|
||||
MineBehavior.INSTANCE.cancel();
|
||||
FollowBehavior.INSTANCE.cancel();
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
event.cancel();
|
||||
baritone.getMineBehavior().cancel();
|
||||
baritone.getFollowBehavior().cancel();
|
||||
pathingBehavior.cancel();
|
||||
logDirect("ok canceled");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("forcecancel")) {
|
||||
MineBehavior.INSTANCE.cancel();
|
||||
FollowBehavior.INSTANCE.cancel();
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
baritone.getMineBehavior().cancel();
|
||||
baritone.getFollowBehavior().cancel();
|
||||
pathingBehavior.cancel();
|
||||
AbstractNodeCostSearch.forceCancel();
|
||||
PathingBehavior.INSTANCE.forceCancel();
|
||||
event.cancel();
|
||||
pathingBehavior.forceCancel();
|
||||
logDirect("ok force canceled");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("gc")) {
|
||||
System.gc();
|
||||
event.cancel();
|
||||
logDirect("Called System.gc();");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("invert")) {
|
||||
Goal goal = PathingBehavior.INSTANCE.getGoal();
|
||||
Goal goal = pathingBehavior.getGoal();
|
||||
BlockPos runAwayFrom;
|
||||
if (goal instanceof GoalXZ) {
|
||||
runAwayFrom = new BlockPos(((GoalXZ) goal).getX(), 0, ((GoalXZ) goal).getZ());
|
||||
@@ -240,54 +263,47 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("Inverting goal of player feet");
|
||||
runAwayFrom = playerFeet();
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalRunAway(1, runAwayFrom) {
|
||||
pathingBehavior.setGoal(new GoalRunAway(1, runAwayFrom) {
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
if (!pathingBehavior.path()) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("follow")) {
|
||||
String name = msg.substring(6).trim();
|
||||
Optional<Entity> toFollow = Optional.empty();
|
||||
if (name.length() == 0) {
|
||||
toFollow = MovementHelper.whatEntityAmILookingAt();
|
||||
toFollow = RayTraceUtils.getSelectedEntity();
|
||||
} else {
|
||||
for (EntityPlayer pl : world().playerEntities) {
|
||||
String theirName = pl.getName().trim().toLowerCase();
|
||||
if (!theirName.equals(player().getName().trim().toLowerCase())) { // don't follow ourselves lol
|
||||
if (theirName.contains(name) || name.contains(theirName)) {
|
||||
toFollow = Optional.of(pl);
|
||||
}
|
||||
if (!theirName.equals(player().getName().trim().toLowerCase()) && (theirName.contains(name) || name.contains(theirName))) { // don't follow ourselves lol
|
||||
toFollow = Optional.of(pl);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!toFollow.isPresent()) {
|
||||
logDirect("Not found");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
FollowBehavior.INSTANCE.follow(toFollow.get());
|
||||
baritone.getFollowBehavior().follow(toFollow.get());
|
||||
logDirect("Following " + toFollow.get());
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("reloadall")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().reloadAllFromDisk();
|
||||
logDirect("ok");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("saveall")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().save();
|
||||
logDirect("ok");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("find")) {
|
||||
String blockType = msg.substring(4).trim();
|
||||
@@ -299,8 +315,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
System.out.println("Was looking for " + blockType + " but actually found " + actually + " " + ChunkPacker.blockToString(actually));
|
||||
}
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("mine")) {
|
||||
String[] blockTypes = msg.substring(4).trim().split(" ");
|
||||
@@ -308,34 +323,30 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
int quantity = Integer.parseInt(blockTypes[1]);
|
||||
Block block = ChunkPacker.stringToBlock(blockTypes[0]);
|
||||
Objects.requireNonNull(block);
|
||||
MineBehavior.INSTANCE.mine(quantity, block);
|
||||
baritone.getMineBehavior().mine(quantity, block);
|
||||
logDirect("Will mine " + quantity + " " + blockTypes[0]);
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
} catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {}
|
||||
for (String s : blockTypes) {
|
||||
if (ChunkPacker.stringToBlock(s) == null) {
|
||||
logDirect(s + " isn't a valid block name");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
|
||||
}
|
||||
MineBehavior.INSTANCE.mine(0, blockTypes);
|
||||
baritone.getMineBehavior().mine(0, blockTypes);
|
||||
logDirect("Started mining blocks of type " + Arrays.toString(blockTypes));
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("thisway")) {
|
||||
try {
|
||||
Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
pathingBehavior.setGoal(goal);
|
||||
logDirect("Goal: " + goal);
|
||||
} catch (NumberFormatException ex) {
|
||||
logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double.");
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("list") || msg.startsWith("get ") || msg.startsWith("show")) {
|
||||
String waypointType = msg.substring(4).trim();
|
||||
@@ -346,8 +357,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
|
||||
if (tag == null) {
|
||||
logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
Set<IWaypoint> waypoints = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getByTag(tag);
|
||||
// might as well show them from oldest to newest
|
||||
@@ -357,11 +367,9 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
for (IWaypoint waypoint : sorted) {
|
||||
logDirect(waypoint.toString());
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("save")) {
|
||||
event.cancel();
|
||||
String name = msg.substring(4).trim();
|
||||
BlockPos pos = playerFeet();
|
||||
if (name.contains(" ")) {
|
||||
@@ -369,19 +377,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
String[] parts = name.split(" ");
|
||||
if (parts.length != 4) {
|
||||
logDirect("Unable to parse, expected four things");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
try {
|
||||
pos = new BlockPos(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
|
||||
} catch (NumberFormatException ex) {
|
||||
logDirect("Unable to parse coordinate integers");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
name = parts[0];
|
||||
}
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, Waypoint.Tag.USER, pos));
|
||||
logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto user' to set goal, say 'list user' to list.");
|
||||
return;
|
||||
logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto " + name + "' to set goal, say 'list user' to list custom waypoints.");
|
||||
return true;
|
||||
}
|
||||
if (msg.startsWith("goto")) {
|
||||
String waypointType = msg.substring(4).trim();
|
||||
@@ -395,40 +403,35 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
String mining = waypointType;
|
||||
Block block = ChunkPacker.stringToBlock(mining);
|
||||
//logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
event.cancel();
|
||||
if (block == null) {
|
||||
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
|
||||
if (waypoint == null) {
|
||||
logDirect("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
List<BlockPos> locs = MineBehavior.INSTANCE.scanFor(Collections.singletonList(block), 64);
|
||||
List<BlockPos> locs = baritone.getMineBehavior().searchWorld(Collections.singletonList(block), 64, world());
|
||||
if (locs.isEmpty()) {
|
||||
logDirect("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
return;
|
||||
pathingBehavior.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||
pathingBehavior.path();
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(tag);
|
||||
if (waypoint == null) {
|
||||
logDirect("None saved for tag " + tag);
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
if (!PathingBehavior.INSTANCE.path()) {
|
||||
if (!goal.isInGoal(playerFeet())) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
pathingBehavior.setGoal(goal);
|
||||
if (!pathingBehavior.path() && !goal.isInGoal(playerFeet())) {
|
||||
logDirect("Currently executing a path. Please cancel it first.");
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("spawn") || msg.equals("bed")) {
|
||||
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.BED);
|
||||
@@ -437,20 +440,18 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
// for some reason the default spawnpoint is underground sometimes
|
||||
Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ());
|
||||
logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal);
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
pathingBehavior.setGoal(goal);
|
||||
} else {
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
pathingBehavior.setGoal(goal);
|
||||
logDirect("Set goal to most recent bed " + goal);
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("sethome")) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet()));
|
||||
logDirect("Saved. Say home to set goal.");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("home")) {
|
||||
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.HOME);
|
||||
@@ -458,40 +459,37 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
logDirect("home not saved");
|
||||
} else {
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
PathingBehavior.INSTANCE.path();
|
||||
pathingBehavior.setGoal(goal);
|
||||
pathingBehavior.path();
|
||||
logDirect("Going to saved home " + goal);
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("costs")) {
|
||||
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(playerFeet())).collect(Collectors.toCollection(ArrayList::new));
|
||||
while (moves.contains(null)) {
|
||||
moves.remove(null);
|
||||
}
|
||||
moves.sort(Comparator.comparingDouble(movement -> movement.getCost(new CalculationContext())));
|
||||
moves.sort(Comparator.comparingDouble(Movement::getCost));
|
||||
for (Movement move : moves) {
|
||||
String[] parts = move.getClass().toString().split("\\.");
|
||||
double cost = move.getCost(new CalculationContext());
|
||||
double cost = move.getCost();
|
||||
String strCost = cost + "";
|
||||
if (cost >= ActionCosts.COST_INF) {
|
||||
strCost = "IMPOSSIBLE";
|
||||
}
|
||||
logDirect(parts[parts.length - 1] + " " + move.getDest().getX() + "," + move.getDest().getY() + "," + move.getDest().getZ() + " " + strCost);
|
||||
}
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("pause")) {
|
||||
boolean enabled = PathingBehavior.INSTANCE.toggle();
|
||||
boolean enabled = pathingBehavior.toggle();
|
||||
logDirect("Pathing Behavior has " + (enabled ? "resumed" : "paused") + ".");
|
||||
event.cancel();
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
if (msg.equals("damn")) {
|
||||
logDirect("daniel");
|
||||
return;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,8 +18,8 @@
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.BlockSlab;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -86,8 +86,8 @@ public interface Helper {
|
||||
*/
|
||||
default void logDebug(String message) {
|
||||
if (!Baritone.settings().chatDebug.get()) {
|
||||
System.out.println("Suppressed debug message:");
|
||||
System.out.println(message);
|
||||
//System.out.println("Suppressed debug message:");
|
||||
//System.out.println(message);
|
||||
return;
|
||||
}
|
||||
logDirect(message);
|
||||
|
||||
@@ -19,16 +19,16 @@ package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.pathing.calc.IPath;
|
||||
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.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.pathing.BetterBlockPos;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
@@ -67,12 +67,13 @@ public final class PathRenderer implements Helper {
|
||||
Goal goal = behavior.getGoal();
|
||||
EntityPlayerSP player = mc.player;
|
||||
if (goal != null && Baritone.settings().renderGoal.value) {
|
||||
PathRenderer.drawLitDankGoalBox(player, goal, partialTicks, Baritone.settings().colorGoalBox.get());
|
||||
drawLitDankGoalBox(player, goal, partialTicks, Baritone.settings().colorGoalBox.get());
|
||||
}
|
||||
if (!Baritone.settings().renderPath.get()) {
|
||||
return;
|
||||
}
|
||||
|
||||
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
|
||||
//long start = System.nanoTime();
|
||||
|
||||
|
||||
@@ -84,28 +85,28 @@ public final class PathRenderer implements Helper {
|
||||
// Render the current path, if there is one
|
||||
if (current != null && current.getPath() != null) {
|
||||
int renderBegin = Math.max(current.getPosition() - 3, 0);
|
||||
PathRenderer.drawPath(current.getPath(), renderBegin, player, partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
drawPath(current.getPath(), renderBegin, player, partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
if (next != null && next.getPath() != null) {
|
||||
PathRenderer.drawPath(next.getPath(), 0, player, partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
drawPath(next.getPath(), 0, player, partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
|
||||
//long split = System.nanoTime();
|
||||
if (current != null) {
|
||||
PathRenderer.drawManySelectionBoxes(player, current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get());
|
||||
PathRenderer.drawManySelectionBoxes(player, current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get());
|
||||
PathRenderer.drawManySelectionBoxes(player, current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get());
|
||||
drawManySelectionBoxes(player, current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get());
|
||||
drawManySelectionBoxes(player, current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get());
|
||||
drawManySelectionBoxes(player, current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get());
|
||||
}
|
||||
|
||||
// If there is a path calculation currently running, render the path calculation process
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> {
|
||||
currentlyRunning.bestPathSoFar().ifPresent(p -> {
|
||||
PathRenderer.drawPath(p, 0, player, partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
drawPath(p, 0, player, partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
});
|
||||
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());
|
||||
drawPath(mr, 0, player, partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
|
||||
drawManySelectionBoxes(player, Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
|
||||
});
|
||||
});
|
||||
//long end = System.nanoTime();
|
||||
@@ -122,6 +123,9 @@ public final class PathRenderer implements Helper {
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
if (Baritone.settings().renderPathIgnoreDepth.get()) {
|
||||
GlStateManager.disableDepth();
|
||||
}
|
||||
List<BetterBlockPos> positions = path.positions();
|
||||
int next;
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
@@ -162,6 +166,9 @@ public final class PathRenderer implements Helper {
|
||||
drawLine(player, x1, y1, z1, x2, y2, z2, partialTicks);
|
||||
tessellator.draw();
|
||||
}
|
||||
if (Baritone.settings().renderPathIgnoreDepth.get()) {
|
||||
GlStateManager.enableDepth();
|
||||
}
|
||||
//GlStateManager.color(0.0f, 0.0f, 0.0f, 0.4f);
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableTexture2D();
|
||||
@@ -187,6 +194,11 @@ public final class PathRenderer implements Helper {
|
||||
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
|
||||
GlStateManager.disableTexture2D();
|
||||
GlStateManager.depthMask(false);
|
||||
|
||||
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
|
||||
GlStateManager.disableDepth();
|
||||
}
|
||||
|
||||
float expand = 0.002F;
|
||||
//BlockPos blockpos = movingObjectPositionIn.getBlockPos();
|
||||
|
||||
@@ -228,6 +240,10 @@ public final class PathRenderer implements Helper {
|
||||
TESSELLATOR.draw();
|
||||
});
|
||||
|
||||
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
|
||||
GlStateManager.enableDepth();
|
||||
}
|
||||
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.disableBlend();
|
||||
|
||||
@@ -23,41 +23,41 @@ import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.init.Enchantments;
|
||||
import net.minecraft.init.MobEffects;
|
||||
import net.minecraft.item.Item.ToolMaterial;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemTool;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A cached list of the best tools on the hotbar for any block
|
||||
*
|
||||
* @author avecowa, Brady, leijurv
|
||||
* @author Avery, Brady, leijurv
|
||||
*/
|
||||
public class ToolSet implements Helper {
|
||||
|
||||
/**
|
||||
* A cache mapping a {@link Block} to how long it will take to break
|
||||
* with this toolset, given the optimum tool is used.
|
||||
*/
|
||||
private Map<Block, Double> breakStrengthCache = new HashMap<>();
|
||||
private final Map<Block, Double> breakStrengthCache;
|
||||
|
||||
/**
|
||||
* Calculate which tool on the hotbar is best for mining
|
||||
*
|
||||
* @param b the blockstate to be mined
|
||||
* @return a byte indicating the index in the tools array that worked best
|
||||
* My buddy leijurv owned me so we have this to not create a new lambda instance.
|
||||
*/
|
||||
public byte getBestSlot(IBlockState b) {
|
||||
byte best = 0;
|
||||
double value = -1;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
double v = calculateStrVsBlock(i, b);
|
||||
if (v > value || value == -1) {
|
||||
value = v;
|
||||
best = i;
|
||||
}
|
||||
private final Function<Block, Double> backendCalculation;
|
||||
|
||||
public ToolSet() {
|
||||
breakStrengthCache = new HashMap<>();
|
||||
|
||||
if (Baritone.settings().considerPotionEffects.get()) {
|
||||
double amplifier = potionAmplifier();
|
||||
Function<Double, Double> amplify = x -> amplifier * x;
|
||||
backendCalculation = amplify.compose(this::getBestDestructionTime);
|
||||
} else {
|
||||
backendCalculation = this::getBestDestructionTime;
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -67,14 +67,64 @@ public class ToolSet implements Helper {
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public double getStrVsBlock(IBlockState state) {
|
||||
Double strength = this.breakStrengthCache.get(state.getBlock());
|
||||
if (strength != null) {
|
||||
// the function will take this path >99% of the time
|
||||
return strength;
|
||||
return breakStrengthCache.computeIfAbsent(state.getBlock(), backendCalculation);
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the material cost of a possible tool. The priority matches the
|
||||
* listed order in the Item.ToolMaterial enum.
|
||||
*
|
||||
* @param itemStack a possibly empty ItemStack
|
||||
* @return values range from -1 to 4
|
||||
*/
|
||||
private int getMaterialCost(ItemStack itemStack) {
|
||||
if (itemStack.getItem() instanceof ItemTool) {
|
||||
ItemTool tool = (ItemTool) itemStack.getItem();
|
||||
return ToolMaterial.valueOf(tool.getToolMaterialName()).ordinal();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
double str = calculateStrVsBlock(getBestSlot(state), state);
|
||||
this.breakStrengthCache.put(state.getBlock(), str);
|
||||
return str;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate which tool on the hotbar is best for mining
|
||||
*
|
||||
* @param b the blockstate to be mined
|
||||
* @return A byte containing the index in the tools array that worked best
|
||||
*/
|
||||
public byte getBestSlot(Block b) {
|
||||
byte best = 0;
|
||||
double value = Double.NEGATIVE_INFINITY;
|
||||
int materialCost = Integer.MIN_VALUE;
|
||||
IBlockState blockState = b.getDefaultState();
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack itemStack = player().inventory.getStackInSlot(i);
|
||||
double v = calculateStrVsBlock(itemStack, blockState);
|
||||
if (v > value) {
|
||||
value = v;
|
||||
best = i;
|
||||
materialCost = getMaterialCost(itemStack);
|
||||
} else if (v == value) {
|
||||
int c = getMaterialCost(itemStack);
|
||||
if (c < materialCost) {
|
||||
value = v;
|
||||
best = i;
|
||||
materialCost = c;
|
||||
}
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate how effectively a block can be destroyed
|
||||
*
|
||||
* @param b the blockstate to be mined
|
||||
* @return A double containing the destruction ticks with the best tool
|
||||
*/
|
||||
private double getBestDestructionTime(Block b) {
|
||||
ItemStack stack = player().inventory.getStackInSlot(getBestSlot(b));
|
||||
return calculateStrVsBlock(stack, b.getDefaultState());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -84,49 +134,55 @@ public class ToolSet implements Helper {
|
||||
* @param state the blockstate to be mined
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
private double calculateStrVsBlock(byte slot, IBlockState state) {
|
||||
// Calculate the slot with the best item
|
||||
ItemStack contents = player().inventory.getStackInSlot(slot);
|
||||
|
||||
float blockHard = state.getBlockHardness(null, null);
|
||||
if (blockHard < 0) {
|
||||
private double calculateStrVsBlock(ItemStack item, IBlockState state) {
|
||||
float hardness = state.getBlockHardness(null, null);
|
||||
if (hardness < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float speed = contents.getDestroySpeed(state);
|
||||
float speed = item.getDestroySpeed(state);
|
||||
if (speed > 1) {
|
||||
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents);
|
||||
if (effLevel > 0 && !contents.isEmpty()) {
|
||||
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, item);
|
||||
if (effLevel > 0 && !item.isEmpty()) {
|
||||
speed += effLevel * effLevel + 1;
|
||||
}
|
||||
}
|
||||
|
||||
if (Baritone.settings().considerPotionEffects.get()) {
|
||||
if (player().isPotionActive(MobEffects.HASTE)) {
|
||||
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||
}
|
||||
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
|
||||
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
|
||||
case 0:
|
||||
speed *= 0.3;
|
||||
break;
|
||||
case 1:
|
||||
speed *= 0.09;
|
||||
break;
|
||||
case 2:
|
||||
speed *= 0.0027;
|
||||
break;
|
||||
default:
|
||||
speed *= 0.00081;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
speed /= blockHard;
|
||||
if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) {
|
||||
return speed / 30;
|
||||
speed /= hardness;
|
||||
if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) {
|
||||
speed /= 30;
|
||||
} else {
|
||||
return speed / 100;
|
||||
speed /= 100;
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates any modifier to breaking time based on status effects.
|
||||
*
|
||||
* @return a double to scale block breaking speed.
|
||||
*/
|
||||
private double potionAmplifier() {
|
||||
double speed = 1;
|
||||
if (player().isPotionActive(MobEffects.HASTE)) {
|
||||
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
|
||||
}
|
||||
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
|
||||
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
|
||||
case 0:
|
||||
speed *= 0.3;
|
||||
break;
|
||||
case 1:
|
||||
speed *= 0.09;
|
||||
break;
|
||||
case 2:
|
||||
speed *= 0.0027;
|
||||
break;
|
||||
default:
|
||||
speed *= 0.00081;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return speed;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import static baritone.utils.Helper.HELPER;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 12:56 AM
|
||||
*/
|
||||
public final class Utils {
|
||||
|
||||
/**
|
||||
* Constant that a degree value is multiplied by to get the equivalent radian value
|
||||
*/
|
||||
public static final double DEG_TO_RAD = Math.PI / 180.0;
|
||||
|
||||
/**
|
||||
* Constant that a radian value is multiplied by to get the equivalent degree value
|
||||
*/
|
||||
public static final double RAD_TO_DEG = 180.0 / Math.PI;
|
||||
|
||||
public static Rotation calcRotationFromCoords(BlockPos orig, BlockPos dest) {
|
||||
return calcRotationFromVec3d(vec3dFromBlockPos(orig), vec3dFromBlockPos(dest));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates rotation to given Vec<sub>dest</sub> from Vec<sub>orig</sub>
|
||||
*
|
||||
* @param orig
|
||||
* @param dest
|
||||
* @return Rotation {@link Rotation}
|
||||
*/
|
||||
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
|
||||
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
|
||||
double yaw = MathHelper.atan2(delta[0], -delta[2]);
|
||||
double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
|
||||
double pitch = MathHelper.atan2(delta[1], dist);
|
||||
return new Rotation(
|
||||
(float) radToDeg(yaw),
|
||||
(float) radToDeg(pitch)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates rotation to given Vec<sub>dest</sub> from Vec<sub>orig</sub>
|
||||
*
|
||||
* @param orig
|
||||
* @param dest
|
||||
* @return Rotation {@link Rotation}
|
||||
*/
|
||||
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest, Rotation current) {
|
||||
return wrapAnglesToRelative(current, calcRotationFromVec3d(orig, dest));
|
||||
}
|
||||
|
||||
public static Vec3d calcCenterFromCoords(BlockPos orig, World world) {
|
||||
IBlockState b = BlockStateInterface.get(orig);
|
||||
AxisAlignedBB bbox = b.getBoundingBox(world, orig);
|
||||
double xDiff = (bbox.minX + bbox.maxX) / 2;
|
||||
double yDiff = (bbox.minY + bbox.maxY) / 2;
|
||||
double zDiff = (bbox.minZ + bbox.maxZ) / 2;
|
||||
if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out
|
||||
yDiff = 0;
|
||||
}
|
||||
return new Vec3d(
|
||||
orig.getX() + xDiff,
|
||||
orig.getY() + yDiff,
|
||||
orig.getZ() + zDiff
|
||||
);
|
||||
}
|
||||
|
||||
public static Vec3d getBlockPosCenter(BlockPos pos) {
|
||||
return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
|
||||
}
|
||||
|
||||
public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) {
|
||||
return target.subtract(current).normalize().add(current);
|
||||
}
|
||||
|
||||
public static Vec3d vec3dFromBlockPos(BlockPos orig) {
|
||||
return new Vec3d(orig.getX() + 0.0D, orig.getY() + 0.0D, orig.getZ() + 0.0D);
|
||||
}
|
||||
|
||||
public static double distanceToCenter(BlockPos pos, double x, double y, double z) {
|
||||
double xdiff = x - (pos.getX() + 0.5D);
|
||||
double ydiff = y - (pos.getY() + 0.5D);
|
||||
double zdiff = z - (pos.getZ() + 0.5D);
|
||||
return Math.sqrt(xdiff * xdiff + ydiff * ydiff + zdiff * zdiff);
|
||||
}
|
||||
|
||||
public static double playerDistanceToCenter(BlockPos pos) {
|
||||
EntityPlayerSP player = HELPER.player();
|
||||
return distanceToCenter(pos, player.posX, player.posY, player.posZ);
|
||||
}
|
||||
|
||||
public static double playerFlatDistanceToCenter(BlockPos pos) {
|
||||
EntityPlayerSP player = HELPER.player();
|
||||
return distanceToCenter(pos, player.posX, pos.getY() + 0.5, player.posZ);
|
||||
}
|
||||
|
||||
public static double degToRad(double deg) {
|
||||
return deg * DEG_TO_RAD;
|
||||
}
|
||||
|
||||
public static double radToDeg(double rad) {
|
||||
return rad * RAD_TO_DEG;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.pathing;
|
||||
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.world.border.WorldBorder;
|
||||
|
||||
public class BetterWorldBorder implements Helper {
|
||||
private final double minX;
|
||||
private final double maxX;
|
||||
private final double minZ;
|
||||
private final double maxZ;
|
||||
|
||||
public BetterWorldBorder(WorldBorder border) {
|
||||
this.minX = border.minX();
|
||||
this.maxX = border.maxX();
|
||||
this.minZ = border.minZ();
|
||||
this.maxZ = border.maxZ();
|
||||
}
|
||||
|
||||
public boolean entirelyContains(int x, int z) {
|
||||
return x + 1 > minX && x < maxX && z + 1 > minZ && z < maxZ;
|
||||
}
|
||||
|
||||
public boolean canPlaceAt(int x, int z) {
|
||||
// move it in 1 block on all sides
|
||||
// because we can't place a block at the very edge against a block outside the border
|
||||
// it won't let us right click it
|
||||
return x > minX && x + 1 < maxX && z > minZ && z + 1 < maxZ;
|
||||
}
|
||||
}
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.utils.pathing;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.junit.Test;
|
||||
|
||||
Reference in New Issue
Block a user