Compare commits
486 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
24e047c12e | ||
|
|
5841bd4e36 | ||
|
|
81e9865067 | ||
|
|
f9d563b9e6 | ||
|
|
3e3312f009 | ||
|
|
327fbc868e | ||
|
|
6d5cfe4187 | ||
|
|
d3e0da7c5e | ||
|
|
38fbc127e6 | ||
|
|
25ef38aaf2 | ||
|
|
d05d5fd98e | ||
|
|
698d40d797 | ||
|
|
2b6c59fa8a | ||
|
|
21bc830143 | ||
|
|
432d42ade8 | ||
|
|
aa9206381d | ||
|
|
d6d9af65fb | ||
|
|
a3f70e7977 | ||
|
|
0057f093db | ||
|
|
6bbdba7a21 | ||
|
|
6a175379fb | ||
|
|
85c21fa8e3 | ||
|
|
bc8c823045 | ||
|
|
9935da8a6f | ||
|
|
c39b6c3fe7 | ||
|
|
c47a6f92c5 | ||
|
|
778628da30 | ||
|
|
ba0ca0cc65 | ||
|
|
fba3828479 | ||
|
|
c8dd4f26f7 | ||
|
|
16a62625b3 | ||
|
|
de5f6d5fce | ||
|
|
98a87d099b | ||
|
|
a6f3c95684 | ||
|
|
75e39e7ef5 | ||
|
|
77b2b26a7a | ||
|
|
1680eeb80d | ||
|
|
9a9b4a1874 | ||
|
|
0e1fee352f | ||
|
|
1136494fc6 | ||
|
|
9b3e5cb444 | ||
|
|
f13dc16af5 | ||
|
|
145a944860 | ||
|
|
dd127ff3e7 | ||
|
|
b0fb474e1d | ||
|
|
a1a94ec0d1 | ||
|
|
678f8bc77f | ||
|
|
41968546d1 | ||
|
|
b51b78f4e4 | ||
|
|
f76283ebfe | ||
|
|
e59bf9ab97 | ||
|
|
b2f66241d5 | ||
|
|
cfdbc851a0 | ||
|
|
6ccebdc978 | ||
|
|
df53040339 | ||
|
|
42dc5b14b0 | ||
|
|
e2538abcb1 | ||
|
|
1697293f12 | ||
|
|
d60e1e8a05 | ||
|
|
d157756d94 | ||
|
|
ea1914a248 | ||
|
|
85087ce04a | ||
|
|
e09127eadf | ||
|
|
e1095962a1 | ||
|
|
eabd1150b0 | ||
|
|
93501248cd | ||
|
|
3a945c8c10 | ||
|
|
54f6851dd9 | ||
|
|
3cef7a7911 | ||
|
|
1cd2fb5b18 | ||
|
|
ba3ca47f8c | ||
|
|
98763271a4 | ||
|
|
063842edc4 | ||
|
|
2453a4a4f1 | ||
|
|
5a8adc5344 | ||
|
|
8b94ac8fca | ||
|
|
c1e12b8746 | ||
|
|
44c1438541 | ||
|
|
c2a857f4d6 | ||
|
|
9d620f8137 | ||
|
|
7c2327b743 | ||
|
|
d91abd5e45 | ||
|
|
4699b46744 | ||
|
|
8f514bd782 | ||
|
|
69ffdb7665 | ||
|
|
f9c5386e7a | ||
|
|
55273b5340 | ||
|
|
04f5ca2647 | ||
|
|
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 | ||
|
|
bf43fd1274 | ||
|
|
cd7c504c76 | ||
|
|
96ba589d4d | ||
|
|
9ffe4f2c25 | ||
|
|
af95f77134 | ||
|
|
8803c618b1 | ||
|
|
78f1c45e13 | ||
|
|
287addb9fd | ||
|
|
cf47573298 | ||
|
|
96ba96ca69 | ||
|
|
da998eb469 | ||
|
|
e75a4b95cc | ||
|
|
d1a0f1e3ca | ||
|
|
344085f4ef | ||
|
|
d37a6a0b2d | ||
|
|
d7fc916d20 | ||
|
|
80a4757242 | ||
|
|
658048ff2d | ||
|
|
0587223da8 | ||
|
|
2d1b81dc20 | ||
|
|
0bd16fb81a | ||
|
|
0c1fec5d1e | ||
|
|
ee16eb7fde | ||
|
|
5c9aeab6b4 | ||
|
|
5c7cae9ab0 | ||
|
|
93fa6cf875 | ||
|
|
5b7bee977b | ||
|
|
8018dac396 | ||
|
|
85ab317c6c | ||
|
|
6b0fb1721b | ||
|
|
fdcdcbb85f | ||
|
|
4e2095d251 | ||
|
|
51275b3a65 | ||
|
|
8d480cefb9 | ||
|
|
3e7f9039c4 | ||
|
|
49828baae3 | ||
|
|
348b02e4f8 | ||
|
|
a73e1185dc | ||
|
|
441dceb731 | ||
|
|
57c4f9e103 | ||
|
|
2741fc2683 | ||
|
|
82f184c848 | ||
|
|
868c023dbd | ||
|
|
e7c357ab7f | ||
|
|
9e1a5008ed | ||
|
|
4a042510d8 | ||
|
|
59b3fe7c3a | ||
|
|
b54ddeadf4 | ||
|
|
a6557121a0 | ||
|
|
2dad6262cf | ||
|
|
af1eb58bb8 | ||
|
|
4e0a507ba0 | ||
|
|
7d39aacd72 | ||
|
|
a8ae8a6171 | ||
|
|
9c99333759 | ||
|
|
17a2aa42e9 | ||
|
|
231f671400 | ||
|
|
ec6ffb0f53 | ||
|
|
221eba11dd | ||
|
|
ad40a9225e | ||
|
|
1544b09c82 | ||
|
|
1d08b3e729 | ||
|
|
8a150568ec | ||
|
|
00b20b2158 | ||
|
|
25e8e1b5fe | ||
|
|
bf7c840ea3 | ||
|
|
78a5838aa1 | ||
|
|
cbef05838d | ||
|
|
4dcf260059 | ||
|
|
2cf973809a | ||
|
|
65974e15ba | ||
|
|
e885d2c221 | ||
|
|
fe61a404d6 | ||
|
|
97ac4bbd4f | ||
|
|
dd29b72295 | ||
|
|
23fa65cee0 | ||
|
|
adc88d1fb9 | ||
|
|
2908c7499c | ||
|
|
ef4c2bbc98 | ||
|
|
dc6b32a154 | ||
|
|
76f593e4bb | ||
|
|
15b991a48e | ||
|
|
f3c93855bb | ||
|
|
f033230548 | ||
|
|
702d0790bc | ||
|
|
599aa42cd8 | ||
|
|
95afaf3eac | ||
|
|
2953e2c522 | ||
|
|
bf450b7d68 | ||
|
|
4e6b6d97ce | ||
|
|
17b2245033 | ||
|
|
7b7c49d7ad | ||
|
|
1522d11df0 | ||
|
|
7eecf69178 | ||
|
|
6aadd00e72 | ||
|
|
e036f5360c | ||
|
|
384dfb5f46 | ||
|
|
8c2aae2ddc | ||
|
|
89bd2a4a07 | ||
|
|
511941c714 | ||
|
|
e58220e2c4 | ||
|
|
477e3a706b | ||
|
|
9ba8949a2e | ||
|
|
9b7d3af03d | ||
|
|
02711a73ed | ||
|
|
25d418e96b | ||
|
|
10430f8142 | ||
|
|
8aba97b577 | ||
|
|
8a0771e5f4 | ||
|
|
9c6c977314 | ||
|
|
8fe5b2369a | ||
|
|
dc6c87b58d | ||
|
|
ef4e19002b | ||
|
|
e6ee5fc6b8 | ||
|
|
38c5388e00 | ||
|
|
519a76a171 | ||
|
|
eefc98a68e | ||
|
|
d0dc8cf726 | ||
|
|
b19c935da1 | ||
|
|
0ade37f14f | ||
|
|
91be4c4643 | ||
|
|
d2b62e2d21 | ||
|
|
267961434c | ||
|
|
0bfe98d306 | ||
|
|
bfa644e7a7 | ||
|
|
0ef1558803 | ||
|
|
9dad1af960 | ||
|
|
407f4dbbae | ||
|
|
7052fe6225 | ||
|
|
49357790f1 | ||
|
|
694219e497 | ||
|
|
af240d38e0 | ||
|
|
9b70ace180 | ||
|
|
a3dbec62dc | ||
|
|
e0a53144db | ||
|
|
b6cc15e9ab | ||
|
|
fe26168a07 | ||
|
|
25de332492 | ||
|
|
2d0f10c79f | ||
|
|
ebb9dd1aaf | ||
|
|
d4c4441cb6 | ||
|
|
91bfab30e0 | ||
|
|
74ea803651 | ||
|
|
a32811942e | ||
|
|
0908e509a1 | ||
|
|
ad14226c5c | ||
|
|
3fcc032547 | ||
|
|
e077995332 | ||
|
|
c9ebc0191d | ||
|
|
db0ebeebee | ||
|
|
70dc2a3009 | ||
|
|
b52de9b197 | ||
|
|
696ec6756d | ||
|
|
c2de6e3f3d | ||
|
|
a5638bdba1 | ||
|
|
697c92ae77 | ||
|
|
c4da682e84 | ||
|
|
33ee39dcce | ||
|
|
bb8e4bd737 | ||
|
|
7a96772a9b | ||
|
|
9b07aa17e4 | ||
|
|
90c59d5b8e | ||
|
|
fd3d5b66e9 | ||
|
|
d97346be6c | ||
|
|
9d13bcfe11 | ||
|
|
724ee62246 | ||
|
|
26e8f02e85 | ||
|
|
b3ff3d2466 | ||
|
|
9c3882e91f | ||
|
|
32a7657c4f | ||
|
|
54617bf634 | ||
|
|
61a00b3965 | ||
|
|
0214ffd158 | ||
|
|
1919f7b2a7 | ||
|
|
c2f4e00314 | ||
|
|
3adfa16db8 | ||
|
|
90fcffdf2a | ||
|
|
0ca84a790b | ||
|
|
04802fbb15 | ||
|
|
587c2cc8e2 | ||
|
|
1c8899ceae | ||
|
|
21534d1c0b | ||
|
|
088009fe4a | ||
|
|
90ac6f331e | ||
|
|
e80e4afa48 | ||
|
|
b73295d180 | ||
|
|
186a3cb6df | ||
|
|
b6fba56291 | ||
|
|
f52fee8254 | ||
|
|
f1061cfd31 | ||
|
|
9a9358bc78 | ||
|
|
8579332cdf | ||
|
|
9dc9edbbee | ||
|
|
2980bb0320 | ||
|
|
084798bd1b | ||
|
|
1c27b9b712 | ||
|
|
129ec8472c | ||
|
|
bb91dc98de | ||
|
|
724162f37f | ||
|
|
3244b102ad | ||
|
|
c8966d22ba | ||
|
|
6669d49636 | ||
|
|
3b480dabdb | ||
|
|
3e69281d61 | ||
|
|
1b04386b01 | ||
|
|
1ca736692d | ||
|
|
4dc4795cb7 | ||
|
|
bcc33362b8 | ||
|
|
ba0b5f929f | ||
|
|
89c960c455 | ||
|
|
14178fcd14 | ||
|
|
5e0fe6d897 | ||
|
|
53ef26dabd | ||
|
|
3db5f2a67f | ||
|
|
13d0e2a5bf | ||
|
|
c3085ae34f | ||
|
|
ce2ec8047e | ||
|
|
335cb7016e | ||
|
|
7a7b050615 | ||
|
|
6ff7ae800a | ||
|
|
2159773723 | ||
|
|
ab3a015d61 | ||
|
|
3142387e45 | ||
|
|
051325e10f | ||
|
|
199d5d57d5 | ||
|
|
b96795c517 | ||
|
|
64ba96daf2 | ||
|
|
14b17d86e5 | ||
|
|
90d5f27026 | ||
|
|
16386b8ddc | ||
|
|
cbef21b9ad | ||
|
|
cec44e3668 | ||
|
|
f09f1e7f85 | ||
|
|
95910bc6cb | ||
|
|
cc488ccff0 | ||
|
|
37e129bfb9 | ||
|
|
6adc923bcb | ||
|
|
065470cecb | ||
|
|
260989bda6 | ||
|
|
64b6e0fd56 | ||
|
|
8f45718b75 | ||
|
|
e66bb7a14b | ||
|
|
8bfe32eeef | ||
|
|
e85c1bbc0d | ||
|
|
f99bf0d000 | ||
|
|
db24a2251f | ||
|
|
fcb3747690 | ||
|
|
dcc27a7447 | ||
|
|
bea39bc613 | ||
|
|
546493ba45 | ||
|
|
dda4928693 | ||
|
|
7d144dd076 | ||
|
|
73e0700ea3 | ||
|
|
3fc36cf798 | ||
|
|
dbc43b445b | ||
|
|
638fcd393a | ||
|
|
7b5f419713 | ||
|
|
253fbad3db | ||
|
|
522de3d4b7 | ||
|
|
dc9ae67657 | ||
|
|
fccac8ed74 | ||
|
|
24c895084e | ||
|
|
16fbfdecb5 | ||
|
|
b79e281074 | ||
|
|
93ac380fd6 | ||
|
|
46066d4cac | ||
|
|
c13cf4f29c | ||
|
|
a4f06a9e1e | ||
|
|
cbc5fc8d08 | ||
|
|
0a27c0b6e4 | ||
|
|
f348a20035 | ||
|
|
bdb98b487f | ||
|
|
2cb6402189 | ||
|
|
861bb7a00a | ||
|
|
43d5458a25 | ||
|
|
fe491e4a7d | ||
|
|
9d1b979318 | ||
|
|
c1794dd0ca | ||
|
|
8f7d8b1cba | ||
|
|
8ebb8a04fa | ||
|
|
ef6435a02a | ||
|
|
5cbe0a8230 | ||
|
|
dcef6b556c | ||
|
|
c07a636db2 | ||
|
|
a6be95fe33 | ||
|
|
14149aa6b1 | ||
|
|
ae901219fb | ||
|
|
6d9600d132 | ||
|
|
ccc55562cd | ||
|
|
67d9ae881f | ||
|
|
61e0525ee8 | ||
|
|
363519db02 | ||
|
|
4bc179bd2a | ||
|
|
76debda76e | ||
|
|
b4eabe19cb | ||
|
|
971b75860f | ||
|
|
5a926bf169 | ||
|
|
d34f37c563 | ||
|
|
6035a01019 | ||
|
|
c880f71dc8 | ||
|
|
13422ef7ce | ||
|
|
84e2efd42c | ||
|
|
113d26937d | ||
|
|
34606415d7 | ||
|
|
6b9c1f0a22 | ||
|
|
132cc0e131 | ||
|
|
5926369a56 | ||
|
|
ff068d374f | ||
|
|
4132d6ff61 | ||
|
|
1f10199e64 | ||
|
|
e97704b37f | ||
|
|
4ae81a3b0b | ||
|
|
f4ec9a8ec1 | ||
|
|
711037b619 | ||
|
|
b32c9f1724 | ||
|
|
be132c531e | ||
|
|
fb8826caf4 | ||
|
|
adff60b118 | ||
|
|
8f863bf19b | ||
|
|
fd61207709 | ||
|
|
8c1a9f460d | ||
|
|
f6d4a315c7 | ||
|
|
fc1a2a6112 | ||
|
|
13547781d2 | ||
|
|
d375d1abc9 | ||
|
|
5e4f31f39e | ||
|
|
dba186347c | ||
|
|
7988274d61 | ||
|
|
b9eeab06a1 | ||
|
|
c0f7d5ab44 | ||
|
|
60f81fb89d | ||
|
|
49bc96dc7e | ||
|
|
9922382581 | ||
|
|
4aa52d2f2e | ||
|
|
9393192036 | ||
|
|
3cdbc4cb83 | ||
|
|
0c7741120a | ||
|
|
e529438c7e | ||
|
|
aebfbba20e | ||
|
|
85cc86346c | ||
|
|
b20e095683 | ||
|
|
b4d7f05165 | ||
|
|
46a12754e9 | ||
|
|
411b2a0acc | ||
|
|
7255ccbdaa | ||
|
|
45dc8b949d | ||
|
|
10e3a5afc4 | ||
|
|
303aa79ffb | ||
|
|
35f3be9296 | ||
|
|
695954bdb0 | ||
|
|
d29b3ee893 | ||
|
|
d9cecb35cb | ||
|
|
71dd6c6333 | ||
|
|
56f13d314a | ||
|
|
b628d67961 | ||
|
|
8fe05c9119 | ||
|
|
e8e6a9bc5c |
2
.github/ISSUE_TEMPLATE/bug.md
vendored
2
.github/ISSUE_TEMPLATE/bug.md
vendored
@@ -11,7 +11,7 @@ Operating system:
|
||||
Java version:
|
||||
Minecraft version:
|
||||
Baritone version:
|
||||
Forge mods (if used):
|
||||
Other mods (if used):
|
||||
|
||||
## Exception, error or logs
|
||||
Please find your `latest.log` or `debug.log` in this folder and attach it to the issue
|
||||
|
||||
16
.github/workflows/gradle_build.yml
vendored
16
.github/workflows/gradle_build.yml
vendored
@@ -13,12 +13,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '16'
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
@@ -31,15 +31,15 @@ jobs:
|
||||
|
||||
- name: Build (forge) with Gradle
|
||||
run: ./gradlew build -Pbaritone.forge_build -Ploom.platform=forge
|
||||
|
||||
|
||||
- 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
|
||||
|
||||
10
.github/workflows/run_tests.yml
vendored
10
.github/workflows/run_tests.yml
vendored
@@ -11,12 +11,12 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Set up JDK 16
|
||||
uses: actions/setup-java@v2
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up JDK 17
|
||||
uses: actions/setup-java@v3
|
||||
with:
|
||||
java-version: '16'
|
||||
distribution: 'adopt'
|
||||
java-version: '17'
|
||||
distribution: 'temurin'
|
||||
|
||||
- name: Grant execute permission for gradlew
|
||||
run: chmod +x gradlew
|
||||
|
||||
6
.gitignore
vendored
6
.gitignore
vendored
@@ -21,6 +21,12 @@ classes/
|
||||
*.iws
|
||||
/logs/
|
||||
|
||||
# Eclipse Files
|
||||
.classpath
|
||||
.project
|
||||
.settings/
|
||||
baritone_Client.launch
|
||||
|
||||
# Copyright Files
|
||||
!/.idea/copyright/Baritone.xml
|
||||
!/.idea/copyright/profiles_settings.xml
|
||||
|
||||
@@ -5,7 +5,7 @@ ENV DEBIAN_FRONTEND noninteractive
|
||||
RUN apt update -y
|
||||
|
||||
RUN apt install \
|
||||
openjdk-16-jdk \
|
||||
openjdk-17-jdk \
|
||||
--assume-yes
|
||||
|
||||
COPY . /code
|
||||
|
||||
98
README.md
98
README.md
@@ -1,49 +1,71 @@
|
||||
# Baritone
|
||||
[](http://hits.dwyl.com/cabaletta/baritone/)
|
||||
[](https://github.com/cabaletta/baritone/releases/)
|
||||
<p align="center">
|
||||
<a href="https://github.com/cabaletta/baritone/releases/"><img src="https://img.shields.io/github/downloads/cabaletta/baritone/total.svg" alt="GitHub All Releases"/></a>
|
||||
</p>
|
||||
|
||||
[](https://travis-ci.com/cabaletta/baritone/)
|
||||
[](https://github.com/cabaletta/baritone/releases/)
|
||||
[](LICENSE)
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
[](https://github.com/cabaletta/baritone/tree/master/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.13.2/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.14.4/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.15.2/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.16.4/)
|
||||
[](https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md)
|
||||
[](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle)
|
||||
[](https://github.com/cabaletta/baritone/issues/)
|
||||
[](https://github.com/cabaletta/baritone/issues/)
|
||||
[](https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed)
|
||||
[](https://github.com/cabaletta/baritone/pulls/)
|
||||

|
||||

|
||||

|
||||
[](https://github.com/cabaletta/baritone/graphs/contributors/)
|
||||
[](https://github.com/cabaletta/baritone/commit/)
|
||||
[](https://impactclient.net/)
|
||||
[](https://github.com/kami-blue/client)
|
||||
[](https://github.com/fr1kin/ForgeHax/)
|
||||
[](https://gitlab.com/emc-mods-indrit/baritone_api)
|
||||
[](https://rootnet.dev/)
|
||||
[](https://futureclient.net/)
|
||||
[](https://rusherhack.org/)
|
||||
[](http://forthebadge.com/)
|
||||
[](http://forthebadge.com/)
|
||||
<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>
|
||||
</p>
|
||||
|
||||
A Minecraft pathfinder bot.
|
||||
<p align="center">
|
||||
<a href="https://travis-ci.com/cabaletta/baritone/"><img src="https://travis-ci.com/cabaletta/baritone.svg?branch=master" alt="Build Status"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/releases/"><img src="https://img.shields.io/github/release/cabaletta/baritone.svg" alt="Release"/></a>
|
||||
<a href="LICENSE"><img src="https://img.shields.io/badge/license-LGPL--3.0%20with%20anime%20exception-green.svg" alt="License"/></a>
|
||||
<a href="https://www.codacy.com/gh/cabaletta/baritone/dashboard?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade"><img src="https://app.codacy.com/project/badge/Grade/cadab857dab049438b6e28b3cfc5570e" alt="Codacy Badge"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg?style=flat" alt="Code of Conduct"/></a>
|
||||
<a href="https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle"><img src="https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle" alt="Known Vulnerabilities"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/issues/"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="Contributions welcome"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/issues/"><img src="https://img.shields.io/github/issues/cabaletta/baritone.svg" alt="Issues"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/cabaletta/baritone.svg" alt="GitHub issues-closed"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/pulls/"><img src="https://img.shields.io/github/issues-pr/cabaletta/baritone.svg" alt="Pull Requests"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/graphs/contributors/"><img src="https://img.shields.io/github/contributors/cabaletta/baritone.svg" alt="GitHub contributors"/></a>
|
||||
<a href="https://github.com/cabaletta/baritone/commit/"><img src="https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg" alt="GitHub commits"/></a>
|
||||
<img src="https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg" alt="Code size"/>
|
||||
<img src="https://img.shields.io/github/repo-size/cabaletta/baritone.svg" alt="GitHub repo size"/>
|
||||
<img src="https://tokei.rs/b1/github/cabaletta/baritone?category=code" alt="Lines of Code"/>
|
||||
</p>
|
||||
|
||||
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. [Tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa)
|
||||
<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/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>
|
||||
<a href="https://futureclient.net/"><img src="https://img.shields.io/badge/Future%20integration-v1.2.12%20%2F%20v1.3.6%20%2F%20v1.4.4-red" alt="Future integration"/></a>
|
||||
<a href="https://rusherhack.org/"><img src="https://img.shields.io/badge/RusherHack%20integration-v1.2.14-green" alt="RusherHack integration"/></a>
|
||||
</p>
|
||||
|
||||
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.14/baritone-api-forge-1.2.14.jar)**. Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
<p align="center">
|
||||
<a href="http://forthebadge.com/"><img src="https://forthebadge.com/images/badges/built-with-swag.svg" alt="forthebadge"/></a>
|
||||
<a href="http://forthebadge.com/"><img src="https://forthebadge.com/images/badges/mom-made-pizza-rolls.svg" alt="forthebadge"/></a>
|
||||
</p>
|
||||
|
||||
For 1.15.2, [click here](https://www.youtube.com/watch?v=j1qKtCZFURM) and see description. If you need Forge 1.15.2, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.5.3), follow the instructions, and get the `api-forge` jar.
|
||||
A Minecraft pathfinder bot.
|
||||
|
||||
For 1.16.4, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. If you need Forge 1.16.4, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.6.2) and get the `api-forge` jar.
|
||||
[**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.
|
||||
|
||||
[Tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa)
|
||||
|
||||
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.17/baritone-api-forge-1.2.17.jar)**. Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
|
||||
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)**.
|
||||
|
||||
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 through 1.16.4. 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).
|
||||
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).
|
||||
|
||||
Have committed at least once a day from Aug 1, 2018, to Aug 1, 2019.
|
||||
|
||||
@@ -75,7 +97,7 @@ jar.
|
||||
|
||||
Below is an example of basic usage for changing some settings, and then pathing to an X/Z goal.
|
||||
|
||||
```
|
||||
```java
|
||||
BaritoneAPI.getSettings().allowSprint.value = true;
|
||||
BaritoneAPI.getSettings().primaryTimeoutMS.value = 2000L;
|
||||
|
||||
|
||||
30
SETUP.md
30
SETUP.md
@@ -2,7 +2,7 @@
|
||||
|
||||
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone.
|
||||
|
||||
You can also use a custom version json for Minecraft, with the [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1) version or the [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1) version
|
||||
You can also use a custom version json for Minecraft, with the [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1) version or the [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1) version or the [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1) version.
|
||||
|
||||
Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
|
||||
@@ -11,9 +11,9 @@ These releases are not always completely up to date with latest features, and ar
|
||||
|
||||
Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases)
|
||||
|
||||
v1.2.* is for 1.12.2, v1.3.* is for 1.13.2
|
||||
v1.2.* is for 1.12.2, v1.3.* is for 1.13.2, v1.4.* is for 1.14.4, v1.5.* is for 1.15.2, v1.6.* is for 1.16.5, v1.7.* is for 1.17.1, v1.8.* is for 1.18.1
|
||||
|
||||
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
|
||||
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by that public keys of `checksums.txt`.
|
||||
|
||||
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
|
||||
|
||||
@@ -22,20 +22,16 @@ The build is fully deterministic and reproducible, and you can verify Travis did
|
||||
|
||||
Building Baritone will result in 5 artifacts created in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
|
||||
|
||||
**The Forge release can simply be added as a Forge mod.**
|
||||
**The Forge and Fabric releases can simply be added as a Forge/Fabric mods.**
|
||||
|
||||
If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar`
|
||||
|
||||
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
|
||||
- **Forge API**: Same as API, but packaged for Forge. This should be used where another mod has a Baritone integration.
|
||||
- **Forge/Fabric API**: Same as API, but packaged for Forge/Fabric. This should be used where another mod has a Baritone integration.
|
||||
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
|
||||
- **Forge Standalone**: Same as Standalone, but packaged for Forge. This should be used when Baritone is your only Forge mod, or none of your other Forge mods integrate with Baritone.
|
||||
- **Forge/Fabric Standalone**: Same as Standalone, but packaged for Forge/Fabric. This should be used when Baritone is your only Forge/Fabric mod, or none of your other Forge/Fabric mods integrate with Baritone.
|
||||
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
|
||||
|
||||
## More Info
|
||||
To replace out Impact 4.5's Baritone build with a customized one, build Baritone as above then copy & **rename** `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.2/baritone-api-1.2.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.5/1.12.2-Impact_4.5.json`, find the line `"name": "cabaletta:baritone-api:1.2"`, remove the comma from the end, and **entirely remove the NEXT line** (starts with `"url"`). **Restart your launcher** then load as normal.
|
||||
|
||||
You can verify whether or not it worked by running `.b version` in chat (only valid in Impact). It should print out the version that you downloaded. Note: The version that comes with 4.5 is `v1.2.3`.
|
||||
- **Forge/Fabric Unoptimized**: Same as Unoptimized, but packaged for Forge/Fabric.
|
||||
|
||||
## Build it yourself
|
||||
- Clone or download Baritone
|
||||
@@ -47,13 +43,13 @@ You can verify whether or not it worked by running `.b version` in chat (only va
|
||||
## 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.
|
||||
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, it might not work because the Java distributions above JDK 8 using may not have the needed javax classes.
|
||||
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 8 download: https://openjdk.java.net/install/
|
||||
Open JDK download: https://openjdk.java.net/install/
|
||||
#### macOS guide
|
||||
In order to get JDK 8, Try running the following command:
|
||||
`% /usr/libexec/java_home -V`
|
||||
@@ -89,6 +85,12 @@ 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:
|
||||
|
||||
```
|
||||
|
||||
18
USAGE.md
18
USAGE.md
@@ -32,13 +32,13 @@ Watch this [showcase video](https://youtu.be/CZkLXWo4Fg4)!
|
||||
|
||||
To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`.
|
||||
|
||||
Some common examples:
|
||||
Commands in Baritone:
|
||||
- `thisway 1000` then `path` to go in the direction you're facing for a thousand blocks
|
||||
- `goal x y z` or `goal x z` or `goal y`, then `path` to set a goal to a certain coordinate then path to it
|
||||
- `goto x y z` or `goto x z` or `goto y` to go to a certain coordinate (in a single step, starts going immediately)
|
||||
- `goal` to set the goal to your player's feet
|
||||
- `goal clear` to clear the goal
|
||||
- `cancel` or `stop` to stop everything
|
||||
- `cancel` or `stop` to stop everything, `forcecancel` is also an option
|
||||
- `goto portal` or `goto ender_chest` or `goto block_type` to go to a block. (in Impact, `.goto` is an alias for `.b goto` for the most part)
|
||||
- `mine diamond_ore iron_ore` to mine diamond ore or iron ore (turn on the setting `legitMine` to only mine ores that it can actually see. It will explore randomly around y=11 until it finds them.) An amount of blocks can also be specified, for example, `mine 64 diamond_ore`.
|
||||
- `click` to click your destination on the screen. Right click path to on top of the block, left click to path into it (either at foot level or eye level), and left click and drag to select an area (`#help sel` to see what you can do with that selection).
|
||||
@@ -47,15 +47,23 @@ Some common examples:
|
||||
- `build` to build a schematic. `build blah.schematic` will load `schematics/blah.schematic` and build it with the origin being your player feet. `build blah.schematic x y z` to set the origin. Any of those can be relative to your player (`~ 69 ~-420` would build at x=player x, y=69, z=player z-420).
|
||||
- `schematica` to build the schematic that is currently open in schematica
|
||||
- `tunnel` to dig and make a tunnel, 1x2. It will only deviate from the straight line if necessary such as to avoid lava. For a dumber tunnel that is really just cleararea, you can `tunnel 3 2 100`, to clear an area 3 high, 2 wide, and 100 deep.
|
||||
- `farm` to automatically harvest, replant, or bone meal crops
|
||||
- `farm` to automatically harvest, replant, or bone meal crops. Use `farm <range>` or `farm <range> <waypoint>` to limit the max distance from the starting point or a waypoint.
|
||||
- `axis` to go to an axis or diagonal axis at y=120 (`axisHeight` is a configurable setting, defaults to 120).
|
||||
- `explore x z` to explore the world from the origin of x,z. Leave out x and z to default to player feet. This will continually path towards the closest chunk to the origin that it's never seen before. `explorefilter filter.json` with optional invert can be used to load in a list of chunks to load.
|
||||
- `invert` to invert the current goal and path. This gets as far away from it as possible, instead of as close as possible. For example, do `goal` then `invert` to run as far as possible from where you're standing at the start.
|
||||
- `come` tells Baritone to head towards your camera, useful when freecam doesn't move your player position.
|
||||
- `blacklist` will stop baritone from going to the closest block so it won't attempt to get to it.
|
||||
- `eta` to get information about the estimated time until the next segment and the goal, be aware that the ETA to your goal is really unprecise.
|
||||
- `proc` to view miscellaneous information about the process currently controlling Baritone.
|
||||
- `repack` to re-cache the chunks around you.
|
||||
- `gc` to call `System.gc()` which may free up some memory.
|
||||
- `render` to fix glitched chunk rendering without having to reload all of them.
|
||||
- `reloadall` to reload Baritone's world cache or `saveall` to save Baritone's world cache.
|
||||
- `find` to search through Baritone's cache and attempt to find the location of the block.
|
||||
- `surface` or `top` to tell Baritone to head towards the closest surface-like area, this can be the surface or highest available air space.
|
||||
- `version` to get the version of Baritone you're running
|
||||
- `damn` daniel
|
||||
|
||||
For the rest of the commands, you can take a look at the code [here](https://baritone.leijurv.com/baritone/api/Settings.html).
|
||||
|
||||
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#field.detail">here</a>.
|
||||
|
||||
There are about a hundred settings, but here are some fun / interesting / important ones that you might want to look at changing in normal usage of Baritone. The documentation for each can be found at the above links.
|
||||
|
||||
10
build.gradle
10
build.gradle
@@ -31,7 +31,7 @@ import baritone.gradle.task.ProguardTask
|
||||
|
||||
def compileType = project.hasProperty("baritone.fabric_build") ? "FABRIC" : project.hasProperty("baritone.forge_build") ? "FORGE" : "OFFICIAL"
|
||||
|
||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_16
|
||||
sourceCompatibility = targetCompatibility = JavaVersion.VERSION_17
|
||||
|
||||
compileJava {
|
||||
options.encoding = "UTF-8" // allow emoji in comments :^)
|
||||
@@ -95,7 +95,7 @@ dependencies {
|
||||
mappings loom.layered() {
|
||||
officialMojangMappings()
|
||||
//technically optional, but really helpful in dev:
|
||||
parchment("org.parchmentmc.data:parchment-1.17.1:2021.10.24@zip" as String)
|
||||
// parchment("org.parchmentmc.data:parchment-1.17.1:2021.10.24@zip" as String)
|
||||
}
|
||||
minecraft "com.mojang:minecraft:${project.minecraft_version}"
|
||||
if (!compileType.equals("FORGE")) {
|
||||
@@ -179,12 +179,12 @@ if (compileType.equals("OFFICIAL")) {
|
||||
|
||||
|
||||
task proguard(type: ProguardTask) {
|
||||
url 'https://downloads.sourceforge.net/project/proguard/v7.1.0-beta5/proguard-7.1.0-beta5.zip'
|
||||
extract 'proguard-7.1.0-beta5/lib/proguard.jar'
|
||||
url 'https://github.com/Guardsquare/proguard/releases/download/v7.2.0-beta2/proguard-7.2.0-beta2.zip'
|
||||
extract 'proguard-7.2.0-beta2/lib/proguard.jar'
|
||||
compType compileType
|
||||
}
|
||||
|
||||
task createDist(type: CreateDistTask, dependsOn: proguard)
|
||||
|
||||
|
||||
build.finalizedBy(createDist)
|
||||
build.finalizedBy(createDist)
|
||||
|
||||
@@ -83,7 +83,7 @@ class BaritoneGradleTask extends DefaultTask {
|
||||
|
||||
protected void verifyArtifacts() throws IllegalStateException {
|
||||
if (!Files.exists(this.artifactPath)) {
|
||||
throw new IllegalStateException("Artifact not found! Run build first!");
|
||||
throw new IllegalStateException("Artifact not found! Run build first! Missing file: " + this.artifactPath);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -237,8 +237,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) + "'");
|
||||
|
||||
template.add(2, "-libraryjars <java.home>/jmods/java.base.jmod(!**.jar;!module-info.class)");
|
||||
template.add(3, "-libraryjars <java.home>/jmods/java.desktop.jmod(!**.jar;!module-info.class)");
|
||||
@@ -312,9 +312,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
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
org.gradle.jvmargs=-Xmx2048M
|
||||
|
||||
mod_version=1.7.1
|
||||
mod_version=1.8.4
|
||||
maven_group=baritone
|
||||
archives_base_name=baritone
|
||||
|
||||
minecraft_version=1.17.1
|
||||
forge_version=1.17.1-37.0.69
|
||||
fabric_version=0.11.6
|
||||
minecraft_version=1.18.2
|
||||
forge_version=1.18.2-40.0.0
|
||||
fabric_version=0.13.1
|
||||
|
||||
# # un comment for forge debugging default (as opposed to fabric)
|
||||
# baritone.forge_build=true
|
||||
# loom.platform=forge
|
||||
# loom.platform=forge
|
||||
|
||||
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
BIN
gradle/wrapper/gradle-wrapper.jar
vendored
Binary file not shown.
2
gradle/wrapper/gradle-wrapper.properties
vendored
2
gradle/wrapper/gradle-wrapper.properties
vendored
@@ -1,5 +1,5 @@
|
||||
distributionBase=GRADLE_USER_HOME
|
||||
distributionPath=wrapper/dists
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.0.2-bin.zip
|
||||
distributionUrl=https\://services.gradle.org/distributions/gradle-7.3.1-bin.zip
|
||||
zipStoreBase=GRADLE_USER_HOME
|
||||
zipStorePath=wrapper/dists
|
||||
|
||||
53
gradlew
vendored
53
gradlew
vendored
@@ -1,5 +1,21 @@
|
||||
#!/usr/bin/env sh
|
||||
|
||||
#
|
||||
# Copyright 2015 the original author or authors.
|
||||
#
|
||||
# Licensed under the Apache License, Version 2.0 (the "License");
|
||||
# you may not use this file except in compliance with the License.
|
||||
# You may obtain a copy of the License at
|
||||
#
|
||||
# https://www.apache.org/licenses/LICENSE-2.0
|
||||
#
|
||||
# Unless required by applicable law or agreed to in writing, software
|
||||
# distributed under the License is distributed on an "AS IS" BASIS,
|
||||
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
# See the License for the specific language governing permissions and
|
||||
# limitations under the License.
|
||||
#
|
||||
|
||||
##############################################################################
|
||||
##
|
||||
## Gradle start up script for UN*X
|
||||
@@ -28,7 +44,7 @@ APP_NAME="Gradle"
|
||||
APP_BASE_NAME=`basename "$0"`
|
||||
|
||||
# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
DEFAULT_JVM_OPTS=""
|
||||
DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
|
||||
|
||||
# Use the maximum available, or set MAX_FD != -1 to use that value.
|
||||
MAX_FD="maximum"
|
||||
@@ -66,6 +82,7 @@ esac
|
||||
|
||||
CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
|
||||
|
||||
|
||||
# Determine the Java command to use to start the JVM.
|
||||
if [ -n "$JAVA_HOME" ] ; then
|
||||
if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
|
||||
@@ -109,10 +126,11 @@ if $darwin; then
|
||||
GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
|
||||
fi
|
||||
|
||||
# For Cygwin, switch paths to Windows format before running java
|
||||
if $cygwin ; then
|
||||
# For Cygwin or MSYS, switch paths to Windows format before running java
|
||||
if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
|
||||
APP_HOME=`cygpath --path --mixed "$APP_HOME"`
|
||||
CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
|
||||
|
||||
JAVACMD=`cygpath --unix "$JAVACMD"`
|
||||
|
||||
# We build the pattern for arguments to be converted via cygpath
|
||||
@@ -138,19 +156,19 @@ if $cygwin ; then
|
||||
else
|
||||
eval `echo args$i`="\"$arg\""
|
||||
fi
|
||||
i=$((i+1))
|
||||
i=`expr $i + 1`
|
||||
done
|
||||
case $i in
|
||||
(0) set -- ;;
|
||||
(1) set -- "$args0" ;;
|
||||
(2) set -- "$args0" "$args1" ;;
|
||||
(3) set -- "$args0" "$args1" "$args2" ;;
|
||||
(4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
(5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
(6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
(7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
(8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
(9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
0) set -- ;;
|
||||
1) set -- "$args0" ;;
|
||||
2) set -- "$args0" "$args1" ;;
|
||||
3) set -- "$args0" "$args1" "$args2" ;;
|
||||
4) set -- "$args0" "$args1" "$args2" "$args3" ;;
|
||||
5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
|
||||
6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
|
||||
7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
|
||||
8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
|
||||
9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
|
||||
esac
|
||||
fi
|
||||
|
||||
@@ -159,14 +177,9 @@ save () {
|
||||
for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
|
||||
echo " "
|
||||
}
|
||||
APP_ARGS=$(save "$@")
|
||||
APP_ARGS=`save "$@"`
|
||||
|
||||
# Collect all arguments for the java command, following the shell quoting and substitution rules
|
||||
eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
|
||||
|
||||
# by default we should be in the correct project dir, but when run from Finder on Mac, the cwd is wrong
|
||||
if [ "$(uname)" = "Darwin" ] && [ "$HOME" = "$PWD" ]; then
|
||||
cd "$(dirname "$0")"
|
||||
fi
|
||||
|
||||
exec "$JAVACMD" "$@"
|
||||
|
||||
43
gradlew.bat
vendored
43
gradlew.bat
vendored
@@ -1,3 +1,19 @@
|
||||
@rem
|
||||
@rem Copyright 2015 the original author or authors.
|
||||
@rem
|
||||
@rem Licensed under the Apache License, Version 2.0 (the "License");
|
||||
@rem you may not use this file except in compliance with the License.
|
||||
@rem You may obtain a copy of the License at
|
||||
@rem
|
||||
@rem https://www.apache.org/licenses/LICENSE-2.0
|
||||
@rem
|
||||
@rem Unless required by applicable law or agreed to in writing, software
|
||||
@rem distributed under the License is distributed on an "AS IS" BASIS,
|
||||
@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
@rem See the License for the specific language governing permissions and
|
||||
@rem limitations under the License.
|
||||
@rem
|
||||
|
||||
@if "%DEBUG%" == "" @echo off
|
||||
@rem ##########################################################################
|
||||
@rem
|
||||
@@ -13,15 +29,18 @@ if "%DIRNAME%" == "" set DIRNAME=.
|
||||
set APP_BASE_NAME=%~n0
|
||||
set APP_HOME=%DIRNAME%
|
||||
|
||||
@rem Resolve any "." and ".." in APP_HOME to make it shorter.
|
||||
for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
|
||||
|
||||
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
|
||||
set DEFAULT_JVM_OPTS=
|
||||
set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
|
||||
|
||||
@rem Find java.exe
|
||||
if defined JAVA_HOME goto findJavaFromJavaHome
|
||||
|
||||
set JAVA_EXE=java.exe
|
||||
%JAVA_EXE% -version >NUL 2>&1
|
||||
if "%ERRORLEVEL%" == "0" goto init
|
||||
if "%ERRORLEVEL%" == "0" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
|
||||
@@ -35,7 +54,7 @@ goto fail
|
||||
set JAVA_HOME=%JAVA_HOME:"=%
|
||||
set JAVA_EXE=%JAVA_HOME%/bin/java.exe
|
||||
|
||||
if exist "%JAVA_EXE%" goto init
|
||||
if exist "%JAVA_EXE%" goto execute
|
||||
|
||||
echo.
|
||||
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
|
||||
@@ -45,28 +64,14 @@ echo location of your Java installation.
|
||||
|
||||
goto fail
|
||||
|
||||
:init
|
||||
@rem Get command-line arguments, handling Windows variants
|
||||
|
||||
if not "%OS%" == "Windows_NT" goto win9xME_args
|
||||
|
||||
:win9xME_args
|
||||
@rem Slurp the command line arguments.
|
||||
set CMD_LINE_ARGS=
|
||||
set _SKIP=2
|
||||
|
||||
:win9xME_args_slurp
|
||||
if "x%~1" == "x" goto execute
|
||||
|
||||
set CMD_LINE_ARGS=%*
|
||||
|
||||
:execute
|
||||
@rem Setup the command line
|
||||
|
||||
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
|
||||
|
||||
|
||||
@rem Execute Gradle
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
|
||||
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
|
||||
|
||||
:end
|
||||
@rem End local scope for the variables with windows NT shell
|
||||
|
||||
5
scripts/proguard.pro
vendored
5
scripts/proguard.pro
vendored
@@ -1,5 +1,6 @@
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
-keepattributes InnerClasses
|
||||
|
||||
-optimizationpasses 5
|
||||
-verbose
|
||||
@@ -27,6 +28,7 @@
|
||||
-keep class baritone.api.IBaritoneProvider
|
||||
|
||||
-keep class baritone.api.utils.MyChunkPos { *; } # even in standalone we need to keep this for gson reflect
|
||||
-keepname class baritone.api.utils.BlockOptionalMeta # this name is exposed to the user, so we need to keep it in all builds
|
||||
|
||||
# Keep any class or member annotated with @KeepName so we dont have to put everything in the script
|
||||
-keep,allowobfuscation @interface baritone.KeepName
|
||||
@@ -45,9 +47,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.**
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main'
|
||||
# methods.
|
||||
|
||||
@@ -37,4 +37,6 @@ pluginManagement {
|
||||
}
|
||||
mavenCentral()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
rootProject.name = 'baritone'
|
||||
|
||||
@@ -17,11 +17,15 @@
|
||||
|
||||
package baritone.api;
|
||||
|
||||
import baritone.api.utils.NotificationHelper;
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.TypeUtils;
|
||||
import baritone.api.utils.gui.BaritoneToast;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
@@ -31,6 +35,7 @@ import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.BiConsumer;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
@@ -45,6 +50,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> allowBreak = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Blocks that baritone will be allowed to break even with allowBreak set to false
|
||||
*/
|
||||
public final Setting<List<Block>> allowBreakAnyway = new Setting<>(new ArrayList<>());
|
||||
|
||||
/**
|
||||
* Allow Baritone to sprint
|
||||
*/
|
||||
@@ -69,9 +79,9 @@ public final class Settings {
|
||||
public final Setting<Boolean> assumeExternalAutoTool = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* If this setting is on, no auto tool will occur at all, not at calculation time nor execution time
|
||||
* Automatically select the best available tool
|
||||
*/
|
||||
public final Setting<Boolean> disableAutoTool = new Setting<>(false);
|
||||
public final Setting<Boolean> autoTool = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* It doesn't actually take twenty ticks to place a block, this cost is so high
|
||||
@@ -98,6 +108,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.
|
||||
@@ -107,6 +124,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);
|
||||
|
||||
@@ -186,6 +205,13 @@ 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
|
||||
));
|
||||
|
||||
/**
|
||||
* blocks that baritone shouldn't break, but can if it needs to.
|
||||
*/
|
||||
public final Setting<List<Block>> blocksToAvoidBreaking = new Setting<>(new ArrayList<>(Arrays.asList( // TODO can this be a HashSet or ImmutableSet?
|
||||
Blocks.CRAFTING_TABLE,
|
||||
Blocks.FURNACE,
|
||||
@@ -193,6 +219,11 @@ public final class Settings {
|
||||
Blocks.TRAPPED_CHEST
|
||||
)));
|
||||
|
||||
/**
|
||||
* this multiplies the break speed, if set above 1 it's "encourage breaking" instead
|
||||
*/
|
||||
public final Setting<Double> avoidBreakingMultiplier = new Setting<>(.1);
|
||||
|
||||
/**
|
||||
* A list of blocks to be treated as if they're air.
|
||||
* <p>
|
||||
@@ -202,6 +233,40 @@ public final class Settings {
|
||||
|
||||
)));
|
||||
|
||||
/**
|
||||
* A list of blocks to be treated as correct.
|
||||
* <p>
|
||||
* If a schematic asks for any block on this list at a certain position, it will be treated as correct, regardless of what it currently is.
|
||||
*/
|
||||
public final Setting<List<Block>> buildSkipBlocks = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||
|
||||
)));
|
||||
|
||||
/**
|
||||
* A mapping of blocks to blocks treated as correct in their position
|
||||
* <p>
|
||||
* If a schematic asks for a block on this mapping, all blocks on the mapped list will be accepted at that location as well
|
||||
* <p>
|
||||
* Syntax same as <a href="https://baritone.leijurv.com/baritone/api/Settings.html#buildSubstitutes">buildSubstitutes</a>
|
||||
*/
|
||||
public final Setting<Map<Block, List<Block>>> buildValidSubstitutes = new Setting<>(new HashMap<>());
|
||||
|
||||
/**
|
||||
* A mapping of blocks to blocks to be built instead
|
||||
* <p>
|
||||
* If a schematic asks for a block on this mapping, Baritone will place the first placeable block in the mapped list
|
||||
* <p>
|
||||
* Usage Syntax:
|
||||
* <pre>
|
||||
* sourceblockA->blockToSubstituteA1,blockToSubstituteA2,...blockToSubstituteAN,sourceBlockB->blockToSubstituteB1,blockToSubstituteB2,...blockToSubstituteBN,...sourceBlockX->blockToSubstituteX1,blockToSubstituteX2...blockToSubstituteXN
|
||||
* </pre>
|
||||
* Example:
|
||||
* <pre>
|
||||
* stone->cobblestone,andesite,oak_planks->birch_planks,acacia_planks,glass
|
||||
* </pre>
|
||||
*/
|
||||
public final Setting<Map<Block, List<Block>>> buildSubstitutes = new Setting<>(new HashMap<>());
|
||||
|
||||
/**
|
||||
* A list of blocks to become air
|
||||
* <p>
|
||||
@@ -216,6 +281,17 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> buildIgnoreExisting = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* If this is true, the builder will ignore directionality of certain blocks like glazed terracotta.
|
||||
*/
|
||||
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>
|
||||
@@ -343,6 +419,9 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Double> mobSpawnerAvoidanceCoefficient = new Setting<>(2.0);
|
||||
|
||||
/**
|
||||
* Distance to avoid mob spawners.
|
||||
*/
|
||||
public final Setting<Integer> mobSpawnerAvoidanceRadius = new Setting<>(16);
|
||||
|
||||
/**
|
||||
@@ -352,6 +431,9 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Double> mobAvoidanceCoefficient = new Setting<>(1.5);
|
||||
|
||||
/**
|
||||
* Distance to avoid mobs.
|
||||
*/
|
||||
public final Setting<Integer> mobAvoidanceRadius = new Setting<>(8);
|
||||
|
||||
/**
|
||||
@@ -502,6 +584,17 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Long> slowPathTimeoutMS = new Setting<>(40000L);
|
||||
|
||||
|
||||
/**
|
||||
* allows baritone to save bed waypoints when interacting with beds
|
||||
*/
|
||||
public final Setting<Boolean> doBedWaypoints = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* allows baritone to save death waypoints
|
||||
*/
|
||||
public final Setting<Boolean> doDeathWaypoints = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing.
|
||||
*/
|
||||
@@ -518,13 +611,6 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Remember the contents of containers (chests, echests, furnaces)
|
||||
* <p>
|
||||
* Really buggy since the packet stuff is multithreaded badly thanks to brady
|
||||
*/
|
||||
public final Setting<Boolean> containerMemory = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Fill in blocks behind you
|
||||
*/
|
||||
@@ -573,6 +659,12 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> renderGoal = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Render the goal as a sick animated thingy instead of just a box
|
||||
* (also controls animation of GoalXZ if {@link #renderGoalXZBeacon} is enabled)
|
||||
*/
|
||||
public final Setting<Boolean> renderGoalAnimated = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Render selection boxes
|
||||
*/
|
||||
@@ -642,7 +734,7 @@ public final class Settings {
|
||||
|
||||
/**
|
||||
* When GetToBlockProcess or MineProcess fails to calculate a path, instead of just giving up, mark the closest instance
|
||||
* of that block as "unreachable" and go towards the next closest. GetToBlock expands this seaarch to the whole "vein"; MineProcess does not.
|
||||
* of that block as "unreachable" and go towards the next closest. GetToBlock expands this search to the whole "vein"; MineProcess does not.
|
||||
* This is because MineProcess finds individual impossible blocks (like one block in a vein that has gravel on top then lava, so it can't break)
|
||||
* Whereas GetToBlock should blacklist the whole "vein" if it can't get to any of them.
|
||||
*/
|
||||
@@ -697,6 +789,16 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> censorRanCommands = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Stop using tools just before they are going to break.
|
||||
*/
|
||||
public final Setting<Boolean> itemSaver = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Durability to leave on the tool when using itemSaver
|
||||
*/
|
||||
public final Setting<Integer> itemSaverThreshold = new Setting<>(10);
|
||||
|
||||
/**
|
||||
* Always prefer silk touch tools over regular tools. This will not sacrifice speed, but it will always prefer silk
|
||||
* touch tools over other tools of the same speed. This includes always choosing ANY silk touch tool over your hand.
|
||||
@@ -758,7 +860,7 @@ public final class Settings {
|
||||
public final Setting<Integer> allowOnlyExposedOresDistance = new Setting<>(1);
|
||||
|
||||
/**
|
||||
* When GetToBlock doesn't know any locations for the desired block, explore randomly instead of giving up.
|
||||
* When GetToBlock or non-legit Mine doesn't know any locations for the desired block, explore randomly instead of giving up.
|
||||
*/
|
||||
public final Setting<Boolean> exploreForBlocks = new Setting<>(true);
|
||||
|
||||
@@ -810,6 +912,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> layerOrder = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* How high should the individual layers be?
|
||||
*/
|
||||
public final Setting<Integer> layerHeight = new Setting<>(1);
|
||||
|
||||
/**
|
||||
* Start building the schematic at a specific layer.
|
||||
* Can help on larger builds when schematic wants to break things its already built
|
||||
@@ -821,6 +928,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> skipFailedLayers = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Only build the selected part of schematics
|
||||
*/
|
||||
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
|
||||
*/
|
||||
@@ -831,6 +943,13 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Integer> buildRepeatCount = new Setting<>(-1);
|
||||
|
||||
/**
|
||||
* Don't notify schematics that they are moved.
|
||||
* e.g. replacing will replace the same spots for every repetition
|
||||
* Mainly for backward compatibility.
|
||||
*/
|
||||
public final Setting<Boolean> buildRepeatSneaky = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow standing above a block while mining it, in BuilderProcess
|
||||
* <p>
|
||||
@@ -939,13 +1058,14 @@ public final class Settings {
|
||||
* Disallow MineBehavior from using X-Ray to see where the ores are. Turn this option on to force it to mine "legit"
|
||||
* where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player
|
||||
* couldn't. If you don't want it to look like you're X-Raying, turn this on
|
||||
* This will always explore, regardless of exploreForBlocks
|
||||
*/
|
||||
public final Setting<Boolean> legitMine = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* What Y level to go to for legit strip mining
|
||||
*/
|
||||
public final Setting<Integer> legitMineYLevel = new Setting<>(11);
|
||||
public final Setting<Integer> legitMineYLevel = new Setting<>(-59);
|
||||
|
||||
/**
|
||||
* Magically see ores that are separated diagonally from existing ores. Basically like mining around the ores that it finds
|
||||
@@ -1023,7 +1143,21 @@ public final class Settings {
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
public final Setting<Consumer<Component>> logger = new Setting<>(Minecraft.getInstance().gui.getChat()::addMessage);
|
||||
public final Setting<Consumer<Component>> logger = new Setting<>(msg -> Minecraft.getInstance().gui.getChat().addMessage(msg));
|
||||
|
||||
/**
|
||||
* The function that is called when Baritone will send a desktop notification. This function can be added to
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
public final Setting<BiConsumer<String, Boolean>> notifier = new Setting<>(NotificationHelper::notify);
|
||||
|
||||
/**
|
||||
* The function that is called when Baritone will show a toast. This function can be added to
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
public final Setting<BiConsumer<Component, Component>> toaster = new Setting<>(BaritoneToast::addOrUpdate);
|
||||
|
||||
/**
|
||||
* Print out ALL command exceptions as a stack trace to stdout, even simple syntax errors
|
||||
@@ -1120,6 +1254,11 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> renderSelectionCorners = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Use sword to mine.
|
||||
*/
|
||||
public final Setting<Boolean> useSwordToMine = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Desktop notifications
|
||||
*/
|
||||
|
||||
@@ -58,6 +58,15 @@ public interface IPathingBehavior extends IBehavior {
|
||||
return Optional.of(current.getPath().ticksRemainingFrom(start));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the estimated remaining ticks to the current goal.
|
||||
* Given that the return type is an optional, {@link Optional#empty()}
|
||||
* will be returned in the case that there is no current goal.
|
||||
*
|
||||
* @return The estimated remaining ticks to the current goal.
|
||||
*/
|
||||
Optional<Double> estimatedTicksToGoal();
|
||||
|
||||
/**
|
||||
* @return The current pathing goal
|
||||
*/
|
||||
|
||||
@@ -37,9 +37,4 @@ public interface IWorldData {
|
||||
*/
|
||||
IWaypointCollection getWaypoints();
|
||||
|
||||
/**
|
||||
* @return The {@link IContainerMemory} instance
|
||||
* @see IContainerMemory
|
||||
*/
|
||||
IContainerMemory getContainerMemory();
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -83,10 +83,10 @@ 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)))
|
||||
|
||||
@@ -252,8 +252,8 @@ public class TabCompleteHelper {
|
||||
public TabCompleteHelper addSettings() {
|
||||
return append(
|
||||
BaritoneAPI.getSettings().allSettings.stream()
|
||||
.filter(s -> !SettingsUtil.javaOnlySetting(s))
|
||||
.map(Settings.Setting::getName)
|
||||
.filter(s -> !s.equalsIgnoreCase("logger"))
|
||||
.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);
|
||||
|
||||
@@ -54,4 +54,18 @@ public interface Goal {
|
||||
default double heuristic(BlockPos pos) {
|
||||
return heuristic(pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the heuristic at the goal.
|
||||
* i.e. {@code heuristic() == heuristic(x,y,z)}
|
||||
* when {@code isInGoal(x,y,z) == true}
|
||||
* This is needed by {@code PathingBehavior#estimatedTicksToGoal} because
|
||||
* some Goals actually do not have a heuristic of 0 when that condition is met
|
||||
*
|
||||
* @return The estimate number of ticks to satisfy the goal when the goal
|
||||
* is already satisfied
|
||||
*/
|
||||
default double heuristic() {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +87,9 @@ public class GoalBlock implements Goal, IGoalRenderPos {
|
||||
public static double calculate(double xDiff, int yDiff, double zDiff) {
|
||||
double heuristic = 0;
|
||||
|
||||
// if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be
|
||||
// therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate
|
||||
heuristic += GoalYLevel.calculate(yDiff, 0);
|
||||
// if yDiff is 1 that means that currentY-goalY==1 which means that we're 1 block above where we should be
|
||||
// therefore going from 0,yDiff,0 to a GoalYLevel of 0 is accurate
|
||||
heuristic += GoalYLevel.calculate(0, yDiff);
|
||||
|
||||
//use the pythagorean and manhattan mixture from GoalXZ
|
||||
heuristic += GoalXZ.calculate(xDiff, zDiff);
|
||||
|
||||
@@ -57,6 +57,16 @@ public class GoalComposite implements Goal {
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {
|
||||
double min = Double.MAX_VALUE;
|
||||
for (Goal g : goals) {
|
||||
// just take the highest value that is guaranteed to be inside the goal
|
||||
min = Math.min(min, g.heuristic());
|
||||
}
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalComposite" + Arrays.toString(goals);
|
||||
|
||||
@@ -45,6 +45,11 @@ public class GoalInverted implements Goal {
|
||||
return -origin.heuristic(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format("GoalInverted{%s}", origin.toString());
|
||||
|
||||
@@ -19,6 +19,8 @@ package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
public class GoalNear implements Goal, IGoalRenderPos {
|
||||
@@ -51,6 +53,34 @@ public class GoalNear implements Goal, IGoalRenderPos {
|
||||
return GoalBlock.calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {// TODO less hacky solution
|
||||
int range = (int) Math.ceil(Math.sqrt(rangeSq));
|
||||
DoubleOpenHashSet maybeAlwaysInside = new DoubleOpenHashSet(); // see pull request #1978
|
||||
double minOutside = Double.POSITIVE_INFINITY;
|
||||
for (int dx = -range; dx <= range; dx++) {
|
||||
for (int dy = -range; dy <= range; dy++) {
|
||||
for (int dz = -range; dz <= range; dz++) {
|
||||
double h = heuristic(x + dx, y + dy, z + dz);
|
||||
if (h < minOutside && isInGoal(x + dx, y + dy, z + dz)) {
|
||||
maybeAlwaysInside.add(h);
|
||||
} else {
|
||||
minOutside = Math.min(minOutside, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double maxInside = Double.NEGATIVE_INFINITY;
|
||||
DoubleIterator it = maybeAlwaysInside.iterator();
|
||||
while (it.hasNext()) {
|
||||
double inside = it.nextDouble();
|
||||
if (inside < minOutside) {
|
||||
maxInside = Math.max(maxInside, inside);
|
||||
}
|
||||
}
|
||||
return maxInside;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
|
||||
@@ -18,9 +18,12 @@
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import java.util.Arrays;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
|
||||
import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
/**
|
||||
* Useful for automated combat (retreating specifically)
|
||||
*
|
||||
@@ -64,7 +67,7 @@ public class GoalRunAway implements Goal {
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(int x, int y, int z) {//mostly copied from GoalBlock
|
||||
public double heuristic(int x, int y, int z) {// mostly copied from GoalBlock
|
||||
double min = Double.MAX_VALUE;
|
||||
for (BlockPos p : from) {
|
||||
double h = GoalXZ.calculate(p.getX() - x, p.getZ() - z);
|
||||
@@ -79,6 +82,48 @@ public class GoalRunAway implements Goal {
|
||||
return min;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {// TODO less hacky solution
|
||||
int distance = (int) Math.ceil(Math.sqrt(distanceSq));
|
||||
int minX = Integer.MAX_VALUE;
|
||||
int minY = Integer.MAX_VALUE;
|
||||
int minZ = Integer.MAX_VALUE;
|
||||
int maxX = Integer.MIN_VALUE;
|
||||
int maxY = Integer.MIN_VALUE;
|
||||
int maxZ = Integer.MIN_VALUE;
|
||||
for (BlockPos p : from) {
|
||||
minX = Math.min(minX, p.getX() - distance);
|
||||
minY = Math.min(minY, p.getY() - distance);
|
||||
minZ = Math.min(minZ, p.getZ() - distance);
|
||||
maxX = Math.max(minX, p.getX() + distance);
|
||||
maxY = Math.max(minY, p.getY() + distance);
|
||||
maxZ = Math.max(minZ, p.getZ() + distance);
|
||||
}
|
||||
DoubleOpenHashSet maybeAlwaysInside = new DoubleOpenHashSet(); // see pull request #1978
|
||||
double minOutside = Double.POSITIVE_INFINITY;
|
||||
for (int x = minX; x <= maxX; x++) {
|
||||
for (int y = minY; y <= maxY; y++) {
|
||||
for (int z = minZ; z <= maxZ; z++) {
|
||||
double h = heuristic(x, y, z);
|
||||
if (h < minOutside && isInGoal(x, y, z)) {
|
||||
maybeAlwaysInside.add(h);
|
||||
} else {
|
||||
minOutside = Math.min(minOutside, h);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
double maxInside = Double.NEGATIVE_INFINITY;
|
||||
DoubleIterator it = maybeAlwaysInside.iterator();
|
||||
while (it.hasNext()) {
|
||||
double inside = it.nextDouble();
|
||||
if (inside < minOutside) {
|
||||
maxInside = Math.max(maxInside, inside);
|
||||
}
|
||||
}
|
||||
return maxInside;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
if (maintainY != null) {
|
||||
|
||||
@@ -64,6 +64,11 @@ public class GoalStrictDirection implements Goal {
|
||||
return heuristic;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return String.format(
|
||||
|
||||
@@ -65,8 +65,8 @@ public interface ActionCosts {
|
||||
|
||||
|
||||
static double[] generateFallNBlocksCost() {
|
||||
double[] costs = new double[257];
|
||||
for (int i = 0; i < 257; i++) {
|
||||
double[] costs = new double[4097];
|
||||
for (int i = 0; i < 4097; i++) {
|
||||
costs[i] = distanceToTicks(i);
|
||||
}
|
||||
return costs;
|
||||
|
||||
@@ -57,6 +57,8 @@ public interface IBuilderProcess extends IBaritoneProcess {
|
||||
|
||||
void buildOpenSchematic();
|
||||
|
||||
void buildOpenLitematic(int i);
|
||||
|
||||
void pause();
|
||||
|
||||
boolean isPaused();
|
||||
|
||||
@@ -70,4 +70,11 @@ public class CompositeSchematic extends AbstractSchematic {
|
||||
}
|
||||
return entry.schematic.desiredState(x - entry.x, y - entry.y, z - entry.z, current, approxPlaceable);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
for (CompositeSchematicEntry entry : schematicArr) {
|
||||
entry.schematic.reset();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,10 +18,11 @@
|
||||
package baritone.api.schematic;
|
||||
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
import java.util.List;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class FillSchematic extends AbstractSchematic {
|
||||
|
||||
private final BlockOptionalMeta bom;
|
||||
@@ -43,8 +44,6 @@ public class FillSchematic extends AbstractSchematic {
|
||||
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
|
||||
if (bom.matches(current)) {
|
||||
return current;
|
||||
} else if (current.getBlock() != Blocks.AIR) {
|
||||
return Blocks.AIR.defaultBlockState();
|
||||
}
|
||||
for (BlockState placeable : approxPlaceable) {
|
||||
if (bom.matches(placeable)) {
|
||||
|
||||
@@ -72,6 +72,11 @@ public interface ISchematic {
|
||||
*/
|
||||
BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable);
|
||||
|
||||
/**
|
||||
* Resets possible caches to avoid wrong behavior when moving the schematic around
|
||||
*/
|
||||
default void reset() {}
|
||||
|
||||
/**
|
||||
* @return The width (X axis length) of this schematic
|
||||
*/
|
||||
|
||||
@@ -31,6 +31,18 @@ public class ReplaceSchematic extends MaskSchematic {
|
||||
this.cache = new Boolean[widthX()][heightY()][lengthZ()];
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
// it's final, can't use this.cache = new Boolean[widthX()][heightY()][lengthZ()]
|
||||
for (int x = 0; x < cache.length; x++) {
|
||||
for (int y = 0; y < cache[0].length; y++) {
|
||||
for (int z = 0; z < cache[0][0].length; z++) {
|
||||
cache[x][y][z] = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
|
||||
if (cache[x][y][z] == null) {
|
||||
|
||||
91
src/api/java/baritone/api/schematic/SubstituteSchematic.java
Normal file
91
src/api/java/baritone/api/schematic/SubstituteSchematic.java
Normal file
@@ -0,0 +1,91 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.schematic;
|
||||
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
public class SubstituteSchematic extends AbstractSchematic {
|
||||
|
||||
private final ISchematic schematic;
|
||||
private final Map<Block, List<Block>> substitutions;
|
||||
private final Map<BlockState, Map<Block, BlockState>> blockStateCache = new HashMap<>();
|
||||
|
||||
public SubstituteSchematic(ISchematic schematic, Map<Block, List<Block>> substitutions) {
|
||||
super(schematic.widthX(), schematic.heightY(), schematic.lengthZ());
|
||||
this.schematic = schematic;
|
||||
this.substitutions = substitutions;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
|
||||
return schematic.inSchematic(x, y, z, currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
|
||||
BlockState desired = schematic.desiredState(x, y, z, current, approxPlaceable);
|
||||
Block desiredBlock = desired.getBlock();
|
||||
if (!substitutions.containsKey(desiredBlock)) {
|
||||
return desired;
|
||||
}
|
||||
List<Block> substitutes = substitutions.get(desiredBlock);
|
||||
if (substitutes.contains(current.getBlock()) && !(current.getBlock() instanceof AirBlock)) {// don't preserve air, it's almost always there and almost never wanted
|
||||
return withBlock(desired, current.getBlock());
|
||||
}
|
||||
for (Block substitute : substitutes) {
|
||||
if (substitute instanceof AirBlock) {
|
||||
return current.getBlock() instanceof AirBlock ? current : Blocks.AIR.defaultBlockState(); // can always "place" air
|
||||
}
|
||||
for (BlockState placeable : approxPlaceable) {
|
||||
if (substitute.equals(placeable.getBlock())) {
|
||||
return withBlock(desired, placeable.getBlock());
|
||||
}
|
||||
}
|
||||
}
|
||||
return substitutes.get(0).defaultBlockState();
|
||||
}
|
||||
|
||||
private BlockState withBlock(BlockState state, Block block) {
|
||||
if (blockStateCache.containsKey(state) && blockStateCache.get(state).containsKey(block)) {
|
||||
return blockStateCache.get(state).get(block);
|
||||
}
|
||||
Collection<Property<?>> properties = state.getProperties();
|
||||
BlockState newState = block.defaultBlockState();
|
||||
for (Property<?> property : properties) {
|
||||
try {
|
||||
newState = copySingleProp(state, newState, property);
|
||||
} catch (IllegalArgumentException e) { //property does not exist for target block
|
||||
}
|
||||
}
|
||||
blockStateCache.computeIfAbsent(state, s -> new HashMap<Block, BlockState>()).put(block, newState);
|
||||
return newState;
|
||||
}
|
||||
|
||||
private <T extends Comparable<T>> BlockState copySingleProp(BlockState fromState, BlockState toState, Property<T> prop) {
|
||||
return toState.setValue(prop, fromState.getValue(prop));
|
||||
}
|
||||
}
|
||||
@@ -29,7 +29,6 @@ import net.minecraft.server.packs.repository.Pack;
|
||||
import net.minecraft.server.packs.repository.PackRepository;
|
||||
import net.minecraft.server.packs.repository.ServerPacksSource;
|
||||
import net.minecraft.server.packs.resources.ReloadableResourceManager;
|
||||
import net.minecraft.server.packs.resources.SimpleReloadableResourceManager;
|
||||
import net.minecraft.util.Unit;
|
||||
import net.minecraft.world.item.Item;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
@@ -147,11 +146,11 @@ public final class BlockOptionalMeta {
|
||||
PackRepository rpl = new PackRepository(PackType.SERVER_DATA, new ServerPacksSource());
|
||||
rpl.reload();
|
||||
PackResources thePack = rpl.getAvailablePacks().iterator().next().open();
|
||||
ReloadableResourceManager resourceManager = new SimpleReloadableResourceManager(PackType.SERVER_DATA);
|
||||
ReloadableResourceManager resourceManager = new ReloadableResourceManager(PackType.SERVER_DATA);
|
||||
manager = new LootTables(predicate);
|
||||
resourceManager.registerReloadListener(manager);
|
||||
try {
|
||||
resourceManager.reload(new ThreadPerTaskExecutor(Thread::new), new ThreadPerTaskExecutor(Thread::new), Collections.singletonList(thePack), CompletableFuture.completedFuture(Unit.INSTANCE)).get();
|
||||
resourceManager.createReload(new ThreadPerTaskExecutor(Thread::new), new ThreadPerTaskExecutor(Thread::new), CompletableFuture.completedFuture(Unit.INSTANCE), Collections.singletonList(thePack)).done().get();
|
||||
} catch (Exception exception) {
|
||||
throw new RuntimeException(exception);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,7 @@ public interface Helper {
|
||||
* @param message The message to display in the popup
|
||||
*/
|
||||
default void logToast(Component title, Component message) {
|
||||
mc.execute(() -> BaritoneToast.addOrUpdate(mc.getToasts(), title, message, BaritoneAPI.getSettings().toastTimer.value));
|
||||
mc.execute(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -93,6 +93,48 @@ public interface Helper {
|
||||
logToast(Helper.getPrefix(), new TextComponent(message));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message as a desktop notification
|
||||
*
|
||||
* @param message The message to display in the notification
|
||||
*/
|
||||
default void logNotification(String message) {
|
||||
logNotification(message, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message as a desktop notification
|
||||
*
|
||||
* @param message The message to display in the notification
|
||||
* @param error Whether to log as an error
|
||||
*/
|
||||
default void logNotification(String message, boolean error) {
|
||||
if (BaritoneAPI.getSettings().desktopNotifications.value) {
|
||||
logNotificationDirect(message, error);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message as a desktop notification regardless of desktopNotifications
|
||||
* (should only be used for critically important messages)
|
||||
*
|
||||
* @param message The message to display in the notification
|
||||
*/
|
||||
default void logNotificationDirect(String message) {
|
||||
logNotificationDirect(message, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message as a desktop notification regardless of desktopNotifications
|
||||
* (should only be used for critically important messages)
|
||||
*
|
||||
* @param message The message to display in the notification
|
||||
* @param error Whether to log as an error
|
||||
*/
|
||||
default void logNotificationDirect(String message, boolean error) {
|
||||
mc.execute(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
|
||||
}
|
||||
|
||||
/**
|
||||
* Send a message to chat only if chatDebug is on
|
||||
*
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils;
|
||||
package baritone.api.utils;
|
||||
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
@@ -37,6 +37,7 @@ import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
@@ -50,6 +51,7 @@ public class SettingsUtil {
|
||||
|
||||
private static final Path SETTINGS_PATH = Minecraft.getInstance().gameDirectory.toPath().resolve("baritone").resolve("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) {
|
||||
@@ -112,7 +114,7 @@ public class SettingsUtil {
|
||||
System.out.println("NULL SETTING?" + setting.getName());
|
||||
continue;
|
||||
}
|
||||
if (setting.getName().equals("logger")) {
|
||||
if (javaOnlySetting(setting)) {
|
||||
continue; // NO
|
||||
}
|
||||
if (setting.value == setting.defaultValue) {
|
||||
@@ -166,13 +168,28 @@ public class SettingsUtil {
|
||||
}
|
||||
|
||||
public static String settingToString(Settings.Setting setting) throws IllegalStateException {
|
||||
if (setting.getName().equals("logger")) {
|
||||
return "logger";
|
||||
if (javaOnlySetting(setting)) {
|
||||
return setting.getName();
|
||||
}
|
||||
|
||||
return setting.getName() + " " + settingValueToString(setting);
|
||||
}
|
||||
|
||||
/**
|
||||
* This should always be the same as whether the setting can be parsed from or serialized to a string
|
||||
*
|
||||
* @param setting The Setting
|
||||
* @return true if the setting can not be set or read by the user
|
||||
*/
|
||||
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;
|
||||
}
|
||||
|
||||
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
|
||||
Settings.Setting setting = settings.byLowerName.get(settingName);
|
||||
if (setting == null) {
|
||||
@@ -262,6 +279,36 @@ public class SettingsUtil {
|
||||
public boolean accepts(Type type) {
|
||||
return List.class.isAssignableFrom(TypeUtils.resolveBaseClass(type));
|
||||
}
|
||||
},
|
||||
MAPPING() {
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
Type keyType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[1];
|
||||
Parser keyParser = Parser.getParser(keyType);
|
||||
Parser valueParser = Parser.getParser(valueType);
|
||||
|
||||
return Stream.of(raw.split(",(?=[^,]*->)"))
|
||||
.map(s -> s.split("->"))
|
||||
.collect(Collectors.toMap(s -> keyParser.parse(context, s[0]), s -> valueParser.parse(context, s[1])));
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
Type keyType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Type valueType = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[1];
|
||||
Parser keyParser = Parser.getParser(keyType);
|
||||
Parser valueParser = Parser.getParser(valueType);
|
||||
|
||||
return ((Map<?, ?>) value).entrySet().stream()
|
||||
.map(o -> keyParser.toString(context, o.getKey()) + "->" + valueParser.toString(context, o.getValue()))
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Type type) {
|
||||
return Map.class.isAssignableFrom(TypeUtils.resolveBaseClass(type));
|
||||
}
|
||||
};
|
||||
|
||||
private final Class<?> cla$$;
|
||||
|
||||
@@ -19,6 +19,7 @@ package baritone.api.utils.gui;
|
||||
|
||||
import com.mojang.blaze3d.platform.GlStateManager;
|
||||
import com.mojang.blaze3d.vertex.PoseStack;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.components.toasts.Toast;
|
||||
import net.minecraft.client.gui.components.toasts.ToastComponent;
|
||||
import net.minecraft.network.chat.Component;
|
||||
@@ -74,4 +75,8 @@ public class BaritoneToast implements Toast {
|
||||
baritonetoast.setDisplayedText(title, subtitle);
|
||||
}
|
||||
}
|
||||
|
||||
public static void addOrUpdate(Component title, Component subtitle) {
|
||||
addOrUpdate(Minecraft.getInstance().getToasts(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,10 +64,10 @@ public class MixinClientPlayNetHandler {
|
||||
}*/
|
||||
|
||||
@Inject(
|
||||
method = "handleLevelChunk",
|
||||
method = "handleLevelChunkWithLight",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postHandleChunkData(ClientboundLevelChunkPacket packetIn, CallbackInfo ci) {
|
||||
private void postHandleChunkData(ClientboundLevelChunkWithLightPacket packetIn, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
LocalPlayer player = ibaritone.getPlayerContext().player();
|
||||
if (player != null && player.connection == (ClientPacketListener) (Object) this) {
|
||||
@@ -175,7 +175,7 @@ public class MixinClientPlayNetHandler {
|
||||
method = "handlePlayerCombatKill",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "Lnet/minecraft/client/Minecraft;setScreen(Lnet/minecraft/client/gui/screens/Screen;)V"
|
||||
target = "Lnet/minecraft/client/player/LocalPlayer;shouldShowDeathScreen()Z"
|
||||
)
|
||||
)
|
||||
private void onPlayerDeath(ClientboundPlayerCombatKillPacket packetIn, CallbackInfo ci) {
|
||||
|
||||
@@ -63,7 +63,7 @@ public class MixinMinecraft {
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;",
|
||||
ordinal = 5,
|
||||
ordinal = 4,
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
|
||||
@@ -26,6 +26,6 @@
|
||||
|
||||
"depends": {
|
||||
"fabricloader": ">=0.11.0",
|
||||
"minecraft": "1.17.x"
|
||||
"minecraft": "1.18.x"
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
"required": true,
|
||||
"package": "baritone.launch.mixins",
|
||||
"refmap": "mixins.baritone.refmap.json",
|
||||
"compatibilityLevel": "JAVA_16",
|
||||
"compatibilityLevel": "JAVA_17",
|
||||
"verbose": false,
|
||||
"injectors": {
|
||||
"maxShiftBy": 2
|
||||
|
||||
@@ -68,8 +68,8 @@ public class Baritone implements IBaritone {
|
||||
|
||||
private PathingBehavior pathingBehavior;
|
||||
private LookBehavior lookBehavior;
|
||||
private MemoryBehavior memoryBehavior;
|
||||
private InventoryBehavior inventoryBehavior;
|
||||
private WaypointBehavior waypointBehavior;
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
|
||||
private FollowProcess followProcess;
|
||||
@@ -100,9 +100,9 @@ public class Baritone implements IBaritone {
|
||||
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
|
||||
pathingBehavior = new PathingBehavior(this);
|
||||
lookBehavior = new LookBehavior(this);
|
||||
memoryBehavior = new MemoryBehavior(this);
|
||||
inventoryBehavior = new InventoryBehavior(this);
|
||||
inputOverrideHandler = new InputOverrideHandler(this);
|
||||
waypointBehavior = new WaypointBehavior(this);
|
||||
}
|
||||
|
||||
this.pathingControlManager = new PathingControlManager(this);
|
||||
@@ -151,10 +151,6 @@ public class Baritone implements IBaritone {
|
||||
return this.playerContext;
|
||||
}
|
||||
|
||||
public MemoryBehavior getMemoryBehavior() {
|
||||
return this.memoryBehavior;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FollowProcess getFollowProcess() {
|
||||
return this.followProcess;
|
||||
|
||||
@@ -120,6 +120,9 @@ public final class InventoryBehavior extends Behavior {
|
||||
if (stack.isEmpty()) {
|
||||
continue;
|
||||
}
|
||||
if (Baritone.settings().itemSaver.value && (stack.getDamageValue() + Baritone.settings().itemSaverThreshold.value) >= stack.getMaxDamage() && stack.getMaxDamage() > 1) {
|
||||
continue;
|
||||
}
|
||||
if (cla$$.isInstance(stack.getItem())) {
|
||||
double speed = ToolSet.calculateSpeedVsBlock(stack, against.defaultBlockState()); // takes into account enchants
|
||||
if (speed > bestSpeed) {
|
||||
@@ -157,6 +160,10 @@ public final class InventoryBehavior extends Behavior {
|
||||
}
|
||||
|
||||
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired) {
|
||||
return throwaway(select, desired, Baritone.settings().allowInventory.value);
|
||||
}
|
||||
|
||||
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired, boolean allowInventory) {
|
||||
LocalPlayer p = ctx.player();
|
||||
NonNullList<ItemStack> inv = p.getInventory().items;
|
||||
for (int i = 0; i < 9; i++) {
|
||||
@@ -189,6 +196,19 @@ public final class InventoryBehavior extends Behavior {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (allowInventory) {
|
||||
for (int i = 9; i < 36; i++) {
|
||||
if (desired.test(inv.get(i))) {
|
||||
swapWithHotBar(i, 7);
|
||||
if (select) {
|
||||
p.getInventory().selected = 7;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,101 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.cache.ContainerMemory;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.UUID;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.level.block.BedBlock;
|
||||
|
||||
|
||||
/**
|
||||
* doesn't work for horse inventories :^)
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/6/2018
|
||||
*/
|
||||
public final class MemoryBehavior extends Behavior {
|
||||
|
||||
public MemoryBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(ctx, event.getPos()) instanceof BedBlock) {
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, BetterBlockPos.from(event.getPos())));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, ctx.playerFeet()));
|
||||
}
|
||||
|
||||
public EnderChestMemory getCurrent() {
|
||||
Path path = baritone.getWorldProvider().getCurrentWorld().directory;
|
||||
return EnderChestMemory.getByServerAndPlayer(path.getParent(), ctx.player().getUUID());
|
||||
}
|
||||
|
||||
public static class EnderChestMemory {
|
||||
|
||||
private static final Map<Path, EnderChestMemory> memory = new HashMap<>();
|
||||
private final Path enderChest;
|
||||
private List<ItemStack> contents;
|
||||
|
||||
private EnderChestMemory(Path enderChest) {
|
||||
this.enderChest = enderChest;
|
||||
System.out.println("Echest storing in " + enderChest);
|
||||
try {
|
||||
this.contents = ContainerMemory.readItemStacks(Files.readAllBytes(enderChest));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("CANNOT read echest =( =(");
|
||||
this.contents = null;
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void save() {
|
||||
System.out.println("Saving");
|
||||
if (contents != null) {
|
||||
try {
|
||||
enderChest.getParent().toFile().mkdir();
|
||||
Files.write(enderChest, ContainerMemory.writeItemStacks(contents));
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("CANNOT save echest =( =(");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static synchronized EnderChestMemory getByServerAndPlayer(Path serverStorage, UUID player) {
|
||||
return memory.computeIfAbsent(serverStorage.resolve("echests").resolve(player.toString()), EnderChestMemory::new);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -51,6 +51,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
private Goal goal;
|
||||
private CalculationContext context;
|
||||
|
||||
/*eta*/
|
||||
private int ticksElapsedSoFar;
|
||||
private BetterBlockPos startPosition;
|
||||
|
||||
private boolean safeToCancel;
|
||||
private boolean pauseRequestedLastTick;
|
||||
private boolean unpausedLastTick;
|
||||
@@ -94,9 +98,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
baritone.getPathingControlManager().cancelEverything();
|
||||
return;
|
||||
}
|
||||
|
||||
expectedSegmentStart = pathStart();
|
||||
baritone.getPathingControlManager().preTick();
|
||||
tickPath();
|
||||
ticksElapsedSoFar++;
|
||||
dispatchEvents();
|
||||
}
|
||||
|
||||
@@ -371,6 +377,40 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
return context;
|
||||
}
|
||||
|
||||
public Optional<Double> estimatedTicksToGoal() {
|
||||
BetterBlockPos currentPos = ctx.playerFeet();
|
||||
if (goal == null || currentPos == null || startPosition == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
if (goal.isInGoal(ctx.playerFeet())) {
|
||||
resetEstimatedTicksToGoal();
|
||||
return Optional.of(0.0);
|
||||
}
|
||||
if (ticksElapsedSoFar == 0) {
|
||||
return Optional.empty();
|
||||
}
|
||||
double current = goal.heuristic(currentPos.x, currentPos.y, currentPos.z);
|
||||
double start = goal.heuristic(startPosition.x, startPosition.y, startPosition.z);
|
||||
if (current == start) {// can't check above because current and start can be equal even if currentPos and startPosition are not
|
||||
return Optional.empty();
|
||||
}
|
||||
double eta = Math.abs(current - goal.heuristic()) * ticksElapsedSoFar / Math.abs(start - current);
|
||||
return Optional.of(eta);
|
||||
}
|
||||
|
||||
private void resetEstimatedTicksToGoal() {
|
||||
resetEstimatedTicksToGoal(expectedSegmentStart);
|
||||
}
|
||||
|
||||
private void resetEstimatedTicksToGoal(BlockPos start) {
|
||||
resetEstimatedTicksToGoal(new BetterBlockPos(start));
|
||||
}
|
||||
|
||||
private void resetEstimatedTicksToGoal(BetterBlockPos start) {
|
||||
ticksElapsedSoFar = 0;
|
||||
startPosition = start;
|
||||
}
|
||||
|
||||
/**
|
||||
* See issue #209
|
||||
*
|
||||
@@ -467,6 +507,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
if (executor.get().getPath().positions().contains(expectedSegmentStart)) {
|
||||
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
current = executor.get();
|
||||
resetEstimatedTicksToGoal(start);
|
||||
} else {
|
||||
logDebug("Warning: discarding orphan path segment with incorrect start");
|
||||
}
|
||||
|
||||
93
src/main/java/baritone/behavior/WaypointBehavior.java
Normal file
93
src/main/java/baritone/behavior/WaypointBehavior.java
Normal file
@@ -0,0 +1,93 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.IWaypoint;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
import net.minecraft.world.level.block.BedBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BedPart;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
public class WaypointBehavior extends Behavior {
|
||||
|
||||
|
||||
public WaypointBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (!Baritone.settings().doBedWaypoints.value)
|
||||
return;
|
||||
if (event.getType() == BlockInteractEvent.Type.USE) {
|
||||
BetterBlockPos pos = BetterBlockPos.from(event.getPos());
|
||||
BlockState state = BlockStateInterface.get(ctx, pos);
|
||||
if (state.getBlock() instanceof BedBlock) {
|
||||
if (state.getValue(BedBlock.PART) == BedPart.FOOT) {
|
||||
pos = pos.relative(state.getValue(BedBlock.FACING));
|
||||
}
|
||||
Set<IWaypoint> waypoints = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getByTag(IWaypoint.Tag.BED);
|
||||
boolean exists = waypoints.stream().map(IWaypoint::getLocation).filter(pos::equals).findFirst().isPresent();
|
||||
if (!exists) {
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, pos));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
if (!Baritone.settings().doDeathWaypoints.value)
|
||||
return;
|
||||
Waypoint deathWaypoint = new Waypoint("death", Waypoint.Tag.DEATH, ctx.playerFeet());
|
||||
baritone.getWorldProvider().getCurrentWorld().getWaypoints().addWaypoint(deathWaypoint);
|
||||
BaseComponent component = new TextComponent("Death position saved.");
|
||||
component.setStyle(component.getStyle()
|
||||
.withColor(ChatFormatting.WHITE)
|
||||
.withHoverEvent(new HoverEvent(
|
||||
HoverEvent.Action.SHOW_TEXT,
|
||||
new TextComponent("Click to goto death")
|
||||
))
|
||||
.withClickEvent(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);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -211,7 +211,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
private BlockPos guessPosition() {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
IWorldData data = ibaritone.getWorldProvider().getCurrentWorld();
|
||||
if (data != null && data.getCachedWorld() == this) {
|
||||
if (data != null && data.getCachedWorld() == this && ibaritone.getPlayerContext().player() != null) {
|
||||
return ibaritone.getPlayerContext().playerFeet();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -132,7 +132,7 @@ public final class ChunkPacker {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
if (x == 0 || x == 15 || z == 0 || z == 15) {
|
||||
Vec3 flow = state.getFluidState().getFlow(chunk.getLevel(), new BlockPos(x + chunk.getPos().x << 4, y, z + chunk.getPos().z << 4));
|
||||
Vec3 flow = state.getFluidState().getFlow(chunk.getLevel(), new BlockPos(x + (chunk.getPos().x << 4), y, z + (chunk.getPos().z << 4)));
|
||||
if (flow.x != 0.0 || flow.z != 0.0) {
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
182
src/main/java/baritone/cache/ContainerMemory.java
vendored
182
src/main/java/baritone/cache/ContainerMemory.java
vendored
@@ -1,182 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.IContainerMemory;
|
||||
import baritone.api.cache.IRememberedInventory;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import io.netty.buffer.ByteBuf;
|
||||
import io.netty.buffer.Unpooled;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.FriendlyByteBuf;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ContainerMemory implements IContainerMemory {
|
||||
|
||||
private final Path saveTo;
|
||||
/**
|
||||
* The current remembered inventories
|
||||
*/
|
||||
private final Map<BlockPos, RememberedInventory> inventories = new HashMap<>();
|
||||
|
||||
|
||||
public ContainerMemory(Path saveTo) {
|
||||
this.saveTo = saveTo;
|
||||
try {
|
||||
read(Files.readAllBytes(saveTo));
|
||||
} catch (NoSuchFileException ignored) {
|
||||
inventories.clear();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
inventories.clear();
|
||||
}
|
||||
}
|
||||
|
||||
private void read(byte[] bytes) throws IOException {
|
||||
FriendlyByteBuf in = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
int chests = in.readInt();
|
||||
for (int i = 0; i < chests; i++) {
|
||||
int x = in.readInt();
|
||||
int y = in.readInt();
|
||||
int z = in.readInt();
|
||||
RememberedInventory rem = new RememberedInventory();
|
||||
rem.items.addAll(readItemStacks(in));
|
||||
rem.size = rem.items.size();
|
||||
rem.windowId = -1;
|
||||
if (rem.items.isEmpty()) {
|
||||
continue; // this only happens if the list has no elements, not if the list has elements that are all empty item stacks
|
||||
}
|
||||
inventories.put(new BlockPos(x, y, z), rem);
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void save() throws IOException {
|
||||
if (!Baritone.settings().containerMemory.value) {
|
||||
return;
|
||||
}
|
||||
ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE);
|
||||
FriendlyByteBuf out = new FriendlyByteBuf(buf);
|
||||
out.writeInt(inventories.size());
|
||||
for (Map.Entry<BlockPos, RememberedInventory> entry : inventories.entrySet()) {
|
||||
out = new FriendlyByteBuf(out.writeInt(entry.getKey().getX()));
|
||||
out = new FriendlyByteBuf(out.writeInt(entry.getKey().getY()));
|
||||
out = new FriendlyByteBuf(out.writeInt(entry.getKey().getZ()));
|
||||
out = writeItemStacks(entry.getValue().getContents(), out);
|
||||
}
|
||||
Files.write(saveTo, out.array());
|
||||
}
|
||||
|
||||
public synchronized void setup(BlockPos pos, int windowId, int slotCount) {
|
||||
RememberedInventory inventory = inventories.computeIfAbsent(pos, x -> new RememberedInventory());
|
||||
inventory.windowId = windowId;
|
||||
inventory.size = slotCount;
|
||||
}
|
||||
|
||||
public synchronized Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
|
||||
return inventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized RememberedInventory getInventoryByPos(BlockPos pos) {
|
||||
return inventories.get(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final synchronized Map<BlockPos, IRememberedInventory> getRememberedInventories() {
|
||||
// make a copy since this map is modified from the packet thread
|
||||
return new HashMap<>(inventories);
|
||||
}
|
||||
|
||||
public static List<ItemStack> readItemStacks(byte[] bytes) throws IOException {
|
||||
FriendlyByteBuf in = new FriendlyByteBuf(Unpooled.wrappedBuffer(bytes));
|
||||
return readItemStacks(in);
|
||||
}
|
||||
|
||||
public static List<ItemStack> readItemStacks(FriendlyByteBuf in) throws IOException {
|
||||
int count = in.readInt();
|
||||
List<ItemStack> result = new ArrayList<>();
|
||||
for (int i = 0; i < count; i++) {
|
||||
result.add(in.readItem());
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static byte[] writeItemStacks(List<ItemStack> write) {
|
||||
ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE);
|
||||
FriendlyByteBuf out = new FriendlyByteBuf(buf);
|
||||
out = writeItemStacks(write, out);
|
||||
return out.array();
|
||||
}
|
||||
|
||||
public static FriendlyByteBuf writeItemStacks(List<ItemStack> write, FriendlyByteBuf out2) {
|
||||
FriendlyByteBuf out = out2; // avoid reassigning an argument LOL
|
||||
out = new FriendlyByteBuf(out.writeInt(write.size()));
|
||||
for (ItemStack stack : write) {
|
||||
out = out.writeItem(stack);
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
/**
|
||||
* An inventory that we are aware of.
|
||||
* <p>
|
||||
* Associated with a {@link BlockPos} in {@link ContainerMemory#inventories}.
|
||||
*/
|
||||
public static class RememberedInventory implements IRememberedInventory {
|
||||
|
||||
/**
|
||||
* The list of items in the inventory
|
||||
*/
|
||||
private final List<ItemStack> items;
|
||||
|
||||
/**
|
||||
* The last known window ID of the inventory
|
||||
*/
|
||||
private int windowId;
|
||||
|
||||
/**
|
||||
* The size of the inventory
|
||||
*/
|
||||
private int size;
|
||||
|
||||
private RememberedInventory() {
|
||||
this.items = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final List<ItemStack> getContents() {
|
||||
return Collections.unmodifiableList(this.items);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final int getSize() {
|
||||
return this.size;
|
||||
}
|
||||
|
||||
public void updateFromOpenWindow(IPlayerContext ctx) {
|
||||
items.clear();
|
||||
items.addAll(ctx.player().containerMenu.getItems().subList(0, size));
|
||||
}
|
||||
}
|
||||
}
|
||||
23
src/main/java/baritone/cache/WorldData.java
vendored
23
src/main/java/baritone/cache/WorldData.java
vendored
@@ -19,15 +19,12 @@ package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.ICachedWorld;
|
||||
import baritone.api.cache.IContainerMemory;
|
||||
import baritone.api.cache.IWaypointCollection;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Path;
|
||||
import net.minecraft.resources.ResourceKey;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.dimension.DimensionType;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Data about a world, from baritone's point of view. Includes cached chunks, waypoints, and map data.
|
||||
*
|
||||
@@ -37,7 +34,6 @@ public class WorldData implements IWorldData {
|
||||
|
||||
public final CachedWorld cache;
|
||||
private final WaypointCollection waypoints;
|
||||
private final ContainerMemory containerMemory;
|
||||
//public final MapData map;
|
||||
public final Path directory;
|
||||
public final DimensionType dimension;
|
||||
@@ -46,7 +42,6 @@ public class WorldData implements IWorldData {
|
||||
this.directory = directory;
|
||||
this.cache = new CachedWorld(directory.resolve("cache"), dimension);
|
||||
this.waypoints = new WaypointCollection(directory.resolve("waypoints"));
|
||||
this.containerMemory = new ContainerMemory(directory.resolve("containers"));
|
||||
this.dimension = dimension;
|
||||
}
|
||||
|
||||
@@ -55,15 +50,6 @@ public class WorldData implements IWorldData {
|
||||
System.out.println("Started saving the world in a new thread");
|
||||
cache.save();
|
||||
});
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
System.out.println("Started saving saved containers in a new thread");
|
||||
try {
|
||||
containerMemory.save();
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
System.out.println("Failed to save saved containers");
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -75,9 +61,4 @@ public class WorldData implements IWorldData {
|
||||
public IWaypointCollection getWaypoints() {
|
||||
return this.waypoints;
|
||||
}
|
||||
|
||||
@Override
|
||||
public IContainerMemory getContainerMemory() {
|
||||
return this.containerMemory;
|
||||
}
|
||||
}
|
||||
|
||||
54
src/main/java/baritone/cache/WorldProvider.java
vendored
54
src/main/java/baritone/cache/WorldProvider.java
vendored
@@ -45,9 +45,11 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
private static final Map<Path, WorldData> worldCache = new HashMap<>(); // this is how the bots have the same cached world
|
||||
|
||||
private WorldData currentWorld;
|
||||
private Level mcWorld; // this let's us detect a broken load/unload hook
|
||||
|
||||
@Override
|
||||
public final WorldData getCurrentWorld() {
|
||||
detectAndHandleBrokenLoading();
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
@@ -57,34 +59,43 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
* @param world The world's Registry Data
|
||||
*/
|
||||
public final void initWorld(ResourceKey<Level> worldKey, DimensionType world) {
|
||||
File directory;
|
||||
File readme;
|
||||
Path directory;
|
||||
Path readme;
|
||||
|
||||
IntegratedServer integratedServer = mc.getSingleplayerServer();
|
||||
|
||||
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
|
||||
if (mc.hasSingleplayerServer()) {
|
||||
directory = DimensionType.getStorageFolder(worldKey, integratedServer.getWorldPath(LevelResource.ROOT).toFile());
|
||||
directory = DimensionType.getStorageFolder(worldKey, integratedServer.getWorldPath(LevelResource.ROOT));
|
||||
|
||||
// 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.gameDirectory.toPath()).getNameCount() != 2) {
|
||||
if (directory.relativize(mc.gameDirectory.toPath()).getNameCount() != 2) {
|
||||
// subdirectory of the main save directory for this world
|
||||
directory = directory.getParentFile();
|
||||
directory = directory.getParent();
|
||||
}
|
||||
|
||||
directory = new File(directory, "baritone");
|
||||
directory = directory.resolve("baritone");
|
||||
readme = directory;
|
||||
} else { // Otherwise, the server must be remote...
|
||||
String folderName = mc.isConnectedToRealms() ? "realms" : mc.getCurrentServer().ip;
|
||||
String folderName;
|
||||
if (mc.getCurrentServer() != null) {
|
||||
folderName = mc.isConnectedToRealms() ? "realms" : mc.getCurrentServer().ip;
|
||||
} else {
|
||||
//replaymod causes null currentServer and false singleplayer.
|
||||
System.out.println("World seems to be a replay. Not loading Baritone cache.");
|
||||
currentWorld = null;
|
||||
mcWorld = mc.level;
|
||||
return;
|
||||
}
|
||||
if (SystemUtils.IS_OS_WINDOWS) {
|
||||
folderName = folderName.replace(":", "_");
|
||||
}
|
||||
directory = new File(Baritone.getDir(), folderName);
|
||||
readme = Baritone.getDir();
|
||||
directory = Baritone.getDir().toPath().resolve(folderName);
|
||||
readme = Baritone.getDir().toPath();
|
||||
}
|
||||
|
||||
// lol wtf is this baritone folder in my minecraft save?
|
||||
try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) {
|
||||
try (FileOutputStream out = new FileOutputStream(readme.resolve("readme.txt").toFile())) {
|
||||
// good thing we have a readme
|
||||
out.write("https://github.com/cabaletta/baritone\n".getBytes());
|
||||
} catch (IOException ignored) {}
|
||||
@@ -101,15 +112,17 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
synchronized (worldCache) {
|
||||
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, world));
|
||||
}
|
||||
this.mcWorld = mc.level;
|
||||
}
|
||||
|
||||
public final Path getDimDir(ResourceKey<Level> level, int height, File directory) {
|
||||
return directory.toPath().resolve(level.location().getNamespace()).resolve(level.location().getPath() + "_" + height);
|
||||
public final Path getDimDir(ResourceKey<Level> level, int height, Path directory) {
|
||||
return directory.resolve(level.location().getNamespace()).resolve(level.location().getPath() + "_" + height);
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
WorldData world = this.currentWorld;
|
||||
this.currentWorld = null;
|
||||
this.mcWorld = null;
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
@@ -117,8 +130,25 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
|
||||
detectAndHandleBrokenLoading();
|
||||
if (this.currentWorld != null) {
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
}
|
||||
}
|
||||
|
||||
private final void detectAndHandleBrokenLoading() {
|
||||
if (this.mcWorld != mc.level) {
|
||||
if (this.currentWorld != null) {
|
||||
System.out.println("mc.world unloaded unnoticed! Unloading Baritone cache now.");
|
||||
closeWorld();
|
||||
}
|
||||
if (mc.level != null) {
|
||||
System.out.println("mc.world loaded unnoticed! Loading Baritone cache now.");
|
||||
initWorld(mc.level.dimension(), mc.level.dimensionType());
|
||||
}
|
||||
} else if (currentWorld == null && mc.level != null && (mc.hasSingleplayerServer() || mc.getCurrentServer() != null)) {
|
||||
System.out.println("Retrying to load Baritone cache");
|
||||
initWorld(mc.level.dimension(), mc.level.dimensionType());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -147,7 +147,7 @@ public enum WorldScanner implements IWorldScanner {
|
||||
boolean foundWithinY = false;
|
||||
for (int y0 : coordinateIterationOrder) {
|
||||
LevelChunkSection section = chunkInternalStorageArray[y0];
|
||||
if (section == null || LevelChunkSection.isEmpty(section)) {
|
||||
if (section == null || section.hasOnlyAir()) {
|
||||
continue;
|
||||
}
|
||||
int yReal = y0 << 4;
|
||||
|
||||
@@ -123,7 +123,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
|
||||
}
|
||||
} else if (argc.hasExactlyOne()) {
|
||||
for (Settings.Setting setting : settings.allSettings) {
|
||||
if (setting.getName().equals("logger")) {
|
||||
if (SettingsUtil.javaOnlySetting(setting)) {
|
||||
continue;
|
||||
}
|
||||
if (setting.getName().equalsIgnoreCase(pair.getA())) {
|
||||
@@ -176,7 +176,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
|
||||
.stream();
|
||||
}
|
||||
Settings.Setting setting = settings.byLowerName.get(argc.getString().toLowerCase(Locale.US));
|
||||
if (setting != null) {
|
||||
if (setting != null && !SettingsUtil.javaOnlySetting(setting)) {
|
||||
if (setting.getValueClass() == Boolean.class) {
|
||||
TabCompleteHelper helper = new TabCompleteHelper();
|
||||
if ((Boolean) setting.value) {
|
||||
|
||||
@@ -38,10 +38,12 @@ public final class DefaultCommands {
|
||||
new GotoCommand(baritone),
|
||||
new PathCommand(baritone),
|
||||
new ProcCommand(baritone),
|
||||
new ETACommand(baritone),
|
||||
new VersionCommand(baritone),
|
||||
new RepackCommand(baritone),
|
||||
new BuildCommand(baritone),
|
||||
new SchematicaCommand(baritone),
|
||||
//new SchematicaCommand(baritone),
|
||||
new LitematicaCommand(baritone),
|
||||
new ComeCommand(baritone),
|
||||
new AxisCommand(baritone),
|
||||
new ForceCancelCommand(baritone),
|
||||
@@ -50,7 +52,6 @@ public final class DefaultCommands {
|
||||
new TunnelCommand(baritone),
|
||||
new RenderCommand(baritone),
|
||||
new FarmCommand(baritone),
|
||||
new ChestsCommand(baritone),
|
||||
new FollowCommand(baritone),
|
||||
new ExploreFilterCommand(baritone),
|
||||
new ReloadAllCommand(baritone),
|
||||
|
||||
84
src/main/java/baritone/command/defaults/ETACommand.java
Normal file
84
src/main/java/baritone/command/defaults/ETACommand.java
Normal file
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* 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.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.pathing.calc.IPathingControlManager;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class ETACommand extends Command {
|
||||
|
||||
public ETACommand(IBaritone baritone) {
|
||||
super(baritone, "eta");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
IPathingControlManager pathingControlManager = baritone.getPathingControlManager();
|
||||
IBaritoneProcess process = pathingControlManager.mostRecentInControl().orElse(null);
|
||||
if (process == null) {
|
||||
throw new CommandInvalidStateException("No process in control");
|
||||
}
|
||||
IPathingBehavior pathingBehavior = baritone.getPathingBehavior();
|
||||
|
||||
double ticksRemainingInSegment = pathingBehavior.ticksRemainingInSegment().orElse(Double.NaN);
|
||||
double ticksRemainingInGoal = pathingBehavior.estimatedTicksToGoal().orElse(Double.NaN);
|
||||
|
||||
logDirect(String.format(
|
||||
"Next segment: %.1fs (%.0f ticks)\n" +
|
||||
"Goal: %.1fs (%.0f ticks)",
|
||||
ticksRemainingInSegment / 20, // we just assume tps is 20, it isn't worth the effort that is needed to calculate it exactly
|
||||
ticksRemainingInSegment,
|
||||
ticksRemainingInGoal / 20,
|
||||
ticksRemainingInGoal
|
||||
));
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) {
|
||||
return Stream.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getShortDesc() {
|
||||
return "View the current ETA";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"The ETA command provides information about the estimated time until the next segment.",
|
||||
"and the goal",
|
||||
"",
|
||||
"Be aware that the ETA to your goal is really unprecise",
|
||||
"",
|
||||
"Usage:",
|
||||
"> eta - View ETA, if present"
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -79,7 +80,7 @@ public class ExecutionControlCommands {
|
||||
}
|
||||
}
|
||||
);
|
||||
pauseCommand = new Command(baritone, "pause", "p") {
|
||||
pauseCommand = new Command(baritone, "pause", "p", "paws") {
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
@@ -112,7 +113,7 @@ public class ExecutionControlCommands {
|
||||
);
|
||||
}
|
||||
};
|
||||
resumeCommand = new Command(baritone, "resume", "r") {
|
||||
resumeCommand = new Command(baritone, "resume", "r", "unpause", "unpaws") {
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
|
||||
@@ -22,13 +22,22 @@ import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.BlockById;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.cache.CachedChunk;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.*;
|
||||
import net.minecraft.network.chat.ClickEvent;
|
||||
import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
|
||||
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
public class FindCommand extends Command {
|
||||
|
||||
@@ -38,12 +47,13 @@ public class FindCommand extends Command {
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMin(1);
|
||||
List<Block> toFind = new ArrayList<>();
|
||||
while (args.hasAny()) {
|
||||
toFind.add(args.getDatatypeFor(BlockById.INSTANCE));
|
||||
}
|
||||
BetterBlockPos origin = ctx.playerFeet();
|
||||
toFind.stream()
|
||||
BaseComponent[] components = toFind.stream()
|
||||
.flatMap(block ->
|
||||
ctx.worldData().getCachedWorld().getLocationsOf(
|
||||
Registry.BLOCK.getKey(block).getPath(),
|
||||
@@ -54,13 +64,39 @@ public class FindCommand extends Command {
|
||||
).stream()
|
||||
)
|
||||
.map(BetterBlockPos::new)
|
||||
.map(BetterBlockPos::toString)
|
||||
.forEach(this::logDirect);
|
||||
.map(this::positionToComponent)
|
||||
.toArray(BaseComponent[]::new);
|
||||
if (components.length > 0) {
|
||||
Arrays.asList(components).forEach(this::logDirect);
|
||||
} else {
|
||||
logDirect("No positions known, are you sure the blocks are cached?");
|
||||
}
|
||||
}
|
||||
|
||||
private BaseComponent positionToComponent(BetterBlockPos pos) {
|
||||
String positionText = String.format("%s %s %s", pos.x, pos.y, pos.z);
|
||||
String command = String.format("%sgoal %s", FORCE_COMMAND_PREFIX, positionText);
|
||||
BaseComponent baseComponent = new TextComponent(pos.toString());
|
||||
BaseComponent hoverComponent = new TextComponent("Click to set goal to this position");
|
||||
baseComponent.setStyle(baseComponent.getStyle()
|
||||
.withColor(ChatFormatting.GRAY)
|
||||
.withInsertion(positionText)
|
||||
.withClickEvent(new ClickEvent(ClickEvent.Action.RUN_COMMAND, command))
|
||||
.withHoverEvent(new HoverEvent(HoverEvent.Action.SHOW_TEXT, hoverComponent)));
|
||||
return baseComponent;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) {
|
||||
return args.tabCompleteDatatype(BlockById.INSTANCE);
|
||||
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
|
||||
return new TabCompleteHelper()
|
||||
.append(
|
||||
CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.stream()
|
||||
.map(Registry.BLOCK::getKey)
|
||||
.map(Object::toString)
|
||||
)
|
||||
.filterPrefixNamespaced(args.getString())
|
||||
.sortAlphabetically()
|
||||
.stream();
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -71,10 +107,11 @@ public class FindCommand extends Command {
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"",
|
||||
"The find command searches through Baritone's cache and attempts to find the location of the block.",
|
||||
"Tab completion will suggest only cached blocks and uncached blocks can not be found.",
|
||||
"",
|
||||
"Usage:",
|
||||
"> "
|
||||
"> find <block> [...] - Try finding the listed blocks"
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ import baritone.api.command.argument.IArgConsumer;
|
||||
import baritone.api.command.datatypes.EntityClassById;
|
||||
import baritone.api.command.datatypes.IDatatypeFor;
|
||||
import baritone.api.command.datatypes.NearbyPlayer;
|
||||
import baritone.api.command.exception.CommandErrorMessageException;
|
||||
import baritone.api.command.exception.CommandException;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
import java.util.*;
|
||||
@@ -60,7 +61,7 @@ public class FollowCommand extends Command {
|
||||
if (gotten instanceof EntityType) {
|
||||
//noinspection unchecked
|
||||
classes.add((EntityType) gotten);
|
||||
} else {
|
||||
} else if (gotten != null) {
|
||||
entities.add((Entity) gotten);
|
||||
}
|
||||
}
|
||||
@@ -74,12 +75,14 @@ public class FollowCommand extends Command {
|
||||
if (group != null) {
|
||||
logDirect(String.format("Following all %s", group.name().toLowerCase(Locale.US)));
|
||||
} else {
|
||||
logDirect("Following these types of entities:");
|
||||
if (classes.isEmpty()) {
|
||||
if (entities.isEmpty()) throw new NoEntitiesException();
|
||||
logDirect("Following these entities:");
|
||||
entities.stream()
|
||||
.map(Entity::toString)
|
||||
.forEach(this::logDirect);
|
||||
} else {
|
||||
logDirect("Following these types of entities:");
|
||||
classes.stream()
|
||||
.map(Registry.ENTITY_TYPE::getKey)
|
||||
.map(Objects::requireNonNull)
|
||||
@@ -156,4 +159,12 @@ public class FollowCommand extends Command {
|
||||
this.datatype = datatype;
|
||||
}
|
||||
}
|
||||
|
||||
public static class NoEntitiesException extends CommandErrorMessageException {
|
||||
|
||||
protected NoEntitiesException() {
|
||||
super("No valid entities in range!");
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,46 +18,34 @@
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.cache.IRememberedInventory;
|
||||
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.utils.BetterBlockPos;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.network.chat.MutableComponent;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
public class ChestsCommand extends Command {
|
||||
public class LitematicaCommand extends Command {
|
||||
|
||||
public ChestsCommand(IBaritone baritone) {
|
||||
super(baritone, "chests");
|
||||
public LitematicaCommand(IBaritone baritone) {
|
||||
super(baritone, "litematica");
|
||||
}
|
||||
|
||||
@Override
|
||||
public void execute(String label, IArgConsumer args) throws CommandException {
|
||||
args.requireMax(0);
|
||||
Set<Map.Entry<BlockPos, IRememberedInventory>> entries =
|
||||
ctx.worldData().getContainerMemory().getRememberedInventories().entrySet();
|
||||
if (entries.isEmpty()) {
|
||||
throw new CommandInvalidStateException("No remembered inventories");
|
||||
}
|
||||
for (Map.Entry<BlockPos, IRememberedInventory> entry : entries) {
|
||||
// betterblockpos has censoring
|
||||
BetterBlockPos pos = new BetterBlockPos(entry.getKey());
|
||||
IRememberedInventory inv = entry.getValue();
|
||||
logDirect(pos.toString());
|
||||
for (ItemStack item : inv.getContents()) {
|
||||
MutableComponent component = (MutableComponent) item.getDisplayName();
|
||||
component.append(String.format(" x %d", item.getCount()));
|
||||
logDirect(component);
|
||||
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
|
||||
@@ -67,16 +55,17 @@ public class ChestsCommand extends Command {
|
||||
|
||||
@Override
|
||||
public String getShortDesc() {
|
||||
return "Display remembered inventories";
|
||||
return "Builds the loaded schematic";
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"The chests command lists remembered inventories, I guess?",
|
||||
"Build a schematic currently open in Litematica.",
|
||||
"",
|
||||
"Usage:",
|
||||
"> chests"
|
||||
"> litematica",
|
||||
"> litematica <#>"
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -65,14 +65,12 @@ public class MineCommand extends Command {
|
||||
return Arrays.asList(
|
||||
"The mine command allows you to tell Baritone to search for and mine individual blocks.",
|
||||
"",
|
||||
"The specified blocks can be ores (which are commonly cached), or any other block.",
|
||||
"The specified blocks can be ores, or any other block.",
|
||||
"",
|
||||
"Also see the legitMine settings (see #set l legitMine).",
|
||||
"",
|
||||
"Usage:",
|
||||
"> mine diamond_ore - Mines all diamonds it can find.",
|
||||
"> mine redstone_ore lit_redstone_ore - Mines redstone ore.",
|
||||
"> mine log:0 - Mines only oak logs."
|
||||
"> mine diamond_ore - Mines all diamonds it can find."
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ public class SchematicaCommand extends Command {
|
||||
@Override
|
||||
public List<String> getLongDesc() {
|
||||
return Arrays.asList(
|
||||
"Builds the schematica currently open in Schematica.",
|
||||
"Builds the schematic currently open in Schematica.",
|
||||
"",
|
||||
"Usage:",
|
||||
"> schematica"
|
||||
|
||||
@@ -36,21 +36,28 @@ import baritone.api.selection.ISelectionManager;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.BlockOptionalMeta;
|
||||
import baritone.api.utils.BlockOptionalMetaLookup;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.IRenderer;
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
|
||||
public class SelCommand extends Command {
|
||||
|
||||
private ISelectionManager manager = baritone.getSelectionManager();
|
||||
private BetterBlockPos pos1 = null;
|
||||
private ISchematic clipboard = null;
|
||||
private Vec3i clipboardOffset = null;
|
||||
|
||||
public SelCommand(IBaritone baritone) {
|
||||
super(baritone, "sel", "selection", "s");
|
||||
@@ -156,6 +163,56 @@ public class SelCommand extends Command {
|
||||
}
|
||||
baritone.getBuilderProcess().build("Fill", composite, origin);
|
||||
logDirect("Filling now");
|
||||
} else if (action == Action.COPY) {
|
||||
BetterBlockPos playerPos = mc.getCameraEntity() != null ? BetterBlockPos.from(mc.getCameraEntity().blockPosition()) : ctx.playerFeet();
|
||||
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
|
||||
args.requireMax(0);
|
||||
ISelection[] selections = manager.getSelections();
|
||||
if (selections.length < 1) {
|
||||
throw new CommandInvalidStateException("No selections");
|
||||
}
|
||||
BlockStateInterface bsi = new BlockStateInterface(ctx);
|
||||
BetterBlockPos origin = selections[0].min();
|
||||
CompositeSchematic composite = new CompositeSchematic(0, 0, 0);
|
||||
for (ISelection selection : selections) {
|
||||
BetterBlockPos min = selection.min();
|
||||
origin = new BetterBlockPos(
|
||||
Math.min(origin.x, min.x),
|
||||
Math.min(origin.y, min.y),
|
||||
Math.min(origin.z, min.z)
|
||||
);
|
||||
}
|
||||
for (ISelection selection : selections) {
|
||||
Vec3i size = selection.size();
|
||||
BetterBlockPos min = selection.min();
|
||||
BlockState[][][] blockstates = new BlockState[size.getX()][size.getZ()][size.getY()];
|
||||
for (int x = 0; x < size.getX(); x++) {
|
||||
for (int y = 0; y < size.getY(); y++) {
|
||||
for (int z = 0; z < size.getZ(); z++) {
|
||||
blockstates[x][z][y] = bsi.get0(min.x + x, min.y + y, min.z + z);
|
||||
}
|
||||
}
|
||||
}
|
||||
ISchematic schematic = new StaticSchematic() {{
|
||||
states = blockstates;
|
||||
x = size.getX();
|
||||
y = size.getY();
|
||||
z = size.getZ();
|
||||
}};
|
||||
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
|
||||
}
|
||||
clipboard = composite;
|
||||
clipboardOffset = origin.subtract(pos);
|
||||
logDirect("Selection copied");
|
||||
} else if (action == Action.PASTE) {
|
||||
BetterBlockPos playerPos = mc.getCameraEntity() != null ? BetterBlockPos.from(mc.getCameraEntity().blockPosition()) : ctx.playerFeet();
|
||||
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
|
||||
args.requireMax(0);
|
||||
if (clipboard == null) {
|
||||
throw new CommandInvalidStateException("You need to copy a selection first");
|
||||
}
|
||||
baritone.getBuilderProcess().build("Fill", clipboard, pos.offset(clipboardOffset));
|
||||
logDirect("Building now");
|
||||
} else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) {
|
||||
args.requireExactly(3);
|
||||
TransformTarget transformTarget = TransformTarget.getByName(args.getString());
|
||||
@@ -250,6 +307,8 @@ public class SelCommand extends Command {
|
||||
"> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.",
|
||||
"> 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.",
|
||||
"> sel paste/p <x> <y> <z> - Build the copied area relative to the specified or your position.",
|
||||
"",
|
||||
"> sel expand <target> <direction> <blocks> - Expand the targets.",
|
||||
"> sel contract <target> <direction> <blocks> - Contract the targets.",
|
||||
@@ -268,6 +327,8 @@ public class SelCommand extends Command {
|
||||
CLEARAREA("cleararea", "ca"),
|
||||
REPLACE("replace", "r"),
|
||||
EXPAND("expand", "ex"),
|
||||
COPY("copy", "cp"),
|
||||
PASTE("paste", "p"),
|
||||
CONTRACT("contract", "ct"),
|
||||
SHIFT("shift", "sh");
|
||||
private final String[] names;
|
||||
|
||||
@@ -23,6 +23,7 @@ import baritone.api.Settings;
|
||||
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.exception.CommandInvalidTypeException;
|
||||
import baritone.api.command.helpers.Paginator;
|
||||
import baritone.api.command.helpers.TabCompleteHelper;
|
||||
@@ -39,8 +40,7 @@ import net.minecraft.network.chat.HoverEvent;
|
||||
import net.minecraft.network.chat.TextComponent;
|
||||
|
||||
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
import static baritone.api.utils.SettingsUtil.settingTypeToString;
|
||||
import static baritone.api.utils.SettingsUtil.settingValueToString;
|
||||
import static baritone.api.utils.SettingsUtil.*;
|
||||
|
||||
public class SetCommand extends Command {
|
||||
|
||||
@@ -64,7 +64,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 -> !s.getName().equals("logger"))
|
||||
.filter(s -> !javaOnlySetting(s))
|
||||
.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());
|
||||
@@ -87,6 +87,7 @@ public class SetCommand extends Command {
|
||||
hoverComponent.append(setting.getName());
|
||||
hoverComponent.append(String.format("\nType: %s", settingTypeToString(setting)));
|
||||
hoverComponent.append(String.format("\n\nValue:\n%s", settingValueToString(setting)));
|
||||
hoverComponent.append(String.format("\n\nDefault Value:\n%s", settingDefaultToString(setting)));
|
||||
String commandSuggestion = Baritone.settings().prefix.value + String.format("set %s ", setting.getName());
|
||||
TextComponent component = new TextComponent(setting.getName());
|
||||
component.setStyle(component.getStyle().withColor(ChatFormatting.GRAY));
|
||||
@@ -127,6 +128,12 @@ public class SetCommand extends Command {
|
||||
if (setting == null) {
|
||||
throw new CommandInvalidTypeException(args.consumed(), "a valid setting");
|
||||
}
|
||||
if (javaOnlySetting(setting)) {
|
||||
// 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
|
||||
throw new CommandInvalidStateException(String.format("Setting %s can only be used via the api.", setting.getName()));
|
||||
}
|
||||
if (!doingSomething && !args.hasAny()) {
|
||||
logDirect(String.format("Value of setting %s:", setting.getName()));
|
||||
logDirect(settingValueToString(setting));
|
||||
@@ -139,7 +146,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(),
|
||||
|
||||
@@ -17,8 +17,10 @@
|
||||
|
||||
package baritone.command.defaults;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.cache.IWaypoint;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.command.Command;
|
||||
import baritone.api.command.argument.IArgConsumer;
|
||||
@@ -35,6 +37,7 @@ import baritone.api.utils.BetterBlockPos;
|
||||
import java.util.*;
|
||||
import java.util.function.BiFunction;
|
||||
import java.util.function.Function;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
import net.minecraft.ChatFormatting;
|
||||
import net.minecraft.network.chat.BaseComponent;
|
||||
@@ -47,6 +50,8 @@ import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
|
||||
|
||||
public class WaypointsCommand extends Command {
|
||||
|
||||
private Map<IWorldData, List<IWaypoint>> deletedWaypoints = new HashMap<>();
|
||||
|
||||
public WaypointsCommand(IBaritone baritone) {
|
||||
super(baritone, "waypoints", "waypoint", "wp");
|
||||
}
|
||||
@@ -125,11 +130,13 @@ public class WaypointsCommand extends Command {
|
||||
);
|
||||
}
|
||||
} else if (action == Action.SAVE) {
|
||||
IWaypoint.Tag tag = IWaypoint.Tag.getByName(args.getString());
|
||||
IWaypoint.Tag tag = args.hasAny() ? IWaypoint.Tag.getByName(args.peekString()) : null;
|
||||
if (tag == null) {
|
||||
throw new CommandInvalidStateException(String.format("'%s' is not a tag ", args.consumedString()));
|
||||
tag = IWaypoint.Tag.USER;
|
||||
} else {
|
||||
args.get();
|
||||
}
|
||||
String name = args.hasAny() ? args.getString() : "";
|
||||
String name = (args.hasExactlyOne() || args.hasExactly(4)) ? args.getString() : "";
|
||||
BetterBlockPos pos = args.hasAny()
|
||||
? args.getDatatypePost(RelativeBlockPos.INSTANCE, ctx.playerFeet())
|
||||
: ctx.playerFeet();
|
||||
@@ -147,7 +154,42 @@ public class WaypointsCommand extends Command {
|
||||
for (IWaypoint waypoint : waypoints) {
|
||||
ForWaypoints.waypoints(this.baritone).removeWaypoint(waypoint);
|
||||
}
|
||||
logDirect(String.format("Cleared %d waypoints", waypoints.length));
|
||||
deletedWaypoints.computeIfAbsent(baritone.getWorldProvider().getCurrentWorld(), k -> new ArrayList<>()).addAll(Arrays.<IWaypoint>asList(waypoints));
|
||||
BaseComponent textComponent = new TextComponent(String.format("Cleared %d waypoints, click to restore them", waypoints.length));
|
||||
textComponent.setStyle(textComponent.getStyle().withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
String.format(
|
||||
"%s%s restore @ %s",
|
||||
FORCE_COMMAND_PREFIX,
|
||||
label,
|
||||
Stream.of(waypoints).map(wp -> Long.toString(wp.getCreationTimestamp())).collect(Collectors.joining(" "))
|
||||
)
|
||||
)));
|
||||
logDirect(textComponent);
|
||||
} else if (action == Action.RESTORE) {
|
||||
List<IWaypoint> waypoints = new ArrayList<>();
|
||||
List<IWaypoint> deletedWaypoints = this.deletedWaypoints.getOrDefault(baritone.getWorldProvider().getCurrentWorld(), Collections.emptyList());
|
||||
if (args.peekString().equals("@")) {
|
||||
args.get();
|
||||
// no args.requireMin(1) because if the user clears an empty tag there is nothing to restore
|
||||
while (args.hasAny()) {
|
||||
long timestamp = args.getAs(Long.class);
|
||||
for (IWaypoint waypoint : deletedWaypoints) {
|
||||
if (waypoint.getCreationTimestamp() == timestamp) {
|
||||
waypoints.add(waypoint);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
args.requireExactly(1);
|
||||
int size = deletedWaypoints.size();
|
||||
int amount = Math.min(size, args.getAs(Integer.class));
|
||||
waypoints = new ArrayList<>(deletedWaypoints.subList(size - amount, size));
|
||||
}
|
||||
waypoints.forEach(ForWaypoints.waypoints(this.baritone)::addWaypoint);
|
||||
deletedWaypoints.removeIf(waypoints::contains);
|
||||
logDirect(String.format("Restored %d waypoints", waypoints.size()));
|
||||
} else {
|
||||
IWaypoint[] waypoints = args.getDatatypeFor(ForWaypoints.INSTANCE);
|
||||
IWaypoint waypoint = null;
|
||||
@@ -216,6 +258,20 @@ public class WaypointsCommand extends Command {
|
||||
waypoint.getCreationTimestamp()
|
||||
)
|
||||
)));
|
||||
BaseComponent recreateComponent = new TextComponent("Click to show a command to recreate this waypoint");
|
||||
recreateComponent.setStyle(recreateComponent.getStyle().withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.SUGGEST_COMMAND,
|
||||
String.format(
|
||||
"%s%s save %s %s %s %s %s",
|
||||
Baritone.settings().prefix.value, // This uses the normal prefix because it is run by the user.
|
||||
label,
|
||||
waypoint.getTag().getName(),
|
||||
waypoint.getName(),
|
||||
waypoint.getLocation().x,
|
||||
waypoint.getLocation().y,
|
||||
waypoint.getLocation().z
|
||||
)
|
||||
)));
|
||||
BaseComponent backComponent = new TextComponent("Click to return to the waypoints list");
|
||||
backComponent.setStyle(backComponent.getStyle().withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
@@ -227,10 +283,22 @@ public class WaypointsCommand extends Command {
|
||||
)));
|
||||
logDirect(deleteComponent);
|
||||
logDirect(goalComponent);
|
||||
logDirect(recreateComponent);
|
||||
logDirect(backComponent);
|
||||
} else if (action == Action.DELETE) {
|
||||
ForWaypoints.waypoints(this.baritone).removeWaypoint(waypoint);
|
||||
logDirect("That waypoint has successfully been deleted");
|
||||
deletedWaypoints.computeIfAbsent(baritone.getWorldProvider().getCurrentWorld(), k -> new ArrayList<>()).add(waypoint);
|
||||
TextComponent textComponent = new TextComponent("That waypoint has successfully been deleted, click to restore it");
|
||||
textComponent.setStyle(textComponent.getStyle().withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
String.format(
|
||||
"%s%s restore @ %s",
|
||||
FORCE_COMMAND_PREFIX,
|
||||
label,
|
||||
waypoint.getCreationTimestamp()
|
||||
)
|
||||
)));
|
||||
logDirect(textComponent);
|
||||
} else if (action == Action.GOAL) {
|
||||
Goal goal = new GoalBlock(waypoint.getLocation());
|
||||
baritone.getCustomGoalProcess().setGoal(goal);
|
||||
@@ -262,6 +330,8 @@ public class WaypointsCommand extends Command {
|
||||
.sortAlphabetically()
|
||||
.filterPrefix(args.getString())
|
||||
.stream();
|
||||
} else if (action == Action.RESTORE) {
|
||||
return Stream.empty();
|
||||
} else {
|
||||
return args.tabCompleteDatatype(ForWaypoints.INSTANCE);
|
||||
}
|
||||
@@ -289,15 +359,19 @@ public class WaypointsCommand extends Command {
|
||||
"",
|
||||
"Note that the info, delete, and goal commands let you specify a waypoint by tag. If there is more than one waypoint with a certain tag, then they will let you select which waypoint you mean.",
|
||||
"",
|
||||
"Missing arguments for the save command use the USER tag, creating an unnamed waypoint and your current position as defaults.",
|
||||
"",
|
||||
"Usage:",
|
||||
"> wp [l/list] - List all waypoints.",
|
||||
"> wp <s/save> <tag> - Save your current position as an unnamed waypoint with the specified tag.",
|
||||
"> wp <s/save> <tag> <name> - Save the waypoint with the specified name.",
|
||||
"> wp <s/save> <tag> <name> <pos> - Save the waypoint with the specified name and position.",
|
||||
"> wp <i/info/show> <tag> - Show info on a waypoint by tag.",
|
||||
"> wp <d/delete> <tag> - Delete a waypoint by tag.",
|
||||
"> wp <g/goal> <tag> - Set a goal to a waypoint by tag.",
|
||||
"> wp <goto> <tag> - Set a goal to a waypoint by tag and start pathing."
|
||||
"> wp <l/list> <tag> - List all waypoints by tag.",
|
||||
"> wp <s/save> - Save an unnamed USER waypoint at your current position",
|
||||
"> wp <s/save> [tag] [name] [pos] - Save a waypoint with the specified tag, name and position.",
|
||||
"> wp <i/info/show> <tag/name> - Show info on a waypoint by tag or name.",
|
||||
"> wp <d/delete> <tag/name> - Delete a waypoint by tag or name.",
|
||||
"> wp <restore> <n> - Restore the last n deleted waypoints.",
|
||||
"> wp <c/clear> <tag> - Delete all waypoints with the specified tag.",
|
||||
"> wp <g/goal> <tag/name> - Set a goal to a waypoint by tag or name.",
|
||||
"> wp <goto> <tag/name> - Set a goal to a waypoint by tag or name and start pathing."
|
||||
);
|
||||
}
|
||||
|
||||
@@ -307,6 +381,7 @@ public class WaypointsCommand extends Command {
|
||||
SAVE("save", "s"),
|
||||
INFO("info", "show", "i"),
|
||||
DELETE("delete", "d"),
|
||||
RESTORE("restore"),
|
||||
GOAL("goal", "g"),
|
||||
GOTO("goto");
|
||||
private final String[] names;
|
||||
|
||||
@@ -25,7 +25,6 @@ import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.utils.NotificationHelper;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -217,9 +216,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
if (logInfo) {
|
||||
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
|
||||
logDebug("No path found =(");
|
||||
if (Baritone.settings().desktopNotifications.value) {
|
||||
NotificationHelper.notify("No path found =(", true);
|
||||
}
|
||||
logNotification("No path found =(", true);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -21,19 +21,24 @@ import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.pathing.precompute.PrecomputedData;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.ToolSet;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.player.Inventory;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.Items;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.Level;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
|
||||
/**
|
||||
@@ -55,11 +60,13 @@ public class CalculationContext {
|
||||
public final boolean canSprint;
|
||||
protected final double placeBlockCost; // protected because you should call the function instead
|
||||
public final boolean allowBreak;
|
||||
public final List<Block> allowBreakAnyway;
|
||||
public final boolean allowParkour;
|
||||
public final boolean allowParkourPlace;
|
||||
public final boolean allowJumpAt256;
|
||||
public final boolean allowParkourAscend;
|
||||
public final boolean assumeWalkOnWater;
|
||||
public final int frostWalker;
|
||||
public final boolean allowDiagonalDescend;
|
||||
public final boolean allowDiagonalAscend;
|
||||
public final boolean allowDownward;
|
||||
@@ -72,11 +79,14 @@ public class CalculationContext {
|
||||
public final double walkOnWaterOnePenalty;
|
||||
public final BetterWorldBorder worldBorder;
|
||||
|
||||
public final PrecomputedData precomputedData;
|
||||
|
||||
public CalculationContext(IBaritone baritone) {
|
||||
this(baritone, false);
|
||||
}
|
||||
|
||||
public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) {
|
||||
this.precomputedData = new PrecomputedData();
|
||||
this.safeForThreadedUse = forUseOnAnotherThread;
|
||||
this.baritone = baritone;
|
||||
LocalPlayer player = baritone.getPlayerContext().player();
|
||||
@@ -89,11 +99,13 @@ public class CalculationContext {
|
||||
this.canSprint = Baritone.settings().allowSprint.value && player.getFoodData().getFoodLevel() > 6;
|
||||
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.value;
|
||||
this.allowBreak = Baritone.settings().allowBreak.value;
|
||||
this.allowBreakAnyway = new ArrayList<>(Baritone.settings().allowBreakAnyway.value);
|
||||
this.allowParkour = Baritone.settings().allowParkour.value;
|
||||
this.allowParkourPlace = Baritone.settings().allowParkourPlace.value;
|
||||
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
|
||||
this.allowParkourAscend = Baritone.settings().allowParkourAscend.value;
|
||||
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value;
|
||||
this.frostWalker = EnchantmentHelper.getEnchantmentLevel(Enchantments.FROST_WALKER, baritone.getPlayerContext().player());
|
||||
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value;
|
||||
this.allowDiagonalAscend = Baritone.settings().allowDiagonalAscend.value;
|
||||
this.allowDownward = Baritone.settings().allowDownward.value;
|
||||
@@ -143,14 +155,13 @@ public class CalculationContext {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!worldBorder.canPlaceAt(x, z)) {
|
||||
// TODO perhaps MovementHelper.canPlaceAgainst could also use this?
|
||||
return COST_INF;
|
||||
}
|
||||
return placeBlockCost;
|
||||
}
|
||||
|
||||
public double breakCostMultiplierAt(int x, int y, int z, BlockState current) {
|
||||
if (!allowBreak) {
|
||||
if (!allowBreak && !allowBreakAnyway.contains(current.getBlock())) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (isPossiblyProtected(x, y, z)) {
|
||||
|
||||
@@ -123,7 +123,7 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
public MovementStatus update() {
|
||||
ctx.player().getAbilities().flying = false;
|
||||
currentState = updateState(currentState);
|
||||
if (MovementHelper.isLiquid(ctx, ctx.playerFeet())) {
|
||||
if (MovementHelper.isLiquid(ctx, ctx.playerFeet()) && ctx.player().position().y < dest.y + 0.6) {
|
||||
currentState.setInput(Input.JUMP, true);
|
||||
}
|
||||
if (ctx.player().isInWall()) {
|
||||
|
||||
@@ -26,29 +26,35 @@ import baritone.api.utils.*;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.pathing.precompute.Ternary;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.BlockGetter;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.piston.MovingPistonBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.BooleanProperty;
|
||||
import net.minecraft.world.level.block.state.properties.Half;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.level.block.state.properties.StairsShape;
|
||||
import net.minecraft.world.level.material.FlowingFluid;
|
||||
import net.minecraft.world.level.material.Fluid;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.level.material.FluidState;
|
||||
import net.minecraft.world.level.material.Material;
|
||||
import net.minecraft.world.level.material.WaterFluid;
|
||||
import net.minecraft.world.level.pathfinder.PathComputationType;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP;
|
||||
import static baritone.pathing.precompute.Ternary.*;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
@@ -58,8 +64,12 @@ import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____S
|
||||
public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
if (!bsi.worldBorder.canPlaceAt(x, z)) {
|
||||
return true;
|
||||
}
|
||||
Block b = state.getBlock();
|
||||
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
return Baritone.settings().blocksToDisallowBreaking.value.contains(b)
|
||||
|| b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
|| b instanceof InfestedBlock // obvious reasons
|
||||
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|
||||
|| avoidAdjacentBreaking(bsi, x, y + 1, z, true)
|
||||
@@ -82,6 +92,19 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
&& FallingBlock.isFree(bsi.get0(x, y - 1, z))) { // and if it would fall (i.e. it's unsupported)
|
||||
return true; // dont break a block that is adjacent to unsupported gravel because it can cause really weird stuff
|
||||
}
|
||||
// only pure liquids for now
|
||||
// waterlogged blocks can have closed bottom sides and such
|
||||
if (block instanceof LiquidBlock) {
|
||||
if (directlyAbove || Baritone.settings().strictLiquidCheck.value) {
|
||||
return true;
|
||||
}
|
||||
int level = state.getValue(LiquidBlock.LEVEL);
|
||||
if (level == 0) {
|
||||
return true; // source blocks like to flow horizontally
|
||||
}
|
||||
// everything else will prefer flowing down
|
||||
return !(bsi.get0(x, y - 1, z).getBlock() instanceof LiquidBlock); // assume everything is in a static state
|
||||
}
|
||||
return !state.getFluidState().isEmpty();
|
||||
}
|
||||
|
||||
@@ -93,32 +116,88 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkThrough(bsi, x, y, z, bsi.get0(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z, BlockState state) {
|
||||
return context.precomputedData.canWalkThrough(context.bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(CalculationContext context, int x, int y, int z) {
|
||||
return context.precomputedData.canWalkThrough(context.bsi, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof AirBlock) { // early return for most common case
|
||||
Ternary canWalkThrough = canWalkThroughBlockState(state);
|
||||
if (canWalkThrough == YES) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BaseFireBlock || block == Blocks.TRIPWIRE || block == Blocks.COBWEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof AbstractSkullBlock || block == Blocks.BUBBLE_COLUMN || block instanceof ShulkerBoxBlock || block instanceof SlabBlock || block instanceof TrapDoorBlock || block == Blocks.HONEY_BLOCK || block == Blocks.END_ROD || block == Blocks.POINTED_DRIPSTONE || block == Blocks.AMETHYST_CLUSTER || block instanceof AzaleaBlock) {
|
||||
if (canWalkThrough == NO) {
|
||||
return false;
|
||||
}
|
||||
return canWalkThroughPosition(bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static Ternary canWalkThroughBlockState(BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof AirBlock) {
|
||||
return YES;
|
||||
}
|
||||
if (block instanceof BaseFireBlock || block == Blocks.TRIPWIRE || block == Blocks.COBWEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof AbstractSkullBlock || block == Blocks.BUBBLE_COLUMN || block instanceof ShulkerBoxBlock || block instanceof SlabBlock || block instanceof TrapDoorBlock || block == Blocks.HONEY_BLOCK || block == Blocks.END_ROD || block == Blocks.SWEET_BERRY_BUSH || block == Blocks.POINTED_DRIPSTONE || block instanceof AmethystClusterBlock || block instanceof AzaleaBlock) {
|
||||
return NO;
|
||||
}
|
||||
if (block == Blocks.BIG_DRIPLEAF) {
|
||||
return false;
|
||||
return NO;
|
||||
}
|
||||
if (block == Blocks.POWDER_SNOW) {
|
||||
return NO;
|
||||
}
|
||||
if (Baritone.settings().blocksToAvoid.value.contains(block)) {
|
||||
return false;
|
||||
return NO;
|
||||
}
|
||||
if (block instanceof DoorBlock || block instanceof FenceGateBlock) {
|
||||
// Because there's no nice method in vanilla to check if a door is openable or not, we just have to assume
|
||||
// that anything that isn't an iron door isn't openable, ignoring that some doors introduced in mods can't
|
||||
// be opened by just interacting.
|
||||
return block != Blocks.IRON_DOOR;
|
||||
// TODO this assumes that all doors in all mods are openable
|
||||
if (block == Blocks.IRON_DOOR) {
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
if (block instanceof WoolCarpetBlock) {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
if (block instanceof CarpetBlock) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (block instanceof SnowLayerBlock) {
|
||||
// we've already checked doors and fence gates
|
||||
// so the only remaining dynamic isPassables are snow and trapdoor
|
||||
// snow layers cached as the top layer of a packed chunk have no metadata, we can't make a decision based on their depth here
|
||||
// it would otherwise make long distance pathing through snowy biomes impossible
|
||||
return MAYBE;
|
||||
}
|
||||
FluidState fluidState = state.getFluidState();
|
||||
if (!fluidState.isEmpty()) {
|
||||
if (fluidState.getType().getAmount(fluidState) != 8) {
|
||||
return NO;
|
||||
} else {
|
||||
return MAYBE;
|
||||
}
|
||||
}
|
||||
if (block instanceof CauldronBlock) {
|
||||
return NO;
|
||||
}
|
||||
try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information
|
||||
if (state.isPathfindable(null, null, PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} catch (Throwable exception) {
|
||||
System.out.println("The block " + state.getBlock().getName().getString() + " requires a special case due to the exception " + exception.getMessage());
|
||||
return MAYBE;
|
||||
}
|
||||
}
|
||||
|
||||
static boolean canWalkThroughPosition(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (block instanceof CarpetBlock) {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
|
||||
if (block instanceof SnowLayerBlock) {
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (!bsi.worldContainsLoadedChunk(x, z)) {
|
||||
@@ -133,52 +212,33 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
|
||||
if (isFlowing(x, y, z, state, bsi)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
FluidState fluidState = state.getFluidState();
|
||||
if (fluidState.getType() instanceof WaterFluid) {
|
||||
if (!fluidState.isEmpty()) {
|
||||
if (isFlowing(x, y, z, state, bsi)) {
|
||||
return false;
|
||||
}
|
||||
// Everything after this point has to be a special case as it relies on the water not being flowing, which means a special case is needed.
|
||||
if (Baritone.settings().assumeWalkOnWater.value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
BlockState up = bsi.get0(x, y + 1, z);
|
||||
if (!up.getFluidState().isEmpty() || up.getBlock() instanceof WaterlilyBlock) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
return fluidState.getType() instanceof WaterFluid;
|
||||
}
|
||||
|
||||
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
|
||||
// has already been accounted for above
|
||||
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
|
||||
return state.isPathfindable(bsi.access, BlockPos.ZERO, PathComputationType.LAND); // workaround for future compatibility =P
|
||||
}
|
||||
|
||||
/**
|
||||
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
|
||||
* not including water, and not including ladders or vines or cobwebs (they slow us down)
|
||||
*
|
||||
* @param context Calculation context to provide block state lookup
|
||||
* @param x The block's x position
|
||||
* @param y The block's y position
|
||||
* @param z The block's z position
|
||||
* @return Whether or not the block at the specified position
|
||||
*/
|
||||
static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
|
||||
return fullyPassable(
|
||||
context.bsi.access,
|
||||
context.bsi.isPassableBlockPos.set(x, y, z),
|
||||
context.bsi.get0(x, y, z)
|
||||
);
|
||||
}
|
||||
|
||||
static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) {
|
||||
return fullyPassable(ctx.world(), pos, ctx.world().getBlockState(pos));
|
||||
}
|
||||
|
||||
static boolean fullyPassable(BlockGetter access, BlockPos pos, BlockState state) {
|
||||
static Ternary fullyPassableBlockState(BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof AirBlock) { // early return for most common case
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
// exceptions - blocks that are isPassable true, but we can't actually jump through
|
||||
if (block instanceof BaseFireBlock
|
||||
@@ -196,10 +256,49 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|| block instanceof EndPortalBlock
|
||||
|| block instanceof SkullBlock
|
||||
|| block instanceof ShulkerBoxBlock) {
|
||||
return false;
|
||||
return NO;
|
||||
}
|
||||
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
|
||||
return state.isPathfindable(access, pos, PathComputationType.LAND);
|
||||
// at least in 1.12.2 vanilla, that is.....
|
||||
try { // A dodgy catch-all at the end, for most blocks with default behaviour this will work, however where blocks are special this will error out, and we can handle it when we have this information
|
||||
if (state.isPathfindable(null, null, PathComputationType.LAND)) {
|
||||
return YES;
|
||||
} else {
|
||||
return NO;
|
||||
}
|
||||
} catch (Throwable exception) {
|
||||
// see PR #1087 for why
|
||||
System.out.println("The block " + state.getBlock().getName().getString() + " requires a special case due to the exception " + exception.getMessage());
|
||||
return MAYBE;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
|
||||
* not including water, and not including ladders or vines or cobwebs (they slow us down)
|
||||
*/
|
||||
static boolean fullyPassable(CalculationContext context, int x, int y, int z) {
|
||||
return fullyPassable(context, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean fullyPassable(CalculationContext context, int x, int y, int z, BlockState state) {
|
||||
return context.precomputedData.fullyPassable(context.bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static boolean fullyPassable(IPlayerContext ctx, BlockPos pos) {
|
||||
BlockState state = ctx.world().getBlockState(pos);
|
||||
Ternary fullyPassable = fullyPassableBlockState(state);
|
||||
if (fullyPassable == YES) {
|
||||
return true;
|
||||
}
|
||||
if (fullyPassable == NO) {
|
||||
return false;
|
||||
}
|
||||
return fullyPassablePosition(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ(), state); // meh
|
||||
}
|
||||
|
||||
static boolean fullyPassablePosition(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
return state.isPathfindable(bsi.access, bsi.isPassableBlockPos.set(x, y, z), PathComputationType.LAND);
|
||||
}
|
||||
|
||||
static boolean isReplaceable(int x, int y, int z, BlockState state, BlockStateInterface bsi) {
|
||||
@@ -287,6 +386,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return !state.getFluidState().isEmpty()
|
||||
|| block == Blocks.MAGMA_BLOCK
|
||||
|| block == Blocks.CACTUS
|
||||
|| block == Blocks.SWEET_BERRY_BUSH
|
||||
|| block instanceof BaseFireBlock
|
||||
|| block == Blocks.END_PORTAL
|
||||
|| block == Blocks.COBWEB
|
||||
@@ -297,6 +397,8 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* Can I walk on this block without anything weird happening like me falling
|
||||
* through? Includes water because we know that we automatically jump on
|
||||
* water
|
||||
* <p>
|
||||
* If changing something in this function remember to also change it in precomputed data
|
||||
*
|
||||
* @param bsi Block state provider
|
||||
* @param x The block's x position
|
||||
@@ -306,36 +408,68 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return Whether or not the specified block can be walked on
|
||||
*/
|
||||
static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof AirBlock || block == Blocks.MAGMA_BLOCK || block == Blocks.BUBBLE_COLUMN || block == Blocks.HONEY_BLOCK) {
|
||||
// early return for most common case (air)
|
||||
// plus magma, which is a normal cube but it hurts you
|
||||
Ternary canWalkOn = canWalkOnBlockState(state);
|
||||
if (canWalkOn == YES) {
|
||||
return true;
|
||||
}
|
||||
if (canWalkOn == NO) {
|
||||
return false;
|
||||
}
|
||||
if (isBlockNormalCube(state)) {
|
||||
return true;
|
||||
return canWalkOnPosition(bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static Ternary canWalkOnBlockState(BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (isBlockNormalCube(state) && block != Blocks.MAGMA_BLOCK && block != Blocks.BUBBLE_COLUMN && block != Blocks.HONEY_BLOCK) {
|
||||
return YES;
|
||||
}
|
||||
if (block instanceof AzaleaBlock) {
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH) {
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) {
|
||||
return true;
|
||||
return YES;
|
||||
}
|
||||
if (block == Blocks.GLASS || block instanceof StainedGlassBlock) {
|
||||
return YES;
|
||||
}
|
||||
if (block instanceof StairBlock) {
|
||||
return YES;
|
||||
}
|
||||
if (isWater(state)) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (MovementHelper.isLava(state) && Baritone.settings().assumeWalkOnLava.value) {
|
||||
return MAYBE;
|
||||
}
|
||||
if (block instanceof SlabBlock) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.value) {
|
||||
if (state.getValue(SlabBlock.TYPE) != SlabType.BOTTOM) {
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
return YES;
|
||||
}
|
||||
return NO;
|
||||
}
|
||||
|
||||
static boolean canWalkOnPosition(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (isWater(state)) {
|
||||
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
|
||||
BlockState upState = bsi.get0(x, y + 1, z);
|
||||
Block up = upState.getBlock();
|
||||
if (up == Blocks.LILY_PAD || up instanceof WoolCarpetBlock) {
|
||||
if (up == Blocks.LILY_PAD || up instanceof CarpetBlock) {
|
||||
return true;
|
||||
}
|
||||
if (isFlowing(x, y, z, state, bsi) || upState.getFluidState().getType() == Fluids.FLOWING_WATER) {
|
||||
if (MovementHelper.isFlowing(x, y, z, state, bsi) || upState.getFluidState().getType() == Fluids.FLOWING_WATER) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return isWater(upState) && !Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
@@ -343,19 +477,20 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return isWater(upState) ^ Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
if (Baritone.settings().assumeWalkOnLava.value && isLava(state) && !isFlowing(x, y, z, state, bsi)) {
|
||||
|
||||
if (MovementHelper.isLava(state) && !MovementHelper.isFlowing(x, y, z, state, bsi) && Baritone.settings().assumeWalkOnLava.value) { // if we get here it means that assumeWalkOnLava must be true, so put it last
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.GLASS || block instanceof StainedGlassBlock) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof SlabBlock) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.value) {
|
||||
return state.getValue(SlabBlock.TYPE) != SlabType.BOTTOM;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
return block instanceof StairBlock;
|
||||
|
||||
return false; // If we don't recognise it then we want to just return false to be safe.
|
||||
}
|
||||
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z, BlockState state) {
|
||||
return context.precomputedData.canWalkOn(context.bsi, x, y, z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkOn(CalculationContext context, int x, int y, int z) {
|
||||
return canWalkOn(context, x, y, z, context.get(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos, BlockState state) {
|
||||
@@ -374,6 +509,60 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkOn(bsi, x, y, z, bsi.get0(x, y, z));
|
||||
}
|
||||
|
||||
static boolean canUseFrostWalker(CalculationContext context, BlockState state) {
|
||||
return context.frostWalker != 0
|
||||
&& state.getMaterial() == Material.WATER
|
||||
&& ((Integer) state.getValue(LiquidBlock.LEVEL)) == 0;
|
||||
}
|
||||
|
||||
static boolean canUseFrostWalker(IPlayerContext ctx, BlockPos pos) {
|
||||
BlockState state = BlockStateInterface.get(ctx, pos);
|
||||
return EnchantmentHelper.hasFrostWalker(ctx.player())
|
||||
&& state.getMaterial() == Material.WATER
|
||||
&& ((Integer) state.getValue(LiquidBlock.LEVEL)) == 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* If movements make us stand/walk on this block, will it have a top to walk on?
|
||||
*/
|
||||
static boolean mustBeSolidToWalkOn(CalculationContext context, int x, int y, int z, BlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.LADDER || block == Blocks.VINE) {
|
||||
return false;
|
||||
}
|
||||
if (!state.getFluidState().isEmpty()) {
|
||||
// used for frostwalker so only includes blocks where we are still on ground when leaving them to any side
|
||||
// TODO 1.19+ : add leaves, add dripleaf?
|
||||
if (block instanceof SlabBlock) {
|
||||
if (state.getValue(SlabBlock.TYPE) != SlabType.BOTTOM) {
|
||||
return true;
|
||||
}
|
||||
} else if (block instanceof StairBlock) {
|
||||
if (state.getValue(StairBlock.HALF) == Half.TOP) {
|
||||
return true;
|
||||
}
|
||||
StairsShape shape = state.getValue(StairBlock.SHAPE);
|
||||
if (shape == StairsShape.INNER_LEFT || shape == StairsShape.INNER_RIGHT) {
|
||||
return true;
|
||||
}
|
||||
} else if (block instanceof TrapDoorBlock) {
|
||||
if (!state.getValue(TrapDoorBlock.OPEN) && state.getValue(TrapDoorBlock.HALF) == Half.TOP) {
|
||||
return true;
|
||||
}
|
||||
} else if (block == Blocks.SCAFFOLDING) {
|
||||
return true;
|
||||
}
|
||||
if (context.assumeWalkOnWater) {
|
||||
return false;
|
||||
}
|
||||
Block blockAbove = context.getBlock(x, y + 1, z);
|
||||
if (blockAbove instanceof LiquidBlock) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z) {
|
||||
return canPlaceAgainst(bsi, x, y, z, bsi.get0(x, y, z));
|
||||
}
|
||||
@@ -387,6 +576,9 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
if (!bsi.worldBorder.canPlaceAt(x, z)) {
|
||||
return false;
|
||||
}
|
||||
// can we look at the center of a side face of this block and likely be able to place?
|
||||
// (thats how this check is used)
|
||||
// therefore dont include weird things that we technically could place against (like carpet) but practically can't
|
||||
@@ -399,7 +591,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, BlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(context.bsi, x, y, z, state)) {
|
||||
if (!canWalkThrough(context, x, y, z, state)) {
|
||||
if (!state.getFluidState().isEmpty()) {
|
||||
return COST_INF;
|
||||
}
|
||||
@@ -451,7 +643,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @param ts previously calculated ToolSet
|
||||
*/
|
||||
static void switchToBestToolFor(IPlayerContext ctx, BlockState b, ToolSet ts, boolean preferSilkTouch) {
|
||||
if (!Baritone.settings().disableAutoTool.value && !Baritone.settings().assumeExternalAutoTool.value) {
|
||||
if (Baritone.settings().autoTool.value && !Baritone.settings().assumeExternalAutoTool.value) {
|
||||
ctx.player().getInventory().selected = ts.getBestSlot(b.getBlock(), preferSilkTouch);
|
||||
}
|
||||
}
|
||||
@@ -608,7 +800,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean isTransparent(Block b) {
|
||||
|
||||
return b == Blocks.AIR ||
|
||||
return b instanceof AirBlock ||
|
||||
b == Blocks.LAVA ||
|
||||
b == Blocks.WATER;
|
||||
}
|
||||
|
||||
@@ -67,7 +67,7 @@ public class MovementAscend extends Movement {
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
BlockState toPlace = context.get(destX, y, destZ);
|
||||
double additionalPlacementCost = 0;
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y, destZ, toPlace)) {
|
||||
additionalPlacementCost = context.costOfPlacingAt(destX, y, destZ, toPlace);
|
||||
if (additionalPlacementCost >= COST_INF) {
|
||||
return COST_INF;
|
||||
@@ -93,7 +93,7 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
}
|
||||
BlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway
|
||||
if (context.get(x, y + 3, z).getBlock() instanceof FallingBlock && (MovementHelper.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof FallingBlock))) {//it would fall on us and possibly suffocate us
|
||||
if (context.get(x, y + 3, z).getBlock() instanceof FallingBlock && (MovementHelper.canWalkThrough(context, x, y + 1, z) || !(srcUp2.getBlock() instanceof FallingBlock))) {//it would fall on us and possibly suffocate us
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
|
||||
@@ -42,6 +42,7 @@ import net.minecraft.world.phys.Vec3;
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
private int numTicks = 0;
|
||||
public boolean forceSafeMode = false;
|
||||
|
||||
public MovementDescend(IBaritone baritone, BetterBlockPos start, BetterBlockPos end) {
|
||||
super(baritone, start, end, new BetterBlockPos[]{end.above(2), end.above(), end}, end.below());
|
||||
@@ -51,6 +52,14 @@ public class MovementDescend extends Movement {
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
forceSafeMode = false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Called by PathExecutor if needing safeMode can only be detected with knowledge about the next movement
|
||||
*/
|
||||
public void forceSafeMode() {
|
||||
forceSafeMode = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -100,7 +109,7 @@ public class MovementDescend extends Movement {
|
||||
//C, D, etc determine the length of the fall
|
||||
|
||||
BlockState below = context.get(destX, y - 2, destZ);
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ, below)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, y - 2, destZ, below)) {
|
||||
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
|
||||
return;
|
||||
}
|
||||
@@ -108,6 +117,9 @@ public class MovementDescend extends Movement {
|
||||
if (destDown.getBlock() == Blocks.LADDER || destDown.getBlock() == Blocks.VINE) {
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.canUseFrostWalker(context, destDown)) { // no need to check assumeWalkOnWater
|
||||
return; // the water will freeze when we try to walk into it
|
||||
}
|
||||
|
||||
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
|
||||
double walk = WALK_OFF_BLOCK_COST;
|
||||
@@ -129,7 +141,7 @@ public class MovementDescend extends Movement {
|
||||
// and potentially replace the water we're going to fall into
|
||||
return false;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y - 2, destZ, below)) {
|
||||
return false;
|
||||
}
|
||||
double costSoFar = 0;
|
||||
@@ -145,7 +157,7 @@ public class MovementDescend extends Movement {
|
||||
int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY
|
||||
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar;
|
||||
if (MovementHelper.isWater(ontoBlock)) {
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) {
|
||||
return false;
|
||||
}
|
||||
if (context.assumeWalkOnWater) {
|
||||
@@ -154,7 +166,7 @@ public class MovementDescend extends Movement {
|
||||
if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) {
|
||||
return false; // TODO flowing check required here?
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, newY - 1, destZ)) {
|
||||
// we could punch right through the water into something else
|
||||
return false;
|
||||
}
|
||||
@@ -173,10 +185,10 @@ public class MovementDescend extends Movement {
|
||||
effectiveStartHeight = newY;
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (MovementHelper.canWalkThrough(context, destX, newY, destZ, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
if (!MovementHelper.canWalkOn(context, destX, newY, destZ, ontoBlock)) {
|
||||
return false;
|
||||
}
|
||||
if (MovementHelper.isBottomSlab(ontoBlock)) {
|
||||
@@ -247,6 +259,9 @@ public class MovementDescend extends Movement {
|
||||
}
|
||||
|
||||
public boolean safeMode() {
|
||||
if (forceSafeMode) {
|
||||
return true;
|
||||
}
|
||||
// (dest - src) + dest is offset 1 more in the same direction
|
||||
// so it's the block we'd need to worry about running into if we decide to sprint straight through this descend
|
||||
BlockPos into = dest.subtract(src.below()).offset(dest);
|
||||
|
||||
@@ -59,7 +59,7 @@ public class MovementDiagonal extends Movement {
|
||||
@Override
|
||||
protected boolean safeToCancel(MovementState state) {
|
||||
//too simple. backfill does not work after cornering with this
|
||||
//return MovementHelper.canWalkOn(ctx, ctx.playerFeet().down());
|
||||
//return context.precomputedData.canWalkOn(ctx, ctx.playerFeet().down());
|
||||
LocalPlayer player = ctx.player();
|
||||
double offset = 0.25;
|
||||
double x = player.position().x;
|
||||
@@ -109,40 +109,49 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) {
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y + 1, destZ)) {
|
||||
return;
|
||||
}
|
||||
BlockState destInto = context.get(destX, y, destZ);
|
||||
BlockState fromDown;
|
||||
boolean ascend = false;
|
||||
BlockState destWalkOn;
|
||||
boolean descend = false;
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto)) {
|
||||
boolean frostWalker = false;
|
||||
if (!MovementHelper.canWalkThrough(context, destX, y, destZ, destInto)) {
|
||||
ascend = true;
|
||||
if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context.bsi, x, y + 2, z) || !MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 2, destZ)) {
|
||||
if (!context.allowDiagonalAscend || !MovementHelper.canWalkThrough(context, x, y + 2, z) || !MovementHelper.canWalkOn(context, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context, destX, y + 2, destZ)) {
|
||||
return;
|
||||
}
|
||||
destWalkOn = destInto;
|
||||
fromDown = context.get(x, y - 1, z);
|
||||
} else {
|
||||
destWalkOn = context.get(destX, y - 1, destZ);
|
||||
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) {
|
||||
fromDown = context.get(x, y - 1, z);
|
||||
boolean standingOnABlock = MovementHelper.mustBeSolidToWalkOn(context, x, y - 1, z, fromDown);
|
||||
frostWalker = standingOnABlock && MovementHelper.canUseFrostWalker(context, destWalkOn);
|
||||
if (!frostWalker && !MovementHelper.canWalkOn(context, destX, y - 1, destZ, destWalkOn)) {
|
||||
descend = true;
|
||||
if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) {
|
||||
if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context, destX, y - 1, destZ, destWalkOn)) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
frostWalker &= !context.assumeWalkOnWater; // do this after checking for descends because jesus can't prevent the water from freezing, it just prevents us from relying on the water freezing
|
||||
}
|
||||
double multiplier = WALK_ONE_BLOCK_COST;
|
||||
// For either possible soul sand, that affects half of our walking
|
||||
if (destWalkOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
} else if (frostWalker) {
|
||||
// frostwalker lets us walk on water without the penalty
|
||||
} else if (destWalkOn.getBlock() == Blocks.WATER) {
|
||||
multiplier += context.walkOnWaterOnePenalty * SQRT_2;
|
||||
}
|
||||
Block fromDown = context.get(x, y - 1, z).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
Block fromDownBlock = fromDown.getBlock();
|
||||
if (fromDownBlock == Blocks.LADDER || fromDownBlock == Blocks.VINE) {
|
||||
return;
|
||||
}
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
if (fromDownBlock == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
BlockState cuttingOver1 = context.get(x, y - 1, destZ);
|
||||
@@ -169,17 +178,17 @@ public class MovementDiagonal extends Movement {
|
||||
BlockState pb0 = context.get(x, y, destZ);
|
||||
BlockState pb2 = context.get(destX, y, z);
|
||||
if (ascend) {
|
||||
boolean ATop = MovementHelper.canWalkThrough(context.bsi, x, y + 2, destZ);
|
||||
boolean AMid = MovementHelper.canWalkThrough(context.bsi, x, y + 1, destZ);
|
||||
boolean ALow = MovementHelper.canWalkThrough(context.bsi, x, y, destZ, pb0);
|
||||
boolean BTop = MovementHelper.canWalkThrough(context.bsi, destX, y + 2, z);
|
||||
boolean BMid = MovementHelper.canWalkThrough(context.bsi, destX, y + 1, z);
|
||||
boolean BLow = MovementHelper.canWalkThrough(context.bsi, destX, y, z, pb2);
|
||||
boolean ATop = MovementHelper.canWalkThrough(context, x, y + 2, destZ);
|
||||
boolean AMid = MovementHelper.canWalkThrough(context, x, y + 1, destZ);
|
||||
boolean ALow = MovementHelper.canWalkThrough(context, x, y, destZ, pb0);
|
||||
boolean BTop = MovementHelper.canWalkThrough(context, destX, y + 2, z);
|
||||
boolean BMid = MovementHelper.canWalkThrough(context, destX, y + 1, z);
|
||||
boolean BLow = MovementHelper.canWalkThrough(context, destX, y, z, pb2);
|
||||
if ((!(ATop && AMid && ALow) && !(BTop && BMid && BLow)) // no option
|
||||
|| MovementHelper.avoidWalkingInto(pb0) // bad
|
||||
|| MovementHelper.avoidWalkingInto(pb2) // bad
|
||||
|| (ATop && AMid && MovementHelper.canWalkOn(context.bsi, x, y, destZ, pb0)) // we could just ascend
|
||||
|| (BTop && BMid && MovementHelper.canWalkOn(context.bsi, destX, y, z, pb2)) // we could just ascend
|
||||
|| (ATop && AMid && MovementHelper.canWalkOn(context, x, y, destZ, pb0)) // we could just ascend
|
||||
|| (BTop && BMid && MovementHelper.canWalkOn(context, destX, y, z, pb2)) // we could just ascend
|
||||
|| (!ATop && AMid && ALow) // head bonk A
|
||||
|| (!BTop && BMid && BLow)) { // head bonk B
|
||||
return;
|
||||
|
||||
@@ -58,7 +58,7 @@ public class MovementDownward extends Movement {
|
||||
if (!context.allowDownward) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) {
|
||||
if (!MovementHelper.canWalkOn(context, x, y - 2, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
BlockState down = context.get(x, y - 1, z);
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
@@ -27,16 +28,16 @@ import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.StairBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.material.Fluids;
|
||||
import net.minecraft.world.level.material.WaterFluid;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementParkour extends Movement {
|
||||
|
||||
private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{};
|
||||
@@ -74,7 +75,7 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
BlockState adj = context.get(x + xDiff, y - 1, z + zDiff);
|
||||
if (MovementHelper.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
if (MovementHelper.canWalkOn(context, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
|
||||
// second most common case -- we could just traverse not parkour
|
||||
return;
|
||||
}
|
||||
@@ -91,9 +92,16 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
BlockState standingOn = context.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof StairBlock || MovementHelper.isBottomSlab(standingOn) || standingOn.getFluidState().getType() != Fluids.EMPTY) {
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof StairBlock || MovementHelper.isBottomSlab(standingOn)) {
|
||||
return;
|
||||
}
|
||||
// we can't jump from (frozen) water with assumeWalkOnWater because we can't be sure it will be frozen
|
||||
if (context.assumeWalkOnWater && !standingOn.getFluidState().isEmpty()) {
|
||||
return;
|
||||
}
|
||||
if (!context.get(x, y, z).getFluidState().isEmpty()) {
|
||||
return; // can't jump out of water
|
||||
}
|
||||
int maxJump;
|
||||
if (standingOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
maxJump = 2; // 1 block gap
|
||||
@@ -104,73 +112,91 @@ public class MovementParkour extends Movement {
|
||||
maxJump = 3;
|
||||
}
|
||||
}
|
||||
|
||||
// check parkour jumps from smallest to largest for obstacles/walls and landing positions
|
||||
int verifiedMaxJump = 1; // i - 1 (when i = 2)
|
||||
for (int i = 2; i <= maxJump; i++) {
|
||||
int destX = x + xDiff * i;
|
||||
int destZ = z + zDiff * i;
|
||||
|
||||
// check head/feet
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
// check for ascend landing position
|
||||
BlockState destInto = context.bsi.get0(destX, y, destZ);
|
||||
if (!MovementHelper.fullyPassable(context.bsi.access, context.bsi.isPassableBlockPos.set(destX, y, destZ), destInto)) {
|
||||
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
|
||||
if (!MovementHelper.fullyPassable(context, destX, y, destZ, destInto)) {
|
||||
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y + 1;
|
||||
res.z = destZ;
|
||||
res.cost = i * SPRINT_ONE_BLOCK_COST + context.jumpPenalty;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
// check for flat landing position
|
||||
BlockState landingOn = context.bsi.get0(destX, y - 1, destZ);
|
||||
// farmland needs to be canwalkon otherwise farm can never work at all, but we want to specifically disallow ending a jumy on farmland haha
|
||||
if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) {
|
||||
// farmland needs to be canWalkOn otherwise farm can never work at all, but we want to specifically disallow ending a jump on farmland haha
|
||||
// frostwalker works here because we can't jump from possibly unfrozen water
|
||||
if ((landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context, destX, y - 1, destZ, landingOn))
|
||||
|| (Math.min(16, context.frostWalker + 2) >= i && MovementHelper.canUseFrostWalker(context, landingOn))
|
||||
) {
|
||||
if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
res.cost = costFromJumpDistance(i) + context.jumpPenalty;
|
||||
return;
|
||||
}
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) {
|
||||
return;
|
||||
break;
|
||||
}
|
||||
|
||||
verifiedMaxJump = i;
|
||||
}
|
||||
if (maxJump != 4) {
|
||||
return;
|
||||
}
|
||||
|
||||
// parkour place starts here
|
||||
if (!context.allowParkourPlace) {
|
||||
return;
|
||||
}
|
||||
// time 2 pop off with that dank skynet parkour place
|
||||
int destX = x + 4 * xDiff;
|
||||
int destZ = z + 4 * zDiff;
|
||||
BlockState toReplace = context.get(destX, y - 1, destZ);
|
||||
double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, toReplace);
|
||||
if (placeCost >= COST_INF) {
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.isReplaceable(destX, y - 1, destZ, toReplace, context.bsi)) {
|
||||
return;
|
||||
}
|
||||
if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepX();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepY();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getStepZ();
|
||||
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
|
||||
// check parkour jumps from largest to smallest for positions to place blocks
|
||||
for (int i = verifiedMaxJump; i > 1; i--) {
|
||||
int destX = x + i * xDiff;
|
||||
int destZ = z + i * zDiff;
|
||||
BlockState toReplace = context.get(destX, y - 1, destZ);
|
||||
double placeCost = context.costOfPlacingAt(destX, y - 1, destZ, toReplace);
|
||||
if (placeCost >= COST_INF) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
res.cost = costFromJumpDistance(4) + placeCost + context.jumpPenalty;
|
||||
return;
|
||||
if (!MovementHelper.isReplaceable(destX, y - 1, destZ, toReplace, context.bsi)) {
|
||||
continue;
|
||||
}
|
||||
if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
continue;
|
||||
}
|
||||
for (int j = 0; j < 5; j++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepX();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepY();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[j].getStepZ();
|
||||
if (againstX == destX - xDiff && againstZ == destZ - zDiff) { // we can't turn around that fast
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
res.cost = costFromJumpDistance(i) + placeCost + context.jumpPenalty;
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -250,7 +276,12 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
} else if (!ctx.playerFeet().equals(src)) {
|
||||
if (ctx.playerFeet().equals(src.relative(direction)) || ctx.player().position().y - src.y > 0.0001) {
|
||||
if (!MovementHelper.canWalkOn(ctx, dest.below()) && !ctx.player().isOnGround() && MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false) == PlaceResult.READY_TO_PLACE) {
|
||||
if (Baritone.settings().allowPlace.value // see PR #3775
|
||||
&& ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway()
|
||||
&& !MovementHelper.canWalkOn(ctx, dest.below())
|
||||
&& !ctx.player().isOnGround()
|
||||
&& MovementHelper.attemptToPlaceABlock(state, baritone, dest.below(), true, false) == PlaceResult.READY_TO_PLACE
|
||||
) {
|
||||
// go in the opposite order to check DOWN before all horizontals -- down is preferable because you don't have to look to the side while in midair, which could mess up the trajectory
|
||||
state.setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
|
||||
@@ -35,6 +35,7 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CarpetBlock;
|
||||
import net.minecraft.world.level.block.FallingBlock;
|
||||
import net.minecraft.world.level.block.FenceGateBlock;
|
||||
import net.minecraft.world.level.block.LadderBlock;
|
||||
@@ -42,6 +43,7 @@ import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementPillar extends Movement {
|
||||
@@ -105,6 +107,10 @@ public class MovementPillar extends Movement {
|
||||
// if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again
|
||||
return COST_INF;
|
||||
}
|
||||
if ((from == Blocks.LILY_PAD || from instanceof CarpetBlock) && !fromDown.getFluidState().isEmpty()) {
|
||||
// to ascend here we'd have to break the block we are standing on
|
||||
return COST_INF;
|
||||
}
|
||||
double hardness = MovementHelper.getMiningDurationTicks(context, x, y + 2, z, toBreak, true);
|
||||
if (hardness >= COST_INF) {
|
||||
return COST_INF;
|
||||
@@ -124,7 +130,7 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
}
|
||||
// this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era.
|
||||
//if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
|
||||
//if (!MovementHelper.canWalkOn(context, chkPos, check) || MovementHelper.canWalkThrough(context, chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
|
||||
// TODO why does canWalkThrough mean this action is COST_INF?
|
||||
// FallingBlock makes sense, and !canWalkOn deals with weird cases like if it were lava
|
||||
// but I don't understand why canWalkThrough makes it impossible
|
||||
|
||||
@@ -35,14 +35,15 @@ import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.CarpetBlock;
|
||||
import net.minecraft.world.level.block.DoorBlock;
|
||||
import net.minecraft.world.level.block.FenceGateBlock;
|
||||
import net.minecraft.world.level.block.LadderBlock;
|
||||
import net.minecraft.world.level.block.SlabBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.SlabType;
|
||||
import net.minecraft.world.level.material.WaterFluid;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
@@ -70,16 +71,18 @@ public class MovementTraverse extends Movement {
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
return ImmutableSet.of(src, dest);
|
||||
return ImmutableSet.of(src, dest); // src.above means that we don't get caught in an infinite loop in water
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
BlockState pb0 = context.get(destX, y + 1, destZ);
|
||||
BlockState pb1 = context.get(destX, y, destZ);
|
||||
BlockState destOn = context.get(destX, y - 1, destZ);
|
||||
BlockState down = context.get(x, y - 1, z);
|
||||
Block srcDown = down.getBlock();
|
||||
if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
BlockState srcDown = context.get(x, y - 1, z);
|
||||
Block srcDownBlock = srcDown.getBlock();
|
||||
boolean standingOnABlock = MovementHelper.mustBeSolidToWalkOn(context, x, y - 1, z, srcDown);
|
||||
boolean frostWalker = standingOnABlock && !context.assumeWalkOnWater && MovementHelper.canUseFrostWalker(context, destOn);
|
||||
if (frostWalker || MovementHelper.canWalkOn(context, destX, y - 1, destZ, destOn)) { //this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
boolean water = false;
|
||||
if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) {
|
||||
@@ -88,10 +91,12 @@ public class MovementTraverse extends Movement {
|
||||
} else {
|
||||
if (destOn.getBlock() == Blocks.SOUL_SAND) {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
} else if (frostWalker) {
|
||||
// with frostwalker we can walk on water without the penalty, if we are sure we won't be using jesus
|
||||
} else if (destOn.getBlock() == Blocks.WATER) {
|
||||
WC += context.walkOnWaterOnePenalty;
|
||||
}
|
||||
if (srcDown == Blocks.SOUL_SAND) {
|
||||
if (srcDownBlock == Blocks.SOUL_SAND) {
|
||||
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
}
|
||||
@@ -109,13 +114,13 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
return WC;
|
||||
}
|
||||
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
|
||||
if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) {
|
||||
hardness1 *= 5;
|
||||
hardness2 *= 5;
|
||||
}
|
||||
return WC + hardness1 + hardness2;
|
||||
} else {//this is a bridge, so we need to place a block
|
||||
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
|
||||
if (srcDownBlock == Blocks.LADDER || srcDownBlock == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.isReplaceable(destX, y - 1, destZ, destOn, context.bsi)) {
|
||||
@@ -146,12 +151,16 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
}
|
||||
// now that we've checked all possible directions to side place, we actually need to backplace
|
||||
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof SlabBlock && down.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)) {
|
||||
if (srcDownBlock == Blocks.SOUL_SAND || (srcDownBlock instanceof SlabBlock && srcDown.getValue(SlabBlock.TYPE) != SlabType.DOUBLE)) {
|
||||
return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/
|
||||
}
|
||||
if (down.getFluidState().getType() instanceof WaterFluid) {
|
||||
if (!standingOnABlock) { // standing on water / swimming
|
||||
return COST_INF; // this is obviously impossible
|
||||
}
|
||||
Block blockSrc = context.getBlock(x, y, z);
|
||||
if ((blockSrc == Blocks.LILY_PAD || blockSrc instanceof CarpetBlock) && !srcDown.getFluidState().isEmpty()) {
|
||||
return COST_INF; // we can stand on these but can't place against them
|
||||
}
|
||||
WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol
|
||||
return WC + placeCost + hardness1 + hardness2;
|
||||
}
|
||||
@@ -232,11 +241,12 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(ctx, positionToPlace) || ladder;
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(ctx, positionToPlace) || ladder || MovementHelper.canUseFrostWalker(ctx, positionToPlace);
|
||||
BlockPos feet = ctx.playerFeet();
|
||||
if (feet.getY() != dest.getY() && !ladder) {
|
||||
logDebug("Wrong Y coordinate");
|
||||
if (feet.getY() < dest.getY()) {
|
||||
System.out.println("In movement traverse");
|
||||
return state.setInput(Input.JUMP, true);
|
||||
}
|
||||
return state;
|
||||
|
||||
@@ -71,8 +71,8 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
private HashSet<BlockPos> toPlace = new HashSet<>();
|
||||
private HashSet<BlockPos> toWalkInto = new HashSet<>();
|
||||
|
||||
private PathingBehavior behavior;
|
||||
private IPlayerContext ctx;
|
||||
private final PathingBehavior behavior;
|
||||
private final IPlayerContext ctx;
|
||||
|
||||
private boolean sprintNextTick;
|
||||
|
||||
@@ -348,7 +348,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
|
||||
|
||||
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
|
||||
if (!new CalculationContext(behavior.baritone).canSprint) {
|
||||
if (!new CalculationContext(behavior.baritone, false).canSprint) {
|
||||
return false;
|
||||
}
|
||||
IMovement current = path.movements().get(pathPosition);
|
||||
@@ -378,6 +378,26 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
// however, descend and ascend don't request sprinting, because they don't know the context of what movement comes after it
|
||||
if (current instanceof MovementDescend) {
|
||||
|
||||
if (pathPosition < path.length() - 2) {
|
||||
// keep this out of onTick, even if that means a tick of delay before it has an effect
|
||||
IMovement next = path.movements().get(pathPosition + 1);
|
||||
if (MovementHelper.canUseFrostWalker(ctx, next.getDest().below())) {
|
||||
// frostwalker only works if you cross the edge of the block on ground so in some cases we may not overshoot
|
||||
// Since MovementDescend can't know the next movement we have to tell it
|
||||
if (next instanceof MovementTraverse || next instanceof MovementParkour) {
|
||||
boolean couldPlaceInstead = Baritone.settings().allowPlace.value && behavior.baritone.getInventoryBehavior().hasGenericThrowaway() && next instanceof MovementParkour; // traverse doesn't react fast enough
|
||||
// this is true if the next movement does not ascend or descends and goes into the same cardinal direction (N-NE-E-SE-S-SW-W-NW) as the descend
|
||||
// in that case current.getDirection() is e.g. (0, -1, 1) and next.getDirection() is e.g. (0, 0, 3) so the cross product of (0, 0, 1) and (0, 0, 3) is taken, which is (0, 0, 0) because the vectors are colinear (don't form a plane)
|
||||
// since movements in exactly the opposite direction (e.g. descend (0, -1, 1) and traverse (0, 0, -1)) would also pass this check we also have to rule out that case
|
||||
// we can do that by adding the directions because traverse is always 1 long like descend and parkour can't jump through current.getSrc().down()
|
||||
boolean sameFlatDirection = !current.getDirection().above().offset(next.getDirection()).equals(BlockPos.ZERO)
|
||||
&& current.getDirection().above().cross(next.getDirection()).equals(BlockPos.ZERO); // here's why you learn maths in school
|
||||
if (sameFlatDirection && !couldPlaceInstead) {
|
||||
((MovementDescend) current).forceSafeMode();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (((MovementDescend) current).safeMode() && !((MovementDescend) current).skipToAscend()) {
|
||||
logDebug("Sprinting would be unsafe");
|
||||
return false;
|
||||
@@ -395,11 +415,20 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
return true;
|
||||
}
|
||||
if (canSprintFromDescendInto(ctx, current, next)) {
|
||||
|
||||
if (next instanceof MovementDescend && pathPosition < path.length() - 3) {
|
||||
IMovement next_next = path.movements().get(pathPosition + 2);
|
||||
if (next_next instanceof MovementDescend && !canSprintFromDescendInto(ctx, next, next_next)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
}
|
||||
if (ctx.playerFeet().equals(current.getDest())) {
|
||||
pathPosition++;
|
||||
onChangeInPathPosition();
|
||||
onTick();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
|
||||
|
||||
117
src/main/java/baritone/pathing/precompute/PrecomputedData.java
Normal file
117
src/main/java/baritone/pathing/precompute/PrecomputedData.java
Normal file
@@ -0,0 +1,117 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.precompute;
|
||||
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import static baritone.pathing.precompute.Ternary.MAYBE;
|
||||
import static baritone.pathing.precompute.Ternary.YES;
|
||||
|
||||
public class PrecomputedData {
|
||||
|
||||
private final int[] data = new int[Block.BLOCK_STATE_REGISTRY.size()];
|
||||
|
||||
private static final int COMPLETED_MASK = 1 << 0;
|
||||
private static final int CAN_WALK_ON_MASK = 1 << 1;
|
||||
private static final int CAN_WALK_ON_SPECIAL_MASK = 1 << 2;
|
||||
private static final int CAN_WALK_THROUGH_MASK = 1 << 3;
|
||||
private static final int CAN_WALK_THROUGH_SPECIAL_MASK = 1 << 4;
|
||||
private static final int FULLY_PASSABLE_MASK = 1 << 5;
|
||||
private static final int FULLY_PASSABLE_SPECIAL_MASK = 1 << 6;
|
||||
|
||||
private int fillData(int id, BlockState state) {
|
||||
int blockData = 0;
|
||||
|
||||
Ternary canWalkOnState = MovementHelper.canWalkOnBlockState(state);
|
||||
if (canWalkOnState == YES) {
|
||||
blockData |= CAN_WALK_ON_MASK;
|
||||
}
|
||||
if (canWalkOnState == MAYBE) {
|
||||
blockData |= CAN_WALK_ON_SPECIAL_MASK;
|
||||
}
|
||||
|
||||
Ternary canWalkThroughState = MovementHelper.canWalkThroughBlockState(state);
|
||||
if (canWalkThroughState == YES) {
|
||||
blockData |= CAN_WALK_THROUGH_MASK;
|
||||
}
|
||||
if (canWalkThroughState == MAYBE) {
|
||||
blockData |= CAN_WALK_THROUGH_SPECIAL_MASK;
|
||||
}
|
||||
|
||||
Ternary fullyPassableState = MovementHelper.fullyPassableBlockState(state);
|
||||
if (fullyPassableState == YES) {
|
||||
blockData |= FULLY_PASSABLE_MASK;
|
||||
}
|
||||
if (fullyPassableState == MAYBE) {
|
||||
blockData |= FULLY_PASSABLE_SPECIAL_MASK;
|
||||
}
|
||||
|
||||
blockData |= COMPLETED_MASK;
|
||||
|
||||
data[id] = blockData; // in theory, this is thread "safe" because every thread should compute the exact same int to write?
|
||||
return blockData;
|
||||
}
|
||||
|
||||
public boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
int id = Block.BLOCK_STATE_REGISTRY.getId(state);
|
||||
int blockData = data[id];
|
||||
|
||||
if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data
|
||||
blockData = fillData(id, state);
|
||||
}
|
||||
|
||||
if ((blockData & CAN_WALK_ON_SPECIAL_MASK) != 0) {
|
||||
return MovementHelper.canWalkOnPosition(bsi, x, y, z, state);
|
||||
} else {
|
||||
return (blockData & CAN_WALK_ON_MASK) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
int id = Block.BLOCK_STATE_REGISTRY.getId(state);
|
||||
int blockData = data[id];
|
||||
|
||||
if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data
|
||||
blockData = fillData(id, state);
|
||||
}
|
||||
|
||||
if ((blockData & CAN_WALK_THROUGH_SPECIAL_MASK) != 0) {
|
||||
return MovementHelper.canWalkThroughPosition(bsi, x, y, z, state);
|
||||
} else {
|
||||
return (blockData & CAN_WALK_THROUGH_MASK) != 0;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean fullyPassable(BlockStateInterface bsi, int x, int y, int z, BlockState state) {
|
||||
int id = Block.BLOCK_STATE_REGISTRY.getId(state);
|
||||
int blockData = data[id];
|
||||
|
||||
if ((blockData & COMPLETED_MASK) == 0) { // we need to fill in the data
|
||||
blockData = fillData(id, state);
|
||||
}
|
||||
|
||||
if ((blockData & FULLY_PASSABLE_SPECIAL_MASK) != 0) {
|
||||
return MovementHelper.fullyPassablePosition(bsi, x, y, z, state);
|
||||
} else {
|
||||
return (blockData & FULLY_PASSABLE_MASK) != 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,24 +15,8 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.cache;
|
||||
package baritone.pathing.precompute;
|
||||
|
||||
import java.util.List;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public interface IRememberedInventory {
|
||||
|
||||
/**
|
||||
* @return The contents of this inventory
|
||||
*/
|
||||
List<ItemStack> getContents();
|
||||
|
||||
/**
|
||||
* @return The number of slots in this inventory
|
||||
*/
|
||||
int getSize();
|
||||
public enum Ternary {
|
||||
YES, MAYBE, NO
|
||||
}
|
||||
@@ -54,12 +54,12 @@ public final class BackfillProcess extends BaritoneProcessHelper {
|
||||
Baritone.settings().backfill.value = false;
|
||||
return false;
|
||||
}
|
||||
amIBreakingABlockHMMMMMMM();
|
||||
for (BlockPos pos : new ArrayList<>(blocksToReplace.keySet())) {
|
||||
if (ctx.world().getChunk(pos) instanceof EmptyLevelChunk) {
|
||||
if (ctx.world().getChunk(pos) instanceof EmptyLevelChunk || ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) {
|
||||
blocksToReplace.remove(pos);
|
||||
}
|
||||
}
|
||||
amIBreakingABlockHMMMMMMM();
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
|
||||
return !toFillIn().isEmpty();
|
||||
@@ -91,7 +91,7 @@ public final class BackfillProcess extends BaritoneProcessHelper {
|
||||
}
|
||||
|
||||
private void amIBreakingABlockHMMMMMMM() {
|
||||
if (!ctx.getSelectedBlock().isPresent()) {
|
||||
if (!ctx.getSelectedBlock().isPresent() || !baritone.getPathingBehavior().isPathing()) {
|
||||
return;
|
||||
}
|
||||
blocksToReplace.put(ctx.getSelectedBlock().get(), ctx.world().getBlockState(ctx.getSelectedBlock().get()));
|
||||
|
||||
@@ -28,6 +28,7 @@ import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.schematic.FillSchematic;
|
||||
import baritone.api.schematic.ISchematic;
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.api.schematic.SubstituteSchematic;
|
||||
import baritone.api.schematic.format.ISchematicFormat;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.RayTraceUtils;
|
||||
@@ -39,34 +40,41 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.NotificationHelper;
|
||||
import baritone.utils.PathingCommandContext;
|
||||
import baritone.utils.schematic.MapArtSchematic;
|
||||
import baritone.utils.schematic.SelectionSchematic;
|
||||
import baritone.utils.schematic.SchematicSystem;
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.utils.schematic.litematica.LitematicaHelper;
|
||||
import baritone.utils.schematic.schematica.SchematicaHelper;
|
||||
import com.google.common.collect.ImmutableMap;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.NbtIo;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.world.InteractionHand;
|
||||
import net.minecraft.world.item.BlockItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.context.BlockPlaceContext;
|
||||
import net.minecraft.world.item.context.UseOnContext;
|
||||
import net.minecraft.world.level.block.AirBlock;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.LiquidBlock;
|
||||
import net.minecraft.world.level.block.*;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import net.minecraft.world.phys.AABB;
|
||||
import net.minecraft.world.phys.BlockHitResult;
|
||||
import net.minecraft.world.phys.HitResult;
|
||||
import net.minecraft.world.phys.Vec3;
|
||||
import net.minecraft.world.phys.shapes.VoxelShape;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.nio.file.Files;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
|
||||
@@ -83,6 +91,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
private int layer;
|
||||
private int numRepeats;
|
||||
private List<BlockState> approxPlaceable;
|
||||
public int stopAtHeight = 0;
|
||||
|
||||
public BuilderProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
@@ -93,6 +102,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
this.name = name;
|
||||
this.schematic = schematic;
|
||||
this.realSchematic = null;
|
||||
boolean buildingSelectionSchematic = schematic instanceof SelectionSchematic;
|
||||
if (!Baritone.settings().buildSubstitutes.value.isEmpty()) {
|
||||
this.schematic = new SubstituteSchematic(this.schematic, Baritone.settings().buildSubstitutes.value);
|
||||
}
|
||||
int x = origin.getX();
|
||||
int y = origin.getY();
|
||||
int z = origin.getZ();
|
||||
@@ -108,8 +121,28 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
this.origin = new Vec3i(x, y, z);
|
||||
this.paused = false;
|
||||
this.layer = Baritone.settings().startAtLayer.value;
|
||||
this.stopAtHeight = schematic.heightY();
|
||||
if (Baritone.settings().buildOnlySelection.value && buildingSelectionSchematic) { // currently redundant but safer maybe
|
||||
if (baritone.getSelectionManager().getSelections().length == 0) {
|
||||
logDirect("Poor little kitten forgot to set a selection while BuildOnlySelection is true");
|
||||
this.stopAtHeight = 0;
|
||||
} else if (Baritone.settings().buildInLayers.value) {
|
||||
OptionalInt minim = Stream.of(baritone.getSelectionManager().getSelections()).mapToInt(sel -> sel.min().y).min();
|
||||
OptionalInt maxim = Stream.of(baritone.getSelectionManager().getSelections()).mapToInt(sel -> sel.max().y).max();
|
||||
if (minim.isPresent() && maxim.isPresent()) {
|
||||
int startAtHeight = Baritone.settings().layerOrder.value ? y + schematic.heightY() - maxim.getAsInt() : minim.getAsInt() - y;
|
||||
this.stopAtHeight = (Baritone.settings().layerOrder.value ? y + schematic.heightY() - minim.getAsInt() : maxim.getAsInt() - y) + 1;
|
||||
this.layer = Math.max(this.layer, startAtHeight / Baritone.settings().layerHeight.value); // startAtLayer or startAtHeight, whichever is highest
|
||||
logDebug(String.format("Schematic starts at y=%s with height %s", y, schematic.heightY()));
|
||||
logDebug(String.format("Selection starts at y=%s and ends at y=%s", minim.getAsInt(), maxim.getAsInt()));
|
||||
logDebug(String.format("Considering relevant height %s - %s", startAtHeight, this.stopAtHeight));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
this.numRepeats = 0;
|
||||
this.observedCompleted = new LongOpenHashSet();
|
||||
this.incorrectPositions = null;
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
@@ -144,6 +177,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
parsed = new MapArtSchematic((IStaticSchematic) parsed);
|
||||
}
|
||||
|
||||
if (Baritone.settings().buildOnlySelection.value) {
|
||||
parsed = new SelectionSchematic(parsed, origin, baritone.getSelectionManager().getSelections());
|
||||
}
|
||||
|
||||
|
||||
build(name, parsed, origin);
|
||||
return true;
|
||||
}
|
||||
@@ -154,10 +192,15 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
Optional<Tuple<IStaticSchematic, BlockPos>> schematic = SchematicaHelper.getOpenSchematic();
|
||||
if (schematic.isPresent()) {
|
||||
IStaticSchematic s = schematic.get().getA();
|
||||
BlockPos origin = schematic.get().getB();
|
||||
ISchematic schem = Baritone.settings().mapArtMode.value ? new MapArtSchematic(s) : s;
|
||||
if (Baritone.settings().buildOnlySelection.value) {
|
||||
schem = new SelectionSchematic(schem, origin, baritone.getSelectionManager().getSelections());
|
||||
}
|
||||
this.build(
|
||||
schematic.get().getA().toString(),
|
||||
Baritone.settings().mapArtMode.value ? new MapArtSchematic(s) : s,
|
||||
schematic.get().getB()
|
||||
schem,
|
||||
origin
|
||||
);
|
||||
} else {
|
||||
logDirect("No schematic currently open");
|
||||
@@ -167,6 +210,28 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildOpenLitematic(int i) {
|
||||
if (LitematicaHelper.isLitematicaPresent()) {
|
||||
//if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager
|
||||
if (LitematicaHelper.hasLoadedSchematic()) {
|
||||
String name = LitematicaHelper.getName(i);
|
||||
try {
|
||||
LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath())), false);
|
||||
Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i);
|
||||
LitematicaSchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
|
||||
build(name, schematic2, correctedOrigin);
|
||||
} catch (Exception e) {
|
||||
logDirect("Schematic File could not be loaded.");
|
||||
}
|
||||
} else {
|
||||
logDirect("No schematic currently loaded");
|
||||
}
|
||||
} else {
|
||||
logDirect("Litematica is not present");
|
||||
}
|
||||
}
|
||||
|
||||
public void clearArea(BlockPos corner1, BlockPos corner2) {
|
||||
BlockPos origin = new BlockPos(Math.min(corner1.getX(), corner2.getX()), Math.min(corner1.getY(), corner2.getY()), Math.min(corner1.getZ(), corner2.getZ()));
|
||||
int widthX = Math.abs(corner1.getX() - corner2.getX()) + 1;
|
||||
@@ -363,6 +428,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
return onTick(calcFailed, isSafeToCancel, 0);
|
||||
}
|
||||
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel, int recursions) {
|
||||
if (recursions > 1000) { // onTick calls itself, don't crash
|
||||
return new PathingCommand(null, PathingCommandType.SET_GOAL_AND_PATH);
|
||||
}
|
||||
approxPlaceable = approxPlaceable(36);
|
||||
if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) {
|
||||
ticks = 5;
|
||||
@@ -384,9 +456,9 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
// layer = realSchematic.heightY() should be everything
|
||||
if (Baritone.settings().layerOrder.value) { // top to bottom
|
||||
maxYInclusive = realSchematic.heightY() - 1;
|
||||
minYInclusive = realSchematic.heightY() - layer;
|
||||
minYInclusive = realSchematic.heightY() - layer * Baritone.settings().layerHeight.value;
|
||||
} else {
|
||||
maxYInclusive = layer - 1;
|
||||
maxYInclusive = layer * Baritone.settings().layerHeight.value - 1;
|
||||
minYInclusive = 0;
|
||||
}
|
||||
schematic = new ISchematic() {
|
||||
@@ -400,6 +472,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return ISchematic.super.inSchematic(x, y, z, currentState) && y >= minYInclusive && y <= maxYInclusive && realSchematic.inSchematic(x, y, z, currentState);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
realSchematic.reset();
|
||||
}
|
||||
|
||||
@Override
|
||||
public int widthX() {
|
||||
return realSchematic.widthX();
|
||||
@@ -418,18 +495,18 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
BuilderCalculationContext bcc = new BuilderCalculationContext();
|
||||
if (!recalc(bcc)) {
|
||||
if (Baritone.settings().buildInLayers.value && layer < realSchematic.heightY()) {
|
||||
if (Baritone.settings().buildInLayers.value && layer * Baritone.settings().layerHeight.value < stopAtHeight) {
|
||||
logDirect("Starting layer " + layer);
|
||||
layer++;
|
||||
return onTick(calcFailed, isSafeToCancel);
|
||||
return onTick(calcFailed, isSafeToCancel, recursions + 1);
|
||||
}
|
||||
Vec3i repeat = Baritone.settings().buildRepeat.value;
|
||||
int max = Baritone.settings().buildRepeatCount.value;
|
||||
numRepeats++;
|
||||
if (repeat.equals(new Vec3i(0, 0, 0)) || (max != -1 && numRepeats >= max)) {
|
||||
logDirect("Done building");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnBuildFinished.value) {
|
||||
NotificationHelper.notify("Done building", false);
|
||||
if (Baritone.settings().notificationOnBuildFinished.value) {
|
||||
logNotification("Done building", false);
|
||||
}
|
||||
onLostControl();
|
||||
return null;
|
||||
@@ -437,8 +514,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
// build repeat time
|
||||
layer = 0;
|
||||
origin = new BlockPos(origin).offset(repeat);
|
||||
if (!Baritone.settings().buildRepeatSneaky.value) {
|
||||
schematic.reset();
|
||||
}
|
||||
logDirect("Repeating build in vector " + repeat + ", new origin is " + origin);
|
||||
return onTick(calcFailed, isSafeToCancel);
|
||||
return onTick(calcFailed, isSafeToCancel, recursions + 1);
|
||||
}
|
||||
if (Baritone.settings().distanceTrim.value) {
|
||||
trim();
|
||||
@@ -505,10 +585,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (goal == null) {
|
||||
goal = assemble(bcc, approxPlaceable, true); // we're far away, so assume that we have our whole inventory to recalculate placeable properly
|
||||
if (goal == null) {
|
||||
if (Baritone.settings().skipFailedLayers.value && Baritone.settings().buildInLayers.value && layer < realSchematic.heightY()) {
|
||||
if (Baritone.settings().skipFailedLayers.value && Baritone.settings().buildInLayers.value && layer * Baritone.settings().layerHeight.value < realSchematic.heightY()) {
|
||||
logDirect("Skipping layer that I cannot construct! Layer #" + layer);
|
||||
layer++;
|
||||
return onTick(calcFailed, isSafeToCancel);
|
||||
return onTick(calcFailed, isSafeToCancel, recursions + 1);
|
||||
}
|
||||
logDirect("Unable to do it. Pausing. resume to resume, cancel to cancel");
|
||||
paused = true;
|
||||
@@ -593,7 +673,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
continue;
|
||||
}
|
||||
// this is not in render distance
|
||||
if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))) {
|
||||
if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))
|
||||
&& !Baritone.settings().buildSkipBlocks.value.contains(schematic.desiredState(x, y, z, current, this.approxPlaceable).getBlock())) {
|
||||
// and we've never seen this position be correct
|
||||
// therefore mark as incorrect
|
||||
incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
|
||||
@@ -816,12 +897,52 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
continue;
|
||||
}
|
||||
// <toxic cloud>
|
||||
result.add(((BlockItem) stack.getItem()).getBlock().getStateForPlacement(new BlockPlaceContext(new UseOnContext(ctx.world(), ctx.player(), InteractionHand.MAIN_HAND, stack, new BlockHitResult(new Vec3(ctx.player().position().x, ctx.player().position().y, ctx.player().position().z), Direction.UP, ctx.playerFeet(), false)) {})));
|
||||
BlockState itemState = ((BlockItem) stack.getItem())
|
||||
.getBlock()
|
||||
.getStateForPlacement(
|
||||
new BlockPlaceContext(
|
||||
new UseOnContext(ctx.world(), ctx.player(), InteractionHand.MAIN_HAND, stack, new BlockHitResult(new Vec3(ctx.player().position().x, ctx.player().position().y, ctx.player().position().z), Direction.UP, ctx.playerFeet(), false)) {}
|
||||
)
|
||||
);
|
||||
if (itemState != null) {
|
||||
result.add(itemState);
|
||||
} else {
|
||||
result.add(Blocks.AIR.defaultBlockState());
|
||||
}
|
||||
// </toxic cloud>
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
public static final Set<Property<?>> orientationProps =
|
||||
ImmutableSet.of(
|
||||
RotatedPillarBlock.AXIS, HorizontalDirectionalBlock.FACING,
|
||||
StairBlock.FACING, StairBlock.HALF, StairBlock.SHAPE,
|
||||
PipeBlock.NORTH, PipeBlock.EAST, PipeBlock.SOUTH, PipeBlock.WEST, PipeBlock.UP,
|
||||
TrapDoorBlock.OPEN, TrapDoorBlock.HALF
|
||||
);
|
||||
|
||||
private boolean sameBlockstate(BlockState first, BlockState second) {
|
||||
if (first.getBlock() != second.getBlock()) {
|
||||
return false;
|
||||
}
|
||||
boolean ignoreDirection = Baritone.settings().buildIgnoreDirection.value;
|
||||
List<String> ignoredProps = Baritone.settings().buildIgnoreProperties.value;
|
||||
if (!ignoreDirection && ignoredProps.isEmpty()) {
|
||||
return first.equals(second); // early return if no properties are being ignored
|
||||
}
|
||||
ImmutableMap<Property<?>, Comparable<?>> map1 = first.getValues();
|
||||
ImmutableMap<Property<?>, Comparable<?>> map2 = second.getValues();
|
||||
for (Property<?> prop : map1.keySet()) {
|
||||
if (map1.get(prop) != map2.get(prop)
|
||||
&& !(ignoreDirection && orientationProps.contains(prop))
|
||||
&& !ignoredProps.contains(prop.getName())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private boolean valid(BlockState current, BlockState desired, boolean itemVerify) {
|
||||
if (desired == null) {
|
||||
return true;
|
||||
@@ -838,10 +959,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (desired.getBlock() instanceof AirBlock && Baritone.settings().buildIgnoreBlocks.value.contains(current.getBlock())) {
|
||||
return true;
|
||||
}
|
||||
if (!(current.getBlock() instanceof AirBlock) && Baritone.settings().buildIgnoreExisting.value && !itemVerify) {
|
||||
if (Baritone.settings().buildSkipBlocks.value.contains(desired.getBlock()) && !itemVerify) {
|
||||
return true;
|
||||
}
|
||||
return current.equals(desired);
|
||||
if (Baritone.settings().buildValidSubstitutes.value.getOrDefault(desired.getBlock(), Collections.emptyList()).contains(current.getBlock()) && !itemVerify) {
|
||||
return true;
|
||||
}
|
||||
if (current.equals(desired)) {
|
||||
return true;
|
||||
}
|
||||
return sameBlockstate(current, desired);
|
||||
}
|
||||
|
||||
public class BuilderCalculationContext extends CalculationContext {
|
||||
@@ -878,7 +1005,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return COST_INF;
|
||||
}
|
||||
BlockState sch = getSchematic(x, y, z, current);
|
||||
if (sch != null) {
|
||||
if (sch != null && !Baritone.settings().buildSkipBlocks.value.contains(sch.getBlock())) {
|
||||
// TODO this can return true even when allowPlace is off.... is that an issue?
|
||||
if (sch.getBlock() instanceof AirBlock) {
|
||||
// we want this to be air, but they're asking if they can place here
|
||||
@@ -908,11 +1035,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
|
||||
@Override
|
||||
public double breakCostMultiplierAt(int x, int y, int z, BlockState current) {
|
||||
if (!allowBreak || isPossiblyProtected(x, y, z)) {
|
||||
if ((!allowBreak && !allowBreakAnyway.contains(current.getBlock())) || isPossiblyProtected(x, y, z)) {
|
||||
return COST_INF;
|
||||
}
|
||||
BlockState sch = getSchematic(x, y, z, current);
|
||||
if (sch != null) {
|
||||
if (sch != null && !Baritone.settings().buildSkipBlocks.value.contains(sch.getBlock())) {
|
||||
if (sch.getBlock() instanceof AirBlock) {
|
||||
// it should be air
|
||||
// regardless of current contents, we can break it
|
||||
|
||||
@@ -23,7 +23,6 @@ import baritone.api.process.ICustomGoalProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.NotificationHelper;
|
||||
|
||||
/**
|
||||
* As set by ExampleBaritoneControl or something idk
|
||||
@@ -94,8 +93,8 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC
|
||||
if (Baritone.settings().disconnectOnArrival.value) {
|
||||
ctx.world().disconnect();
|
||||
}
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnPathComplete.value) {
|
||||
NotificationHelper.notify("Pathing complete", false);
|
||||
if (Baritone.settings().notificationOnPathComplete.value) {
|
||||
logNotification("Pathing complete", false);
|
||||
}
|
||||
return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.MyChunkPos;
|
||||
import baritone.cache.CachedWorld;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.NotificationHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
@@ -83,8 +82,8 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (calcFailed) {
|
||||
logDirect("Failed");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnExploreFinished.value) {
|
||||
NotificationHelper.notify("Exploration failed", true);
|
||||
if (Baritone.settings().notificationOnExploreFinished.value) {
|
||||
logNotification("Exploration failed", true);
|
||||
}
|
||||
onLostControl();
|
||||
return null;
|
||||
@@ -92,8 +91,8 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
IChunkFilter filter = calcFilter();
|
||||
if (!Baritone.settings().disableCompletionCheck.value && filter.countRemain() == 0) {
|
||||
logDirect("Explored all chunks");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnExploreFinished.value) {
|
||||
NotificationHelper.notify("Explored all chunks", false);
|
||||
if (Baritone.settings().notificationOnExploreFinished.value) {
|
||||
logNotification("Explored all chunks", false);
|
||||
}
|
||||
onLostControl();
|
||||
return null;
|
||||
|
||||
@@ -31,7 +31,6 @@ import baritone.api.utils.input.Input;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.NotificationHelper;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -276,8 +275,8 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
|
||||
|
||||
if (calcFailed) {
|
||||
logDirect("Farm failed");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnFarmFail.value) {
|
||||
NotificationHelper.notify("Farm failed", true);
|
||||
if (Baritone.settings().notificationOnFarmFail.value) {
|
||||
logNotification("Farm failed", true);
|
||||
}
|
||||
onLostControl();
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
|
||||
@@ -30,11 +30,13 @@ import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import java.util.*;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.inventory.InventoryMenu;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
|
||||
|
||||
@@ -57,7 +59,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
start = ctx.playerFeet();
|
||||
blacklist = new ArrayList<>();
|
||||
arrivalTickCount = 0;
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
rescan(new ArrayList<>(), new GetToBlockCalculationContext(false));
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -68,7 +70,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
@Override
|
||||
public synchronized PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (knownLocations == null) {
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
rescan(new ArrayList<>(), new GetToBlockCalculationContext(false));
|
||||
}
|
||||
if (knownLocations.isEmpty()) {
|
||||
if (Baritone.settings().exploreForBlocks.value && !calcFailed) {
|
||||
@@ -77,6 +79,11 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
}, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
|
||||
@@ -102,7 +109,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value;
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> current = new ArrayList<>(knownLocations);
|
||||
CalculationContext context = new CalculationContext(baritone, true);
|
||||
CalculationContext context = new GetToBlockCalculationContext(true);
|
||||
Baritone.getExecutor().execute(() -> rescan(current, context));
|
||||
}
|
||||
if (goal.isInGoal(ctx.playerFeet()) && goal.isInGoal(baritone.getPathingBehavior().pathStart()) && isSafeToCancel) {
|
||||
@@ -147,6 +154,20 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
return !newBlacklist.isEmpty();
|
||||
}
|
||||
|
||||
// this is to signal to MineProcess that we don't care about the allowBreak setting
|
||||
// it is NOT to be used to actually calculate a path
|
||||
public class GetToBlockCalculationContext extends CalculationContext {
|
||||
|
||||
public GetToBlockCalculationContext(boolean forUseOnAnotherThread) {
|
||||
super(GetToBlockProcess.super.baritone, forUseOnAnotherThread);
|
||||
}
|
||||
|
||||
@Override
|
||||
public double breakCostMultiplierAt(int x, int y, int z, BlockState current) {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
|
||||
// safer than direct double comparison from distanceSq
|
||||
private boolean areAdjacent(BlockPos posA, BlockPos posB) {
|
||||
int diffX = Math.abs(posA.getX() - posB.getX());
|
||||
@@ -222,7 +243,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
if (!Baritone.settings().rightClickContainerOnArrival.value) {
|
||||
return false;
|
||||
}
|
||||
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
|
||||
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.BLAST_FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
|
||||
}
|
||||
|
||||
private boolean blockOnTopMustBeRemoved(Block block) {
|
||||
|
||||
@@ -30,7 +30,6 @@ import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.NotificationHelper;
|
||||
import net.minecraft.client.multiplayer.ClientLevel;
|
||||
import net.minecraft.core.BlockPos;
|
||||
import net.minecraft.world.entity.Entity;
|
||||
@@ -41,6 +40,7 @@ import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.Blocks;
|
||||
import net.minecraft.world.level.block.FallingBlock;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
@@ -89,25 +89,21 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
if (calcFailed) {
|
||||
if (!knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
|
||||
logDirect("Unable to find any path to " + filter + ", blacklisting presumably unreachable closest instance...");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) {
|
||||
NotificationHelper.notify("Unable to find any path to " + filter + ", blacklisting presumably unreachable closest instance...", true);
|
||||
if (Baritone.settings().notificationOnMineFail.value) {
|
||||
logNotification("Unable to find any path to " + filter + ", blacklisting presumably unreachable closest instance...", true);
|
||||
}
|
||||
knownOreLocations.stream().min(Comparator.comparingDouble(ctx.playerFeet()::distSqr)).ifPresent(blacklist::add);
|
||||
knownOreLocations.removeIf(blacklist::contains);
|
||||
} else {
|
||||
logDirect("Unable to find any path to " + filter + ", canceling mine");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) {
|
||||
NotificationHelper.notify("Unable to find any path to " + filter + ", canceling mine", true);
|
||||
if (Baritone.settings().notificationOnMineFail.value) {
|
||||
logNotification("Unable to find any path to " + filter + ", canceling mine", true);
|
||||
}
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (!Baritone.settings().allowBreak.value) {
|
||||
logDirect("Unable to mine when allowBreak is false!");
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
|
||||
updateLoucaSystem();
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value;
|
||||
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||
@@ -116,7 +112,10 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
Baritone.getExecutor().execute(() -> rescan(curr, context));
|
||||
}
|
||||
if (Baritone.settings().legitMine.value) {
|
||||
addNearby();
|
||||
if (!addNearby()) {
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Optional<BlockPos> shaft = curr.stream()
|
||||
.filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ())
|
||||
@@ -178,6 +177,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
}
|
||||
|
||||
private PathingCommand updateGoal() {
|
||||
BlockOptionalMetaLookup filter = filterFilter();
|
||||
if (filter == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
boolean legit = Baritone.settings().legitMine.value;
|
||||
List<BlockPos> locs = knownOreLocations;
|
||||
if (!locs.isEmpty()) {
|
||||
@@ -189,10 +193,10 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
return new PathingCommand(goal, legit ? PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
// we don't know any ore locations at the moment
|
||||
if (!legit) {
|
||||
if (!legit && !Baritone.settings().exploreForBlocks.value) {
|
||||
return null;
|
||||
}
|
||||
// only in non-Xray mode (aka legit mode) do we do this
|
||||
// only when we should explore for blocks or are in legit mode we do this
|
||||
int y = Baritone.settings().legitMineYLevel.value;
|
||||
if (branchPoint == null) {
|
||||
/*if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
|
||||
@@ -212,12 +216,18 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic() {
|
||||
return Double.NEGATIVE_INFINITY;
|
||||
}
|
||||
};
|
||||
}
|
||||
return new PathingCommand(branchPointRunaway, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
private void rescan(List<BlockPos> already, CalculationContext context) {
|
||||
BlockOptionalMetaLookup filter = filterFilter();
|
||||
if (filter == null) {
|
||||
return;
|
||||
}
|
||||
@@ -227,10 +237,10 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
List<BlockPos> dropped = droppedItemsScan();
|
||||
List<BlockPos> locs = searchWorld(context, filter, ORE_LOCATIONS_COUNT, already, blacklist, dropped);
|
||||
locs.addAll(dropped);
|
||||
if (locs.isEmpty()) {
|
||||
if (locs.isEmpty() && !Baritone.settings().exploreForBlocks.value) {
|
||||
logDirect("No locations for " + filter + " known, cancelling");
|
||||
if (Baritone.settings().desktopNotifications.value && Baritone.settings().notificationOnMineFail.value) {
|
||||
NotificationHelper.notify("No locations for " + filter + " known, cancelling", true);
|
||||
if (Baritone.settings().notificationOnMineFail.value) {
|
||||
logNotification("No locations for " + filter + " known, cancelling", true);
|
||||
}
|
||||
cancel();
|
||||
return;
|
||||
@@ -367,11 +377,18 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
return prune(ctx, locs, filter, max, blacklist, dropped);
|
||||
}
|
||||
|
||||
private void addNearby() {
|
||||
private boolean addNearby() {
|
||||
List<BlockPos> dropped = droppedItemsScan();
|
||||
knownOreLocations.addAll(dropped);
|
||||
BlockPos playerFeet = ctx.playerFeet();
|
||||
BlockStateInterface bsi = new BlockStateInterface(ctx);
|
||||
|
||||
|
||||
BlockOptionalMetaLookup filter = filterFilter();
|
||||
if (filter == null) {
|
||||
return false;
|
||||
}
|
||||
|
||||
int searchDist = 10;
|
||||
double fakedBlockReachDistance = 20; // at least 10 * sqrt(3) with some extra space to account for positioning within the block
|
||||
for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) {
|
||||
@@ -389,6 +406,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
}
|
||||
}
|
||||
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, filter, ORE_LOCATIONS_COUNT, blacklist, dropped);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, BlockOptionalMetaLookup filter, int max, List<BlockPos> blacklist, List<BlockPos> dropped) {
|
||||
@@ -464,10 +482,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
@Override
|
||||
public void mine(int quantity, BlockOptionalMetaLookup filter) {
|
||||
this.filter = filter;
|
||||
if (filter != null && !Baritone.settings().allowBreak.value) {
|
||||
logDirect("Unable to mine when allowBreak is false!");
|
||||
this.mine(quantity, (BlockOptionalMetaLookup) null);
|
||||
return;
|
||||
if (this.filterFilter() == null) {
|
||||
this.filter = null;
|
||||
}
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
@@ -479,4 +495,22 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
}
|
||||
}
|
||||
|
||||
private BlockOptionalMetaLookup filterFilter() {
|
||||
if (this.filter == null) {
|
||||
return null;
|
||||
}
|
||||
if (!Baritone.settings().allowBreak.value) {
|
||||
BlockOptionalMetaLookup f = new BlockOptionalMetaLookup(this.filter.blocks()
|
||||
.stream()
|
||||
.filter(e -> Baritone.settings().allowBreakAnyway.value.contains(e.getBlock()))
|
||||
.toArray(BlockOptionalMeta[]::new));
|
||||
if (f.blocks().isEmpty()) {
|
||||
logDirect("Unable to mine when allowBreak is false and target block is not in allowBreakAnyway!");
|
||||
return null;
|
||||
}
|
||||
return f;
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,7 @@ import baritone.api.utils.IPlayerContext;
|
||||
import baritone.cache.CachedRegion;
|
||||
import baritone.cache.WorldData;
|
||||
import baritone.utils.accessor.IClientChunkProvider;
|
||||
import baritone.utils.pathing.BetterWorldBorder;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ClientChunkCache;
|
||||
import net.minecraft.core.BlockPos;
|
||||
@@ -43,9 +44,10 @@ public class BlockStateInterface {
|
||||
|
||||
private final ClientChunkCache provider;
|
||||
private final WorldData worldData;
|
||||
protected final BlockGetter world;
|
||||
protected final Level world;
|
||||
public final BlockPos.MutableBlockPos isPassableBlockPos;
|
||||
public final BlockGetter access;
|
||||
public final BetterWorldBorder worldBorder;
|
||||
|
||||
private LevelChunk prev = null;
|
||||
private CachedRegion prevCached = null;
|
||||
@@ -64,6 +66,7 @@ public class BlockStateInterface {
|
||||
|
||||
public BlockStateInterface(Level world, WorldData worldData, boolean copyLoadedChunks) {
|
||||
this.world = world;
|
||||
this.worldBorder = new BetterWorldBorder(world.getWorldBorder());
|
||||
this.worldData = worldData;
|
||||
if (copyLoadedChunks) {
|
||||
this.provider = ((IClientChunkProvider) world.getChunkSource()).createThreadSafeCopy();
|
||||
@@ -97,9 +100,9 @@ public class BlockStateInterface {
|
||||
}
|
||||
|
||||
public BlockState get0(int x, int y, int z) { // Mickey resigned
|
||||
y -= worldData.dimension.minY();
|
||||
y -= world.dimensionType().minY();
|
||||
// Invalid vertical position
|
||||
if (y < 0 || y >= worldData.dimension.height()) {
|
||||
if (y < 0 || y >= world.dimensionType().height()) {
|
||||
return AIR;
|
||||
}
|
||||
|
||||
@@ -169,7 +172,7 @@ public class BlockStateInterface {
|
||||
// get the block at x,y,z from this chunk WITHOUT creating a single blockpos object
|
||||
public static BlockState getFromChunk(LevelChunk chunk, int x, int y, int z) {
|
||||
LevelChunkSection section = chunk.getSections()[y >> 4];
|
||||
if (LevelChunkSection.isEmpty(section)) {
|
||||
if (section.hasOnlyAir()) {
|
||||
return AIR;
|
||||
}
|
||||
return section.getBlockState(x & 15, y & 15, z & 15);
|
||||
|
||||
@@ -91,12 +91,12 @@ public class GuiClick extends Screen implements Helper {
|
||||
BaritoneAPI.getProvider().getPrimaryBaritone().getSelectionManager().removeAllSelections();
|
||||
BaritoneAPI.getProvider().getPrimaryBaritone().getSelectionManager().addSelection(BetterBlockPos.from(clickStart), BetterBlockPos.from(currentMouseOver));
|
||||
BaseComponent component = new TextComponent("Selection made! For usage: " + Baritone.settings().prefix.value + "help sel");
|
||||
component.getStyle()
|
||||
component.setStyle(component.getStyle()
|
||||
.withColor(ChatFormatting.WHITE)
|
||||
.withClickEvent(new ClickEvent(
|
||||
ClickEvent.Action.RUN_COMMAND,
|
||||
FORCE_COMMAND_PREFIX + "help sel"
|
||||
));
|
||||
)));
|
||||
Helper.HELPER.logDirect(component);
|
||||
clickStart = null;
|
||||
} else {
|
||||
|
||||
@@ -225,8 +225,13 @@ public final class PathRenderer implements IRenderer, Helper {
|
||||
double minX, maxX;
|
||||
double minZ, maxZ;
|
||||
double minY, maxY;
|
||||
double y1, y2;
|
||||
double y = Mth.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
|
||||
double y, y1, y2;
|
||||
if (!settings.renderGoalAnimated.value) {
|
||||
// y = 1 causes rendering issues when the player is at the same y as the top of a block for some reason
|
||||
y = 0.999F;
|
||||
} else {
|
||||
y = Mth.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
|
||||
}
|
||||
if (goal instanceof IGoalRenderPos) {
|
||||
BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
minX = goalPos.getX() + 0.002 - renderPosX;
|
||||
@@ -265,9 +270,9 @@ public final class PathRenderer implements IRenderer, Helper {
|
||||
stack,
|
||||
mc.renderBuffers().bufferSource(),
|
||||
TEXTURE_BEACON_BEAM,
|
||||
partialTicks,
|
||||
settings.renderGoalAnimated.value ? partialTicks : 0,
|
||||
1.0F,
|
||||
player.level.getGameTime(),
|
||||
settings.renderGoalAnimated.value ? player.level.getGameTime() : 0,
|
||||
0,
|
||||
256,
|
||||
color.getColorComponents(null),
|
||||
|
||||
@@ -18,18 +18,20 @@
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
import net.minecraft.client.player.LocalPlayer;
|
||||
import net.minecraft.world.effect.MobEffects;
|
||||
import net.minecraft.world.item.DiggerItem;
|
||||
import net.minecraft.world.item.ItemStack;
|
||||
import net.minecraft.world.item.SwordItem;
|
||||
import net.minecraft.world.item.TieredItem;
|
||||
import net.minecraft.world.item.enchantment.EnchantmentHelper;
|
||||
import net.minecraft.world.item.enchantment.Enchantments;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Function;
|
||||
|
||||
/**
|
||||
* A cached list of the best tools on the hotbar for any block
|
||||
*
|
||||
@@ -74,13 +76,20 @@ public class ToolSet {
|
||||
}
|
||||
|
||||
/**
|
||||
* Evaluate the material cost of a possible tool. Will return 1 for tools, -1 for other
|
||||
* Evaluate the material cost of a possible tool. The priority matches the
|
||||
* harvest level order; there is a chance for multiple at the same with modded tools
|
||||
* but in that case we don't really care.
|
||||
*
|
||||
* @param itemStack a possibly empty ItemStack
|
||||
* @return Either 1 or -1
|
||||
* @return values from 0 up
|
||||
*/
|
||||
private int getMaterialCost(ItemStack itemStack) {
|
||||
return itemStack.getItem() instanceof DiggerItem ? 1 : -1;
|
||||
if (itemStack.getItem() instanceof TieredItem) {
|
||||
TieredItem tool = (TieredItem) itemStack.getItem();
|
||||
return tool.getTier().getLevel();
|
||||
} else {
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean hasSilkTouch(ItemStack stack) {
|
||||
@@ -105,7 +114,7 @@ public class ToolSet {
|
||||
If we actually want know what efficiency our held item has instead of the best one
|
||||
possible, this lets us make pathing depend on the actual tool to be used (if auto tool is disabled)
|
||||
*/
|
||||
if (Baritone.settings().disableAutoTool.value && pathingCalculation) {
|
||||
if (!Baritone.settings().autoTool.value && pathingCalculation) {
|
||||
return player.getInventory().selected;
|
||||
}
|
||||
|
||||
@@ -116,6 +125,13 @@ public class ToolSet {
|
||||
BlockState blockState = b.defaultBlockState();
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack itemStack = player.getInventory().getItem(i);
|
||||
if (!Baritone.settings().useSwordToMine.value && itemStack.getItem() instanceof SwordItem) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (Baritone.settings().itemSaver.value && (itemStack.getDamageValue() + Baritone.settings().itemSaverThreshold.value) >= itemStack.getMaxDamage() && itemStack.getMaxDamage() > 1) {
|
||||
continue;
|
||||
}
|
||||
double speed = calculateSpeedVsBlock(itemStack, blockState);
|
||||
boolean silkTouch = hasSilkTouch(itemStack);
|
||||
if (speed > highestSpeed) {
|
||||
@@ -149,7 +165,7 @@ public class ToolSet {
|
||||
}
|
||||
|
||||
private double avoidanceMultiplier(Block b) {
|
||||
return Baritone.settings().blocksToAvoidBreaking.value.contains(b) ? 0.1 : 1;
|
||||
return Baritone.settings().blocksToAvoidBreaking.value.contains(b) ? Baritone.settings().avoidBreakingMultiplier.value : 1;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.schematic;
|
||||
|
||||
import baritone.api.schematic.ISchematic;
|
||||
import baritone.api.schematic.MaskSchematic;
|
||||
import baritone.api.selection.ISelection;
|
||||
import net.minecraft.core.Direction;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SelectionSchematic extends MaskSchematic {
|
||||
|
||||
private final ISelection[] selections;
|
||||
|
||||
public SelectionSchematic(ISchematic schematic, Vec3i origin, ISelection[] selections) {
|
||||
super(schematic);
|
||||
this.selections = Stream.of(selections).map(
|
||||
sel -> sel
|
||||
.shift(Direction.WEST, origin.getX())
|
||||
.shift(Direction.DOWN, origin.getY())
|
||||
.shift(Direction.NORTH, origin.getZ()))
|
||||
.toArray(ISelection[]::new);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
|
||||
for (ISelection selection : selections) {
|
||||
if (x >= selection.min().x && y >= selection.min().y && z >= selection.min().z
|
||||
&& x <= selection.max().x && y <= selection.max().y && z <= selection.max().z) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,7 @@ package baritone.utils.schematic.format;
|
||||
|
||||
import baritone.api.schematic.IStaticSchematic;
|
||||
import baritone.api.schematic.format.ISchematicFormat;
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import baritone.utils.schematic.format.defaults.MCEditSchematic;
|
||||
import baritone.utils.schematic.format.defaults.SpongeSchematic;
|
||||
import org.apache.commons.io.FilenameUtils;
|
||||
@@ -65,6 +66,26 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
|
||||
throw new UnsupportedOperationException("Unsupported Version of a Sponge Schematic");
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* The Litematica schematic specification. Commonly denoted by the ".litematic" file extension.
|
||||
*/
|
||||
LITEMATICA("litematic") {
|
||||
@Override
|
||||
public IStaticSchematic parse(InputStream input) throws IOException {
|
||||
CompoundTag nbt = NbtIo.readCompressed(input);
|
||||
int version = nbt.getInt("Version");
|
||||
switch (version) {
|
||||
case 4: //1.12
|
||||
case 5: //1.13-1.17
|
||||
throw new UnsupportedOperationException("This litematic Version is too old.");
|
||||
case 6: //1.18+
|
||||
return new LitematicaSchematic(nbt, false);
|
||||
default:
|
||||
throw new UnsupportedOperationException("Unsuported Version of a Litematica Schematic");
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
private final String extension;
|
||||
|
||||
@@ -0,0 +1,347 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.schematic.format.defaults;
|
||||
|
||||
import baritone.utils.schematic.StaticSchematic;
|
||||
import net.minecraft.core.Registry;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.nbt.CompoundTag;
|
||||
import net.minecraft.nbt.ListTag;
|
||||
import net.minecraft.resources.ResourceLocation;
|
||||
import net.minecraft.world.level.block.Block;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
import net.minecraft.world.level.block.state.properties.Property;
|
||||
import org.apache.commons.lang3.Validate;
|
||||
|
||||
import javax.annotation.Nullable;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Based on EmersonDove's work
|
||||
* <a href="https://github.com/cabaletta/baritone/pull/2544">...</a>
|
||||
*
|
||||
* @author rycbar
|
||||
* @since 22.09.2022
|
||||
*/
|
||||
public final class LitematicaSchematic extends StaticSchematic {
|
||||
private final Vec3i offsetMinCorner;
|
||||
private final CompoundTag nbt;
|
||||
|
||||
/**
|
||||
* @param nbtTagCompound a decompressed file stream aka nbt data.
|
||||
* @param rotated if the schematic is rotated by 90°.
|
||||
*/
|
||||
public LitematicaSchematic(CompoundTag nbtTagCompound, boolean rotated) {
|
||||
this.nbt = nbtTagCompound;
|
||||
this.offsetMinCorner = new Vec3i(getMinOfSchematic("x"), getMinOfSchematic("y"), getMinOfSchematic("z"));
|
||||
this.y = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("y"));
|
||||
|
||||
if (rotated) {
|
||||
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
|
||||
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
|
||||
} else {
|
||||
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
|
||||
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
|
||||
}
|
||||
this.states = new BlockState[this.x][this.z][this.y];
|
||||
fillInSchematic();
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Array of subregion names.
|
||||
*/
|
||||
private static String[] getRegions(CompoundTag nbt) {
|
||||
return nbt.getCompound("Regions").getAllKeys().toArray(new String[0]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets both ends from a region box for a given axis and returns the lower one.
|
||||
*
|
||||
* @param s axis that should be read.
|
||||
* @return the lower coord of the requested axis.
|
||||
*/
|
||||
private static int getMinOfSubregion(CompoundTag nbt, String subReg, String s) {
|
||||
int a = nbt.getCompound("Regions").getCompound(subReg).getCompound("Position").getInt(s);
|
||||
int b = nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt(s);
|
||||
if (b < 0) {
|
||||
b++;
|
||||
}
|
||||
return Math.min(a, a + b);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param blockStatePalette List of all different block types used in the schematic.
|
||||
* @return Array of BlockStates.
|
||||
*/
|
||||
private static BlockState[] getBlockList(ListTag blockStatePalette) {
|
||||
BlockState[] blockList = new BlockState[blockStatePalette.size()];
|
||||
|
||||
for (int i = 0; i < blockStatePalette.size(); i++) {
|
||||
Block block = Registry.BLOCK.get(new ResourceLocation((((CompoundTag) blockStatePalette.get(i)).getString("Name"))));
|
||||
CompoundTag properties = ((CompoundTag) blockStatePalette.get(i)).getCompound("Properties");
|
||||
|
||||
blockList[i] = getBlockState(block, properties);
|
||||
}
|
||||
return blockList;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param block block.
|
||||
* @param properties List of Properties the block has.
|
||||
* @return A blockState.
|
||||
*/
|
||||
private static BlockState getBlockState(Block block, CompoundTag properties) {
|
||||
BlockState blockState = block.defaultBlockState();
|
||||
|
||||
for (Object key : properties.getAllKeys().toArray()) {
|
||||
Property<?> property = block.getStateDefinition().getProperty((String) key);
|
||||
String propertyValue = properties.getString((String) key);
|
||||
if (property != null) {
|
||||
blockState = setPropertyValue(blockState, property, propertyValue);
|
||||
}
|
||||
}
|
||||
return blockState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @author Emerson
|
||||
*/
|
||||
private static <T extends Comparable<T>> BlockState setPropertyValue(BlockState state, Property<T> property, String value) {
|
||||
Optional<T> parsed = property.getValue(value);
|
||||
if (parsed.isPresent()) {
|
||||
return state.setValue(property, parsed.get());
|
||||
} else {
|
||||
throw new IllegalArgumentException("Invalid value for property " + property);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param amountOfBlockTypes amount of block types in the schematic.
|
||||
* @return amount of bits used to encode a block.
|
||||
*/
|
||||
private static int getBitsPerBlock(int amountOfBlockTypes) {
|
||||
return (int) Math.max(2, Math.ceil(Math.log(amountOfBlockTypes) / Math.log(2)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculates the volume of the subregion. As size can be a negative value we take the absolute value of the
|
||||
* multiplication as the volume still holds a positive amount of blocks.
|
||||
*
|
||||
* @return the volume of the subregion.
|
||||
*/
|
||||
private static long getVolume(CompoundTag nbt, String subReg) {
|
||||
return Math.abs(
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x") *
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y") *
|
||||
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array of Long values.
|
||||
*/
|
||||
private static long[] getBlockStates(CompoundTag nbt, String subReg) {
|
||||
return nbt.getCompound("Regions").getCompound(subReg).getLongArray("BlockStates");
|
||||
}
|
||||
|
||||
/**
|
||||
* Subregion don't have to be the same size as the enclosing size of the schematic. If they are smaller we check here if the current block is part of the subregion.
|
||||
*
|
||||
* @param x coord of the block relative to the minimum corner.
|
||||
* @param y coord of the block relative to the minimum corner.
|
||||
* @param z coord of the block relative to the minimum corner.
|
||||
* @return if the current block is part of the subregion.
|
||||
*/
|
||||
private static boolean inSubregion(CompoundTag nbt, String subReg, int x, int y, int z) {
|
||||
return x >= 0 && y >= 0 && z >= 0 &&
|
||||
x < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x")) &&
|
||||
y < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y")) &&
|
||||
z < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
|
||||
}
|
||||
|
||||
/**
|
||||
* @param s axis.
|
||||
* @return the lowest coordinate of that axis of the schematic.
|
||||
*/
|
||||
private int getMinOfSchematic(String s) {
|
||||
int n = Integer.MAX_VALUE;
|
||||
for (String subReg : getRegions(nbt)) {
|
||||
n = Math.min(n, getMinOfSubregion(nbt, subReg, s));
|
||||
}
|
||||
return n;
|
||||
}
|
||||
|
||||
/**
|
||||
* reads the file data.
|
||||
*/
|
||||
private void fillInSchematic() {
|
||||
for (String subReg : getRegions(nbt)) {
|
||||
ListTag usedBlockTypes = nbt.getCompound("Regions").getCompound(subReg).getList("BlockStatePalette", 10);
|
||||
BlockState[] blockList = getBlockList(usedBlockTypes);
|
||||
|
||||
int bitsPerBlock = getBitsPerBlock(usedBlockTypes.size());
|
||||
long regionVolume = getVolume(nbt, subReg);
|
||||
long[] blockStateArray = getBlockStates(nbt, subReg);
|
||||
|
||||
LitematicaBitArray bitArray = new LitematicaBitArray(bitsPerBlock, regionVolume, blockStateArray);
|
||||
|
||||
writeSubregionIntoSchematic(nbt, subReg, blockList, bitArray);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Writes the file data in to the IBlockstate array.
|
||||
*
|
||||
* @param blockList list with the different block types used in the schematic.
|
||||
* @param bitArray bit array that holds the placement pattern.
|
||||
*/
|
||||
private void writeSubregionIntoSchematic(CompoundTag nbt, String subReg, BlockState[] blockList, LitematicaBitArray bitArray) {
|
||||
Vec3i offsetSubregion = new Vec3i(getMinOfSubregion(nbt, subReg, "x"), getMinOfSubregion(nbt, subReg, "y"), getMinOfSubregion(nbt, subReg, "z"));
|
||||
int index = 0;
|
||||
for (int y = 0; y < this.y; y++) {
|
||||
for (int z = 0; z < this.z; z++) {
|
||||
for (int x = 0; x < this.x; x++) {
|
||||
if (inSubregion(nbt, subReg, x, y, z)) {
|
||||
this.states[x - (offsetMinCorner.getX() - offsetSubregion.getX())][z - (offsetMinCorner.getZ() - offsetSubregion.getZ())][y - (offsetMinCorner.getY() - offsetSubregion.getY())] = blockList[bitArray.getAt(index)];
|
||||
index++;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return offset from the schematic origin to the minimum Corner as a Vec3i.
|
||||
*/
|
||||
public Vec3i getOffsetMinCorner() {
|
||||
return offsetMinCorner;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return x size of the schematic.
|
||||
*/
|
||||
public int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return y size of the schematic.
|
||||
*/
|
||||
public int getY() {
|
||||
return this.y;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return z size of the schematic.
|
||||
*/
|
||||
public int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param x position relative to the minimum corner of the schematic.
|
||||
* @param y position relative to the minimum corner of the schematic.
|
||||
* @param z position relative to the minimum corner of the schematic.
|
||||
* @param blockState new blockstate of the block at this position.
|
||||
*/
|
||||
public void setDirect(int x, int y, int z, BlockState blockState) {
|
||||
this.states[x][z][y] = blockState;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param rotated if the schematic is rotated by 90°.
|
||||
* @return a copy of the schematic.
|
||||
*/
|
||||
public LitematicaSchematic getCopy(boolean rotated) {
|
||||
return new LitematicaSchematic(nbt, rotated);
|
||||
}
|
||||
|
||||
/**
|
||||
* @author maruohon
|
||||
* Class from the Litematica mod by maruohon
|
||||
* Usage under LGPLv3 with the permission of the author.
|
||||
* <a href="https://github.com/maruohon/litematica">...</a>
|
||||
*/
|
||||
private static class LitematicaBitArray {
|
||||
/**
|
||||
* The long array that is used to store the data for this BitArray.
|
||||
*/
|
||||
private final long[] longArray;
|
||||
/**
|
||||
* Number of bits a single entry takes up
|
||||
*/
|
||||
private final int bitsPerEntry;
|
||||
/**
|
||||
* The maximum value for a single entry. This also works as a bitmask for a single entry.
|
||||
* For instance, if bitsPerEntry were 5, this value would be 31 (ie, {@code 0b00011111}).
|
||||
*/
|
||||
private final long maxEntryValue;
|
||||
/**
|
||||
* Number of entries in this array (<b>not</b> the length of the long array that internally backs this array)
|
||||
*/
|
||||
private final long arraySize;
|
||||
|
||||
public LitematicaBitArray(int bitsPerEntryIn, long arraySizeIn, @Nullable long[] longArrayIn) {
|
||||
Validate.inclusiveBetween(1L, 32L, bitsPerEntryIn);
|
||||
this.arraySize = arraySizeIn;
|
||||
this.bitsPerEntry = bitsPerEntryIn;
|
||||
this.maxEntryValue = (1L << bitsPerEntryIn) - 1L;
|
||||
|
||||
if (longArrayIn != null) {
|
||||
this.longArray = longArrayIn;
|
||||
} else {
|
||||
this.longArray = new long[(int) (roundUp(arraySizeIn * (long) bitsPerEntryIn, 64L) / 64L)];
|
||||
}
|
||||
}
|
||||
|
||||
public static long roundUp(long number, long interval) {
|
||||
int sign = 1;
|
||||
if (interval == 0) {
|
||||
return 0;
|
||||
} else if (number == 0) {
|
||||
return interval;
|
||||
} else {
|
||||
if (number < 0) {
|
||||
sign = -1;
|
||||
}
|
||||
|
||||
long i = number % (interval * sign);
|
||||
return i == 0 ? number : number + (interval * sign) - i;
|
||||
}
|
||||
}
|
||||
|
||||
public int getAt(long index) {
|
||||
Validate.inclusiveBetween(0L, this.arraySize - 1L, index);
|
||||
long startOffset = index * (long) this.bitsPerEntry;
|
||||
int startArrIndex = (int) (startOffset >> 6); // startOffset / 64
|
||||
int endArrIndex = (int) (((index + 1L) * (long) this.bitsPerEntry - 1L) >> 6);
|
||||
int startBitOffset = (int) (startOffset & 0x3F); // startOffset % 64
|
||||
|
||||
if (startArrIndex == endArrIndex) {
|
||||
return (int) (this.longArray[startArrIndex] >>> startBitOffset & this.maxEntryValue);
|
||||
} else {
|
||||
int endOffset = 64 - startBitOffset;
|
||||
return (int) ((this.longArray[startArrIndex] >>> startBitOffset | this.longArray[endArrIndex] << endOffset) & this.maxEntryValue);
|
||||
}
|
||||
}
|
||||
|
||||
public long size() {
|
||||
return this.arraySize;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,215 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.utils.schematic.litematica;
|
||||
|
||||
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
|
||||
import fi.dy.masa.litematica.Litematica;
|
||||
import fi.dy.masa.litematica.data.DataManager;
|
||||
import net.minecraft.core.Vec3i;
|
||||
import net.minecraft.world.level.block.Mirror;
|
||||
import net.minecraft.world.level.block.Rotation;
|
||||
import net.minecraft.world.level.block.state.BlockState;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* Helper class that provides access or processes data related to Litmatica schematics.
|
||||
*
|
||||
* @author rycbar
|
||||
* @since 28.09.2022
|
||||
*/
|
||||
public final class LitematicaHelper {
|
||||
|
||||
/**
|
||||
* @return if Litmatica is installed.
|
||||
*/
|
||||
public static boolean isLitematicaPresent() {
|
||||
try {
|
||||
Class.forName(Litematica.class.getName());
|
||||
return true;
|
||||
} catch (ClassNotFoundException | NoClassDefFoundError ex) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return if there are loaded schematics.
|
||||
*/
|
||||
public static boolean hasLoadedSchematic() {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size() > 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the name of the requested schematic.
|
||||
*/
|
||||
public static String getName(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getName();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the world coordinates of the schematic origin. This can but does not have to be the minimum corner.
|
||||
*/
|
||||
public static Vec3i getOrigin(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getOrigin();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return Filepath of the schematic file.
|
||||
*/
|
||||
public static File getSchematicFile(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getSchematicFile();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return rotation of the schematic placement.
|
||||
*/
|
||||
public static Rotation getRotation(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getRotation();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the mirroring of the schematic placement.
|
||||
*/
|
||||
public static Mirror getMirror(int i) {
|
||||
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getMirror();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param schematic original schematic.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored.
|
||||
*/
|
||||
public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) {
|
||||
int x = LitematicaHelper.getOrigin(i).getX();
|
||||
int y = LitematicaHelper.getOrigin(i).getY();
|
||||
int z = LitematicaHelper.getOrigin(i).getZ();
|
||||
int mx = schematic.getOffsetMinCorner().getX();
|
||||
int my = schematic.getOffsetMinCorner().getY();
|
||||
int mz = schematic.getOffsetMinCorner().getZ();
|
||||
int sx = (schematic.getX() - 1) * -1;
|
||||
int sz = (schematic.getZ() - 1) * -1;
|
||||
|
||||
Vec3i correctedOrigin;
|
||||
Mirror mirror = LitematicaHelper.getMirror(i);
|
||||
Rotation rotation = LitematicaHelper.getRotation(i);
|
||||
|
||||
//todo there has to be a better way to do this but i cant finde it atm
|
||||
switch (mirror) {
|
||||
case FRONT_BACK:
|
||||
case LEFT_RIGHT:
|
||||
switch ((mirror.ordinal() * 2 + rotation.ordinal()) % 4) {
|
||||
case 1:
|
||||
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + (sx - mx));
|
||||
break;
|
||||
case 2:
|
||||
correctedOrigin = new Vec3i(x + mx, y + my, z + (sz - mz));
|
||||
break;
|
||||
case 3:
|
||||
correctedOrigin = new Vec3i(x + mz, y + my, z + mx);
|
||||
break;
|
||||
default:
|
||||
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + mz);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
switch (rotation) {
|
||||
case CLOCKWISE_90:
|
||||
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + mx);
|
||||
break;
|
||||
case CLOCKWISE_180:
|
||||
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + (sz - mz));
|
||||
break;
|
||||
case COUNTERCLOCKWISE_90:
|
||||
correctedOrigin = new Vec3i(x + mz, y + my, z + (sx - mx));
|
||||
break;
|
||||
default:
|
||||
correctedOrigin = new Vec3i(x + mx, y + my, z + mz);
|
||||
break;
|
||||
}
|
||||
}
|
||||
return correctedOrigin;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the xyz offsets of the block relative to the schematic minimum corner.
|
||||
* @param sizeX size of the schematic in the x-axis direction.
|
||||
* @param sizeZ size of the schematic in the z-axis direction.
|
||||
* @param mirror the mirroring of the schematic placement.
|
||||
* @return the corresponding xyz coordinates after mirroring them according to the given mirroring.
|
||||
*/
|
||||
public static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) {
|
||||
int xOut = in.getX();
|
||||
int zOut = in.getZ();
|
||||
if (mirror == Mirror.LEFT_RIGHT) {
|
||||
zOut = sizeZ - in.getZ();
|
||||
} else if (mirror == Mirror.FRONT_BACK) {
|
||||
xOut = sizeX - in.getX();
|
||||
}
|
||||
return new Vec3i(xOut, in.getY(), zOut);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param in the xyz offsets of the block relative to the schematic minimum corner.
|
||||
* @param sizeX size of the schematic in the x-axis direction.
|
||||
* @param sizeZ size of the schematic in the z-axis direction.
|
||||
* @return the corresponding xyz coordinates after rotation them 90° clockwise.
|
||||
*/
|
||||
public static Vec3i rotate(Vec3i in, int sizeX, int sizeZ) {
|
||||
return new Vec3i(sizeX - (sizeX - sizeZ) - in.getZ(), in.getY(), in.getX());
|
||||
}
|
||||
|
||||
/**
|
||||
* IDFK this just grew and it somehow works. If you understand how, pls tell me.
|
||||
*
|
||||
* @param schemIn give in the original schematic.
|
||||
* @param i index of the Schematic in the schematic placement list.
|
||||
* @return get it out rotated and mirrored.
|
||||
*/
|
||||
public static LitematicaSchematic blackMagicFuckery(LitematicaSchematic schemIn, int i) {
|
||||
LitematicaSchematic tempSchem = schemIn.getCopy(LitematicaHelper.getRotation(i).ordinal() % 2 == 1);
|
||||
for (int yCounter = 0; yCounter < schemIn.getY(); yCounter++) {
|
||||
for (int zCounter = 0; zCounter < schemIn.getZ(); zCounter++) {
|
||||
for (int xCounter = 0; xCounter < schemIn.getX(); xCounter++) {
|
||||
Vec3i xyzHolder = new Vec3i(xCounter, yCounter, zCounter);
|
||||
xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1, LitematicaHelper.getMirror(i));
|
||||
for (int turns = 0; turns < LitematicaHelper.getRotation(i).ordinal(); turns++) {
|
||||
if ((turns % 2) == 0) {
|
||||
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1);
|
||||
} else {
|
||||
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getZ() - 1, schemIn.getX() - 1);
|
||||
}
|
||||
}
|
||||
BlockState state = schemIn.getDirect(xCounter, yCounter, zCounter);
|
||||
try {
|
||||
state = state.mirror(LitematicaHelper.getMirror(i)).rotate(LitematicaHelper.getRotation(i));
|
||||
} catch (NullPointerException e) {
|
||||
//nothing to worry about it's just a hole in the schematic.
|
||||
}
|
||||
tempSchem.setDirect(xyzHolder.getX(), xyzHolder.getY(), xyzHolder.getZ(), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
return tempSchem;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user