Compare commits
176 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12ddeee278 | ||
|
|
26e0af1188 | ||
|
|
42bb44120d | ||
|
|
ac1e0e7d6b | ||
|
|
838e75f025 | ||
|
|
5f0527be71 | ||
|
|
fd49333db6 | ||
|
|
31b30e3a31 | ||
|
|
0fe8c628c7 | ||
|
|
f86f0ab6cd | ||
|
|
40e83423bc | ||
|
|
0de802e7ba | ||
|
|
249f93877c | ||
|
|
8ac57c8da3 | ||
|
|
aff430ac51 | ||
|
|
d79f7f9615 | ||
|
|
db96a5a3ec | ||
|
|
79f1503c8b | ||
|
|
eace2ad161 | ||
|
|
d74420b265 | ||
|
|
7aab08ae0f | ||
|
|
2fc8490c72 | ||
|
|
ddc2820418 | ||
|
|
9e1e89b91f | ||
|
|
7c4036dfb1 | ||
|
|
bbaa602fe9 | ||
|
|
921822acd7 | ||
|
|
f019b81bd9 | ||
|
|
50df7b2026 | ||
|
|
92130f1642 | ||
|
|
fd13d5cbdc | ||
|
|
209b51b253 | ||
|
|
3fa0f34c1e | ||
|
|
bf0c47c85c | ||
|
|
9de3074041 | ||
|
|
37a95aea97 | ||
|
|
3116405953 | ||
|
|
ed4f9cee78 | ||
|
|
b8ac867fb9 | ||
|
|
3f6c87a8ed | ||
|
|
bf08c4fcf4 | ||
|
|
f357eb230b | ||
|
|
f3086c2231 | ||
|
|
002415425a | ||
|
|
c54d878d1c | ||
|
|
590f5d98ee | ||
|
|
849072f8ca | ||
|
|
59157c1ee0 | ||
|
|
3c9f5b2c91 | ||
|
|
7e5dedd8f3 | ||
|
|
cdfa86c977 | ||
|
|
ba1ccce962 | ||
|
|
64fdad424f | ||
|
|
1dc5be3985 | ||
|
|
a5668532b1 | ||
|
|
1d6f5df155 | ||
|
|
bac24af90e | ||
|
|
290e697d4a | ||
|
|
a5752507e1 | ||
|
|
1bfc0305fd | ||
|
|
497fb74829 | ||
|
|
91a1f05ff2 | ||
|
|
1a258b2bec | ||
|
|
81c53d5db1 | ||
|
|
9eefcbc9b6 | ||
|
|
52cfe5cf7e | ||
|
|
b550b92b0a | ||
|
|
28695031d7 | ||
|
|
93dee4fd19 | ||
|
|
f6657846d3 | ||
|
|
db163867df | ||
|
|
58fcf328b9 | ||
|
|
8e8cfdd2a6 | ||
|
|
991d822557 | ||
|
|
c25b1325da | ||
|
|
ea1de44ca8 | ||
|
|
50291089db | ||
|
|
f22f4aed00 | ||
|
|
d644c5b754 | ||
|
|
1e2ae34dbe | ||
|
|
5102d9164e | ||
|
|
a690e1eca4 | ||
|
|
d25d6c2611 | ||
|
|
a231748b4e | ||
|
|
800545f0b5 | ||
|
|
ef72c56833 | ||
|
|
ec57888ce1 | ||
|
|
960ff6ed98 | ||
|
|
e682fc75a6 | ||
|
|
7e8c852528 | ||
|
|
42032890ed | ||
|
|
8867fb7010 | ||
|
|
6b6931c86d | ||
|
|
b915151ae3 | ||
|
|
7609f3082e | ||
|
|
99f9dd1671 | ||
|
|
1a0cca794c | ||
|
|
e71547b9ef | ||
|
|
246a246cb7 | ||
|
|
b87a1fa420 | ||
|
|
b12c4e9f8c | ||
|
|
330089f1e2 | ||
|
|
acdcbf5146 | ||
|
|
f6045b7cb4 | ||
|
|
a07d7d0526 | ||
|
|
6b2fd5acee | ||
|
|
8786148fef | ||
|
|
edb433ea6e | ||
|
|
a02704e097 | ||
|
|
e66fdea500 | ||
|
|
1947459acf | ||
|
|
52aa609ac7 | ||
|
|
74f46cd6eb | ||
|
|
1704d56274 | ||
|
|
92bc067633 | ||
|
|
64639b377f | ||
|
|
81f7375591 | ||
|
|
74d82f2339 | ||
|
|
42c62a0559 | ||
|
|
b25a6305ce | ||
|
|
98e90e72f7 | ||
|
|
10851ddf14 | ||
|
|
402079d7db | ||
|
|
b184141db2 | ||
|
|
42c6abbf72 | ||
|
|
8bb19797e1 | ||
|
|
f9a8aa0c2b | ||
|
|
6b274b3f1e | ||
|
|
f02c3115d1 | ||
|
|
ee9ca6dd49 | ||
|
|
8a5e3f7009 | ||
|
|
b29878d0f2 | ||
|
|
19c8194eae | ||
|
|
d8381c71fd | ||
|
|
4b76fa995c | ||
|
|
088056b3d0 | ||
|
|
0c09441154 | ||
|
|
69d3bc0c2e | ||
|
|
1018db797e | ||
|
|
b31e0a87cb | ||
|
|
4572b75db7 | ||
|
|
15fdbb2312 | ||
|
|
848b7c6de0 | ||
|
|
2b96a2e463 | ||
|
|
354b26b1da | ||
|
|
62b2f81ba1 | ||
|
|
5826931eea | ||
|
|
a8119366a1 | ||
|
|
b0575fbe0c | ||
|
|
866cf34f50 | ||
|
|
23908ad14f | ||
|
|
6d06713610 | ||
|
|
18d3c4c2bd | ||
|
|
faece77e8c | ||
|
|
413c11a23e | ||
|
|
4c9253fa5e | ||
|
|
d86a34a527 | ||
|
|
92aba1b78e | ||
|
|
28ba97c3de | ||
|
|
24c23e28ec | ||
|
|
2a2842361b | ||
|
|
632e05c4c2 | ||
|
|
980d68536c | ||
|
|
4144344acd | ||
|
|
e962c39506 | ||
|
|
48f309ac05 | ||
|
|
0688a57a38 | ||
|
|
078b3909b3 | ||
|
|
d51b23bd1e | ||
|
|
9378f7e8a0 | ||
|
|
e7e434a95b | ||
|
|
be1203fabb | ||
|
|
340d2a1d54 | ||
|
|
f84b749ff4 | ||
|
|
a223585daa | ||
|
|
163e97aad6 |
12
.github/workflows/gradle_build.yml
vendored
12
.github/workflows/gradle_build.yml
vendored
@@ -13,14 +13,14 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
cache: gradle
|
||||
|
||||
@@ -31,13 +31,13 @@ jobs:
|
||||
run: ./gradlew build -Pmod_version="$(git describe --always --tags --first-parent | cut -c2-)"
|
||||
|
||||
- name: Archive Artifacts
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Artifacts
|
||||
path: dist/
|
||||
|
||||
- name: Archive mapping.txt
|
||||
uses: actions/upload-artifact@v3
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: Mappings
|
||||
path: mapping/
|
||||
|
||||
8
.github/workflows/run_tests.yml
vendored
8
.github/workflows/run_tests.yml
vendored
@@ -11,11 +11,11 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
- uses: actions/checkout@v4
|
||||
- name: Set up JDK 21
|
||||
uses: actions/setup-java@v4
|
||||
with:
|
||||
java-version: '17'
|
||||
java-version: '21'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
|
||||
@@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt update -y
|
||||
|
||||
RUN apt install \
|
||||
openjdk-17-jdk \
|
||||
openjdk-21-jdk \
|
||||
git \
|
||||
--assume-yes
|
||||
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.19.2-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.19.4-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.20.1-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.21.3-brightgreen.svg" alt="Minecraft"/></a>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -63,11 +64,14 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s
|
||||
| [1.12.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.2.19/baritone-api-forge-1.2.19.jar) | |
|
||||
| [1.16.5 Forge](https://github.com/cabaletta/baritone/releases/download/v1.6.5/baritone-api-forge-1.6.5.jar) | [1.16.5 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.6.5/baritone-api-fabric-1.6.5.jar) |
|
||||
| [1.17.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.7.3/baritone-api-forge-1.7.3.jar) | [1.17.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.7.3/baritone-api-fabric-1.7.3.jar) |
|
||||
| [1.18.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.8.5/baritone-api-forge-1.8.5.jar) | [1.18.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.8.5/baritone-api-fabric-1.8.5.jar) |
|
||||
| [1.18.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.8.6/baritone-api-forge-1.8.6.jar) | [1.18.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.8.6/baritone-api-fabric-1.8.6.jar) |
|
||||
| [1.19.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.4/baritone-api-forge-1.9.4.jar) | [1.19.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.4/baritone-api-fabric-1.9.4.jar) |
|
||||
| [1.19.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.1/baritone-api-forge-1.9.1.jar) | [1.19.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.1/baritone-api-fabric-1.9.1.jar) |
|
||||
| [1.19.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-forge-1.9.3.jar) | [1.19.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.9.3/baritone-api-fabric-1.9.3.jar) |
|
||||
| [1.20.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-forge-1.10.1.jar) | [1.20.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-fabric-1.10.1.jar) |
|
||||
| [1.20.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-forge-1.10.2.jar) | [1.20.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-fabric-1.10.2.jar) |
|
||||
| [1.20.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-forge-1.10.2.jar) | [1.20.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-fabric-1.10.2.jar) |
|
||||
| [1.21.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.11.1/baritone-api-forge-1.11.1.jar) | [1.21.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.11.1/baritone-api-fabric-1.11.1.jar) |
|
||||
|
||||
**Message for 2b2t players looking for 1.19/1.20 Baritone** If you like, please try the beta for Baritone Elytra for 2b2t, find it in #announcements of [the Baritone discord](http://discord.gg/s6fRBAUpmr). It supports 1.19.4 and 1.20.1, Forge or Fabric. If you have to see it to believe it, watch [this YouTube video](https://youtu.be/NnSlQi-68eQ).
|
||||
|
||||
|
||||
81
SETUP.md
81
SETUP.md
@@ -1,78 +1,87 @@
|
||||
# Installation
|
||||
|
||||
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone.
|
||||
|
||||
You can also use a custom version json for Minecraft, with the [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1) version or the [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1) version or the [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1) version.
|
||||
The easiest way to install Baritone is to install it as Forge/Neoforge/Fabric mod, but if you know how you can also use with a custom `version.json`
|
||||
(Examples: [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1), [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1), [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1)).
|
||||
|
||||
Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
|
||||
## Prebuilt official releases
|
||||
These releases are not always completely up to date with latest features, and are only released from `master`. (so if you want `backfill-2` branch for example, you'll have to build it yourself)
|
||||
Releases are made rarely and are not always up to date with the latest features and bug fixes.
|
||||
|
||||
Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases)
|
||||
|
||||
v1.2.* is for 1.12.2, v1.3.* is for 1.13.2, v1.4.* is for 1.14.4, v1.5.* is for 1.15.2, v1.6.* is for 1.16.5, v1.7.* is for 1.17.1, v1.8.* is for 1.18.1
|
||||
The mapping between major Minecraft versions and major Baritone versions is as follows
|
||||
| Minecraft version | 1.12 | 1.13 | 1.14 | 1.15 | 1.16 | 1.17 | 1.18 | 1.19 | 1.20 | 1.21 |
|
||||
|-------------------|------|------|------|------|------|------|------|------|-------|-------|
|
||||
| Baritone version | v1.2 | v1.3 | v1.4 | v1.5 | v1.6 | v1.7 | v1.8 | v1.9 | v1.10 | v1.11 |
|
||||
|
||||
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by that public keys of `checksums.txt`.
|
||||
|
||||
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
|
||||
The build is fully deterministic and reproducible, and you can verify that by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
|
||||
|
||||
|
||||
## Artifacts
|
||||
|
||||
Building Baritone will result in 5 artifacts created in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
|
||||
Building Baritone will create the final artifacts in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
|
||||
|
||||
**The Forge and Fabric releases can simply be added as a Forge/Fabric mods.**
|
||||
**The Forge, NeoForge and Fabric releases can simply be added as a Forge/Neoforge/Fabric mods.**
|
||||
|
||||
If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar`
|
||||
If another one of your other mods has a Baritone integration, you want `baritone-api-*-VERSION.jar`.
|
||||
If you want to report a bug and spare us some effort, you want `baritone-unoptimized-*-VERSION.jar`.
|
||||
Otherwise, you want `baritone-standalone-*-VERSION.jar`
|
||||
|
||||
Here's what the various qualifiers mean
|
||||
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
|
||||
- **Forge/Fabric API**: Same as API, but packaged for Forge/Fabric. This should be used where another mod has a Baritone integration.
|
||||
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
|
||||
- **Forge/Fabric Standalone**: Same as Standalone, but packaged for Forge/Fabric. This should be used when Baritone is your only Forge/Fabric mod, or none of your other Forge/Fabric mods integrate with Baritone.
|
||||
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
|
||||
- **Forge/Fabric Unoptimized**: Same as Unoptimized, but packaged for Forge/Fabric.
|
||||
- **Standalone**: Everything is obfuscated. Other mods cannot use Baritone, but you get a bit of extra performance.
|
||||
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used in production, but is really helpful for crash reports.
|
||||
|
||||
- **No loader**: Loadable as a launchwrapper tweaker against vanilla Minecraft using a custom `version.json`.
|
||||
- **Forge/Neoforge/Fabric**: Loadable as a standard mod using the respective loader. The fabric build may or may not work on Quilt.
|
||||
|
||||
If you build from source you will also find mapping files in the `dist` directory. These contain the renamings done by ProGuard and are useful if you want to read obfuscated stack traces.
|
||||
|
||||
## Build it yourself
|
||||
- Clone or download Baritone
|
||||
|
||||

|
||||
- If you choose to download, make sure you extract the ZIP archive.
|
||||
- If you choose to download, make sure you download the correct branch and extract the ZIP archive.
|
||||
- Follow one of the instruction sets below, based on your preference
|
||||
|
||||
## Command Line
|
||||
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
|
||||
|
||||
If you have errors with a package missing please make sure you have setup your environment, and are using Oracle JDK 8 for 1.12.2-1.16.5, JDK 16+ for 1.17.1, and JDK 17+ for 1.18.1.
|
||||
|
||||
To check which java you are using do
|
||||
`java -version` in a command prompt or terminal.
|
||||
If you are using anything above OpenJDK 8 for 1.12.2-1.16.5, it might not work because the Java distributions above JDK 8 using may not have the needed javax classes.
|
||||
The recommended Java versions by Minecraft version are
|
||||
| Minecraft version | Java version |
|
||||
|-------------------------------|---------------|
|
||||
| 1.12.2 - 1.16.5 | 8 |
|
||||
| 1.17.1 | 16 |
|
||||
| 1.18.2 - 1.20.4 | 17 |
|
||||
| 1.20.5 - 1.21.4 | 21 |
|
||||
|
||||
Download java: https://adoptium.net/
|
||||
#### macOS guide
|
||||
In order to get JDK 8, Try running the following command:
|
||||
`% /usr/libexec/java_home -V`
|
||||
If it doesn't work try this guide: https://stackoverflow.com/questions/46513639/how-to-downgrade-java-from-9-to-8-on-a-macos-eclipse-is-not-running-with-java-9
|
||||
|
||||
If you see something like
|
||||
|
||||
`% 1.8.0_VERSION, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_VERSION.jdk/Contents/Home`
|
||||
|
||||
in the list then you've got JDK 8 installed.
|
||||
In order to get JDK 8 running in the **current terminal window** you will have to run this command:
|
||||
|
||||
`% export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)`
|
||||
|
||||
To add OpenJDK 8 to your PATH add the export line to the end of your `.zshrc / .bashrc` if you want it to apply to each new terminal. If you're using bash change the .bachrc and if you're using zsh change the .zshrc
|
||||
To check which java version you are using do `java -version` in a command prompt or terminal.
|
||||
|
||||
### Building Baritone
|
||||
|
||||
These tasks depend on the minecraft version, but are (for the most part) standard for building mods.
|
||||
|
||||
for more details, see [the build ci action](/.github/workflows/gradle_build.yml)
|
||||
For more details, see [the build ci action](/.github/workflows/gradle_build.yml) of the branch you want to build.
|
||||
|
||||
For most branches `gradlew build` should build everything, but there are exceptions and this file might be out of date.
|
||||
|
||||
More specifically, on older branches the setup used to be that `gradlew build` builds the tweaker jar
|
||||
and `gradlew build -Pbaritone.forge_build` / `gradlew build -Pbaritone.fabric_build` are needed to build
|
||||
for Forge/Fabric instead. And you might have to run `setupDecompWorkspace` first.
|
||||
|
||||
## IntelliJ
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
|
||||
- depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working
|
||||
- Depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working
|
||||
|
||||
## Github Actions
|
||||
Most branches have a CI workflow at `.github/workflows/gradle_build.yml`. If you fork this repository and enable actions for your fork
|
||||
you can push a dummy commit to trigger it and have GitHub build Baritone for you.
|
||||
|
||||
If the commit you want to build is less than 90 days old, you can also find the corresponding workflow run in
|
||||
[this list](https://github.com/cabaletta/baritone/actions/workflows/gradle_build.yml) and download the artifacts from there.
|
||||
|
||||
24
build.gradle
24
build.gradle
@@ -37,7 +37,13 @@ allprojects {
|
||||
}
|
||||
group = rootProject.maven_group
|
||||
|
||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
|
||||
sourceCompatibility = targetCompatibility = JavaVersion.toVersion(project.java_version)
|
||||
|
||||
java {
|
||||
toolchain {
|
||||
languageVersion.set(JavaLanguageVersion.of(sourceCompatibility.majorVersion.toInteger()))
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
maven {
|
||||
@@ -72,12 +78,10 @@ allprojects {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation "org.spongepowered:mixin:0.8.5"
|
||||
implementation "org.ow2.asm:asm:9.3"
|
||||
// The following line declares the yarn mappings you may select this one as well.
|
||||
// mappings "net.fabricmc:yarn:1.17.1+build.32:v2"
|
||||
//launchImplementation('dev.babbaj:nether-pathfinder:1.3.0')
|
||||
implementation "dev.babbaj:nether-pathfinder:${nether_pathfinder_version}"
|
||||
compileOnly "org.spongepowered:mixin:${project.mixin_version}"
|
||||
compileOnly "org.ow2.asm:asm:${project.asm_version}"
|
||||
|
||||
implementation "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
|
||||
|
||||
implementation 'com.google.code.findbugs:jsr305:3.0.2'
|
||||
}
|
||||
@@ -88,14 +92,16 @@ allprojects {
|
||||
mappings {
|
||||
intermediary()
|
||||
mojmap()
|
||||
parchment("1.20.2", "2023.10.22")
|
||||
parchment("1.20.6", "2024.05.01")
|
||||
|
||||
devFallbackNamespace "official"
|
||||
}
|
||||
}
|
||||
|
||||
tasks.withType(JavaCompile).configureEach {
|
||||
it.options.encoding = "UTF-8"
|
||||
|
||||
def targetVersion = 17
|
||||
def targetVersion = project.java_version.toInteger()
|
||||
if (JavaVersion.current().isJava9Compatible()) {
|
||||
it.options.release = targetVersion
|
||||
}
|
||||
|
||||
@@ -40,5 +40,5 @@ dependencies {
|
||||
implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'
|
||||
implementation group: 'commons-io', name: 'commons-io', version: '2.7'
|
||||
|
||||
implementation group: 'xyz.wagyourtail.unimined', name: 'xyz.wagyourtail.unimined.gradle.plugin', version: '1.1.0'
|
||||
implementation group: 'xyz.wagyourtail.unimined', name: 'xyz.wagyourtail.unimined.gradle.plugin', version: '1.2.9'
|
||||
}
|
||||
@@ -36,8 +36,8 @@ import java.nio.file.Paths;
|
||||
class BaritoneGradleTask extends DefaultTask {
|
||||
|
||||
protected static final String
|
||||
PROGUARD_ZIP = "proguard.zip",
|
||||
PROGUARD_JAR = "proguard.jar",
|
||||
PROGUARD_ZIP = "proguard-%s.zip",
|
||||
PROGUARD_JAR = "proguard-%s.jar",
|
||||
PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro",
|
||||
PROGUARD_CONFIG_DEST = "template.pro",
|
||||
PROGUARD_API_CONFIG = "api.pro",
|
||||
|
||||
@@ -26,6 +26,9 @@ import org.gradle.api.tasks.TaskCollection;
|
||||
import org.gradle.api.tasks.compile.ForkOptions;
|
||||
import org.gradle.api.tasks.compile.JavaCompile;
|
||||
import org.gradle.internal.jvm.Jvm;
|
||||
import org.gradle.jvm.toolchain.JavaLanguageVersion;
|
||||
import org.gradle.jvm.toolchain.JavaLauncher;
|
||||
import org.gradle.jvm.toolchain.JavaToolchainService;
|
||||
import xyz.wagyourtail.unimined.api.UniminedExtension;
|
||||
import xyz.wagyourtail.unimined.api.minecraft.MinecraftConfig;
|
||||
|
||||
@@ -47,17 +50,10 @@ import java.util.zip.ZipFile;
|
||||
public class ProguardTask extends BaritoneGradleTask {
|
||||
|
||||
@Input
|
||||
private String url;
|
||||
private String proguardVersion;
|
||||
|
||||
public String getUrl() {
|
||||
return url;
|
||||
}
|
||||
|
||||
@Input
|
||||
private String extract;
|
||||
|
||||
public String getExtract() {
|
||||
return extract;
|
||||
public String getProguardVersion() {
|
||||
return proguardVersion;
|
||||
}
|
||||
|
||||
private List<String> requiredLibraries;
|
||||
@@ -99,98 +95,33 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
}
|
||||
|
||||
private void downloadProguard() throws Exception {
|
||||
Path proguardZip = getTemporaryFile(PROGUARD_ZIP);
|
||||
Path proguardZip = getTemporaryFile(String.format(PROGUARD_ZIP, proguardVersion));
|
||||
if (!Files.exists(proguardZip)) {
|
||||
write(new URL(this.url).openStream(), proguardZip);
|
||||
write(new URL(String.format("https://github.com/Guardsquare/proguard/releases/download/v%s/proguard-%s.zip", proguardVersion, proguardVersion)).openStream(), proguardZip);
|
||||
}
|
||||
}
|
||||
|
||||
private void extractProguard() throws Exception {
|
||||
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
|
||||
Path proguardJar = getTemporaryFile(String.format(PROGUARD_JAR, proguardVersion));
|
||||
if (!Files.exists(proguardJar)) {
|
||||
ZipFile zipFile = new ZipFile(getTemporaryFile(PROGUARD_ZIP).toFile());
|
||||
ZipEntry zipJarEntry = zipFile.getEntry(this.extract);
|
||||
ZipFile zipFile = new ZipFile(getTemporaryFile(String.format(PROGUARD_ZIP, proguardVersion)).toFile());
|
||||
ZipEntry zipJarEntry = zipFile.getEntry(String.format("proguard-%s/lib/proguard.jar", proguardVersion));
|
||||
write(zipFile.getInputStream(zipJarEntry), proguardJar);
|
||||
zipFile.close();
|
||||
}
|
||||
}
|
||||
|
||||
private String getJavaBinPathForProguard() throws Exception {
|
||||
String path;
|
||||
try {
|
||||
path = findJavaPathByGradleConfig();
|
||||
if (path != null) return path;
|
||||
} catch (Exception ex) {
|
||||
System.err.println("Unable to find java by javaCompile options");
|
||||
ex.printStackTrace();
|
||||
private JavaLauncher getJavaLauncherForProguard() {
|
||||
var toolchains = getProject().getExtensions().getByType(JavaToolchainService.class);
|
||||
var toolchain = toolchains.launcherFor((spec) -> {
|
||||
spec.getLanguageVersion().set(JavaLanguageVersion.of(getProject().findProperty("java_version").toString()));
|
||||
}).getOrNull();
|
||||
|
||||
if (toolchain == null) {
|
||||
throw new IllegalStateException("Java toolchain not found");
|
||||
}
|
||||
|
||||
path = findJavaByGradleCurrentRuntime();
|
||||
if (path != null) return path;
|
||||
|
||||
try {
|
||||
path = findJavaByJavaHome();
|
||||
if (path != null) return path;
|
||||
} catch (Exception ex) {
|
||||
System.err.println("Unable to find java by JAVA_HOME");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
|
||||
throw new Exception("Unable to find java to determine ProGuard libraryjars. Please specify forkOptions.executable in javaCompile," +
|
||||
" JAVA_HOME environment variable, or make sure to run Gradle with the correct JDK (a v1.8 only)");
|
||||
}
|
||||
|
||||
private String findJavaByGradleCurrentRuntime() {
|
||||
String path = Jvm.current().getJavaExecutable().getAbsolutePath();
|
||||
System.out.println("Using Gradle's runtime Java for ProGuard");
|
||||
return path;
|
||||
}
|
||||
|
||||
private String findJavaByJavaHome() {
|
||||
final String javaHomeEnv = System.getenv("JAVA_HOME");
|
||||
if (javaHomeEnv != null) {
|
||||
String path = Jvm.forHome(new File(javaHomeEnv)).getJavaExecutable().getAbsolutePath();
|
||||
System.out.println("Detected Java path by JAVA_HOME");
|
||||
return path;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private String findJavaPathByGradleConfig() {
|
||||
final TaskCollection<JavaCompile> javaCompiles = super.getProject().getTasks().withType(JavaCompile.class);
|
||||
|
||||
final JavaCompile compileTask = javaCompiles.iterator().next();
|
||||
final ForkOptions forkOptions = compileTask.getOptions().getForkOptions();
|
||||
|
||||
if (forkOptions != null) {
|
||||
String javacPath = forkOptions.getExecutable();
|
||||
if (javacPath != null) {
|
||||
File javacFile = new File(javacPath);
|
||||
if (javacFile.exists()) {
|
||||
File[] maybeJava = javacFile.getParentFile().listFiles((dir, name) -> name.equals("java"));
|
||||
if (maybeJava != null && maybeJava.length > 0) {
|
||||
String path = maybeJava[0].getAbsolutePath();
|
||||
System.out.println("Detected Java path by forkOptions");
|
||||
return path;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
private boolean validateJavaVersion(String java) {
|
||||
//TODO: fix for j16
|
||||
// final JavaVersion javaVersion = new DefaultJvmVersionDetector(new DefaultExecActionFactory(new IdentityFileResolver())).getJavaVersion(java);
|
||||
//
|
||||
// if (!javaVersion.getMajorVersion().equals("8")) {
|
||||
// System.out.println("Failed to validate Java version " + javaVersion.toString() + " [" + java + "] for ProGuard libraryjars");
|
||||
// // throw new RuntimeException("Java version incorrect: " + javaVersion.getMajorVersion() + " for " + java);
|
||||
// return false;
|
||||
// }
|
||||
//
|
||||
// System.out.println("Validated Java version " + javaVersion.toString() + " [" + java + "] for ProGuard libraryjars");
|
||||
return true;
|
||||
return toolchain;
|
||||
}
|
||||
|
||||
private void generateConfigs() throws Exception {
|
||||
@@ -284,13 +215,8 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
public void setUrl(String url) {
|
||||
this.url = url;
|
||||
}
|
||||
|
||||
|
||||
public void setExtract(String extract) {
|
||||
this.extract = extract;
|
||||
public void setProguardVersion(String url) {
|
||||
this.proguardVersion = url;
|
||||
}
|
||||
|
||||
private void runProguard(Path config) throws Exception {
|
||||
@@ -299,39 +225,15 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
Files.delete(this.proguardOut);
|
||||
}
|
||||
|
||||
// Make paths relative to work directory; fixes spaces in path to config, @"" doesn't work
|
||||
Path workingDirectory = getTemporaryFile("");
|
||||
Path proguardJar = workingDirectory.relativize(getTemporaryFile(PROGUARD_JAR));
|
||||
config = workingDirectory.relativize(config);
|
||||
|
||||
// Honestly, if you still have spaces in your path at this point, you're SOL.
|
||||
getProject().javaexec(spec -> {
|
||||
spec.workingDir(workingDirectory.toFile());
|
||||
spec.args("@" + workingDirectory.relativize(config));
|
||||
spec.classpath(getTemporaryFile(String.format(PROGUARD_JAR, proguardVersion)));
|
||||
|
||||
Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString())
|
||||
.directory(workingDirectory.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(), System.out);
|
||||
this.printOutputLog(p.getErrorStream(), System.err);
|
||||
|
||||
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
|
||||
int exitCode = p.waitFor();
|
||||
if (exitCode != 0) {
|
||||
Thread.sleep(1000);
|
||||
throw new IllegalStateException("Proguard exited with code " + exitCode);
|
||||
}
|
||||
spec.executable(getJavaLauncherForProguard().getExecutablePath().getAsFile());
|
||||
}).assertNormalExitValue().rethrowFailure();
|
||||
}
|
||||
|
||||
private void printOutputLog(InputStream stream, PrintStream outerr) {
|
||||
new Thread(() -> {
|
||||
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
|
||||
String line;
|
||||
while ((line = reader.readLine()) != null) {
|
||||
outerr.println(line);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -71,10 +71,10 @@ public class Determinizer {
|
||||
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
|
||||
copy(jarFile.getInputStream(entry), cancer);
|
||||
String manifest = new String(cancer.toByteArray());
|
||||
if (!manifest.contains("baritone.launch.BaritoneTweaker")) {
|
||||
if (!manifest.contains("baritone.launch.tweaker.BaritoneTweaker")) {
|
||||
throw new IllegalStateException("unable to replace");
|
||||
}
|
||||
manifest = manifest.replace("baritone.launch.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
|
||||
manifest = manifest.replace("baritone.launch.tweaker.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
|
||||
jos.write(manifest.getBytes());
|
||||
} else {
|
||||
copy(jarFile.getInputStream(entry), jos);
|
||||
|
||||
@@ -45,7 +45,7 @@ dependencies {
|
||||
common sourceSet.output
|
||||
shadowCommon sourceSet.output
|
||||
}
|
||||
include "dev.babbaj:nether-pathfinder:${nether_pathfinder_version}"
|
||||
include "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -78,8 +78,7 @@ components.java {
|
||||
}
|
||||
|
||||
task proguard(type: ProguardTask) {
|
||||
url 'https://github.com/Guardsquare/proguard/releases/download/v7.2.1/proguard-7.2.1.zip'
|
||||
extract 'proguard-7.2.1/lib/proguard.jar'
|
||||
proguardVersion "7.4.2"
|
||||
compType "fabric"
|
||||
}
|
||||
|
||||
|
||||
@@ -10,7 +10,8 @@
|
||||
],
|
||||
"contact": {
|
||||
"homepage": "https://github.com/cabaletta/baritone",
|
||||
"sources": "https://github.com/cabaletta/baritone"
|
||||
"sources": "https://github.com/cabaletta/baritone",
|
||||
"issues": "https://github.com/cabaletta/baritone/issues"
|
||||
},
|
||||
|
||||
"license": "LGPL-3.0",
|
||||
@@ -25,6 +26,13 @@
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.14.22",
|
||||
"minecraft": ["1.20.3", "1.20.4"]
|
||||
"minecraft": ["1.21","1.21.1"]
|
||||
},
|
||||
"custom": {
|
||||
"modmenu": {
|
||||
"links": {
|
||||
"modmenu.discord": "https://discord.gg/s6fRBAUpmr"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,7 @@ plugins {
|
||||
archivesBaseName = archivesBaseName + "-forge"
|
||||
|
||||
unimined.minecraft {
|
||||
mappings {
|
||||
devFallbackNamespace "intermediary"
|
||||
}
|
||||
|
||||
forge {
|
||||
minecraftForge {
|
||||
loader project.forge_version
|
||||
mixinConfig ["mixins.baritone.json"]
|
||||
}
|
||||
@@ -56,7 +52,7 @@ dependencies {
|
||||
common sourceSet.output
|
||||
shadowCommon sourceSet.output
|
||||
}
|
||||
shadowCommon "dev.babbaj:nether-pathfinder:${nether_pathfinder_version}"
|
||||
shadowCommon "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
@@ -99,8 +95,7 @@ components.java {
|
||||
}
|
||||
|
||||
task proguard(type: ProguardTask) {
|
||||
url 'https://github.com/Guardsquare/proguard/releases/download/v7.2.1/proguard-7.2.1.zip'
|
||||
extract 'proguard-7.2.1/lib/proguard.jar'
|
||||
proguardVersion "7.4.2"
|
||||
compType "forge"
|
||||
}
|
||||
|
||||
|
||||
@@ -35,6 +35,6 @@ A Minecraft pathfinder bot.
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange="[1.20.3, 1.20.4]"
|
||||
versionRange="[1.21, 1.21.1]"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
|
||||
@@ -2,15 +2,23 @@ org.gradle.jvmargs=-Xmx4G
|
||||
|
||||
available_loaders=fabric,forge,neoforge,tweaker
|
||||
|
||||
mod_version=1.10.2
|
||||
mod_version=1.11.2
|
||||
maven_group=baritone
|
||||
archives_base_name=baritone
|
||||
|
||||
minecraft_version=1.20.4
|
||||
java_version=21
|
||||
|
||||
forge_version=49.0.3
|
||||
neoforge_version=0-beta
|
||||
minecraft_version=1.21
|
||||
|
||||
fabric_version=0.14.22
|
||||
forge_version=51.0.16
|
||||
|
||||
nether_pathfinder_version=1.4.1
|
||||
neoforge_version=20-beta
|
||||
|
||||
fabric_version=0.15.11
|
||||
|
||||
nether_pathfinder_version=1.4.1
|
||||
|
||||
// These dependencies are used for common and tweaker
|
||||
// while mod loaders usually ship their own version
|
||||
mixin_version=0.8.5
|
||||
asm_version=9.7
|
||||
|
||||
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-8.7-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
@@ -25,9 +25,6 @@ plugins {
|
||||
archivesBaseName = archivesBaseName + "-neoforge"
|
||||
|
||||
unimined.minecraft {
|
||||
mappings {
|
||||
devFallbackNamespace "intermediary"
|
||||
}
|
||||
|
||||
neoForged {
|
||||
loader project.neoforge_version
|
||||
@@ -65,13 +62,13 @@ dependencies {
|
||||
common sourceSet.output
|
||||
shadowCommon sourceSet.output
|
||||
}
|
||||
shadowCommon "dev.babbaj:nether-pathfinder:${nether_pathfinder_version}"
|
||||
shadowCommon "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
|
||||
}
|
||||
|
||||
processResources {
|
||||
inputs.property "version", project.version
|
||||
|
||||
filesMatching("META-INF/mods.toml") {
|
||||
filesMatching("META-INF/neoforge.mods.toml") {
|
||||
expand "version": project.version
|
||||
}
|
||||
}
|
||||
@@ -108,8 +105,7 @@ components.java {
|
||||
}
|
||||
|
||||
task proguard(type: ProguardTask) {
|
||||
url 'https://github.com/Guardsquare/proguard/releases/download/v7.2.1/proguard-7.2.1.zip'
|
||||
extract 'proguard-7.2.1/lib/proguard.jar'
|
||||
proguardVersion "7.4.2"
|
||||
compType "neoforge"
|
||||
}
|
||||
|
||||
@@ -131,4 +127,4 @@ publishing {
|
||||
repositories {
|
||||
// Add repositories to publish to here.
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.neoforged.api.distmarker.Dist;
|
||||
import net.neoforged.fml.common.Mod;
|
||||
|
||||
@Mod("baritoe")
|
||||
@Mod(value = "baritoe", dist = Dist.CLIENT)
|
||||
public class BaritoneForgeModXD {
|
||||
}
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
# This is an example mods.toml file. It contains the data relating to the loading mods.
|
||||
# This is an example neoforge.mods.toml file. It contains the data relating to the loading mods.
|
||||
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
|
||||
# The overall format is standard TOML format, v0.5.0.
|
||||
# Note that there are a couple of TOML lists in this file.
|
||||
@@ -33,8 +33,8 @@ A Minecraft pathfinder bot.
|
||||
|
||||
[[dependencies.baritoe]]
|
||||
modId="minecraft"
|
||||
mandatory=true
|
||||
type="required"
|
||||
# This version range declares a minimum of the current minecraft version up to but not including the next major version
|
||||
versionRange="[1.20.3, 1.20.4]"
|
||||
versionRange="[1.21,1.21.1]"
|
||||
ordering="NONE"
|
||||
side="BOTH"
|
||||
5
scripts/proguard.pro
vendored
5
scripts/proguard.pro
vendored
@@ -54,6 +54,11 @@
|
||||
-dontwarn baritone.utils.schematic.schematica.**
|
||||
-dontwarn baritone.utils.schematic.litematica.**
|
||||
|
||||
# nether-pathfinder uses JNI to acess its own classes
|
||||
# and some of our builds include it before running proguard
|
||||
# conservatively keep all of it, even though only PathSegment.<init> is needed
|
||||
-keep,allowoptimization class dev.babbaj.pathfinder.** { *; }
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main'
|
||||
# methods.
|
||||
-keepclasseswithmembers public class * {
|
||||
|
||||
@@ -29,6 +29,11 @@ import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.annotation.ElementType;
|
||||
@@ -50,6 +55,7 @@ import java.util.function.Consumer;
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class Settings {
|
||||
private static final Logger LOGGER = LoggerFactory.getLogger("Baritone");
|
||||
|
||||
/**
|
||||
* Allow Baritone to break blocks
|
||||
@@ -71,6 +77,16 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> allowPlace = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to place blocks in fluid source blocks
|
||||
*/
|
||||
public final Setting<Boolean> allowPlaceInFluidsSource = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to place blocks in flowing fluid
|
||||
*/
|
||||
public final Setting<Boolean> allowPlaceInFluidsFlow = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to move items in your inventory to your hotbar
|
||||
*/
|
||||
@@ -169,6 +185,13 @@ public final class Settings {
|
||||
* <p>
|
||||
* Defaults to false because this fails on constantiam. Please let me know if this is ever disabled. Please.
|
||||
*/
|
||||
public final Setting<Boolean> allowJumpAtBuildLimit = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Just here so mods that use the API don't break. Does nothing.
|
||||
*/
|
||||
@Deprecated
|
||||
@JavaOnly
|
||||
public final Setting<Boolean> allowJumpAt256 = new Setting<>(false);
|
||||
|
||||
/**
|
||||
@@ -382,6 +405,12 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Float> blockReachDistance = new Setting<>(4.5f);
|
||||
|
||||
/**
|
||||
* How many ticks between breaking a block and starting to break the next block. Default in game is 6 ticks.
|
||||
* Values under 1 will be clamped. The delay only applies to non-instant (1-tick) breaks.
|
||||
*/
|
||||
public final Setting<Integer> blockBreakSpeed = new Setting<>(6);
|
||||
|
||||
/**
|
||||
* How many degrees to randomize the pitch and yaw every tick. Set to 0 to disable
|
||||
*/
|
||||
@@ -900,6 +929,13 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Integer> maxCachedWorldScanCount = new Setting<>(10);
|
||||
|
||||
/**
|
||||
* Mine will not scan for or remember more than this many target locations.
|
||||
* Note that the number of locations retrieved from cache is additionaly
|
||||
* limited by {@link #maxCachedWorldScanCount}.
|
||||
*/
|
||||
public final Setting<Integer> mineMaxOreLocationsCount = new Setting<>(64);
|
||||
|
||||
/**
|
||||
* Sets the minimum y level whilst mining - set to 0 to turn off.
|
||||
* if world has negative y values, subtract the min world height to get the value to put here
|
||||
@@ -957,6 +993,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> replantNetherWart = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Farming will scan for at most this many blocks.
|
||||
*/
|
||||
public final Setting<Integer> farmMaxScanSize = new Setting<>(256);
|
||||
|
||||
/**
|
||||
* When the cache scan gives less blocks than the maximum threshold (but still above zero), scan the main world too.
|
||||
* <p>
|
||||
@@ -1048,6 +1089,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Double> breakCorrectBlockPenaltyMultiplier = new Setting<>(10d);
|
||||
|
||||
/**
|
||||
* Multiply the cost of placing a block that's incorrect in the builder's schematic by this coefficient
|
||||
*/
|
||||
public final Setting<Double> placeIncorrectBlockPenaltyMultiplier = new Setting<>(2d);
|
||||
|
||||
/**
|
||||
* When this setting is true, build a schematic with the highest X coordinate being the origin, instead of the lowest
|
||||
*/
|
||||
@@ -1063,6 +1109,28 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> schematicOrientationZ = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Rotates the schematic before building it.
|
||||
* Possible values are
|
||||
* <ul>
|
||||
* <li> NONE - No rotation </li>
|
||||
* <li> CLOCKWISE_90 - Rotate 90° clockwise </li>
|
||||
* <li> CLOCKWISE_180 - Rotate 180° clockwise </li>
|
||||
* <li> COUNTERCLOCKWISE_90 - Rotate 270° clockwise </li>
|
||||
* </ul>
|
||||
*/
|
||||
public final Setting<Rotation> buildSchematicRotation = new Setting<>(Rotation.NONE);
|
||||
|
||||
/**
|
||||
* Mirrors the schematic before building it.
|
||||
* Possible values are
|
||||
* <ul>
|
||||
* <li> FRONT_BACK - mirror the schematic along its local x axis </li>
|
||||
* <li> LEFT_RIGHT - mirror the schematic along its local z axis </li>
|
||||
* </ul>
|
||||
*/
|
||||
public final Setting<Mirror> buildSchematicMirror = new Setting<>(Mirror.NONE);
|
||||
|
||||
/**
|
||||
* The fallback used by the build command when no extension is specified. This may be useful if schematics of a
|
||||
* particular format are used often, and the user does not wish to have to specify the extension with every usage.
|
||||
@@ -1174,6 +1242,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Integer> followRadius = new Setting<>(3);
|
||||
|
||||
/**
|
||||
* The maximum distance to the entity you're following
|
||||
*/
|
||||
public final Setting<Integer> followTargetMaxDistance = new Setting<>(0);
|
||||
|
||||
/**
|
||||
* Turn this on if your exploration filter is enormous, you don't want it to check if it's done,
|
||||
* and you are just fine with it just hanging on completion
|
||||
@@ -1209,8 +1282,12 @@ public final class Settings {
|
||||
*/
|
||||
@JavaOnly
|
||||
public final Setting<Consumer<Component>> logger = new Setting<>((msg) -> {
|
||||
final GuiMessageTag tag = useMessageTag.value ? Helper.MESSAGE_TAG : null;
|
||||
Minecraft.getInstance().gui.getChat().addMessage(msg, null, tag);
|
||||
try {
|
||||
final GuiMessageTag tag = useMessageTag.value ? Helper.MESSAGE_TAG : null;
|
||||
Minecraft.getInstance().gui.getChat().addMessage(msg, null, tag);
|
||||
} catch (Throwable t) {
|
||||
LOGGER.warn("Failed to log message to chat: " + msg.getString(), t);
|
||||
}
|
||||
});
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,20 +23,14 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum BlockById implements IDatatypeFor<Block> {
|
||||
INSTANCE;
|
||||
|
||||
/**
|
||||
* Matches (domain:)?name? where domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ respectively.
|
||||
*/
|
||||
private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?[a-z0-9/_.-]*");
|
||||
|
||||
@Override
|
||||
public Block get(IDatatypeContext ctx) throws CommandException {
|
||||
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
|
||||
ResourceLocation id = ResourceLocation.parse(ctx.getConsumer().getString());
|
||||
Block block;
|
||||
if ((block = BuiltInRegistries.BLOCK.getOptional(id).orElse(null)) == null) {
|
||||
throw new IllegalArgumentException("no block found by that id");
|
||||
@@ -48,10 +42,6 @@ public enum BlockById implements IDatatypeFor<Block> {
|
||||
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
|
||||
String arg = ctx.getConsumer().getString();
|
||||
|
||||
if (!PATTERN.matcher(arg).matches()) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
return new TabCompleteHelper()
|
||||
.append(
|
||||
BuiltInRegistries.BLOCK.keySet()
|
||||
|
||||
@@ -30,7 +30,7 @@ public enum EntityClassById implements IDatatypeFor<EntityType> {
|
||||
|
||||
@Override
|
||||
public EntityType get(IDatatypeContext ctx) throws CommandException {
|
||||
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
|
||||
ResourceLocation id = ResourceLocation.parse(ctx.getConsumer().getString());
|
||||
EntityType entity;
|
||||
if ((entity = BuiltInRegistries.ENTITY_TYPE.getOptional(id).orElse(null)) == null) {
|
||||
throw new IllegalArgumentException("no entity found by that id");
|
||||
|
||||
@@ -77,7 +77,7 @@ public enum ForBlockOptionalMeta implements IDatatypeFor<BlockOptionalMeta> {
|
||||
properties = parts[1];
|
||||
}
|
||||
|
||||
Block block = BuiltInRegistries.BLOCK.getOptional(new ResourceLocation(blockId)).orElse(null);
|
||||
Block block = BuiltInRegistries.BLOCK.getOptional(ResourceLocation.parse(blockId)).orElse(null);
|
||||
if (block == null) {
|
||||
// This block doesn't exist so there's no properties to complete.
|
||||
return Stream.empty();
|
||||
|
||||
53
src/api/java/baritone/api/command/datatypes/ItemById.java
Normal file
53
src/api/java/baritone/api/command/datatypes/ItemById.java
Normal file
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* 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.command.datatypes;
|
||||
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum ItemById implements IDatatypeFor<Item> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public Item get(IDatatypeContext ctx) throws CommandException {
|
||||
ResourceLocation id = ResourceLocation.parse(ctx.getConsumer().getString());
|
||||
Item item;
|
||||
if ((item = BuiltInRegistries.ITEM.getOptional(id).orElse(null)) == null) {
|
||||
throw new IllegalArgumentException("No item found by that id");
|
||||
}
|
||||
return item;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
|
||||
return new TabCompleteHelper()
|
||||
.append(
|
||||
BuiltInRegistries.BLOCK.keySet()
|
||||
.stream()
|
||||
.map(ResourceLocation::toString)
|
||||
)
|
||||
.filterPrefixNamespaced(ctx.getConsumer().getString())
|
||||
.sortAlphabetically()
|
||||
.stream();
|
||||
}
|
||||
}
|
||||
@@ -212,7 +212,12 @@ public class TabCompleteHelper {
|
||||
* @return This {@link TabCompleteHelper}
|
||||
*/
|
||||
public TabCompleteHelper filterPrefixNamespaced(String prefix) {
|
||||
return filterPrefix(new ResourceLocation(prefix).toString());
|
||||
ResourceLocation loc = ResourceLocation.tryParse(prefix);
|
||||
if (loc == null) {
|
||||
stream = Stream.empty();
|
||||
return this;
|
||||
}
|
||||
return filterPrefix(loc.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -44,7 +44,7 @@ public class GoalRunAway implements Goal {
|
||||
|
||||
public GoalRunAway(double distance, Integer maintainY, BlockPos... from) {
|
||||
if (from.length == 0) {
|
||||
throw new IllegalArgumentException();
|
||||
throw new IllegalArgumentException("Positions to run away from must not be empty");
|
||||
}
|
||||
this.from = from;
|
||||
this.distanceSq = (int) (distance * distance);
|
||||
|
||||
@@ -24,6 +24,7 @@ import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -74,4 +75,17 @@ public interface IBuilderProcess extends IBaritoneProcess {
|
||||
* cause it to give up. This is updated every tick, but only while the builder process is active.
|
||||
*/
|
||||
List<BlockState> getApproxPlaceable();
|
||||
/**
|
||||
* Returns the lower bound of the current mining layer if mineInLayers is true.
|
||||
* If mineInLayers is false, this will return an empty optional.
|
||||
* @return The lower bound of the current mining layer
|
||||
*/
|
||||
Optional<Integer> getMinLayer();
|
||||
|
||||
/**
|
||||
* Returns the upper bound of the current mining layer if mineInLayers is true.
|
||||
* If mineInLayers is false, this will return an empty optional.
|
||||
* @return The upper bound of the current mining layer
|
||||
*/
|
||||
Optional<Integer> getMaxLayer();
|
||||
}
|
||||
|
||||
@@ -17,9 +17,11 @@
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -34,6 +36,13 @@ public interface IFollowProcess extends IBaritoneProcess {
|
||||
*/
|
||||
void follow(Predicate<Entity> filter);
|
||||
|
||||
/**
|
||||
* Try to pick up any items matching this predicate
|
||||
*
|
||||
* @param filter the predicate
|
||||
*/
|
||||
void pickup(Predicate<ItemStack> filter);
|
||||
|
||||
/**
|
||||
* @return The entities that are currently being followed. null if not currently following, empty if nothing matches the predicate
|
||||
*/
|
||||
|
||||
@@ -21,6 +21,7 @@ import baritone.api.command.registry.Registry;
|
||||
import baritone.api.schematic.format.ISchematicFormat;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -41,4 +42,9 @@ public interface ISchematicSystem {
|
||||
* @return The corresponding format for the file, {@link Optional#empty()} if no candidates were found.
|
||||
*/
|
||||
Optional<ISchematicFormat> getByFile(File file);
|
||||
|
||||
/**
|
||||
* @return A list of file extensions used by supported formats
|
||||
*/
|
||||
List<String> getFileExtensions();
|
||||
}
|
||||
|
||||
114
src/api/java/baritone/api/schematic/MirroredSchematic.java
Normal file
114
src/api/java/baritone/api/schematic/MirroredSchematic.java
Normal file
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* 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.schematic;
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class MirroredSchematic implements ISchematic {
|
||||
|
||||
private final ISchematic schematic;
|
||||
private final Mirror mirror;
|
||||
|
||||
public MirroredSchematic(ISchematic schematic, Mirror mirror) {
|
||||
this.schematic = schematic;
|
||||
this.mirror = mirror;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
|
||||
return schematic.inSchematic(
|
||||
mirrorX(x, widthX(), mirror),
|
||||
y,
|
||||
mirrorZ(z, lengthZ(), mirror),
|
||||
mirror(currentState, mirror)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
|
||||
return mirror(schematic.desiredState(
|
||||
mirrorX(x, widthX(), mirror),
|
||||
y,
|
||||
mirrorZ(z, lengthZ(), mirror),
|
||||
mirror(current, mirror),
|
||||
mirror(approxPlaceable, mirror)
|
||||
), mirror);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
schematic.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int widthX() {
|
||||
return schematic.widthX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int heightY() {
|
||||
return schematic.heightY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lengthZ() {
|
||||
return schematic.lengthZ();
|
||||
}
|
||||
|
||||
private static int mirrorX(int x, int sizeX, Mirror mirror) {
|
||||
switch (mirror) {
|
||||
case NONE:
|
||||
case LEFT_RIGHT:
|
||||
return x;
|
||||
case FRONT_BACK:
|
||||
return sizeX - x - 1;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown mirror");
|
||||
}
|
||||
|
||||
private static int mirrorZ(int z, int sizeZ, Mirror mirror) {
|
||||
switch (mirror) {
|
||||
case NONE:
|
||||
case FRONT_BACK:
|
||||
return z;
|
||||
case LEFT_RIGHT:
|
||||
return sizeZ - z - 1;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown mirror");
|
||||
}
|
||||
|
||||
private static BlockState mirror(BlockState state, Mirror mirror) {
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
return state.mirror(mirror);
|
||||
}
|
||||
|
||||
private static List<BlockState> mirror(List<BlockState> states, Mirror mirror) {
|
||||
if (states == null) {
|
||||
return null;
|
||||
}
|
||||
return states.stream()
|
||||
.map(s -> mirror(s, mirror))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
136
src/api/java/baritone/api/schematic/RotatedSchematic.java
Normal file
136
src/api/java/baritone/api/schematic/RotatedSchematic.java
Normal file
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* 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.schematic;
|
||||
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class RotatedSchematic implements ISchematic {
|
||||
|
||||
private final ISchematic schematic;
|
||||
private final Rotation rotation;
|
||||
private final Rotation inverseRotation;
|
||||
|
||||
public RotatedSchematic(ISchematic schematic, Rotation rotation) {
|
||||
this.schematic = schematic;
|
||||
this.rotation = rotation;
|
||||
// I don't think a 14 line switch would improve readability
|
||||
this.inverseRotation = rotation.getRotated(rotation).getRotated(rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
|
||||
return schematic.inSchematic(
|
||||
rotateX(x, z, widthX(), lengthZ(), inverseRotation),
|
||||
y,
|
||||
rotateZ(x, z, widthX(), lengthZ(), inverseRotation),
|
||||
rotate(currentState, inverseRotation)
|
||||
);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
|
||||
return rotate(schematic.desiredState(
|
||||
rotateX(x, z, widthX(), lengthZ(), inverseRotation),
|
||||
y,
|
||||
rotateZ(x, z, widthX(), lengthZ(), inverseRotation),
|
||||
rotate(current, inverseRotation),
|
||||
rotate(approxPlaceable, inverseRotation)
|
||||
), rotation);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
schematic.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int widthX() {
|
||||
return flipsCoordinates(rotation) ? schematic.lengthZ() : schematic.widthX();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int heightY() {
|
||||
return schematic.heightY();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lengthZ() {
|
||||
return flipsCoordinates(rotation) ? schematic.widthX() : schematic.lengthZ();
|
||||
}
|
||||
|
||||
/**
|
||||
* Wether {@code rotation} swaps the x and z components
|
||||
*/
|
||||
private static boolean flipsCoordinates(Rotation rotation) {
|
||||
return rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90;
|
||||
}
|
||||
|
||||
/**
|
||||
* The x component of x,y after applying the rotation
|
||||
*/
|
||||
private static int rotateX(int x, int z, int sizeX, int sizeZ, Rotation rotation) {
|
||||
switch (rotation) {
|
||||
case NONE:
|
||||
return x;
|
||||
case CLOCKWISE_90:
|
||||
return sizeZ - z - 1;
|
||||
case CLOCKWISE_180:
|
||||
return sizeX - x - 1;
|
||||
case COUNTERCLOCKWISE_90:
|
||||
return z;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown rotation");
|
||||
}
|
||||
|
||||
/**
|
||||
* The z component of x,y after applying the rotation
|
||||
*/
|
||||
private static int rotateZ(int x, int z, int sizeX, int sizeZ, Rotation rotation) {
|
||||
switch (rotation) {
|
||||
case NONE:
|
||||
return z;
|
||||
case CLOCKWISE_90:
|
||||
return x;
|
||||
case CLOCKWISE_180:
|
||||
return sizeZ - z - 1;
|
||||
case COUNTERCLOCKWISE_90:
|
||||
return sizeX - x - 1;
|
||||
}
|
||||
throw new IllegalArgumentException("Unknown rotation");
|
||||
}
|
||||
|
||||
private static BlockState rotate(BlockState state, Rotation rotation) {
|
||||
if (state == null) {
|
||||
return null;
|
||||
}
|
||||
return state.rotate(rotation);
|
||||
}
|
||||
|
||||
private static List<BlockState> rotate(List<BlockState> states, Rotation rotation) {
|
||||
if (states == null) {
|
||||
return null;
|
||||
}
|
||||
return states.stream()
|
||||
.map(s -> rotate(s, rotation))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
}
|
||||
@@ -23,6 +23,7 @@ import baritone.api.schematic.IStaticSchematic;
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* The base of a {@link ISchematic} file format
|
||||
@@ -42,4 +43,9 @@ public interface ISchematicFormat {
|
||||
* @return Whether or not the specified file matches this schematic format
|
||||
*/
|
||||
boolean isFileType(File file);
|
||||
|
||||
/**
|
||||
* @return A list of file extensions used by this format
|
||||
*/
|
||||
List<String> getFileExtensions();
|
||||
}
|
||||
|
||||
@@ -18,26 +18,38 @@
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.utils.accessor.IItemStack;
|
||||
import baritone.api.utils.accessor.ILootTable;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import io.netty.util.concurrent.ThreadPerTaskExecutor;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.commands.Commands;
|
||||
import net.minecraft.core.LayeredRegistryAccess;
|
||||
import net.minecraft.core.RegistryAccess;
|
||||
import net.minecraft.resources.RegistryDataLoader;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.RegistryLayer;
|
||||
import net.minecraft.server.ReloadableServerRegistries;
|
||||
import net.minecraft.server.ReloadableServerResources;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.server.level.progress.ChunkProgressListener;
|
||||
import net.minecraft.server.packs.PackType;
|
||||
import net.minecraft.server.packs.VanillaPackResources;
|
||||
import net.minecraft.server.packs.repository.BuiltInPackSource;
|
||||
import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.server.packs.repository.ServerPacksSource;
|
||||
import net.minecraft.server.packs.resources.CloseableResourceManager;
|
||||
import net.minecraft.server.packs.resources.MultiPackResourceManager;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.server.packs.resources.ResourceManager;
|
||||
import net.minecraft.world.RandomSequences;
|
||||
import net.minecraft.world.flag.FeatureFlagSet;
|
||||
import net.minecraft.world.flag.FeatureFlags;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.CustomSpawner;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
@@ -48,8 +60,8 @@ import net.minecraft.world.level.storage.LevelStorageSource;
|
||||
import net.minecraft.world.level.storage.ServerLevelData;
|
||||
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.LootDataManager;
|
||||
import net.minecraft.world.level.storage.loot.LootParams;
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
|
||||
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@@ -75,7 +87,6 @@ public final class BlockOptionalMeta {
|
||||
private final Set<BlockState> blockstates;
|
||||
private final ImmutableSet<Integer> stateHashes;
|
||||
private final ImmutableSet<Integer> stackHashes;
|
||||
private static LootDataManager lootTables;
|
||||
private static Map<Block, List<Item>> drops = new HashMap<>();
|
||||
|
||||
public BlockOptionalMeta(@Nonnull Block block) {
|
||||
@@ -218,43 +229,21 @@ public final class BlockOptionalMeta {
|
||||
return null;
|
||||
}
|
||||
|
||||
public static LootDataManager getManager() {
|
||||
if (lootTables == null) {
|
||||
MultiPackResourceManager resources = new MultiPackResourceManager(PackType.SERVER_DATA, List.of(getVanillaServerPack()));
|
||||
ReloadableResourceManager resourceManager = new ReloadableResourceManager(PackType.SERVER_DATA);
|
||||
lootTables = new LootDataManager();
|
||||
resourceManager.registerReloadListener(lootTables);
|
||||
try {
|
||||
resourceManager.createReload(new ThreadPerTaskExecutor(Thread::new), new ThreadPerTaskExecutor(Thread::new), CompletableFuture.completedFuture(Unit.INSTANCE), resources.listPacks().toList()).done().get();
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
}
|
||||
return lootTables;
|
||||
}
|
||||
|
||||
private static synchronized List<Item> drops(Block b) {
|
||||
return drops.computeIfAbsent(b, block -> {
|
||||
ResourceLocation lootTableLocation = block.getLootTable();
|
||||
if (lootTableLocation == BuiltInLootTables.EMPTY) {
|
||||
ResourceLocation lootTableLocation = block.getLootTable().location();
|
||||
if (lootTableLocation.equals(BuiltInLootTables.EMPTY.location())) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
List<Item> items = new ArrayList<>();
|
||||
try {
|
||||
ServerLevel lv2 = ServerLevelStub.fastCreate();
|
||||
|
||||
getManager().getLootTable(lootTableLocation).getRandomItemsRaw(
|
||||
new LootContext.Builder(
|
||||
new LootParams.Builder(ServerLevelStub.fastCreate())
|
||||
.withParameter(LootContextParams.ORIGIN, Vec3.atLowerCornerOf(BlockPos.ZERO))
|
||||
.withParameter(LootContextParams.TOOL, ItemStack.EMPTY)
|
||||
.withOptionalParameter(LootContextParams.BLOCK_ENTITY, null)
|
||||
.withParameter(LootContextParams.BLOCK_STATE, block.defaultBlockState())
|
||||
.create(LootContextParamSets.BLOCK)
|
||||
).withOptionalRandomSeed(1L)
|
||||
.create(null),
|
||||
stack -> items.add(stack.getItem())
|
||||
);
|
||||
LootParams.Builder lv5 = new LootParams.Builder(lv2)
|
||||
.withParameter(LootContextParams.ORIGIN, Vec3.ZERO)
|
||||
.withParameter(LootContextParams.BLOCK_STATE, b.defaultBlockState())
|
||||
.withParameter(LootContextParams.TOOL, new ItemStack(Items.NETHERITE_PICKAXE, 1));
|
||||
getDrops(block, lv5).stream().map(ItemStack::getItem).forEach(items::add);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
@@ -263,9 +252,22 @@ public final class BlockOptionalMeta {
|
||||
});
|
||||
}
|
||||
|
||||
private static class ServerLevelStub extends ServerLevel {
|
||||
private static List<ItemStack> getDrops(Block state, LootParams.Builder params) {
|
||||
ResourceKey<LootTable> lv = state.getLootTable();
|
||||
if (lv == BuiltInLootTables.EMPTY) {
|
||||
return Collections.emptyList();
|
||||
} else {
|
||||
LootParams lv2 = params.withParameter(LootContextParams.BLOCK_STATE, state.defaultBlockState()).create(LootContextParamSets.BLOCK);
|
||||
ServerLevelStub lv3 = (ServerLevelStub) lv2.getLevel();
|
||||
LootTable lv4 = lv3.holder().getLootTable(lv);
|
||||
return((ILootTable) lv4).invokeGetRandomItems(new LootContext.Builder(lv2).withOptionalRandomSeed(1).create(null));
|
||||
}
|
||||
}
|
||||
|
||||
public static class ServerLevelStub extends ServerLevel {
|
||||
private static Minecraft client = Minecraft.getInstance();
|
||||
private static Unsafe unsafe = getUnsafe();
|
||||
private static CompletableFuture<RegistryAccess> registryAccess = load();
|
||||
|
||||
public ServerLevelStub(MinecraftServer $$0, Executor $$1, LevelStorageSource.LevelStorageAccess $$2, ServerLevelData $$3, ResourceKey<Level> $$4, LevelStem $$5, ChunkProgressListener $$6, boolean $$7, long $$8, List<CustomSpawner> $$9, boolean $$10, @Nullable RandomSequences $$11) {
|
||||
super($$0, $$1, $$2, $$3, $$4, $$5, $$6, $$7, $$8, $$9, $$10, $$11);
|
||||
@@ -285,6 +287,15 @@ public final class BlockOptionalMeta {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public RegistryAccess registryAccess() {
|
||||
return registryAccess.join();
|
||||
}
|
||||
|
||||
public ReloadableServerRegistries.Holder holder() {
|
||||
return new ReloadableServerRegistries.Holder(registryAccess().freeze());
|
||||
}
|
||||
|
||||
public static Unsafe getUnsafe() {
|
||||
try {
|
||||
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
|
||||
@@ -295,5 +306,45 @@ public final class BlockOptionalMeta {
|
||||
}
|
||||
}
|
||||
|
||||
public static CompletableFuture<RegistryAccess> load() {
|
||||
PackRepository packRepository = Minecraft.getInstance().getResourcePackRepository();
|
||||
CloseableResourceManager closeableResourceManager = new MultiPackResourceManager(
|
||||
PackType.SERVER_DATA,
|
||||
List.of(packRepository.getPack(BuiltInPackSource.VANILLA_ID).open())
|
||||
);
|
||||
LayeredRegistryAccess<RegistryLayer> layeredRegistryAccess = loadAndReplaceLayer(
|
||||
closeableResourceManager, RegistryLayer.createRegistryAccess(), RegistryLayer.WORLDGEN, RegistryDataLoader.WORLDGEN_REGISTRIES
|
||||
);
|
||||
return ReloadableServerResources.loadResources(
|
||||
closeableResourceManager,
|
||||
layeredRegistryAccess,
|
||||
FeatureFlags.VANILLA_SET,
|
||||
Commands.CommandSelection.INTEGRATED,
|
||||
2,
|
||||
Runnable::run,
|
||||
Minecraft.getInstance()
|
||||
).thenApply(reloadableServerResources -> reloadableServerResources.fullRegistries().get());
|
||||
}
|
||||
|
||||
private static LayeredRegistryAccess<RegistryLayer> loadAndReplaceLayer(
|
||||
ResourceManager resourceManager,
|
||||
LayeredRegistryAccess<RegistryLayer> registryAccess,
|
||||
RegistryLayer registryLayer,
|
||||
List<RegistryDataLoader.RegistryData<?>> registryData
|
||||
) {
|
||||
RegistryAccess.Frozen frozen = loadLayer(resourceManager, registryAccess, registryLayer, registryData);
|
||||
return registryAccess.replaceFrom(registryLayer, frozen);
|
||||
}
|
||||
|
||||
private static RegistryAccess.Frozen loadLayer(
|
||||
ResourceManager resourceManager,
|
||||
LayeredRegistryAccess<RegistryLayer> registryAccess,
|
||||
RegistryLayer registryLayer,
|
||||
List<RegistryDataLoader.RegistryData<?>> registryData
|
||||
) {
|
||||
RegistryAccess.Frozen frozen = registryAccess.getAccessForLoading(registryLayer);
|
||||
return RegistryDataLoader.load(resourceManager, frozen, registryData);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,14 @@ public interface IPlayerContext {
|
||||
return new Rotation(player().getYRot(), player().getXRot());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the player's eye height, taking into account whether or not the player is sneaking.
|
||||
*
|
||||
* @param ifSneaking Whether or not the player is sneaking
|
||||
* @return The player's eye height
|
||||
* @deprecated Use entity.getEyeHeight(Pose.CROUCHING) instead
|
||||
*/
|
||||
@Deprecated
|
||||
static double eyeHeight(boolean ifSneaking) {
|
||||
return ifSneaking ? 1.27 : 1.62;
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.Pose;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
@@ -62,6 +63,6 @@ public final class RayTraceUtils {
|
||||
}
|
||||
|
||||
public static Vec3 inferSneakingEyePosition(Entity entity) {
|
||||
return new Vec3(entity.getX(), entity.getY() + IPlayerContext.eyeHeight(true), entity.getZ());
|
||||
return new Vec3(entity.getX(), entity.getY() + entity.getEyeHeight(Pose.CROUCHING), entity.getZ());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,6 +27,9 @@ import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
@@ -80,6 +83,10 @@ public class SettingsUtil {
|
||||
|
||||
String settingName = matcher.group("setting").toLowerCase();
|
||||
String settingValue = matcher.group("value");
|
||||
// TODO remove soonish
|
||||
if ("allowjumpat256".equals(settingName)) {
|
||||
settingName = "allowjumpatbuildlimit";
|
||||
}
|
||||
try {
|
||||
parseAndApply(settings, settingName, settingValue);
|
||||
} catch (Exception ex) {
|
||||
@@ -149,7 +156,7 @@ public class SettingsUtil {
|
||||
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
|
||||
}
|
||||
|
||||
return io.toString(new ParserContext(setting), value);
|
||||
return io.toString(setting.getType(), value);
|
||||
}
|
||||
|
||||
public static String settingValueToString(Settings.Setting setting) throws IllegalArgumentException {
|
||||
@@ -196,7 +203,7 @@ public class SettingsUtil {
|
||||
}
|
||||
Class intendedType = setting.getValueClass();
|
||||
ISettingParser ioMethod = Parser.getParser(setting.getType());
|
||||
Object parsed = ioMethod.parse(new ParserContext(setting), settingValue);
|
||||
Object parsed = ioMethod.parse(setting.getType(), settingValue);
|
||||
if (!intendedType.isInstance(parsed)) {
|
||||
throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass());
|
||||
}
|
||||
@@ -205,26 +212,13 @@ public class SettingsUtil {
|
||||
|
||||
private interface ISettingParser<T> {
|
||||
|
||||
T parse(ParserContext context, String raw);
|
||||
T parse(Type type, String raw);
|
||||
|
||||
String toString(ParserContext context, T value);
|
||||
String toString(Type type, T value);
|
||||
|
||||
boolean accepts(Type type);
|
||||
}
|
||||
|
||||
private static class ParserContext {
|
||||
|
||||
private final Settings.Setting<?> setting;
|
||||
|
||||
private ParserContext(Settings.Setting<?> setting) {
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
private Settings.Setting<?> getSetting() {
|
||||
return this.setting;
|
||||
}
|
||||
}
|
||||
|
||||
private enum Parser implements ISettingParser {
|
||||
|
||||
DOUBLE(Double.class, Double::parseDouble),
|
||||
@@ -233,7 +227,8 @@ public class SettingsUtil {
|
||||
FLOAT(Float.class, Float::parseFloat),
|
||||
LONG(Long.class, Long::parseLong),
|
||||
STRING(String.class, String::new),
|
||||
DIRECTION(Direction.class, Direction::byName),
|
||||
MIRROR(Mirror.class, Mirror::valueOf, Mirror::name),
|
||||
ROTATION(Rotation.class, Rotation::valueOf, Rotation::name),
|
||||
COLOR(
|
||||
Color.class,
|
||||
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
|
||||
@@ -251,26 +246,26 @@ public class SettingsUtil {
|
||||
),
|
||||
ITEM(
|
||||
Item.class,
|
||||
str -> BuiltInRegistries.ITEM.get(new ResourceLocation(str.trim())), // TODO this now returns AIR on failure instead of null, is that an issue?
|
||||
str -> BuiltInRegistries.ITEM.get(ResourceLocation.parse(str.trim())), // TODO this now returns AIR on failure instead of null, is that an issue?
|
||||
item -> BuiltInRegistries.ITEM.getKey(item).toString()
|
||||
),
|
||||
LIST() {
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(type);
|
||||
public Object parse(Type type, String raw) {
|
||||
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(elementType);
|
||||
return Stream.of(raw.split(","))
|
||||
.map(s -> parser.parse(context, s))
|
||||
.map(s -> parser.parse(elementType, s))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(type);
|
||||
public String toString(Type type, Object value) {
|
||||
Type elementType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(elementType);
|
||||
|
||||
return ((List<?>) value).stream()
|
||||
.map(o -> parser.toString(context, o))
|
||||
.map(o -> parser.toString(elementType, o))
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@@ -281,26 +276,26 @@ public class SettingsUtil {
|
||||
},
|
||||
MAPPING() {
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
Type keyType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[1];
|
||||
public Object parse(Type type, String raw) {
|
||||
Type keyType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) type).getActualTypeArguments()[1];
|
||||
Parser keyParser = Parser.getParser(keyType);
|
||||
Parser valueParser = Parser.getParser(valueType);
|
||||
|
||||
return Stream.of(raw.split(",(?=[^,]*->)"))
|
||||
.map(s -> s.split("->"))
|
||||
.collect(Collectors.toMap(s -> keyParser.parse(context, s[0]), s -> valueParser.parse(context, s[1])));
|
||||
.collect(Collectors.toMap(s -> keyParser.parse(keyType, s[0]), s -> valueParser.parse(valueType, s[1])));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
Type keyType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[1];
|
||||
public String toString(Type type, Object value) {
|
||||
Type keyType = ((ParameterizedType) type).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) type).getActualTypeArguments()[1];
|
||||
Parser keyParser = Parser.getParser(keyType);
|
||||
Parser valueParser = Parser.getParser(valueType);
|
||||
|
||||
return ((Map<?, ?>) value).entrySet().stream()
|
||||
.map(o -> keyParser.toString(context, o.getKey()) + "->" + valueParser.toString(context, o.getValue()))
|
||||
.map(o -> keyParser.toString(keyType, o.getKey()) + "->" + valueParser.toString(valueType, o.getValue()))
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@@ -331,14 +326,14 @@ public class SettingsUtil {
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
public Object parse(Type type, String raw) {
|
||||
Object parsed = this.parser.apply(raw);
|
||||
Objects.requireNonNull(parsed);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
public String toString(Type type, Object value) {
|
||||
return this.toString.apply(value);
|
||||
}
|
||||
|
||||
|
||||
28
src/api/java/baritone/api/utils/accessor/ILootTable.java
Normal file
28
src/api/java/baritone/api/utils/accessor/ILootTable.java
Normal file
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* 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.accessor;
|
||||
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
|
||||
public interface ILootTable {
|
||||
|
||||
ObjectArrayList<ItemStack> invokeGetRandomItems(LootContext context);
|
||||
|
||||
}
|
||||
@@ -47,7 +47,7 @@ public class BaritoneToast implements Toast {
|
||||
|
||||
|
||||
//TODO: check
|
||||
gui.blit(new ResourceLocation("textures/gui/toasts.png"), 0, 0, 0, 32, 160, 32);
|
||||
gui.blit(ResourceLocation.parse("textures/gui/toasts.png"), 0, 0, 0, 32, 160, 32);
|
||||
|
||||
if (this.subtitle == null) {
|
||||
gui.drawString(toastGui.getMinecraft().font, this.title, 18, 12, -11534256);
|
||||
|
||||
@@ -27,17 +27,37 @@ import net.minecraft.client.KeyMapping;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.entity.player.Abilities;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Unique;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Group;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.lang.invoke.MethodHandle;
|
||||
import java.lang.invoke.MethodHandles;
|
||||
import java.lang.invoke.MethodType;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018
|
||||
*/
|
||||
@Mixin(LocalPlayer.class)
|
||||
public class MixinClientPlayerEntity {
|
||||
@Unique
|
||||
private static final MethodHandle MAY_FLY = baritone$resolveMayFly();
|
||||
|
||||
@Unique
|
||||
private static MethodHandle baritone$resolveMayFly() {
|
||||
try {
|
||||
var lookup = MethodHandles.publicLookup();
|
||||
return lookup.findVirtual(LocalPlayer.class, "mayFly", MethodType.methodType(boolean.class));
|
||||
} catch (NoSuchMethodException e) {
|
||||
return null;
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "tick",
|
||||
@@ -61,6 +81,7 @@ public class MixinClientPlayerEntity {
|
||||
target = "net/minecraft/world/entity/player/Abilities.mayfly:Z"
|
||||
)
|
||||
)
|
||||
@Group(name = "mayFly", min = 1, max = 1)
|
||||
private boolean isAllowFlying(Abilities capabilities) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((LocalPlayer) (Object) this);
|
||||
if (baritone == null) {
|
||||
@@ -69,6 +90,22 @@ public class MixinClientPlayerEntity {
|
||||
return !baritone.getPathingBehavior().isPathing() && capabilities.mayfly;
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;mayFly()Z"
|
||||
)
|
||||
)
|
||||
@Group(name = "mayFly", min = 1, max = 1)
|
||||
private boolean onMayFlyNeoforge(LocalPlayer instance) throws Throwable {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((LocalPlayer) (Object) this);
|
||||
if (baritone == null) {
|
||||
return (boolean) MAY_FLY.invokeExact(instance);
|
||||
}
|
||||
return !baritone.getPathingBehavior().isPathing() && (boolean) MAY_FLY.invokeExact(instance);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "aiStep",
|
||||
at = @At(
|
||||
|
||||
@@ -19,41 +19,28 @@ package baritone.launch.mixins;
|
||||
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
import net.minecraft.server.MinecraftServer;
|
||||
import net.minecraft.server.ReloadableServerRegistries;
|
||||
import net.minecraft.server.level.ServerLevel;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.LootDataManager;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(LootContext.Builder.class)
|
||||
public class MixinLootContext {
|
||||
public abstract class MixinLootContextBuilder {
|
||||
|
||||
@Redirect(
|
||||
method = "create",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/server/level/ServerLevel.getServer()Lnet/minecraft/server/MinecraftServer;"
|
||||
)
|
||||
)
|
||||
private MinecraftServer getServer(ServerLevel world) {
|
||||
if (world == null) {
|
||||
return null;
|
||||
@Shadow public abstract ServerLevel getLevel();
|
||||
|
||||
@Redirect(method = "create", at = @At(value = "INVOKE", target = "Lnet/minecraft/server/MinecraftServer;reloadableRegistries()Lnet/minecraft/server/ReloadableServerRegistries$Holder;"))
|
||||
private ReloadableServerRegistries.Holder create(MinecraftServer instance) {
|
||||
if (instance != null) {
|
||||
return instance.reloadableRegistries();
|
||||
}
|
||||
return world.getServer();
|
||||
if (getLevel() instanceof BlockOptionalMeta.ServerLevelStub sls) {
|
||||
return sls.holder();
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "create",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/server/MinecraftServer;getLootData()Lnet/minecraft/world/level/storage/loot/LootDataManager;"
|
||||
)
|
||||
)
|
||||
private LootDataManager getLootTableManager(MinecraftServer server) {
|
||||
if (server == null) {
|
||||
return BlockOptionalMeta.getManager();
|
||||
}
|
||||
return server.getLootData();
|
||||
}
|
||||
}
|
||||
34
src/launch/java/baritone/launch/mixins/MixinLootTable.java
Normal file
34
src/launch/java/baritone/launch/mixins/MixinLootTable.java
Normal file
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.api.utils.accessor.ILootTable;
|
||||
import it.unimi.dsi.fastutil.objects.ObjectArrayList;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.storage.loot.LootContext;
|
||||
import net.minecraft.world.level.storage.loot.LootTable;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
@Mixin(LootTable.class)
|
||||
public abstract class MixinLootTable implements ILootTable {
|
||||
|
||||
@Invoker
|
||||
public abstract ObjectArrayList<ItemStack> invokeGetRandomItems(LootContext context);
|
||||
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.WorldEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.screens.ReceivingLevelScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
@@ -130,7 +131,7 @@ public class MixinMinecraft {
|
||||
method = "setLevel",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(ClientLevel world, CallbackInfo ci) {
|
||||
private void preLoadWorld(ClientLevel world, ReceivingLevelScreen.Reason arg2, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.level == null && world == null) {
|
||||
return;
|
||||
@@ -150,7 +151,7 @@ public class MixinMinecraft {
|
||||
method = "setLevel",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(ClientLevel world, CallbackInfo ci) {
|
||||
private void postLoadWorld(ClientLevel world, ReceivingLevelScreen.Reason arg2, CallbackInfo ci) {
|
||||
// still fire event for both null, as that means we've just finished exiting a world
|
||||
|
||||
// mc.world changing is only the primary baritone
|
||||
|
||||
@@ -31,6 +31,10 @@ public abstract class MixinPlayerController implements IPlayerControllerMP {
|
||||
@Override
|
||||
public abstract void setIsHittingBlock(boolean isHittingBlock);
|
||||
|
||||
@Accessor("isDestroying")
|
||||
@Override
|
||||
public abstract boolean isHittingBlock();
|
||||
|
||||
@Accessor("destroyBlockPos")
|
||||
@Override
|
||||
public abstract BlockPos getCurrentBlock();
|
||||
@@ -38,4 +42,8 @@ public abstract class MixinPlayerController implements IPlayerControllerMP {
|
||||
@Invoker("ensureHasSentCarriedItem")
|
||||
@Override
|
||||
public abstract void callSyncCurrentPlayItem();
|
||||
|
||||
@Accessor("destroyDelay")
|
||||
@Override
|
||||
public abstract void setDestroyDelay(int destroyDelay);
|
||||
}
|
||||
|
||||
@@ -21,25 +21,22 @@ import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.utils.accessor.IGuiScreen;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.Style;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Invoker;
|
||||
|
||||
import java.net.URI;
|
||||
import net.minecraft.client.gui.screens.Screen;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
import java.net.URI;
|
||||
|
||||
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
@Mixin(Screen.class)
|
||||
public abstract class MixinScreen implements IGuiScreen {
|
||||
|
||||
@Override
|
||||
@Invoker("openLink")
|
||||
public abstract void openLinkInvoker(URI url);
|
||||
|
||||
|
||||
//TODO: switch to enum extention with mixin 9.0 or whenever Mumfrey gets around to it
|
||||
@Inject(at = @At(value = "INVOKE", target = "Lorg/slf4j/Logger;error(Ljava/lang/String;Ljava/lang/Object;)V", remap = false, ordinal = 1), method = "handleComponentClicked", cancellable = true)
|
||||
public void handleCustomClickEvent(Style style, CallbackInfoReturnable<Boolean> cir) {
|
||||
@@ -47,9 +44,13 @@ public abstract class MixinScreen implements IGuiScreen {
|
||||
if (clickEvent == null) {
|
||||
return;
|
||||
}
|
||||
String command = clickEvent.getValue();
|
||||
if (command == null || !command.startsWith(FORCE_COMMAND_PREFIX)) {
|
||||
return;
|
||||
}
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
|
||||
if (baritone != null) {
|
||||
baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(clickEvent.getValue()));
|
||||
baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(command));
|
||||
}
|
||||
cir.setReturnValue(true);
|
||||
cir.cancel();
|
||||
|
||||
@@ -22,6 +22,7 @@ import baritone.api.IBaritone;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Camera;
|
||||
import net.minecraft.client.DeltaTracker;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.LevelRenderer;
|
||||
import net.minecraft.client.renderer.LightTexture;
|
||||
@@ -41,12 +42,13 @@ public class MixinWorldRenderer {
|
||||
|
||||
@Inject(
|
||||
method = "renderLevel",
|
||||
at = @At("RETURN"),
|
||||
locals = LocalCapture.CAPTURE_FAILSOFT
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void onStartHand(PoseStack matrixStackIn, float partialTicks, long finishTimeNano, boolean drawBlockOutline, Camera activeRenderInfoIn, GameRenderer gameRendererIn, LightTexture lightmapIn, Matrix4f projectionIn, CallbackInfo ci) {
|
||||
private void onStartHand(final DeltaTracker deltaTracker, final boolean bl, final Camera camera, final GameRenderer gameRenderer, final LightTexture lightTexture, final Matrix4f matrix4f, final Matrix4f matrix4f2, final CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks, matrixStackIn, projectionIn));
|
||||
PoseStack poseStack = new PoseStack();
|
||||
poseStack.mulPose(matrix4f);
|
||||
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(deltaTracker.getGameTimeDeltaPartialTick(false), poseStack, matrix4f2));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,8 @@
|
||||
"MixinFireworkRocketEntity",
|
||||
"MixinItemStack",
|
||||
"MixinLivingEntity",
|
||||
"MixinLootContext",
|
||||
"MixinLootContextBuilder",
|
||||
"MixinLootTable",
|
||||
"MixinMinecraft",
|
||||
"MixinNetworkManager",
|
||||
"MixinPalettedContainer",
|
||||
@@ -26,5 +27,7 @@
|
||||
"MixinPlayerController",
|
||||
"MixinScreen",
|
||||
"MixinWorldRenderer"
|
||||
],
|
||||
"mixins": [
|
||||
]
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ public class Baritone implements IBaritone {
|
||||
private final ExploreProcess exploreProcess;
|
||||
private final FarmProcess farmProcess;
|
||||
private final InventoryPauserProcess inventoryPauserProcess;
|
||||
private final ElytraProcess elytraProcess;
|
||||
private final IElytraProcess elytraProcess;
|
||||
|
||||
private final PathingControlManager pathingControlManager;
|
||||
private final SelectionManager selectionManager;
|
||||
|
||||
@@ -265,7 +265,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (goal == null) {
|
||||
return false;
|
||||
}
|
||||
if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) {
|
||||
if (goal.isInGoal(ctx.playerFeet())) {
|
||||
return false;
|
||||
}
|
||||
synchronized (pathPlanLock) {
|
||||
@@ -553,7 +553,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
});
|
||||
}
|
||||
|
||||
private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
Goal transformed = goal;
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) {
|
||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
@@ -562,7 +562,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
}
|
||||
Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous, context);
|
||||
return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context);
|
||||
BetterBlockPos feet = ctx.playerFeet();
|
||||
var realStart = new BetterBlockPos(start);
|
||||
var sub = feet.subtract(realStart);
|
||||
if (feet.getY() == realStart.getY() && Math.abs(sub.getX()) <= 1 && Math.abs(sub.getZ()) <= 1) {
|
||||
realStart = feet;
|
||||
}
|
||||
return new AStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -35,6 +35,7 @@ import baritone.command.argument.CommandArguments;
|
||||
import baritone.command.manager.CommandManager;
|
||||
import baritone.utils.accessor.IGuiScreen;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.Util;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.util.Tuple;
|
||||
@@ -97,8 +98,8 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
return false;
|
||||
} else if (msg.trim().equalsIgnoreCase("orderpizza")) {
|
||||
try {
|
||||
((IGuiScreen) ctx.minecraft().screen).openLinkInvoker(new URI("https://www.dominos.com/en/pages/order/"));
|
||||
} catch (NullPointerException | URISyntaxException ignored) {}
|
||||
Util.getPlatform().openUri("https://www.dominos.com/en/pages/order/");
|
||||
} catch (Exception ignored) {}
|
||||
return false;
|
||||
}
|
||||
if (msg.isEmpty()) {
|
||||
|
||||
@@ -26,11 +26,13 @@ import baritone.api.command.datatypes.RelativeFile;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandInvalidStateException;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.utils.schematic.SchematicSystem;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.StringJoiner;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class BuildCommand extends Command {
|
||||
@@ -44,10 +46,29 @@ public class BuildCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
File file = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile();
|
||||
final File file0 = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile();
|
||||
File file = file0;
|
||||
if (FilenameUtils.getExtension(file.getAbsolutePath()).isEmpty()) {
|
||||
file = new File(file.getAbsolutePath() + "." + Baritone.settings().schematicFallbackExtension.value);
|
||||
}
|
||||
if (!file.exists()) {
|
||||
if (file0.exists()) {
|
||||
throw new CommandInvalidStateException(String.format(
|
||||
"Cannot load %s because I do not know which schematic format"
|
||||
+ " that is. Please rename the file to include the correct"
|
||||
+ " file extension.",
|
||||
file));
|
||||
}
|
||||
throw new CommandInvalidStateException("Cannot find " + file);
|
||||
}
|
||||
if (!SchematicSystem.INSTANCE.getByFile(file).isPresent()) {
|
||||
StringJoiner formats = new StringJoiner(", ");
|
||||
SchematicSystem.INSTANCE.getFileExtensions().forEach(formats::add);
|
||||
throw new CommandInvalidStateException(String.format(
|
||||
"Unsupported schematic format. Reckognized file extensions are: %s",
|
||||
formats
|
||||
));
|
||||
}
|
||||
BetterBlockPos origin = ctx.playerFeet();
|
||||
BetterBlockPos buildOrigin;
|
||||
if (args.hasAny()) {
|
||||
@@ -59,7 +80,7 @@ public class BuildCommand extends Command {
|
||||
}
|
||||
boolean success = baritone.getBuilderProcess().build(file.getName(), file, buildOrigin);
|
||||
if (!success) {
|
||||
throw new CommandInvalidStateException("Couldn't load the schematic. Make sure to use the FULL file name, including the extension (e.g. blah.schematic).");
|
||||
throw new CommandInvalidStateException("Couldn't load the schematic. Either your schematic is corrupt or this is a bug.");
|
||||
}
|
||||
logDirect(String.format("Successfully loaded schematic for building\nOrigin: %s", buildOrigin));
|
||||
}
|
||||
|
||||
@@ -53,6 +53,7 @@ public final class DefaultCommands {
|
||||
new RenderCommand(baritone),
|
||||
new FarmCommand(baritone),
|
||||
new FollowCommand(baritone),
|
||||
new PickupCommand(baritone),
|
||||
new ExploreFilterCommand(baritone),
|
||||
new ReloadAllCommand(baritone),
|
||||
new SaveAllCommand(baritone),
|
||||
|
||||
@@ -216,7 +216,7 @@ public class ElytraCommand extends Command {
|
||||
final String osArch = System.getProperty("os.arch");
|
||||
final String osName = System.getProperty("os.name");
|
||||
return String.format(
|
||||
"Legacy architectures are not supported. Your CPU is %s and your operating system is %s. " +
|
||||
"Failed loading native library. Your CPU is %s and your operating system is %s. " +
|
||||
"Supported architectures are 64 bit x86, and 64 bit ARM. Supported operating systems are Windows, " +
|
||||
"Linux, and Mac",
|
||||
osArch, osName
|
||||
|
||||
@@ -34,18 +34,9 @@ public class LitematicaCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
int schematic = 0;
|
||||
if (args.hasAny()) {
|
||||
args.requireMax(1);
|
||||
if (args.is(Integer.class)) {
|
||||
schematic = args.getAs(Integer.class) - 1;
|
||||
}
|
||||
}
|
||||
try {
|
||||
baritone.getBuilderProcess().buildOpenLitematic(schematic);
|
||||
} catch (IndexOutOfBoundsException e) {
|
||||
logDirect("Pleas provide a valid index.");
|
||||
}
|
||||
args.requireMax(1);
|
||||
int schematic = args.hasAny() ? args.getAs(Integer.class) - 1 : 0;
|
||||
baritone.getBuilderProcess().buildOpenLitematic(schematic);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
82
src/main/java/baritone/command/defaults/PickupCommand.java
Normal file
82
src/main/java/baritone/command/defaults/PickupCommand.java
Normal file
@@ -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.command.defaults;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.ItemById;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.item.Item;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class PickupCommand extends Command {
|
||||
|
||||
public PickupCommand(IBaritone baritone) {
|
||||
super(baritone, "pickup");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
Set<Item> collecting = new HashSet<>();
|
||||
while (args.hasAny()) {
|
||||
Item item = args.getDatatypeFor(ItemById.INSTANCE);
|
||||
collecting.add(item);
|
||||
}
|
||||
if (collecting.isEmpty()) {
|
||||
baritone.getFollowProcess().pickup(stack -> true);
|
||||
logDirect("Picking up all items");
|
||||
} else {
|
||||
baritone.getFollowProcess().pickup(stack -> collecting.contains(stack.getItem()));
|
||||
logDirect("Picking up these items:");
|
||||
collecting.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).forEach(this::logDirect);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
while (args.has(2)) {
|
||||
if (args.peekDatatypeOrNull(ItemById.INSTANCE) == null) {
|
||||
return Stream.empty();
|
||||
}
|
||||
args.get();
|
||||
}
|
||||
return args.tabCompleteDatatype(ItemById.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortDesc() {
|
||||
return "Pickup items";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"Usage:",
|
||||
"> pickup - Pickup anything",
|
||||
"> pickup <item1> <item2> <...> - Pickup certain items"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -40,10 +40,10 @@ public class RenderCommand extends Command {
|
||||
int renderDistance = (ctx.minecraft().options.renderDistance().get() + 1) * 16;
|
||||
ctx.minecraft().levelRenderer.setBlocksDirty(
|
||||
origin.x - renderDistance,
|
||||
0,
|
||||
ctx.world().getMinBuildHeight(),
|
||||
origin.z - renderDistance,
|
||||
origin.x + renderDistance,
|
||||
255,
|
||||
ctx.world().getMaxBuildHeight(),
|
||||
origin.z + renderDistance
|
||||
);
|
||||
logDirect("Done");
|
||||
|
||||
@@ -42,6 +42,7 @@ import baritone.api.utils.BlockOptionalMetaLookup;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.IRenderer;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
@@ -75,9 +76,9 @@ public class SelCommand extends Command {
|
||||
float opacity = Baritone.settings().selectionOpacity.value;
|
||||
float lineWidth = Baritone.settings().selectionLineWidth.value;
|
||||
boolean ignoreDepth = Baritone.settings().renderSelectionIgnoreDepth.value;
|
||||
IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
|
||||
IRenderer.emitAABB(event.getModelViewStack(), new AABB(pos1));
|
||||
IRenderer.endLines(ignoreDepth);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
|
||||
IRenderer.emitAABB(bufferBuilder, event.getModelViewStack(), new AABB(pos1));
|
||||
IRenderer.endLines(bufferBuilder, ignoreDepth);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -227,12 +228,7 @@ public class SelCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
ISchematic schematic = new StaticSchematic() {{
|
||||
states = blockstates;
|
||||
x = size.getX();
|
||||
y = size.getY();
|
||||
z = size.getZ();
|
||||
}};
|
||||
ISchematic schematic = new StaticSchematic(blockstates);
|
||||
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
|
||||
}
|
||||
clipboard = composite;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class TunnelCommand extends Command {
|
||||
int width = Integer.parseInt(args.getArgs().get(1).getValue());
|
||||
int depth = Integer.parseInt(args.getArgs().get(2).getValue());
|
||||
|
||||
if (width < 1 || height < 2 || depth < 1 || height > 255) {
|
||||
if (width < 1 || height < 2 || depth < 1 || height > ctx.world().getMaxBuildHeight()){
|
||||
logDirect("Width and depth must at least be 1 block; Height must at least be 2 blocks, and cannot be greater than the build limit.");
|
||||
cont = false;
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ 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.api.utils.SettingsUtil;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Moves;
|
||||
@@ -41,8 +42,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
private final Favoring favoring;
|
||||
private final CalculationContext calcContext;
|
||||
|
||||
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) {
|
||||
super(startX, startY, startZ, goal, context);
|
||||
public AStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) {
|
||||
super(realStart, startX, startY, startZ, goal, context);
|
||||
this.favoring = favoring;
|
||||
this.calcContext = context;
|
||||
}
|
||||
@@ -96,7 +97,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
numNodes++;
|
||||
if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) {
|
||||
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
|
||||
return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext));
|
||||
}
|
||||
for (Moves moves : allMoves) {
|
||||
int newX = currentNode.x + moves.xOffset;
|
||||
@@ -122,17 +123,39 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
continue;
|
||||
}
|
||||
if (actionCost <= 0 || Double.isNaN(actionCost)) {
|
||||
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
|
||||
throw new IllegalStateException(String.format(
|
||||
"%s from %s %s %s calculated implausible cost %s",
|
||||
moves,
|
||||
SettingsUtil.maybeCensor(currentNode.x),
|
||||
SettingsUtil.maybeCensor(currentNode.y),
|
||||
SettingsUtil.maybeCensor(currentNode.z),
|
||||
actionCost));
|
||||
}
|
||||
// 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
|
||||
// check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination
|
||||
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
|
||||
continue;
|
||||
}
|
||||
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
|
||||
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
|
||||
throw new IllegalStateException(String.format(
|
||||
"%s from %s %s %s ended at x z %s %s instead of %s %s",
|
||||
moves,
|
||||
SettingsUtil.maybeCensor(currentNode.x),
|
||||
SettingsUtil.maybeCensor(currentNode.y),
|
||||
SettingsUtil.maybeCensor(currentNode.z),
|
||||
SettingsUtil.maybeCensor(res.x),
|
||||
SettingsUtil.maybeCensor(res.z),
|
||||
SettingsUtil.maybeCensor(newX),
|
||||
SettingsUtil.maybeCensor(newZ)));
|
||||
}
|
||||
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
|
||||
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
|
||||
throw new IllegalStateException(String.format(
|
||||
"%s from %s %s %s ended at y %s instead of %s",
|
||||
moves,
|
||||
SettingsUtil.maybeCensor(currentNode.x),
|
||||
SettingsUtil.maybeCensor(currentNode.y),
|
||||
SettingsUtil.maybeCensor(currentNode.z),
|
||||
SettingsUtil.maybeCensor(res.y),
|
||||
SettingsUtil.maybeCensor(currentNode.y + moves.yOffset)));
|
||||
}
|
||||
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
|
||||
if (isFavoring) {
|
||||
|
||||
@@ -36,6 +36,7 @@ import java.util.Optional;
|
||||
*/
|
||||
public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
|
||||
protected final BetterBlockPos realStart;
|
||||
protected final int startX;
|
||||
protected final int startY;
|
||||
protected final int startZ;
|
||||
@@ -81,7 +82,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
*/
|
||||
protected static final double MIN_IMPROVEMENT = 0.01;
|
||||
|
||||
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
|
||||
AbstractNodeCostSearch(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, CalculationContext context) {
|
||||
this.realStart = realStart;
|
||||
this.startX = startX;
|
||||
this.startY = startY;
|
||||
this.startZ = startZ;
|
||||
@@ -177,7 +179,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
|
||||
@Override
|
||||
public Optional<IPath> pathToMostRecentNodeConsidered() {
|
||||
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
|
||||
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(realStart, startNode, node, 0, goal, context));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -208,7 +210,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
|
||||
logDebug("A* cost coefficient " + COEFFICIENTS[i]);
|
||||
}
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context));
|
||||
return Optional.of(new Path(realStart, startNode, bestSoFar[i], numNodes, goal, context));
|
||||
}
|
||||
}
|
||||
// instead of returning bestSoFar[0], be less misleading
|
||||
|
||||
@@ -27,6 +27,7 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.pathing.path.CutoffPath;
|
||||
import baritone.utils.pathing.PathBase;
|
||||
import com.google.common.collect.Lists;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
@@ -68,28 +69,40 @@ class Path extends PathBase {
|
||||
|
||||
private volatile boolean verified;
|
||||
|
||||
Path(PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) {
|
||||
this.start = new BetterBlockPos(start.x, start.y, start.z);
|
||||
Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) {
|
||||
this.end = new BetterBlockPos(end.x, end.y, end.z);
|
||||
this.numNodes = numNodes;
|
||||
this.movements = new ArrayList<>();
|
||||
this.goal = goal;
|
||||
this.context = context;
|
||||
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||
LinkedList<PathNode> tempNodes = new LinkedList<>();
|
||||
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
// Instead, do it into a linked list, then convert at the end
|
||||
List<BetterBlockPos> tempPath = new ArrayList<>();
|
||||
List<PathNode> tempNodes = new ArrayList<>();
|
||||
while (current != null) {
|
||||
tempNodes.addFirst(current);
|
||||
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
|
||||
tempNodes.add(current);
|
||||
tempPath.add(new BetterBlockPos(current.x, current.y, current.z));
|
||||
current = current.previous;
|
||||
}
|
||||
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
|
||||
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
||||
// to performantly do that conversion since it knows the length.
|
||||
this.path = new ArrayList<>(tempPath);
|
||||
this.nodes = new ArrayList<>(tempNodes);
|
||||
|
||||
// If the position the player is at is different from the position we told A* to start from,
|
||||
// and A* gave us no movements, then add a fake node that will allow a movement to be created
|
||||
// that gets us to the single position in the path.
|
||||
// See PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519
|
||||
var startNodePos = new BetterBlockPos(start.x, start.y, start.z);
|
||||
if (!realStart.equals(startNodePos) && start.equals(end)) {
|
||||
this.start = realStart;
|
||||
PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal);
|
||||
fakeNode.cost = 0;
|
||||
tempNodes.add(fakeNode);
|
||||
tempPath.add(realStart);
|
||||
} else {
|
||||
this.start = startNodePos;
|
||||
}
|
||||
|
||||
// Nodes are traversed last to first so we need to reverse the list
|
||||
this.path = Lists.reverse(tempPath);
|
||||
this.nodes = Lists.reverse(tempNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -99,7 +112,7 @@ class Path extends PathBase {
|
||||
|
||||
private boolean assembleMovements() {
|
||||
if (path.isEmpty() || !movements.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Path must not be empty");
|
||||
}
|
||||
for (int i = 0; i < path.size() - 1; i++) {
|
||||
double cost = nodes.get(i + 1).cost - nodes.get(i).cost;
|
||||
@@ -132,7 +145,7 @@ class Path extends PathBase {
|
||||
@Override
|
||||
public IPath postProcess() {
|
||||
if (verified) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Path must not be verified twice");
|
||||
}
|
||||
verified = true;
|
||||
boolean failed = assembleMovements();
|
||||
@@ -141,7 +154,7 @@ class Path extends PathBase {
|
||||
if (failed) { // at least one movement became impossible during calculation
|
||||
CutoffPath res = new CutoffPath(this, movements().size());
|
||||
if (res.movements().size() != movements.size()) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Path has wrong size after cutoff");
|
||||
}
|
||||
return res;
|
||||
}
|
||||
@@ -153,7 +166,8 @@ class Path extends PathBase {
|
||||
@Override
|
||||
public List<IMovement> movements() {
|
||||
if (!verified) {
|
||||
throw new IllegalStateException();
|
||||
// edge case note: this is called during verification
|
||||
throw new IllegalStateException("Path not yet verified");
|
||||
}
|
||||
return Collections.unmodifiableList(movements);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package baritone.pathing.calc;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
|
||||
/**
|
||||
* A node in the path, containing the cost and steps to get to it.
|
||||
@@ -68,7 +69,12 @@ public final class PathNode {
|
||||
this.cost = ActionCosts.COST_INF;
|
||||
this.estimatedCostToGoal = goal.heuristic(x, y, z);
|
||||
if (Double.isNaN(estimatedCostToGoal)) {
|
||||
throw new IllegalStateException(goal + " calculated implausible heuristic");
|
||||
throw new IllegalStateException(String.format(
|
||||
"%s calculated implausible heuristic NaN at %s %s %s",
|
||||
goal,
|
||||
SettingsUtil.maybeCensor(x),
|
||||
SettingsUtil.maybeCensor(y),
|
||||
SettingsUtil.maybeCensor(z)));
|
||||
}
|
||||
this.heapPosition = -1;
|
||||
this.x = x;
|
||||
|
||||
@@ -92,7 +92,7 @@ public final class BinaryHeapOpenSet implements IOpenSet {
|
||||
@Override
|
||||
public final PathNode removeLowest() {
|
||||
if (size == 0) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Cannot remove from empty heap");
|
||||
}
|
||||
PathNode result = array[1];
|
||||
PathNode val = array[size];
|
||||
|
||||
@@ -27,11 +27,14 @@ import baritone.utils.ToolSet;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.item.enchantment.*;
|
||||
import net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -63,7 +66,7 @@ public class CalculationContext {
|
||||
public final List<Block> allowBreakAnyway;
|
||||
public final boolean allowParkour;
|
||||
public final boolean allowParkourPlace;
|
||||
public final boolean allowJumpAt256;
|
||||
public final boolean allowJumpAtBuildLimit;
|
||||
public final boolean allowParkourAscend;
|
||||
public final boolean assumeWalkOnWater;
|
||||
public boolean allowFallIntoLava;
|
||||
@@ -104,23 +107,48 @@ public class CalculationContext {
|
||||
this.allowBreakAnyway = new ArrayList<>(Baritone.settings().allowBreakAnyway.value);
|
||||
this.allowParkour = Baritone.settings().allowParkour.value;
|
||||
this.allowParkourPlace = Baritone.settings().allowParkourPlace.value;
|
||||
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
|
||||
this.allowJumpAtBuildLimit = Baritone.settings().allowJumpAtBuildLimit.value;
|
||||
this.allowParkourAscend = Baritone.settings().allowParkourAscend.value;
|
||||
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value;
|
||||
this.allowFallIntoLava = false; // Super secret internal setting for ElytraBehavior
|
||||
this.frostWalker = EnchantmentHelper.getEnchantmentLevel(Enchantments.FROST_WALKER, baritone.getPlayerContext().player());
|
||||
// todo: technically there can now be datapack enchants that replace blocks with any other at any range
|
||||
int frostWalkerLevel = 0;
|
||||
for (EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
ItemEnchantments itemEnchantments = baritone.getPlayerContext()
|
||||
.player()
|
||||
.getItemBySlot(slot)
|
||||
.getEnchantments();
|
||||
for (Holder<Enchantment> enchant : itemEnchantments.keySet()) {
|
||||
if (enchant.is(Enchantments.FROST_WALKER)) {
|
||||
frostWalkerLevel = itemEnchantments.getLevel(enchant);
|
||||
}
|
||||
}
|
||||
}
|
||||
this.frostWalker = frostWalkerLevel;
|
||||
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value;
|
||||
this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value;
|
||||
this.allowDownward = Baritone.settings().allowDownward.value;
|
||||
this.minFallHeight = 3; // Minimum fall height used by MovementFall
|
||||
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.value;
|
||||
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.value;
|
||||
int depth = EnchantmentHelper.getDepthStrider(player);
|
||||
if (depth > 3) {
|
||||
depth = 3;
|
||||
float waterSpeedMultiplier = 1.0f;
|
||||
OUTER: for (EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
ItemEnchantments itemEnchantments = baritone.getPlayerContext()
|
||||
.player()
|
||||
.getItemBySlot(slot)
|
||||
.getEnchantments();
|
||||
for (Holder<Enchantment> enchant : itemEnchantments.keySet()) {
|
||||
List<EnchantmentAttributeEffect> effects = enchant.value()
|
||||
.getEffects(EnchantmentEffectComponents.ATTRIBUTES);
|
||||
for (EnchantmentAttributeEffect effect : effects) {
|
||||
if (effect.attribute().is(Attributes.WATER_MOVEMENT_EFFICIENCY.unwrapKey().get())) {
|
||||
waterSpeedMultiplier = effect.amount().calculate(itemEnchantments.getLevel(enchant));
|
||||
break OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
float mult = depth / 3.0F;
|
||||
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult;
|
||||
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - waterSpeedMultiplier) + ActionCosts.WALK_ONE_BLOCK_COST * waterSpeedMultiplier;
|
||||
this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.value;
|
||||
this.backtrackCostFavoringCoefficient = Baritone.settings().backtrackCostFavoringCoefficient.value;
|
||||
this.jumpPenalty = Baritone.settings().jumpPenalty.value;
|
||||
@@ -161,6 +189,12 @@ public class CalculationContext {
|
||||
if (!worldBorder.canPlaceAt(x, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!Baritone.settings().allowPlaceInFluidsSource.value && current.getFluidState().isSource()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!Baritone.settings().allowPlaceInFluidsFlow.value && !current.getFluidState().isEmpty() && !current.getFluidState().isSource()) {
|
||||
return COST_INF;
|
||||
}
|
||||
return placeBlockCost;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,11 @@ import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.entity.EquipmentSlot;
|
||||
import net.minecraft.world.item.enchantment.Enchantment;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.item.enchantment.ItemEnchantments;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.piston.MovingPistonBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
@@ -177,15 +181,10 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block instanceof CauldronBlock) {
|
||||
return NO;
|
||||
}
|
||||
try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information
|
||||
if (state.isPathfindable(null, null, PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} catch (Throwable exception) {
|
||||
System.out.println("The block " + state.getBlock().getName().getString() + " requires a special case due to the exception " + exception.getMessage());
|
||||
return MAYBE;
|
||||
if (state.isPathfindable(PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -228,10 +227,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return fluidState.getType() instanceof WaterFluid;
|
||||
}
|
||||
|
||||
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
|
||||
// has already been accounted for above
|
||||
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
|
||||
return state.isPathfindable(bsi.access, BlockPos.ZERO, PathComputationType.LAND); // workaround for future compatibility =P
|
||||
return state.isPathfindable(PathComputationType.LAND);
|
||||
}
|
||||
|
||||
static Ternary fullyPassableBlockState(BlockState state) {
|
||||
@@ -259,16 +255,10 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
|
||||
// at least in 1.12.2 vanilla, that is.....
|
||||
try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information
|
||||
if (state.isPathfindable(null, null, PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} catch (Throwable exception) {
|
||||
// see PR #1087 for why
|
||||
System.out.println("The block " + state.getBlock().getName().getString() + " requires a special case due to the exception " + exception.getMessage());
|
||||
return MAYBE;
|
||||
if (state.isPathfindable(PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -293,11 +283,14 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (fullyPassable == NO) {
|
||||
return false;
|
||||
}
|
||||
return fullyPassablePosition(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ(), state); // meh
|
||||
return state.isPathfindable(PathComputationType.LAND);
|
||||
}
|
||||
|
||||
/**
|
||||
* params retained for backwards compatibility
|
||||
*/
|
||||
static boolean fullyPassablePosition(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
return state.isPathfindable(bsi.access, bsi.isPassableBlockPos.set(x, y, z), PathComputationType.LAND);
|
||||
return state.isPathfindable(PathComputationType.LAND);
|
||||
}
|
||||
|
||||
static boolean isReplaceable(int x, int y, int z, BlockState state, BlockStateInterface bsi) {
|
||||
@@ -428,7 +421,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH) {
|
||||
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH || block == Blocks.SOUL_SAND) {
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) {
|
||||
@@ -511,14 +504,27 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
static boolean canUseFrostWalker(CalculationContext context, BlockState state) {
|
||||
return context.frostWalker != 0
|
||||
&& state == FrostedIceBlock.meltsInto()
|
||||
&& ((Integer) state.getValue(LiquidBlock.LEVEL)) == 0;
|
||||
&& state.getValue(LiquidBlock.LEVEL) == 0;
|
||||
}
|
||||
|
||||
static boolean canUseFrostWalker(IPlayerContext ctx, BlockPos pos) {
|
||||
boolean hasFrostWalker = false;
|
||||
OUTER: for (EquipmentSlot slot : EquipmentSlot.values()) {
|
||||
ItemEnchantments itemEnchantments = ctx
|
||||
.player()
|
||||
.getItemBySlot(slot)
|
||||
.getEnchantments();
|
||||
for (Holder<Enchantment> enchant : itemEnchantments.keySet()) {
|
||||
if (enchant.is(Enchantments.FROST_WALKER)) {
|
||||
hasFrostWalker = true;
|
||||
break OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
BlockState state = BlockStateInterface.get(ctx, pos);
|
||||
return EnchantmentHelper.hasFrostWalker(ctx.player())
|
||||
return hasFrostWalker
|
||||
&& state == FrostedIceBlock.meltsInto()
|
||||
&& ((Integer) state.getValue(LiquidBlock.LEVEL)) == 0;
|
||||
&& state.getValue(LiquidBlock.LEVEL) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -347,7 +347,7 @@ public enum Moves {
|
||||
|
||||
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
|
||||
if (dynamicXZ || dynamicY) {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("Movements with dynamic offset must override `apply`");
|
||||
}
|
||||
result.x = x + xOffset;
|
||||
result.y = y + yOffset;
|
||||
@@ -356,6 +356,6 @@ public enum Moves {
|
||||
}
|
||||
|
||||
public double cost(CalculationContext context, int x, int y, int z) {
|
||||
throw new UnsupportedOperationException();
|
||||
throw new UnsupportedOperationException("Movements must override `cost` or `apply`");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,9 +147,9 @@ public class MovementDescend extends Movement {
|
||||
int effectiveStartHeight = y;
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
int newY = y - fallHeight;
|
||||
if (newY < 0) {
|
||||
if (newY < context.world.getMinBuildHeight()) {
|
||||
// when pathing in the end, where you could plausibly fall into the void
|
||||
// this check prevents it from getting the block at y=-1 and crashing
|
||||
// this check prevents it from getting the block at y=(below whatever the minimum height is) and crashing
|
||||
return false;
|
||||
}
|
||||
boolean reachedMinimum = fallHeight >= context.minFallHeight;
|
||||
|
||||
@@ -64,10 +64,9 @@ public class MovementParkour extends Movement {
|
||||
if (!context.allowParkour) {
|
||||
return;
|
||||
}
|
||||
if (y == 256 && !context.allowJumpAt256) {
|
||||
if (!context.allowJumpAtBuildLimit && y >= context.world.getMaxBuildHeight()) {
|
||||
return;
|
||||
}
|
||||
|
||||
int xDiff = dir.getStepX();
|
||||
int zDiff = dir.getStepZ();
|
||||
if (!MovementHelper.fullyPassable(context, x + xDiff, y, z + zDiff)) {
|
||||
|
||||
@@ -455,7 +455,9 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
if (data != null) {
|
||||
BetterBlockPos fallDest = new BetterBlockPos(data.getB());
|
||||
if (!path.positions().contains(fallDest)) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException(String.format(
|
||||
"Fall override at %s %s %s returned illegal destination %s %s %s",
|
||||
current.getSrc(), fallDest));
|
||||
}
|
||||
if (ctx.playerFeet().equals(fallDest)) {
|
||||
pathPosition = path.positions().indexOf(fallDest);
|
||||
@@ -603,7 +605,9 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
}
|
||||
return SplicedPath.trySplice(path, next.path, false).map(path -> {
|
||||
if (!path.getDest().equals(next.getPath().getDest())) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException(String.format(
|
||||
"Path has end %s instead of %s after splicing",
|
||||
path.getDest(), next.getPath().getDest()));
|
||||
}
|
||||
PathExecutor ret = new PathExecutor(behavior, path);
|
||||
ret.pathPosition = pathPosition;
|
||||
@@ -619,7 +623,9 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.value;
|
||||
CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1);
|
||||
if (!newPath.getDest().equals(path.getDest())) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException(String.format(
|
||||
"Path has end %s instead of %s after trimming its start",
|
||||
newPath.getDest(), path.getDest()));
|
||||
}
|
||||
logDebug("Discarding earliest segment movements, length cut from " + path.length() + " to " + newPath.length());
|
||||
PathExecutor ret = new PathExecutor(behavior, newPath);
|
||||
|
||||
@@ -92,7 +92,7 @@ public class SplicedPath extends PathBase {
|
||||
}
|
||||
int positionInSecond = second.positions().indexOf(first.positions().get(firstPositionInSecond));
|
||||
if (!allowOverlapCutoff && positionInSecond != 0) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Paths to be spliced are overlapping incorrectly");
|
||||
}
|
||||
List<BetterBlockPos> positions = new ArrayList<>();
|
||||
List<IMovement> movements = new ArrayList<>();
|
||||
|
||||
@@ -28,7 +28,10 @@ import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.schematic.FillSchematic;
|
||||
import baritone.api.schematic.ISchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.api.schematic.MaskSchematic;
|
||||
import baritone.api.schematic.SubstituteSchematic;
|
||||
import baritone.api.schematic.RotatedSchematic;
|
||||
import baritone.api.schematic.MirroredSchematic;
|
||||
import baritone.api.schematic.format.ISchematicFormat;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.input.Input;
|
||||
@@ -41,17 +44,13 @@ import baritone.utils.PathingCommandContext;
|
||||
import baritone.utils.schematic.MapArtSchematic;
|
||||
import baritone.utils.schematic.SelectionSchematic;
|
||||
import baritone.utils.schematic.SchematicSystem;
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.utils.schematic.litematica.LitematicaHelper;
|
||||
import baritone.utils.schematic.schematica.SchematicaHelper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
@@ -76,7 +75,6 @@ import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
@@ -85,6 +83,14 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
|
||||
public final class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
|
||||
|
||||
private static final Set<Property<?>> ORIENTATION_PROPS =
|
||||
ImmutableSet.of(
|
||||
RotatedPillarBlock.AXIS, HorizontalDirectionalBlock.FACING,
|
||||
StairBlock.FACING, StairBlock.HALF, StairBlock.SHAPE,
|
||||
PipeBlock.NORTH, PipeBlock.EAST, PipeBlock.SOUTH, PipeBlock.WEST, PipeBlock.UP,
|
||||
TrapDoorBlock.OPEN, TrapDoorBlock.HALF
|
||||
);
|
||||
|
||||
private HashSet<BetterBlockPos> incorrectPositions;
|
||||
private LongOpenHashSet observedCompleted; // positions that are completed even if they're out of render distance and we can't make sure right now
|
||||
private String name;
|
||||
@@ -111,6 +117,20 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (!Baritone.settings().buildSubstitutes.value.isEmpty()) {
|
||||
this.schematic = new SubstituteSchematic(this.schematic, Baritone.settings().buildSubstitutes.value);
|
||||
}
|
||||
if (Baritone.settings().buildSchematicMirror.value != net.minecraft.world.level.block.Mirror.NONE) {
|
||||
this.schematic = new MirroredSchematic(this.schematic, Baritone.settings().buildSchematicMirror.value);
|
||||
}
|
||||
if (Baritone.settings().buildSchematicRotation.value != net.minecraft.world.level.block.Rotation.NONE) {
|
||||
this.schematic = new RotatedSchematic(this.schematic, Baritone.settings().buildSchematicRotation.value);
|
||||
}
|
||||
// TODO this preserves the old behavior, but maybe we should bake the setting value right here
|
||||
this.schematic = new MaskSchematic(this.schematic) {
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z, BlockState current) {
|
||||
// partOfMask is only called inside the schematic so desiredState is not null
|
||||
return !Baritone.settings().buildSkipBlocks.value.contains(this.desiredState(x, y, z, current, Collections.emptyList()).getBlock());
|
||||
}
|
||||
};
|
||||
int x = origin.getX();
|
||||
int y = origin.getY();
|
||||
int z = origin.getZ();
|
||||
@@ -169,15 +189,15 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (!format.isPresent()) {
|
||||
return false;
|
||||
}
|
||||
ISchematic parsed;
|
||||
IStaticSchematic parsed;
|
||||
try {
|
||||
parsed = format.get().parse(new FileInputStream(schematic));
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return false;
|
||||
}
|
||||
parsed = applyMapArtAndSelection(origin, (IStaticSchematic) parsed);
|
||||
build(name, parsed, origin);
|
||||
ISchematic schem = applyMapArtAndSelection(origin, parsed);
|
||||
build(name, schem, origin);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -197,17 +217,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (SchematicaHelper.isSchematicaPresent()) {
|
||||
Optional<Tuple<IStaticSchematic, BlockPos>> schematic = SchematicaHelper.getOpenSchematic();
|
||||
if (schematic.isPresent()) {
|
||||
IStaticSchematic s = schematic.get().getA();
|
||||
IStaticSchematic raw = schematic.get().getA();
|
||||
BlockPos origin = schematic.get().getB();
|
||||
ISchematic schem = Baritone.settings().mapArtMode.value ? new MapArtSchematic(s) : s;
|
||||
if (Baritone.settings().buildOnlySelection.value) {
|
||||
schem = new SelectionSchematic(schem, origin, baritone.getSelectionManager().getSelections());
|
||||
}
|
||||
this.build(
|
||||
schematic.get().getA().toString(),
|
||||
schem,
|
||||
origin
|
||||
);
|
||||
ISchematic schem = applyMapArtAndSelection(origin, raw);
|
||||
this.build(raw.toString(), schem, origin);
|
||||
} else {
|
||||
logDirect("No schematic currently open");
|
||||
}
|
||||
@@ -220,19 +233,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
public void buildOpenLitematic(int i) {
|
||||
if (LitematicaHelper.isLitematicaPresent()) {
|
||||
//if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager
|
||||
if (LitematicaHelper.hasLoadedSchematic()) {
|
||||
String name = LitematicaHelper.getName(i);
|
||||
try {
|
||||
LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath()), NbtAccounter.unlimitedHeap()), false);
|
||||
Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i);
|
||||
ISchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
|
||||
schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2);
|
||||
build(name, schematic2, correctedOrigin);
|
||||
} catch (Exception e) {
|
||||
logDirect("Schematic File could not be loaded.");
|
||||
}
|
||||
if (LitematicaHelper.hasLoadedSchematic(i)) {
|
||||
Tuple<IStaticSchematic, Vec3i> schematic = LitematicaHelper.getSchematic(i);
|
||||
Vec3i correctedOrigin = schematic.getB();
|
||||
ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA());
|
||||
build(schematic.getA().toString(), schematic2, correctedOrigin);
|
||||
} else {
|
||||
logDirect("No schematic currently loaded");
|
||||
logDirect(String.format("List of placements has no entry %s", i + 1));
|
||||
}
|
||||
} else {
|
||||
logDirect("Litematica is not present");
|
||||
@@ -363,7 +370,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (!placementPlausible(new BetterBlockPos(x, y, z), toPlace)) {
|
||||
continue;
|
||||
}
|
||||
AABB aabb = placeAgainstState.getShape(ctx.world(), placeAgainstPos).bounds();
|
||||
VoxelShape shape = placeAgainstState.getShape(ctx.world(), placeAgainstPos);
|
||||
if (shape.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
AABB aabb = shape.bounds();
|
||||
for (Vec3 placementMultiplier : aabbSideMultipliers(against)) {
|
||||
double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x);
|
||||
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
|
||||
@@ -430,7 +441,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
double z = side.getStepZ() == 0 ? 0.5 : (1 + side.getStepZ()) / 2D;
|
||||
return new Vec3[]{new Vec3(x, 0.25, z), new Vec3(x, 0.75, z)};
|
||||
default: // null
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected side " + side);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -439,8 +450,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return onTick(calcFailed, isSafeToCancel, 0);
|
||||
}
|
||||
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel, int recursions) {
|
||||
if (recursions > 1000) { // onTick calls itself, don't crash
|
||||
private PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel, int recursions) {
|
||||
if (recursions > 100) { // onTick calls itself, don't crash
|
||||
return new PathingCommand(null, PathingCommandType.SET_GOAL_AND_PATH);
|
||||
}
|
||||
approxPlaceable = approxPlaceable(36);
|
||||
@@ -684,8 +695,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
continue;
|
||||
}
|
||||
// this is not in render distance
|
||||
if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))
|
||||
&& !Baritone.settings().buildSkipBlocks.value.contains(schematic.desiredState(x, y, z, current, this.approxPlaceable).getBlock())) {
|
||||
if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))) {
|
||||
// and we've never seen this position be correct
|
||||
// therefore mark as incorrect
|
||||
incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
|
||||
@@ -708,13 +718,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
List<BetterBlockPos> sourceLiquids = new ArrayList<>();
|
||||
List<BetterBlockPos> flowingLiquids = new ArrayList<>();
|
||||
Map<BlockState, Integer> missing = new HashMap<>();
|
||||
List<BetterBlockPos> outOfBounds = new ArrayList<>();
|
||||
incorrectPositions.forEach(pos -> {
|
||||
BlockState state = bcc.bsi.get0(pos);
|
||||
if (state.getBlock() instanceof AirBlock) {
|
||||
if (containsBlockState(approxPlaceable, bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
|
||||
BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
|
||||
if (desired == null) {
|
||||
outOfBounds.add(pos);
|
||||
} else if (containsBlockState(approxPlaceable, desired)) {
|
||||
placeable.add(pos);
|
||||
} else {
|
||||
BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
|
||||
missing.put(desired, 1 + missing.getOrDefault(desired, 0));
|
||||
}
|
||||
} else {
|
||||
@@ -732,6 +745,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
});
|
||||
incorrectPositions.removeAll(outOfBounds);
|
||||
List<Goal> toBreak = new ArrayList<>();
|
||||
breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
|
||||
List<Goal> toPlace = new ArrayList<>();
|
||||
@@ -984,6 +998,22 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return paused ? "Builder Paused" : "Building " + name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> getMinLayer() {
|
||||
if (Baritone.settings().buildInLayers.value) {
|
||||
return Optional.of(this.layer);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public Optional<Integer> getMaxLayer() {
|
||||
if (Baritone.settings().buildInLayers.value) {
|
||||
return Optional.of(this.stopAtHeight);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private List<BlockState> approxPlaceable(int size) {
|
||||
List<BlockState> result = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
@@ -1010,15 +1040,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final Set<Property<?>> orientationProps =
|
||||
ImmutableSet.of(
|
||||
RotatedPillarBlock.AXIS, HorizontalDirectionalBlock.FACING,
|
||||
StairBlock.FACING, StairBlock.HALF, StairBlock.SHAPE,
|
||||
PipeBlock.NORTH, PipeBlock.EAST, PipeBlock.SOUTH, PipeBlock.WEST, PipeBlock.UP,
|
||||
TrapDoorBlock.OPEN, TrapDoorBlock.HALF
|
||||
);
|
||||
|
||||
private boolean sameBlockstate(BlockState first, BlockState second) {
|
||||
private static boolean sameBlockstate(BlockState first, BlockState second) {
|
||||
if (first.getBlock() != second.getBlock()) {
|
||||
return false;
|
||||
}
|
||||
@@ -1027,11 +1049,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (!ignoreDirection && ignoredProps.isEmpty()) {
|
||||
return first.equals(second); // early return if no properties are being ignored
|
||||
}
|
||||
ImmutableMap<Property<?>, Comparable<?>> map1 = first.getValues();
|
||||
ImmutableMap<Property<?>, Comparable<?>> map2 = second.getValues();
|
||||
Map<Property<?>, Comparable<?>> map1 = first.getValues();
|
||||
Map<Property<?>, Comparable<?>> map2 = second.getValues();
|
||||
for (Property<?> prop : map1.keySet()) {
|
||||
if (map1.get(prop) != map2.get(prop)
|
||||
&& !(ignoreDirection && orientationProps.contains(prop))
|
||||
&& !(ignoreDirection && ORIENTATION_PROPS.contains(prop))
|
||||
&& !ignoredProps.contains(prop.getName())) {
|
||||
return false;
|
||||
}
|
||||
@@ -1039,7 +1061,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean containsBlockState(Collection<BlockState> states, BlockState state) {
|
||||
private static boolean containsBlockState(Collection<BlockState> states, BlockState state) {
|
||||
for (BlockState testee : states) {
|
||||
if (sameBlockstate(testee, state)) {
|
||||
return true;
|
||||
@@ -1048,7 +1070,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean valid(BlockState current, BlockState desired, boolean itemVerify) {
|
||||
private static boolean valid(BlockState current, BlockState desired, boolean itemVerify) {
|
||||
if (desired == null) {
|
||||
return true;
|
||||
}
|
||||
@@ -1067,9 +1089,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (!(current.getBlock() instanceof AirBlock) && Baritone.settings().buildIgnoreExisting.value && !itemVerify) {
|
||||
return true;
|
||||
}
|
||||
if (Baritone.settings().buildSkipBlocks.value.contains(desired.getBlock()) && !itemVerify) {
|
||||
return true;
|
||||
}
|
||||
if (Baritone.settings().buildValidSubstitutes.value.getOrDefault(desired.getBlock(), Collections.emptyList()).contains(current.getBlock()) && !itemVerify) {
|
||||
return true;
|
||||
}
|
||||
@@ -1113,12 +1132,12 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return COST_INF;
|
||||
}
|
||||
BlockState sch = getSchematic(x, y, z, current);
|
||||
if (sch != null && !Baritone.settings().buildSkipBlocks.value.contains(sch.getBlock())) {
|
||||
if (sch != null) {
|
||||
// TODO this can return true even when allowPlace is off.... is that an issue?
|
||||
if (sch.getBlock() instanceof AirBlock) {
|
||||
// we want this to be air, but they're asking if they can place here
|
||||
// this won't be a schematic block, this will be a throwaway
|
||||
return placeBlockCost * 2; // we're going to have to break it eventually
|
||||
return placeBlockCost * Baritone.settings().placeIncorrectBlockPenaltyMultiplier.value; // we're going to have to break it eventually
|
||||
}
|
||||
if (placeable.contains(sch)) {
|
||||
return 0; // thats right we gonna make it FREE to place a block where it should go in a structure
|
||||
@@ -1131,7 +1150,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
// we want it to be something that we don't have
|
||||
// even more of a pain to place something wrong
|
||||
return placeBlockCost * 3;
|
||||
return placeBlockCost * 1.5 * Baritone.settings().placeIncorrectBlockPenaltyMultiplier.value;
|
||||
} else {
|
||||
if (hasThrowaway) {
|
||||
return placeBlockCost;
|
||||
@@ -1147,7 +1166,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return COST_INF;
|
||||
}
|
||||
BlockState sch = getSchematic(x, y, z, current);
|
||||
if (sch != null && !Baritone.settings().buildSkipBlocks.value.contains(sch.getBlock())) {
|
||||
if (sch != null) {
|
||||
if (sch.getBlock() instanceof AirBlock) {
|
||||
// it should be air
|
||||
// regardless of current contents, we can break it
|
||||
|
||||
@@ -114,7 +114,7 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC
|
||||
}
|
||||
return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected state " + this.state);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -84,10 +84,10 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro
|
||||
baritone.getGameEventHandler().registerEventListener(this);
|
||||
}
|
||||
|
||||
public static <T extends IElytraProcess> T create(final Baritone baritone) {
|
||||
return (T) (NetherPathfinderContext.isSupported()
|
||||
public static IElytraProcess create(final Baritone baritone) {
|
||||
return NetherPathfinderContext.isSupported()
|
||||
? new ElytraProcess(baritone)
|
||||
: new NullElytraProcess(baritone));
|
||||
: new NullElytraProcess(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -360,7 +360,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro
|
||||
|
||||
private boolean shouldLandForSafety() {
|
||||
ItemStack chest = ctx.player().getItemBySlot(EquipmentSlot.CHEST);
|
||||
if (chest.getItem() != Items.ELYTRA || chest.getItem().getMaxDamage() - chest.getDamageValue() < Baritone.settings().elytraMinimumDurability.value) {
|
||||
if (chest.getItem() != Items.ELYTRA || chest.getMaxDamage() - chest.getDamageValue() < Baritone.settings().elytraMinimumDurability.value) {
|
||||
// elytrabehavior replaces when durability <= minimumDurability, so if durability < minimumDurability then we can reasonably assume that the elytra will soon be broken without replacement
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -118,7 +118,9 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
int dz = (mult * 2 - 1) * zval; // dz can be either -zval or zval
|
||||
int trueDist = Math.abs(dx) + Math.abs(dz);
|
||||
if (trueDist != dist) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException(String.format(
|
||||
"Offset %s %s has distance %s, expected %s",
|
||||
dx, dz, trueDist, dist));
|
||||
}
|
||||
switch (filter.isAlreadyExplored(chunkX + dx, chunkZ + dz)) {
|
||||
case UNKNOWN:
|
||||
|
||||
@@ -42,6 +42,7 @@ import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.BambooStalkBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.BonemealableBlock;
|
||||
@@ -95,6 +96,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
Items.NETHER_WART,
|
||||
Items.COCOA_BEANS,
|
||||
Blocks.SUGAR_CANE.asItem(),
|
||||
Blocks.BAMBOO.asItem(),
|
||||
Blocks.CACTUS.asItem()
|
||||
);
|
||||
|
||||
@@ -137,6 +139,15 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
return true;
|
||||
}
|
||||
},
|
||||
BAMBOO(Blocks.BAMBOO, null) {
|
||||
@Override
|
||||
public boolean readyToHarvest(Level world, BlockPos pos, BlockState state) {
|
||||
if (Baritone.settings().replantCrops.value) {
|
||||
return world.getBlockState(pos.below()).getBlock() instanceof BambooStalkBlock;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
},
|
||||
CACTUS(Blocks.CACTUS, null) {
|
||||
@Override
|
||||
public boolean readyToHarvest(Level world, BlockPos pos, BlockState state) {
|
||||
@@ -191,20 +202,20 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
ArrayList<Block> scan = new ArrayList<>();
|
||||
for (Harvest harvest : Harvest.values()) {
|
||||
scan.add(harvest.block);
|
||||
}
|
||||
if (Baritone.settings().replantCrops.value) {
|
||||
scan.add(Blocks.FARMLAND);
|
||||
scan.add(Blocks.JUNGLE_LOG);
|
||||
if (Baritone.settings().replantNetherWart.value) {
|
||||
scan.add(Blocks.SOUL_SAND);
|
||||
}
|
||||
}
|
||||
|
||||
if (Baritone.settings().mineGoalUpdateInterval.value != 0 && tickCount++ % Baritone.settings().mineGoalUpdateInterval.value == 0) {
|
||||
Baritone.getExecutor().execute(() -> locations = BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius(ctx, scan, 256, 10, 10));
|
||||
ArrayList<Block> scan = new ArrayList<>();
|
||||
for (Harvest harvest : Harvest.values()) {
|
||||
scan.add(harvest.block);
|
||||
}
|
||||
if (Baritone.settings().replantCrops.value) {
|
||||
scan.add(Blocks.FARMLAND);
|
||||
scan.add(Blocks.JUNGLE_LOG);
|
||||
if (Baritone.settings().replantNetherWart.value) {
|
||||
scan.add(Blocks.SOUL_SAND);
|
||||
}
|
||||
}
|
||||
|
||||
Baritone.getExecutor().execute(() -> locations = BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius(ctx, scan, Baritone.settings().farmMaxScanSize.value, 10, 10));
|
||||
}
|
||||
if (locations == null) {
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
@@ -256,7 +267,12 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
}
|
||||
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
BetterBlockPos playerPos = ctx.playerFeet();
|
||||
double blockReachDistance = ctx.playerController().getBlockReachDistance();
|
||||
for (BlockPos pos : toBreak) {
|
||||
if (playerPos.distSqr(pos) > blockReachDistance * blockReachDistance) {
|
||||
continue;
|
||||
}
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
|
||||
if (rot.isPresent() && isSafeToCancel) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
@@ -270,10 +286,13 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
ArrayList<BlockPos> both = new ArrayList<>(openFarmland);
|
||||
both.addAll(openSoulsand);
|
||||
for (BlockPos pos : both) {
|
||||
if (playerPos.distSqr(pos) > blockReachDistance * blockReachDistance) {
|
||||
continue;
|
||||
}
|
||||
boolean soulsand = openSoulsand.contains(pos);
|
||||
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, new Vec3(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
|
||||
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, new Vec3(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), blockReachDistance, false);
|
||||
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) {
|
||||
HitResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
|
||||
HitResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), blockReachDistance);
|
||||
if (result instanceof BlockHitResult && ((BlockHitResult) result).getDirection() == Direction.UP) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
if (ctx.isLookingAt(pos)) {
|
||||
@@ -284,14 +303,17 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
}
|
||||
}
|
||||
for (BlockPos pos : openLog) {
|
||||
if (playerPos.distSqr(pos) > blockReachDistance * blockReachDistance) {
|
||||
continue;
|
||||
}
|
||||
for (Direction dir : Direction.Plane.HORIZONTAL) {
|
||||
if (!(ctx.world().getBlockState(pos.relative(dir)).getBlock() instanceof AirBlock)) {
|
||||
continue;
|
||||
}
|
||||
Vec3 faceCenter = Vec3.atCenterOf(pos).add(Vec3.atLowerCornerOf(dir.getNormal()).scale(0.5));
|
||||
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, faceCenter, ctx.playerController().getBlockReachDistance(), false);
|
||||
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, faceCenter, blockReachDistance, false);
|
||||
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isCocoa)) {
|
||||
HitResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
|
||||
HitResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), blockReachDistance);
|
||||
if (result instanceof BlockHitResult && ((BlockHitResult) result).getDirection() == dir) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
if (ctx.isLookingAt(pos)) {
|
||||
@@ -303,6 +325,9 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
}
|
||||
}
|
||||
for (BlockPos pos : bonemealable) {
|
||||
if (playerPos.distSqr(pos) > blockReachDistance * blockReachDistance) {
|
||||
continue;
|
||||
}
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
|
||||
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isBoneMeal)) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
@@ -359,6 +384,14 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
}
|
||||
}
|
||||
}
|
||||
if (goalz.isEmpty()) {
|
||||
logDirect("Farm failed");
|
||||
if (Baritone.settings().notificationOnFarmFail.value) {
|
||||
logNotification("Farm failed", true);
|
||||
}
|
||||
onLostControl();
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
return new PathingCommand(new GoalComposite(goalz.toArray(new Goal[0])), PathingCommandType.SET_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
|
||||
@@ -19,6 +19,7 @@ package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalNear;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
@@ -27,11 +28,14 @@ import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
import net.minecraft.world.entity.item.ItemEntity;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Collectors;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
|
||||
/**
|
||||
* Follow an entity
|
||||
@@ -42,6 +46,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
|
||||
private Predicate<Entity> filter;
|
||||
private List<Entity> cache;
|
||||
private boolean into; // walk straight into the target, regardless of settings
|
||||
|
||||
public FollowProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
@@ -56,12 +61,15 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
|
||||
private Goal towards(Entity following) {
|
||||
BlockPos pos;
|
||||
if (Baritone.settings().followOffsetDistance.value == 0) {
|
||||
if (Baritone.settings().followOffsetDistance.value == 0 || into) {
|
||||
pos = following.blockPosition();
|
||||
} else {
|
||||
GoalXZ g = GoalXZ.fromDirection(following.position(), Baritone.settings().followOffsetDirection.value, Baritone.settings().followOffsetDistance.value);
|
||||
pos = new BetterBlockPos(g.getX(), following.position().y, g.getZ());
|
||||
}
|
||||
if (into) {
|
||||
return new GoalBlock(pos);
|
||||
}
|
||||
return new GoalNear(pos, Baritone.settings().followRadius.value);
|
||||
}
|
||||
|
||||
@@ -76,6 +84,10 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
if (entity.equals(ctx.player())) {
|
||||
return false;
|
||||
}
|
||||
int maxDist = Baritone.settings().followTargetMaxDistance.value;
|
||||
if (maxDist != 0 && entity.distanceToSqr(ctx.player()) > maxDist * maxDist) {
|
||||
return false;
|
||||
}
|
||||
return ctx.entitiesStream().anyMatch(entity::equals);
|
||||
}
|
||||
|
||||
@@ -110,6 +122,13 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
@Override
|
||||
public void follow(Predicate<Entity> filter) {
|
||||
this.filter = filter;
|
||||
this.into = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void pickup(Predicate<ItemStack> filter) {
|
||||
this.filter = e -> e instanceof ItemEntity && filter.test(((ItemEntity) e).getItem());
|
||||
this.into = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -53,8 +53,6 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
*/
|
||||
public final class MineProcess extends BaritoneProcessHelper implements IMineProcess {
|
||||
|
||||
private static final int ORE_LOCATIONS_COUNT = 64;
|
||||
|
||||
private BlockOptionalMetaLookup filter;
|
||||
private List<BlockPos> knownOreLocations;
|
||||
private List<BlockPos> blacklist; // inaccessible
|
||||
@@ -79,7 +77,6 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
int curr = ctx.player().getInventory().items.stream()
|
||||
.filter(stack -> filter.has(stack))
|
||||
.mapToInt(ItemStack::getCount).sum();
|
||||
System.out.println("Currently have " + curr + " valid items");
|
||||
if (curr >= desiredQuantity) {
|
||||
logDirect("Have " + curr + " valid items");
|
||||
cancel();
|
||||
@@ -121,7 +118,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
.filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ())
|
||||
.filter(pos -> pos.getY() >= ctx.playerFeet().getY())
|
||||
.filter(pos -> !(BlockStateInterface.get(ctx, pos).getBlock() instanceof AirBlock)) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =(
|
||||
.min(Comparator.comparingDouble(ctx.playerFeet()::distSqr));
|
||||
.min(Comparator.comparingDouble(ctx.playerFeet().above()::distSqr));
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
if (shaft.isPresent() && ctx.player().onGround()) {
|
||||
BlockPos pos = shaft.get();
|
||||
@@ -186,7 +183,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
List<BlockPos> locs = knownOreLocations;
|
||||
if (!locs.isEmpty()) {
|
||||
CalculationContext context = new CalculationContext(baritone);
|
||||
List<BlockPos> locs2 = prune(context, new ArrayList<>(locs), filter, ORE_LOCATIONS_COUNT, blacklist, droppedItemsScan());
|
||||
List<BlockPos> locs2 = prune(context, new ArrayList<>(locs), filter, Baritone.settings().mineMaxOreLocationsCount.value, blacklist, droppedItemsScan());
|
||||
// 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
|
||||
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2, context)).toArray(Goal[]::new));
|
||||
knownOreLocations = locs2;
|
||||
@@ -235,7 +232,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
return;
|
||||
}
|
||||
List<BlockPos> dropped = droppedItemsScan();
|
||||
List<BlockPos> locs = searchWorld(context, filter, ORE_LOCATIONS_COUNT, already, blacklist, dropped);
|
||||
List<BlockPos> locs = searchWorld(context, filter, Baritone.settings().mineMaxOreLocationsCount.value, already, blacklist, dropped);
|
||||
locs.addAll(dropped);
|
||||
if (locs.isEmpty() && !Baritone.settings().exploreForBlocks.value) {
|
||||
logDirect("No locations for " + filter + " known, cancelling");
|
||||
@@ -425,7 +422,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
}
|
||||
}
|
||||
}
|
||||
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, filter, ORE_LOCATIONS_COUNT, blacklist, dropped);
|
||||
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, filter, Baritone.settings().mineMaxOreLocationsCount.value, blacklist, dropped);
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -488,7 +485,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
|
||||
|
||||
public static boolean plausibleToBreak(CalculationContext ctx, BlockPos pos) {
|
||||
if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), ctx.bsi.get0(pos), true) >= COST_INF) {
|
||||
BlockState state = ctx.bsi.get0(pos);
|
||||
if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), state, true) >= COST_INF) {
|
||||
return false;
|
||||
}
|
||||
if (MovementHelper.avoidBreaking(ctx.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
@@ -31,10 +31,12 @@ import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.IRenderer;
|
||||
import baritone.utils.PathRenderer;
|
||||
import baritone.utils.accessor.IFireworkRocketEntity;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import it.unimi.dsi.fastutil.floats.FloatArrayList;
|
||||
import it.unimi.dsi.fastutil.floats.FloatIterator;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.NonNullList;
|
||||
import net.minecraft.core.component.DataComponents;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.network.protocol.game.ClientboundPlayerPositionPacket;
|
||||
import net.minecraft.util.Mth;
|
||||
@@ -44,6 +46,7 @@ import net.minecraft.world.entity.projectile.FireworkRocketEntity;
|
||||
import net.minecraft.world.inventory.ClickType;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.component.Fireworks;
|
||||
import net.minecraft.world.level.ChunkPos;
|
||||
import net.minecraft.world.level.ClipContext;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
@@ -422,28 +425,28 @@ public final class ElytraBehavior implements Helper {
|
||||
PathRenderer.drawGoal(event.getModelViewStack(), ctx, new GoalBlock(this.aimPos), event.getPartialTicks(), Color.GREEN);
|
||||
}
|
||||
if (!this.clearLines.isEmpty() && settings.elytraRenderRaytraces.value) {
|
||||
IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(Color.GREEN, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
for (Pair<Vec3, Vec3> line : this.clearLines) {
|
||||
IRenderer.emitLine(event.getModelViewStack(), line.first(), line.second());
|
||||
IRenderer.emitLine(bufferBuilder, event.getModelViewStack(), line.first(), line.second());
|
||||
}
|
||||
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderPathIgnoreDepth.value);
|
||||
}
|
||||
if (!this.blockedLines.isEmpty() && Baritone.settings().elytraRenderRaytraces.value) {
|
||||
IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(Color.BLUE, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
for (Pair<Vec3, Vec3> line : this.blockedLines) {
|
||||
IRenderer.emitLine(event.getModelViewStack(), line.first(), line.second());
|
||||
IRenderer.emitLine(bufferBuilder, event.getModelViewStack(), line.first(), line.second());
|
||||
}
|
||||
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderPathIgnoreDepth.value);
|
||||
}
|
||||
if (this.simulationLine != null && Baritone.settings().elytraRenderSimulation.value) {
|
||||
IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(new Color(0x36CCDC), settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
final Vec3 offset = ctx.player().getPosition(event.getPartialTicks());
|
||||
for (int i = 0; i < this.simulationLine.size() - 1; i++) {
|
||||
final Vec3 src = this.simulationLine.get(i).add(offset);
|
||||
final Vec3 dst = this.simulationLine.get(i + 1).add(offset);
|
||||
IRenderer.emitLine(event.getModelViewStack(), src, dst);
|
||||
IRenderer.emitLine(bufferBuilder, event.getModelViewStack(), src, dst);
|
||||
}
|
||||
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderPathIgnoreDepth.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -922,9 +925,8 @@ public final class ElytraBehavior implements Helper {
|
||||
if (itemStack.getItem() != Items.FIREWORK_ROCKET) {
|
||||
return false;
|
||||
}
|
||||
// If it has NBT data, make sure it won't cause us to explode.
|
||||
final CompoundTag compound = itemStack.getTagElement("Fireworks");
|
||||
return compound == null || !compound.getAllKeys().contains("Explosions");
|
||||
Fireworks fw = itemStack.get(DataComponents.FIREWORKS);
|
||||
return fw != null && fw.explosions().isEmpty();
|
||||
}
|
||||
|
||||
private static boolean isBoostingFireworks(final ItemStack itemStack) {
|
||||
@@ -932,11 +934,9 @@ public final class ElytraBehavior implements Helper {
|
||||
}
|
||||
|
||||
private static OptionalInt getFireworkBoost(final ItemStack itemStack) {
|
||||
if (isFireworks(itemStack)) {
|
||||
final CompoundTag compound = itemStack.getTagElement("Fireworks");
|
||||
if (compound != null && compound.getAllKeys().contains("Flight")) {
|
||||
return OptionalInt.of(compound.getByte("Flight"));
|
||||
}
|
||||
Fireworks fw = itemStack.get(DataComponents.FIREWORKS);
|
||||
if (fw != null && fw.explosions().isEmpty()) {
|
||||
return OptionalInt.of(fw.flightDuration());
|
||||
}
|
||||
return OptionalInt.empty();
|
||||
}
|
||||
@@ -1292,7 +1292,7 @@ public final class ElytraBehavior implements Helper {
|
||||
NonNullList<ItemStack> invy = ctx.player().getInventory().items;
|
||||
for (int i = 0; i < invy.size(); i++) {
|
||||
ItemStack slot = invy.get(i);
|
||||
if (slot.getItem() == Items.ELYTRA && (slot.getItem().getMaxDamage() - slot.getDamageValue()) > Baritone.settings().elytraMinimumDurability.value) {
|
||||
if (slot.getItem() == Items.ELYTRA && (slot.getMaxDamage() - slot.getDamageValue()) > Baritone.settings().elytraMinimumDurability.value) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
@@ -1306,7 +1306,7 @@ public final class ElytraBehavior implements Helper {
|
||||
|
||||
ItemStack chest = ctx.player().getItemBySlot(EquipmentSlot.CHEST);
|
||||
if (chest.getItem() != Items.ELYTRA
|
||||
|| chest.getItem().getMaxDamage() - chest.getDamageValue() > Baritone.settings().elytraMinimumDurability.value) {
|
||||
|| chest.getMaxDamage() - chest.getDamageValue() > Baritone.settings().elytraMinimumDurability.value) {
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
@@ -37,7 +37,7 @@ public class Selection implements ISelection {
|
||||
max.z - min.z + 1
|
||||
);
|
||||
|
||||
this.aabb = new AABB(this.min);
|
||||
this.aabb = new AABB(min.x, min.y, min.z, max.x + 1, max.y + 1, max.z + 1);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,7 @@ import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.selection.ISelection;
|
||||
import baritone.utils.IRenderer;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
@@ -28,27 +29,27 @@ public class SelectionRenderer implements IRenderer, AbstractGameEventListener {
|
||||
return;
|
||||
}
|
||||
|
||||
IRenderer.startLines(settings.colorSelection.value, opacity, lineWidth, ignoreDepth);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(settings.colorSelection.value, opacity, lineWidth, ignoreDepth);
|
||||
|
||||
for (ISelection selection : selections) {
|
||||
IRenderer.emitAABB(stack, selection.aabb(), SELECTION_BOX_EXPANSION);
|
||||
IRenderer.emitAABB(bufferBuilder, stack, selection.aabb(), SELECTION_BOX_EXPANSION);
|
||||
}
|
||||
|
||||
if (settings.renderSelectionCorners.value) {
|
||||
IRenderer.glColor(settings.colorSelectionPos1.value, opacity);
|
||||
|
||||
for (ISelection selection : selections) {
|
||||
IRenderer.emitAABB(stack, new AABB(selection.pos1()));
|
||||
IRenderer.emitAABB(bufferBuilder, stack, new AABB(selection.pos1()));
|
||||
}
|
||||
|
||||
IRenderer.glColor(settings.colorSelectionPos2.value, opacity);
|
||||
|
||||
for (ISelection selection : selections) {
|
||||
IRenderer.emitAABB(stack, new AABB(selection.pos2()));
|
||||
IRenderer.emitAABB(bufferBuilder, stack, new AABB(selection.pos2()));
|
||||
}
|
||||
}
|
||||
|
||||
IRenderer.endLines(ignoreDepth);
|
||||
IRenderer.endLines(bufferBuilder, ignoreDepth);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,7 +17,9 @@
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.utils.accessor.IPlayerControllerMP;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
@@ -27,9 +29,12 @@ import net.minecraft.world.phys.HitResult;
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
public final class BlockBreakHelper {
|
||||
// base ticks between block breaks caused by tick logic
|
||||
private static final int BASE_BREAK_DELAY = 1;
|
||||
|
||||
private final IPlayerContext ctx;
|
||||
private boolean didBreakLastTick;
|
||||
private boolean wasHitting;
|
||||
private int breakDelayTimer = 0;
|
||||
|
||||
BlockBreakHelper(IPlayerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
@@ -37,38 +42,46 @@ public final class BlockBreakHelper {
|
||||
|
||||
public void stopBreakingBlock() {
|
||||
// The player controller will never be null, but the player can be
|
||||
if (ctx.player() != null && didBreakLastTick) {
|
||||
if (!ctx.playerController().hasBrokenBlock()) {
|
||||
// insane bypass to check breaking succeeded
|
||||
ctx.playerController().setHittingBlock(true);
|
||||
}
|
||||
if (ctx.player() != null && wasHitting) {
|
||||
ctx.playerController().setHittingBlock(false);
|
||||
ctx.playerController().resetBlockRemoving();
|
||||
didBreakLastTick = false;
|
||||
wasHitting = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void tick(boolean isLeftClick) {
|
||||
if (breakDelayTimer > 0) {
|
||||
breakDelayTimer--;
|
||||
return;
|
||||
}
|
||||
HitResult trace = ctx.objectMouseOver();
|
||||
boolean isBlockTrace = trace != null && trace.getType() == HitResult.Type.BLOCK;
|
||||
|
||||
if (isLeftClick && isBlockTrace) {
|
||||
if (!didBreakLastTick) {
|
||||
ctx.playerController().setHittingBlock(wasHitting);
|
||||
if (ctx.playerController().hasBrokenBlock()) {
|
||||
ctx.playerController().syncHeldItem();
|
||||
ctx.playerController().clickBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection());
|
||||
ctx.player().swing(InteractionHand.MAIN_HAND);
|
||||
} else {
|
||||
if (ctx.playerController().onPlayerDamageBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection())) {
|
||||
ctx.player().swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
if (ctx.playerController().hasBrokenBlock()) { // block broken this tick
|
||||
// break delay timer only applies for multi-tick block breaks like vanilla
|
||||
breakDelayTimer = BaritoneAPI.getSettings().blockBreakSpeed.value - BASE_BREAK_DELAY;
|
||||
// must reset controller's destroy delay to prevent the client from delaying itself unnecessarily
|
||||
((IPlayerControllerMP) ctx.minecraft().gameMode).setDestroyDelay(0);
|
||||
}
|
||||
}
|
||||
|
||||
// Attempt to break the block
|
||||
if (ctx.playerController().onPlayerDamageBlock(((BlockHitResult) trace).getBlockPos(), ((BlockHitResult) trace).getDirection())) {
|
||||
ctx.player().swing(InteractionHand.MAIN_HAND);
|
||||
}
|
||||
|
||||
// if true, we're breaking a block. if false, we broke the block this tick
|
||||
wasHitting = !ctx.playerController().hasBrokenBlock();
|
||||
// this value will be reset by the MC client handling mouse keys
|
||||
// since we're not spoofing the click keybind to the client, the client will stop the break if isDestroyingBlock is true
|
||||
// we store and restore this value on the next tick to determine if we're breaking a block
|
||||
ctx.playerController().setHittingBlock(false);
|
||||
|
||||
didBreakLastTick = true;
|
||||
} else if (didBreakLastTick) {
|
||||
stopBreakingBlock();
|
||||
didBreakLastTick = false;
|
||||
} else {
|
||||
wasHitting = false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,8 @@ import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
|
||||
public class BlockPlaceHelper {
|
||||
// base ticks between places caused by tick logic
|
||||
private static final int BASE_PLACE_DELAY = 1;
|
||||
|
||||
private final IPlayerContext ctx;
|
||||
private int rightClickTimer;
|
||||
@@ -42,7 +44,7 @@ public class BlockPlaceHelper {
|
||||
if (!rightClickRequested || ctx.player().isHandsBusy() || mouseOver == null || mouseOver.getType() != HitResult.Type.BLOCK) {
|
||||
return;
|
||||
}
|
||||
rightClickTimer = Baritone.settings().rightClickSpeed.value;
|
||||
rightClickTimer = Baritone.settings().rightClickSpeed.value - BASE_PLACE_DELAY;
|
||||
for (InteractionHand hand : InteractionHand.values()) {
|
||||
if (ctx.playerController().processRightClickBlock(ctx.player(), ctx.world(), hand, (BlockHitResult) mouseOver) == InteractionResult.SUCCESS) {
|
||||
ctx.player().swing(hand);
|
||||
|
||||
@@ -30,9 +30,9 @@ import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.chunk.ChunkStatus;
|
||||
import net.minecraft.world.level.chunk.LevelChunk;
|
||||
import net.minecraft.world.level.chunk.LevelChunkSection;
|
||||
import net.minecraft.world.level.chunk.status.ChunkStatus;
|
||||
|
||||
/**
|
||||
* Wraps get for chuck caching capability
|
||||
@@ -70,7 +70,7 @@ public class BlockStateInterface {
|
||||
}
|
||||
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value;
|
||||
if (!ctx.minecraft().isSameThread()) {
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("BlockStateInterface must be constructed on the main thread");
|
||||
}
|
||||
this.isPassableBlockPos = new BlockPos.MutableBlockPos();
|
||||
this.access = new BlockStateInterfaceAccessWrapper(this);
|
||||
|
||||
@@ -56,12 +56,12 @@ public final class BlockStateInterfaceAccessWrapper implements BlockGetter {
|
||||
|
||||
@Override
|
||||
public int getHeight() {
|
||||
return 255;
|
||||
return bsi.world.getHeight();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMinBuildHeight() {
|
||||
return 0;
|
||||
return bsi.world.getMinBuildHeight();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import baritone.api.BaritoneAPI;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.client.gui.GuiGraphics;
|
||||
@@ -74,13 +75,11 @@ public class GuiClick extends Screen implements Helper {
|
||||
Vec3 far = toWorld(mx, my, 1); // "Use 0.945 that's what stack overflow says" - leijurv
|
||||
|
||||
if (near != null && far != null) {
|
||||
///
|
||||
Vec3 viewerPos = new Vec3(PathRenderer.posX(), PathRenderer.posY(), PathRenderer.posZ());
|
||||
LocalPlayer player = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().player();
|
||||
HitResult result = player.level().clip(new ClipContext(near.add(viewerPos), far.add(viewerPos), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player));
|
||||
if (result != null && result.getType() == HitResult.Type.BLOCK) {
|
||||
currentMouseOver = ((BlockHitResult) result).getBlockPos();
|
||||
System.out.println("currentMouseOver = " + currentMouseOver);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -128,11 +127,11 @@ public class GuiClick extends Screen implements Helper {
|
||||
// drawSingleSelectionBox WHEN?
|
||||
PathRenderer.drawManySelectionBoxes(modelViewStack, e, Collections.singletonList(currentMouseOver), Color.CYAN);
|
||||
if (clickStart != null && !clickStart.equals(currentMouseOver)) {
|
||||
IRenderer.startLines(Color.RED, Baritone.settings().pathRenderLineWidthPixels.value, true);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(Color.RED, Baritone.settings().pathRenderLineWidthPixels.value, true);
|
||||
BetterBlockPos a = new BetterBlockPos(currentMouseOver);
|
||||
BetterBlockPos b = new BetterBlockPos(clickStart);
|
||||
IRenderer.emitAABB(modelViewStack, new AABB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
|
||||
IRenderer.endLines(true);
|
||||
IRenderer.emitAABB(bufferBuilder, modelViewStack, new AABB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
|
||||
IRenderer.endLines(bufferBuilder, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,15 +28,12 @@ import net.minecraft.client.renderer.GameRenderer;
|
||||
import net.minecraft.client.renderer.texture.TextureManager;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import org.joml.Matrix3f;
|
||||
import org.joml.Matrix4f;
|
||||
|
||||
import java.awt.*;
|
||||
|
||||
public interface IRenderer {
|
||||
|
||||
Tesselator tessellator = Tesselator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuilder();
|
||||
IEntityRenderManager renderManager = (IEntityRenderManager) Minecraft.getInstance().getEntityRenderDispatcher();
|
||||
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
|
||||
Settings settings = BaritoneAPI.getSettings();
|
||||
@@ -51,7 +48,7 @@ public interface IRenderer {
|
||||
IRenderer.color[3] = alpha;
|
||||
}
|
||||
|
||||
static void startLines(Color color, float alpha, float lineWidth, boolean ignoreDepth) {
|
||||
static BufferBuilder startLines(Color color, float alpha, float lineWidth, boolean ignoreDepth) {
|
||||
RenderSystem.enableBlend();
|
||||
RenderSystem.setShader(GameRenderer::getPositionColorShader);
|
||||
RenderSystem.blendFuncSeparate(
|
||||
@@ -69,15 +66,19 @@ public interface IRenderer {
|
||||
RenderSystem.disableDepthTest();
|
||||
}
|
||||
RenderSystem.setShader(GameRenderer::getRendertypeLinesShader);
|
||||
buffer.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL);
|
||||
return tessellator.begin(VertexFormat.Mode.LINES, DefaultVertexFormat.POSITION_COLOR_NORMAL);
|
||||
}
|
||||
|
||||
static void startLines(Color color, float lineWidth, boolean ignoreDepth) {
|
||||
startLines(color, .4f, lineWidth, ignoreDepth);
|
||||
static BufferBuilder startLines(Color color, float lineWidth, boolean ignoreDepth) {
|
||||
return startLines(color, .4f, lineWidth, ignoreDepth);
|
||||
}
|
||||
|
||||
static void endLines(boolean ignoredDepth) {
|
||||
tessellator.end();
|
||||
static void endLines(BufferBuilder bufferBuilder, boolean ignoredDepth) {
|
||||
MeshData meshData = bufferBuilder.build();
|
||||
if (meshData != null) {
|
||||
BufferUploader.drawWithShader(meshData);
|
||||
}
|
||||
|
||||
if (ignoredDepth) {
|
||||
RenderSystem.enableDepthTest();
|
||||
}
|
||||
@@ -87,7 +88,7 @@ public interface IRenderer {
|
||||
RenderSystem.disableBlend();
|
||||
}
|
||||
|
||||
static void emitLine(PoseStack stack, double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
static void emitLine(BufferBuilder bufferBuilder, PoseStack stack, double x1, double y1, double z1, double x2, double y2, double z2) {
|
||||
final double dx = x2 - x1;
|
||||
final double dy = y2 - y1;
|
||||
final double dz = z2 - z1;
|
||||
@@ -97,60 +98,59 @@ public interface IRenderer {
|
||||
final float ny = (float) (dy * invMag);
|
||||
final float nz = (float) (dz * invMag);
|
||||
|
||||
emitLine(stack, x1, y1, z1, x2, y2, z2, nx, ny, nz);
|
||||
emitLine(bufferBuilder, stack, x1, y1, z1, x2, y2, z2, nx, ny, nz);
|
||||
}
|
||||
|
||||
static void emitLine(PoseStack stack,
|
||||
static void emitLine(BufferBuilder bufferBuilder, PoseStack stack,
|
||||
double x1, double y1, double z1,
|
||||
double x2, double y2, double z2,
|
||||
double nx, double ny, double nz) {
|
||||
emitLine(stack,
|
||||
emitLine(bufferBuilder, stack,
|
||||
(float) x1, (float) y1, (float) z1,
|
||||
(float) x2, (float) y2, (float) z2,
|
||||
(float) nx, (float) ny, (float) nz
|
||||
);
|
||||
}
|
||||
|
||||
static void emitLine(PoseStack stack,
|
||||
static void emitLine(BufferBuilder bufferBuilder, PoseStack stack,
|
||||
float x1, float y1, float z1,
|
||||
float x2, float y2, float z2,
|
||||
float nx, float ny, float nz) {
|
||||
final Matrix4f matrix4f = stack.last().pose();
|
||||
final Matrix3f normal = stack.last().normal();
|
||||
PoseStack.Pose pose = stack.last();
|
||||
|
||||
buffer.vertex(matrix4f, x1, y1, z1).color(color[0], color[1], color[2], color[3]).normal(normal, nx, ny, nz).endVertex();
|
||||
buffer.vertex(matrix4f, x2, y2, z2).color(color[0], color[1], color[2], color[3]).normal(normal, nx, ny, nz).endVertex();
|
||||
bufferBuilder.addVertex(pose, x1, y1, z1).setColor(color[0], color[1], color[2], color[3]).setNormal(pose, nx, ny, nz);
|
||||
bufferBuilder.addVertex(pose, x2, y2, z2).setColor(color[0], color[1], color[2], color[3]).setNormal(pose, nx, ny, nz);
|
||||
}
|
||||
|
||||
static void emitAABB(PoseStack stack, AABB aabb) {
|
||||
static void emitAABB(BufferBuilder bufferBuilder, PoseStack stack, AABB aabb) {
|
||||
AABB toDraw = aabb.move(-renderManager.renderPosX(), -renderManager.renderPosY(), -renderManager.renderPosZ());
|
||||
|
||||
// bottom
|
||||
emitLine(stack, toDraw.minX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.minY, toDraw.minZ, 1.0, 0.0, 0.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.minY, toDraw.maxZ, 0.0, 0.0, 1.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.minY, toDraw.maxZ, -1.0, 0.0, 0.0);
|
||||
emitLine(stack, toDraw.minX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.minY, toDraw.minZ, 0.0, 0.0, -1.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.minY, toDraw.minZ, 1.0, 0.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.minY, toDraw.maxZ, 0.0, 0.0, 1.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.minY, toDraw.maxZ, -1.0, 0.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.minY, toDraw.minZ, 0.0, 0.0, -1.0);
|
||||
// top
|
||||
emitLine(stack, toDraw.minX, toDraw.maxY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.minZ, 1.0, 0.0, 0.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.maxY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.maxZ, 0.0, 0.0, 1.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.maxY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.maxZ, -1.0, 0.0, 0.0);
|
||||
emitLine(stack, toDraw.minX, toDraw.maxY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.minZ, 0.0, 0.0, -1.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.maxY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.minZ, 1.0, 0.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.maxY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.maxZ, 0.0, 0.0, 1.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.maxY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.maxZ, -1.0, 0.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.maxY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.minZ, 0.0, 0.0, -1.0);
|
||||
// corners
|
||||
emitLine(stack, toDraw.minX, toDraw.minY, toDraw.minZ, toDraw.minX, toDraw.maxY, toDraw.minZ, 0.0, 1.0, 0.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.minZ, 0.0, 1.0, 0.0);
|
||||
emitLine(stack, toDraw.maxX, toDraw.minY, toDraw.maxZ, toDraw.maxX, toDraw.maxY, toDraw.maxZ, 0.0, 1.0, 0.0);
|
||||
emitLine(stack, toDraw.minX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.maxZ, 0.0, 1.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.minY, toDraw.minZ, toDraw.minX, toDraw.maxY, toDraw.minZ, 0.0, 1.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.minY, toDraw.minZ, toDraw.maxX, toDraw.maxY, toDraw.minZ, 0.0, 1.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.maxX, toDraw.minY, toDraw.maxZ, toDraw.maxX, toDraw.maxY, toDraw.maxZ, 0.0, 1.0, 0.0);
|
||||
emitLine(bufferBuilder, stack, toDraw.minX, toDraw.minY, toDraw.maxZ, toDraw.minX, toDraw.maxY, toDraw.maxZ, 0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
static void emitAABB(PoseStack stack, AABB aabb, double expand) {
|
||||
emitAABB(stack, aabb.inflate(expand, expand, expand));
|
||||
static void emitAABB(BufferBuilder bufferBuilder, PoseStack stack, AABB aabb, double expand) {
|
||||
emitAABB(bufferBuilder, stack, aabb.inflate(expand, expand, expand));
|
||||
}
|
||||
|
||||
static void emitLine(PoseStack stack, Vec3 start, Vec3 end) {
|
||||
static void emitLine(BufferBuilder bufferBuilder, PoseStack stack, Vec3 start, Vec3 end) {
|
||||
double vpX = renderManager.renderPosX();
|
||||
double vpY = renderManager.renderPosY();
|
||||
double vpZ = renderManager.renderPosZ();
|
||||
emitLine(stack, start.x - vpX, start.y - vpY, start.z - vpZ, end.x - vpX, end.y - vpY, end.z - vpZ);
|
||||
emitLine(bufferBuilder, stack, start.x - vpX, start.y - vpY, start.z - vpZ, end.x - vpX, end.y - vpY, end.z - vpZ);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,6 +26,7 @@ import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import com.mojang.blaze3d.systems.RenderSystem;
|
||||
import com.mojang.blaze3d.vertex.BufferBuilder;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.renderer.blockentity.BeaconRenderer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -37,6 +38,7 @@ import net.minecraft.world.level.dimension.DimensionType;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.shapes.Shapes;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
import org.jetbrains.annotations.Nullable;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Arrays;
|
||||
@@ -50,7 +52,7 @@ import java.util.List;
|
||||
*/
|
||||
public final class PathRenderer implements IRenderer {
|
||||
|
||||
private static final ResourceLocation TEXTURE_BEACON_BEAM = new ResourceLocation("textures/entity/beacon_beam.png");
|
||||
private static final ResourceLocation TEXTURE_BEACON_BEAM = ResourceLocation.parse("textures/entity/beacon_beam.png");
|
||||
|
||||
|
||||
private PathRenderer() {}
|
||||
@@ -133,7 +135,7 @@ public final class PathRenderer implements IRenderer {
|
||||
}
|
||||
|
||||
public static void drawPath(PoseStack stack, List<BetterBlockPos> positions, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0, double offset) {
|
||||
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
|
||||
|
||||
int fadeStart = fadeStart0 + startIndex;
|
||||
int fadeEnd = fadeEnd0 + startIndex;
|
||||
@@ -167,13 +169,13 @@ public final class PathRenderer implements IRenderer {
|
||||
IRenderer.glColor(color, alpha);
|
||||
}
|
||||
|
||||
emitPathLine(stack, start.x, start.y, start.z, end.x, end.y, end.z, offset);
|
||||
emitPathLine(bufferBuilder, stack, start.x, start.y, start.z, end.x, end.y, end.z, offset);
|
||||
}
|
||||
|
||||
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderPathIgnoreDepth.value);
|
||||
}
|
||||
|
||||
private static void emitPathLine(PoseStack stack, double x1, double y1, double z1, double x2, double y2, double z2, double offset) {
|
||||
private static void emitPathLine(BufferBuilder bufferBuilder, PoseStack stack, double x1, double y1, double z1, double x2, double y2, double z2, double offset) {
|
||||
final double extraOffset = offset + 0.03D;
|
||||
|
||||
double vpX = posX();
|
||||
@@ -181,20 +183,20 @@ public final class PathRenderer implements IRenderer {
|
||||
double vpZ = posZ();
|
||||
boolean renderPathAsFrickinThingy = !settings.renderPathAsLine.value;
|
||||
|
||||
IRenderer.emitLine(stack,
|
||||
IRenderer.emitLine(bufferBuilder, stack,
|
||||
x1 + offset - vpX, y1 + offset - vpY, z1 + offset - vpZ,
|
||||
x2 + offset - vpX, y2 + offset - vpY, z2 + offset - vpZ
|
||||
);
|
||||
if (renderPathAsFrickinThingy) {
|
||||
IRenderer.emitLine(stack,
|
||||
IRenderer.emitLine(bufferBuilder, stack,
|
||||
x2 + offset - vpX, y2 + offset - vpY, z2 + offset - vpZ,
|
||||
x2 + offset - vpX, y2 + extraOffset - vpY, z2 + offset - vpZ
|
||||
);
|
||||
IRenderer.emitLine(stack,
|
||||
IRenderer.emitLine(bufferBuilder, stack,
|
||||
x2 + offset - vpX, y2 + extraOffset - vpY, z2 + offset - vpZ,
|
||||
x1 + offset - vpX, y1 + extraOffset - vpY, z1 + offset - vpZ
|
||||
);
|
||||
IRenderer.emitLine(stack,
|
||||
IRenderer.emitLine(bufferBuilder, stack,
|
||||
x1 + offset - vpX, y1 + extraOffset - vpY, z1 + offset - vpZ,
|
||||
x1 + offset - vpX, y1 + offset - vpY, z1 + offset - vpZ
|
||||
);
|
||||
@@ -202,7 +204,7 @@ public final class PathRenderer implements IRenderer {
|
||||
}
|
||||
|
||||
public static void drawManySelectionBoxes(PoseStack stack, Entity player, Collection<BlockPos> positions, Color color) {
|
||||
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderSelectionBoxesIgnoreDepth.value);
|
||||
BufferBuilder bufferBuilder = IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderSelectionBoxesIgnoreDepth.value);
|
||||
|
||||
//BlockPos blockpos = movingObjectPositionIn.getBlockPos();
|
||||
BlockStateInterface bsi = new BlockStateInterface(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()); // TODO this assumes same dimension between primary baritone and render view? is this safe?
|
||||
@@ -212,17 +214,20 @@ public final class PathRenderer implements IRenderer {
|
||||
VoxelShape shape = state.getShape(player.level(), pos);
|
||||
AABB toDraw = shape.isEmpty() ? Shapes.block().bounds() : shape.bounds();
|
||||
toDraw = toDraw.move(pos);
|
||||
IRenderer.emitAABB(stack, toDraw, .002D);
|
||||
IRenderer.emitAABB(bufferBuilder, stack, toDraw, .002D);
|
||||
});
|
||||
|
||||
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderSelectionBoxesIgnoreDepth.value);
|
||||
}
|
||||
|
||||
public static void drawGoal(PoseStack stack, IPlayerContext ctx, Goal goal, float partialTicks, Color color) {
|
||||
drawGoal(stack, ctx, goal, partialTicks, color, true);
|
||||
drawGoal(null, stack, ctx, goal, partialTicks, color, true);
|
||||
}
|
||||
|
||||
private static void drawGoal(PoseStack stack, IPlayerContext ctx, Goal goal, float partialTicks, Color color, boolean setupRender) {
|
||||
private static void drawGoal(@Nullable BufferBuilder bufferBuilder, PoseStack stack, IPlayerContext ctx, Goal goal, float partialTicks, Color color, boolean setupRender) {
|
||||
if (!setupRender && bufferBuilder == null) {
|
||||
throw new RuntimeException("BufferBuilder must not be null if setupRender is false");
|
||||
}
|
||||
double renderPosX = posX();
|
||||
double renderPosY = posY();
|
||||
double renderPosZ = posZ();
|
||||
@@ -254,7 +259,7 @@ public final class PathRenderer implements IRenderer {
|
||||
y2 -= 0.5;
|
||||
maxY--;
|
||||
}
|
||||
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
drawDankLitGoalBox(bufferBuilder, stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
} else if (goal instanceof GoalXZ) {
|
||||
GoalXZ goalPos = (GoalXZ) goal;
|
||||
minY = ctx.world().getMinBuildHeight();
|
||||
@@ -280,7 +285,7 @@ public final class PathRenderer implements IRenderer {
|
||||
settings.renderGoalAnimated.value ? ctx.world().getGameTime() : 0,
|
||||
(int) minY,
|
||||
(int) maxY,
|
||||
color.getColorComponents(null),
|
||||
color.getRGB(),
|
||||
|
||||
// Arguments filled by the private method lol
|
||||
0.2F,
|
||||
@@ -304,19 +309,19 @@ public final class PathRenderer implements IRenderer {
|
||||
y2 = 0;
|
||||
minY -= renderPosY;
|
||||
maxY -= renderPosY;
|
||||
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
drawDankLitGoalBox(bufferBuilder, stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
} else if (goal instanceof GoalComposite) {
|
||||
// Simple way to determine if goals can be batched, without having some sort of GoalRenderer
|
||||
boolean batch = Arrays.stream(((GoalComposite) goal).goals()).allMatch(IGoalRenderPos.class::isInstance);
|
||||
|
||||
BufferBuilder buf = bufferBuilder;
|
||||
if (batch) {
|
||||
IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
|
||||
buf = IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
|
||||
}
|
||||
for (Goal g : ((GoalComposite) goal).goals()) {
|
||||
drawGoal(stack, ctx, g, partialTicks, color, !batch);
|
||||
drawGoal(buf, stack, ctx, g, partialTicks, color, !batch);
|
||||
}
|
||||
if (batch) {
|
||||
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
|
||||
IRenderer.endLines(buf, settings.renderGoalIgnoreDepth.value);
|
||||
}
|
||||
} else if (goal instanceof GoalInverted) {
|
||||
drawGoal(stack, ctx, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
|
||||
@@ -330,37 +335,37 @@ public final class PathRenderer implements IRenderer {
|
||||
maxY = minY + 2;
|
||||
y1 = 1 + y + goalpos.level - renderPosY;
|
||||
y2 = 1 - y + goalpos.level - renderPosY;
|
||||
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
drawDankLitGoalBox(bufferBuilder, stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
|
||||
}
|
||||
}
|
||||
|
||||
private static void drawDankLitGoalBox(PoseStack stack, Color colorIn, double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double y1, double y2, boolean setupRender) {
|
||||
private static void drawDankLitGoalBox(BufferBuilder bufferBuilder, PoseStack stack, Color colorIn, double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double y1, double y2, boolean setupRender) {
|
||||
if (setupRender) {
|
||||
IRenderer.startLines(colorIn, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
|
||||
bufferBuilder = IRenderer.startLines(colorIn, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
|
||||
}
|
||||
|
||||
renderHorizontalQuad(stack, minX, maxX, minZ, maxZ, y1);
|
||||
renderHorizontalQuad(stack, minX, maxX, minZ, maxZ, y2);
|
||||
renderHorizontalQuad(bufferBuilder, stack, minX, maxX, minZ, maxZ, y1);
|
||||
renderHorizontalQuad(bufferBuilder, stack, minX, maxX, minZ, maxZ, y2);
|
||||
|
||||
for (double y = minY; y < maxY; y += 16) {
|
||||
double max = Math.min(maxY, y + 16);
|
||||
IRenderer.emitLine(stack, minX, y, minZ, minX, max, minZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(stack, maxX, y, minZ, maxX, max, minZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(stack, maxX, y, maxZ, maxX, max, maxZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(stack, minX, y, maxZ, minX, max, maxZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, minX, y, minZ, minX, max, minZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, maxX, y, minZ, maxX, max, minZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, maxX, y, maxZ, maxX, max, maxZ, 0.0, 1.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, minX, y, maxZ, minX, max, maxZ, 0.0, 1.0, 0.0);
|
||||
}
|
||||
|
||||
if (setupRender) {
|
||||
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
|
||||
IRenderer.endLines(bufferBuilder, settings.renderGoalIgnoreDepth.value);
|
||||
}
|
||||
}
|
||||
|
||||
private static void renderHorizontalQuad(PoseStack stack, double minX, double maxX, double minZ, double maxZ, double y) {
|
||||
private static void renderHorizontalQuad(BufferBuilder bufferBuilder, PoseStack stack, double minX, double maxX, double minZ, double maxZ, double y) {
|
||||
if (y != 0) {
|
||||
IRenderer.emitLine(stack, minX, y, minZ, maxX, y, minZ, 1.0, 0.0, 0.0);
|
||||
IRenderer.emitLine(stack, maxX, y, minZ, maxX, y, maxZ, 0.0, 0.0, 1.0);
|
||||
IRenderer.emitLine(stack, maxX, y, maxZ, minX, y, maxZ, -1.0, 0.0, 0.0);
|
||||
IRenderer.emitLine(stack, minX, y, maxZ, minX, y, minZ, 0.0, 0.0, -1.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, minX, y, minZ, maxX, y, minZ, 1.0, 0.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, maxX, y, minZ, maxX, y, maxZ, 0.0, 0.0, 1.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, maxX, y, maxZ, minX, y, maxZ, -1.0, 0.0, 0.0);
|
||||
IRenderer.emitLine(bufferBuilder, stack, minX, y, maxZ, minX, y, minZ, 0.0, 0.0, -1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -68,7 +68,7 @@ public class PathingControlManager implements IPathingControlManager {
|
||||
for (IBaritoneProcess proc : processes) {
|
||||
proc.onLostControl();
|
||||
if (proc.isActive() && !proc.isTemporary()) { // it's okay only for a temporary thing (like combat pause) to maintain control even if you say to cancel
|
||||
throw new IllegalStateException(proc.displayName());
|
||||
throw new IllegalStateException(proc.displayName() + " stayed active after being cancelled");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -121,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager {
|
||||
}
|
||||
break;
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
throw new IllegalStateException("Unexpected command type " + command.commandType);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -19,16 +19,19 @@ package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.Holder;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.entity.ai.attributes.Attributes;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.SwordItem;
|
||||
import net.minecraft.world.item.TieredItem;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.item.enchantment.*;
|
||||
import net.minecraft.world.item.enchantment.effects.EnchantmentAttributeEffect;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
@@ -86,14 +89,22 @@ public class ToolSet {
|
||||
private int getMaterialCost(ItemStack itemStack) {
|
||||
if (itemStack.getItem() instanceof TieredItem) {
|
||||
TieredItem tool = (TieredItem) itemStack.getItem();
|
||||
return tool.getTier().getLevel();
|
||||
return (int) tool.getTier().getAttackDamageBonus();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSilkTouch(ItemStack stack) {
|
||||
return EnchantmentHelper.getItemEnchantmentLevel(Enchantments.SILK_TOUCH, stack) > 0;
|
||||
ItemEnchantments enchantments = stack.getEnchantments();
|
||||
for (Holder<Enchantment> enchant : enchantments.keySet()) {
|
||||
// silk touch enchantment is still special cased as affecting block drops
|
||||
// not possible to add custom attribute via datapack
|
||||
if (enchant.is(Enchantments.SILK_TOUCH) && enchantments.getLevel(enchant) > 0) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -177,16 +188,28 @@ public class ToolSet {
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public static double calculateSpeedVsBlock(ItemStack item, BlockState state) {
|
||||
float hardness = state.getDestroySpeed(null, null);
|
||||
float hardness;
|
||||
try {
|
||||
hardness = state.getDestroySpeed(null, null);
|
||||
} catch (NullPointerException npe) {
|
||||
// can't easily determine the hardness so treat it as unbreakable
|
||||
return -1;
|
||||
}
|
||||
if (hardness < 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
float speed = item.getDestroySpeed(state);
|
||||
if (speed > 1) {
|
||||
int effLevel = EnchantmentHelper.getItemEnchantmentLevel(Enchantments.BLOCK_EFFICIENCY, item);
|
||||
if (effLevel > 0 && !item.isEmpty()) {
|
||||
speed += effLevel * effLevel + 1;
|
||||
final ItemEnchantments itemEnchantments = item.getEnchantments();
|
||||
OUTER: for (Holder<Enchantment> enchant : itemEnchantments.keySet()) {
|
||||
List<EnchantmentAttributeEffect> effects = enchant.value().getEffects(EnchantmentEffectComponents.ATTRIBUTES);
|
||||
for (EnchantmentAttributeEffect e : effects) {
|
||||
if (e.attribute().is(Attributes.MINING_EFFICIENCY.unwrapKey().get())) {
|
||||
speed += e.amount().calculate(itemEnchantments.getLevel(enchant));
|
||||
break OUTER;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -23,7 +23,11 @@ public interface IPlayerControllerMP {
|
||||
|
||||
void setIsHittingBlock(boolean isHittingBlock);
|
||||
|
||||
boolean isHittingBlock();
|
||||
|
||||
BlockPos getCurrentBlock();
|
||||
|
||||
void callSyncCurrentPlayItem();
|
||||
|
||||
void setDestroyDelay(int destroyDelay);
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ package baritone.utils.player;
|
||||
import baritone.api.utils.IPlayerController;
|
||||
import baritone.utils.accessor.IPlayerControllerMP;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
@@ -54,7 +53,7 @@ public final class BaritonePlayerController implements IPlayerController {
|
||||
|
||||
@Override
|
||||
public boolean hasBrokenBlock() {
|
||||
return ((IPlayerControllerMP) mc.gameMode).getCurrentBlock().getY() == -1;
|
||||
return !((IPlayerControllerMP) mc.gameMode).isHittingBlock();
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -41,6 +41,7 @@ public class MapArtSchematic extends MaskSchematic {
|
||||
private static int[][] generateHeightMap(IStaticSchematic schematic) {
|
||||
int[][] heightMap = new int[schematic.widthX()][schematic.lengthZ()];
|
||||
|
||||
int missingColumns = 0;
|
||||
for (int x = 0; x < schematic.widthX(); x++) {
|
||||
for (int z = 0; z < schematic.lengthZ(); z++) {
|
||||
BlockState[] column = schematic.getColumn(x, z);
|
||||
@@ -48,12 +49,14 @@ public class MapArtSchematic extends MaskSchematic {
|
||||
if (lowestBlockY.isPresent()) {
|
||||
heightMap[x][z] = lowestBlockY.getAsInt();
|
||||
} else {
|
||||
System.out.println("Column " + x + "," + z + " has no blocks, but it's apparently map art? wtf");
|
||||
System.out.println("Letting it be whatever");
|
||||
heightMap[x][z] = 256;
|
||||
missingColumns++;
|
||||
heightMap[x][z] = Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (missingColumns != 0) {
|
||||
System.out.println(missingColumns + " columns had no block despite being in a map art, letting them be whatever");
|
||||
}
|
||||
return heightMap;
|
||||
}
|
||||
|
||||
|
||||
@@ -24,6 +24,7 @@ import baritone.utils.schematic.format.DefaultSchematicFormats;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -48,4 +49,9 @@ public enum SchematicSystem implements ISchematicSystem {
|
||||
public Optional<ISchematicFormat> getByFile(File file) {
|
||||
return this.registry.stream().filter(format -> format.isFileType(file)).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFileExtensions() {
|
||||
return this.registry.stream().map(ISchematicFormat::getFileExtensions).flatMap(List::stream).toList();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,6 +32,16 @@ public class StaticSchematic extends AbstractSchematic implements IStaticSchemat
|
||||
|
||||
protected BlockState[][][] states;
|
||||
|
||||
public StaticSchematic() {}
|
||||
|
||||
public StaticSchematic(BlockState[][][] states) {
|
||||
this.states = states;
|
||||
boolean empty = states.length == 0 || states[0].length == 0 || states[0][0].length == 0;
|
||||
this.x = empty ? 0 : states.length;
|
||||
this.z = empty ? 0 : states[0].length;
|
||||
this.y = empty ? 0 : states[0][0].length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
|
||||
return this.states[x][z][y];
|
||||
|
||||
@@ -22,14 +22,16 @@ import baritone.api.schematic.format.ISchematicFormat;
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.utils.schematic.format.defaults.MCEditSchematic;
|
||||
import baritone.utils.schematic.format.defaults.SpongeSchematic;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtAccounter;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* Default implementations of {@link ISchematicFormat}
|
||||
@@ -81,8 +83,10 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
|
||||
case 4: //1.12
|
||||
case 5: //1.13-1.17
|
||||
throw new UnsupportedOperationException("This litematic Version is too old.");
|
||||
case 6: //1.18+
|
||||
return new LitematicaSchematic(nbt, false);
|
||||
case 6: //1.18-1.20
|
||||
throw new UnsupportedOperationException("This litematic Version is too old.");
|
||||
case 7: //1.21+
|
||||
return new LitematicaSchematic(nbt);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsuported Version of a Litematica Schematic");
|
||||
}
|
||||
@@ -99,4 +103,9 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
|
||||
public boolean isFileType(File file) {
|
||||
return this.extension.equalsIgnoreCase(FilenameUtils.getExtension(file.getAbsolutePath()));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getFileExtensions() {
|
||||
return Collections.singletonList(this.extension);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,9 @@
|
||||
|
||||
package baritone.utils.schematic.format.defaults;
|
||||
|
||||
import baritone.api.schematic.CompositeSchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.core.registries.BuiltInRegistries;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
@@ -30,6 +31,7 @@ import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Collections;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -39,35 +41,24 @@ import java.util.Optional;
|
||||
* @author rycbar
|
||||
* @since 22.09.2022
|
||||
*/
|
||||
public final class LitematicaSchematic extends StaticSchematic {
|
||||
private final Vec3i offsetMinCorner;
|
||||
private final CompoundTag nbt;
|
||||
public final class LitematicaSchematic extends CompositeSchematic implements IStaticSchematic {
|
||||
|
||||
/**
|
||||
* @param nbtTagCompound a decompressed file stream aka nbt data.
|
||||
* @param rotated if the schematic is rotated by 90°.
|
||||
*/
|
||||
public LitematicaSchematic(CompoundTag nbtTagCompound, boolean rotated) {
|
||||
this.nbt = nbtTagCompound;
|
||||
this.offsetMinCorner = new Vec3i(getMinOfSchematic("x"), getMinOfSchematic("y"), getMinOfSchematic("z"));
|
||||
this.y = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("y"));
|
||||
|
||||
if (rotated) {
|
||||
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
|
||||
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
|
||||
} else {
|
||||
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
|
||||
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
|
||||
}
|
||||
this.states = new BlockState[this.x][this.z][this.y];
|
||||
fillInSchematic();
|
||||
public LitematicaSchematic(CompoundTag nbt) {
|
||||
super(0, 0, 0);
|
||||
fillInSchematic(nbt);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Array of subregion names.
|
||||
* @return Array of subregion tags.
|
||||
*/
|
||||
private static String[] getRegions(CompoundTag nbt) {
|
||||
return nbt.getCompound("Regions").getAllKeys().toArray(new String[0]);
|
||||
private static CompoundTag[] getRegions(CompoundTag nbt) {
|
||||
return nbt.getCompound("Regions").getAllKeys().stream()
|
||||
.map(nbt.getCompound("Regions")::getCompound)
|
||||
.toArray(CompoundTag[]::new);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -76,14 +67,10 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
* @param s axis that should be read.
|
||||
* @return the lower coord of the requested axis.
|
||||
*/
|
||||
private static int getMinOfSubregion(CompoundTag nbt, String subReg, String s) {
|
||||
int a = nbt.getCompound("Regions").getCompound(subReg).getCompound("Position").getInt(s);
|
||||
int b = nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt(s);
|
||||
if (b < 0) {
|
||||
b++;
|
||||
}
|
||||
return Math.min(a, a + b);
|
||||
|
||||
private static int getMinOfSubregion(CompoundTag subReg, String s) {
|
||||
int a = subReg.getCompound("Position").getInt(s);
|
||||
int b = subReg.getCompound("Size").getInt(s);
|
||||
return Math.min(a, a + b + 1);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +81,7 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
BlockState[] blockList = new BlockState[blockStatePalette.size()];
|
||||
|
||||
for (int i = 0; i < blockStatePalette.size(); i++) {
|
||||
Block block = BuiltInRegistries.BLOCK.get(new ResourceLocation((((CompoundTag) blockStatePalette.get(i)).getString("Name"))));
|
||||
Block block = BuiltInRegistries.BLOCK.get(ResourceLocation.parse((((CompoundTag) blockStatePalette.get(i)).getString("Name"))));
|
||||
CompoundTag properties = ((CompoundTag) blockStatePalette.get(i)).getCompound("Properties");
|
||||
|
||||
blockList[i] = getBlockState(block, properties);
|
||||
@@ -110,7 +97,7 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
private static BlockState getBlockState(Block block, CompoundTag properties) {
|
||||
BlockState blockState = block.defaultBlockState();
|
||||
|
||||
for (Object key : properties.getAllKeys().toArray()) {
|
||||
for (Object key : properties.getAllKeys()) {
|
||||
Property<?> property = block.getStateDefinition().getProperty((String) key);
|
||||
String propertyValue = properties.getString((String) key);
|
||||
if (property != null) {
|
||||
@@ -146,43 +133,19 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
*
|
||||
* @return the volume of the subregion.
|
||||
*/
|
||||
private static long getVolume(CompoundTag nbt, String subReg) {
|
||||
return Math.abs(
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x") *
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y") *
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of Long values.
|
||||
*/
|
||||
private static long[] getBlockStates(CompoundTag nbt, String subReg) {
|
||||
return nbt.getCompound("Regions").getCompound(subReg).getLongArray("BlockStates");
|
||||
}
|
||||
|
||||
/**
|
||||
* Subregion don't have to be the same size as the enclosing size of the schematic. If they are smaller we check here if the current block is part of the subregion.
|
||||
*
|
||||
* @param x coord of the block relative to the minimum corner.
|
||||
* @param y coord of the block relative to the minimum corner.
|
||||
* @param z coord of the block relative to the minimum corner.
|
||||
* @return if the current block is part of the subregion.
|
||||
*/
|
||||
private static boolean inSubregion(CompoundTag nbt, String subReg, int x, int y, int z) {
|
||||
return x >= 0 && y >= 0 && z >= 0 &&
|
||||
x < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x")) &&
|
||||
y < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y")) &&
|
||||
z < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
|
||||
private static long getVolume(CompoundTag subReg) {
|
||||
CompoundTag size = subReg.getCompound("Size");
|
||||
return Math.abs(size.getInt("x") * size.getInt("y") * size.getInt("z"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s axis.
|
||||
* @return the lowest coordinate of that axis of the schematic.
|
||||
*/
|
||||
private int getMinOfSchematic(String s) {
|
||||
private static int getMinOfSchematic(CompoundTag nbt, String s) {
|
||||
int n = Integer.MAX_VALUE;
|
||||
for (String subReg : getRegions(nbt)) {
|
||||
n = Math.min(n, getMinOfSubregion(nbt, subReg, s));
|
||||
for (CompoundTag subReg : getRegions(nbt)) {
|
||||
n = Math.min(n, getMinOfSubregion(subReg, s));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
@@ -190,18 +153,18 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
/**
|
||||
* reads the file data.
|
||||
*/
|
||||
private void fillInSchematic() {
|
||||
for (String subReg : getRegions(nbt)) {
|
||||
ListTag usedBlockTypes = nbt.getCompound("Regions").getCompound(subReg).getList("BlockStatePalette", 10);
|
||||
private void fillInSchematic(CompoundTag nbt) {
|
||||
Vec3i offsetMinCorner = new Vec3i(getMinOfSchematic(nbt, "x"), getMinOfSchematic(nbt, "y"), getMinOfSchematic(nbt, "z"));
|
||||
for (CompoundTag subReg : getRegions(nbt)) {
|
||||
ListTag usedBlockTypes = subReg.getList("BlockStatePalette", 10);
|
||||
BlockState[] blockList = getBlockList(usedBlockTypes);
|
||||
|
||||
int bitsPerBlock = getBitsPerBlock(usedBlockTypes.size());
|
||||
long regionVolume = getVolume(nbt, subReg);
|
||||
long[] blockStateArray = getBlockStates(nbt, subReg);
|
||||
long regionVolume = getVolume(subReg);
|
||||
long[] blockStateArray = subReg.getLongArray("BlockStates");
|
||||
|
||||
LitematicaBitArray bitArray = new LitematicaBitArray(bitsPerBlock, regionVolume, blockStateArray);
|
||||
|
||||
writeSubregionIntoSchematic(nbt, subReg, blockList, bitArray);
|
||||
writeSubregionIntoSchematic(subReg, offsetMinCorner, blockList, bitArray);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -211,65 +174,30 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
* @param blockList list with the different block types used in the schematic.
|
||||
* @param bitArray bit array that holds the placement pattern.
|
||||
*/
|
||||
private void writeSubregionIntoSchematic(CompoundTag nbt, String subReg, BlockState[] blockList, LitematicaBitArray bitArray) {
|
||||
Vec3i offsetSubregion = new Vec3i(getMinOfSubregion(nbt, subReg, "x"), getMinOfSubregion(nbt, subReg, "y"), getMinOfSubregion(nbt, subReg, "z"));
|
||||
private void writeSubregionIntoSchematic(CompoundTag subReg, Vec3i offsetMinCorner, BlockState[] blockList, LitematicaBitArray bitArray) {
|
||||
int offsetX = getMinOfSubregion(subReg, "x") - offsetMinCorner.getX();
|
||||
int offsetY = getMinOfSubregion(subReg, "y") - offsetMinCorner.getY();
|
||||
int offsetZ = getMinOfSubregion(subReg, "z") - offsetMinCorner.getZ();
|
||||
CompoundTag size = subReg.getCompound("Size");
|
||||
int sizeX = Math.abs(size.getInt("x"));
|
||||
int sizeY = Math.abs(size.getInt("y"));
|
||||
int sizeZ = Math.abs(size.getInt("z"));
|
||||
BlockState[][][] states = new BlockState[sizeX][sizeZ][sizeY];
|
||||
int index = 0;
|
||||
for (int y = 0; y < this.y; y++) {
|
||||
for (int z = 0; z < this.z; z++) {
|
||||
for (int x = 0; x < this.x; x++) {
|
||||
if (inSubregion(nbt, subReg, x, y, z)) {
|
||||
this.states[x - (offsetMinCorner.getX() - offsetSubregion.getX())][z - (offsetMinCorner.getZ() - offsetSubregion.getZ())][y - (offsetMinCorner.getY() - offsetSubregion.getY())] = blockList[bitArray.getAt(index)];
|
||||
index++;
|
||||
}
|
||||
for (int y = 0; y < sizeY; y++) {
|
||||
for (int z = 0; z < sizeZ; z++) {
|
||||
for (int x = 0; x < sizeX; x++) {
|
||||
states[x][z][y] = blockList[bitArray.getAt(index)];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.put(new StaticSchematic(states), offsetX, offsetY, offsetZ);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return offset from the schematic origin to the minimum Corner as a Vec3i.
|
||||
*/
|
||||
public Vec3i getOffsetMinCorner() {
|
||||
return offsetMinCorner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return x size of the schematic.
|
||||
*/
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return y size of the schematic.
|
||||
*/
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return z size of the schematic.
|
||||
*/
|
||||
public int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x position relative to the minimum corner of the schematic.
|
||||
* @param y position relative to the minimum corner of the schematic.
|
||||
* @param z position relative to the minimum corner of the schematic.
|
||||
* @param blockState new blockstate of the block at this position.
|
||||
*/
|
||||
public void setDirect(int x, int y, int z, BlockState blockState) {
|
||||
this.states[x][z][y] = blockState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rotated if the schematic is rotated by 90°.
|
||||
* @return a copy of the schematic.
|
||||
*/
|
||||
public LitematicaSchematic getCopy(boolean rotated) {
|
||||
return new LitematicaSchematic(nbt, rotated);
|
||||
@Override
|
||||
public BlockState getDirect(int x, int y, int z) {
|
||||
return desiredState(x, y, z, null, Collections.emptyList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -345,4 +273,4 @@ public final class LitematicaSchematic extends StaticSchematic {
|
||||
return this.arraySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -130,7 +130,7 @@ public final class SpongeSchematic extends StaticSchematic {
|
||||
String location = m.group("location");
|
||||
String properties = m.group("properties");
|
||||
|
||||
ResourceLocation resourceLocation = new ResourceLocation(location);
|
||||
ResourceLocation resourceLocation = ResourceLocation.parse(location);
|
||||
Map<String, String> propertiesMap = new HashMap<>();
|
||||
if (properties != null) {
|
||||
for (String property : properties.split(",")) {
|
||||
|
||||
@@ -17,15 +17,26 @@
|
||||
|
||||
package baritone.utils.schematic.litematica;
|
||||
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.api.schematic.CompositeSchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import fi.dy.masa.litematica.Litematica;
|
||||
import fi.dy.masa.litematica.data.DataManager;
|
||||
import fi.dy.masa.litematica.schematic.placement.SchematicPlacement;
|
||||
import fi.dy.masa.litematica.schematic.placement.SubRegionPlacement;
|
||||
import fi.dy.masa.litematica.world.SchematicWorldHandler;
|
||||
import fi.dy.masa.litematica.world.WorldSchematic;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Helper class that provides access or processes data related to Litmatica schematics.
|
||||
@@ -48,168 +59,98 @@ public final class LitematicaHelper {
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if there are loaded schematics.
|
||||
* @return if {@code i} is a valid placement index
|
||||
*/
|
||||
public static boolean hasLoadedSchematic() {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size() > 0;
|
||||
public static boolean hasLoadedSchematic(int i) {
|
||||
return 0 <= i && i < DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the name of the requested schematic.
|
||||
*/
|
||||
public static String getName(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getName();
|
||||
private static SchematicPlacement getPlacement(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the world coordinates of the schematic origin. This can but does not have to be the minimum corner.
|
||||
*/
|
||||
public static Vec3i getOrigin(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return Filepath of the schematic file.
|
||||
*/
|
||||
public static File getSchematicFile(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getSchematicFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return rotation of the schematic placement.
|
||||
*/
|
||||
public static Rotation getRotation(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the mirroring of the schematic placement.
|
||||
*/
|
||||
public static Mirror getMirror(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getMirror();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param schematic original schematic.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored.
|
||||
*/
|
||||
public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) {
|
||||
int x = LitematicaHelper.getOrigin(i).getX();
|
||||
int y = LitematicaHelper.getOrigin(i).getY();
|
||||
int z = LitematicaHelper.getOrigin(i).getZ();
|
||||
int mx = schematic.getOffsetMinCorner().getX();
|
||||
int my = schematic.getOffsetMinCorner().getY();
|
||||
int mz = schematic.getOffsetMinCorner().getZ();
|
||||
int sx = (schematic.getX() - 1) * -1;
|
||||
int sz = (schematic.getZ() - 1) * -1;
|
||||
|
||||
Vec3i correctedOrigin;
|
||||
Mirror mirror = LitematicaHelper.getMirror(i);
|
||||
Rotation rotation = LitematicaHelper.getRotation(i);
|
||||
|
||||
//todo there has to be a better way to do this but i cant finde it atm
|
||||
switch (mirror) {
|
||||
case FRONT_BACK:
|
||||
case LEFT_RIGHT:
|
||||
switch ((mirror.ordinal() * 2 + rotation.ordinal()) % 4) {
|
||||
case 1:
|
||||
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + (sx - mx));
|
||||
break;
|
||||
case 2:
|
||||
correctedOrigin = new Vec3i(x + mx, y + my, z + (sz - mz));
|
||||
break;
|
||||
case 3:
|
||||
correctedOrigin = new Vec3i(x + mz, y + my, z + mx);
|
||||
break;
|
||||
default:
|
||||
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + mz);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rotation) {
|
||||
case CLOCKWISE_90:
|
||||
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + mx);
|
||||
break;
|
||||
case CLOCKWISE_180:
|
||||
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + (sz - mz));
|
||||
break;
|
||||
case COUNTERCLOCKWISE_90:
|
||||
correctedOrigin = new Vec3i(x + mz, y + my, z + (sx - mx));
|
||||
break;
|
||||
default:
|
||||
correctedOrigin = new Vec3i(x + mx, y + my, z + mz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return correctedOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the xyz offsets of the block relative to the schematic minimum corner.
|
||||
* @param sizeX size of the schematic in the x-axis direction.
|
||||
* @param sizeZ size of the schematic in the z-axis direction.
|
||||
* @param mirror the mirroring of the schematic placement.
|
||||
* @return the corresponding xyz coordinates after mirroring them according to the given mirroring.
|
||||
*/
|
||||
public static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) {
|
||||
int xOut = in.getX();
|
||||
int zOut = in.getZ();
|
||||
private static Vec3i transform(Vec3i in, Mirror mirror, Rotation rotation) {
|
||||
int x = in.getX();
|
||||
int z = in.getZ();
|
||||
if (mirror == Mirror.LEFT_RIGHT) {
|
||||
zOut = sizeZ - in.getZ();
|
||||
z = -z;
|
||||
} else if (mirror == Mirror.FRONT_BACK) {
|
||||
xOut = sizeX - in.getX();
|
||||
x = -x;
|
||||
}
|
||||
switch (rotation) {
|
||||
case CLOCKWISE_90:
|
||||
return new Vec3i(-z, in.getY(), x);
|
||||
case CLOCKWISE_180:
|
||||
return new Vec3i(-x, in.getY(), -z);
|
||||
case COUNTERCLOCKWISE_90:
|
||||
return new Vec3i(z, in.getY(), -x);
|
||||
default:
|
||||
return new Vec3i(x, in.getY(), z);
|
||||
}
|
||||
return new Vec3i(xOut, in.getY(), zOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the xyz offsets of the block relative to the schematic minimum corner.
|
||||
* @param sizeX size of the schematic in the x-axis direction.
|
||||
* @param sizeZ size of the schematic in the z-axis direction.
|
||||
* @return the corresponding xyz coordinates after rotation them 90° clockwise.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return The transformed schematic and the position of its minimum corner
|
||||
*/
|
||||
public static Vec3i rotate(Vec3i in, int sizeX, int sizeZ) {
|
||||
return new Vec3i(sizeX - (sizeX - sizeZ) - in.getZ(), in.getY(), in.getX());
|
||||
}
|
||||
|
||||
/**
|
||||
* IDFK this just grew and it somehow works. If you understand how, pls tell me.
|
||||
*
|
||||
* @param schemIn give in the original schematic.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return get it out rotated and mirrored.
|
||||
*/
|
||||
public static LitematicaSchematic blackMagicFuckery(LitematicaSchematic schemIn, int i) {
|
||||
LitematicaSchematic tempSchem = schemIn.getCopy(LitematicaHelper.getRotation(i).ordinal() % 2 == 1);
|
||||
for (int yCounter = 0; yCounter < schemIn.getY(); yCounter++) {
|
||||
for (int zCounter = 0; zCounter < schemIn.getZ(); zCounter++) {
|
||||
for (int xCounter = 0; xCounter < schemIn.getX(); xCounter++) {
|
||||
Vec3i xyzHolder = new Vec3i(xCounter, yCounter, zCounter);
|
||||
xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1, LitematicaHelper.getMirror(i));
|
||||
for (int turns = 0; turns < LitematicaHelper.getRotation(i).ordinal(); turns++) {
|
||||
if ((turns % 2) == 0) {
|
||||
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1);
|
||||
} else {
|
||||
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getZ() - 1, schemIn.getX() - 1);
|
||||
}
|
||||
public static Tuple<IStaticSchematic, Vec3i> getSchematic(int i) {
|
||||
SchematicPlacement placement = getPlacement(i);
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
HashMap<Vec3i, StaticSchematic> subRegions = new HashMap<>();
|
||||
Level schematicWorld = SchematicWorldHandler.getSchematicWorld();
|
||||
for (Map.Entry<String, SubRegionPlacement> entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) {
|
||||
SubRegionPlacement subPlacement = entry.getValue();
|
||||
Vec3i pos = transform(subPlacement.getPos(), placement.getMirror(), placement.getRotation());
|
||||
Vec3i size = placement.getSchematic().getAreaSize(entry.getKey());
|
||||
size = transform(size, placement.getMirror(), placement.getRotation());
|
||||
size = transform(size, subPlacement.getMirror(), subPlacement.getRotation());
|
||||
int mx = Math.min(size.getX() + 1, 0);
|
||||
int my = Math.min(size.getY() + 1, 0);
|
||||
int mz = Math.min(size.getZ() + 1, 0);
|
||||
minX = Math.min(minX, pos.getX() + mx);
|
||||
minY = Math.min(minY, pos.getY() + my);
|
||||
minZ = Math.min(minZ, pos.getZ() + mz);
|
||||
BlockPos origin = placement.getOrigin().offset(pos).offset(mx, my, mz);
|
||||
BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())];
|
||||
for (int x = 0; x < states.length; x++) {
|
||||
for (int z = 0; z < states[x].length; z++) {
|
||||
for (int y = 0; y < states[x][z].length; y++) {
|
||||
states[x][z][y] = schematicWorld.getBlockState(origin.offset(x, y, z));
|
||||
}
|
||||
BlockState state = schemIn.getDirect(xCounter, yCounter, zCounter);
|
||||
try {
|
||||
state = state.mirror(LitematicaHelper.getMirror(i)).rotate(LitematicaHelper.getRotation(i));
|
||||
} catch (NullPointerException e) {
|
||||
//nothing to worry about it's just a hole in the schematic.
|
||||
}
|
||||
tempSchem.setDirect(xyzHolder.getX(), xyzHolder.getY(), xyzHolder.getZ(), state);
|
||||
}
|
||||
}
|
||||
StaticSchematic schematic = new StaticSchematic(states);
|
||||
subRegions.put(pos.offset(mx, my, mz), schematic);
|
||||
}
|
||||
return tempSchem;
|
||||
LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(placement.getName());
|
||||
for (Map.Entry<Vec3i, StaticSchematic> entry : subRegions.entrySet()) {
|
||||
Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ);
|
||||
composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
return new Tuple<>(composite, placement.getOrigin().offset(minX, minY, minZ));
|
||||
}
|
||||
}
|
||||
|
||||
private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic {
|
||||
private final String name;
|
||||
|
||||
public LitematicaPlacementSchematic(String name) {
|
||||
super(0, 0, 0);
|
||||
this.name = name;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState getDirect(int x, int y, int z) {
|
||||
if (inSchematic(x, y, z, null)) {
|
||||
return desiredState(x, y, z, null, Collections.emptyList());
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return name;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,14 +20,8 @@ package fi.dy.masa.litematica.data;
|
||||
import fi.dy.masa.litematica.schematic.placement.SchematicPlacementManager;
|
||||
|
||||
public class DataManager {
|
||||
public static final DataManager INSTANCE = new DataManager();
|
||||
private final SchematicPlacementManager schematicPlacementManager = new SchematicPlacementManager();
|
||||
|
||||
private static DataManager getInstance() {
|
||||
return INSTANCE;
|
||||
}
|
||||
|
||||
public static SchematicPlacementManager getSchematicPlacementManager() {
|
||||
return getInstance().schematicPlacementManager;
|
||||
throw new LinkageError();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
/*
|
||||
* 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 fi.dy.masa.litematica.schematic;
|
||||
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class LitematicaSchematic {
|
||||
|
||||
public BlockPos getAreaSize(String name) {
|
||||
throw new LinkageError();
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user