Compare commits
286 Commits
bepitone
...
pr/invento
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
6a6d0642be | ||
|
|
dbf5058066 | ||
|
|
bc18f0eabd | ||
|
|
827ce7e2a8 | ||
|
|
2e32c63bc2 | ||
|
|
53651980ad | ||
|
|
ec089cdeaa | ||
|
|
2408c9b6af | ||
|
|
600d5e8a67 | ||
|
|
57c3e369b0 | ||
|
|
827125d827 | ||
|
|
4d7eb003e6 | ||
|
|
1ef622c936 | ||
|
|
c44701e689 | ||
|
|
7f27c9d85f | ||
|
|
15621ea763 | ||
|
|
4591fd7eb3 | ||
|
|
028405dd30 | ||
|
|
2953b1cfaf | ||
|
|
b2cdd27ca2 | ||
|
|
4bf2dd6851 | ||
|
|
8211ae4af5 | ||
|
|
15f4253b3d | ||
|
|
24b0bd2edf | ||
|
|
e3a1ac85cc | ||
|
|
1ea071de09 | ||
|
|
c9a18caf49 | ||
|
|
bfae100cb9 | ||
|
|
b0ebbf4dfb | ||
|
|
9d12a4ba3d | ||
|
|
6dc953631b | ||
|
|
0682e63707 | ||
|
|
7e426bd2e8 | ||
|
|
367ce5fa17 | ||
|
|
41d730fb04 | ||
|
|
30278a1c52 | ||
|
|
d87d1ab9b5 | ||
|
|
31c9072970 | ||
|
|
f7a20a3acf | ||
|
|
b111fd2f3e | ||
|
|
84777c2437 | ||
|
|
13742df877 | ||
|
|
f55f7f19b4 | ||
|
|
e43200865c | ||
|
|
1de2d55965 | ||
|
|
6c8f2698d6 | ||
|
|
411c43d90e | ||
|
|
bac5fd7438 | ||
|
|
4df31a3fbb | ||
|
|
5fd915ab8a | ||
|
|
6aeb73b5bd | ||
|
|
a665605a5a | ||
|
|
e00e0032b4 | ||
|
|
f1bf1e8663 | ||
|
|
ef4cdfd646 | ||
|
|
c86643874d | ||
|
|
26a2945696 | ||
|
|
04b09fbfbd | ||
|
|
f14caa3778 | ||
|
|
ea9245ad26 | ||
|
|
8534e1ba55 | ||
|
|
ae66004b80 | ||
|
|
5b39c0dd96 | ||
|
|
2db2d8be59 | ||
|
|
75d47bb110 | ||
|
|
3662b3fdf1 | ||
|
|
b03d31e990 | ||
|
|
54f0a3c14c | ||
|
|
6a80b0d4ff | ||
|
|
5e724c1e3a | ||
|
|
88e604426c | ||
|
|
dd7b492b0c | ||
|
|
c7f4e366e2 | ||
|
|
382f82b0e0 | ||
|
|
ab3d9e9c47 | ||
|
|
714ebb2c2d | ||
|
|
1b254a4811 | ||
|
|
76fe0d14d3 | ||
|
|
2022d33d03 | ||
|
|
c8b8deb3d6 | ||
|
|
4885d49d20 | ||
|
|
13fc58933d | ||
|
|
c217a34f13 | ||
|
|
15182cb151 | ||
|
|
8a65a1cfc5 | ||
|
|
5bdd5b0c0d | ||
|
|
7da802a238 | ||
|
|
e334aae608 | ||
|
|
c48a9d98b4 | ||
|
|
ed34ae73c0 | ||
|
|
c8a0ae9e10 | ||
|
|
67a085c95f | ||
|
|
1d5ee079b4 | ||
|
|
bb36ebfc0c | ||
|
|
a7d15d1e32 | ||
|
|
4317dca024 | ||
|
|
77ca36c794 | ||
|
|
a09e63d6aa | ||
|
|
fbe28e397e | ||
|
|
364ae87ef8 | ||
|
|
ffd00080f2 | ||
|
|
94d757104b | ||
|
|
9729e63d98 | ||
|
|
f232bbdb15 | ||
|
|
26574b4a9b | ||
|
|
a1b1ef88cf | ||
|
|
b6c52cd8e1 | ||
|
|
34abbfb5da | ||
|
|
0d14bde583 | ||
|
|
4b0a8eb166 | ||
|
|
80ec9023ce | ||
|
|
5dd10b6e81 | ||
|
|
415fa048ba | ||
|
|
a1661e94b5 | ||
|
|
c45a714b77 | ||
|
|
271c2ff636 | ||
|
|
e4cd35ac33 | ||
|
|
e8a4a9fdac | ||
|
|
5f2eadbfa6 | ||
|
|
35ab687d5e | ||
|
|
3ff2bd4f17 | ||
|
|
f334b3b765 | ||
|
|
ff1732011e | ||
|
|
c5721fb7e3 | ||
|
|
3200d976d7 | ||
|
|
6698505dd8 | ||
|
|
790a4f6769 | ||
|
|
c9d7a5bea6 | ||
|
|
f1ead19b6e | ||
|
|
174bdd2307 | ||
|
|
814c17522a | ||
|
|
b622adf300 | ||
|
|
c1b58f8a01 | ||
|
|
c1a9621dfa | ||
|
|
6de266a106 | ||
|
|
334d9c119b | ||
|
|
1a2c30b4e3 | ||
|
|
413cc1469f | ||
|
|
7404414e7a | ||
|
|
49b1f3528b | ||
|
|
26cceede15 | ||
|
|
698d40d797 | ||
|
|
2b6c59fa8a | ||
|
|
21bc830143 | ||
|
|
aa9206381d | ||
|
|
d6d9af65fb | ||
|
|
a3f70e7977 | ||
|
|
6bbdba7a21 | ||
|
|
6a175379fb | ||
|
|
85c21fa8e3 | ||
|
|
bc8c823045 | ||
|
|
9935da8a6f | ||
|
|
c39b6c3fe7 | ||
|
|
c47a6f92c5 | ||
|
|
778628da30 | ||
|
|
ba0ca0cc65 | ||
|
|
fba3828479 | ||
|
|
c8dd4f26f7 | ||
|
|
16a62625b3 | ||
|
|
de5f6d5fce | ||
|
|
98a87d099b | ||
|
|
a6f3c95684 | ||
|
|
75e39e7ef5 | ||
|
|
77b2b26a7a | ||
|
|
1680eeb80d | ||
|
|
9a9b4a1874 | ||
|
|
145a944860 | ||
|
|
dd127ff3e7 | ||
|
|
b0fb474e1d | ||
|
|
a1a94ec0d1 | ||
|
|
678f8bc77f | ||
|
|
41968546d1 | ||
|
|
f76283ebfe | ||
|
|
e59bf9ab97 | ||
|
|
b2f66241d5 | ||
|
|
b71c9e776a | ||
|
|
746faf6df6 | ||
|
|
a367031fe2 | ||
|
|
853dadd906 | ||
|
|
e55db05f20 | ||
|
|
98a748afb3 | ||
|
|
c04eb066cb | ||
|
|
6260c6d3d7 | ||
|
|
ce1fb49252 | ||
|
|
ecdec87e7a | ||
|
|
cfdbc851a0 | ||
|
|
6ccebdc978 | ||
|
|
df53040339 | ||
|
|
42dc5b14b0 | ||
|
|
e2538abcb1 | ||
|
|
1697293f12 | ||
|
|
96f432d2d5 | ||
|
|
0ae59755e3 | ||
|
|
12b596e536 | ||
|
|
0b6088cd2d | ||
|
|
1736f2ffc7 | ||
|
|
d60e1e8a05 | ||
|
|
d157756d94 | ||
|
|
ea1914a248 | ||
|
|
85087ce04a | ||
|
|
e09127eadf | ||
|
|
e1095962a1 | ||
|
|
eabd1150b0 | ||
|
|
93501248cd | ||
|
|
3a945c8c10 | ||
|
|
3cef7a7911 | ||
|
|
1cd2fb5b18 | ||
|
|
ba3ca47f8c | ||
|
|
4699b46744 | ||
|
|
69ffdb7665 | ||
|
|
f9c5386e7a | ||
|
|
55273b5340 | ||
|
|
5cd1c9d15d | ||
|
|
b461b2af2f | ||
|
|
3a5608566e | ||
|
|
fc65f22feb | ||
|
|
f53bfa89a9 | ||
|
|
fdfeeb2ffa | ||
|
|
3e75cc7408 | ||
|
|
d1930e03e1 | ||
|
|
144a534bb3 | ||
|
|
de1256cc80 | ||
|
|
76404c8af6 | ||
|
|
fb814e912d | ||
|
|
43ee86b4fe | ||
|
|
eb697b7a17 | ||
|
|
3da5bbd267 | ||
|
|
c14be17e53 | ||
|
|
45c0b38156 | ||
|
|
025f6235f9 | ||
|
|
4ba3c883e6 | ||
|
|
3a4168a661 | ||
|
|
484b3326c7 | ||
|
|
e99fcbbe36 | ||
|
|
7ba3de57d0 | ||
|
|
5ff274f040 | ||
|
|
293f5db172 | ||
|
|
d928e705b9 | ||
|
|
7a48824ced | ||
|
|
8aa8918124 | ||
|
|
a091c17b83 | ||
|
|
52aa0d9b8a | ||
|
|
3d8eddc4e1 | ||
|
|
295265c261 | ||
|
|
376d6422ec | ||
|
|
113e340474 | ||
|
|
c89d8b69e5 | ||
|
|
70303634f5 | ||
|
|
325aa7201b | ||
|
|
75a3fc699e | ||
|
|
3cd8ce8323 | ||
|
|
240e81a9e0 | ||
|
|
40449400d3 | ||
|
|
9ffe4f2c25 | ||
|
|
af95f77134 | ||
|
|
78f1c45e13 | ||
|
|
cf47573298 | ||
|
|
96ba96ca69 | ||
|
|
da998eb469 | ||
|
|
e75a4b95cc | ||
|
|
344085f4ef | ||
|
|
d37a6a0b2d | ||
|
|
d7fc916d20 | ||
|
|
80a4757242 | ||
|
|
658048ff2d | ||
|
|
0587223da8 | ||
|
|
2d1b81dc20 | ||
|
|
0bd16fb81a | ||
|
|
0c1fec5d1e | ||
|
|
ee16eb7fde | ||
|
|
5c9aeab6b4 | ||
|
|
5c7cae9ab0 | ||
|
|
93fa6cf875 | ||
|
|
5b7bee977b | ||
|
|
8018dac396 | ||
|
|
85ab317c6c | ||
|
|
6b0fb1721b | ||
|
|
fdcdcbb85f | ||
|
|
8d480cefb9 | ||
|
|
3e7f9039c4 | ||
|
|
868c023dbd | ||
|
|
e7c357ab7f | ||
|
|
9e1a5008ed | ||
|
|
a6557121a0 | ||
|
|
2dad6262cf | ||
|
|
af1eb58bb8 |
10
.github/workflows/gradle_build.yml
vendored
10
.github/workflows/gradle_build.yml
vendored
@@ -13,12 +13,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 8
|
||||
uses: actions/setup-java@v2
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'adopt'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
@@ -27,13 +27,13 @@ jobs:
|
||||
run: ./gradlew build
|
||||
|
||||
- name: Archive Artifacts
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Artifacts
|
||||
path: dist/
|
||||
|
||||
- name: Archive mapping.txt
|
||||
uses: actions/upload-artifact@v2
|
||||
uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: Mappings
|
||||
path: build/tmp/proguard/mapping.txt
|
||||
|
||||
8
.github/workflows/run_tests.yml
vendored
8
.github/workflows/run_tests.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 9
|
||||
uses: actions/setup-java@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 8
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '8'
|
||||
distribution: 'adopt'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
42
README.md
42
README.md
@@ -4,13 +4,16 @@
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
<a href="https://github.com/cabaletta/baritone/tree/master"><img src="https://img.shields.io/badge/MC-1.12.2-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.13.2"><img src="https://img.shields.io/badge/MC-1.13.2-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.14.4"><img src="https://img.shields.io/badge/MC-1.14.4-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.15.2"><img src="https://img.shields.io/badge/MC-1.15.2-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.16.5"><img src="https://img.shields.io/badge/MC-1.16.5-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.17.1"><img src="https://img.shields.io/badge/MC-1.17.1-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/tree/1.18.2"><img src="https://img.shields.io/badge/MC-1.18.2-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.12.2-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.13.2-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.14.4-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.15.2-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.16.5-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.17.1-yellow.svg" alt="Minecraft"/></a>
|
||||
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.18.2-brightgreen.svg" alt="Minecraft"/></a>
|
||||
<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>
|
||||
</p>
|
||||
|
||||
<p align="center">
|
||||
@@ -33,7 +36,7 @@
|
||||
|
||||
<p align="center">
|
||||
<a href="https://impactclient.net/"><img src="https://img.shields.io/badge/Impact%20integration-v1.2.14%20/%20v1.3.8%20/%20v1.4.6%20/%20v1.5.3%20/%20v1.6.3-brightgreen.svg" alt="Impact integration"/></a>
|
||||
<a href="https://github.com/kami-blue/client"><img src="https://img.shields.io/badge/KAMI%20Blue%20integration-v1.2.14--master-green" alt="KAMI Blue integration"/></a>
|
||||
<a href="https://github.com/lambda-client/lambda"><img src="https://img.shields.io/badge/Lambda%20integration-v1.2.17-brightgreen.svg" alt="Lambda integration"/></a>
|
||||
<a href="https://github.com/fr1kin/ForgeHax/"><img src="https://img.shields.io/badge/ForgeHax%20%22integration%22-scuffed-yellow.svg" alt="ForgeHax integration"/></a>
|
||||
<a href="https://aristois.net/"><img src="https://img.shields.io/badge/Aristois%20add--on%20integration-v1.6.3-green.svg" alt="Aristois add-on integration"/></a>
|
||||
<a href="https://rootnet.dev/"><img src="https://img.shields.io/badge/rootNET%20integration-v1.2.14-green.svg" alt="rootNET integration"/></a>
|
||||
@@ -48,19 +51,26 @@
|
||||
|
||||
A Minecraft pathfinder bot.
|
||||
|
||||
Baritone is the pathfinding system used in [Impact](https://impactclient.net/) since 4.4. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a (very old!) video I made showing off what it can do.
|
||||
|
||||
[**Baritone Discord Server**](http://discord.gg/s6fRBAUpmr)
|
||||
|
||||
Baritone is the pathfinding system used in [Impact](https://impactclient.net/) since 4.4. There's a [showcase video](https://youtu.be/CZkLXWo4Fg4) made by @Adovin#0730 on Baritone which I recommend. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a (very old!) video I made showing off what it can do.
|
||||
**Quick download links:**
|
||||
|
||||
[Tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa)
|
||||
| Forge | Fabric |
|
||||
|---------------------------------------------------------------------------------------------------------------|---------------------------------------------------------------------------------------------------------------|
|
||||
| [1.12.2 Forge](https://github.com/cabaletta/baritone/releases/download/v1.2.17/baritone-api-forge-1.2.17.jar) | |
|
||||
| [1.16.5 Forge](https://github.com/cabaletta/baritone/releases/download/v1.6.4/baritone-api-forge-1.6.4.jar) | [1.16.5 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.6.4/baritone-api-fabric-1.6.4.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.4/baritone-api-forge-1.8.4.jar) | [1.18.2 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.8.4/baritone-api-fabric-1.8.4.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) |
|
||||
|
||||
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone. The second easiest way (for 1.12.2 only) is to install the v1.2.* `api-forge` jar from [releases](https://github.com/cabaletta/baritone/releases). **For 1.12.2 Forge, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.2.15/baritone-api-forge-1.2.15.jar)**. Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
**How to immediately get started:** Type `#goto 1000 500` in chat to go to x=1000 z=500. Type `#mine diamond_ore` to mine diamond ore. Type `#stop` to stop. For more, read [the usage page](USAGE.md) and/or watch this [tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa)
|
||||
|
||||
For 1.16.5, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. If you need Forge or Fabric 1.16.5, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.6.3) and get the `api-forge` or `api-fabric` jar. **For 1.16.5 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.6.3/baritone-api-fabric-1.6.3.jar)**.
|
||||
|
||||
If you need Forge or Fabric 1.17.1, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.7.2) and get the `api-forge` or `api-fabric` jar. **For 1.17.1 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.7.2/baritone-api-fabric-1.7.2.jar)**.
|
||||
|
||||
If you need Forge or Fabric 1.18.2, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.8.3) and get the `api-forge` or `api-fabric` jar. **For 1.18.2 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.8.3/baritone-api-fabric-1.8.3.jar)**. **For 1.18.2 Forge, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.8.3/baritone-api-forge-1.8.3.jar)**.
|
||||
For other versions of Minecraft or more complicated situations or for development, see [Installation & setup](SETUP.md). Also consider just installing [Impact](https://impactclient.net/), which comes with Baritone and is easier to install than wrangling with version JSONs and zips. For 1.16.5, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it. There's a [showcase video](https://youtu.be/CZkLXWo4Fg4) made by @Adovin#6313 on Baritone which I recommend.
|
||||
|
||||
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
||||
the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2 onwards. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
|
||||
67
SETUP.md
67
SETUP.md
@@ -43,13 +43,13 @@ If another one of your Forge mods has a Baritone integration, you want `baritone
|
||||
## 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.
|
||||
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.
|
||||
|
||||
Open JDK download: https://openjdk.java.net/install/
|
||||
Download java: https://adoptium.net/
|
||||
#### macOS guide
|
||||
In order to get JDK 8, Try running the following command:
|
||||
`% /usr/libexec/java_home -V`
|
||||
@@ -66,68 +66,13 @@ In order to get JDK 8 running in the **current terminal window** you will have t
|
||||
|
||||
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
|
||||
|
||||
Setting up the Environment:
|
||||
### Building Baritone
|
||||
|
||||
```
|
||||
$ gradlew setupDecompWorkspace
|
||||
$ gradlew --refresh-dependencies
|
||||
```
|
||||
These tasks depend on the minecraft version, but are (for the most part) standard for building mods.
|
||||
|
||||
Building Baritone:
|
||||
|
||||
```
|
||||
$ gradlew build
|
||||
```
|
||||
|
||||
For minecraft 1.15.2+, run the following instead to include the Forge jars:
|
||||
|
||||
```
|
||||
$ gradlew build -Pbaritone.forge_build
|
||||
```
|
||||
|
||||
Do this instead for Fabric jars:
|
||||
|
||||
```
|
||||
$ gradlew build -Pbaritone.fabric_build
|
||||
```
|
||||
|
||||
Running Baritone:
|
||||
|
||||
```
|
||||
$ gradlew runClient
|
||||
```
|
||||
|
||||
For information on how to build baritone, see [Building Baritone](#building-baritone)
|
||||
for more details, see [the build ci action](/.github/workflows/gradle_build.yml)
|
||||
|
||||
## IntelliJ
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
|
||||

|
||||
|
||||
- Run the Gradle tasks `setupDecompWorkspace` then `genIntellijRuns`
|
||||
|
||||

|
||||
|
||||
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
|
||||
|
||||

|
||||
|
||||
- Select the "Minecraft Client" launch config
|
||||
|
||||

|
||||
|
||||
- Click on ``Edit Configurations...`` from the same dropdown and select the "Minecraft Client" config
|
||||
|
||||

|
||||
|
||||
- In `Edit Configurations...` you need to select `baritone_launch` for `Use classpath of module:`.
|
||||
|
||||

|
||||
|
||||
## IntelliJ
|
||||
|
||||
- Navigate to the gradle tasks on the right tab as follows
|
||||
|
||||

|
||||
|
||||
- Double click on **build** to run it
|
||||
- depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working
|
||||
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '1.2.15'
|
||||
version '1.2.17'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
|
||||
@@ -209,8 +209,8 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
|
||||
// Setup the template that will be used to derive the API and Standalone configs
|
||||
List<String> template = Files.readAllLines(getTemporaryFile(PROGUARD_CONFIG_DEST));
|
||||
template.add(0, "-injars " + this.artifactPath.toString());
|
||||
template.add(1, "-outjars " + this.getTemporaryFile(PROGUARD_EXPORT_PATH));
|
||||
template.add(0, "-injars '" + this.artifactPath.toString() + "'");
|
||||
template.add(1, "-outjars '" + this.getTemporaryFile(PROGUARD_EXPORT_PATH) + "'");
|
||||
|
||||
// Acquire the RT jar using "java -verbose". This doesn't work on Java 9+
|
||||
Process p = new ProcessBuilder(this.getJavaBinPathForProguard(), "-verbose").start();
|
||||
@@ -405,9 +405,15 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
Files.delete(this.proguardOut);
|
||||
}
|
||||
|
||||
Path proguardJar = getTemporaryFile(PROGUARD_JAR);
|
||||
// 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.
|
||||
|
||||
Process p = new ProcessBuilder("java", "-jar", proguardJar.toString(), "@" + config.toString())
|
||||
.directory(getTemporaryFile("").toFile()) // Set the working directory to the temporary folder]
|
||||
.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
|
||||
|
||||
2
scripts/proguard.pro
vendored
2
scripts/proguard.pro
vendored
@@ -42,8 +42,10 @@
|
||||
|
||||
#try to keep usage of schematica in separate classes
|
||||
-keep class baritone.utils.schematic.schematica.**
|
||||
-keep class baritone.utils.schematic.litematica.**
|
||||
#proguard doesnt like it when it cant find our fake schematica classes
|
||||
-dontwarn baritone.utils.schematic.schematica.**
|
||||
-dontwarn baritone.utils.schematic.litematica.**
|
||||
|
||||
# copy all necessary libraries into tempLibraries to build
|
||||
|
||||
|
||||
@@ -35,7 +35,7 @@ public final class BaritoneAPI {
|
||||
|
||||
static {
|
||||
settings = new Settings();
|
||||
SettingsUtil.readAndApply(settings);
|
||||
SettingsUtil.readAndApply(settings, SettingsUtil.SETTINGS_DEFAULT_NAME);
|
||||
|
||||
ServiceLoader<IBaritoneProvider> baritoneLoader = ServiceLoader.load(IBaritoneProvider.class);
|
||||
Iterator<IBaritoneProvider> instances = baritoneLoader.iterator();
|
||||
|
||||
@@ -21,6 +21,7 @@ import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.command.ICommand;
|
||||
import baritone.api.command.ICommandSystem;
|
||||
import baritone.api.schematic.ISchematicSystem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
|
||||
import java.util.List;
|
||||
@@ -52,15 +53,13 @@ public interface IBaritoneProvider {
|
||||
List<IBaritone> getAllBaritones();
|
||||
|
||||
/**
|
||||
* Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be
|
||||
* replaced with or be overloaded in addition to {@code #getBaritoneForUser(IBaritoneUser)} when
|
||||
* {@code bot-system} is merged into {@code master}.
|
||||
* Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}.
|
||||
*
|
||||
* @param player The player
|
||||
* @return The {@link IBaritone} instance.
|
||||
*/
|
||||
default IBaritone getBaritoneForPlayer(EntityPlayerSP player) {
|
||||
for (IBaritone baritone : getAllBaritones()) {
|
||||
for (IBaritone baritone : this.getAllBaritones()) {
|
||||
if (Objects.equals(player, baritone.getPlayerContext().player())) {
|
||||
return baritone;
|
||||
}
|
||||
@@ -68,6 +67,39 @@ public interface IBaritoneProvider {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the {@link IBaritone} instance for a given {@link Minecraft}.
|
||||
*
|
||||
* @param minecraft The minecraft
|
||||
* @return The {@link IBaritone} instance.
|
||||
*/
|
||||
default IBaritone getBaritoneForMinecraft(Minecraft minecraft) {
|
||||
for (IBaritone baritone : this.getAllBaritones()) {
|
||||
if (Objects.equals(minecraft, baritone.getPlayerContext().minecraft())) {
|
||||
return baritone;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates and registers a new {@link IBaritone} instance using the specified {@link Minecraft}. The existing
|
||||
* instance is returned if already registered.
|
||||
*
|
||||
* @param minecraft The minecraft
|
||||
* @return The {@link IBaritone} instance
|
||||
*/
|
||||
IBaritone createBaritone(Minecraft minecraft);
|
||||
|
||||
/**
|
||||
* Destroys and removes the specified {@link IBaritone} instance. If the specified instance is the
|
||||
* {@link #getPrimaryBaritone() primary baritone}, this operation has no effect and will return {@code false}.
|
||||
*
|
||||
* @param baritone The baritone instance to remove
|
||||
* @return Whether the baritone instance was removed
|
||||
*/
|
||||
boolean destroyBaritone(IBaritone baritone);
|
||||
|
||||
/**
|
||||
* Returns the {@link IWorldScanner} instance. This is not a type returned by
|
||||
* {@link IBaritone} implementation, because it is not linked with {@link IBaritone}.
|
||||
|
||||
@@ -29,13 +29,17 @@ import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* Baritone's settings. Settings apply to all Baritone instances.
|
||||
@@ -69,6 +73,23 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> allowInventory = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Allow Baritone to automatically put useful items (such as tools and throwaway blocks) on the hotbar while
|
||||
* pathing. This can reduce delays when retrieving items due settings like {@link #ticksBetweenInventoryMoves} and
|
||||
* {@link #inventoryMoveOnlyIfStationary}. Requires {@link #allowInventory}.
|
||||
*/
|
||||
public final Setting<Boolean> allowHotbarManagement = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Wait this many ticks between InventoryBehavior moving inventory items
|
||||
*/
|
||||
public final Setting<Integer> ticksBetweenInventoryMoves = new Setting<>(1);
|
||||
|
||||
/**
|
||||
* Come to a halt before doing any inventory moves. Intended for anticheat such as 2b2t
|
||||
*/
|
||||
public final Setting<Boolean> inventoryMoveOnlyIfStationary = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Disable baritone's auto-tool at runtime, but still assume that another mod will provide auto tool functionality
|
||||
* <p>
|
||||
@@ -107,6 +128,13 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Double> walkOnWaterOnePenalty = new Setting<>(3D);
|
||||
|
||||
/**
|
||||
* Don't allow breaking blocks next to liquids.
|
||||
* <p>
|
||||
* Enable if you have mods adding custom fluid physics.
|
||||
*/
|
||||
public final Setting<Boolean> strictLiquidCheck = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
|
||||
* Reliability: questionable.
|
||||
@@ -116,6 +144,8 @@ public final class Settings {
|
||||
/**
|
||||
* Allow Baritone to assume it can walk on still water just like any other block.
|
||||
* This functionality is assumed to be provided by a separate library that might have imported Baritone.
|
||||
* <p>
|
||||
* Note: This will prevent some usage of the frostwalker enchantment, like pillaring up from water.
|
||||
*/
|
||||
public final Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
|
||||
|
||||
@@ -196,7 +226,7 @@ public final class Settings {
|
||||
* Blocks that Baritone is not allowed to break
|
||||
*/
|
||||
public final Setting<List<Block>> blocksToDisallowBreaking = new Setting<>(new ArrayList<>(
|
||||
// Leave Empty by Default
|
||||
// Leave Empty by Default
|
||||
));
|
||||
|
||||
/**
|
||||
@@ -279,6 +309,12 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> buildIgnoreDirection = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* A list of names of block properties the builder will ignore.
|
||||
*/
|
||||
public final Setting<List<String>> buildIgnoreProperties = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||
)));
|
||||
|
||||
/**
|
||||
* If this setting is true, Baritone will never break a block that is adjacent to an unsupported falling block.
|
||||
* <p>
|
||||
@@ -593,6 +629,13 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* The chunk packer queue can never grow to larger than this, if it does, the oldest chunks are discarded
|
||||
* <p>
|
||||
* The newest chunks are kept, so that if you're moving in a straight line quickly then stop, your immediate render distance is still included
|
||||
*/
|
||||
public final Setting<Integer> chunkPackerQueueMaxSize = new Setting<>(2000);
|
||||
|
||||
/**
|
||||
* Fill in blocks behind you
|
||||
*/
|
||||
@@ -694,6 +737,18 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> freeLook = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Break and place blocks without having to force the client-sided rotations. Having this setting enabled implies
|
||||
* {@link #freeLook}.
|
||||
*/
|
||||
public final Setting<Boolean> blockFreeLook = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* When true, the player will remain with its existing look direction as often as possible.
|
||||
* Although, in some cases this can get it stuck, hence this setting to disable that behavior.
|
||||
*/
|
||||
public final Setting<Boolean> remainWithExistingLookDirection = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
|
||||
* <p>
|
||||
@@ -828,6 +883,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Integer> minYLevelWhileMining = new Setting<>(0);
|
||||
|
||||
/**
|
||||
* Sets the maximum y level to mine ores at.
|
||||
*/
|
||||
public final Setting<Integer> maxYLevelWhileMining = new Setting<>(255); // 1.17+ defaults to maximum possible world height
|
||||
|
||||
/**
|
||||
* This will only allow baritone to mine exposed ores, can be used to stop ore obfuscators on servers that use them.
|
||||
*/
|
||||
@@ -912,7 +972,7 @@ public final class Settings {
|
||||
/**
|
||||
* Only build the selected part of schematics
|
||||
*/
|
||||
public final Setting<Boolean> buildOnlySelection = new Setting<>(false);
|
||||
public final Setting<Boolean> buildOnlySelection = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* How far to move before repeating the build. 0 to disable repeating on a certain axis, 0,0,0 to disable entirely
|
||||
@@ -1124,6 +1184,7 @@ public final class Settings {
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
@JavaOnly
|
||||
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(msg -> Minecraft.getMinecraft().ingameGUI.getChatGUI().printChatMessage(msg));
|
||||
|
||||
/**
|
||||
@@ -1131,6 +1192,7 @@ public final class Settings {
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
@JavaOnly
|
||||
public final Setting<BiConsumer<String, Boolean>> notifier = new Setting<>(NotificationHelper::notify);
|
||||
|
||||
/**
|
||||
@@ -1138,6 +1200,7 @@ public final class Settings {
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
@JavaOnly
|
||||
public final Setting<BiConsumer<ITextComponent, ITextComponent>> toaster = new Setting<>(BaritoneToast::addOrUpdate);
|
||||
|
||||
/**
|
||||
@@ -1282,6 +1345,7 @@ public final class Settings {
|
||||
public T value;
|
||||
public final T defaultValue;
|
||||
private String name;
|
||||
private boolean javaOnly;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Setting(T value) {
|
||||
@@ -1290,6 +1354,7 @@ public final class Settings {
|
||||
}
|
||||
this.value = value;
|
||||
this.defaultValue = value;
|
||||
this.javaOnly = false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1326,8 +1391,25 @@ public final class Settings {
|
||||
public final Type getType() {
|
||||
return settingTypes.get(this);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should always be the same as whether the setting can be parsed from or serialized to a string; in other
|
||||
* words, the only way to modify it is by writing to {@link #value} programatically.
|
||||
*
|
||||
* @return {@code true} if the setting can not be set or read by the user
|
||||
*/
|
||||
public boolean isJavaOnly() {
|
||||
return javaOnly;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Marks a {@link Setting} field as being {@link Setting#isJavaOnly() Java-only}
|
||||
*/
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@Target(ElementType.FIELD)
|
||||
private @interface JavaOnly {}
|
||||
|
||||
// here be dragons
|
||||
|
||||
Settings() {
|
||||
@@ -1343,6 +1425,7 @@ public final class Settings {
|
||||
Setting<?> setting = (Setting<?>) field.get(this);
|
||||
String name = field.getName();
|
||||
setting.name = name;
|
||||
setting.javaOnly = field.isAnnotationPresent(JavaOnly.class);
|
||||
name = name.toLowerCase();
|
||||
if (tmpByName.containsKey(name)) {
|
||||
throw new IllegalStateException("Duplicate setting name");
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package baritone.api.behavior;
|
||||
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.behavior.look.IAimProcessor;
|
||||
import baritone.api.utils.Rotation;
|
||||
|
||||
/**
|
||||
@@ -26,14 +28,23 @@ import baritone.api.utils.Rotation;
|
||||
public interface ILookBehavior extends IBehavior {
|
||||
|
||||
/**
|
||||
* Updates the current {@link ILookBehavior} target to target
|
||||
* the specified rotations on the next tick. If force is {@code true},
|
||||
* then freeLook will be overriden and angles will be set regardless.
|
||||
* If any sort of block interaction is required, force should be {@code true},
|
||||
* otherwise, it should be {@code false};
|
||||
* Updates the current {@link ILookBehavior} target to target the specified rotations on the next tick. If any sort
|
||||
* of block interaction is required, {@code blockInteract} should be {@code true}. It is not guaranteed that the
|
||||
* rotations set by the caller will be the exact rotations expressed by the client (This is due to settings like
|
||||
* {@link Settings#randomLooking}). If the rotations produced by this behavior are required, then the
|
||||
* {@link #getAimProcessor() aim processor} should be used.
|
||||
*
|
||||
* @param rotation The target rotations
|
||||
* @param force Whether or not to "force" the rotations
|
||||
* @param rotation The target rotations
|
||||
* @param blockInteract Whether the target rotations are needed for a block interaction
|
||||
*/
|
||||
void updateTarget(Rotation rotation, boolean force);
|
||||
void updateTarget(Rotation rotation, boolean blockInteract);
|
||||
|
||||
/**
|
||||
* The aim processor instance for this {@link ILookBehavior}, which is responsible for applying additional,
|
||||
* deterministic transformations to the target rotation set by {@link #updateTarget}.
|
||||
*
|
||||
* @return The aim processor
|
||||
* @see IAimProcessor#fork
|
||||
*/
|
||||
IAimProcessor getAimProcessor();
|
||||
}
|
||||
|
||||
45
src/api/java/baritone/api/behavior/look/IAimProcessor.java
Normal file
45
src/api/java/baritone/api/behavior/look/IAimProcessor.java
Normal file
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* 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.behavior.look;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public interface IAimProcessor {
|
||||
|
||||
/**
|
||||
* Returns the actual rotation that will be used when the desired rotation is requested. The returned rotation
|
||||
* always reflects what would happen in the upcoming tick. In other words, it is a pure function, and no internal
|
||||
* state changes. If simulation of the rotation states beyond the next tick is required, then a
|
||||
* {@link IAimProcessor#fork fork} should be created.
|
||||
*
|
||||
* @param desired The desired rotation to set
|
||||
* @return The actual rotation
|
||||
*/
|
||||
Rotation peekRotation(Rotation desired);
|
||||
|
||||
/**
|
||||
* Returns a copy of this {@link IAimProcessor} which has its own internal state and is manually tickable.
|
||||
*
|
||||
* @return The forked processor
|
||||
* @see ITickableAimProcessor
|
||||
*/
|
||||
ITickableAimProcessor fork();
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* 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.behavior.look;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public interface ITickableAimProcessor extends IAimProcessor {
|
||||
|
||||
/**
|
||||
* Advances the internal state of this aim processor by a single tick.
|
||||
*/
|
||||
void tick();
|
||||
|
||||
/**
|
||||
* Calls {@link #tick()} the specified number of times.
|
||||
*
|
||||
* @param ticks The number of calls
|
||||
*/
|
||||
void advance(int ticks);
|
||||
|
||||
/**
|
||||
* Returns the actual rotation as provided by {@link #peekRotation(Rotation)}, and then automatically advances the
|
||||
* internal state by one {@link #tick() tick}.
|
||||
*
|
||||
* @param rotation The desired rotation to set
|
||||
* @return The actual rotation
|
||||
*/
|
||||
Rotation nextRotation(Rotation rotation);
|
||||
}
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package baritone.api.cache;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/24/2018
|
||||
@@ -29,4 +31,11 @@ public interface IWorldProvider {
|
||||
* @return The current world data
|
||||
*/
|
||||
IWorldData getCurrentWorld();
|
||||
|
||||
default void ifWorldLoaded(Consumer<IWorldData> callback) {
|
||||
final IWorldData currentWorld = this.getCurrentWorld();
|
||||
if (currentWorld != null) {
|
||||
callback.accept(currentWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,11 +23,17 @@ import net.minecraft.block.Block;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
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());
|
||||
@@ -40,13 +46,19 @@ public enum BlockById implements IDatatypeFor<Block> {
|
||||
|
||||
@Override
|
||||
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(
|
||||
Block.REGISTRY.getKeys()
|
||||
.stream()
|
||||
.map(Object::toString)
|
||||
)
|
||||
.filterPrefixNamespaced(ctx.getConsumer().getString())
|
||||
.filterPrefixNamespaced(arg)
|
||||
.sortAlphabetically()
|
||||
.stream();
|
||||
}
|
||||
|
||||
43
src/api/java/baritone/api/command/datatypes/ForAxis.java
Normal file
43
src/api/java/baritone/api/command/datatypes/ForAxis.java
Normal file
@@ -0,0 +1,43 @@
|
||||
/*
|
||||
* 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.util.EnumFacing;
|
||||
|
||||
import java.util.Locale;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum ForAxis implements IDatatypeFor<EnumFacing.Axis> {
|
||||
INSTANCE;
|
||||
|
||||
@Override
|
||||
public EnumFacing.Axis get(IDatatypeContext ctx) throws CommandException {
|
||||
return EnumFacing.Axis.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
|
||||
return new TabCompleteHelper()
|
||||
.append(Stream.of(EnumFacing.Axis.values())
|
||||
.map(EnumFacing.Axis::getName).map(String::toLowerCase))
|
||||
.filterPrefix(ctx.getConsumer().getString())
|
||||
.stream();
|
||||
}
|
||||
}
|
||||
@@ -18,20 +18,136 @@
|
||||
package baritone.api.command.datatypes;
|
||||
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import java.util.Set;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum ForBlockOptionalMeta implements IDatatypeFor<BlockOptionalMeta> {
|
||||
INSTANCE;
|
||||
|
||||
/**
|
||||
* Matches (domain:)?name([(property=value)*])? but the input can be truncated at any position.
|
||||
* domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ because that's what mc 1.13+ accepts.
|
||||
* property and value use the same format as domain.
|
||||
*/
|
||||
// Good luck reading this.
|
||||
private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?(?:[a-z0-9/_.-]+(?:\\[(?:(?:[a-z0-9_.-]+=[a-z0-9_.-]+,)*(?:[a-z0-9_.-]+(?:=(?:[a-z0-9_.-]+(?:\\])?)?)?)?|\\])?)?)?");
|
||||
|
||||
@Override
|
||||
public BlockOptionalMeta get(IDatatypeContext ctx) throws CommandException {
|
||||
return new BlockOptionalMeta(ctx.getConsumer().getString());
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(IDatatypeContext ctx) {
|
||||
return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
|
||||
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
|
||||
String arg = ctx.getConsumer().peekString();
|
||||
|
||||
if (!PATTERN.matcher(arg).matches()) {
|
||||
// Invalid format; we can't complete this.
|
||||
ctx.getConsumer().getString();
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
if (arg.endsWith("]")) {
|
||||
// We are already done.
|
||||
ctx.getConsumer().getString();
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
if (!arg.contains("[")) {
|
||||
// no properties so we are completing the block id
|
||||
return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
|
||||
}
|
||||
|
||||
ctx.getConsumer().getString();
|
||||
|
||||
// destructuring assignment? Please?
|
||||
String blockId, properties;
|
||||
{
|
||||
String[] parts = splitLast(arg, '[');
|
||||
blockId = parts[0];
|
||||
properties = parts[1];
|
||||
}
|
||||
|
||||
Block block = Block.REGISTRY.getObject(new ResourceLocation(blockId));
|
||||
if (block == null) {
|
||||
// This block doesn't exist so there's no properties to complete.
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
String leadingProperties, lastProperty;
|
||||
{
|
||||
String[] parts = splitLast(properties, ',');
|
||||
leadingProperties = parts[0];
|
||||
lastProperty = parts[1];
|
||||
}
|
||||
|
||||
if (!lastProperty.contains("=")) {
|
||||
// The last property-value pair doesn't have a value yet so we are completing its name
|
||||
Set<String> usedProps = Stream.of(leadingProperties.split(","))
|
||||
.map(pair -> pair.split("=")[0])
|
||||
.collect(Collectors.toSet());
|
||||
|
||||
String prefix = arg.substring(0, arg.length() - lastProperty.length());
|
||||
return new TabCompleteHelper()
|
||||
.append(
|
||||
block.getBlockState()
|
||||
.getProperties()
|
||||
.stream()
|
||||
.map(IProperty::getName)
|
||||
)
|
||||
.filter(prop -> !usedProps.contains(prop))
|
||||
.filterPrefix(lastProperty)
|
||||
.sortAlphabetically()
|
||||
.map(prop -> prefix + prop)
|
||||
.stream();
|
||||
}
|
||||
|
||||
String lastName, lastValue;
|
||||
{
|
||||
String[] parts = splitLast(lastProperty, '=');
|
||||
lastName = parts[0];
|
||||
lastValue = parts[1];
|
||||
}
|
||||
|
||||
// We are completing the value of a property
|
||||
String prefix = arg.substring(0, arg.length() - lastValue.length());
|
||||
|
||||
IProperty<?> property = block.getBlockState().getProperty(lastName);
|
||||
if (property == null) {
|
||||
// The property does not exist so there's no values to complete
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
return new TabCompleteHelper()
|
||||
.append(getValues(property))
|
||||
.filterPrefix(lastValue)
|
||||
.sortAlphabetically()
|
||||
.map(val -> prefix + val)
|
||||
.stream();
|
||||
}
|
||||
|
||||
/**
|
||||
* Always returns exactly two strings.
|
||||
* If the separator is not found the FIRST returned string is empty.
|
||||
*/
|
||||
private static String[] splitLast(String string, char chr) {
|
||||
int idx = string.lastIndexOf(chr);
|
||||
if (idx == -1) {
|
||||
return new String[]{"", string};
|
||||
}
|
||||
return new String[]{string.substring(0, idx), string.substring(idx + 1)};
|
||||
}
|
||||
|
||||
// this shouldn't need to be a separate method?
|
||||
private static <T extends Comparable<T>> Stream<String> getValues(IProperty<T> property) {
|
||||
return property.getAllowedValues().stream().map(property::getName);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -26,7 +26,8 @@ import java.util.stream.Stream;
|
||||
|
||||
public enum RelativeCoordinate implements IDatatypePost<Double, Double> {
|
||||
INSTANCE;
|
||||
private static Pattern PATTERN = Pattern.compile("^(~?)([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)([k-k]?)|)$");
|
||||
private static String ScalesAliasRegex = "[kKmM]";
|
||||
private static Pattern PATTERN = Pattern.compile("^(~?)([+-]?(?:\\d+(?:\\.\\d*)?|\\.\\d+)(" + ScalesAliasRegex + "?)|)$");
|
||||
|
||||
@Override
|
||||
public Double apply(IDatatypeContext ctx, Double origin) throws CommandException {
|
||||
@@ -41,11 +42,15 @@ public enum RelativeCoordinate implements IDatatypePost<Double, Double> {
|
||||
|
||||
boolean isRelative = !matcher.group(1).isEmpty();
|
||||
|
||||
double offset = matcher.group(2).isEmpty() ? 0 : Double.parseDouble(matcher.group(2).replaceAll("k", ""));
|
||||
double offset = matcher.group(2).isEmpty() ? 0 : Double.parseDouble(matcher.group(2).replaceAll(ScalesAliasRegex, ""));
|
||||
|
||||
if (matcher.group(2).contains("k")) {
|
||||
if (matcher.group(2).toLowerCase().contains("k")) {
|
||||
offset *= 1000;
|
||||
}
|
||||
if (matcher.group(2).toLowerCase().contains("m")) {
|
||||
offset *= 1000000;
|
||||
}
|
||||
|
||||
|
||||
if (isRelative) {
|
||||
return origin + offset;
|
||||
|
||||
@@ -19,6 +19,8 @@ package baritone.api.command.datatypes;
|
||||
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.utils.Helper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
@@ -83,18 +85,23 @@ public enum RelativeFile implements IDatatypePost<File, File> {
|
||||
boolean useParent = !currentPathStringThing.isEmpty() && !currentPathStringThing.endsWith(File.separator);
|
||||
File currentFile = currentPath.isAbsolute() ? currentPath.toFile() : new File(base, currentPathStringThing);
|
||||
return Stream.of(Objects.requireNonNull(getCanonicalFileUnchecked(
|
||||
useParent
|
||||
? currentFile.getParentFile()
|
||||
: currentFile
|
||||
).listFiles()))
|
||||
useParent
|
||||
? currentFile.getParentFile()
|
||||
: currentFile
|
||||
).listFiles()))
|
||||
.map(f -> (currentPath.isAbsolute() ? f : basePath.relativize(f.toPath()).toString()) +
|
||||
(f.isDirectory() ? File.separator : ""))
|
||||
.filter(s -> s.toLowerCase(Locale.US).startsWith(currentPathStringThing.toLowerCase(Locale.US)))
|
||||
.filter(s -> !s.contains(" "));
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static File gameDir() {
|
||||
File gameDir = HELPER.mc.gameDir.getAbsoluteFile();
|
||||
return gameDir(Helper.mc);
|
||||
}
|
||||
|
||||
public static File gameDir(Minecraft mc) {
|
||||
File gameDir = mc.gameDir.getAbsoluteFile();
|
||||
if (gameDir.getName().equals(".")) {
|
||||
return gameDir.getParentFile();
|
||||
}
|
||||
|
||||
@@ -253,7 +253,7 @@ public class TabCompleteHelper {
|
||||
public TabCompleteHelper addSettings() {
|
||||
return append(
|
||||
BaritoneAPI.getSettings().allSettings.stream()
|
||||
.filter(s -> !SettingsUtil.javaOnlySetting(s))
|
||||
.filter(s -> !s.isJavaOnly())
|
||||
.map(Settings.Setting::getName)
|
||||
.sorted(String.CASE_INSENSITIVE_ORDER)
|
||||
);
|
||||
|
||||
@@ -84,7 +84,7 @@ public class Registry<V> {
|
||||
* @param entry The entry to unregister.
|
||||
*/
|
||||
public void unregister(V entry) {
|
||||
if (registered(entry)) {
|
||||
if (!registered(entry)) {
|
||||
return;
|
||||
}
|
||||
_entries.remove(entry);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.utils.Rotation;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
|
||||
@@ -31,14 +32,27 @@ public final class RotationMoveEvent {
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
private final Rotation original;
|
||||
|
||||
/**
|
||||
* The yaw rotation
|
||||
*/
|
||||
private float yaw;
|
||||
|
||||
public RotationMoveEvent(Type type, float yaw) {
|
||||
/**
|
||||
* The pitch rotation
|
||||
*/
|
||||
private float pitch;
|
||||
|
||||
public RotationMoveEvent(Type type, float yaw, float pitch) {
|
||||
this.type = type;
|
||||
this.original = new Rotation(yaw, pitch);
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
public Rotation getOriginal() {
|
||||
return this.original;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -46,21 +60,37 @@ public final class RotationMoveEvent {
|
||||
*
|
||||
* @param yaw Yaw rotation
|
||||
*/
|
||||
public final void setYaw(float yaw) {
|
||||
public void setYaw(float yaw) {
|
||||
this.yaw = yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The yaw rotation
|
||||
*/
|
||||
public final float getYaw() {
|
||||
public float getYaw() {
|
||||
return this.yaw;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the pitch movement rotation
|
||||
*
|
||||
* @param pitch Pitch rotation
|
||||
*/
|
||||
public void setPitch(float pitch) {
|
||||
this.pitch = pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The pitch rotation
|
||||
*/
|
||||
public float getPitch() {
|
||||
return pitch;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of the event
|
||||
*/
|
||||
public final Type getType() {
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
|
||||
@@ -42,6 +42,16 @@ public class GoalAxis implements Goal {
|
||||
return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.value + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.value, y);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
return o.getClass() == GoalAxis.class;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 201385781;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalAxis";
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -66,6 +67,26 @@ public class GoalBlock implements Goal, IGoalRenderPos {
|
||||
return calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalBlock goal = (GoalBlock) o;
|
||||
return x == goal.x
|
||||
&& y == goal.y
|
||||
&& z == goal.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) BetterBlockPos.longHash(x, y, z) * 905165533;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -67,6 +67,24 @@ public class GoalComposite implements Goal {
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalComposite goal = (GoalComposite) o;
|
||||
return Arrays.equals(goals, goal.goals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return Arrays.hashCode(goals);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalComposite" + Arrays.toString(goals);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -60,6 +61,26 @@ public class GoalGetToBlock implements Goal, IGoalRenderPos {
|
||||
return GoalBlock.calculate(xDiff, yDiff < 0 ? yDiff + 1 : yDiff, zDiff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalGetToBlock goal = (GoalGetToBlock) o;
|
||||
return x == goal.x
|
||||
&& y == goal.y
|
||||
&& z == goal.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) BetterBlockPos.longHash(x, y, z) * -49639096;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -17,6 +17,8 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Invert any goal.
|
||||
* <p>
|
||||
@@ -50,6 +52,24 @@ public class GoalInverted implements Goal {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalInverted goal = (GoalInverted) o;
|
||||
return Objects.equals(origin, goal.origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return origin.hashCode() * 495796690;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("GoalInverted{%s}", origin.toString());
|
||||
|
||||
@@ -17,10 +17,11 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class GoalNear implements Goal, IGoalRenderPos {
|
||||
@@ -86,6 +87,27 @@ public class GoalNear implements Goal, IGoalRenderPos {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalNear goal = (GoalNear) o;
|
||||
return x == goal.x
|
||||
&& y == goal.y
|
||||
&& z == goal.z
|
||||
&& rangeSq == goal.rangeSq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) BetterBlockPos.longHash(x, y, z) + rangeSq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -18,11 +18,12 @@
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* Useful for automated combat (retreating specifically)
|
||||
@@ -124,6 +125,29 @@ public class GoalRunAway implements Goal {
|
||||
return maxInside;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalRunAway goal = (GoalRunAway) o;
|
||||
return distanceSq == goal.distanceSq
|
||||
&& Arrays.equals(from, goal.from)
|
||||
&& Objects.equals(maintainY, goal.maintainY);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = Arrays.hashCode(from);
|
||||
hash = hash * 1196803141 + distanceSq;
|
||||
hash = hash * -2053788840 + maintainY;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (maintainY != null) {
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -69,6 +70,31 @@ public class GoalStrictDirection implements Goal {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalStrictDirection goal = (GoalStrictDirection) o;
|
||||
return x == goal.x
|
||||
&& y == goal.y
|
||||
&& z == goal.z
|
||||
&& dx == goal.dx
|
||||
&& dz == goal.dz;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = (int) BetterBlockPos.longHash(x, y, z);
|
||||
hash = hash * 630627507 + dx;
|
||||
hash = hash * -283028380 + dz;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -72,6 +73,26 @@ public class GoalTwoBlocks implements Goal, IGoalRenderPos {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalTwoBlocks goal = (GoalTwoBlocks) o;
|
||||
return x == goal.x
|
||||
&& y == goal.y
|
||||
&& z == goal.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return (int) BetterBlockPos.longHash(x, y, z) * 516508351;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -64,6 +64,27 @@ public class GoalXZ implements Goal {
|
||||
return calculate(xDiff, zDiff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalXZ goal = (GoalXZ) o;
|
||||
return x == goal.x && z == goal.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
int hash = 1791873246;
|
||||
hash = hash * 222601791 + x;
|
||||
hash = hash * -1331679453 + z;
|
||||
return hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -58,6 +58,24 @@ public class GoalYLevel implements Goal, ActionCosts {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || getClass() != o.getClass()) {
|
||||
return false;
|
||||
}
|
||||
|
||||
GoalYLevel goal = (GoalYLevel) o;
|
||||
return level == goal.level;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return level * 1271009915;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -51,6 +51,7 @@ public interface IBuilderProcess extends IBaritoneProcess {
|
||||
*/
|
||||
boolean build(String name, File schematic, Vec3i origin);
|
||||
|
||||
@Deprecated
|
||||
default boolean build(String schematicFile, BlockPos origin) {
|
||||
File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile);
|
||||
return build(schematicFile, file, origin);
|
||||
@@ -58,6 +59,8 @@ public interface IBuilderProcess extends IBaritoneProcess {
|
||||
|
||||
void buildOpenSchematic();
|
||||
|
||||
void buildOpenLitematic(int i);
|
||||
|
||||
void pause();
|
||||
|
||||
boolean isPaused();
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.schematic;
|
||||
|
||||
import baritone.api.schematic.mask.Mask;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
import java.util.List;
|
||||
@@ -41,4 +42,14 @@ public abstract class MaskSchematic extends AbstractSchematic {
|
||||
public IBlockState desiredState(int x, int y, int z, IBlockState current, List<IBlockState> approxPlaceable) {
|
||||
return schematic.desiredState(x, y, z, current, approxPlaceable);
|
||||
}
|
||||
|
||||
public static MaskSchematic create(ISchematic schematic, Mask function) {
|
||||
return new MaskSchematic(schematic) {
|
||||
|
||||
@Override
|
||||
protected boolean partOfMask(int x, int y, int z, IBlockState currentState) {
|
||||
return function.partOfMask(x, y, z, currentState);
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
@@ -33,7 +34,7 @@ public class SubstituteSchematic extends AbstractSchematic {
|
||||
private final Map<Block, List<Block>> substitutions;
|
||||
private final Map<IBlockState, Map<Block, IBlockState>> blockStateCache = new HashMap<>();
|
||||
|
||||
public SubstituteSchematic(ISchematic schematic, Map<Block,List<Block>> substitutions) {
|
||||
public SubstituteSchematic(ISchematic schematic, Map<Block, List<Block>> substitutions) {
|
||||
super(schematic.widthX(), schematic.heightY(), schematic.lengthZ());
|
||||
this.schematic = schematic;
|
||||
this.substitutions = substitutions;
|
||||
@@ -80,9 +81,10 @@ public class SubstituteSchematic extends AbstractSchematic {
|
||||
} catch (IllegalArgumentException e) { //property does not exist for target block
|
||||
}
|
||||
}
|
||||
blockStateCache.computeIfAbsent(state, s -> new HashMap<Block,IBlockState>()).put(block, newState);
|
||||
blockStateCache.computeIfAbsent(state, s -> new HashMap<Block, IBlockState>()).put(block, newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
private <T extends Comparable<T>> IBlockState copySingleProp(IBlockState fromState, IBlockState toState, IProperty<T> prop) {
|
||||
return toState.withProperty(prop, fromState.getValue(prop));
|
||||
}
|
||||
|
||||
49
src/api/java/baritone/api/schematic/mask/AbstractMask.java
Normal file
49
src/api/java/baritone/api/schematic/mask/AbstractMask.java
Normal file
@@ -0,0 +1,49 @@
|
||||
/*
|
||||
* 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.mask;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public abstract class AbstractMask implements Mask {
|
||||
|
||||
private final int widthX;
|
||||
private final int heightY;
|
||||
private final int lengthZ;
|
||||
|
||||
public AbstractMask(int widthX, int heightY, int lengthZ) {
|
||||
this.widthX = widthX;
|
||||
this.heightY = heightY;
|
||||
this.lengthZ = lengthZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int widthX() {
|
||||
return this.widthX;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int heightY() {
|
||||
return this.heightY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int lengthZ() {
|
||||
return this.lengthZ;
|
||||
}
|
||||
}
|
||||
60
src/api/java/baritone/api/schematic/mask/Mask.java
Normal file
60
src/api/java/baritone/api/schematic/mask/Mask.java
Normal file
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* 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.mask;
|
||||
|
||||
import baritone.api.schematic.mask.operator.BinaryOperatorMask;
|
||||
import baritone.api.schematic.mask.operator.NotMask;
|
||||
import baritone.api.utils.BooleanBinaryOperators;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public interface Mask {
|
||||
|
||||
/**
|
||||
* @param x The relative x position of the block
|
||||
* @param y The relative y position of the block
|
||||
* @param z The relative z position of the block
|
||||
* @param currentState The current state of that block in the world, may be {@code null}
|
||||
* @return Whether the given position is included in this mask
|
||||
*/
|
||||
boolean partOfMask(int x, int y, int z, IBlockState currentState);
|
||||
|
||||
int widthX();
|
||||
|
||||
int heightY();
|
||||
|
||||
int lengthZ();
|
||||
|
||||
default Mask not() {
|
||||
return new NotMask(this);
|
||||
}
|
||||
|
||||
default Mask union(Mask other) {
|
||||
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.OR);
|
||||
}
|
||||
|
||||
default Mask intersection(Mask other) {
|
||||
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.AND);
|
||||
}
|
||||
|
||||
default Mask xor(Mask other) {
|
||||
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.XOR);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,44 @@
|
||||
/*
|
||||
* 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.mask;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
final class PreComputedMask extends AbstractMask implements StaticMask {
|
||||
|
||||
private final boolean[][][] mask;
|
||||
|
||||
public PreComputedMask(StaticMask mask) {
|
||||
super(mask.widthX(), mask.heightY(), mask.lengthZ());
|
||||
|
||||
this.mask = new boolean[this.heightY()][this.lengthZ()][this.widthX()];
|
||||
for (int y = 0; y < this.heightY(); y++) {
|
||||
for (int z = 0; z < this.lengthZ(); z++) {
|
||||
for (int x = 0; x < this.widthX(); x++) {
|
||||
this.mask[y][z][x] = mask.partOfMask(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z) {
|
||||
return this.mask[y][z][x];
|
||||
}
|
||||
}
|
||||
82
src/api/java/baritone/api/schematic/mask/StaticMask.java
Normal file
82
src/api/java/baritone/api/schematic/mask/StaticMask.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.api.schematic.mask;
|
||||
|
||||
import baritone.api.schematic.mask.operator.BinaryOperatorMask;
|
||||
import baritone.api.schematic.mask.operator.NotMask;
|
||||
import baritone.api.utils.BooleanBinaryOperators;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
/**
|
||||
* A mask that is context-free. In other words, it doesn't require the current block state to determine if a relative
|
||||
* position is a part of the mask.
|
||||
*
|
||||
* @author Brady
|
||||
*/
|
||||
public interface StaticMask extends Mask {
|
||||
|
||||
/**
|
||||
* Determines if a given relative coordinate is included in this mask, without the need for the current block state.
|
||||
*
|
||||
* @param x The relative x position of the block
|
||||
* @param y The relative y position of the block
|
||||
* @param z The relative z position of the block
|
||||
* @return Whether the given position is included in this mask
|
||||
*/
|
||||
boolean partOfMask(int x, int y, int z);
|
||||
|
||||
/**
|
||||
* Implements the parent {@link Mask#partOfMask partOfMask function} by calling the static function
|
||||
* provided in this functional interface without needing the {@link IBlockState} argument. This {@code default}
|
||||
* implementation should <b><u>NOT</u></b> be overriden.
|
||||
*
|
||||
* @param x The relative x position of the block
|
||||
* @param y The relative y position of the block
|
||||
* @param z The relative z position of the block
|
||||
* @param currentState The current state of that block in the world, may be {@code null}
|
||||
* @return Whether the given position is included in this mask
|
||||
*/
|
||||
@Override
|
||||
default boolean partOfMask(int x, int y, int z, IBlockState currentState) {
|
||||
return this.partOfMask(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
default StaticMask not() {
|
||||
return new NotMask.Static(this);
|
||||
}
|
||||
|
||||
default StaticMask union(StaticMask other) {
|
||||
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.OR);
|
||||
}
|
||||
|
||||
default StaticMask intersection(StaticMask other) {
|
||||
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.AND);
|
||||
}
|
||||
|
||||
default StaticMask xor(StaticMask other) {
|
||||
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.XOR);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a pre-computed mask using {@code this} function, with the specified size parameters.
|
||||
*/
|
||||
default StaticMask compute() {
|
||||
return new PreComputedMask(this);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,79 @@
|
||||
/*
|
||||
* 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.mask.operator;
|
||||
|
||||
import baritone.api.schematic.mask.AbstractMask;
|
||||
import baritone.api.schematic.mask.Mask;
|
||||
import baritone.api.schematic.mask.StaticMask;
|
||||
import baritone.api.utils.BooleanBinaryOperator;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class BinaryOperatorMask extends AbstractMask {
|
||||
|
||||
private final Mask a;
|
||||
private final Mask b;
|
||||
private final BooleanBinaryOperator operator;
|
||||
|
||||
public BinaryOperatorMask(Mask a, Mask b, BooleanBinaryOperator operator) {
|
||||
super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z, IBlockState currentState) {
|
||||
return this.operator.applyAsBoolean(
|
||||
partOfMask(a, x, y, z, currentState),
|
||||
partOfMask(b, x, y, z, currentState)
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean partOfMask(Mask mask, int x, int y, int z, IBlockState currentState) {
|
||||
return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.partOfMask(x, y, z, currentState);
|
||||
}
|
||||
|
||||
public static final class Static extends AbstractMask implements StaticMask {
|
||||
|
||||
private final StaticMask a;
|
||||
private final StaticMask b;
|
||||
private final BooleanBinaryOperator operator;
|
||||
|
||||
public Static(StaticMask a, StaticMask b, BooleanBinaryOperator operator) {
|
||||
super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
this.operator = operator;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z) {
|
||||
return this.operator.applyAsBoolean(
|
||||
partOfMask(a, x, y, z),
|
||||
partOfMask(b, x, y, z)
|
||||
);
|
||||
}
|
||||
|
||||
private static boolean partOfMask(StaticMask mask, int x, int y, int z) {
|
||||
return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.partOfMask(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,56 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.schematic.mask.operator;
|
||||
|
||||
import baritone.api.schematic.mask.AbstractMask;
|
||||
import baritone.api.schematic.mask.Mask;
|
||||
import baritone.api.schematic.mask.StaticMask;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class NotMask extends AbstractMask {
|
||||
|
||||
private final Mask source;
|
||||
|
||||
public NotMask(Mask source) {
|
||||
super(source.widthX(), source.heightY(), source.lengthZ());
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z, IBlockState currentState) {
|
||||
return !this.source.partOfMask(x, y, z, currentState);
|
||||
}
|
||||
|
||||
public static final class Static extends AbstractMask implements StaticMask {
|
||||
|
||||
private final StaticMask source;
|
||||
|
||||
public Static(StaticMask source) {
|
||||
super(source.widthX(), source.heightY(), source.lengthZ());
|
||||
this.source = source;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z) {
|
||||
return !this.source.partOfMask(x, y, z);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,69 @@
|
||||
/*
|
||||
* 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.mask.shape;
|
||||
|
||||
import baritone.api.schematic.mask.AbstractMask;
|
||||
import baritone.api.schematic.mask.StaticMask;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class CylinderMask extends AbstractMask implements StaticMask {
|
||||
|
||||
private final double centerA;
|
||||
private final double centerB;
|
||||
private final double radiusSqA;
|
||||
private final double radiusSqB;
|
||||
private final boolean filled;
|
||||
private final EnumFacing.Axis alignment;
|
||||
|
||||
public CylinderMask(int widthX, int heightY, int lengthZ, boolean filled, EnumFacing.Axis alignment) {
|
||||
super(widthX, heightY, lengthZ);
|
||||
this.centerA = this.getA(widthX, heightY, alignment) / 2.0;
|
||||
this.centerB = this.getB(heightY, lengthZ, alignment) / 2.0;
|
||||
this.radiusSqA = (this.centerA - 1) * (this.centerA - 1);
|
||||
this.radiusSqB = (this.centerB - 1) * (this.centerB - 1);
|
||||
this.filled = filled;
|
||||
this.alignment = alignment;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z) {
|
||||
double da = Math.abs((this.getA(x, y, this.alignment) + 0.5) - this.centerA);
|
||||
double db = Math.abs((this.getB(y, z, this.alignment) + 0.5) - this.centerB);
|
||||
if (this.outside(da, db)) {
|
||||
return false;
|
||||
}
|
||||
return this.filled
|
||||
|| this.outside(da + 1, db)
|
||||
|| this.outside(da, db + 1);
|
||||
}
|
||||
|
||||
private boolean outside(double da, double db) {
|
||||
return da * da / this.radiusSqA + db * db / this.radiusSqB > 1;
|
||||
}
|
||||
|
||||
private static int getA(int x, int y, EnumFacing.Axis alignment) {
|
||||
return alignment == EnumFacing.Axis.X ? y : x;
|
||||
}
|
||||
|
||||
private static int getB(int y, int z, EnumFacing.Axis alignment) {
|
||||
return alignment == EnumFacing.Axis.Z ? y : z;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,64 @@
|
||||
/*
|
||||
* 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.mask.shape;
|
||||
|
||||
import baritone.api.schematic.mask.AbstractMask;
|
||||
import baritone.api.schematic.mask.StaticMask;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class SphereMask extends AbstractMask implements StaticMask {
|
||||
|
||||
private final double centerX;
|
||||
private final double centerY;
|
||||
private final double centerZ;
|
||||
private final double radiusSqX;
|
||||
private final double radiusSqY;
|
||||
private final double radiusSqZ;
|
||||
private final boolean filled;
|
||||
|
||||
public SphereMask(int widthX, int heightY, int lengthZ, boolean filled) {
|
||||
super(widthX, heightY, lengthZ);
|
||||
this.centerX = widthX / 2.0;
|
||||
this.centerY = heightY / 2.0;
|
||||
this.centerZ = lengthZ / 2.0;
|
||||
this.radiusSqX = this.centerX * this.centerX;
|
||||
this.radiusSqY = this.centerY * this.centerY;
|
||||
this.radiusSqZ = this.centerZ * this.centerZ;
|
||||
this.filled = filled;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean partOfMask(int x, int y, int z) {
|
||||
double dx = Math.abs((x + 0.5) - this.centerX);
|
||||
double dy = Math.abs((y + 0.5) - this.centerY);
|
||||
double dz = Math.abs((z + 0.5) - this.centerZ);
|
||||
if (this.outside(dx, dy, dz)) {
|
||||
return false;
|
||||
}
|
||||
return this.filled
|
||||
|| this.outside(dx + 1, dy, dz)
|
||||
|| this.outside(dx, dy + 1, dz)
|
||||
|| this.outside(dx, dy, dz + 1);
|
||||
}
|
||||
|
||||
private boolean outside(double dx, double dy, double dz) {
|
||||
return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package baritone.api.utils;
|
||||
|
||||
import baritone.api.utils.accessor.IItemStack;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.properties.IProperty;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -36,21 +37,24 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class BlockOptionalMeta {
|
||||
// id:meta or id[] or id[properties] where id and properties are any text with at least one character and meta is a one or two digit number
|
||||
private static final Pattern PATTERN = Pattern.compile("^(?<id>.+?)(?::(?<meta>\\d\\d?)|\\[(?<properties>.+?)?\\])?$");
|
||||
|
||||
private final Block block;
|
||||
private final int meta;
|
||||
private final boolean noMeta;
|
||||
private final String propertiesDescription; // exists so toString() can return something more useful than a list of all blockstates
|
||||
private final Set<IBlockState> blockstates;
|
||||
private final ImmutableSet<Integer> stateHashes;
|
||||
private final ImmutableSet<Integer> stackHashes;
|
||||
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
|
||||
private final Set<Integer> stateHashes;
|
||||
private final Set<Integer> stackHashes;
|
||||
private static final Map<Object, Object> normalizations;
|
||||
|
||||
public BlockOptionalMeta(@Nonnull Block block, @Nullable Integer meta) {
|
||||
this.block = block;
|
||||
this.noMeta = meta == null;
|
||||
this.meta = noMeta ? 0 : meta;
|
||||
this.blockstates = getStates(block, meta);
|
||||
this.propertiesDescription = "{}";
|
||||
this.blockstates = getStates(block, meta, Collections.emptyMap());
|
||||
this.stateHashes = getStateHashes(blockstates);
|
||||
this.stackHashes = getStackHashes(blockstates);
|
||||
}
|
||||
@@ -60,24 +64,27 @@ public final class BlockOptionalMeta {
|
||||
}
|
||||
|
||||
public BlockOptionalMeta(@Nonnull String selector) {
|
||||
Matcher matcher = pattern.matcher(selector);
|
||||
Matcher matcher = PATTERN.matcher(selector);
|
||||
|
||||
if (!matcher.find()) {
|
||||
throw new IllegalArgumentException("invalid block selector");
|
||||
}
|
||||
|
||||
MatchResult matchResult = matcher.toMatchResult();
|
||||
noMeta = matchResult.group(2) == null;
|
||||
noMeta = matcher.group("meta") == null;
|
||||
|
||||
ResourceLocation id = new ResourceLocation(matchResult.group(1));
|
||||
ResourceLocation id = new ResourceLocation(matcher.group("id"));
|
||||
|
||||
if (!Block.REGISTRY.containsKey(id)) {
|
||||
throw new IllegalArgumentException("Invalid block ID");
|
||||
}
|
||||
|
||||
block = Block.REGISTRY.getObject(id);
|
||||
meta = noMeta ? 0 : Integer.parseInt(matchResult.group(2));
|
||||
blockstates = getStates(block, getMeta());
|
||||
|
||||
String props = matcher.group("properties");
|
||||
Map<IProperty<?>, ?> properties = props == null || props.equals("") ? Collections.emptyMap() : parseProperties(block, props);
|
||||
|
||||
propertiesDescription = props == null ? "{}" : "{" + props.replace("=", ":") + "}";
|
||||
meta = noMeta ? 0 : Integer.parseInt(matcher.group("meta"));
|
||||
blockstates = getStates(block, getMeta(), properties);
|
||||
stateHashes = getStateHashes(blockstates);
|
||||
stackHashes = getStackHashes(blockstates);
|
||||
}
|
||||
@@ -243,9 +250,32 @@ public final class BlockOptionalMeta {
|
||||
return state.getBlock().getMetaFromState(normalize(state));
|
||||
}
|
||||
|
||||
private static Set<IBlockState> getStates(@Nonnull Block block, @Nullable Integer meta) {
|
||||
private static Map<IProperty<?>, ?> parseProperties(Block block, String raw) {
|
||||
ImmutableMap.Builder<IProperty<?>, Object> builder = ImmutableMap.builder();
|
||||
for (String pair : raw.split(",")) {
|
||||
String[] parts = pair.split("=");
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException(String.format("\"%s\" is not a valid property-value pair", pair));
|
||||
}
|
||||
String rawKey = parts[0];
|
||||
String rawValue = parts[1];
|
||||
IProperty<?> key = block.getBlockState().getProperty(rawKey);
|
||||
Comparable<?> value = castToIProperty(key).parseValue(rawValue)
|
||||
.toJavaUtil().orElseThrow(() -> new IllegalArgumentException(String.format(
|
||||
"\"%s\" is not a valid value for %s on %s",
|
||||
rawValue, key, block
|
||||
)));
|
||||
builder.put(key, value);
|
||||
}
|
||||
return builder.build();
|
||||
}
|
||||
|
||||
private static Set<IBlockState> getStates(@Nonnull Block block, @Nullable Integer meta, @Nonnull Map<IProperty<?>, ?> properties) {
|
||||
return block.getBlockState().getValidStates().stream()
|
||||
.filter(blockstate -> meta == null || stateMeta(blockstate) == meta)
|
||||
.filter(blockstate -> properties.entrySet().stream().allMatch(entry ->
|
||||
blockstate.getValue(entry.getKey()) == entry.getValue()
|
||||
))
|
||||
.collect(Collectors.toSet());
|
||||
}
|
||||
|
||||
@@ -274,6 +304,7 @@ public final class BlockOptionalMeta {
|
||||
return block;
|
||||
}
|
||||
|
||||
@Deprecated // deprecated because getMeta() == null no longer implies that this BOM only cares about the block
|
||||
public Integer getMeta() {
|
||||
return noMeta ? null : meta;
|
||||
}
|
||||
@@ -300,7 +331,11 @@ public final class BlockOptionalMeta {
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("BlockOptionalMeta{block=%s,meta=%s}", block, getMeta());
|
||||
if (noMeta) {
|
||||
return String.format("BlockOptionalMeta{block=%s,properties=%s}", block, propertiesDescription);
|
||||
} else {
|
||||
return String.format("BlockOptionalMeta{block=%s,meta=%s}", block, getMeta());
|
||||
}
|
||||
}
|
||||
|
||||
public static IBlockState blockStateFromStack(ItemStack stack) {
|
||||
@@ -315,4 +350,12 @@ public final class BlockOptionalMeta {
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public Set<IBlockState> getAllBlockStates() {
|
||||
return blockstates;
|
||||
}
|
||||
|
||||
public Set<Integer> stackHashes() {
|
||||
return stackHashes;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,68 +17,70 @@
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.utils.accessor.IItemStack;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class BlockOptionalMetaLookup {
|
||||
|
||||
private final ImmutableSet<Block> blockSet;
|
||||
private final ImmutableSet<IBlockState> blockStateSet;
|
||||
private final ImmutableSet<Integer> stackHashes;
|
||||
private final BlockOptionalMeta[] boms;
|
||||
|
||||
public BlockOptionalMetaLookup(BlockOptionalMeta... boms) {
|
||||
this.boms = boms;
|
||||
Set<Block> blocks = new HashSet<>();
|
||||
Set<IBlockState> blockStates = new HashSet<>();
|
||||
Set<Integer> stacks = new HashSet<>();
|
||||
for (BlockOptionalMeta bom : boms) {
|
||||
blocks.add(bom.getBlock());
|
||||
blockStates.addAll(bom.getAllBlockStates());
|
||||
stacks.addAll(bom.stackHashes());
|
||||
}
|
||||
this.blockSet = ImmutableSet.copyOf(blocks);
|
||||
this.blockStateSet = ImmutableSet.copyOf(blockStates);
|
||||
this.stackHashes = ImmutableSet.copyOf(stacks);
|
||||
}
|
||||
|
||||
public BlockOptionalMetaLookup(Block... blocks) {
|
||||
this.boms = Stream.of(blocks)
|
||||
this(Stream.of(blocks)
|
||||
.map(BlockOptionalMeta::new)
|
||||
.toArray(BlockOptionalMeta[]::new);
|
||||
.toArray(BlockOptionalMeta[]::new));
|
||||
|
||||
}
|
||||
|
||||
public BlockOptionalMetaLookup(List<Block> blocks) {
|
||||
this.boms = blocks.stream()
|
||||
this(blocks.stream()
|
||||
.map(BlockOptionalMeta::new)
|
||||
.toArray(BlockOptionalMeta[]::new);
|
||||
.toArray(BlockOptionalMeta[]::new));
|
||||
}
|
||||
|
||||
public BlockOptionalMetaLookup(String... blocks) {
|
||||
this.boms = Stream.of(blocks)
|
||||
this(Stream.of(blocks)
|
||||
.map(BlockOptionalMeta::new)
|
||||
.toArray(BlockOptionalMeta[]::new);
|
||||
.toArray(BlockOptionalMeta[]::new));
|
||||
}
|
||||
|
||||
public boolean has(Block block) {
|
||||
for (BlockOptionalMeta bom : boms) {
|
||||
if (bom.getBlock() == block) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return blockSet.contains(block);
|
||||
}
|
||||
|
||||
public boolean has(IBlockState state) {
|
||||
for (BlockOptionalMeta bom : boms) {
|
||||
if (bom.matches(state)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
return blockStateSet.contains(state);
|
||||
}
|
||||
|
||||
public boolean has(ItemStack stack) {
|
||||
for (BlockOptionalMeta bom : boms) {
|
||||
if (bom.matches(stack)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
int hash = ((IItemStack) (Object) stack).getBaritoneHash();
|
||||
return stackHashes.contains(hash)
|
||||
|| stackHashes.contains(hash - stack.getItemDamage());
|
||||
}
|
||||
|
||||
public List<BlockOptionalMeta> blocks() {
|
||||
|
||||
27
src/api/java/baritone/api/utils/BooleanBinaryOperator.java
Normal file
27
src/api/java/baritone/api/utils/BooleanBinaryOperator.java
Normal file
@@ -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 baritone.api.utils;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
@FunctionalInterface
|
||||
public interface BooleanBinaryOperator {
|
||||
|
||||
boolean applyAsBoolean(boolean a, boolean b);
|
||||
}
|
||||
38
src/api/java/baritone/api/utils/BooleanBinaryOperators.java
Normal file
38
src/api/java/baritone/api/utils/BooleanBinaryOperators.java
Normal file
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* 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;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public enum BooleanBinaryOperators implements BooleanBinaryOperator {
|
||||
OR((a, b) -> a || b),
|
||||
AND((a, b) -> a && b),
|
||||
XOR((a, b) -> a ^ b);
|
||||
|
||||
private final BooleanBinaryOperator op;
|
||||
|
||||
BooleanBinaryOperators(BooleanBinaryOperator op) {
|
||||
this.op = op;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean applyAsBoolean(boolean a, boolean b) {
|
||||
return this.op.applyAsBoolean(a, b);
|
||||
}
|
||||
}
|
||||
@@ -42,8 +42,10 @@ public interface Helper {
|
||||
Helper HELPER = new Helper() {};
|
||||
|
||||
/**
|
||||
* Instance of the game
|
||||
* The main game instance returned by {@link Minecraft#getMinecraft()}.
|
||||
* Deprecated since {@link IPlayerContext#minecraft()} should be used instead (In the majority of cases).
|
||||
*/
|
||||
@Deprecated
|
||||
Minecraft mc = Minecraft.getMinecraft();
|
||||
|
||||
static ITextComponent getPrefix() {
|
||||
@@ -70,7 +72,7 @@ public interface Helper {
|
||||
* @param message The message to display in the popup
|
||||
*/
|
||||
default void logToast(ITextComponent title, ITextComponent message) {
|
||||
mc.addScheduledTask(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
|
||||
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -131,7 +133,7 @@ public interface Helper {
|
||||
* @param error Whether to log as an error
|
||||
*/
|
||||
default void logNotificationDirect(String message, boolean error) {
|
||||
mc.addScheduledTask(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
|
||||
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -168,7 +170,7 @@ public interface Helper {
|
||||
if (logAsToast) {
|
||||
logToast(getPrefix(), component);
|
||||
} else {
|
||||
mc.addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
|
||||
Minecraft.getMinecraft().addScheduledTask(() -> BaritoneAPI.getSettings().logger.value.accept(component));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
47
src/api/java/baritone/api/utils/IBaritoneInventory.java
Normal file
47
src/api/java/baritone/api/utils/IBaritoneInventory.java
Normal file
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.item.ItemStack;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public interface IBaritoneInventory {
|
||||
|
||||
/**
|
||||
* Returns a stream containing all the player's regular inventory slots and items. The elements of the stream are in
|
||||
* the order of hotbar, offhand, then main inventory, for a total of 37 slots. This explicitly does not contain the
|
||||
* armor slots or crafting grid, which may otherwise be accessed with {@link #armorSlots()} and/or {@link #itemAt}.
|
||||
*
|
||||
* @return All the player's inventory slots and items
|
||||
*/
|
||||
Stream<Pair<InventorySlot, ItemStack>> allSlots();
|
||||
|
||||
Stream<Pair<InventorySlot, ItemStack>> hotbarSlots();
|
||||
|
||||
Stream<Pair<InventorySlot, ItemStack>> inventorySlots();
|
||||
|
||||
Pair<InventorySlot, ItemStack> offhand();
|
||||
|
||||
Stream<Pair<InventorySlot, ItemStack>> armorSlots();
|
||||
|
||||
ItemStack itemAt(InventorySlot slot);
|
||||
}
|
||||
@@ -17,8 +17,10 @@
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import net.minecraft.block.BlockSlab;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
@@ -33,10 +35,16 @@ import java.util.Optional;
|
||||
*/
|
||||
public interface IPlayerContext {
|
||||
|
||||
IBaritone baritone();
|
||||
|
||||
Minecraft minecraft();
|
||||
|
||||
EntityPlayerSP player();
|
||||
|
||||
IPlayerController playerController();
|
||||
|
||||
IBaritoneInventory inventory();
|
||||
|
||||
World world();
|
||||
|
||||
IWorldData worldData();
|
||||
@@ -72,6 +80,8 @@ public interface IPlayerContext {
|
||||
return new Vec3d(player().posX, player().posY + player().getEyeHeight(), player().posZ);
|
||||
}
|
||||
|
||||
BetterBlockPos viewerPos();
|
||||
|
||||
default Rotation playerRotations() {
|
||||
return new Rotation(player().rotationYaw, player().rotationPitch);
|
||||
}
|
||||
|
||||
129
src/api/java/baritone/api/utils/InventorySlot.java
Normal file
129
src/api/java/baritone/api/utils/InventorySlot.java
Normal file
@@ -0,0 +1,129 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import java.util.function.ObjIntConsumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class InventorySlot {
|
||||
|
||||
/**
|
||||
* Maps directly to the slot ids of the player's inventory container.
|
||||
* <table width="100%">
|
||||
* <tr>
|
||||
* <th width="10%">Index</th>
|
||||
* <th>Description</th>
|
||||
* </tr>
|
||||
* <tr><td>0</td><td>crafting output</td></tr>
|
||||
* <tr><td>1-4</td><td>crafting grid</td></tr>
|
||||
* <tr><td>5-8</td><td>armor</td></tr>
|
||||
* <tr><td>9-35</td><td>inventory (index 9-35)</td></tr>
|
||||
* <tr><td>36-44</td><td>hotbar (index 0-8)</td></tr>
|
||||
* <tr><td>45</td><td>off-hand</td></tr>
|
||||
* </table>
|
||||
*/
|
||||
private static final InventorySlot[] SLOTS = new InventorySlot[46];
|
||||
|
||||
static {
|
||||
final ObjIntConsumer<Type> populate = new ObjIntConsumer<Type>() {
|
||||
private int index;
|
||||
|
||||
@Override
|
||||
public void accept(Type type, int count) {
|
||||
for (int i = 0; i < count; i++) {
|
||||
SLOTS[this.index] = new InventorySlot(this.index, type);
|
||||
this.index++;
|
||||
}
|
||||
}
|
||||
};
|
||||
populate.accept(Type.CRAFTING_OUTPUT, 1);
|
||||
populate.accept(Type.CRAFTING_GRID, 4);
|
||||
populate.accept(Type.ARMOR, 4);
|
||||
populate.accept(Type.INVENTORY, 27);
|
||||
populate.accept(Type.HOTBAR, 9);
|
||||
populate.accept(Type.OFFHAND, 1);
|
||||
}
|
||||
|
||||
private final int slotId;
|
||||
private final Type type;
|
||||
|
||||
private InventorySlot(int slotId, Type type) {
|
||||
this.slotId = slotId;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The ID of this slot, as used by {@code ContainerPlayer}
|
||||
*/
|
||||
public int getSlotId() {
|
||||
return this.slotId;
|
||||
}
|
||||
|
||||
public Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the index of this slot in {@code mainInventory}. If this slot does not correspond to an index into
|
||||
* {@code mainInventory}, then an {@link IllegalArgumentException} is thrown.
|
||||
*
|
||||
* @return The index of this slot in the player's {@code mainInventory}
|
||||
* @throws IllegalArgumentException if type is not {@link Type#HOTBAR} or {@link Type#INVENTORY}
|
||||
*/
|
||||
public int getInventoryIndex() {
|
||||
switch (this.getType()) {
|
||||
case HOTBAR:
|
||||
return this.slotId - 36;
|
||||
case INVENTORY:
|
||||
return this.slotId;
|
||||
default:
|
||||
throw new IllegalStateException("Slot type must be either HOTBAR or INVENTORY");
|
||||
}
|
||||
}
|
||||
|
||||
public static InventorySlot inventory(final int index) {
|
||||
if (index >= 0 && index < 9) {
|
||||
return SLOTS[index + 36]; // HOTBAR
|
||||
} else if (index >= 9 && index < 36) {
|
||||
return SLOTS[index]; // INVENTORY
|
||||
}
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
|
||||
public static InventorySlot armor(final int index) {
|
||||
if (index < 0 || index >= 4) {
|
||||
throw new IllegalArgumentException();
|
||||
}
|
||||
return SLOTS[index + 5];
|
||||
}
|
||||
|
||||
public static InventorySlot offhand() {
|
||||
return SLOTS[45];
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
CRAFTING_OUTPUT,
|
||||
CRAFTING_GRID,
|
||||
ARMOR,
|
||||
INVENTORY,
|
||||
HOTBAR,
|
||||
OFFHAND
|
||||
}
|
||||
}
|
||||
59
src/api/java/baritone/api/utils/Pair.java
Normal file
59
src/api/java/baritone/api/utils/Pair.java
Normal file
@@ -0,0 +1,59 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
*/
|
||||
public final class Pair<A, B> {
|
||||
|
||||
private final A a;
|
||||
private final B b;
|
||||
|
||||
public Pair(A a, B b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
public A first() {
|
||||
return this.a;
|
||||
}
|
||||
|
||||
public B second() {
|
||||
return this.b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (this == o) {
|
||||
return true;
|
||||
}
|
||||
if (o == null || o.getClass() != Pair.class) {
|
||||
return false;
|
||||
}
|
||||
Pair<?, ?> pair = (Pair<?, ?>) o;
|
||||
return Objects.equals(this.a, pair.a) && Objects.equals(this.b, pair.b);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return 31 * Objects.hashCode(this.a) + Objects.hashCode(this.b);
|
||||
}
|
||||
}
|
||||
@@ -26,12 +26,12 @@ public class Rotation {
|
||||
/**
|
||||
* The yaw angle of this Rotation
|
||||
*/
|
||||
private float yaw;
|
||||
private final float yaw;
|
||||
|
||||
/**
|
||||
* The pitch angle of this Rotation
|
||||
*/
|
||||
private float pitch;
|
||||
private final float pitch;
|
||||
|
||||
public Rotation(float yaw, float pitch) {
|
||||
this.yaw = yaw;
|
||||
@@ -110,6 +110,10 @@ public class Rotation {
|
||||
);
|
||||
}
|
||||
|
||||
public Rotation withPitch(float pitch) {
|
||||
return new Rotation(this.yaw, pitch);
|
||||
}
|
||||
|
||||
/**
|
||||
* Is really close to
|
||||
*
|
||||
|
||||
@@ -134,14 +134,14 @@ public final class RotationUtils {
|
||||
* @param ctx Context for the viewing entity
|
||||
* @param pos The target block position
|
||||
* @return The optional rotation
|
||||
* @see #reachable(EntityPlayerSP, BlockPos, double)
|
||||
* @see #reachable(IPlayerContext, BlockPos, double)
|
||||
*/
|
||||
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos) {
|
||||
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
|
||||
return reachable(ctx, pos, false);
|
||||
}
|
||||
|
||||
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, boolean wouldSneak) {
|
||||
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
|
||||
return reachable(ctx, pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -151,18 +151,17 @@ public final class RotationUtils {
|
||||
* side that is reachable. The return type will be {@link Optional#empty()} if the entity is
|
||||
* unable to reach any of the sides of the block.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param ctx Context for the viewing entity
|
||||
* @param pos The target block position
|
||||
* @param blockReachDistance The block reach distance of the entity
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
|
||||
return reachable(entity, pos, blockReachDistance, false);
|
||||
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance) {
|
||||
return reachable(ctx, pos, blockReachDistance, false);
|
||||
}
|
||||
|
||||
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
|
||||
if (baritone.getPlayerContext().isLookingAt(pos)) {
|
||||
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
|
||||
if (BaritoneAPI.getSettings().remainWithExistingLookDirection.value && ctx.isLookingAt(pos)) {
|
||||
/*
|
||||
* why add 0.0001?
|
||||
* to indicate that we actually have a desired pitch
|
||||
@@ -173,10 +172,10 @@ public final class RotationUtils {
|
||||
*
|
||||
* or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level
|
||||
*/
|
||||
Rotation hypothetical = new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F);
|
||||
Rotation hypothetical = ctx.playerRotations().add(new Rotation(0, 0.0001F));
|
||||
if (wouldSneak) {
|
||||
// the concern here is: what if we're looking at it now, but as soon as we start sneaking we no longer are
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, hypothetical, blockReachDistance, true);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), hypothetical, blockReachDistance, true);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(pos)) {
|
||||
return Optional.of(hypothetical); // yes, if we sneaked we would still be looking at the block
|
||||
}
|
||||
@@ -184,19 +183,19 @@ public final class RotationUtils {
|
||||
return Optional.of(hypothetical);
|
||||
}
|
||||
}
|
||||
Optional<Rotation> possibleRotation = reachableCenter(entity, pos, blockReachDistance, wouldSneak);
|
||||
Optional<Rotation> possibleRotation = reachableCenter(ctx, pos, blockReachDistance, wouldSneak);
|
||||
//System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
|
||||
IBlockState state = entity.world.getBlockState(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
|
||||
IBlockState state = ctx.world().getBlockState(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(ctx.world(), pos);
|
||||
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
|
||||
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
|
||||
possibleRotation = reachableOffset(ctx, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
@@ -209,12 +208,55 @@ public final class RotationUtils {
|
||||
* the given offsetted position. The return type will be {@link Optional#empty()} if
|
||||
* the entity is unable to reach the block with the offset applied.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param ctx Context for the viewing entity
|
||||
* @param pos The target block position
|
||||
* @param offsetPos The position of the block with the offset applied.
|
||||
* @param blockReachDistance The block reach distance of the entity
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableOffset(IPlayerContext ctx, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) {
|
||||
Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.player().getPositionEyes(1.0F);
|
||||
Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, ctx.playerRotations());
|
||||
Rotation actualRotation = BaritoneAPI.getProvider().getBaritoneForPlayer(ctx.player()).getLookBehavior().getAimProcessor().peekRotation(rotation);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), actualRotation, blockReachDistance, wouldSneak);
|
||||
//System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
if (ctx.world().getBlockState(pos).getBlock() instanceof BlockFire && result.getBlockPos().equals(pos.down())) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified entity is able to reach the specified block where it is
|
||||
* looking at the direct center of it's hitbox.
|
||||
*
|
||||
* @param ctx Context for the viewing entity
|
||||
* @param pos The target block position
|
||||
* @param blockReachDistance The block reach distance of the entity
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableCenter(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
|
||||
return reachableOffset(ctx, pos, VecUtils.calculateBlockCenter(ctx.world(), pos), blockReachDistance, wouldSneak);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
|
||||
return reachable(entity, pos, blockReachDistance, false);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
|
||||
IPlayerContext ctx = baritone.getPlayerContext();
|
||||
return reachable(ctx, pos, blockReachDistance, wouldSneak);
|
||||
}
|
||||
|
||||
@Deprecated
|
||||
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance, boolean wouldSneak) {
|
||||
Vec3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(entity) : entity.getPositionEyes(1.0F);
|
||||
Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
|
||||
@@ -231,15 +273,7 @@ public final class RotationUtils {
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines if the specified entity is able to reach the specified block where it is
|
||||
* looking at the direct center of it's hitbox.
|
||||
*
|
||||
* @param entity The viewing entity
|
||||
* @param pos The target block position
|
||||
* @param blockReachDistance The block reach distance of the entity
|
||||
* @return The optional rotation
|
||||
*/
|
||||
@Deprecated
|
||||
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
|
||||
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.world, pos), blockReachDistance, wouldSneak);
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package baritone.api.utils;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.Settings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
@@ -44,13 +45,10 @@ import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static net.minecraft.client.Minecraft.getMinecraft;
|
||||
|
||||
public class SettingsUtil {
|
||||
|
||||
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
|
||||
public static final String SETTINGS_DEFAULT_NAME = "settings.txt";
|
||||
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>.+)"); // key and value split by the first space
|
||||
private static final String[] JAVA_ONLY_SETTINGS = {"logger", "notifier", "toaster"};
|
||||
|
||||
private static boolean isComment(String line) {
|
||||
return line.startsWith("#") || line.startsWith("//");
|
||||
@@ -68,12 +66,12 @@ public class SettingsUtil {
|
||||
}
|
||||
}
|
||||
|
||||
public static void readAndApply(Settings settings) {
|
||||
public static void readAndApply(Settings settings, String settingsName) {
|
||||
try {
|
||||
forEachLine(SETTINGS_PATH, line -> {
|
||||
forEachLine(settingsByName(settingsName), line -> {
|
||||
Matcher matcher = SETTING_PATTERN.matcher(line);
|
||||
if (!matcher.matches()) {
|
||||
System.out.println("Invalid syntax in setting file: " + line);
|
||||
Helper.HELPER.logDirect("Invalid syntax in setting file: " + line);
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -82,29 +80,33 @@ public class SettingsUtil {
|
||||
try {
|
||||
parseAndApply(settings, settingName, settingValue);
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Unable to parse line " + line);
|
||||
Helper.HELPER.logDirect("Unable to parse line " + line);
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (NoSuchFileException ignored) {
|
||||
System.out.println("Baritone settings file not found, resetting.");
|
||||
Helper.HELPER.logDirect("Baritone settings file not found, resetting.");
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
|
||||
Helper.HELPER.logDirect("Exception while reading Baritone settings, some settings may be reset to default values!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public static synchronized void save(Settings settings) {
|
||||
try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) {
|
||||
try (BufferedWriter out = Files.newBufferedWriter(settingsByName(SETTINGS_DEFAULT_NAME))) {
|
||||
for (Settings.Setting setting : modifiedSettings(settings)) {
|
||||
out.write(settingToString(setting) + "\n");
|
||||
}
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Exception thrown while saving Baritone settings!");
|
||||
Helper.HELPER.logDirect("Exception thrown while saving Baritone settings!");
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private static Path settingsByName(String name) {
|
||||
return Minecraft.getMinecraft().gameDir.toPath().resolve("baritone").resolve(name);
|
||||
}
|
||||
|
||||
public static List<Settings.Setting> modifiedSettings(Settings settings) {
|
||||
List<Settings.Setting> modified = new ArrayList<>();
|
||||
for (Settings.Setting setting : settings.allSettings) {
|
||||
@@ -112,7 +114,7 @@ public class SettingsUtil {
|
||||
System.out.println("NULL SETTING?" + setting.getName());
|
||||
continue;
|
||||
}
|
||||
if (javaOnlySetting(setting)) {
|
||||
if (setting.isJavaOnly()) {
|
||||
continue; // NO
|
||||
}
|
||||
if (setting.value == setting.defaultValue) {
|
||||
@@ -166,7 +168,7 @@ public class SettingsUtil {
|
||||
}
|
||||
|
||||
public static String settingToString(Settings.Setting setting) throws IllegalStateException {
|
||||
if (javaOnlySetting(setting)) {
|
||||
if (setting.isJavaOnly()) {
|
||||
return setting.getName();
|
||||
}
|
||||
|
||||
@@ -174,18 +176,14 @@ public class SettingsUtil {
|
||||
}
|
||||
|
||||
/**
|
||||
* This should always be the same as whether the setting can be parsed from or serialized to a string
|
||||
* Deprecated. Use {@link Settings.Setting#isJavaOnly()} instead.
|
||||
*
|
||||
* @param the setting
|
||||
* @param setting The Setting
|
||||
* @return true if the setting can not be set or read by the user
|
||||
*/
|
||||
@Deprecated
|
||||
public static boolean javaOnlySetting(Settings.Setting setting) {
|
||||
for (String name : JAVA_ONLY_SETTINGS) { // no JAVA_ONLY_SETTINGS.contains(...) because that would be case sensitive
|
||||
if (setting.getName().equalsIgnoreCase(name)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return setting.isJavaOnly();
|
||||
}
|
||||
|
||||
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
|
||||
@@ -299,7 +297,7 @@ public class SettingsUtil {
|
||||
Parser keyParser = Parser.getParser(keyType);
|
||||
Parser valueParser = Parser.getParser(valueType);
|
||||
|
||||
return ((Map<?,?>) value).entrySet().stream()
|
||||
return ((Map<?, ?>) value).entrySet().stream()
|
||||
.map(o -> keyParser.toString(context, o.getKey()) + "->" + valueParser.toString(context, o.getValue()))
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.utils.gui;
|
||||
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.toasts.GuiToast;
|
||||
import net.minecraft.client.gui.toasts.IToast;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
@@ -73,6 +74,6 @@ public class BaritoneToast implements IToast {
|
||||
}
|
||||
|
||||
public static void addOrUpdate(ITextComponent title, ITextComponent subtitle) {
|
||||
addOrUpdate(net.minecraft.client.Minecraft.getMinecraft().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
|
||||
addOrUpdate(Minecraft.getMinecraft().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,4 +64,14 @@ public abstract class MixinBitArray implements IBitArray {
|
||||
|
||||
return out;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaxEntryValue() {
|
||||
return maxEntryValue;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getBitsPerEntry() {
|
||||
return bitsPerEntry;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -35,6 +35,16 @@ public abstract class MixinBlockStateContainer implements IBlockStateContainer {
|
||||
@Shadow
|
||||
protected IBlockStatePalette palette;
|
||||
|
||||
@Override
|
||||
public IBlockStatePalette getPalette() {
|
||||
return palette;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BitArray getStorage() {
|
||||
return storage;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBlockState getAtPalette(int index) {
|
||||
return palette.getBlockState(index);
|
||||
|
||||
@@ -25,11 +25,14 @@ import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.world.World;
|
||||
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.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
|
||||
|
||||
/**
|
||||
@@ -42,11 +45,14 @@ public abstract class MixinEntityLivingBase extends Entity {
|
||||
/**
|
||||
* Event called to override the movement direction when jumping
|
||||
*/
|
||||
@Unique
|
||||
private RotationMoveEvent jumpRotationEvent;
|
||||
|
||||
public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) {
|
||||
@Unique
|
||||
private RotationMoveEvent elytraRotationEvent;
|
||||
|
||||
public MixinEntityLivingBase(World worldIn) {
|
||||
super(worldIn);
|
||||
this.jumpRotationEvent = jumpRotationEvent;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -54,14 +60,10 @@ public abstract class MixinEntityLivingBase extends Entity {
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preMoveRelative(CallbackInfo ci) {
|
||||
// noinspection ConstantConditions
|
||||
if (EntityPlayerSP.class.isInstance(this)) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
|
||||
if (baritone != null) {
|
||||
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
|
||||
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
|
||||
}
|
||||
}
|
||||
this.getBaritone().ifPresent(baritone -> {
|
||||
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw, this.rotationPitch);
|
||||
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
|
||||
});
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
@@ -79,6 +81,38 @@ public abstract class MixinEntityLivingBase extends Entity {
|
||||
return self.rotationYaw;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "travel",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/entity/EntityLivingBase.getLookVec()Lnet/minecraft/util/math/Vec3d;"
|
||||
)
|
||||
)
|
||||
private void onPreElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) {
|
||||
this.getBaritone().ifPresent(baritone -> {
|
||||
this.elytraRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
|
||||
baritone.getGameEventHandler().onPlayerRotationMove(this.elytraRotationEvent);
|
||||
this.rotationYaw = this.elytraRotationEvent.getYaw();
|
||||
this.rotationPitch = this.elytraRotationEvent.getPitch();
|
||||
});
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "travel",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/entity/EntityLivingBase.move(Lnet/minecraft/entity/MoverType;DDD)V",
|
||||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void onPostElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) {
|
||||
if (this.elytraRotationEvent != null) {
|
||||
this.rotationYaw = this.elytraRotationEvent.getOriginal().getYaw();
|
||||
this.rotationPitch = this.elytraRotationEvent.getOriginal().getPitch();
|
||||
this.elytraRotationEvent = null;
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "travel",
|
||||
at = @At(
|
||||
@@ -86,17 +120,32 @@ public abstract class MixinEntityLivingBase extends Entity {
|
||||
target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
|
||||
)
|
||||
)
|
||||
private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
|
||||
// noinspection ConstantConditions
|
||||
if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) {
|
||||
private void onMoveRelative(EntityLivingBase self, float strafe, float up, float forward, float friction) {
|
||||
Optional<IBaritone> baritone = this.getBaritone();
|
||||
if (!baritone.isPresent()) {
|
||||
moveRelative(strafe, up, forward, friction);
|
||||
return;
|
||||
}
|
||||
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
|
||||
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
|
||||
float originalYaw = this.rotationYaw;
|
||||
this.rotationYaw = motionUpdateRotationEvent.getYaw();
|
||||
|
||||
RotationMoveEvent event = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
|
||||
baritone.get().getGameEventHandler().onPlayerRotationMove(event);
|
||||
|
||||
this.rotationYaw = event.getYaw();
|
||||
this.rotationPitch = event.getPitch();
|
||||
|
||||
this.moveRelative(strafe, up, forward, friction);
|
||||
this.rotationYaw = originalYaw;
|
||||
|
||||
this.rotationYaw = event.getOriginal().getYaw();
|
||||
this.rotationPitch = event.getOriginal().getPitch();
|
||||
}
|
||||
|
||||
@Unique
|
||||
private Optional<IBaritone> getBaritone() {
|
||||
// noinspection ConstantConditions
|
||||
if (EntityPlayerSP.class.isInstance(this)) {
|
||||
return Optional.ofNullable(BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this));
|
||||
} else {
|
||||
return Optional.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,9 +61,8 @@ public class MixinEntityPlayerSP {
|
||||
method = "onUpdate",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.isRiding()Z",
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
target = "net/minecraft/client/entity/AbstractClientPlayer.onUpdate()V",
|
||||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void onPreUpdate(CallbackInfo ci) {
|
||||
@@ -73,22 +72,6 @@ public class MixinEntityPlayerSP {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onUpdate",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
|
||||
shift = At.Shift.BY,
|
||||
by = 2
|
||||
)
|
||||
)
|
||||
private void onPostUpdate(CallbackInfo ci) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
|
||||
if (baritone != null) {
|
||||
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
|
||||
}
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "onLivingUpdate",
|
||||
at = @At(
|
||||
|
||||
@@ -25,7 +25,8 @@ import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
@Mixin(ItemTool.class)
|
||||
public class MixinItemTool implements IItemTool {
|
||||
@Shadow protected Item.ToolMaterial toolMaterial;
|
||||
@Shadow
|
||||
protected Item.ToolMaterial toolMaterial;
|
||||
|
||||
@Override
|
||||
public int getHarvestLevel() {
|
||||
|
||||
@@ -20,6 +20,7 @@ package baritone.launch.mixins;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.WorldEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
@@ -84,7 +85,21 @@ public class MixinMinecraft {
|
||||
|
||||
baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/multiplayer/WorldClient.updateEntities()V",
|
||||
shift = At.Shift.AFTER
|
||||
)
|
||||
)
|
||||
private void postUpdateEntities(CallbackInfo ci) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(this.player);
|
||||
if (baritone != null) {
|
||||
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
||||
@@ -0,0 +1,35 @@
|
||||
/*
|
||||
* 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.utils.accessor.INBTTagLongArray;
|
||||
import net.minecraft.nbt.NBTTagLongArray;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.gen.Accessor;
|
||||
|
||||
/**
|
||||
* @author rycbar
|
||||
* @since 26.09.2022
|
||||
*/
|
||||
@Mixin(NBTTagLongArray.class)
|
||||
public abstract class MixinNBTTagLongArray implements INBTTagLongArray {
|
||||
|
||||
@Accessor("data")
|
||||
@Override
|
||||
public abstract long[] getLongArray();
|
||||
}
|
||||
@@ -23,6 +23,7 @@
|
||||
"MixinItemStack",
|
||||
"MixinItemTool",
|
||||
"MixinMinecraft",
|
||||
"MixinNBTTagLongArray",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinPlayerControllerMP",
|
||||
|
||||
@@ -20,8 +20,9 @@ package baritone;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.behavior.IBehavior;
|
||||
import baritone.api.event.listener.IEventBus;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.behavior.*;
|
||||
import baritone.cache.WorldProvider;
|
||||
@@ -33,16 +34,17 @@ import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.GuiClick;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.PathingControlManager;
|
||||
import baritone.utils.player.PrimaryPlayerContext;
|
||||
import baritone.utils.player.BaritonePlayerContext;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.concurrent.Executor;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -50,87 +52,101 @@ import java.util.concurrent.TimeUnit;
|
||||
*/
|
||||
public class Baritone implements IBaritone {
|
||||
|
||||
private static ThreadPoolExecutor threadPool;
|
||||
private static File dir;
|
||||
private static final ThreadPoolExecutor threadPool;
|
||||
|
||||
static {
|
||||
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
|
||||
dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
}
|
||||
|
||||
private GameEventHandler gameEventHandler;
|
||||
private final Minecraft mc;
|
||||
private final Path directory;
|
||||
|
||||
private PathingBehavior pathingBehavior;
|
||||
private LookBehavior lookBehavior;
|
||||
private InventoryBehavior inventoryBehavior;
|
||||
private WaypointBehavior waypointBehavior;
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
private final GameEventHandler gameEventHandler;
|
||||
|
||||
private FollowProcess followProcess;
|
||||
private MineProcess mineProcess;
|
||||
private GetToBlockProcess getToBlockProcess;
|
||||
private CustomGoalProcess customGoalProcess;
|
||||
private BuilderProcess builderProcess;
|
||||
private ExploreProcess exploreProcess;
|
||||
private BackfillProcess backfillProcess;
|
||||
private FarmProcess farmProcess;
|
||||
private final PathingBehavior pathingBehavior;
|
||||
private final LookBehavior lookBehavior;
|
||||
private final InventoryBehavior inventoryBehavior;
|
||||
private final InputOverrideHandler inputOverrideHandler;
|
||||
|
||||
private PathingControlManager pathingControlManager;
|
||||
private SelectionManager selectionManager;
|
||||
private CommandManager commandManager;
|
||||
private final FollowProcess followProcess;
|
||||
private final MineProcess mineProcess;
|
||||
private final GetToBlockProcess getToBlockProcess;
|
||||
private final CustomGoalProcess customGoalProcess;
|
||||
private final BuilderProcess builderProcess;
|
||||
private final ExploreProcess exploreProcess;
|
||||
private final FarmProcess farmProcess;
|
||||
private final InventoryPauserProcess inventoryPauserProcess;
|
||||
|
||||
private IPlayerContext playerContext;
|
||||
private WorldProvider worldProvider;
|
||||
private final PathingControlManager pathingControlManager;
|
||||
private final SelectionManager selectionManager;
|
||||
private final CommandManager commandManager;
|
||||
|
||||
private final IPlayerContext playerContext;
|
||||
private final WorldProvider worldProvider;
|
||||
|
||||
public BlockStateInterface bsi;
|
||||
|
||||
Baritone() {
|
||||
Baritone(Minecraft mc) {
|
||||
this.mc = mc;
|
||||
this.gameEventHandler = new GameEventHandler(this);
|
||||
|
||||
this.directory = mc.gameDir.toPath().resolve("baritone");
|
||||
if (!Files.exists(this.directory)) {
|
||||
try {
|
||||
Files.createDirectories(this.directory);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
|
||||
this.playerContext = PrimaryPlayerContext.INSTANCE;
|
||||
this.playerContext = new BaritonePlayerContext(this, mc);
|
||||
|
||||
{
|
||||
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
|
||||
pathingBehavior = new PathingBehavior(this);
|
||||
lookBehavior = new LookBehavior(this);
|
||||
inventoryBehavior = new InventoryBehavior(this);
|
||||
inputOverrideHandler = new InputOverrideHandler(this);
|
||||
waypointBehavior = new WaypointBehavior(this);
|
||||
this.lookBehavior = this.registerBehavior(LookBehavior::new);
|
||||
this.pathingBehavior = this.registerBehavior(PathingBehavior::new);
|
||||
this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new);
|
||||
this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new);
|
||||
this.registerBehavior(WaypointBehavior::new);
|
||||
}
|
||||
|
||||
this.pathingControlManager = new PathingControlManager(this);
|
||||
{
|
||||
this.pathingControlManager.registerProcess(followProcess = new FollowProcess(this));
|
||||
this.pathingControlManager.registerProcess(mineProcess = new MineProcess(this));
|
||||
this.pathingControlManager.registerProcess(customGoalProcess = new CustomGoalProcess(this)); // very high iq
|
||||
this.pathingControlManager.registerProcess(getToBlockProcess = new GetToBlockProcess(this));
|
||||
this.pathingControlManager.registerProcess(builderProcess = new BuilderProcess(this));
|
||||
this.pathingControlManager.registerProcess(exploreProcess = new ExploreProcess(this));
|
||||
this.pathingControlManager.registerProcess(backfillProcess = new BackfillProcess(this));
|
||||
this.pathingControlManager.registerProcess(farmProcess = new FarmProcess(this));
|
||||
this.followProcess = this.registerProcess(FollowProcess::new);
|
||||
this.mineProcess = this.registerProcess(MineProcess::new);
|
||||
this.customGoalProcess = this.registerProcess(CustomGoalProcess::new); // very high iq
|
||||
this.getToBlockProcess = this.registerProcess(GetToBlockProcess::new);
|
||||
this.builderProcess = this.registerProcess(BuilderProcess::new);
|
||||
this.exploreProcess = this.registerProcess(ExploreProcess::new);
|
||||
this.farmProcess = this.registerProcess(FarmProcess::new);
|
||||
this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new);
|
||||
this.registerProcess(BackfillProcess::new);
|
||||
}
|
||||
|
||||
this.worldProvider = new WorldProvider();
|
||||
this.worldProvider = new WorldProvider(this);
|
||||
this.selectionManager = new SelectionManager(this);
|
||||
this.commandManager = new CommandManager(this);
|
||||
}
|
||||
|
||||
public void registerBehavior(IBehavior behavior) {
|
||||
this.gameEventHandler.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
public <T extends IBehavior> T registerBehavior(Function<Baritone, T> constructor) {
|
||||
final T behavior = constructor.apply(this);
|
||||
this.registerBehavior(behavior);
|
||||
return behavior;
|
||||
}
|
||||
|
||||
public <T extends IBaritoneProcess> T registerProcess(Function<Baritone, T> constructor) {
|
||||
final T behavior = constructor.apply(this);
|
||||
this.pathingControlManager.registerProcess(behavior);
|
||||
return behavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingControlManager getPathingControlManager() {
|
||||
return this.pathingControlManager;
|
||||
}
|
||||
|
||||
public void registerBehavior(Behavior behavior) {
|
||||
this.gameEventHandler.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputOverrideHandler getInputOverrideHandler() {
|
||||
return this.inputOverrideHandler;
|
||||
@@ -170,6 +186,7 @@ public class Baritone implements IBaritone {
|
||||
return this.lookBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ExploreProcess getExploreProcess() {
|
||||
return this.exploreProcess;
|
||||
}
|
||||
@@ -179,10 +196,15 @@ public class Baritone implements IBaritone {
|
||||
return this.mineProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FarmProcess getFarmProcess() {
|
||||
return this.farmProcess;
|
||||
}
|
||||
|
||||
public InventoryPauserProcess getInventoryPauserProcess() {
|
||||
return this.inventoryPauserProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingBehavior getPathingBehavior() {
|
||||
return this.pathingBehavior;
|
||||
@@ -213,19 +235,19 @@ public class Baritone implements IBaritone {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
Helper.mc.addScheduledTask(() -> Helper.mc.displayGuiScreen(new GuiClick()));
|
||||
mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiClick()));
|
||||
} catch (Exception ignored) {}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public Path getDirectory() {
|
||||
return this.directory;
|
||||
}
|
||||
|
||||
public static Settings settings() {
|
||||
return BaritoneAPI.getSettings();
|
||||
}
|
||||
|
||||
public static File getDir() {
|
||||
return dir;
|
||||
}
|
||||
|
||||
public static Executor getExecutor() {
|
||||
return threadPool;
|
||||
}
|
||||
|
||||
@@ -22,13 +22,15 @@ import baritone.api.IBaritoneProvider;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.command.ICommandSystem;
|
||||
import baritone.api.schematic.ISchematicSystem;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.cache.FasterWorldScanner;
|
||||
import baritone.command.CommandSystem;
|
||||
import baritone.command.ExampleBaritoneControl;
|
||||
import baritone.utils.schematic.SchematicSystem;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -36,30 +38,45 @@ import java.util.List;
|
||||
*/
|
||||
public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
private final Baritone primary;
|
||||
private final List<IBaritone> all;
|
||||
private final List<IBaritone> allView;
|
||||
|
||||
{
|
||||
this.primary = new Baritone();
|
||||
this.all = Collections.singletonList(this.primary);
|
||||
public BaritoneProvider() {
|
||||
this.all = new CopyOnWriteArrayList<>();
|
||||
this.allView = Collections.unmodifiableList(this.all);
|
||||
|
||||
// Setup chat control, just for the primary instance
|
||||
new ExampleBaritoneControl(this.primary);
|
||||
final Baritone primary = (Baritone) this.createBaritone(Minecraft.getMinecraft());
|
||||
primary.registerBehavior(ExampleBaritoneControl::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IBaritone getPrimaryBaritone() {
|
||||
return primary;
|
||||
return this.all.get(0);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<IBaritone> getAllBaritones() {
|
||||
return all;
|
||||
return this.allView;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized IBaritone createBaritone(Minecraft minecraft) {
|
||||
IBaritone baritone = this.getBaritoneForMinecraft(minecraft);
|
||||
if (baritone == null) {
|
||||
this.all.add(baritone = new Baritone(minecraft));
|
||||
}
|
||||
return baritone;
|
||||
}
|
||||
|
||||
@Override
|
||||
public synchronized boolean destroyBaritone(IBaritone baritone) {
|
||||
return baritone != this.getPrimaryBaritone() && this.all.remove(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IWorldScanner getWorldScanner() {
|
||||
return WorldScanner.INSTANCE;
|
||||
return FasterWorldScanner.INSTANCE;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
36
src/main/java/baritone/PerformanceCritical.java
Normal file
36
src/main/java/baritone/PerformanceCritical.java
Normal file
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone;
|
||||
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
|
||||
import java.lang.annotation.ElementType;
|
||||
import java.lang.annotation.Retention;
|
||||
import java.lang.annotation.RetentionPolicy;
|
||||
import java.lang.annotation.Target;
|
||||
|
||||
/**
|
||||
* Annotation that should be used on methods which are performance critical (i.e. called millions of times per second
|
||||
* by the pathfinder) and should be modified with care. Particularly useful for methods for which this fact is not
|
||||
* obvious, such as those which don't have a {@link CalculationContext} parameter.
|
||||
*
|
||||
* @author Brady
|
||||
*/
|
||||
@Target(ElementType.METHOD)
|
||||
@Retention(RetentionPolicy.SOURCE)
|
||||
public @interface PerformanceCritical {}
|
||||
@@ -35,6 +35,5 @@ public class Behavior implements IBehavior {
|
||||
protected Behavior(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
this.ctx = baritone.getPlayerContext();
|
||||
baritone.registerBehavior(this);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,24 +18,31 @@
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.InventorySlot;
|
||||
import baritone.api.utils.Pair;
|
||||
import baritone.utils.ItemInteractionHelper;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.ClickType;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.OptionalInt;
|
||||
import java.util.Random;
|
||||
import java.util.function.IntPredicate;
|
||||
import java.util.function.Predicate;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public final class InventoryBehavior extends Behavior {
|
||||
public final class InventoryBehavior extends Behavior implements Helper {
|
||||
|
||||
private int ticksSinceLastInventoryMove;
|
||||
private int[] lastTickRequestedMove; // not everything asks every tick, so remember the request while coming to a halt
|
||||
|
||||
public InventoryBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
@@ -43,33 +50,61 @@ public final class InventoryBehavior extends Behavior {
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (!Baritone.settings().allowInventory.value) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
return;
|
||||
}
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
ticksSinceLastInventoryMove++;
|
||||
|
||||
// TODO: Move these checks into "requestSwapWithHotBar" or whatever supersedes it
|
||||
if (!this.canAccessInventory()) {
|
||||
return;
|
||||
}
|
||||
if (ctx.player().openContainer != ctx.player().inventoryContainer) {
|
||||
// we have a crafting table or a chest or something open
|
||||
return;
|
||||
}
|
||||
if (firstValidThrowaway() >= 9) { // aka there are none on the hotbar, but there are some in main inventory
|
||||
swapWithHotBar(firstValidThrowaway(), 8);
|
||||
|
||||
if (Baritone.settings().allowHotbarManagement.value && baritone.getPathingBehavior().isPathing()) {
|
||||
this.setupHotbar();
|
||||
}
|
||||
int pick = bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
|
||||
if (pick >= 9) {
|
||||
swapWithHotBar(pick, 0);
|
||||
|
||||
if (lastTickRequestedMove != null) {
|
||||
logDebug("Remembering to move " + lastTickRequestedMove[0] + " " + lastTickRequestedMove[1] + " from a previous tick");
|
||||
requestSwapWithHotBar(lastTickRequestedMove[0], lastTickRequestedMove[1]);
|
||||
}
|
||||
}
|
||||
|
||||
public void attemptToPutOnHotbar(int inMainInvy, Predicate<Integer> disallowedHotbar) {
|
||||
private void setupHotbar() {
|
||||
// TODO: Some way of indicating which slots are currently reserved by this setting
|
||||
|
||||
final InventorySlot throwaway = this.findSlotMatching(this::isThrowawayItem);
|
||||
if (throwaway != null && throwaway.getType() == InventorySlot.Type.INVENTORY) {
|
||||
// aka there are none on the hotbar, but there are some in main inventory
|
||||
this.requestSwapWithHotBar(throwaway.getInventoryIndex(), 8);
|
||||
return;
|
||||
}
|
||||
|
||||
final InventorySlot pick = this.bestToolAgainst(Blocks.STONE, ItemPickaxe.class);
|
||||
if (pick != null && pick.getType() == InventorySlot.Type.INVENTORY) {
|
||||
this.requestSwapWithHotBar(pick.getInventoryIndex(), 0);
|
||||
}
|
||||
}
|
||||
|
||||
private InventorySlot bestToolAgainst(final Block against, final Class<? extends ItemTool> cla$$) {
|
||||
return new ToolSet(ctx).getBestSlot(against.getDefaultState(), Baritone.settings().preferSilkTouch.value, stack -> cla$$.isInstance(stack.getItem()));
|
||||
}
|
||||
|
||||
public boolean attemptToPutOnHotbar(int inMainInvy, IntPredicate disallowedHotbar) {
|
||||
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
|
||||
if (destination.isPresent()) {
|
||||
swapWithHotBar(inMainInvy, destination.getAsInt());
|
||||
if (!requestSwapWithHotBar(inMainInvy, destination.getAsInt())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public OptionalInt getTempHotbarSlot(Predicate<Integer> disallowedHotbar) {
|
||||
public OptionalInt getTempHotbarSlot(IntPredicate disallowedHotbar) {
|
||||
// we're using 0 and 8 for pickaxe and throwaway
|
||||
ArrayList<Integer> candidates = new ArrayList<>();
|
||||
for (int i = 1; i < 8; i++) {
|
||||
@@ -90,118 +125,188 @@ public final class InventoryBehavior extends Behavior {
|
||||
return OptionalInt.of(candidates.get(new Random().nextInt(candidates.size())));
|
||||
}
|
||||
|
||||
private void swapWithHotBar(int inInventory, int inHotbar) {
|
||||
private boolean requestSwapWithHotBar(int inInventory, int inHotbar) {
|
||||
lastTickRequestedMove = new int[]{inInventory, inHotbar};
|
||||
if (ticksSinceLastInventoryMove < Baritone.settings().ticksBetweenInventoryMoves.value) {
|
||||
logDebug("Inventory move requested but delaying " + ticksSinceLastInventoryMove + " " + Baritone.settings().ticksBetweenInventoryMoves.value);
|
||||
return false;
|
||||
}
|
||||
if (Baritone.settings().inventoryMoveOnlyIfStationary.value && !baritone.getInventoryPauserProcess().stationaryForInventoryMove()) {
|
||||
logDebug("Inventory move requested but delaying until stationary");
|
||||
return false;
|
||||
}
|
||||
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
|
||||
}
|
||||
|
||||
private int firstValidThrowaway() { // TODO offhand idk
|
||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
||||
for (int i = 0; i < invy.size(); i++) {
|
||||
if (Baritone.settings().acceptableThrowawayItems.value.contains(invy.get(i).getItem())) {
|
||||
return i;
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
|
||||
private int bestToolAgainst(Block against, Class<? extends ItemTool> cla$$) {
|
||||
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
|
||||
int bestInd = -1;
|
||||
double bestSpeed = -1;
|
||||
for (int i = 0; i < invy.size(); i++) {
|
||||
ItemStack stack = invy.get(i);
|
||||
if (stack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (Baritone.settings().itemSaver.value && (stack.getItemDamage() + Baritone.settings().itemSaverThreshold.value) >= stack.getMaxDamage() && stack.getMaxDamage() > 1) {
|
||||
continue;
|
||||
}
|
||||
if (cla$$.isInstance(stack.getItem())) {
|
||||
double speed = ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState()); // takes into account enchants
|
||||
if (speed > bestSpeed) {
|
||||
bestSpeed = speed;
|
||||
bestInd = i;
|
||||
}
|
||||
}
|
||||
}
|
||||
return bestInd;
|
||||
ticksSinceLastInventoryMove = 0;
|
||||
lastTickRequestedMove = null;
|
||||
return true;
|
||||
}
|
||||
|
||||
public boolean hasGenericThrowaway() {
|
||||
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
|
||||
if (throwaway(false, stack -> item.equals(stack.getItem()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
return this.canSelectItem(this::isThrowawayItem);
|
||||
}
|
||||
|
||||
public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) {
|
||||
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
|
||||
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) {
|
||||
return true; // gotem
|
||||
final Predicate<Predicate<? super ItemStack>> op = select ? this::trySelectItem : this::canSelectItem;
|
||||
|
||||
final IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z, baritone.bsi.get0(x, y, z));
|
||||
if (maybe != null) {
|
||||
return op.test(stack -> {
|
||||
if (!(stack.getItem() instanceof ItemBlock)) {
|
||||
return false;
|
||||
}
|
||||
Block block = ((ItemBlock) stack.getItem()).getBlock();
|
||||
return maybe.equals(block.getStateForPlacement(
|
||||
ctx.world(),
|
||||
ctx.playerFeet(),
|
||||
EnumFacing.UP,
|
||||
0.5f, 1.0f, 0.5f,
|
||||
stack.getItem().getMetadata(stack.getMetadata()),
|
||||
ctx.player()
|
||||
));
|
||||
}) || op.test(stack -> {
|
||||
// Since a stack didn't match the desired block state, accept a match of just the block
|
||||
return stack.getItem() instanceof ItemBlock
|
||||
&& ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock());
|
||||
});
|
||||
}
|
||||
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock()))) {
|
||||
return op.test(this::isThrowawayItem);
|
||||
}
|
||||
|
||||
public boolean canSelectItem(Predicate<? super ItemStack> desired) {
|
||||
return this.resolveSelectionStrategy(this.findSlotMatching(desired)) != null;
|
||||
}
|
||||
|
||||
public boolean trySelectItem(Predicate<? super ItemStack> desired) {
|
||||
final SelectionStrategy strategy = this.resolveSelectionStrategy(this.findSlotMatching(desired));
|
||||
if (strategy != null) {
|
||||
strategy.run();
|
||||
// TODO: Consider cases where returning the SelectionType is needed/useful to the caller
|
||||
return true;
|
||||
}
|
||||
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
|
||||
if (throwaway(select, stack -> item.equals(stack.getItem()))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired) {
|
||||
return throwaway(select, desired, Baritone.settings().allowInventory.value);
|
||||
public SelectionStrategy resolveSelectionStrategy(final InventorySlot slot) {
|
||||
if (slot != null) {
|
||||
switch (slot.getType()) {
|
||||
case HOTBAR:
|
||||
return SelectionStrategy.of(SelectionType.IMMEDIATE, () ->
|
||||
ctx.player().inventory.currentItem = slot.getInventoryIndex());
|
||||
case OFFHAND:
|
||||
// TODO: It's probably worth adding a parameter to this method so that the caller can indicate what
|
||||
// the purpose of the item is. For example, attacks are always done using the main hand, so
|
||||
// just switching to a non-interacting hotbar item isn't sufficient.
|
||||
final ItemStack heldItem = ctx.player().inventory.getCurrentItem();
|
||||
|
||||
if (!ItemInteractionHelper.couldInteract(heldItem)) {
|
||||
// Don't need to do anything, the item held in the main hand doesn't have any interaction.
|
||||
return SelectionStrategy.of(SelectionType.IMMEDIATE, () -> {});
|
||||
}
|
||||
|
||||
final InventorySlot hotbar = this.findHotbarMatching(item -> !ItemInteractionHelper.couldInteract(item));
|
||||
if (hotbar != null) {
|
||||
return SelectionStrategy.of(SelectionType.IMMEDIATE, () ->
|
||||
ctx.player().inventory.currentItem = hotbar.getInventoryIndex());
|
||||
}
|
||||
|
||||
// TODO: Swap offhand with an unimportant item
|
||||
break;
|
||||
case INVENTORY:
|
||||
if (this.canAccessInventory()) {
|
||||
return SelectionStrategy.of(SelectionType.ENQUEUED, () -> {
|
||||
// TODO: Determine if hotbar swap can be immediate, and return type accordingly
|
||||
// Also don't only swap into slot 7 that's silly
|
||||
requestSwapWithHotBar(slot.getInventoryIndex(), 7);
|
||||
ctx.player().inventory.currentItem = 7;
|
||||
});
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired, boolean allowInventory) {
|
||||
EntityPlayerSP p = ctx.player();
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
// this usage of settings() is okay because it's only called once during pathing
|
||||
// (while creating the CalculationContext at the very beginning)
|
||||
// and then it's called during execution
|
||||
// since this function is never called during cost calculation, we don't need to migrate
|
||||
// acceptableThrowawayItems to the CalculationContext
|
||||
if (desired.test(item)) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (desired.test(p.inventory.offHandInventory.get(0))) {
|
||||
// main hand takes precedence over off hand
|
||||
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
|
||||
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
|
||||
// so we need to select in the main hand something that doesn't right click
|
||||
// so not a shovel, not a hoe, not a block, etc
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public InventorySlot findBestAccessibleMatching(final Comparator<? super ItemStack> comparator,
|
||||
final Predicate<? super ItemStack> filter) {
|
||||
final Stream<Pair<InventorySlot, ItemStack>> accessible = this.canAccessInventory()
|
||||
? ctx.inventory().allSlots()
|
||||
: Stream.concat(ctx.inventory().hotbarSlots(), Stream.of(ctx.inventory().offhand()));
|
||||
return this.findBestMatching0(accessible, comparator, filter);
|
||||
}
|
||||
|
||||
if (allowInventory) {
|
||||
for (int i = 9; i < 36; i++) {
|
||||
if (desired.test(inv.get(i))) {
|
||||
swapWithHotBar(i, 7);
|
||||
if (select) {
|
||||
p.inventory.currentItem = 7;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
public InventorySlot findSlotMatching(final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestSlotMatching(null, filter);
|
||||
}
|
||||
|
||||
return false;
|
||||
/**
|
||||
* Returns an {@link InventorySlot} that contains a stack matching the given predicate. A comparator may be
|
||||
* specified to prioritize slot selection. The comparator may be {@code null}, in which case, the first slot
|
||||
* matching the predicate is returned. The considered slots are in the order of hotbar, offhand, and finally the
|
||||
* main inventory (if {@link #canAccessInventory()} is {@code true}).
|
||||
*
|
||||
* @param comparator A comparator to find the best element, may be {@code null}
|
||||
* @param filter The predicate to match
|
||||
* @return A matching slot, or {@code null} if none.
|
||||
*/
|
||||
public InventorySlot findBestSlotMatching(final Comparator<? super ItemStack> comparator, final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestMatching0(ctx.inventory().allSlots(), comparator, filter);
|
||||
}
|
||||
|
||||
public InventorySlot findHotbarMatching(final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestHotbarMatching(null, filter);
|
||||
}
|
||||
|
||||
public InventorySlot findBestHotbarMatching(final Comparator<? super ItemStack> comparator, final Predicate<? super ItemStack> filter) {
|
||||
return this.findBestMatching0(ctx.inventory().hotbarSlots(), comparator, filter);
|
||||
}
|
||||
|
||||
private InventorySlot findBestMatching0(final Stream<Pair<InventorySlot, ItemStack>> slots,
|
||||
final Comparator<? super ItemStack> comparator,
|
||||
final Predicate<? super ItemStack> filter) {
|
||||
final Stream<Pair<InventorySlot, ItemStack>> filtered = slots.filter(slot -> filter.test(slot.second()));
|
||||
return (comparator != null
|
||||
? filtered.max((a, b) -> comparator.compare(a.second(), b.second()))
|
||||
: filtered.findFirst()
|
||||
).map(Pair::first).orElse(null);
|
||||
}
|
||||
|
||||
public boolean canAccessInventory() {
|
||||
return Baritone.settings().allowInventory.value;
|
||||
}
|
||||
|
||||
public boolean isThrowawayItem(ItemStack stack) {
|
||||
return this.isThrowawayItem(stack.getItem());
|
||||
}
|
||||
|
||||
public boolean isThrowawayItem(Item item) {
|
||||
return Baritone.settings().acceptableThrowawayItems.value.contains(item);
|
||||
}
|
||||
|
||||
public interface SelectionStrategy extends Runnable {
|
||||
|
||||
@Override
|
||||
void run();
|
||||
|
||||
SelectionType getType();
|
||||
|
||||
static SelectionStrategy of(final SelectionType type, final Runnable runnable) {
|
||||
return new SelectionStrategy() {
|
||||
@Override
|
||||
public void run() {
|
||||
runnable.run();
|
||||
}
|
||||
|
||||
@Override
|
||||
public SelectionType getType() {
|
||||
return type;
|
||||
}
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
public enum SelectionType {
|
||||
IMMEDIATE, ENQUEUED
|
||||
}
|
||||
}
|
||||
|
||||
@@ -20,40 +20,57 @@ package baritone.behavior;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.behavior.ILookBehavior;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RotationMoveEvent;
|
||||
import baritone.api.behavior.look.IAimProcessor;
|
||||
import baritone.api.behavior.look.ITickableAimProcessor;
|
||||
import baritone.api.event.events.*;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.behavior.look.ForkableRandom;
|
||||
import net.minecraft.network.play.client.CPacketPlayer;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
public final class LookBehavior extends Behavior implements ILookBehavior {
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
* The current look target, may be {@code null}.
|
||||
*/
|
||||
private Rotation target;
|
||||
private Target target;
|
||||
|
||||
/**
|
||||
* Whether or not rotations are currently being forced
|
||||
* The rotation known to the server. Returned by {@link #getEffectiveRotation()} for use in {@link IPlayerContext}.
|
||||
*/
|
||||
private boolean force;
|
||||
private Rotation serverRotation;
|
||||
|
||||
/**
|
||||
* The last player yaw angle. Used when free looking
|
||||
* The last player rotation. Used to restore the player's angle when using free look.
|
||||
*
|
||||
* @see Settings#freeLook
|
||||
*/
|
||||
private float lastYaw;
|
||||
private Rotation prevRotation;
|
||||
|
||||
private final AimProcessor processor;
|
||||
|
||||
public LookBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
this.processor = new AimProcessor(baritone.getPlayerContext());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateTarget(Rotation target, boolean force) {
|
||||
this.target = target;
|
||||
this.force = force || !Baritone.settings().freeLook.value;
|
||||
public void updateTarget(Rotation rotation, boolean blockInteract) {
|
||||
this.target = new Target(rotation, blockInteract);
|
||||
}
|
||||
|
||||
@Override
|
||||
public IAimProcessor getAimProcessor() {
|
||||
return this.processor;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.IN) {
|
||||
this.processor.tick();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -61,35 +78,30 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
|
||||
if (this.target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Whether or not we're going to silently set our angles
|
||||
boolean silent = Baritone.settings().antiCheatCompatibility.value && !this.force;
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE: {
|
||||
if (this.force) {
|
||||
ctx.player().rotationYaw = this.target.getYaw();
|
||||
float oldPitch = ctx.player().rotationPitch;
|
||||
float desiredPitch = this.target.getPitch();
|
||||
ctx.player().rotationPitch = desiredPitch;
|
||||
ctx.player().rotationYaw += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
|
||||
ctx.player().rotationPitch += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
|
||||
if (desiredPitch == oldPitch && !Baritone.settings().freeLook.value) {
|
||||
nudgeToLevel();
|
||||
}
|
||||
this.target = null;
|
||||
if (this.target.mode == Target.Mode.NONE) {
|
||||
// Just return for PRE, we still want to set target to null on POST
|
||||
return;
|
||||
}
|
||||
if (silent) {
|
||||
this.lastYaw = ctx.player().rotationYaw;
|
||||
ctx.player().rotationYaw = this.target.getYaw();
|
||||
if (this.target.mode == Target.Mode.SERVER) {
|
||||
this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch);
|
||||
}
|
||||
|
||||
final Rotation actual = this.processor.peekRotation(this.target.rotation);
|
||||
ctx.player().rotationYaw = actual.getYaw();
|
||||
ctx.player().rotationPitch = actual.getPitch();
|
||||
break;
|
||||
}
|
||||
case POST: {
|
||||
if (silent) {
|
||||
ctx.player().rotationYaw = this.lastYaw;
|
||||
this.target = null;
|
||||
// Reset the player's rotations back to their original values
|
||||
if (this.prevRotation != null) {
|
||||
ctx.player().rotationYaw = this.prevRotation.getYaw();
|
||||
ctx.player().rotationPitch = this.prevRotation.getPitch();
|
||||
this.prevRotation = null;
|
||||
}
|
||||
// The target is done being used for this game tick, so it can be invalidated
|
||||
this.target = null;
|
||||
break;
|
||||
}
|
||||
default:
|
||||
@@ -97,34 +109,214 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendPacket(PacketEvent event) {
|
||||
if (!(event.getPacket() instanceof CPacketPlayer)) {
|
||||
return;
|
||||
}
|
||||
|
||||
final CPacketPlayer packet = (CPacketPlayer) event.getPacket();
|
||||
if (packet instanceof CPacketPlayer.Rotation || packet instanceof CPacketPlayer.PositionRotation) {
|
||||
this.serverRotation = new Rotation(packet.getYaw(0.0f), packet.getPitch(0.0f));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldEvent(WorldEvent event) {
|
||||
this.serverRotation = null;
|
||||
this.target = null;
|
||||
}
|
||||
|
||||
public void pig() {
|
||||
if (this.target != null) {
|
||||
ctx.player().rotationYaw = this.target.getYaw();
|
||||
final Rotation actual = this.processor.peekRotation(this.target.rotation);
|
||||
ctx.player().rotationYaw = actual.getYaw();
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Rotation> getEffectiveRotation() {
|
||||
if (Baritone.settings().freeLook.value || Baritone.settings().blockFreeLook.value) {
|
||||
return Optional.ofNullable(this.serverRotation);
|
||||
}
|
||||
// If neither of the freeLook settings are on, just defer to the player's actual rotations
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRotationMove(RotationMoveEvent event) {
|
||||
if (this.target != null) {
|
||||
final Rotation actual = this.processor.peekRotation(this.target.rotation);
|
||||
event.setYaw(actual.getYaw());
|
||||
event.setPitch(actual.getPitch());
|
||||
}
|
||||
}
|
||||
|
||||
event.setYaw(this.target.getYaw());
|
||||
private static final class AimProcessor extends AbstractAimProcessor {
|
||||
|
||||
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
|
||||
// Also the type has to be MOTION_UPDATE because that is called after JUMP
|
||||
if (!Baritone.settings().antiCheatCompatibility.value && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE && !this.force) {
|
||||
this.target = null;
|
||||
public AimProcessor(final IPlayerContext ctx) {
|
||||
super(ctx);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rotation getPrevRotation() {
|
||||
// Implementation will use LookBehavior.serverRotation
|
||||
return ctx.playerRotations();
|
||||
}
|
||||
}
|
||||
|
||||
private static abstract class AbstractAimProcessor implements ITickableAimProcessor {
|
||||
|
||||
protected final IPlayerContext ctx;
|
||||
private final ForkableRandom rand;
|
||||
private double randomYawOffset;
|
||||
private double randomPitchOffset;
|
||||
|
||||
public AbstractAimProcessor(IPlayerContext ctx) {
|
||||
this.ctx = ctx;
|
||||
this.rand = new ForkableRandom();
|
||||
}
|
||||
|
||||
private AbstractAimProcessor(final AbstractAimProcessor source) {
|
||||
this.ctx = source.ctx;
|
||||
this.rand = source.rand.fork();
|
||||
this.randomYawOffset = source.randomYawOffset;
|
||||
this.randomPitchOffset = source.randomPitchOffset;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final Rotation peekRotation(final Rotation rotation) {
|
||||
final Rotation prev = this.getPrevRotation();
|
||||
|
||||
float desiredYaw = rotation.getYaw();
|
||||
float desiredPitch = rotation.getPitch();
|
||||
|
||||
// In other words, the target doesn't care about the pitch, so it used playerRotations().getPitch()
|
||||
// and it's safe to adjust it to a normal level
|
||||
if (desiredPitch == prev.getPitch()) {
|
||||
desiredPitch = nudgeToLevel(desiredPitch);
|
||||
}
|
||||
|
||||
desiredYaw += this.randomYawOffset;
|
||||
desiredPitch += this.randomPitchOffset;
|
||||
|
||||
return new Rotation(
|
||||
this.calculateMouseMove(prev.getYaw(), desiredYaw),
|
||||
this.calculateMouseMove(prev.getPitch(), desiredPitch)
|
||||
).clamp();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void tick() {
|
||||
this.randomYawOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
|
||||
this.randomPitchOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void advance(int ticks) {
|
||||
for (int i = 0; i < ticks; i++) {
|
||||
this.tick();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Rotation nextRotation(final Rotation rotation) {
|
||||
final Rotation actual = this.peekRotation(rotation);
|
||||
this.tick();
|
||||
return actual;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final ITickableAimProcessor fork() {
|
||||
return new AbstractAimProcessor(this) {
|
||||
|
||||
private Rotation prev = AbstractAimProcessor.this.getPrevRotation();
|
||||
|
||||
@Override
|
||||
public Rotation nextRotation(final Rotation rotation) {
|
||||
return (this.prev = super.nextRotation(rotation));
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Rotation getPrevRotation() {
|
||||
return this.prev;
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
protected abstract Rotation getPrevRotation();
|
||||
|
||||
/**
|
||||
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
|
||||
*/
|
||||
private float nudgeToLevel(float pitch) {
|
||||
if (pitch < -20) {
|
||||
return pitch + 1;
|
||||
} else if (pitch > 10) {
|
||||
return pitch - 1;
|
||||
}
|
||||
return pitch;
|
||||
}
|
||||
|
||||
private float calculateMouseMove(float current, float target) {
|
||||
final float delta = target - current;
|
||||
final int deltaPx = angleToMouse(delta);
|
||||
return current + mouseToAngle(deltaPx);
|
||||
}
|
||||
|
||||
private int angleToMouse(float angleDelta) {
|
||||
final float minAngleChange = mouseToAngle(1);
|
||||
return Math.round(angleDelta / minAngleChange);
|
||||
}
|
||||
|
||||
private float mouseToAngle(int mouseDelta) {
|
||||
final float f = ctx.minecraft().gameSettings.mouseSensitivity * 0.6f + 0.2f;
|
||||
return mouseDelta * f * f * f * 8.0f * 0.15f;
|
||||
}
|
||||
}
|
||||
|
||||
private static class Target {
|
||||
|
||||
public final Rotation rotation;
|
||||
public final Mode mode;
|
||||
|
||||
public Target(Rotation rotation, boolean blockInteract) {
|
||||
this.rotation = rotation;
|
||||
this.mode = Mode.resolve(blockInteract);
|
||||
}
|
||||
|
||||
enum Mode {
|
||||
/**
|
||||
* Rotation will be set client-side and is visual to the player
|
||||
*/
|
||||
CLIENT,
|
||||
|
||||
/**
|
||||
* Rotation will be set server-side and is silent to the player
|
||||
*/
|
||||
SERVER,
|
||||
|
||||
/**
|
||||
* Rotation will remain unaffected on both the client and server
|
||||
*/
|
||||
NONE;
|
||||
|
||||
static Mode resolve(boolean blockInteract) {
|
||||
final Settings settings = Baritone.settings();
|
||||
final boolean antiCheat = settings.antiCheatCompatibility.value;
|
||||
final boolean blockFreeLook = settings.blockFreeLook.value;
|
||||
final boolean freeLook = settings.freeLook.value;
|
||||
|
||||
if (!freeLook && !blockFreeLook) return CLIENT;
|
||||
if (!blockFreeLook && blockInteract) return CLIENT;
|
||||
|
||||
// Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player
|
||||
// rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be
|
||||
// whatever the player is mousing over visually. Let's just settle for setting it silently.
|
||||
if (antiCheat || blockInteract) return SERVER;
|
||||
|
||||
// Pathing regularly without antiCheatCompatibility, don't set the player rotation
|
||||
return NONE;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
|
||||
*/
|
||||
private void nudgeToLevel() {
|
||||
if (ctx.player().rotationPitch < -20) {
|
||||
ctx.player().rotationPitch++;
|
||||
} else if (ctx.player().rotationPitch > 10) {
|
||||
ctx.player().rotationPitch--;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -99,6 +99,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
baritone.getPathingControlManager().cancelEverything();
|
||||
return;
|
||||
}
|
||||
|
||||
expectedSegmentStart = pathStart();
|
||||
baritone.getPathingControlManager().preTick();
|
||||
tickPath();
|
||||
@@ -238,11 +239,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (current != null) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
lastAutoJump = mc.gameSettings.autoJump;
|
||||
mc.gameSettings.autoJump = false;
|
||||
lastAutoJump = ctx.minecraft().gameSettings.autoJump;
|
||||
ctx.minecraft().gameSettings.autoJump = false;
|
||||
break;
|
||||
case POST:
|
||||
mc.gameSettings.autoJump = lastAutoJump;
|
||||
ctx.minecraft().gameSettings.autoJump = lastAutoJump;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
@@ -71,21 +71,21 @@ public class WaypointBehavior extends Behavior {
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(deathWaypoint);
|
||||
ITextComponent component = new TextComponentString("Death position saved.");
|
||||
component.getStyle()
|
||||
.setColor(TextFormatting.WHITE)
|
||||
.setHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new TextComponentString("Click to goto death")
|
||||
))
|
||||
.setClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
String.format(
|
||||
"%s%s goto %s @ %d",
|
||||
FORCE_COMMAND_PREFIX,
|
||||
"wp",
|
||||
deathWaypoint.getTag().getName(),
|
||||
deathWaypoint.getCreationTimestamp()
|
||||
)
|
||||
));
|
||||
.setColor(TextFormatting.WHITE)
|
||||
.setHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new TextComponentString("Click to goto death")
|
||||
))
|
||||
.setClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
String.format(
|
||||
"%s%s goto %s @ %d",
|
||||
FORCE_COMMAND_PREFIX,
|
||||
"wp",
|
||||
deathWaypoint.getTag().getName(),
|
||||
deathWaypoint.getCreationTimestamp()
|
||||
)
|
||||
));
|
||||
Helper.HELPER.logDirect(component);
|
||||
}
|
||||
|
||||
|
||||
85
src/main/java/baritone/behavior/look/ForkableRandom.java
Normal file
85
src/main/java/baritone/behavior/look/ForkableRandom.java
Normal file
@@ -0,0 +1,85 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.look;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
import java.util.function.LongSupplier;
|
||||
|
||||
/**
|
||||
* Implementation of Xoroshiro256++
|
||||
* <p>
|
||||
* Extended to produce random double-precision floating point numbers, and allow copies to be spawned via {@link #fork},
|
||||
* which share the same internal state as the source object.
|
||||
*
|
||||
* @author Brady
|
||||
*/
|
||||
public final class ForkableRandom {
|
||||
|
||||
private static final double DOUBLE_UNIT = 0x1.0p-53;
|
||||
|
||||
private final long[] s;
|
||||
|
||||
public ForkableRandom() {
|
||||
this(System.nanoTime() ^ System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public ForkableRandom(long seedIn) {
|
||||
final AtomicLong seed = new AtomicLong(seedIn);
|
||||
final LongSupplier splitmix64 = () -> {
|
||||
long z = seed.addAndGet(0x9e3779b97f4a7c15L);
|
||||
z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
|
||||
z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
|
||||
return z ^ (z >>> 31);
|
||||
};
|
||||
this.s = new long[] {
|
||||
splitmix64.getAsLong(),
|
||||
splitmix64.getAsLong(),
|
||||
splitmix64.getAsLong(),
|
||||
splitmix64.getAsLong()
|
||||
};
|
||||
}
|
||||
|
||||
private ForkableRandom(long[] s) {
|
||||
this.s = s;
|
||||
}
|
||||
|
||||
public double nextDouble() {
|
||||
return (this.next() >>> 11) * DOUBLE_UNIT;
|
||||
}
|
||||
|
||||
public long next() {
|
||||
final long result = rotl(this.s[0] + this.s[3], 23) + this.s[0];
|
||||
final long t = this.s[1] << 17;
|
||||
this.s[2] ^= this.s[0];
|
||||
this.s[3] ^= this.s[1];
|
||||
this.s[1] ^= this.s[2];
|
||||
this.s[0] ^= this.s[3];
|
||||
this.s[2] ^= t;
|
||||
this.s[3] = rotl(this.s[3], 45);
|
||||
return result;
|
||||
}
|
||||
|
||||
public ForkableRandom fork() {
|
||||
return new ForkableRandom(Arrays.copyOf(this.s, 4));
|
||||
}
|
||||
|
||||
private static long rotl(long x, int k) {
|
||||
return (x << k) | (x >>> (64 - k));
|
||||
}
|
||||
}
|
||||
@@ -307,6 +307,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
try {
|
||||
ChunkPos pos = toPackQueue.take();
|
||||
Chunk chunk = toPackMap.remove(pos);
|
||||
if (toPackQueue.size() > Baritone.settings().chunkPackerQueueMaxSize.value) {
|
||||
continue;
|
||||
}
|
||||
CachedChunk cached = ChunkPacker.pack(chunk);
|
||||
CachedWorld.this.updateCachedChunk(cached);
|
||||
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);
|
||||
|
||||
276
src/main/java/baritone/cache/FasterWorldScanner.java
vendored
Normal file
276
src/main/java/baritone/cache/FasterWorldScanner.java
vendored
Normal file
@@ -0,0 +1,276 @@
|
||||
/*
|
||||
* 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.cache;
|
||||
|
||||
import baritone.api.cache.ICachedWorld;
|
||||
import baritone.api.cache.IWorldScanner;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.BlockOptionalMetaLookup;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.utils.accessor.IBitArray;
|
||||
import baritone.utils.accessor.IBlockStateContainer;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
||||
import it.unimi.dsi.fastutil.ints.IntList;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.network.PacketBuffer;
|
||||
import net.minecraft.util.BitArray;
|
||||
import net.minecraft.util.ObjectIntIdentityMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.*;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.IntConsumer;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public enum FasterWorldScanner implements IWorldScanner {
|
||||
INSTANCE;
|
||||
@Override
|
||||
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) {
|
||||
assert ctx.world() != null;
|
||||
if (maxSearchRadius < 0) {
|
||||
throw new IllegalArgumentException("chunkRange must be >= 0");
|
||||
}
|
||||
return scanChunksInternal(ctx, filter, getChunkRange(ctx.playerFeet().x >> 4, ctx.playerFeet().z >> 4, maxSearchRadius), max);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BlockPos> scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) {
|
||||
Stream<BlockPos> stream = scanChunkInternal(ctx, filter, pos);
|
||||
if (max >= 0) {
|
||||
stream = stream.limit(max);
|
||||
}
|
||||
return stream.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repack(IPlayerContext ctx) {
|
||||
return this.repack(ctx, 40);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int repack(IPlayerContext ctx, int range) {
|
||||
IChunkProvider chunkProvider = ctx.world().getChunkProvider();
|
||||
ICachedWorld cachedWorld = ctx.worldData().getCachedWorld();
|
||||
|
||||
BetterBlockPos playerPos = ctx.playerFeet();
|
||||
|
||||
int playerChunkX = playerPos.getX() >> 4;
|
||||
int playerChunkZ = playerPos.getZ() >> 4;
|
||||
|
||||
int minX = playerChunkX - range;
|
||||
int minZ = playerChunkZ - range;
|
||||
int maxX = playerChunkX + range;
|
||||
int maxZ = playerChunkZ + range;
|
||||
|
||||
int queued = 0;
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
Chunk chunk = chunkProvider.getLoadedChunk(x, z);
|
||||
|
||||
if (chunk != null && !chunk.isEmpty()) {
|
||||
queued++;
|
||||
cachedWorld.queueForPacking(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return queued;
|
||||
}
|
||||
|
||||
// ordered in a way that the closest blocks are generally first
|
||||
public static List<ChunkPos> getChunkRange(int centerX, int centerZ, int chunkRadius) {
|
||||
List<ChunkPos> chunks = new ArrayList<>();
|
||||
// spiral out
|
||||
chunks.add(new ChunkPos(centerX, centerZ));
|
||||
for (int i = 1; i < chunkRadius; i++) {
|
||||
for (int j = 0; j <= i; j++) {
|
||||
chunks.add(new ChunkPos(centerX - j, centerZ - i));
|
||||
if (j != 0) {
|
||||
chunks.add(new ChunkPos(centerX + j, centerZ - i));
|
||||
chunks.add(new ChunkPos(centerX - j, centerZ + i));
|
||||
}
|
||||
chunks.add(new ChunkPos(centerX + j, centerZ + i));
|
||||
if (j != i) {
|
||||
chunks.add(new ChunkPos(centerX - i, centerZ - j));
|
||||
chunks.add(new ChunkPos(centerX + i, centerZ - j));
|
||||
if (j != 0) {
|
||||
chunks.add(new ChunkPos(centerX - i, centerZ + j));
|
||||
chunks.add(new ChunkPos(centerX + i, centerZ + j));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return chunks;
|
||||
}
|
||||
|
||||
private List<BlockPos> scanChunksInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, List<ChunkPos> chunkPositions, int maxBlocks) {
|
||||
assert ctx.world() != null;
|
||||
try {
|
||||
// p -> scanChunkInternal(ctx, lookup, p)
|
||||
Stream<BlockPos> posStream = chunkPositions.parallelStream().flatMap(p -> scanChunkInternal(ctx, lookup, p));
|
||||
if (maxBlocks >= 0) {
|
||||
// WARNING: this can be expensive if maxBlocks is large...
|
||||
// see limit's javadoc
|
||||
posStream = posStream.limit(maxBlocks);
|
||||
}
|
||||
return posStream.collect(Collectors.toList());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
throw e;
|
||||
}
|
||||
}
|
||||
|
||||
private Stream<BlockPos> scanChunkInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, ChunkPos pos) {
|
||||
IChunkProvider chunkProvider = ctx.world().getChunkProvider();
|
||||
// if chunk is not loaded, return empty stream
|
||||
if (!chunkProvider.isChunkGeneratedAt(pos.x, pos.z)) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
long chunkX = (long) pos.x << 4;
|
||||
long chunkZ = (long) pos.z << 4;
|
||||
|
||||
int playerSectionY = ctx.playerFeet().y >> 4;
|
||||
|
||||
return collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), chunkX, chunkZ, playerSectionY).stream();
|
||||
}
|
||||
|
||||
|
||||
|
||||
private List<BlockPos> collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, long chunkX, long chunkZ, int playerSection) {
|
||||
// iterate over sections relative to player
|
||||
List<BlockPos> blocks = new ArrayList<>();
|
||||
ExtendedBlockStorage[] sections = chunk.getBlockStorageArray();
|
||||
int l = sections.length;
|
||||
int i = playerSection - 1;
|
||||
int j = playerSection;
|
||||
for (; i >= 0 || j < l; ++j, --i) {
|
||||
if (j < l) {
|
||||
visitSection(lookup, sections[j], blocks, chunkX, chunkZ);
|
||||
}
|
||||
if (i >= 0) {
|
||||
visitSection(lookup, sections[i], blocks, chunkX, chunkZ);
|
||||
}
|
||||
}
|
||||
return blocks;
|
||||
}
|
||||
|
||||
private void visitSection(BlockOptionalMetaLookup lookup, ExtendedBlockStorage section, List<BlockPos> blocks, long chunkX, long chunkZ) {
|
||||
if (section == null || section.isEmpty()) {
|
||||
return;
|
||||
}
|
||||
|
||||
BlockStateContainer sectionContainer = section.getData();
|
||||
//this won't work if the PaletteStorage is of the type EmptyPaletteStorage
|
||||
if (((IBlockStateContainer) sectionContainer).getStorage() == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette());
|
||||
if (isInFilter.length == 0) {
|
||||
return;
|
||||
}
|
||||
|
||||
BitArray array = ((IBlockStateContainer) section.getData()).getStorage();
|
||||
long[] longArray = array.getBackingLongArray();
|
||||
int arraySize = array.size();
|
||||
int bitsPerEntry = ((IBitArray) array).getBitsPerEntry();
|
||||
long maxEntryValue = ((IBitArray) array).getMaxEntryValue();
|
||||
|
||||
|
||||
int yOffset = section.getYLocation();
|
||||
|
||||
for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) {
|
||||
final int i = idx * bitsPerEntry;
|
||||
final int j = i >> 6;
|
||||
final int l = i & 63;
|
||||
final int k = kl >> 6;
|
||||
final long jl = longArray[j] >>> l;
|
||||
|
||||
if (j == k) {
|
||||
if (isInFilter[(int) (jl & maxEntryValue)]) {
|
||||
//noinspection DuplicateExpressions
|
||||
blocks.add(new BlockPos(
|
||||
chunkX + ((idx & 255) & 15),
|
||||
yOffset + (idx >> 8),
|
||||
chunkZ + ((idx & 255) >> 4)
|
||||
));
|
||||
}
|
||||
} else {
|
||||
if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) {
|
||||
//noinspection DuplicateExpressions
|
||||
blocks.add(new BlockPos(
|
||||
chunkX + ((idx & 255) & 15),
|
||||
yOffset + (idx >> 8),
|
||||
chunkZ + ((idx & 255) >> 4)
|
||||
));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) {
|
||||
boolean commonBlockFound = false;
|
||||
ObjectIntIdentityMap<IBlockState> paletteMap = getPalette(palette);
|
||||
int size = paletteMap.size();
|
||||
|
||||
boolean[] isInFilter = new boolean[size];
|
||||
|
||||
for (int i = 0; i < size; i++) {
|
||||
IBlockState state = paletteMap.getByValue(i);
|
||||
if (lookup.has(state)) {
|
||||
isInFilter[i] = true;
|
||||
commonBlockFound = true;
|
||||
} else {
|
||||
isInFilter[i] = false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!commonBlockFound) {
|
||||
return new boolean[0];
|
||||
}
|
||||
return isInFilter;
|
||||
}
|
||||
|
||||
/**
|
||||
* cheats to get the actual map of id -> blockstate from the various palette implementations
|
||||
*/
|
||||
private static ObjectIntIdentityMap<IBlockState> getPalette(IBlockStatePalette palette) {
|
||||
if (palette instanceof BlockStatePaletteRegistry) {
|
||||
return Block.BLOCK_STATE_IDS;
|
||||
} else {
|
||||
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
|
||||
palette.write(buf);
|
||||
int size = buf.readVarInt();
|
||||
ObjectIntIdentityMap<IBlockState> states = new ObjectIntIdentityMap<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
IBlockState state = Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt());
|
||||
assert state != null;
|
||||
states.put(state, i);
|
||||
}
|
||||
return states;
|
||||
}
|
||||
}
|
||||
}
|
||||
1
src/main/java/baritone/cache/WorldData.java
vendored
1
src/main/java/baritone/cache/WorldData.java
vendored
@@ -22,7 +22,6 @@ import baritone.api.cache.ICachedWorld;
|
||||
import baritone.api.cache.IWaypointCollection;
|
||||
import baritone.api.cache.IWorldData;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
|
||||
179
src/main/java/baritone/cache/WorldProvider.java
vendored
179
src/main/java/baritone/cache/WorldProvider.java
vendored
@@ -19,111 +19,166 @@ package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.client.multiplayer.ServerData;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.charset.StandardCharsets;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018
|
||||
*/
|
||||
public class WorldProvider implements IWorldProvider, Helper {
|
||||
public class WorldProvider implements IWorldProvider {
|
||||
|
||||
private static final Map<Path, WorldData> worldCache = new HashMap<>(); // this is how the bots have the same cached world
|
||||
private static final Map<Path, WorldData> worldCache = new HashMap<>();
|
||||
|
||||
private final Baritone baritone;
|
||||
private final IPlayerContext ctx;
|
||||
private WorldData currentWorld;
|
||||
|
||||
/**
|
||||
* This lets us detect a broken load/unload hook.
|
||||
* @see #detectAndHandleBrokenLoading()
|
||||
*/
|
||||
private World mcWorld;
|
||||
|
||||
public WorldProvider(Baritone baritone) {
|
||||
this.baritone = baritone;
|
||||
this.ctx = baritone.getPlayerContext();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final WorldData getCurrentWorld() {
|
||||
this.detectAndHandleBrokenLoading();
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called when a new world is initialized to discover the
|
||||
*
|
||||
* @param dimension The ID of the world's dimension
|
||||
* @param world The new world
|
||||
*/
|
||||
public final void initWorld(int dimension) {
|
||||
File directory;
|
||||
File readme;
|
||||
public final void initWorld(World world) {
|
||||
this.getSaveDirectories(world).ifPresent(dirs -> {
|
||||
final Path worldDir = dirs.getFirst();
|
||||
final Path readmeDir = dirs.getSecond();
|
||||
|
||||
IntegratedServer integratedServer = mc.getIntegratedServer();
|
||||
|
||||
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
|
||||
if (mc.isSingleplayer()) {
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimension);
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
directory = loader.getChunkSaveLocation();
|
||||
|
||||
// Gets the "depth" of this directory relative the the game's run directory, 2 is the location of the world
|
||||
if (directory.toPath().relativize(mc.gameDir.toPath()).getNameCount() != 2) {
|
||||
// subdirectory of the main save directory for this world
|
||||
directory = directory.getParentFile();
|
||||
}
|
||||
|
||||
directory = new File(directory, "baritone");
|
||||
readme = directory;
|
||||
} else { // Otherwise, the server must be remote...
|
||||
String folderName;
|
||||
if (mc.getCurrentServerData() != null) {
|
||||
folderName = mc.getCurrentServerData().serverIP;
|
||||
} else {
|
||||
//replaymod causes null currentServerData and false singleplayer.
|
||||
currentWorld = null;
|
||||
return;
|
||||
}
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
folderName = folderName.replace(":", "_");
|
||||
}
|
||||
directory = new File(Baritone.getDir(), folderName);
|
||||
readme = Baritone.getDir();
|
||||
}
|
||||
|
||||
// lol wtf is this baritone folder in my minecraft save?
|
||||
try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) {
|
||||
// good thing we have a readme
|
||||
out.write("https://github.com/cabaletta/baritone\n".getBytes());
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
// We will actually store the world data in a subfolder: "DIM<id>"
|
||||
Path dir = new File(directory, "DIM" + dimension).toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
// lol wtf is this baritone folder in my minecraft save?
|
||||
// good thing we have a readme
|
||||
Files.createDirectories(readmeDir);
|
||||
Files.write(
|
||||
readmeDir.resolve("readme.txt"),
|
||||
"https://github.com/cabaletta/baritone\n".getBytes(StandardCharsets.US_ASCII)
|
||||
);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
System.out.println("Baritone world data dir: " + dir);
|
||||
synchronized (worldCache) {
|
||||
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension));
|
||||
}
|
||||
// We will actually store the world data in a subfolder: "DIM<id>"
|
||||
final Path worldDataDir = this.getWorldDataDirectory(worldDir, world);
|
||||
try {
|
||||
Files.createDirectories(worldDataDir);
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
System.out.println("Baritone world data dir: " + worldDataDir);
|
||||
synchronized (worldCache) {
|
||||
final int dimension = world.provider.getDimensionType().getId();
|
||||
this.currentWorld = worldCache.computeIfAbsent(worldDataDir, d -> new WorldData(d, dimension));
|
||||
}
|
||||
this.mcWorld = ctx.world();
|
||||
});
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
WorldData world = this.currentWorld;
|
||||
this.currentWorld = null;
|
||||
this.mcWorld = null;
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
world.onClose();
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
|
||||
if (this.currentWorld != null) {
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
private Path getWorldDataDirectory(Path parent, World world) {
|
||||
return parent.resolve("DIM" + world.provider.getDimensionType().getId());
|
||||
}
|
||||
|
||||
/**
|
||||
* @param world The world
|
||||
* @return An {@link Optional} containing the world's baritone dir and readme dir, or {@link Optional#empty()} if
|
||||
* the world isn't valid for caching.
|
||||
*/
|
||||
private Optional<Tuple<Path, Path>> getSaveDirectories(World world) {
|
||||
Path worldDir;
|
||||
Path readmeDir;
|
||||
|
||||
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
|
||||
if (ctx.minecraft().isSingleplayer()) {
|
||||
final int dimension = world.provider.getDimensionType().getId();
|
||||
final WorldServer localServerWorld = ctx.minecraft().getIntegratedServer().getWorld(dimension);
|
||||
final IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
final IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
worldDir = loader.getChunkSaveLocation().toPath();
|
||||
|
||||
// Gets the "depth" of this directory relative to the game's run directory, 2 is the location of the world
|
||||
if (worldDir.relativize(ctx.minecraft().gameDir.toPath()).getNameCount() != 2) {
|
||||
// subdirectory of the main save directory for this world
|
||||
worldDir = worldDir.getParent();
|
||||
}
|
||||
|
||||
worldDir = worldDir.resolve("baritone");
|
||||
readmeDir = worldDir;
|
||||
} else { // Otherwise, the server must be remote...
|
||||
String folderName;
|
||||
final ServerData serverData = ctx.minecraft().getCurrentServerData();
|
||||
if (serverData != null) {
|
||||
folderName = serverData.serverIP;
|
||||
} else {
|
||||
//replaymod causes null currentServerData and false singleplayer.
|
||||
System.out.println("World seems to be a replay. Not loading Baritone cache.");
|
||||
currentWorld = null;
|
||||
mcWorld = ctx.world();
|
||||
return Optional.empty();
|
||||
}
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
folderName = folderName.replace(":", "_");
|
||||
}
|
||||
// TODO: This should probably be in "baritone/servers"
|
||||
worldDir = baritone.getDirectory().resolve(folderName);
|
||||
// Just write the readme to the baritone directory instead of each server save in it
|
||||
readmeDir = baritone.getDirectory();
|
||||
}
|
||||
|
||||
return Optional.of(new Tuple<>(worldDir, readmeDir));
|
||||
}
|
||||
|
||||
/**
|
||||
* Why does this exist instead of fixing the event? Some mods break the event. Lol.
|
||||
*/
|
||||
private void detectAndHandleBrokenLoading() {
|
||||
if (this.mcWorld != ctx.world()) {
|
||||
if (this.currentWorld != null) {
|
||||
System.out.println("mc.world unloaded unnoticed! Unloading Baritone cache now.");
|
||||
closeWorld();
|
||||
}
|
||||
if (ctx.world() != null) {
|
||||
System.out.println("mc.world loaded unnoticed! Loading Baritone cache now.");
|
||||
initWorld(ctx.world());
|
||||
}
|
||||
} else if (this.currentWorld == null && ctx.world() != null && (ctx.minecraft().isSingleplayer() || ctx.minecraft().getCurrentServerData() != null)) {
|
||||
System.out.println("Retrying to load Baritone cache");
|
||||
initWorld(ctx.world());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -17,8 +17,8 @@
|
||||
|
||||
package baritone.command;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.command.argument.ICommandArgument;
|
||||
import baritone.api.command.exception.CommandNotEnoughArgumentsException;
|
||||
@@ -30,6 +30,7 @@ import baritone.api.event.events.TabCompleteEvent;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.command.argument.ArgConsumer;
|
||||
import baritone.command.argument.CommandArguments;
|
||||
import baritone.command.manager.CommandManager;
|
||||
@@ -49,14 +50,14 @@ import java.util.stream.Stream;
|
||||
|
||||
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
public class ExampleBaritoneControl implements Helper, AbstractGameEventListener {
|
||||
public class ExampleBaritoneControl extends Behavior implements Helper {
|
||||
|
||||
private static final Settings settings = BaritoneAPI.getSettings();
|
||||
private final ICommandManager manager;
|
||||
|
||||
public ExampleBaritoneControl(IBaritone baritone) {
|
||||
public ExampleBaritoneControl(Baritone baritone) {
|
||||
super(baritone);
|
||||
this.manager = baritone.getCommandManager();
|
||||
baritone.getGameEventHandler().registerEventListener(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +101,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
|
||||
return false;
|
||||
} else if (msg.trim().equalsIgnoreCase("orderpizza")) {
|
||||
try {
|
||||
((IGuiScreen) mc.currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/"));
|
||||
((IGuiScreen) ctx.minecraft().currentScreen).openLink(new URI("https://www.dominos.com/en/pages/order/"));
|
||||
} catch (NullPointerException | URISyntaxException ignored) {}
|
||||
return false;
|
||||
}
|
||||
@@ -124,7 +125,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
|
||||
}
|
||||
} else if (argc.hasExactlyOne()) {
|
||||
for (Settings.Setting setting : settings.allSettings) {
|
||||
if (SettingsUtil.javaOnlySetting(setting)) {
|
||||
if (setting.isJavaOnly()) {
|
||||
continue;
|
||||
}
|
||||
if (setting.getName().equalsIgnoreCase(pair.getFirst())) {
|
||||
@@ -177,7 +178,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
|
||||
.stream();
|
||||
}
|
||||
Settings.Setting setting = settings.byLowerName.get(argc.getString().toLowerCase(Locale.US));
|
||||
if (setting != null && !SettingsUtil.javaOnlySetting(setting)) {
|
||||
if (setting != null && !setting.isJavaOnly()) {
|
||||
if (setting.getValueClass() == Boolean.class) {
|
||||
TabCompleteHelper helper = new TabCompleteHelper();
|
||||
if ((Boolean) setting.value) {
|
||||
|
||||
@@ -373,6 +373,8 @@ public class ArgConsumer implements IArgConsumer {
|
||||
public <T extends IDatatype> Stream<String> tabCompleteDatatype(T datatype) {
|
||||
try {
|
||||
return datatype.tabComplete(this.context);
|
||||
} catch (CommandException ignored) {
|
||||
// NOP
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import baritone.api.command.datatypes.RelativeFile;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandInvalidStateException;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -36,10 +35,11 @@ import java.util.stream.Stream;
|
||||
|
||||
public class BuildCommand extends Command {
|
||||
|
||||
private static final File schematicsDir = new File(Minecraft.getMinecraft().gameDir, "schematics");
|
||||
private final File schematicsDir;
|
||||
|
||||
public BuildCommand(IBaritone baritone) {
|
||||
super(baritone, "build");
|
||||
this.schematicsDir = new File(baritone.getPlayerContext().minecraft().gameDir, "schematics");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,10 +21,7 @@ import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandInvalidStateException;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
@@ -39,11 +36,7 @@ public class ComeCommand extends Command {
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
Entity entity = mc.getRenderViewEntity();
|
||||
if (entity == null) {
|
||||
throw new CommandInvalidStateException("render view entity is null");
|
||||
}
|
||||
baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(new BlockPos(entity)));
|
||||
baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(ctx.viewerPos()));
|
||||
logDirect("Coming");
|
||||
}
|
||||
|
||||
|
||||
@@ -43,6 +43,7 @@ public final class DefaultCommands {
|
||||
new RepackCommand(baritone),
|
||||
new BuildCommand(baritone),
|
||||
new SchematicaCommand(baritone),
|
||||
new LitematicaCommand(baritone),
|
||||
new ComeCommand(baritone),
|
||||
new AxisCommand(baritone),
|
||||
new ForceCancelCommand(baritone),
|
||||
|
||||
@@ -18,17 +18,16 @@
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.calc.IPathingControlManager;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
import baritone.api.behavior.IPathingBehavior;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandInvalidStateException;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.pathing.calc.IPathingControlManager;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ETACommand extends Command {
|
||||
|
||||
@@ -56,6 +56,7 @@ public class ExecutionControlCommands {
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
|
||||
|
||||
@@ -41,7 +41,7 @@ public class ExploreFilterCommand extends Command {
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(2);
|
||||
File file = args.getDatatypePost(RelativeFile.INSTANCE, mc.gameDir.getAbsoluteFile().getParentFile());
|
||||
File file = args.getDatatypePost(RelativeFile.INSTANCE, ctx.minecraft().gameDir.getAbsoluteFile().getParentFile());
|
||||
boolean invert = false;
|
||||
if (args.hasAny()) {
|
||||
if (args.getString().equalsIgnoreCase("invert")) {
|
||||
@@ -65,7 +65,7 @@ public class ExploreFilterCommand extends Command {
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
if (args.hasExactlyOne()) {
|
||||
return RelativeFile.tabComplete(args, RelativeFile.gameDir());
|
||||
return RelativeFile.tabComplete(args, RelativeFile.gameDir(ctx.minecraft()));
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@@ -79,10 +79,10 @@ public class FindCommand extends Command {
|
||||
ITextComponent baseComponent = new TextComponentString(pos.toString());
|
||||
ITextComponent hoverComponent = new TextComponentString("Click to set goal to this position");
|
||||
baseComponent.getStyle()
|
||||
.setColor(TextFormatting.GRAY)
|
||||
.setInsertion(positionText)
|
||||
.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))
|
||||
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverComponent));
|
||||
.setColor(TextFormatting.GRAY)
|
||||
.setInsertion(positionText)
|
||||
.setClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))
|
||||
.setHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverComponent));
|
||||
return baseComponent;
|
||||
}
|
||||
|
||||
@@ -90,9 +90,9 @@ public class FindCommand extends Command {
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
return new TabCompleteHelper()
|
||||
.append(
|
||||
CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.stream()
|
||||
.map(Block.REGISTRY::getNameForObject)
|
||||
.map(Object::toString)
|
||||
CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.stream()
|
||||
.map(Block.REGISTRY::getNameForObject)
|
||||
.map(Object::toString)
|
||||
)
|
||||
.filterPrefixNamespaced(args.getString())
|
||||
.sortAlphabetically()
|
||||
|
||||
@@ -51,7 +51,7 @@ public class GoalCommand extends Command {
|
||||
}
|
||||
} else {
|
||||
args.requireMax(3);
|
||||
BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
|
||||
BetterBlockPos origin = ctx.playerFeet();
|
||||
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
|
||||
goalProcess.setGoal(goal);
|
||||
logDirect(String.format("Goal: %s", goal.toString()));
|
||||
|
||||
@@ -20,7 +20,6 @@ package baritone.command.defaults;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.BlockById;
|
||||
import baritone.api.command.datatypes.ForBlockOptionalMeta;
|
||||
import baritone.api.command.datatypes.RelativeCoordinate;
|
||||
import baritone.api.command.datatypes.RelativeGoal;
|
||||
@@ -46,7 +45,7 @@ public class GotoCommand extends Command {
|
||||
// is no need to handle the case of empty arguments.
|
||||
if (args.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) {
|
||||
args.requireMax(3);
|
||||
BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
|
||||
BetterBlockPos origin = ctx.playerFeet();
|
||||
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
|
||||
logDirect(String.format("Going to: %s", goal.toString()));
|
||||
baritone.getCustomGoalProcess().setGoalAndPath(goal);
|
||||
@@ -61,7 +60,8 @@ public class GotoCommand extends Command {
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
// since it's either a goal or a block, I don't think we can tab complete properly?
|
||||
// so just tab complete for the block variant
|
||||
return args.tabCompleteDatatype(BlockById.INSTANCE);
|
||||
args.requireMax(1);
|
||||
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -0,0 +1,71 @@
|
||||
/*
|
||||
* 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.exception.CommandException;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class LitematicaCommand extends Command {
|
||||
|
||||
public LitematicaCommand(IBaritone baritone) {
|
||||
super(baritone, "litematica");
|
||||
}
|
||||
|
||||
@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.");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortDesc() {
|
||||
return "Builds the loaded schematic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"Build a schematic currently open in Litematica.",
|
||||
"",
|
||||
"Usage:",
|
||||
"> litematica",
|
||||
"> litematica <#>"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -17,10 +17,10 @@
|
||||
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.BlockById;
|
||||
import baritone.api.command.datatypes.ForBlockOptionalMeta;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
@@ -45,14 +45,18 @@ public class MineCommand extends Command {
|
||||
while (args.hasAny()) {
|
||||
boms.add(args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE));
|
||||
}
|
||||
WorldScanner.INSTANCE.repack(ctx);
|
||||
BaritoneAPI.getProvider().getWorldScanner().repack(ctx);
|
||||
logDirect(String.format("Mining %s", boms.toString()));
|
||||
baritone.getMineProcess().mine(quantity, boms.toArray(new BlockOptionalMeta[0]));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) {
|
||||
return args.tabCompleteDatatype(BlockById.INSTANCE);
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
args.getAsOrDefault(Integer.class, 0);
|
||||
while (args.has(2)) {
|
||||
args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
|
||||
}
|
||||
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
@@ -38,7 +39,7 @@ public class PathCommand extends Command {
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
|
||||
args.requireMax(0);
|
||||
WorldScanner.INSTANCE.repack(ctx);
|
||||
BaritoneAPI.getProvider().getWorldScanner().repack(ctx);
|
||||
customGoalProcess.path();
|
||||
logDirect("Now pathing");
|
||||
}
|
||||
|
||||
@@ -37,8 +37,8 @@ public class RenderCommand extends Command {
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
BetterBlockPos origin = ctx.playerFeet();
|
||||
int renderDistance = (mc.gameSettings.renderDistanceChunks + 1) * 16;
|
||||
mc.renderGlobal.markBlockRangeForRenderUpdate(
|
||||
int renderDistance = (ctx.minecraft().gameSettings.renderDistanceChunks + 1) * 16;
|
||||
ctx.minecraft().renderGlobal.markBlockRangeForRenderUpdate(
|
||||
origin.x - renderDistance,
|
||||
0,
|
||||
origin.z - renderDistance,
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
@@ -36,7 +37,7 @@ public class RepackCommand extends Command {
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
logDirect(String.format("Queued %d chunks for repacking", WorldScanner.INSTANCE.repack(ctx)));
|
||||
logDirect(String.format("Queued %d chunks for repacking", BaritoneAPI.getProvider().getWorldScanner().repack(ctx)));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -21,6 +21,7 @@ import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.ForAxis;
|
||||
import baritone.api.command.datatypes.ForBlockOptionalMeta;
|
||||
import baritone.api.command.datatypes.ForEnumFacing;
|
||||
import baritone.api.command.datatypes.RelativeBlockPos;
|
||||
@@ -31,13 +32,15 @@ import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.schematic.*;
|
||||
import baritone.api.schematic.mask.shape.CylinderMask;
|
||||
import baritone.api.schematic.mask.shape.SphereMask;
|
||||
import baritone.api.selection.ISelection;
|
||||
import baritone.api.selection.ISelectionManager;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
import baritone.api.utils.BlockOptionalMetaLookup;
|
||||
import baritone.utils.IRenderer;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.IRenderer;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -50,6 +53,7 @@ import java.awt.*;
|
||||
import java.util.List;
|
||||
import java.util.*;
|
||||
import java.util.function.Function;
|
||||
import java.util.function.UnaryOperator;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SelCommand extends Command {
|
||||
@@ -72,7 +76,7 @@ public class SelCommand extends Command {
|
||||
float lineWidth = Baritone.settings().selectionLineWidth.value;
|
||||
boolean ignoreDepth = Baritone.settings().renderSelectionIgnoreDepth.value;
|
||||
IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
|
||||
IRenderer.drawAABB(new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
|
||||
IRenderer.emitAABB(new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
|
||||
IRenderer.endLines(ignoreDepth);
|
||||
}
|
||||
});
|
||||
@@ -88,7 +92,7 @@ public class SelCommand extends Command {
|
||||
if (action == Action.POS2 && pos1 == null) {
|
||||
throw new CommandInvalidStateException("Set pos1 first before using pos2");
|
||||
}
|
||||
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
|
||||
BetterBlockPos playerPos = ctx.viewerPos();
|
||||
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
|
||||
args.requireMax(0);
|
||||
if (action == Action.POS1) {
|
||||
@@ -117,11 +121,13 @@ public class SelCommand extends Command {
|
||||
logDirect("Undid pos2");
|
||||
}
|
||||
}
|
||||
} else if (action == Action.SET || action == Action.WALLS || action == Action.SHELL || action == Action.CLEARAREA || action == Action.REPLACE) {
|
||||
} else if (action.isFillAction()) {
|
||||
BlockOptionalMeta type = action == Action.CLEARAREA
|
||||
? new BlockOptionalMeta(Blocks.AIR)
|
||||
: args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
|
||||
BlockOptionalMetaLookup replaces = null;
|
||||
|
||||
final BlockOptionalMetaLookup replaces; // Action.REPLACE
|
||||
final EnumFacing.Axis alignment; // Action.(H)CYLINDER
|
||||
if (action == Action.REPLACE) {
|
||||
args.requireMin(1);
|
||||
List<BlockOptionalMeta> replacesList = new ArrayList<>();
|
||||
@@ -131,8 +137,15 @@ public class SelCommand extends Command {
|
||||
}
|
||||
type = args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
|
||||
replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0]));
|
||||
alignment = null;
|
||||
} else if (action == Action.CYLINDER || action == Action.HCYLINDER) {
|
||||
args.requireMax(1);
|
||||
alignment = args.hasAny() ? args.getDatatypeFor(ForAxis.INSTANCE) : EnumFacing.Axis.Y;
|
||||
replaces = null;
|
||||
} else {
|
||||
args.requireMax(0);
|
||||
replaces = null;
|
||||
alignment = null;
|
||||
}
|
||||
ISelection[] selections = manager.getSelections();
|
||||
if (selections.length == 0) {
|
||||
@@ -151,20 +164,41 @@ public class SelCommand extends Command {
|
||||
for (ISelection selection : selections) {
|
||||
Vec3i size = selection.size();
|
||||
BetterBlockPos min = selection.min();
|
||||
ISchematic schematic = new FillSchematic(size.getX(), size.getY(), size.getZ(), type);
|
||||
if (action == Action.WALLS) {
|
||||
schematic = new WallsSchematic(schematic);
|
||||
} else if (action == Action.SHELL) {
|
||||
schematic = new ShellSchematic(schematic);
|
||||
} else if (action == Action.REPLACE) {
|
||||
schematic = new ReplaceSchematic(schematic, replaces);
|
||||
}
|
||||
|
||||
// Java 8 so no switch expressions 😿
|
||||
UnaryOperator<ISchematic> create = fill -> {
|
||||
final int w = fill.widthX();
|
||||
final int h = fill.heightY();
|
||||
final int l = fill.lengthZ();
|
||||
|
||||
switch (action) {
|
||||
case WALLS:
|
||||
return new WallsSchematic(fill);
|
||||
case SHELL:
|
||||
return new ShellSchematic(fill);
|
||||
case REPLACE:
|
||||
return new ReplaceSchematic(fill, replaces);
|
||||
case SPHERE:
|
||||
return MaskSchematic.create(fill, new SphereMask(w, h, l, true).compute());
|
||||
case HSPHERE:
|
||||
return MaskSchematic.create(fill, new SphereMask(w, h, l, false).compute());
|
||||
case CYLINDER:
|
||||
return MaskSchematic.create(fill, new CylinderMask(w, h, l, true, alignment).compute());
|
||||
case HCYLINDER:
|
||||
return MaskSchematic.create(fill, new CylinderMask(w, h, l, false, alignment).compute());
|
||||
default:
|
||||
// Silent fail
|
||||
return fill;
|
||||
}
|
||||
};
|
||||
|
||||
ISchematic schematic = create.apply(new FillSchematic(size.getX(), size.getY(), size.getZ(), type));
|
||||
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
|
||||
}
|
||||
baritone.getBuilderProcess().build("Fill", composite, origin);
|
||||
logDirect("Filling now");
|
||||
} else if (action == Action.COPY) {
|
||||
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
|
||||
BetterBlockPos playerPos = ctx.viewerPos();
|
||||
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
|
||||
args.requireMax(0);
|
||||
ISelection[] selections = manager.getSelections();
|
||||
@@ -193,7 +227,7 @@ public class SelCommand extends Command {
|
||||
}
|
||||
}
|
||||
}
|
||||
ISchematic schematic = new StaticSchematic(){{
|
||||
ISchematic schematic = new StaticSchematic() {{
|
||||
states = blockstates;
|
||||
x = size.getX();
|
||||
y = size.getY();
|
||||
@@ -205,7 +239,7 @@ public class SelCommand extends Command {
|
||||
clipboardOffset = origin.subtract(pos);
|
||||
logDirect("Selection copied");
|
||||
} else if (action == Action.PASTE) {
|
||||
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(new BlockPos(mc.getRenderViewEntity())) : ctx.playerFeet();
|
||||
BetterBlockPos playerPos = ctx.viewerPos();
|
||||
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
|
||||
args.requireMax(0);
|
||||
if (clipboard == null) {
|
||||
@@ -254,12 +288,15 @@ public class SelCommand extends Command {
|
||||
if (args.hasAtMost(3)) {
|
||||
return args.tabCompleteDatatype(RelativeBlockPos.INSTANCE);
|
||||
}
|
||||
} else if (action == Action.SET || action == Action.WALLS || action == Action.CLEARAREA || action == Action.REPLACE) {
|
||||
} else if (action.isFillAction()) {
|
||||
if (args.hasExactlyOne() || action == Action.REPLACE) {
|
||||
while (args.has(2)) {
|
||||
args.get();
|
||||
}
|
||||
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
|
||||
} else if (args.hasExactly(2) && (action == Action.CYLINDER || action == Action.HCYLINDER)) {
|
||||
args.get();
|
||||
return args.tabCompleteDatatype(ForAxis.INSTANCE);
|
||||
}
|
||||
} else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) {
|
||||
if (args.hasExactlyOne()) {
|
||||
@@ -305,6 +342,10 @@ public class SelCommand extends Command {
|
||||
"> sel set/fill/s/f [block] - Completely fill all selections with a block.",
|
||||
"> sel walls/w [block] - Fill in the walls of the selection with a specified block.",
|
||||
"> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.",
|
||||
"> sel sphere/sph [block] - Fills the selection with a sphere bounded by the sides.",
|
||||
"> sel hsphere/hsph [block] - The same as sphere, but hollow.",
|
||||
"> sel cylinder/cyl [block] <axis> - Fills the selection with a cylinder bounded by the sides, oriented about the given axis. (default=y)",
|
||||
"> sel hcylinder/hcyl [block] <axis> - The same as cylinder, but hollow.",
|
||||
"> sel cleararea/ca - Basically 'set air'.",
|
||||
"> sel replace/r <blocks...> <with> - Replaces blocks with another block.",
|
||||
"> sel copy/cp <x> <y> <z> - Copy the selected area relative to the specified or your position.",
|
||||
@@ -324,6 +365,10 @@ public class SelCommand extends Command {
|
||||
SET("set", "fill", "s", "f"),
|
||||
WALLS("walls", "w"),
|
||||
SHELL("shell", "shl"),
|
||||
SPHERE("sphere", "sph"),
|
||||
HSPHERE("hsphere", "hsph"),
|
||||
CYLINDER("cylinder", "cyl"),
|
||||
HCYLINDER("hcylinder", "hcyl"),
|
||||
CLEARAREA("cleararea", "ca"),
|
||||
REPLACE("replace", "r"),
|
||||
EXPAND("expand", "ex"),
|
||||
@@ -355,6 +400,18 @@ public class SelCommand extends Command {
|
||||
}
|
||||
return names.toArray(new String[0]);
|
||||
}
|
||||
|
||||
public final boolean isFillAction() {
|
||||
return this == SET
|
||||
|| this == WALLS
|
||||
|| this == SHELL
|
||||
|| this == SPHERE
|
||||
|| this == HSPHERE
|
||||
|| this == CYLINDER
|
||||
|| this == HCYLINDER
|
||||
|| this == CLEARAREA
|
||||
|| this == REPLACE;
|
||||
}
|
||||
}
|
||||
|
||||
enum TransformTarget {
|
||||
|
||||
@@ -22,12 +22,14 @@ import baritone.api.IBaritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.RelativeFile;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandInvalidStateException;
|
||||
import baritone.api.command.exception.CommandInvalidTypeException;
|
||||
import baritone.api.command.helpers.Paginator;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
import net.minecraft.util.text.TextComponentString;
|
||||
import net.minecraft.util.text.TextFormatting;
|
||||
@@ -57,6 +59,18 @@ public class SetCommand extends Command {
|
||||
logDirect("Settings saved");
|
||||
return;
|
||||
}
|
||||
if (Arrays.asList("load", "ld").contains(arg)) {
|
||||
String file = SETTINGS_DEFAULT_NAME;
|
||||
if (args.hasAny()) {
|
||||
file = args.getString();
|
||||
}
|
||||
// reset to defaults
|
||||
SettingsUtil.modifiedSettings(Baritone.settings()).forEach(Settings.Setting::reset);
|
||||
// then load from disk
|
||||
SettingsUtil.readAndApply(Baritone.settings(), file);
|
||||
logDirect("Settings reloaded from " + file);
|
||||
return;
|
||||
}
|
||||
boolean viewModified = Arrays.asList("m", "mod", "modified").contains(arg);
|
||||
boolean viewAll = Arrays.asList("all", "l", "list").contains(arg);
|
||||
boolean paginate = viewModified || viewAll;
|
||||
@@ -65,7 +79,7 @@ public class SetCommand extends Command {
|
||||
args.requireMax(1);
|
||||
List<? extends Settings.Setting> toPaginate =
|
||||
(viewModified ? SettingsUtil.modifiedSettings(Baritone.settings()) : Baritone.settings().allSettings).stream()
|
||||
.filter(s -> !javaOnlySetting(s))
|
||||
.filter(s -> !s.isJavaOnly())
|
||||
.filter(s -> s.getName().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US)))
|
||||
.sorted((s1, s2) -> String.CASE_INSENSITIVE_ORDER.compare(s1.getName(), s2.getName()))
|
||||
.collect(Collectors.toList());
|
||||
@@ -129,7 +143,7 @@ public class SetCommand extends Command {
|
||||
if (setting == null) {
|
||||
throw new CommandInvalidTypeException(args.consumed(), "a valid setting");
|
||||
}
|
||||
if (javaOnlySetting(setting)) {
|
||||
if (setting.isJavaOnly()) {
|
||||
// ideally it would act as if the setting didn't exist
|
||||
// but users will see it in Settings.java or its javadoc
|
||||
// so at some point we have to tell them or they will see it as a bug
|
||||
@@ -147,7 +161,8 @@ public class SetCommand extends Command {
|
||||
throw new CommandInvalidTypeException(args.consumed(), "a toggleable setting", "some other setting");
|
||||
}
|
||||
//noinspection unchecked
|
||||
((Settings.Setting<Boolean>) setting).value ^= true;
|
||||
Settings.Setting<Boolean> asBoolSetting = (Settings.Setting<Boolean>) setting;
|
||||
asBoolSetting.value ^= true;
|
||||
logDirect(String.format(
|
||||
"Toggled setting %s to %s",
|
||||
setting.getName(),
|
||||
@@ -208,6 +223,9 @@ public class SetCommand extends Command {
|
||||
.addToggleableSettings()
|
||||
.filterPrefix(args.getString())
|
||||
.stream();
|
||||
} else if (Arrays.asList("ld", "load").contains(arg.toLowerCase(Locale.US))) {
|
||||
// settings always use the directory of the main Minecraft instance
|
||||
return RelativeFile.tabComplete(args, Minecraft.getMinecraft().gameDir.toPath().resolve("baritone").toFile());
|
||||
}
|
||||
Settings.Setting setting = Baritone.settings().byLowerName.get(arg.toLowerCase(Locale.US));
|
||||
if (setting != null) {
|
||||
@@ -227,7 +245,7 @@ public class SetCommand extends Command {
|
||||
return new TabCompleteHelper()
|
||||
.addSettings()
|
||||
.sortAlphabetically()
|
||||
.prepend("list", "modified", "reset", "toggle", "save")
|
||||
.prepend("list", "modified", "reset", "toggle", "save", "load")
|
||||
.filterPrefix(arg)
|
||||
.stream();
|
||||
}
|
||||
@@ -254,7 +272,9 @@ public class SetCommand extends Command {
|
||||
"> set reset all - Reset ALL SETTINGS to their defaults",
|
||||
"> set reset <setting> - Reset a setting to its default",
|
||||
"> set toggle <setting> - Toggle a boolean setting",
|
||||
"> set save - Save all settings (this is automatic tho)"
|
||||
"> set save - Save all settings (this is automatic tho)",
|
||||
"> set load - Load settings from settings.txt",
|
||||
"> set load [filename] - Load settings from another file in your minecraft/baritone"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,13 +38,13 @@ public class SurfaceCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
final BetterBlockPos playerPos = baritone.getPlayerContext().playerFeet();
|
||||
final int surfaceLevel = baritone.getPlayerContext().world().getSeaLevel();
|
||||
final int worldHeight = baritone.getPlayerContext().world().getActualHeight();
|
||||
final BetterBlockPos playerPos = ctx.playerFeet();
|
||||
final int surfaceLevel = ctx.world().getSeaLevel();
|
||||
final int worldHeight = ctx.world().getActualHeight();
|
||||
|
||||
// Ensure this command will not run if you are above the surface level and the block above you is air
|
||||
// As this would imply that your are already on the open surface
|
||||
if (playerPos.getY() > surfaceLevel && mc.world.getBlockState(playerPos.up()).getBlock() instanceof BlockAir) {
|
||||
if (playerPos.getY() > surfaceLevel && ctx.world().getBlockState(playerPos.up()).getBlock() instanceof BlockAir) {
|
||||
logDirect("Already at surface");
|
||||
return;
|
||||
}
|
||||
@@ -54,7 +54,7 @@ public class SurfaceCommand extends Command {
|
||||
for (int currentIteratedY = startingYPos; currentIteratedY < worldHeight; currentIteratedY++) {
|
||||
final BetterBlockPos newPos = new BetterBlockPos(playerPos.getX(), currentIteratedY, playerPos.getZ());
|
||||
|
||||
if (!(mc.world.getBlockState(newPos).getBlock() instanceof BlockAir) && newPos.getY() > playerPos.getY()) {
|
||||
if (!(ctx.world().getBlockState(newPos).getBlock() instanceof BlockAir) && newPos.getY() > playerPos.getY()) {
|
||||
Goal goal = new GoalBlock(newPos.up());
|
||||
logDirect(String.format("Going to: %s", goal.toString()));
|
||||
baritone.getCustomGoalProcess().setGoalAndPath(goal);
|
||||
|
||||
@@ -20,8 +20,8 @@ package baritone.command.defaults;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.cache.IWaypoint;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.ForWaypoints;
|
||||
@@ -50,7 +50,7 @@ import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
public class WaypointsCommand extends Command {
|
||||
|
||||
private Map<IWorldData,List<IWaypoint>> deletedWaypoints = new HashMap<>();
|
||||
private Map<IWorldData, List<IWaypoint>> deletedWaypoints = new HashMap<>();
|
||||
|
||||
public WaypointsCommand(IBaritone baritone) {
|
||||
super(baritone, "waypoints", "waypoint", "wp");
|
||||
@@ -149,7 +149,11 @@ public class WaypointsCommand extends Command {
|
||||
logDirect(component);
|
||||
} else if (action == Action.CLEAR) {
|
||||
args.requireMax(1);
|
||||
IWaypoint.Tag tag = IWaypoint.Tag.getByName(args.getString());
|
||||
String name = args.getString();
|
||||
IWaypoint.Tag tag = IWaypoint.Tag.getByName(name);
|
||||
if (tag == null) {
|
||||
throw new CommandInvalidStateException("Invalid tag, \"" + name + "\"");
|
||||
}
|
||||
IWaypoint[] waypoints = ForWaypoints.getWaypointsByTag(this.baritone, tag);
|
||||
for (IWaypoint waypoint : waypoints) {
|
||||
ForWaypoints.waypoints(this.baritone).removeWaypoint(waypoint);
|
||||
|
||||
@@ -21,6 +21,7 @@ import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.command.ICommand;
|
||||
import baritone.api.command.argument.ICommandArgument;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.exception.CommandUnhandledException;
|
||||
import baritone.api.command.exception.ICommandException;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
@@ -151,9 +152,12 @@ public class CommandManager implements ICommandManager {
|
||||
private Stream<String> tabComplete() {
|
||||
try {
|
||||
return this.command.tabComplete(this.label, this.args);
|
||||
} catch (CommandException ignored) {
|
||||
// NOP
|
||||
} catch (Throwable t) {
|
||||
return Stream.empty();
|
||||
t.printStackTrace();
|
||||
}
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -114,7 +114,7 @@ public final class GameEventHandler implements IEventBus, Helper {
|
||||
if (event.getState() == EventState.POST) {
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null) {
|
||||
cache.initWorld(event.getWorld().provider.getDimensionType().getId());
|
||||
cache.initWorld(event.getWorld());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user