Compare commits

...

121 Commits
1.21 ... 1.20.4

Author SHA1 Message Date
ZacSharp
573ae10ecc v1.10.4 2025-05-13 20:33:55 +02:00
ZacSharp
ac1e0e7d6b Merge branch '1.20.2' into 1.20.4 2025-05-13 13:41:44 +02:00
ZacSharp
838e75f025 Merge branch '1.20.1' 1.20.2 2025-05-13 12:40:00 +02:00
ZacSharp
5f0527be71 Merge branch '1.19.4' into 1.20.1 2025-05-13 12:37:45 +02:00
leijurv
fd49333db6 Merge pull request #4747 from ZacSharp/pr/1.19.4/setting/migrateAllowJumpAt256
Migrate `allowJumpAt256` to `allowJumpAtBuildLimit` in settings files
2025-05-12 13:30:24 -07:00
ZacSharp
31b30e3a31 Migrate allowJumpAt256 to allowJumpAtBuildLimit in settings files 2025-05-10 20:24:26 +02:00
leijurv
0fe8c628c7 Merge pull request #4745 from ZacSharp/pr/1.19.4/misc/bsi/fixWrapperHeight
Fix height vs. max build height mixup
2025-05-10 11:07:24 -07:00
ZacSharp
f86f0ab6cd Fix height vs. max build height mixup 2025-05-10 15:51:20 +02:00
Murat Bayraktar
40e83423bc Update build limits (#4736)
* Update minimum build limit

* Update MovementDescend.java to work for any minimum height

* Update RenderCommand.java for dynamic build heights.

* Fix so it actually compiles.

* Small syntax change.

* Simpler formatting

* Fix more height issues.

* Remove allowJumpAt256 as redundant.

* Remove allowJumpAt256 as redundant.

* Update CalculationContext.java

* Update Settings.java

* Update Settings.java

* Deprecate allowJumpAt256.

* Re-introduce build limit jump setting.

* Update MovementParkour.java

* Update CalculationContext.java

* Update Settings.java

* Update CalculationContext.java

* Update src/api/java/baritone/api/Settings.java

Co-authored-by: ZacSharp <68165024+ZacSharp@users.noreply.github.com>

---------

Co-authored-by: Murat65536 <bob65536@proton.me>
Co-authored-by: ZacSharp <68165024+ZacSharp@users.noreply.github.com>
2025-05-09 22:36:17 -07:00
leijurv
0de802e7ba Merge pull request #4727 from ZacSharp/pr/1.20.4/misc/backportSelectionAabbAndMixinFix
Backport #4465 and #4396 to 1.20.4
2025-05-04 18:45:33 -07:00
Wagyourtail
249f93877c fix neoforge and forge for 1.20.4
cherry picked, squashed and adapted from commits 74d82f2339 and 81f7375591
2025-04-27 01:26:58 +02:00
ZacSharp
8ac57c8da3 Fix selection box aabbs
(cherry picked from commit e682fc75a6)
2025-04-26 23:24:24 +02:00
ZacSharp
db96a5a3ec Merge branch '1.20.2' into 1.20.4 2025-04-22 23:47:58 +02:00
ZacSharp
79f1503c8b Merge branch '1.20.1' into 1.20.2 2025-04-22 20:33:01 +02:00
ZacSharp
eace2ad161 Merge branch '1.19.4' into 1.20.1 2025-04-22 20:13:44 +02:00
leijurv
d74420b265 Merge pull request #4720 from ZacSharp/pr/1.19.4/commands/preventRemoteCommandExecution
Don't let servers trick users into running arbitrary Baritone commands
2025-04-21 16:23:49 -07:00
ZacSharp
7aab08ae0f Don't let servers trick users into running arbitrary Baritone commands
As of now there shouldn't be any exploitable commands, but better be safe
2025-04-22 00:50:02 +02:00
leijurv
2fc8490c72 Merge pull request #4712 from ZacSharp/pr/1.19.4/misc/moreExceptionMessages
Add messages to more exceptions and improve some existing ones
2025-04-19 00:08:40 -07:00
leijurv
ddc2820418 Merge pull request #4713 from ZacSharp/pr/1.19.4/misc/useMinecraftEyeHeight
Use minecraft method to determine sneaking eye height
2025-04-18 15:30:30 -07:00
ZacSharp
9e1e89b91f Fix ancient comment 2025-04-18 23:34:16 +02:00
ZacSharp
7c4036dfb1 Don't leak coordinates in exceptions 2025-04-18 23:28:39 +02:00
ZacSharp
bbaa602fe9 Use minecraft method to determine sneaking eye height
Co-authored-by: Matthew Herber <matthewherber@sbcglobal.net>
2025-04-18 22:49:03 +02:00
ZacSharp
921822acd7 Add messages to more exceptions and improve some existing ones 2025-04-18 00:58:16 +02:00
leijurv
f019b81bd9 Merge pull request #2527 from ZacSharp/itemFollowing
Item following
2025-03-29 20:42:14 -07:00
leijurv
50df7b2026 Merge pull request #4677 from ZacSharp/pr/1.19.4/misc/backportCurrentLayerAndMenuLinks
Backport #4634 and #4205 to 1.19.4
2025-03-20 14:42:51 -07:00
Jack
92130f1642 Add issues links and link to Discord for ModMenu 2025-03-16 11:17:18 +01:00
Ic3Tank
fd13d5cbdc Expose current layer in IBuilderProcess 2025-03-16 11:14:51 +01:00
ZacSharp
209b51b253 Fix parsing invalid ResourceLocations once again
This is to fix `ItemById` by making `filterPrefixNamespaced` not fail on invalid prefixes
2025-03-15 20:16:06 +01:00
ZacSharp
3fa0f34c1e Remove unused import 2025-03-15 20:14:50 +01:00
ZacSharp
bf0c47c85c Command to pickup items 2025-03-15 20:14:38 +01:00
leijurv
9de3074041 Merge pull request #4662 from ZacSharp/pr/1.19.4/mine/fixCanWalkThroughButAvoidBreaking
Fix `MineProcess` stalling on blocks which are `canWalkThrough` but shouldn't be broken
2025-03-14 11:49:00 -07:00
leijurv
37a95aea97 Merge pull request #4661 from ZacSharp/pr/1.19.4/schematics/betterErrorMessage
Improve error messages from `#build`
2025-03-14 11:48:27 -07:00
leijurv
3116405953 Merge pull request #4660 from ZacSharp/pr/1.19.4/elytra/keepNetherPathfinderClasses
Fix nether-pathfinder with optimized forge/neoforge builds
2025-03-14 11:48:10 -07:00
leijurv
ed4f9cee78 Merge pull request #4659 from ZacSharp/pr/1.19.4/mixin/backportForgeFix
Backport #4138 to 1.19.4
2025-03-14 11:46:35 -07:00
ZacSharp
b8ac867fb9 Break from eye level outwards
We might be standing inside passable blocks (e.g. sugar cane) so the
block at foot level is occluded by the one at eye level.
This does still break if we are standing inside a non-target with a
target above or below.
2025-03-13 19:32:35 +01:00
ZacSharp
3f6c87a8ed Better error message for unsupported formats 2025-03-08 23:35:23 +01:00
ZacSharp
bf08c4fcf4 Improve error messages from #build 2025-02-27 18:36:35 +01:00
ZacSharp
f357eb230b Remove spam 2025-02-27 15:55:09 +01:00
ZacSharp
f3086c2231 Filter blocks where avoidBreaking returns false
shaft-mining checks `avoidBreaking` so not checking it here can cause
Baritone to walk to a position and then do nothing.
2025-02-27 15:36:59 +01:00
ZacSharp
002415425a Slightly rephrase compatibility message
We cannot distinguish between unsupported systems and failures on supported systems
so strongly implying the former is potentially misleading.
2025-02-26 17:05:40 +01:00
ZacSharp
c54d878d1c Fix nether-pathfinder on forge 2025-02-26 17:05:23 +01:00
rfresh2
590f5d98ee fix forge mixin crash
cherry-picked from 7902517663
2025-02-26 16:12:21 +01:00
leijurv
849072f8ca Merge pull request #4636 from Lyzev/1.19.4
add(Settings): added settings to control block placement in fluid sources and flowing fluids
2025-02-08 10:57:21 -08:00
Lyzev
59157c1ee0 fix(CostOfPlacingAt): improve fluid placement checks in CalculationContext 2025-02-08 12:15:55 +01:00
leijurv
3c9f5b2c91 Merge pull request #4596 from cattyngmd/1.19.4-follow-target-max-distance
Added followTargetMaxDistance setting
2025-02-07 16:58:17 -08:00
Lyzev
cdfa86c977 add(Settings): added settings to control block placement in fluid sources and flowing fluids 2025-02-06 18:48:51 +01:00
cattyn
64fdad424f added maximum distance setting for FollowProcess 2024-12-28 14:29:05 +03:00
leijurv
a5668532b1 Merge pull request #4587 from ZacSharp/pr/1.19.4/documenation/updateBuildInstructions
Update build instructions
2024-12-21 23:07:03 -08:00
ZacSharp
bac24af90e Update SETUP.md 2024-12-14 16:29:49 +01:00
leijurv
497fb74829 Merge pull request #4560 from rfresh2/litematica-fix-1.19.4
fix litematica remapping error
2024-11-20 20:02:14 -08:00
leijurv
91a1f05ff2 Update README.md 2024-11-20 01:23:03 -08:00
rfresh2
1a258b2bec fix litematica remapping error 2024-11-18 11:20:52 -08:00
leijurv
93dee4fd19 Merge pull request #4532 from babbaj/fix-loops
fix loops in path
2024-10-21 14:03:42 -07:00
Babbaj
f6657846d3 fix loops in path (fixes #4528) 2024-10-21 02:09:31 -04:00
leijurv
db163867df Merge pull request #4531 from ZacSharp/pr/1.19.4/pathing/canWalkOnSoulSand
Allow walking on soul sand once again
2024-10-20 20:02:43 -07:00
leijurv
58fcf328b9 Merge pull request #4530 from ZacSharp/pr/1.19.4/builder/fixPositionOutOfBounds
Handle positions going out of bounds between ticks
2024-10-20 20:01:25 -07:00
leijurv
8e8cfdd2a6 Merge pull request #4529 from ZacSharp/pr/1.19.4/builder/fixEmptyShapeCrash
Don't call `shape.bounds()` on empty shapes
2024-10-20 20:00:53 -07:00
ZacSharp
991d822557 Make soul sand canWalkOn again 2024-10-20 21:23:38 +02:00
ZacSharp
c25b1325da Handle positions going out of bounds between ticks
They also have to be removed rather than ignored because they won't be scanned
again and would stay in `incorrectPositions` indefinitely.
2024-10-20 18:34:17 +02:00
ZacSharp
ea1de44ca8 Don't call shape.bounds() on empty shapes
`minecraft:moving_piston` is the only block I currently know which could cause this to crash.
2024-10-20 18:13:15 +02:00
leijurv
f22f4aed00 Merge pull request #4519 from babbaj/edge-fix
Fix not moving from edge of block
2024-10-15 16:04:17 -07:00
Babbaj
d644c5b754 a bit more elegant 2024-10-15 18:56:46 -04:00
Babbaj
1e2ae34dbe crucial performance optimization 2024-10-15 18:25:42 -04:00
Babbaj
a690e1eca4 prepend feet to the path if start is adjacent to feet 2024-10-14 17:25:20 -04:00
leijurv
d25d6c2611 Merge pull request #4452 from ZacSharp/pr/1.19.4/builder/rotateAndMirrorSchematics
Add settings to rotate/mirror schematics
2024-09-15 23:34:52 -07:00
leijurv
ef72c56833 Merge pull request #4453 from ZacSharp/pr/1.19.4/schematics/litematicaRework
Almost rewrite litematic handling
2024-08-22 11:01:27 -07:00
ZacSharp
7e8c852528 Setting to mirror schematics 2024-08-02 01:42:46 +02:00
ZacSharp
42032890ed Setting to rotate schematics 2024-08-02 01:41:50 +02:00
ZacSharp
6b6931c86d Remove unused stub
The class doesn't even exist in the version of Litematica I'm using so it doesn't
seem to have an effect on descriptor strings in our bytecode. Otherwise my game
would crash.
2024-07-30 19:26:05 +02:00
ZacSharp
b915151ae3 We don't expect any exceptions here anymore 2024-07-30 19:26:05 +02:00
ZacSharp
7609f3082e Keep subregions as separate boxes 2024-07-30 19:26:05 +02:00
ZacSharp
99f9dd1671 Performance 2024-07-30 19:26:05 +02:00
ZacSharp
1a0cca794c Use toString like for schematica 2024-07-30 19:26:04 +02:00
ZacSharp
e71547b9ef Take blocks from the schematic world 2024-07-30 19:26:04 +02:00
ZacSharp
246a246cb7 Less nested schematics 2024-07-30 19:26:04 +02:00
ZacSharp
b87a1fa420 Take data directly from Litematica 2024-07-30 19:25:57 +02:00
ZacSharp
b12c4e9f8c Merge loading steps 2024-07-30 19:17:13 +02:00
ZacSharp
330089f1e2 Shorten / simplify some Litematica related things 2024-07-30 19:17:08 +02:00
leijurv
f6045b7cb4 Merge pull request #4438 from ZacSharp/pr/1.19.4/build/syncMixinAndAsm
Sync mixin and asm versions between common and tweaker
2024-07-28 00:39:37 -07:00
ZacSharp
a07d7d0526 Sync mixin and asm versions between common and tweaker 2024-07-21 13:33:00 +02:00
leijurv
1018db797e Merge pull request #4315 from ZacSharp/1.20.4-update
Merge 1.19.4 into 1.20.4
2024-04-24 12:49:27 -07:00
ZacSharp
354b26b1da Merge branch '1.19.4' into 1.20.4 2024-03-29 03:30:39 +01:00
leijurv
6d06713610 Merge pull request #4280 from ZacSharp/1.20.4-update
Merge 1.19.4 into 1.20.4
2024-03-28 16:51:28 -07:00
ZacSharp
980d68536c Merge branch '1.19.4' into 1.20.4 2024-02-20 15:24:50 +01:00
leijurv
a223585daa Merge pull request #4205 from Jatc252/patch-1
Add issues link and link to Discord for ModMenu
2024-01-06 09:51:56 -10:00
Leijurv
8a0f3018bf v1.10.2 2024-01-06 11:28:46 -08:00
leijurv
3e7eb87a36 Merge pull request #4214 from wagyourtail/1.20/1.20.4
1.20.4
2024-01-06 09:26:22 -10:00
Wagyourtail
c146440cb2 mark 1.20.3 as supported 2023-12-17 03:36:23 -07:00
Wagyourtail
4b6652b4cf 1.20.4 2023-12-07 14:18:39 -07:00
Wagyourtail
21feeb664e fix missing function 2023-11-23 19:31:55 -07:00
Wagyourtail
3dbcf0102a fix forge version 2023-11-23 19:14:10 -07:00
Wagyourtail
c1b555c289 bump parchment 2023-11-23 19:11:39 -07:00
Wagyourtail
dce35e339f Merge remote-tracking branch 'origin/1.19.4' into 1.20.2 2023-11-23 19:06:07 -07:00
Jack
163e97aad6 Add issues links and link to Discord for ModMenu 2023-11-23 20:36:51 +10:00
leijurv
a945cfaa3c Merge pull request #4172 from ZacSharp/1.20.2-update
Merge 1.19.4 into 1.20.2
2023-10-31 11:26:58 -07:00
ZacSharp
3a3b012199 Merge branch '1.19.4' into 1.20.2 2023-10-29 02:08:57 +01:00
leijurv
9bf890a7b6 Merge pull request #4136 from rfresh2/1.20.2
1.20.2
2023-09-27 22:23:00 -07:00
leijurv
e1e620a0d9 Merge pull request #4138 from rfresh2/fix-forge-1-20-1-crash
Fix forge 1.20.1 crash
2023-09-27 22:19:09 -07:00
rfresh2
f5d15927de 1.20.2 2023-09-24 15:44:15 -07:00
rfresh2
7902517663 fix forge mixin crash 2023-09-24 15:44:15 -07:00
rfresh2
4db988dbef fix forge mixin crash 2023-09-24 15:34:59 -07:00
Leijurv
97067b9078 Merge branch '1.19.4' into 1.20.1 2023-08-22 13:29:08 -07:00
Leijurv
3b30b06313 Merge branch '1.19.4' into 1.20.1 2023-08-20 13:37:07 -07:00
Leijurv
5a4500177d Merge branch '1.19.4' into 1.20.1 2023-08-20 11:54:08 -07:00
Leijurv
fa28a56e84 Merge branch '1.19.4' into 1.20.1 2023-08-18 18:20:38 -07:00
Leijurv
7668952ca8 Merge branch '1.19.4' into 1.20.1 2023-08-18 16:37:43 -07:00
Leijurv
b16590d504 Merge branch '1.20.1' of github.com:cabaletta/baritone into 1.20.1 2023-08-18 13:38:43 -07:00
Leijurv
51843f7074 Merge branch '1.19.4' into 1.20.1 2023-08-18 13:37:20 -07:00
leijurv
2821a2a0a7 Merge pull request #4078 from ZacSharp/1.20.1-update
Merge 1.19.4 into 1.20.1
2023-07-30 14:22:57 -07:00
ZacSharp
e0308dee49 Merge branch '1.19.4' into 1.20.1 2023-07-25 01:35:55 +02:00
Leijurv
7487b90d50 v1.10.1 2023-06-13 21:21:45 -07:00
leijurv
09554ab39d Merge pull request #3943 from wagyourtail/1.20/1.20
1.20
2023-06-13 20:53:05 -07:00
Wagyourtail
2ae7bc6a64 bump unimined to latest stable 2023-06-13 19:42:16 -06:00
Wagyourtail
6979bd6971 support both 2023-06-13 19:42:08 -06:00
Wagyourtail
b2bd025896 1.20.1 2023-06-13 19:32:55 -06:00
Wagyourtail
666a890088 fix frog 2023-06-11 16:46:15 -06:00
Wagyourtail
b389b573e5 add frog 2023-06-09 08:27:38 -06:00
Wagyourtail
eb28298983 confirm release version works 2023-06-07 17:03:21 -06:00
Wagyourtail
336b2c2798 pre.7 2023-05-31 07:54:16 -04:00
Wagyourtail
63d0064d69 pre.2 2023-05-18 22:37:07 -06:00
Wagyourtail
43eb4e3581 prepare for 1.20 2023-05-10 16:17:40 -06:00
93 changed files with 1467 additions and 726 deletions

View File

@@ -14,6 +14,7 @@
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.19.2-brightgreen.svg" alt="Minecraft"/></a>
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.19.4-brightgreen.svg" alt="Minecraft"/></a>
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.20.1-brightgreen.svg" alt="Minecraft"/></a>
<a href="#Baritone"><img src="https://img.shields.io/badge/MC-1.21.3-brightgreen.svg" alt="Minecraft"/></a>
</p>
<p align="center">
@@ -70,6 +71,7 @@ Baritone is the pathfinding system used in [Impact](https://impactclient.net/) s
| [1.20.1 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-forge-1.10.1.jar) | [1.20.1 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.1/baritone-api-fabric-1.10.1.jar) |
| [1.20.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-forge-1.10.2.jar) | [1.20.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-fabric-1.10.2.jar) |
| [1.20.4 Forge](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-forge-1.10.2.jar) | [1.20.4 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.10.2/baritone-api-fabric-1.10.2.jar) |
| [1.21.3 Forge](https://github.com/cabaletta/baritone/releases/download/v1.11.1/baritone-api-forge-1.11.1.jar) | [1.21.3 Fabric](https://github.com/cabaletta/baritone/releases/download/v1.11.1/baritone-api-fabric-1.11.1.jar) |
**Message for 2b2t players looking for 1.19/1.20 Baritone** If you like, please try the beta for Baritone Elytra for 2b2t, find it in #announcements of [the Baritone discord](http://discord.gg/s6fRBAUpmr). It supports 1.19.4 and 1.20.1, Forge or Fabric. If you have to see it to believe it, watch [this YouTube video](https://youtu.be/NnSlQi-68eQ).

View File

@@ -1,78 +1,87 @@
# Installation
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone.
You can also use a custom version json for Minecraft, with the [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1) version or the [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1) version or the [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1) version.
The easiest way to install Baritone is to install it as Forge/Neoforge/Fabric mod, but if you know how you can also use with a custom `version.json`
(Examples: [1.14.4](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1), [1.15.2](https://www.dropbox.com/s/8rx6f0kts9hvd4f/1.15.2-Baritone.zip?dl=1), [1.16.5](https://www.dropbox.com/s/i6f292o2i7o9acp/1.16.5-Baritone.zip?dl=1)).
Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
## Prebuilt official releases
These releases are not always completely up to date with latest features, and are only released from `master`. (so if you want `backfill-2` branch for example, you'll have to build it yourself)
Releases are made rarely and are not always up to date with the latest features and bug fixes.
Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases)
v1.2.* is for 1.12.2, v1.3.* is for 1.13.2, v1.4.* is for 1.14.4, v1.5.* is for 1.15.2, v1.6.* is for 1.16.5, v1.7.* is for 1.17.1, v1.8.* is for 1.18.1
The mapping between major Minecraft versions and major Baritone versions is as follows
| Minecraft version | 1.12 | 1.13 | 1.14 | 1.15 | 1.16 | 1.17 | 1.18 | 1.19 | 1.20 | 1.21 |
|-------------------|------|------|------|------|------|------|------|------|-------|-------|
| Baritone version | v1.2 | v1.3 | v1.4 | v1.5 | v1.6 | v1.7 | v1.8 | v1.9 | v1.10 | v1.11 |
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by that public keys of `checksums.txt`.
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
The build is fully deterministic and reproducible, and you can verify that by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
## Artifacts
Building Baritone will result in 5 artifacts created in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
Building Baritone will create the final artifacts in the ``dist`` directory. These are the same as the artifacts created in the [releases](https://github.com/cabaletta/baritone/releases).
**The Forge and Fabric releases can simply be added as a Forge/Fabric mods.**
**The Forge, NeoForge and Fabric releases can simply be added as a Forge/Neoforge/Fabric mods.**
If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar`
If another one of your other mods has a Baritone integration, you want `baritone-api-*-VERSION.jar`.
If you want to report a bug and spare us some effort, you want `baritone-unoptimized-*-VERSION.jar`.
Otherwise, you want `baritone-standalone-*-VERSION.jar`
Here's what the various qualifiers mean
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
- **Forge/Fabric API**: Same as API, but packaged for Forge/Fabric. This should be used where another mod has a Baritone integration.
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
- **Forge/Fabric Standalone**: Same as Standalone, but packaged for Forge/Fabric. This should be used when Baritone is your only Forge/Fabric mod, or none of your other Forge/Fabric mods integrate with Baritone.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
- **Forge/Fabric Unoptimized**: Same as Unoptimized, but packaged for Forge/Fabric.
- **Standalone**: Everything is obfuscated. Other mods cannot use Baritone, but you get a bit of extra performance.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used in production, but is really helpful for crash reports.
- **No loader**: Loadable as a launchwrapper tweaker against vanilla Minecraft using a custom `version.json`.
- **Forge/Neoforge/Fabric**: Loadable as a standard mod using the respective loader. The fabric build may or may not work on Quilt.
If you build from source you will also find mapping files in the `dist` directory. These contain the renamings done by ProGuard and are useful if you want to read obfuscated stack traces.
## Build it yourself
- Clone or download Baritone
![Image](https://i.imgur.com/kbqBtoN.png)
- If you choose to download, make sure you extract the ZIP archive.
- If you choose to download, make sure you download the correct branch and extract the ZIP archive.
- Follow one of the instruction sets below, based on your preference
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
If you have errors with a package missing please make sure you have setup your environment, and are using Oracle JDK 8 for 1.12.2-1.16.5, JDK 16+ for 1.17.1, and JDK 17+ for 1.18.1.
To check which java you are using do
`java -version` in a command prompt or terminal.
If you are using anything above OpenJDK 8 for 1.12.2-1.16.5, it might not work because the Java distributions above JDK 8 using may not have the needed javax classes.
The recommended Java versions by Minecraft version are
| Minecraft version | Java version |
|-------------------------------|---------------|
| 1.12.2 - 1.16.5 | 8 |
| 1.17.1 | 16 |
| 1.18.2 - 1.20.4 | 17 |
| 1.20.5 - 1.21.4 | 21 |
Download java: https://adoptium.net/
#### macOS guide
In order to get JDK 8, Try running the following command:
`% /usr/libexec/java_home -V`
If it doesn't work try this guide: https://stackoverflow.com/questions/46513639/how-to-downgrade-java-from-9-to-8-on-a-macos-eclipse-is-not-running-with-java-9
If you see something like
`% 1.8.0_VERSION, x86_64: "Java SE 8" /Library/Java/JavaVirtualMachines/jdk1.8.0_VERSION.jdk/Contents/Home`
in the list then you've got JDK 8 installed.
In order to get JDK 8 running in the **current terminal window** you will have to run this command:
`% export JAVA_HOME=$(/usr/libexec/java_home -v 1.8)`
To add OpenJDK 8 to your PATH add the export line to the end of your `.zshrc / .bashrc` if you want it to apply to each new terminal. If you're using bash change the .bachrc and if you're using zsh change the .zshrc
To check which java version you are using do `java -version` in a command prompt or terminal.
### Building Baritone
These tasks depend on the minecraft version, but are (for the most part) standard for building mods.
for more details, see [the build ci action](/.github/workflows/gradle_build.yml)
For more details, see [the build ci action](/.github/workflows/gradle_build.yml) of the branch you want to build.
For most branches `gradlew build` should build everything, but there are exceptions and this file might be out of date.
More specifically, on older branches the setup used to be that `gradlew build` builds the tweaker jar
and `gradlew build -Pbaritone.forge_build` / `gradlew build -Pbaritone.fabric_build` are needed to build
for Forge/Fabric instead. And you might have to run `setupDecompWorkspace` first.
## IntelliJ
- Open the project in IntelliJ as a Gradle project
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
- depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working
- Depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working
## Github Actions
Most branches have a CI workflow at `.github/workflows/gradle_build.yml`. If you fork this repository and enable actions for your fork
you can push a dummy commit to trigger it and have GitHub build Baritone for you.
If the commit you want to build is less than 90 days old, you can also find the corresponding workflow run in
[this list](https://github.com/cabaletta/baritone/actions/workflows/gradle_build.yml) and download the artifacts from there.

View File

@@ -38,7 +38,7 @@ allprojects {
group = rootProject.maven_group
sourceCompatibility = targetCompatibility = JavaVersion.toVersion(project.java_version)
java {
toolchain {
languageVersion.set(JavaLanguageVersion.of(sourceCompatibility.majorVersion.toInteger()))
@@ -78,12 +78,12 @@ allprojects {
}
dependencies {
implementation "org.spongepowered:mixin:0.8.5"
implementation "org.ow2.asm:asm:9.3"
// The following line declares the yarn mappings you may select this one as well.
// mappings "net.fabricmc:yarn:1.17.1+build.32:v2"
//launchImplementation('dev.babbaj:nether-pathfinder:1.3.0')
compileOnly "org.spongepowered:mixin:${project.mixin_version}"
compileOnly "org.ow2.asm:asm:${project.asm_version}"
implementation "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
implementation 'com.google.code.findbugs:jsr305:3.0.2'
}
unimined.minecraft(sourceSets.main, true) {
@@ -92,7 +92,7 @@ allprojects {
mappings {
intermediary()
mojmap()
parchment("2023.06.26")
parchment("1.20.2", "2023.10.22")
}
}

View File

@@ -40,5 +40,5 @@ dependencies {
implementation group: 'com.google.code.gson', name: 'gson', version: '2.9.0'
implementation group: 'commons-io', name: 'commons-io', version: '2.7'
implementation group: 'xyz.wagyourtail.unimined', name: 'xyz.wagyourtail.unimined.gradle.plugin', version: '1.0.5'
implementation group: 'xyz.wagyourtail.unimined', name: 'xyz.wagyourtail.unimined.gradle.plugin', version: '1.2.9'
}

View File

@@ -1,4 +1,3 @@
{
"schemaVersion": 1,
"id": "baritone",
@@ -11,7 +10,8 @@
],
"contact": {
"homepage": "https://github.com/cabaletta/baritone",
"sources": "https://github.com/cabaletta/baritone"
"sources": "https://github.com/cabaletta/baritone",
"issues": "https://github.com/cabaletta/baritone/issues"
},
"license": "LGPL-3.0",
@@ -25,7 +25,14 @@
],
"depends": {
"fabricloader": ">=0.11.0",
"minecraft": "1.19.4"
"fabricloader": ">=0.14.22",
"minecraft": ["1.20.3", "1.20.4"]
},
"custom": {
"modmenu": {
"links": {
"modmenu.discord": "https://discord.gg/s6fRBAUpmr"
}
}
}
}

View File

@@ -6,7 +6,7 @@
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[33,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
loaderVersion="[48,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license="https://raw.githubusercontent.com/cabaletta/baritone/1.16.2/LICENSE"
# A URL to refer people to when problems occur with this mod
issueTrackerURL="https://github.com/cabaletta/baritone/issues" #optional
@@ -35,6 +35,6 @@ A Minecraft pathfinder bot.
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[1.19.4]"
versionRange="[1.20.3, 1.20.4]"
ordering="NONE"
side="BOTH"

View File

@@ -1,15 +1,24 @@
org.gradle.jvmargs=-Xmx4G
mod_version=1.9.3
available_loaders=fabric,forge,neoforge,tweaker
mod_version=1.10.4
maven_group=baritone
archives_base_name=baritone
java_version=17
minecraft_version=1.19.4
minecraft_version=1.20.4
forge_version=45.0.43
forge_version=49.0.3
fabric_version=0.14.11
neoforge_version=0-beta
nether_pathfinder_version=1.4.1
fabric_version=0.14.22
nether_pathfinder_version=1.4.1
// These dependencies are used for common and tweaker
// while mod loaders usually ship their own version
mixin_version=0.8.5
asm_version=9.3

133
neoforge/build.gradle Normal file
View File

@@ -0,0 +1,133 @@
/*
* 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/>.
*/
import baritone.gradle.task.CreateDistTask
import baritone.gradle.task.ProguardTask
plugins {
id "com.github.johnrengelman.shadow" version "8.0.0"
}
archivesBaseName = archivesBaseName + "-neoforge"
unimined.minecraft {
mappings {
devFallbackNamespace "intermediary"
}
neoForged {
loader project.neoforge_version
mixinConfig ["mixins.baritone.json"]
}
minecraftRemapper.config {
// neoforge adds 1 conflict, where 2 interfaces have a method with the same name on yarn/mojmap,
// but the method has different names in the intermediary mappings.
// this is a conflict because they have a class that extends both interfaces.
// this shouldn't be a problem as long as named mappings don't make the name of those 2 methods different.
ignoreConflicts(true)
}
}
//loom {
// forge {
// mixinConfig 'mixins.baritone.json'
// }
//}
configurations {
common
shadowCommon // Don't use shadow from the shadow plugin because we don't want IDEA to index this.
compileClasspath.extendsFrom common
runtimeClasspath.extendsFrom common
}
dependencies {
// because of multiple sourcesets `common project(":")` doesn't work
for (sourceSet in rootProject.sourceSets) {
if (sourceSet == rootProject.sourceSets.test) continue
if (sourceSet == rootProject.sourceSets.schematica_api) continue
common sourceSet.output
shadowCommon sourceSet.output
}
shadowCommon "dev.babbaj:nether-pathfinder:${project.nether_pathfinder_version}"
}
processResources {
inputs.property "version", project.version
filesMatching("META-INF/mods.toml") {
expand "version": project.version
}
}
shadowJar {
configurations = [project.configurations.shadowCommon]
archiveClassifier.set "dev-shadow"
}
remapJar {
inputFile.set shadowJar.archiveFile
dependsOn shadowJar
archiveClassifier.set null
}
jar {
archiveClassifier.set "dev"
manifest {
attributes(
'MixinConfigs': 'mixins.baritone.json',
"MixinConnector": "baritone.launch.BaritoneMixinConnector",
'Implementation-Title': 'Baritone',
'Implementation-Version': version,
)
}
}
components.java {
withVariantsFromConfiguration(project.configurations.shadowRuntimeElements) {
skip()
}
}
task proguard(type: ProguardTask) {
proguardVersion "7.2.1"
compType "neoforge"
}
task createDist(type: CreateDistTask, dependsOn: proguard) {
compType "neoforge"
}
build.finalizedBy(createDist)
publishing {
publications {
mavenFabric(MavenPublication) {
artifactId = rootProject.archives_base_name + "-" + project.name
from components.java
}
}
// See https://docs.gradle.org/current/userguide/publishing_maven.html for information on how to set up publishing.
repositories {
// Add repositories to publish to here.
}
}

View File

@@ -0,0 +1,18 @@
#
# 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/>.
#
loom.platform=forge

View File

@@ -0,0 +1,24 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import net.neoforged.fml.common.Mod;
@Mod("baritoe")
public class BaritoneForgeModXD {
}

View File

@@ -0,0 +1,40 @@
# This is an example mods.toml file. It contains the data relating to the loading mods.
# There are several mandatory fields (#mandatory), and many more that are optional (#optional).
# The overall format is standard TOML format, v0.5.0.
# Note that there are a couple of TOML lists in this file.
# Find more information on toml format here: https://github.com/toml-lang/toml
# The name of the mod loader type to load - for regular FML @Mod mods it should be javafml
modLoader="javafml" #mandatory
# A version range to match for said mod loader - for regular FML @Mod it will be the forge version
loaderVersion="[1,)" #mandatory This is typically bumped every Minecraft version by Forge. See our download page for lists of versions.
license="https://raw.githubusercontent.com/cabaletta/baritone/1.16.2/LICENSE"
# A URL to refer people to when problems occur with this mod
issueTrackerURL="https://github.com/cabaletta/baritone/issues" #optional
# A list of mods - how many allowed here is determined by the individual mod loader
[[mods]] #mandatory
# The modid of the mod
modId="baritoe" #mandatory
# The version number of the mod - there's a few well known ${} variables useable here or just hardcode it
version="${version}" #mandatory
# A display name for the mod
displayName="Baritone" #mandatory
# A URL for the "homepage" for this mod, displayed in the mod UI
displayURL="https://github.com/cabaletta/baritone" #optional
# A file name (in the root of the mod JAR) containing a logo for display
#logoFile="examplemod.png" #optional
# A text field displayed in the mod UI
credits="Hat Gamers" #optional
# A text field displayed in the mod UI
authors="leijurv, Brady" #optional
# The description text for the mod (multi line!) (#mandatory)
description='''
A Minecraft pathfinder bot.
'''
[[dependencies.baritoe]]
modId="minecraft"
mandatory=true
# This version range declares a minimum of the current minecraft version up to but not including the next major version
versionRange="[1.20.3, 1.20.4]"
ordering="NONE"
side="BOTH"

View File

@@ -0,0 +1,6 @@
{
"pack": {
"description": "null",
"pack_format": 8
}
}

View File

@@ -54,6 +54,11 @@
-dontwarn baritone.utils.schematic.schematica.**
-dontwarn baritone.utils.schematic.litematica.**
# nether-pathfinder uses JNI to acess its own classes
# and some of our builds include it before running proguard
# conservatively keep all of it, even though only PathSegment.<init> is needed
-keep,allowoptimization class dev.babbaj.pathfinder.** { *; }
# Keep - Applications. Keep all application classes, along with their 'main'
# methods.
-keepclasseswithmembers public class * {

View File

@@ -42,9 +42,6 @@ pluginManagement {
rootProject.name = 'baritone'
include("tweaker")
if (System.getProperty("Baritone.enabled_platforms") == null) {
System.setProperty("Baritone.enabled_platforms", "fabric,forge")
}
for (platform in System.getProperty("Baritone.enabled_platforms").split(",")) {
for (platform in available_loaders.split(",")) {
include(platform)
}

View File

@@ -29,6 +29,9 @@ import net.minecraft.network.chat.Component;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Blocks;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -74,6 +77,16 @@ public final class Settings {
*/
public final Setting<Boolean> allowPlace = new Setting<>(true);
/**
* Allow Baritone to place blocks in fluid source blocks
*/
public final Setting<Boolean> allowPlaceInFluidsSource = new Setting<>(true);
/**
* Allow Baritone to place blocks in flowing fluid
*/
public final Setting<Boolean> allowPlaceInFluidsFlow = new Setting<>(true);
/**
* Allow Baritone to move items in your inventory to your hotbar
*/
@@ -172,6 +185,13 @@ public final class Settings {
* <p>
* Defaults to false because this fails on constantiam. Please let me know if this is ever disabled. Please.
*/
public final Setting<Boolean> allowJumpAtBuildLimit = new Setting<>(false);
/**
* Just here so mods that use the API don't break. Does nothing.
*/
@Deprecated
@JavaOnly
public final Setting<Boolean> allowJumpAt256 = new Setting<>(false);
/**
@@ -1089,6 +1109,28 @@ public final class Settings {
*/
public final Setting<Boolean> schematicOrientationZ = new Setting<>(false);
/**
* Rotates the schematic before building it.
* Possible values are
* <ul>
* <li> NONE - No rotation </li>
* <li> CLOCKWISE_90 - Rotate 90° clockwise </li>
* <li> CLOCKWISE_180 - Rotate 180° clockwise </li>
* <li> COUNTERCLOCKWISE_90 - Rotate 270° clockwise </li>
* </ul>
*/
public final Setting<Rotation> buildSchematicRotation = new Setting<>(Rotation.NONE);
/**
* Mirrors the schematic before building it.
* Possible values are
* <ul>
* <li> FRONT_BACK - mirror the schematic along its local x axis </li>
* <li> LEFT_RIGHT - mirror the schematic along its local z axis </li>
* </ul>
*/
public final Setting<Mirror> buildSchematicMirror = new Setting<>(Mirror.NONE);
/**
* The fallback used by the build command when no extension is specified. This may be useful if schematics of a
* particular format are used often, and the user does not wish to have to specify the extension with every usage.
@@ -1200,6 +1242,11 @@ public final class Settings {
*/
public final Setting<Integer> followRadius = new Setting<>(3);
/**
* The maximum distance to the entity you're following
*/
public final Setting<Integer> followTargetMaxDistance = new Setting<>(0);
/**
* Turn this on if your exploration filter is enormous, you don't want it to check if it's done,
* and you are just fine with it just hanging on completion

View File

@@ -23,17 +23,11 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.level.block.Block;
import java.util.regex.Pattern;
import java.util.stream.Stream;
public enum BlockById implements IDatatypeFor<Block> {
INSTANCE;
/**
* Matches (domain:)?name? where domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ respectively.
*/
private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?[a-z0-9/_.-]*");
@Override
public Block get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
@@ -48,10 +42,6 @@ public enum BlockById implements IDatatypeFor<Block> {
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
String arg = ctx.getConsumer().getString();
if (!PATTERN.matcher(arg).matches()) {
return Stream.empty();
}
return new TabCompleteHelper()
.append(
BuiltInRegistries.BLOCK.keySet()

View File

@@ -0,0 +1,53 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import java.util.stream.Stream;
public enum ItemById implements IDatatypeFor<Item> {
INSTANCE;
@Override
public Item get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
Item item;
if ((item = BuiltInRegistries.ITEM.getOptional(id).orElse(null)) == null) {
throw new IllegalArgumentException("No item found by that id");
}
return item;
}
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(
BuiltInRegistries.BLOCK.keySet()
.stream()
.map(ResourceLocation::toString)
)
.filterPrefixNamespaced(ctx.getConsumer().getString())
.sortAlphabetically()
.stream();
}
}

View File

@@ -212,7 +212,12 @@ public class TabCompleteHelper {
* @return This {@link TabCompleteHelper}
*/
public TabCompleteHelper filterPrefixNamespaced(String prefix) {
return filterPrefix(new ResourceLocation(prefix).toString());
ResourceLocation loc = ResourceLocation.tryParse(prefix);
if (loc == null) {
stream = Stream.empty();
return this;
}
return filterPrefix(loc.toString());
}
/**

View File

@@ -44,7 +44,7 @@ public class GoalRunAway implements Goal {
public GoalRunAway(double distance, Integer maintainY, BlockPos... from) {
if (from.length == 0) {
throw new IllegalArgumentException();
throw new IllegalArgumentException("Positions to run away from must not be empty");
}
this.from = from;
this.distanceSq = (int) (distance * distance);

View File

@@ -24,6 +24,7 @@ import net.minecraft.core.Vec3i;
import net.minecraft.world.level.block.state.BlockState;
import java.io.File;
import java.util.List;
import java.util.Optional;
/**
* @author Brady
@@ -74,4 +75,17 @@ public interface IBuilderProcess extends IBaritoneProcess {
* cause it to give up. This is updated every tick, but only while the builder process is active.
*/
List<BlockState> getApproxPlaceable();
/**
* Returns the lower bound of the current mining layer if mineInLayers is true.
* If mineInLayers is false, this will return an empty optional.
* @return The lower bound of the current mining layer
*/
Optional<Integer> getMinLayer();
/**
* Returns the upper bound of the current mining layer if mineInLayers is true.
* If mineInLayers is false, this will return an empty optional.
* @return The upper bound of the current mining layer
*/
Optional<Integer> getMaxLayer();
}

View File

@@ -17,9 +17,11 @@
package baritone.api.process;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import java.util.function.Predicate;
import net.minecraft.world.entity.Entity;
/**
* @author Brady
@@ -34,6 +36,13 @@ public interface IFollowProcess extends IBaritoneProcess {
*/
void follow(Predicate<Entity> filter);
/**
* Try to pick up any items matching this predicate
*
* @param filter the predicate
*/
void pickup(Predicate<ItemStack> filter);
/**
* @return The entities that are currently being followed. null if not currently following, empty if nothing matches the predicate
*/

View File

@@ -21,6 +21,7 @@ import baritone.api.command.registry.Registry;
import baritone.api.schematic.format.ISchematicFormat;
import java.io.File;
import java.util.List;
import java.util.Optional;
/**
@@ -41,4 +42,9 @@ public interface ISchematicSystem {
* @return The corresponding format for the file, {@link Optional#empty()} if no candidates were found.
*/
Optional<ISchematicFormat> getByFile(File file);
/**
* @return A list of file extensions used by supported formats
*/
List<String> getFileExtensions();
}

View File

@@ -0,0 +1,114 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Mirror;
import java.util.List;
import java.util.stream.Collectors;
public class MirroredSchematic implements ISchematic {
private final ISchematic schematic;
private final Mirror mirror;
public MirroredSchematic(ISchematic schematic, Mirror mirror) {
this.schematic = schematic;
this.mirror = mirror;
}
@Override
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
return schematic.inSchematic(
mirrorX(x, widthX(), mirror),
y,
mirrorZ(z, lengthZ(), mirror),
mirror(currentState, mirror)
);
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
return mirror(schematic.desiredState(
mirrorX(x, widthX(), mirror),
y,
mirrorZ(z, lengthZ(), mirror),
mirror(current, mirror),
mirror(approxPlaceable, mirror)
), mirror);
}
@Override
public void reset() {
schematic.reset();
}
@Override
public int widthX() {
return schematic.widthX();
}
@Override
public int heightY() {
return schematic.heightY();
}
@Override
public int lengthZ() {
return schematic.lengthZ();
}
private static int mirrorX(int x, int sizeX, Mirror mirror) {
switch (mirror) {
case NONE:
case LEFT_RIGHT:
return x;
case FRONT_BACK:
return sizeX - x - 1;
}
throw new IllegalArgumentException("Unknown mirror");
}
private static int mirrorZ(int z, int sizeZ, Mirror mirror) {
switch (mirror) {
case NONE:
case FRONT_BACK:
return z;
case LEFT_RIGHT:
return sizeZ - z - 1;
}
throw new IllegalArgumentException("Unknown mirror");
}
private static BlockState mirror(BlockState state, Mirror mirror) {
if (state == null) {
return null;
}
return state.mirror(mirror);
}
private static List<BlockState> mirror(List<BlockState> states, Mirror mirror) {
if (states == null) {
return null;
}
return states.stream()
.map(s -> mirror(s, mirror))
.collect(Collectors.toList());
}
}

View File

@@ -0,0 +1,136 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.Rotation;
import java.util.List;
import java.util.stream.Collectors;
public class RotatedSchematic implements ISchematic {
private final ISchematic schematic;
private final Rotation rotation;
private final Rotation inverseRotation;
public RotatedSchematic(ISchematic schematic, Rotation rotation) {
this.schematic = schematic;
this.rotation = rotation;
// I don't think a 14 line switch would improve readability
this.inverseRotation = rotation.getRotated(rotation).getRotated(rotation);
}
@Override
public boolean inSchematic(int x, int y, int z, BlockState currentState) {
return schematic.inSchematic(
rotateX(x, z, widthX(), lengthZ(), inverseRotation),
y,
rotateZ(x, z, widthX(), lengthZ(), inverseRotation),
rotate(currentState, inverseRotation)
);
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
return rotate(schematic.desiredState(
rotateX(x, z, widthX(), lengthZ(), inverseRotation),
y,
rotateZ(x, z, widthX(), lengthZ(), inverseRotation),
rotate(current, inverseRotation),
rotate(approxPlaceable, inverseRotation)
), rotation);
}
@Override
public void reset() {
schematic.reset();
}
@Override
public int widthX() {
return flipsCoordinates(rotation) ? schematic.lengthZ() : schematic.widthX();
}
@Override
public int heightY() {
return schematic.heightY();
}
@Override
public int lengthZ() {
return flipsCoordinates(rotation) ? schematic.widthX() : schematic.lengthZ();
}
/**
* Wether {@code rotation} swaps the x and z components
*/
private static boolean flipsCoordinates(Rotation rotation) {
return rotation == Rotation.CLOCKWISE_90 || rotation == Rotation.COUNTERCLOCKWISE_90;
}
/**
* The x component of x,y after applying the rotation
*/
private static int rotateX(int x, int z, int sizeX, int sizeZ, Rotation rotation) {
switch (rotation) {
case NONE:
return x;
case CLOCKWISE_90:
return sizeZ - z - 1;
case CLOCKWISE_180:
return sizeX - x - 1;
case COUNTERCLOCKWISE_90:
return z;
}
throw new IllegalArgumentException("Unknown rotation");
}
/**
* The z component of x,y after applying the rotation
*/
private static int rotateZ(int x, int z, int sizeX, int sizeZ, Rotation rotation) {
switch (rotation) {
case NONE:
return z;
case CLOCKWISE_90:
return x;
case CLOCKWISE_180:
return sizeZ - z - 1;
case COUNTERCLOCKWISE_90:
return sizeX - x - 1;
}
throw new IllegalArgumentException("Unknown rotation");
}
private static BlockState rotate(BlockState state, Rotation rotation) {
if (state == null) {
return null;
}
return state.rotate(rotation);
}
private static List<BlockState> rotate(List<BlockState> states, Rotation rotation) {
if (states == null) {
return null;
}
return states.stream()
.map(s -> rotate(s, rotation))
.collect(Collectors.toList());
}
}

View File

@@ -23,6 +23,7 @@ import baritone.api.schematic.IStaticSchematic;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
/**
* The base of a {@link ISchematic} file format
@@ -42,4 +43,9 @@ public interface ISchematicFormat {
* @return Whether or not the specified file matches this schematic format
*/
boolean isFileType(File file);
/**
* @return A list of file extensions used by this format
*/
List<String> getFileExtensions();
}

View File

@@ -28,12 +28,13 @@ import net.minecraft.resources.ResourceLocation;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.server.level.progress.ChunkProgressListener;
import net.minecraft.server.packs.*;
import net.minecraft.server.packs.PackType;
import net.minecraft.server.packs.VanillaPackResources;
import net.minecraft.server.packs.repository.ServerPacksSource;
import net.minecraft.server.packs.resources.MultiPackResourceManager;
import net.minecraft.server.packs.resources.ReloadableResourceManager;
import net.minecraft.util.RandomSource;
import net.minecraft.util.Unit;
import net.minecraft.world.RandomSequences;
import net.minecraft.world.flag.FeatureFlagSet;
import net.minecraft.world.item.Item;
import net.minecraft.world.item.ItemStack;
@@ -47,24 +48,18 @@ import net.minecraft.world.level.storage.LevelStorageSource;
import net.minecraft.world.level.storage.ServerLevelData;
import net.minecraft.world.level.storage.loot.BuiltInLootTables;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootTables;
import net.minecraft.world.level.storage.loot.PredicateManager;
import net.minecraft.world.level.storage.loot.LootDataManager;
import net.minecraft.world.level.storage.loot.LootParams;
import net.minecraft.world.level.storage.loot.parameters.LootContextParamSets;
import net.minecraft.world.level.storage.loot.parameters.LootContextParams;
import net.minecraft.world.phys.Vec3;
import sun.misc.Unsafe;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.lang.reflect.Field;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.*;
import java.util.concurrent.CompletableFuture;
import java.util.concurrent.Executor;
import java.util.regex.Matcher;
@@ -78,10 +73,9 @@ public final class BlockOptionalMeta {
private final Block block;
private final String propertiesDescription; // exists so toString() can return something more useful than a list of all blockstates
private final Set<BlockState> blockstates;
private final Set<Integer> stateHashes;
private final Set<Integer> stackHashes;
private static LootTables lootTables;
private static PredicateManager predicate = new PredicateManager();
private final ImmutableSet<Integer> stateHashes;
private final ImmutableSet<Integer> stackHashes;
private static LootDataManager lootTables;
private static Map<Block, List<Item>> drops = new HashMap<>();
public BlockOptionalMeta(@Nonnull Block block) {
@@ -224,11 +218,11 @@ public final class BlockOptionalMeta {
return null;
}
public static LootTables getManager() {
public static LootDataManager getManager() {
if (lootTables == null) {
MultiPackResourceManager resources = new MultiPackResourceManager(PackType.SERVER_DATA, List.of(getVanillaServerPack()));
ReloadableResourceManager resourceManager = new ReloadableResourceManager(PackType.SERVER_DATA);
lootTables = new LootTables(predicate);
lootTables = new LootDataManager();
resourceManager.registerReloadListener(lootTables);
try {
resourceManager.createReload(new ThreadPerTaskExecutor(Thread::new), new ThreadPerTaskExecutor(Thread::new), CompletableFuture.completedFuture(Unit.INSTANCE), resources.listPacks().toList()).done().get();
@@ -240,10 +234,6 @@ public final class BlockOptionalMeta {
return lootTables;
}
public static PredicateManager getPredicateManager() {
return predicate;
}
private static synchronized List<Item> drops(Block b) {
return drops.computeIfAbsent(b, block -> {
ResourceLocation lootTableLocation = block.getLootTable();
@@ -252,15 +242,18 @@ public final class BlockOptionalMeta {
} else {
List<Item> items = new ArrayList<>();
try {
getManager().get(lootTableLocation).getRandomItems(
new LootContext.Builder(ServerLevelStub.fastCreate())
.withRandom(RandomSource.create())
.withParameter(LootContextParams.ORIGIN, Vec3.atLowerCornerOf(BlockPos.ZERO))
.withParameter(LootContextParams.TOOL, ItemStack.EMPTY)
.withOptionalParameter(LootContextParams.BLOCK_ENTITY, null)
.withParameter(LootContextParams.BLOCK_STATE, block.defaultBlockState())
.create(LootContextParamSets.BLOCK),
stack -> items.add(stack.getItem())
getManager().getLootTable(lootTableLocation).getRandomItemsRaw(
new LootContext.Builder(
new LootParams.Builder(ServerLevelStub.fastCreate())
.withParameter(LootContextParams.ORIGIN, Vec3.atLowerCornerOf(BlockPos.ZERO))
.withParameter(LootContextParams.TOOL, ItemStack.EMPTY)
.withOptionalParameter(LootContextParams.BLOCK_ENTITY, null)
.withParameter(LootContextParams.BLOCK_STATE, block.defaultBlockState())
.create(LootContextParamSets.BLOCK)
).withOptionalRandomSeed(1L)
.create(null),
stack -> items.add(stack.getItem())
);
} catch (Exception e) {
e.printStackTrace();
@@ -273,8 +266,9 @@ public final class BlockOptionalMeta {
private static class ServerLevelStub extends ServerLevel {
private static Minecraft client = Minecraft.getInstance();
private static Unsafe unsafe = getUnsafe();
public ServerLevelStub(MinecraftServer $$0, Executor $$1, LevelStorageSource.LevelStorageAccess $$2, ServerLevelData $$3, ResourceKey<Level> $$4, LevelStem $$5, ChunkProgressListener $$6, boolean $$7, long $$8, List<CustomSpawner> $$9, boolean $$10) {
super($$0, $$1, $$2, $$3, $$4, $$5, $$6, $$7, $$8, $$9, $$10);
public ServerLevelStub(MinecraftServer $$0, Executor $$1, LevelStorageSource.LevelStorageAccess $$2, ServerLevelData $$3, ResourceKey<Level> $$4, LevelStem $$5, ChunkProgressListener $$6, boolean $$7, long $$8, List<CustomSpawner> $$9, boolean $$10, @Nullable RandomSequences $$11) {
super($$0, $$1, $$2, $$3, $$4, $$5, $$6, $$7, $$8, $$9, $$10, $$11);
}
@Override

View File

@@ -99,6 +99,14 @@ public interface IPlayerContext {
return new Rotation(player().getYRot(), player().getXRot());
}
/**
* Returns the player's eye height, taking into account whether or not the player is sneaking.
*
* @param ifSneaking Whether or not the player is sneaking
* @return The player's eye height
* @deprecated Use entity.getEyeHeight(Pose.CROUCHING) instead
*/
@Deprecated
static double eyeHeight(boolean ifSneaking) {
return ifSneaking ? 1.27 : 1.62;
}

View File

@@ -18,6 +18,7 @@
package baritone.api.utils;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.Pose;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
@@ -58,10 +59,10 @@ public final class RayTraceUtils {
direction.y * blockReachDistance,
direction.z * blockReachDistance
);
return entity.level.clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, entity));
return entity.level().clip(new ClipContext(start, end, ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, entity));
}
public static Vec3 inferSneakingEyePosition(Entity entity) {
return new Vec3(entity.getX(), entity.getY() + IPlayerContext.eyeHeight(true), entity.getZ());
return new Vec3(entity.getX(), entity.getY() + entity.getEyeHeight(Pose.CROUCHING), entity.getZ());
}
}

View File

@@ -283,7 +283,7 @@ public final class RotationUtils {
if (((BlockHitResult) result).getBlockPos().equals(pos)) {
return Optional.of(rotation);
}
if (entity.level.getBlockState(pos).getBlock() instanceof BaseFireBlock && ((BlockHitResult) result).getBlockPos().equals(pos.below())) {
if (entity.level().getBlockState(pos).getBlock() instanceof BaseFireBlock && ((BlockHitResult) result).getBlockPos().equals(pos.below())) {
return Optional.of(rotation);
}
}
@@ -292,6 +292,6 @@ public final class RotationUtils {
@Deprecated
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.level, pos), blockReachDistance, wouldSneak);
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.level(), pos), blockReachDistance, wouldSneak);
}
}

View File

@@ -27,6 +27,9 @@ import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import net.minecraft.world.level.block.Block;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import java.awt.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
@@ -80,6 +83,10 @@ public class SettingsUtil {
String settingName = matcher.group("setting").toLowerCase();
String settingValue = matcher.group("value");
// TODO remove soonish
if ("allowjumpat256".equals(settingName)) {
settingName = "allowjumpatbuildlimit";
}
try {
parseAndApply(settings, settingName, settingValue);
} catch (Exception ex) {
@@ -220,7 +227,8 @@ public class SettingsUtil {
FLOAT(Float.class, Float::parseFloat),
LONG(Long.class, Long::parseLong),
STRING(String.class, String::new),
DIRECTION(Direction.class, Direction::byName),
MIRROR(Mirror.class, Mirror::valueOf, Mirror::name),
ROTATION(Rotation.class, Rotation::valueOf, Rotation::name),
COLOR(
Color.class,
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),

View File

@@ -20,6 +20,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.GuiGraphics;
import net.minecraft.client.gui.components.toasts.Toast;
import net.minecraft.client.gui.components.toasts.ToastComponent;
import net.minecraft.network.chat.Component;
@@ -38,7 +39,7 @@ public class BaritoneToast implements Toast {
this.totalShowTime = totalShowTime;
}
public Visibility render(PoseStack matrixStack, ToastComponent toastGui, long delta) {
public Visibility render(GuiGraphics gui, ToastComponent toastGui, long delta) {
if (this.newDisplay) {
this.firstDrawTime = delta;
this.newDisplay = false;
@@ -46,15 +47,13 @@ public class BaritoneToast implements Toast {
//TODO: check
toastGui.getMinecraft().getTextureManager().bindForSetup(new ResourceLocation("textures/gui/toasts.png"));
//GlStateManager._color4f(1.0F, 1.0F, 1.0F, 255.0F);
toastGui.blit(matrixStack, 0, 0, 0, 32, 160, 32);
gui.blit(new ResourceLocation("textures/gui/toasts.png"), 0, 0, 0, 32, 160, 32);
if (this.subtitle == null) {
toastGui.getMinecraft().font.draw(matrixStack, this.title, 18, 12, -11534256);
gui.drawString(toastGui.getMinecraft().font, this.title, 18, 12, -11534256);
} else {
toastGui.getMinecraft().font.draw(matrixStack, this.title, 18, 7, -11534256);
toastGui.getMinecraft().font.draw(matrixStack, this.subtitle, 18, 18, -16777216);
gui.drawString(toastGui.getMinecraft().font, this.title, 18, 7, -11534256);
gui.drawString(toastGui.getMinecraft().font, this.subtitle, 18, 18, -16777216);
}
return delta - this.firstDrawTime < totalShowTime ? Visibility.SHOW : Visibility.HIDE;

View File

@@ -27,15 +27,16 @@ import baritone.api.event.events.type.EventState;
import baritone.api.utils.Pair;
import baritone.cache.CachedChunk;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientCommonPacketListenerImpl;
import net.minecraft.client.multiplayer.ClientPacketListener;
import net.minecraft.client.multiplayer.CommonListenerCookie;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.core.BlockPos;
import net.minecraft.network.Connection;
import net.minecraft.network.protocol.game.*;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.block.state.BlockState;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -48,7 +49,7 @@ import java.util.List;
* @since 8/3/2018
*/
@Mixin(ClientPacketListener.class)
public class MixinClientPlayNetHandler {
public abstract class MixinClientPlayNetHandler extends ClientCommonPacketListenerImpl {
// unused lol
/*@Inject(
@@ -74,9 +75,9 @@ public class MixinClientPlayNetHandler {
}
}*/
@Shadow
@Final
private Minecraft minecraft;
protected MixinClientPlayNetHandler(final Minecraft arg, final Connection arg2, final CommonListenerCookie arg3) {
super(arg, arg2, arg3);
}
@Inject(
method = "sendChat(Ljava/lang/String;)V",
@@ -124,7 +125,7 @@ public class MixinClientPlayNetHandler {
LocalPlayer player = ibaritone.getPlayerContext().player();
if (player != null && player.connection == (ClientPacketListener) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.PRE, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
new ChunkEvent(EventState.PRE, ChunkEvent.Type.UNLOAD, packet.pos().x, packet.pos().z)
);
}
}
@@ -139,7 +140,7 @@ public class MixinClientPlayNetHandler {
LocalPlayer player = ibaritone.getPlayerContext().player();
if (player != null && player.connection == (ClientPacketListener) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.POST, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
new ChunkEvent(EventState.POST, ChunkEvent.Type.UNLOAD, packet.pos().x, packet.pos().z)
);
}
}

View File

@@ -26,20 +26,38 @@ import baritone.behavior.LookBehavior;
import net.minecraft.client.KeyMapping;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.world.entity.player.Abilities;
import net.minecraft.world.item.ElytraItem;
import net.minecraft.world.item.ItemStack;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Group;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.lang.invoke.MethodHandle;
import java.lang.invoke.MethodHandles;
import java.lang.invoke.MethodType;
/**
* @author Brady
* @since 8/1/2018
*/
@Mixin(LocalPlayer.class)
public class MixinClientPlayerEntity {
@Unique
private static final MethodHandle MAY_FLY = baritone$resolveMayFly();
@Unique
private static MethodHandle baritone$resolveMayFly() {
try {
var lookup = MethodHandles.publicLookup();
return lookup.findVirtual(LocalPlayer.class, "mayFly", MethodType.methodType(boolean.class));
} catch (NoSuchMethodException e) {
return null;
} catch (IllegalAccessException e) {
throw new RuntimeException(e);
}
}
@Inject(
method = "tick",
@@ -63,6 +81,7 @@ public class MixinClientPlayerEntity {
target = "net/minecraft/world/entity/player/Abilities.mayfly:Z"
)
)
@Group(name = "mayFly", min = 1, max = 1)
private boolean isAllowFlying(Abilities capabilities) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((LocalPlayer) (Object) this);
if (baritone == null) {
@@ -71,6 +90,22 @@ public class MixinClientPlayerEntity {
return !baritone.getPathingBehavior().isPathing() && capabilities.mayfly;
}
@Redirect(
method = "aiStep",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/player/LocalPlayer;mayFly()Z"
)
)
@Group(name = "mayFly", min = 1, max = 1)
private boolean onMayFlyNeoforge(LocalPlayer instance) throws Throwable {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((LocalPlayer) (Object) this);
if (baritone == null) {
return (boolean) MAY_FLY.invokeExact(instance);
}
return !baritone.getPathingBehavior().isPathing() && (boolean) MAY_FLY.invokeExact(instance);
}
@Redirect(
method = "aiStep",
at = @At(
@@ -112,14 +147,14 @@ public class MixinClientPlayerEntity {
method = "aiStep",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/item/ElytraItem.isFlyEnabled(Lnet/minecraft/world/item/ItemStack;)Z"
target = "Lnet/minecraft/client/player/LocalPlayer;tryToStartFallFlying()Z"
)
)
private boolean isFlyEnabled(ItemStack stack) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((LocalPlayer) (Object) this);
private boolean tryToStartFallFlying(final LocalPlayer instance) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(instance);
if (baritone != null && baritone.getPathingBehavior().isPathing()) {
return false;
}
return ElytraItem.isFlyEnabled(stack);
return instance.tryToStartFallFlying();
}
}

View File

@@ -50,7 +50,7 @@ public abstract class MixinFireworkRocketEntity extends Entity implements IFirew
@Override
public LivingEntity getBoostedEntity() {
if (this.isAttachedToEntity() && this.attachedToEntity == null) { // isAttachedToEntity checks if the optional is present
final Entity entity = this.level.getEntity(this.entityData.get(DATA_ATTACHED_TO_TARGET).getAsInt());
final Entity entity = this.level().getEntity(this.entityData.get(DATA_ATTACHED_TO_TARGET).getAsInt());
if (entity instanceof LivingEntity) {
this.attachedToEntity = (LivingEntity) entity;
}

View File

@@ -21,8 +21,7 @@ import baritone.api.utils.BlockOptionalMeta;
import net.minecraft.server.MinecraftServer;
import net.minecraft.server.level.ServerLevel;
import net.minecraft.world.level.storage.loot.LootContext;
import net.minecraft.world.level.storage.loot.LootTables;
import net.minecraft.world.level.storage.loot.PredicateManager;
import net.minecraft.world.level.storage.loot.LootDataManager;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@@ -48,27 +47,13 @@ public class MixinLootContext {
method = "create",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/MinecraftServer;getLootTables()Lnet/minecraft/world/level/storage/loot/LootTables;"
target = "Lnet/minecraft/server/MinecraftServer;getLootData()Lnet/minecraft/world/level/storage/loot/LootDataManager;"
)
)
private LootTables getLootTableManager(MinecraftServer server) {
private LootDataManager getLootTableManager(MinecraftServer server) {
if (server == null) {
return BlockOptionalMeta.getManager();
}
return server.getLootTables();
}
@Redirect(
method = "create",
at = @At(
value = "INVOKE",
target = "Lnet/minecraft/server/MinecraftServer;getPredicateManager()Lnet/minecraft/world/level/storage/loot/PredicateManager;"
)
)
private PredicateManager getLootPredicateManager(MinecraftServer server) {
if (server == null) {
return BlockOptionalMeta.getPredicateManager();
}
return server.getPredicateManager();
return server.getLootData();
}
}

View File

@@ -167,12 +167,25 @@ public class MixinMinecraft {
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "Lnet/minecraft/client/gui/screens/Screen;passEvents:Z"
target = "Lnet/minecraft/client/Minecraft;screen:Lnet/minecraft/client/gui/screens/Screen;"
),
slice = @Slice(
from = @At(
value = "INVOKE",
target = "Lnet/minecraft/client/gui/components/DebugScreenOverlay;showDebugScreen()Z"
),
to = @At(
value = "CONSTANT",
args = "stringValue=Keybindings"
)
)
)
private boolean passEvents(Screen screen) {
private Screen passEvents(Minecraft instance) {
// allow user input is only the primary baritone
return (BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().isPathing() && player != null) || screen.passEvents;
if (BaritoneAPI.getProvider().getPrimaryBaritone().getPathingBehavior().isPathing() && player != null) {
return null;
}
return instance.screen;
}
// TODO

View File

@@ -23,8 +23,6 @@ import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.type.EventState;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.network.Connection;
import net.minecraft.network.PacketSendListener;
import net.minecraft.network.protocol.Packet;
@@ -54,7 +52,7 @@ public class MixinNetworkManager {
method = "sendPacket",
at = @At("HEAD")
)
private void preDispatchPacket(Packet<?> packet, PacketSendListener packetSendListener, CallbackInfo ci) {
private void preDispatchPacket(Packet<?> packet, PacketSendListener packetSendListener, boolean flush, CallbackInfo ci) {
if (this.receiving != PacketFlow.CLIENTBOUND) {
return;
}
@@ -70,7 +68,7 @@ public class MixinNetworkManager {
method = "sendPacket",
at = @At("RETURN")
)
private void postDispatchPacket(Packet<?> packet, PacketSendListener packetSendListener, CallbackInfo ci) {
private void postDispatchPacket(Packet<?> packet, PacketSendListener packetSendListener, boolean flush, CallbackInfo ci) {
if (this.receiving != PacketFlow.CLIENTBOUND) {
return;
}

View File

@@ -21,17 +21,19 @@ import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.ChatEvent;
import baritone.utils.accessor.IGuiScreen;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.network.chat.ClickEvent;
import net.minecraft.network.chat.Style;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Invoker;
import java.net.URI;
import net.minecraft.client.gui.screens.Screen;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import java.net.URI;
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
@Mixin(Screen.class)
public abstract class MixinScreen implements IGuiScreen {
@@ -47,9 +49,13 @@ public abstract class MixinScreen implements IGuiScreen {
if (clickEvent == null) {
return;
}
String command = clickEvent.getValue();
if (command == null || !command.startsWith(FORCE_COMMAND_PREFIX)) {
return;
}
IBaritone baritone = BaritoneAPI.getProvider().getPrimaryBaritone();
if (baritone != null) {
baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(clickEvent.getValue()));
baritone.getGameEventHandler().onSendChatMessage(new ChatEvent(command));
}
cir.setReturnValue(true);
cir.cancel();

View File

@@ -265,7 +265,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (goal == null) {
return false;
}
if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) {
if (goal.isInGoal(ctx.playerFeet())) {
return false;
}
synchronized (pathPlanLock) {
@@ -423,7 +423,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public BetterBlockPos pathStart() { // TODO move to a helper or util class
BetterBlockPos feet = ctx.playerFeet();
if (!MovementHelper.canWalkOn(ctx, feet.below())) {
if (ctx.player().isOnGround()) {
if (ctx.player().onGround()) {
double playerX = ctx.player().position().x;
double playerZ = ctx.player().position().z;
ArrayList<BetterBlockPos> closest = new ArrayList<>();
@@ -553,7 +553,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
});
}
private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
private AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
Goal transformed = goal;
if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) {
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
@@ -562,7 +562,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
}
Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous, context);
return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context);
BetterBlockPos feet = ctx.playerFeet();
var realStart = new BetterBlockPos(start);
var sub = feet.subtract(realStart);
if (feet.getY() == realStart.getY() && Math.abs(sub.getX()) <= 1 && Math.abs(sub.getZ()) <= 1) {
realStart = feet;
}
return new AStarPathFinder(realStart, start.getX(), start.getY(), start.getZ(), transformed, favoring, context);
}
@Override

View File

@@ -162,26 +162,26 @@ public enum FasterWorldScanner implements IWorldScanner {
}
private List<BlockPos> collectChunkSections(BlockOptionalMetaLookup lookup, LevelChunk chunk, long chunkX, long chunkZ, int playerSection) {
// iterate over sections relative to player
List<BlockPos> blocks = new ArrayList<>();
int chunkY = chunk.getMinBuildHeight();
LevelChunkSection[] sections = chunk.getSections();
int l = sections.length;
int i = playerSection - 1;
int j = playerSection;
for (; i >= 0 || j < l; ++j, --i) {
if (j < l) {
visitSection(lookup, sections[j], blocks, chunkX, chunkZ);
visitSection(lookup, sections[j], blocks, chunkX, chunkY + j * 16, chunkZ);
}
if (i >= 0) {
visitSection(lookup, sections[i], blocks, chunkX, chunkZ);
visitSection(lookup, sections[i], blocks, chunkX, chunkY + i * 16, chunkZ);
}
}
return blocks;
}
private void visitSection(BlockOptionalMetaLookup lookup, LevelChunkSection section, List<BlockPos> blocks, long chunkX, long chunkZ) {
private void visitSection(BlockOptionalMetaLookup lookup, LevelChunkSection section, List<BlockPos> blocks, long chunkX, int sectionY, long chunkZ) {
if (section == null || section.hasOnlyAir()) {
return;
}
@@ -192,7 +192,6 @@ public enum FasterWorldScanner implements IWorldScanner {
return;
}
int yOffset = section.bottomBlockY();
Palette<BlockState> palette = ((IPalettedContainer<BlockState>) sectionContainer).getPalette();
if (palette instanceof SingleValuePalette) {
@@ -204,7 +203,7 @@ public enum FasterWorldScanner implements IWorldScanner {
for (int z = 0; z < 16; ++z) {
blocks.add(new BlockPos(
(int) chunkX + x,
yOffset + y,
sectionY + y,
(int) chunkZ + z
));
}
@@ -233,7 +232,7 @@ public enum FasterWorldScanner implements IWorldScanner {
//noinspection DuplicateExpressions
blocks.add(new BlockPos(
(int) chunkX + ((idx & 255) & 15),
yOffset + (idx >> 8),
sectionY + (idx >> 8),
(int) chunkZ + ((idx & 255) >> 4)
));
}

View File

@@ -140,7 +140,7 @@ public class WorldProvider implements IWorldProvider {
String folderName;
final ServerData serverData = ctx.minecraft().getCurrentServer();
if (serverData != null) {
folderName = ctx.minecraft().isConnectedToRealms() ? "realms" : serverData.ip;
folderName = serverData.isRealm() ? "realms" : serverData.ip;
} else {
//replaymod causes null currentServer and false singleplayer.
System.out.println("World seems to be a replay. Not loading Baritone cache.");

View File

@@ -26,11 +26,13 @@ import baritone.api.command.datatypes.RelativeFile;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.utils.BetterBlockPos;
import baritone.utils.schematic.SchematicSystem;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.StringJoiner;
import java.util.stream.Stream;
public class BuildCommand extends Command {
@@ -44,10 +46,29 @@ public class BuildCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
File file = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile();
final File file0 = args.getDatatypePost(RelativeFile.INSTANCE, schematicsDir).getAbsoluteFile();
File file = file0;
if (FilenameUtils.getExtension(file.getAbsolutePath()).isEmpty()) {
file = new File(file.getAbsolutePath() + "." + Baritone.settings().schematicFallbackExtension.value);
}
if (!file.exists()) {
if (file0.exists()) {
throw new CommandInvalidStateException(String.format(
"Cannot load %s because I do not know which schematic format"
+ " that is. Please rename the file to include the correct"
+ " file extension.",
file));
}
throw new CommandInvalidStateException("Cannot find " + file);
}
if (!SchematicSystem.INSTANCE.getByFile(file).isPresent()) {
StringJoiner formats = new StringJoiner(", ");
SchematicSystem.INSTANCE.getFileExtensions().forEach(formats::add);
throw new CommandInvalidStateException(String.format(
"Unsupported schematic format. Reckognized file extensions are: %s",
formats
));
}
BetterBlockPos origin = ctx.playerFeet();
BetterBlockPos buildOrigin;
if (args.hasAny()) {
@@ -59,7 +80,7 @@ public class BuildCommand extends Command {
}
boolean success = baritone.getBuilderProcess().build(file.getName(), file, buildOrigin);
if (!success) {
throw new CommandInvalidStateException("Couldn't load the schematic. Make sure to use the FULL file name, including the extension (e.g. blah.schematic).");
throw new CommandInvalidStateException("Couldn't load the schematic. Either your schematic is corrupt or this is a bug.");
}
logDirect(String.format("Successfully loaded schematic for building\nOrigin: %s", buildOrigin));
}

View File

@@ -53,6 +53,7 @@ public final class DefaultCommands {
new RenderCommand(baritone),
new FarmCommand(baritone),
new FollowCommand(baritone),
new PickupCommand(baritone),
new ExploreFilterCommand(baritone),
new ReloadAllCommand(baritone),
new SaveAllCommand(baritone),

View File

@@ -216,7 +216,7 @@ public class ElytraCommand extends Command {
final String osArch = System.getProperty("os.arch");
final String osName = System.getProperty("os.name");
return String.format(
"Legacy architectures are not supported. Your CPU is %s and your operating system is %s. " +
"Failed loading native library. Your CPU is %s and your operating system is %s. " +
"Supported architectures are 64 bit x86, and 64 bit ARM. Supported operating systems are Windows, " +
"Linux, and Mac",
osArch, osName

View File

@@ -34,18 +34,9 @@ public class LitematicaCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
int schematic = 0;
if (args.hasAny()) {
args.requireMax(1);
if (args.is(Integer.class)) {
schematic = args.getAs(Integer.class) - 1;
}
}
try {
baritone.getBuilderProcess().buildOpenLitematic(schematic);
} catch (IndexOutOfBoundsException e) {
logDirect("Pleas provide a valid index.");
}
args.requireMax(1);
int schematic = args.hasAny() ? args.getAs(Integer.class) - 1 : 0;
baritone.getBuilderProcess().buildOpenLitematic(schematic);
}
@Override

View File

@@ -0,0 +1,82 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.command.defaults;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.datatypes.ItemById;
import baritone.api.command.exception.CommandException;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.resources.ResourceLocation;
import net.minecraft.world.item.Item;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
public class PickupCommand extends Command {
public PickupCommand(IBaritone baritone) {
super(baritone, "pickup");
}
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
Set<Item> collecting = new HashSet<>();
while (args.hasAny()) {
Item item = args.getDatatypeFor(ItemById.INSTANCE);
collecting.add(item);
}
if (collecting.isEmpty()) {
baritone.getFollowProcess().pickup(stack -> true);
logDirect("Picking up all items");
} else {
baritone.getFollowProcess().pickup(stack -> collecting.contains(stack.getItem()));
logDirect("Picking up these items:");
collecting.stream().map(BuiltInRegistries.ITEM::getKey).map(ResourceLocation::toString).forEach(this::logDirect);
}
}
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
while (args.has(2)) {
if (args.peekDatatypeOrNull(ItemById.INSTANCE) == null) {
return Stream.empty();
}
args.get();
}
return args.tabCompleteDatatype(ItemById.INSTANCE);
}
@Override
public String getShortDesc() {
return "Pickup items";
}
@Override
public List<String> getLongDesc() {
return Arrays.asList(
"Usage:",
"> pickup - Pickup anything",
"> pickup <item1> <item2> <...> - Pickup certain items"
);
}
}

View File

@@ -40,10 +40,10 @@ public class RenderCommand extends Command {
int renderDistance = (ctx.minecraft().options.renderDistance().get() + 1) * 16;
ctx.minecraft().levelRenderer.setBlocksDirty(
origin.x - renderDistance,
0,
ctx.world().getMinBuildHeight(),
origin.z - renderDistance,
origin.x + renderDistance,
255,
ctx.world().getMaxBuildHeight(),
origin.z + renderDistance
);
logDirect("Done");

View File

@@ -76,7 +76,7 @@ public class SelCommand extends Command {
float lineWidth = Baritone.settings().selectionLineWidth.value;
boolean ignoreDepth = Baritone.settings().renderSelectionIgnoreDepth.value;
IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
IRenderer.emitAABB(event.getModelViewStack(), new AABB(pos1, pos1.offset(1, 1, 1)));
IRenderer.emitAABB(event.getModelViewStack(), new AABB(pos1));
IRenderer.endLines(ignoreDepth);
}
});
@@ -227,12 +227,7 @@ public class SelCommand extends Command {
}
}
}
ISchematic schematic = new StaticSchematic() {{
states = blockstates;
x = size.getX();
y = size.getY();
z = size.getZ();
}};
ISchematic schematic = new StaticSchematic(blockstates);
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
}
clipboard = composite;

View File

@@ -44,7 +44,7 @@ public class TunnelCommand extends Command {
int width = Integer.parseInt(args.getArgs().get(1).getValue());
int depth = Integer.parseInt(args.getArgs().get(2).getValue());
if (width < 1 || height < 2 || depth < 1 || height > 255) {
if (width < 1 || height < 2 || depth < 1 || height > ctx.world().getMaxBuildHeight()){
logDirect("Width and depth must at least be 1 block; Height must at least be 2 blocks, and cannot be greater than the build limit.");
cont = false;
}

View File

@@ -22,6 +22,7 @@ import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves;
@@ -41,8 +42,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
private final Favoring favoring;
private final CalculationContext calcContext;
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) {
super(startX, startY, startZ, goal, context);
public AStarPathFinder(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, Favoring favoring, CalculationContext context) {
super(realStart, startX, startY, startZ, goal, context);
this.favoring = favoring;
this.calcContext = context;
}
@@ -96,7 +97,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
numNodes++;
if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) {
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
return Optional.of(new Path(realStart, startNode, currentNode, numNodes, goal, calcContext));
}
for (Moves moves : allMoves) {
int newX = currentNode.x + moves.xOffset;
@@ -122,17 +123,39 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
continue;
}
if (actionCost <= 0 || Double.isNaN(actionCost)) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
throw new IllegalStateException(String.format(
"%s from %s %s %s calculated implausible cost %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
actionCost));
}
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
// check destination after verifying it's not COST_INF -- some movements return COST_INF without adjusting the destination
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
continue;
}
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
throw new IllegalStateException(String.format(
"%s from %s %s %s ended at x z %s %s instead of %s %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
SettingsUtil.maybeCensor(res.x),
SettingsUtil.maybeCensor(res.z),
SettingsUtil.maybeCensor(newX),
SettingsUtil.maybeCensor(newZ)));
}
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
throw new IllegalStateException(String.format(
"%s from %s %s %s ended at y %s instead of %s",
moves,
SettingsUtil.maybeCensor(currentNode.x),
SettingsUtil.maybeCensor(currentNode.y),
SettingsUtil.maybeCensor(currentNode.z),
SettingsUtil.maybeCensor(res.y),
SettingsUtil.maybeCensor(currentNode.y + moves.yOffset)));
}
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (isFavoring) {

View File

@@ -36,6 +36,7 @@ import java.util.Optional;
*/
public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
protected final BetterBlockPos realStart;
protected final int startX;
protected final int startY;
protected final int startZ;
@@ -81,7 +82,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
*/
protected static final double MIN_IMPROVEMENT = 0.01;
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
AbstractNodeCostSearch(BetterBlockPos realStart, int startX, int startY, int startZ, Goal goal, CalculationContext context) {
this.realStart = realStart;
this.startX = startX;
this.startY = startY;
this.startZ = startZ;
@@ -177,7 +179,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
@Override
public Optional<IPath> pathToMostRecentNodeConsidered() {
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(realStart, startNode, node, 0, goal, context));
}
@Override
@@ -208,7 +210,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
logDebug("A* cost coefficient " + COEFFICIENTS[i]);
}
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context));
return Optional.of(new Path(realStart, startNode, bestSoFar[i], numNodes, goal, context));
}
}
// instead of returning bestSoFar[0], be less misleading

View File

@@ -27,6 +27,7 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.Moves;
import baritone.pathing.path.CutoffPath;
import baritone.utils.pathing.PathBase;
import com.google.common.collect.Lists;
import java.util.ArrayList;
import java.util.Collections;
@@ -68,28 +69,40 @@ class Path extends PathBase {
private volatile boolean verified;
Path(PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) {
this.start = new BetterBlockPos(start.x, start.y, start.z);
Path(BetterBlockPos realStart, PathNode start, PathNode end, int numNodes, Goal goal, CalculationContext context) {
this.end = new BetterBlockPos(end.x, end.y, end.z);
this.numNodes = numNodes;
this.movements = new ArrayList<>();
this.goal = goal;
this.context = context;
PathNode current = end;
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
LinkedList<PathNode> tempNodes = new LinkedList<>();
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
// Instead, do it into a linked list, then convert at the end
List<BetterBlockPos> tempPath = new ArrayList<>();
List<PathNode> tempNodes = new ArrayList<>();
while (current != null) {
tempNodes.addFirst(current);
tempPath.addFirst(new BetterBlockPos(current.x, current.y, current.z));
tempNodes.add(current);
tempPath.add(new BetterBlockPos(current.x, current.y, current.z));
current = current.previous;
}
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
// to performantly do that conversion since it knows the length.
this.path = new ArrayList<>(tempPath);
this.nodes = new ArrayList<>(tempNodes);
// If the position the player is at is different from the position we told A* to start from,
// and A* gave us no movements, then add a fake node that will allow a movement to be created
// that gets us to the single position in the path.
// See PathingBehavior#createPathfinder and https://github.com/cabaletta/baritone/pull/4519
var startNodePos = new BetterBlockPos(start.x, start.y, start.z);
if (!realStart.equals(startNodePos) && start.equals(end)) {
this.start = realStart;
PathNode fakeNode = new PathNode(realStart.x, realStart.y, realStart.z, goal);
fakeNode.cost = 0;
tempNodes.add(fakeNode);
tempPath.add(realStart);
} else {
this.start = startNodePos;
}
// Nodes are traversed last to first so we need to reverse the list
this.path = Lists.reverse(tempPath);
this.nodes = Lists.reverse(tempNodes);
}
@Override
@@ -99,7 +112,7 @@ class Path extends PathBase {
private boolean assembleMovements() {
if (path.isEmpty() || !movements.isEmpty()) {
throw new IllegalStateException();
throw new IllegalStateException("Path must not be empty");
}
for (int i = 0; i < path.size() - 1; i++) {
double cost = nodes.get(i + 1).cost - nodes.get(i).cost;
@@ -132,7 +145,7 @@ class Path extends PathBase {
@Override
public IPath postProcess() {
if (verified) {
throw new IllegalStateException();
throw new IllegalStateException("Path must not be verified twice");
}
verified = true;
boolean failed = assembleMovements();
@@ -141,7 +154,7 @@ class Path extends PathBase {
if (failed) { // at least one movement became impossible during calculation
CutoffPath res = new CutoffPath(this, movements().size());
if (res.movements().size() != movements.size()) {
throw new IllegalStateException();
throw new IllegalStateException("Path has wrong size after cutoff");
}
return res;
}
@@ -153,7 +166,8 @@ class Path extends PathBase {
@Override
public List<IMovement> movements() {
if (!verified) {
throw new IllegalStateException();
// edge case note: this is called during verification
throw new IllegalStateException("Path not yet verified");
}
return Collections.unmodifiableList(movements);
}

View File

@@ -20,6 +20,7 @@ package baritone.pathing.calc;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
/**
* A node in the path, containing the cost and steps to get to it.
@@ -68,7 +69,12 @@ public final class PathNode {
this.cost = ActionCosts.COST_INF;
this.estimatedCostToGoal = goal.heuristic(x, y, z);
if (Double.isNaN(estimatedCostToGoal)) {
throw new IllegalStateException(goal + " calculated implausible heuristic");
throw new IllegalStateException(String.format(
"%s calculated implausible heuristic NaN at %s %s %s",
goal,
SettingsUtil.maybeCensor(x),
SettingsUtil.maybeCensor(y),
SettingsUtil.maybeCensor(z)));
}
this.heapPosition = -1;
this.x = x;

View File

@@ -92,7 +92,7 @@ public final class BinaryHeapOpenSet implements IOpenSet {
@Override
public final PathNode removeLowest() {
if (size == 0) {
throw new IllegalStateException();
throw new IllegalStateException("Cannot remove from empty heap");
}
PathNode result = array[1];
PathNode val = array[size];

View File

@@ -63,7 +63,7 @@ public class CalculationContext {
public final List<Block> allowBreakAnyway;
public final boolean allowParkour;
public final boolean allowParkourPlace;
public final boolean allowJumpAt256;
public final boolean allowJumpAtBuildLimit;
public final boolean allowParkourAscend;
public final boolean assumeWalkOnWater;
public boolean allowFallIntoLava;
@@ -104,7 +104,7 @@ public class CalculationContext {
this.allowBreakAnyway = new ArrayList<>(Baritone.settings().allowBreakAnyway.value);
this.allowParkour = Baritone.settings().allowParkour.value;
this.allowParkourPlace = Baritone.settings().allowParkourPlace.value;
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
this.allowJumpAtBuildLimit = Baritone.settings().allowJumpAtBuildLimit.value;
this.allowParkourAscend = Baritone.settings().allowParkourAscend.value;
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value;
this.allowFallIntoLava = false; // Super secret internal setting for ElytraBehavior
@@ -161,6 +161,12 @@ public class CalculationContext {
if (!worldBorder.canPlaceAt(x, z)) {
return COST_INF;
}
if (!Baritone.settings().allowPlaceInFluidsSource.value && current.getFluidState().isSource()) {
return COST_INF;
}
if (!Baritone.settings().allowPlaceInFluidsFlow.value && !current.getFluidState().isEmpty() && !current.getFluidState().isSource()) {
return COST_INF;
}
return placeBlockCost;
}

View File

@@ -43,7 +43,6 @@ import net.minecraft.world.level.material.FlowingFluid;
import net.minecraft.world.level.material.Fluid;
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;
@@ -327,7 +326,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.LARGE_FERN || block == Blocks.TALL_GRASS) {
return true;
}
return state.getMaterial().isReplaceable();
return state.canBeReplaced();
}
@Deprecated
@@ -429,7 +428,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
return YES;
}
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH) {
if (block == Blocks.FARMLAND || block == Blocks.DIRT_PATH || block == Blocks.SOUL_SAND) {
return YES;
}
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST) {
@@ -511,14 +510,14 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean canUseFrostWalker(CalculationContext context, BlockState state) {
return context.frostWalker != 0
&& state.getMaterial() == Material.WATER
&& state == FrostedIceBlock.meltsInto()
&& ((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
&& state == FrostedIceBlock.meltsInto()
&& ((Integer) state.getValue(LiquidBlock.LEVEL)) == 0;
}

View File

@@ -347,7 +347,7 @@ public enum Moves {
public void apply(CalculationContext context, int x, int y, int z, MutableMoveResult result) {
if (dynamicXZ || dynamicY) {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("Movements with dynamic offset must override `apply`");
}
result.x = x + xOffset;
result.y = y + yOffset;
@@ -356,6 +356,6 @@ public enum Moves {
}
public double cost(CalculationContext context, int x, int y, int z) {
throw new UnsupportedOperationException();
throw new UnsupportedOperationException("Movements must override `cost` or `apply`");
}
}

View File

@@ -147,9 +147,9 @@ public class MovementDescend extends Movement {
int effectiveStartHeight = y;
for (int fallHeight = 3; true; fallHeight++) {
int newY = y - fallHeight;
if (newY < 0) {
if (newY < context.world.getMinBuildHeight()) {
// when pathing in the end, where you could plausibly fall into the void
// this check prevents it from getting the block at y=-1 and crashing
// this check prevents it from getting the block at y=(below whatever the minimum height is) and crashing
return false;
}
boolean reachedMinimum = fallHeight >= context.minFallHeight;

View File

@@ -100,7 +100,7 @@ public class MovementFall extends Movement {
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (ctx.player().position().y - dest.getY() < ctx.playerController().getBlockReachDistance() && !ctx.player().isOnGround()) {
if (ctx.player().position().y - dest.getY() < ctx.playerController().getBlockReachDistance() && !ctx.player().onGround()) {
ctx.player().getInventory().selected = ctx.player().getInventory().findSlotMatchingItem(STACK_BUCKET_WATER);
targetRotation = new Rotation(toDest.getYaw(), 90.0F);
@@ -135,7 +135,7 @@ public class MovementFall extends Movement {
}
Vec3 destCenter = VecUtils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder)
if (Math.abs(ctx.player().position().x + ctx.player().getDeltaMovement().x - destCenter.x) > 0.1 || Math.abs(ctx.player().position().z + ctx.player().getDeltaMovement().z - destCenter.z) > 0.1) {
if (!ctx.player().isOnGround() && Math.abs(ctx.player().getDeltaMovement().y) > 0.4) {
if (!ctx.player().onGround() && Math.abs(ctx.player().getDeltaMovement().y) > 0.4) {
state.setInput(Input.SNEAK, true);
}
state.setInput(Input.MOVE_FORWARD, true);
@@ -147,7 +147,7 @@ public class MovementFall extends Movement {
double dist = Math.abs(avoid.getX() * (destCenter.x - avoid.getX() / 2.0 - ctx.player().position().x)) + Math.abs(avoid.getZ() * (destCenter.z - avoid.getZ() / 2.0 - ctx.player().position().z));
if (dist < 0.6) {
state.setInput(Input.MOVE_FORWARD, true);
} else if (!ctx.player().isOnGround()) {
} else if (!ctx.player().onGround()) {
state.setInput(Input.SNEAK, false);
}
}

View File

@@ -64,10 +64,9 @@ public class MovementParkour extends Movement {
if (!context.allowParkour) {
return;
}
if (y == 256 && !context.allowJumpAt256) {
if (!context.allowJumpAtBuildLimit && y >= context.world.getMaxBuildHeight()) {
return;
}
int xDiff = dir.getStepX();
int zDiff = dir.getStepZ();
if (!MovementHelper.fullyPassable(context, x + xDiff, y, z + zDiff)) {
@@ -279,7 +278,7 @@ public class MovementParkour extends Movement {
if (Baritone.settings().allowPlace.value // see PR #3775
&& ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway()
&& !MovementHelper.canWalkOn(ctx, dest.below())
&& !ctx.player().isOnGround()
&& !ctx.player().onGround()
&& 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

View File

@@ -32,14 +32,7 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import com.google.common.collect.ImmutableSet;
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;
import net.minecraft.world.level.block.SlabBlock;
import net.minecraft.world.level.block.*;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.block.state.properties.SlabType;
import net.minecraft.world.phys.Vec3;
@@ -256,7 +249,7 @@ public class MovementPillar extends Movement {
BlockState frState = BlockStateInterface.get(ctx, src);
Block fr = frState.getBlock();
// TODO: Evaluate usage of getMaterial().isReplaceable()
if (!(fr instanceof AirBlock || frState.getMaterial().isReplaceable())) {
if (!(fr instanceof AirBlock || frState.canBeReplaced())) {
RotationUtils.reachable(ctx, src, ctx.playerController().getBlockReachDistance())
.map(rot -> new MovementState.MovementTarget(rot, true))
.ifPresent(state::setTarget);

View File

@@ -261,7 +261,7 @@ public class MovementTraverse extends Movement {
}
Block low = BlockStateInterface.get(ctx, src).getBlock();
Block high = BlockStateInterface.get(ctx, src.above()).getBlock();
if (ctx.player().position().y > src.y + 0.1D && !ctx.player().isOnGround() && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) {
if (ctx.player().position().y > src.y + 0.1D && !ctx.player().onGround() && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) {
// hitting W could cause us to climb the ladder instead of going forward
// wait until we're on the ground
return state;

View File

@@ -272,7 +272,7 @@ public class PathExecutor implements IPathExecutor, Helper {
if (!current.isPresent()) {
return false;
}
if (!ctx.player().isOnGround()) {
if (!ctx.player().onGround()) {
return false;
}
if (!MovementHelper.canWalkOn(ctx, ctx.playerFeet().below())) {
@@ -321,7 +321,7 @@ public class PathExecutor implements IPathExecutor, Helper {
* @return Whether or not it was possible to snap to the current player feet
*/
public boolean snipsnapifpossible() {
if (!ctx.player().isOnGround() && ctx.world().getFluidState(ctx.playerFeet()).isEmpty()) {
if (!ctx.player().onGround() && ctx.world().getFluidState(ctx.playerFeet()).isEmpty()) {
// if we're falling in the air, and not in water, don't splice
return false;
} else {
@@ -455,7 +455,9 @@ public class PathExecutor implements IPathExecutor, Helper {
if (data != null) {
BetterBlockPos fallDest = new BetterBlockPos(data.getB());
if (!path.positions().contains(fallDest)) {
throw new IllegalStateException();
throw new IllegalStateException(String.format(
"Fall override at %s %s %s returned illegal destination %s %s %s",
current.getSrc(), fallDest));
}
if (ctx.playerFeet().equals(fallDest)) {
pathPosition = path.positions().indexOf(fallDest);
@@ -603,7 +605,9 @@ public class PathExecutor implements IPathExecutor, Helper {
}
return SplicedPath.trySplice(path, next.path, false).map(path -> {
if (!path.getDest().equals(next.getPath().getDest())) {
throw new IllegalStateException();
throw new IllegalStateException(String.format(
"Path has end %s instead of %s after splicing",
path.getDest(), next.getPath().getDest()));
}
PathExecutor ret = new PathExecutor(behavior, path);
ret.pathPosition = pathPosition;
@@ -619,7 +623,9 @@ public class PathExecutor implements IPathExecutor, Helper {
int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.value;
CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1);
if (!newPath.getDest().equals(path.getDest())) {
throw new IllegalStateException();
throw new IllegalStateException(String.format(
"Path has end %s instead of %s after trimming its start",
newPath.getDest(), path.getDest()));
}
logDebug("Discarding earliest segment movements, length cut from " + path.length() + " to " + newPath.length());
PathExecutor ret = new PathExecutor(behavior, newPath);

View File

@@ -92,7 +92,7 @@ public class SplicedPath extends PathBase {
}
int positionInSecond = second.positions().indexOf(first.positions().get(firstPositionInSecond));
if (!allowOverlapCutoff && positionInSecond != 0) {
throw new IllegalStateException();
throw new IllegalStateException("Paths to be spliced are overlapping incorrectly");
}
List<BetterBlockPos> positions = new ArrayList<>();
List<IMovement> movements = new ArrayList<>();

View File

@@ -30,6 +30,8 @@ import baritone.api.schematic.ISchematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.MaskSchematic;
import baritone.api.schematic.SubstituteSchematic;
import baritone.api.schematic.RotatedSchematic;
import baritone.api.schematic.MirroredSchematic;
import baritone.api.schematic.format.ISchematicFormat;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
@@ -42,7 +44,6 @@ 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;
@@ -51,7 +52,6 @@ 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;
@@ -76,7 +76,6 @@ import net.minecraft.world.phys.shapes.VoxelShape;
import java.io.File;
import java.io.FileInputStream;
import java.nio.file.Files;
import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;
@@ -119,6 +118,12 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
if (!Baritone.settings().buildSubstitutes.value.isEmpty()) {
this.schematic = new SubstituteSchematic(this.schematic, Baritone.settings().buildSubstitutes.value);
}
if (Baritone.settings().buildSchematicMirror.value != net.minecraft.world.level.block.Mirror.NONE) {
this.schematic = new MirroredSchematic(this.schematic, Baritone.settings().buildSchematicMirror.value);
}
if (Baritone.settings().buildSchematicRotation.value != net.minecraft.world.level.block.Rotation.NONE) {
this.schematic = new RotatedSchematic(this.schematic, Baritone.settings().buildSchematicRotation.value);
}
// TODO this preserves the old behavior, but maybe we should bake the setting value right here
this.schematic = new MaskSchematic(this.schematic) {
@Override
@@ -229,19 +234,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
public void buildOpenLitematic(int i) {
if (LitematicaHelper.isLitematicaPresent()) {
//if java.lang.NoSuchMethodError is thrown see comment in SchematicPlacementManager
if (LitematicaHelper.hasLoadedSchematic()) {
String name = LitematicaHelper.getName(i);
try {
LitematicaSchematic schematic1 = new LitematicaSchematic(NbtIo.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath())), false);
Vec3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i);
ISchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2);
build(name, schematic2, correctedOrigin);
} catch (Exception e) {
logDirect("Schematic File could not be loaded.");
}
if (LitematicaHelper.hasLoadedSchematic(i)) {
Tuple<IStaticSchematic, Vec3i> schematic = LitematicaHelper.getSchematic(i);
Vec3i correctedOrigin = schematic.getB();
ISchematic schematic2 = applyMapArtAndSelection(correctedOrigin, schematic.getA());
build(schematic.getA().toString(), schematic2, correctedOrigin);
} else {
logDirect("No schematic currently loaded");
logDirect(String.format("List of placements has no entry %s", i + 1));
}
} else {
logDirect("Litematica is not present");
@@ -372,7 +371,11 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
if (!placementPlausible(new BetterBlockPos(x, y, z), toPlace)) {
continue;
}
AABB aabb = placeAgainstState.getShape(ctx.world(), placeAgainstPos).bounds();
VoxelShape shape = placeAgainstState.getShape(ctx.world(), placeAgainstPos);
if (shape.isEmpty()) {
continue;
}
AABB aabb = shape.bounds();
for (Vec3 placementMultiplier : aabbSideMultipliers(against)) {
double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x);
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
@@ -439,7 +442,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
double z = side.getStepZ() == 0 ? 0.5 : (1 + side.getStepZ()) / 2D;
return new Vec3[]{new Vec3(x, 0.25, z), new Vec3(x, 0.75, z)};
default: // null
throw new IllegalStateException();
throw new IllegalStateException("Unexpected side " + side);
}
}
@@ -542,7 +545,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
}
Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc);
if (toBreak.isPresent() && isSafeToCancel && ctx.player().isOnGround()) {
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround()) {
// we'd like to pause to break this block
// only change look direction if it's safe (don't want to fuck up an in progress parkour for example
Rotation rot = toBreak.get().getB();
@@ -562,7 +565,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
}
List<BlockState> desirableOnHotbar = new ArrayList<>();
Optional<Placement> toPlace = searchForPlacables(bcc, desirableOnHotbar);
if (toPlace.isPresent() && isSafeToCancel && ctx.player().isOnGround() && ticks <= 0) {
if (toPlace.isPresent() && isSafeToCancel && ctx.player().onGround() && ticks <= 0) {
Rotation rot = toPlace.get().rot;
baritone.getLookBehavior().updateTarget(rot, true);
ctx.player().getInventory().selected = toPlace.get().hotbarSelection;
@@ -716,13 +719,16 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
List<BetterBlockPos> sourceLiquids = new ArrayList<>();
List<BetterBlockPos> flowingLiquids = new ArrayList<>();
Map<BlockState, Integer> missing = new HashMap<>();
List<BetterBlockPos> outOfBounds = new ArrayList<>();
incorrectPositions.forEach(pos -> {
BlockState state = bcc.bsi.get0(pos);
if (state.getBlock() instanceof AirBlock) {
if (containsBlockState(approxPlaceable, bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
if (desired == null) {
outOfBounds.add(pos);
} else if (containsBlockState(approxPlaceable, desired)) {
placeable.add(pos);
} else {
BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
missing.put(desired, 1 + missing.getOrDefault(desired, 0));
}
} else {
@@ -740,6 +746,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
}
}
});
incorrectPositions.removeAll(outOfBounds);
List<Goal> toBreak = new ArrayList<>();
breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
List<Goal> toPlace = new ArrayList<>();
@@ -992,6 +999,22 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return paused ? "Builder Paused" : "Building " + name;
}
@Override
public Optional<Integer> getMinLayer() {
if (Baritone.settings().buildInLayers.value) {
return Optional.of(this.layer);
}
return Optional.empty();
}
@Override
public Optional<Integer> getMaxLayer() {
if (Baritone.settings().buildInLayers.value) {
return Optional.of(this.stopAtHeight);
}
return Optional.empty();
}
private List<BlockState> approxPlaceable(int size) {
List<BlockState> result = new ArrayList<>();
for (int i = 0; i < size; i++) {

View File

@@ -114,7 +114,7 @@ public final class CustomGoalProcess extends BaritoneProcessHelper implements IC
}
return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH);
default:
throw new IllegalStateException();
throw new IllegalStateException("Unexpected state " + this.state);
}
}

View File

@@ -204,7 +204,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro
}
if (this.state == State.FLYING || this.state == State.START_FLYING) {
this.state = ctx.player().isOnGround() && Baritone.settings().elytraAutoJump.value
this.state = ctx.player().onGround() && Baritone.settings().elytraAutoJump.value
? State.LOCATE_JUMP
: State.START_FLYING;
}
@@ -322,7 +322,7 @@ public class ElytraProcess extends BaritoneProcessHelper implements IBaritonePro
}
private void pathTo0(BlockPos destination, boolean appendDestination) {
if (ctx.player() == null || ctx.player().level.dimension() != Level.NETHER) {
if (ctx.player() == null || ctx.player().level().dimension() != Level.NETHER) {
return;
}
this.onLostControl();

View File

@@ -118,7 +118,9 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
int dz = (mult * 2 - 1) * zval; // dz can be either -zval or zval
int trueDist = Math.abs(dx) + Math.abs(dz);
if (trueDist != dist) {
throw new IllegalStateException();
throw new IllegalStateException(String.format(
"Offset %s %s has distance %s, expected %s",
dx, dz, trueDist, dist));
}
switch (filter.isAlreadyExplored(chunkX + dx, chunkZ + dz)) {
case UNKNOWN:

View File

@@ -260,7 +260,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
if (state.getBlock() instanceof BonemealableBlock) {
BonemealableBlock ig = (BonemealableBlock) state.getBlock();
if (ig.isValidBonemealTarget(ctx.world(), pos, state, true) && ig.isBonemealSuccess(ctx.world(), ctx.world().random, pos, state)) {
if (ig.isValidBonemealTarget(ctx.world(), pos, state) && ig.isBonemealSuccess(ctx.world(), ctx.world().random, pos, state)) {
bonemealable.add(pos);
}
}
@@ -376,7 +376,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
}
for (Entity entity : ctx.entities()) {
if (entity instanceof ItemEntity && entity.isOnGround()) {
if (entity instanceof ItemEntity && entity.onGround()) {
ItemEntity ei = (ItemEntity) entity;
if (PICKUP_DROPPED.contains(ei.getItem().getItem())) {
// +0.1 because of farmland's 0.9375 dummy height lol

View File

@@ -19,6 +19,7 @@ package baritone.process;
import baritone.Baritone;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalNear;
import baritone.api.pathing.goals.GoalXZ;
@@ -27,11 +28,14 @@ import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.BetterBlockPos;
import baritone.utils.BaritoneProcessHelper;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
import net.minecraft.world.entity.item.ItemEntity;
import net.minecraft.world.item.ItemStack;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Collectors;
import net.minecraft.core.BlockPos;
import net.minecraft.world.entity.Entity;
/**
* Follow an entity
@@ -42,6 +46,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
private Predicate<Entity> filter;
private List<Entity> cache;
private boolean into; // walk straight into the target, regardless of settings
public FollowProcess(Baritone baritone) {
super(baritone);
@@ -56,12 +61,15 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
private Goal towards(Entity following) {
BlockPos pos;
if (Baritone.settings().followOffsetDistance.value == 0) {
if (Baritone.settings().followOffsetDistance.value == 0 || into) {
pos = following.blockPosition();
} else {
GoalXZ g = GoalXZ.fromDirection(following.position(), Baritone.settings().followOffsetDirection.value, Baritone.settings().followOffsetDistance.value);
pos = new BetterBlockPos(g.getX(), following.position().y, g.getZ());
}
if (into) {
return new GoalBlock(pos);
}
return new GoalNear(pos, Baritone.settings().followRadius.value);
}
@@ -76,6 +84,10 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
if (entity.equals(ctx.player())) {
return false;
}
int maxDist = Baritone.settings().followTargetMaxDistance.value;
if (maxDist != 0 && entity.distanceToSqr(ctx.player()) > maxDist * maxDist) {
return false;
}
return ctx.entitiesStream().anyMatch(entity::equals);
}
@@ -110,6 +122,13 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
@Override
public void follow(Predicate<Entity> filter) {
this.filter = filter;
this.into = false;
}
@Override
public void pickup(Predicate<ItemStack> filter) {
this.filter = e -> e instanceof ItemEntity && filter.test(((ItemEntity) e).getItem());
this.into = true;
}
@Override

View File

@@ -77,7 +77,6 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
int curr = ctx.player().getInventory().items.stream()
.filter(stack -> filter.has(stack))
.mapToInt(ItemStack::getCount).sum();
System.out.println("Currently have " + curr + " valid items");
if (curr >= desiredQuantity) {
logDirect("Have " + curr + " valid items");
cancel();
@@ -119,9 +118,9 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
.filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ())
.filter(pos -> pos.getY() >= ctx.playerFeet().getY())
.filter(pos -> !(BlockStateInterface.get(ctx, pos).getBlock() instanceof AirBlock)) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =(
.min(Comparator.comparingDouble(ctx.playerFeet()::distSqr));
.min(Comparator.comparingDouble(ctx.playerFeet().above()::distSqr));
baritone.getInputOverrideHandler().clearAllKeys();
if (shaft.isPresent() && ctx.player().isOnGround()) {
if (shaft.isPresent() && ctx.player().onGround()) {
BlockPos pos = shaft.get();
BlockState state = baritone.bsi.get0(pos);
if (!MovementHelper.avoidBreaking(baritone.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) {
@@ -486,7 +485,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
public static boolean plausibleToBreak(CalculationContext ctx, BlockPos pos) {
if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), ctx.bsi.get0(pos), true) >= COST_INF) {
BlockState state = ctx.bsi.get0(pos);
if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), state, true) >= COST_INF) {
return false;
}
if (MovementHelper.avoidBreaking(ctx.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) {
return false;
}

View File

@@ -25,6 +25,7 @@ import baritone.api.event.events.*;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.MovementHelper;
import baritone.process.ElytraProcess;
import baritone.utils.BlockStateInterface;
import baritone.utils.IRenderer;
@@ -45,9 +46,10 @@ import net.minecraft.world.item.ItemStack;
import net.minecraft.world.item.Items;
import net.minecraft.world.level.ChunkPos;
import net.minecraft.world.level.ClipContext;
import net.minecraft.world.level.block.AirBlock;
import net.minecraft.world.level.block.state.BlockState;
import net.minecraft.world.level.chunk.ChunkSource;
import net.minecraft.world.level.chunk.LevelChunk;
import net.minecraft.world.level.material.Material;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.HitResult;
import net.minecraft.world.phys.Vec3;
@@ -1264,8 +1266,8 @@ public final class ElytraBehavior implements Helper {
private boolean passable(int x, int y, int z, boolean ignoreLava) {
if (ignoreLava) {
final Material mat = this.bsi.get0(x, y, z).getMaterial();
return mat == Material.AIR || mat == Material.LAVA;
final BlockState state = this.bsi.get0(x, y, z);
return state.getBlock() instanceof AirBlock || MovementHelper.isLava(state);
} else {
return !this.boi.get0(x, y, z);
}

View File

@@ -37,7 +37,7 @@ public class Selection implements ISelection {
max.z - min.z + 1
);
this.aabb = new AABB(this.min, this.max.offset(1, 1, 1));
this.aabb = new AABB(min.x, min.y, min.z, max.x + 1, max.y + 1, max.z + 1);
}
@Override

View File

@@ -38,13 +38,13 @@ public class SelectionRenderer implements IRenderer, AbstractGameEventListener {
IRenderer.glColor(settings.colorSelectionPos1.value, opacity);
for (ISelection selection : selections) {
IRenderer.emitAABB(stack, new AABB(selection.pos1(), selection.pos1().offset(1, 1, 1)));
IRenderer.emitAABB(stack, new AABB(selection.pos1()));
}
IRenderer.glColor(settings.colorSelectionPos2.value, opacity);
for (ISelection selection : selections) {
IRenderer.emitAABB(stack, new AABB(selection.pos2(), selection.pos2().offset(1, 1, 1)));
IRenderer.emitAABB(stack, new AABB(selection.pos2()));
}
}

View File

@@ -70,7 +70,7 @@ public class BlockStateInterface {
}
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value;
if (!ctx.minecraft().isSameThread()) {
throw new IllegalStateException();
throw new IllegalStateException("BlockStateInterface must be constructed on the main thread");
}
this.isPassableBlockPos = new BlockPos.MutableBlockPos();
this.access = new BlockStateInterfaceAccessWrapper(this);

View File

@@ -56,12 +56,12 @@ public final class BlockStateInterfaceAccessWrapper implements BlockGetter {
@Override
public int getHeight() {
return 255;
return bsi.world.getHeight();
}
@Override
public int getMinBuildHeight() {
return 0;
return bsi.world.getMinBuildHeight();
}
}

View File

@@ -24,6 +24,7 @@ import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Helper;
import com.mojang.blaze3d.vertex.PoseStack;
import net.minecraft.ChatFormatting;
import net.minecraft.client.gui.GuiGraphics;
import net.minecraft.client.gui.screens.Screen;
import net.minecraft.client.player.LocalPlayer;
import net.minecraft.client.renderer.GameRenderer;
@@ -62,7 +63,7 @@ public class GuiClick extends Screen implements Helper {
}
@Override
public void render(PoseStack stack, int mouseX, int mouseY, float partialTicks) {
public void render(GuiGraphics stack, int mouseX, int mouseY, float partialTicks) {
double mx = mc.mouseHandler.xpos();
double my = mc.mouseHandler.ypos();
@@ -75,7 +76,7 @@ public class GuiClick extends Screen implements Helper {
if (near != null && far != null) {
Vec3 viewerPos = new Vec3(PathRenderer.posX(), PathRenderer.posY(), PathRenderer.posZ());
LocalPlayer player = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().player();
HitResult result = player.level.clip(new ClipContext(near.add(viewerPos), far.add(viewerPos), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player));
HitResult result = player.level().clip(new ClipContext(near.add(viewerPos), far.add(viewerPos), ClipContext.Block.OUTLINE, ClipContext.Fluid.NONE, player));
if (result != null && result.getType() == HitResult.Type.BLOCK) {
currentMouseOver = ((BlockHitResult) result).getBlockPos();
}

View File

@@ -209,7 +209,7 @@ public final class PathRenderer implements IRenderer {
positions.forEach(pos -> {
BlockState state = bsi.get0(pos);
VoxelShape shape = state.getShape(player.level, pos);
VoxelShape shape = state.getShape(player.level(), pos);
AABB toDraw = shape.isEmpty() ? Shapes.block().bounds() : shape.bounds();
toDraw = toDraw.move(pos);
IRenderer.emitAABB(stack, toDraw, .002D);

View File

@@ -68,7 +68,7 @@ public class PathingControlManager implements IPathingControlManager {
for (IBaritoneProcess proc : processes) {
proc.onLostControl();
if (proc.isActive() && !proc.isTemporary()) { // it's okay only for a temporary thing (like combat pause) to maintain control even if you say to cancel
throw new IllegalStateException(proc.displayName());
throw new IllegalStateException(proc.displayName() + " stayed active after being cancelled");
}
}
}
@@ -121,7 +121,7 @@ public class PathingControlManager implements IPathingControlManager {
}
break;
default:
throw new IllegalStateException();
throw new IllegalStateException("Unexpected command type " + command.commandType);
}
}

View File

@@ -24,6 +24,7 @@ import baritone.utils.schematic.format.DefaultSchematicFormats;
import java.io.File;
import java.util.Arrays;
import java.util.List;
import java.util.Optional;
/**
@@ -48,4 +49,9 @@ public enum SchematicSystem implements ISchematicSystem {
public Optional<ISchematicFormat> getByFile(File file) {
return this.registry.stream().filter(format -> format.isFileType(file)).findFirst();
}
@Override
public List<String> getFileExtensions() {
return this.registry.stream().map(ISchematicFormat::getFileExtensions).flatMap(List::stream).toList();
}
}

View File

@@ -32,6 +32,16 @@ public class StaticSchematic extends AbstractSchematic implements IStaticSchemat
protected BlockState[][][] states;
public StaticSchematic() {}
public StaticSchematic(BlockState[][][] states) {
this.states = states;
boolean empty = states.length == 0 || states[0].length == 0 || states[0][0].length == 0;
this.x = empty ? 0 : states.length;
this.z = empty ? 0 : states[0].length;
this.y = empty ? 0 : states[0][0].length;
}
@Override
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
return this.states[x][z][y];

View File

@@ -22,13 +22,16 @@ import baritone.api.schematic.format.ISchematicFormat;
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
import baritone.utils.schematic.format.defaults.MCEditSchematic;
import baritone.utils.schematic.format.defaults.SpongeSchematic;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtAccounter;
import net.minecraft.nbt.NbtIo;
import org.apache.commons.io.FilenameUtils;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import net.minecraft.nbt.CompoundTag;
import net.minecraft.nbt.NbtIo;
import java.util.Collections;
import java.util.List;
/**
* Default implementations of {@link ISchematicFormat}
@@ -44,7 +47,7 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
MCEDIT("schematic") {
@Override
public IStaticSchematic parse(InputStream input) throws IOException {
return new MCEditSchematic(NbtIo.readCompressed(input));
return new MCEditSchematic(NbtIo.readCompressed(input, NbtAccounter.unlimitedHeap()));
}
},
@@ -56,7 +59,7 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
SPONGE("schem") {
@Override
public IStaticSchematic parse(InputStream input) throws IOException {
CompoundTag nbt = NbtIo.readCompressed(input);
CompoundTag nbt = NbtIo.readCompressed(input, NbtAccounter.unlimitedHeap());
int version = nbt.getInt("Version");
switch (version) {
case 1:
@@ -74,14 +77,14 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
LITEMATICA("litematic") {
@Override
public IStaticSchematic parse(InputStream input) throws IOException {
CompoundTag nbt = NbtIo.readCompressed(input);
CompoundTag nbt = NbtIo.readCompressed(input, NbtAccounter.unlimitedHeap());
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);
return new LitematicaSchematic(nbt);
default:
throw new UnsupportedOperationException("Unsuported Version of a Litematica Schematic");
}
@@ -98,4 +101,9 @@ public enum DefaultSchematicFormats implements ISchematicFormat {
public boolean isFileType(File file) {
return this.extension.equalsIgnoreCase(FilenameUtils.getExtension(file.getAbsolutePath()));
}
@Override
public List<String> getFileExtensions() {
return Collections.singletonList(this.extension);
}
}

View File

@@ -17,8 +17,9 @@
package baritone.utils.schematic.format.defaults;
import baritone.api.schematic.CompositeSchematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.utils.schematic.StaticSchematic;
import net.minecraft.core.Registry;
import net.minecraft.core.Vec3i;
import net.minecraft.core.registries.BuiltInRegistries;
import net.minecraft.nbt.CompoundTag;
@@ -30,6 +31,7 @@ import net.minecraft.world.level.block.state.properties.Property;
import org.apache.commons.lang3.Validate;
import javax.annotation.Nullable;
import java.util.Collections;
import java.util.Optional;
/**
@@ -39,35 +41,24 @@ import java.util.Optional;
* @author rycbar
* @since 22.09.2022
*/
public final class LitematicaSchematic extends StaticSchematic {
private final Vec3i offsetMinCorner;
private final CompoundTag nbt;
public final class LitematicaSchematic extends CompositeSchematic implements IStaticSchematic {
/**
* @param nbtTagCompound a decompressed file stream aka nbt data.
* @param rotated if the schematic is rotated by 90°.
*/
public LitematicaSchematic(CompoundTag nbtTagCompound, boolean rotated) {
this.nbt = nbtTagCompound;
this.offsetMinCorner = new Vec3i(getMinOfSchematic("x"), getMinOfSchematic("y"), getMinOfSchematic("z"));
this.y = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("y"));
if (rotated) {
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
} else {
this.x = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("x"));
this.z = Math.abs(nbt.getCompound("Metadata").getCompound("EnclosingSize").getInt("z"));
}
this.states = new BlockState[this.x][this.z][this.y];
fillInSchematic();
public LitematicaSchematic(CompoundTag nbt) {
super(0, 0, 0);
fillInSchematic(nbt);
}
/**
* @return Array of subregion names.
* @return Array of subregion tags.
*/
private static String[] getRegions(CompoundTag nbt) {
return nbt.getCompound("Regions").getAllKeys().toArray(new String[0]);
private static CompoundTag[] getRegions(CompoundTag nbt) {
return nbt.getCompound("Regions").getAllKeys().stream()
.map(nbt.getCompound("Regions")::getCompound)
.toArray(CompoundTag[]::new);
}
/**
@@ -76,14 +67,10 @@ public final class LitematicaSchematic extends StaticSchematic {
* @param s axis that should be read.
* @return the lower coord of the requested axis.
*/
private static int getMinOfSubregion(CompoundTag nbt, String subReg, String s) {
int a = nbt.getCompound("Regions").getCompound(subReg).getCompound("Position").getInt(s);
int b = nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt(s);
if (b < 0) {
b++;
}
return Math.min(a, a + b);
private static int getMinOfSubregion(CompoundTag subReg, String s) {
int a = subReg.getCompound("Position").getInt(s);
int b = subReg.getCompound("Size").getInt(s);
return Math.min(a, a + b + 1);
}
/**
@@ -110,7 +97,7 @@ public final class LitematicaSchematic extends StaticSchematic {
private static BlockState getBlockState(Block block, CompoundTag properties) {
BlockState blockState = block.defaultBlockState();
for (Object key : properties.getAllKeys().toArray()) {
for (Object key : properties.getAllKeys()) {
Property<?> property = block.getStateDefinition().getProperty((String) key);
String propertyValue = properties.getString((String) key);
if (property != null) {
@@ -146,43 +133,19 @@ public final class LitematicaSchematic extends StaticSchematic {
*
* @return the volume of the subregion.
*/
private static long getVolume(CompoundTag nbt, String subReg) {
return Math.abs(
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x") *
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y") *
nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
}
/**
* @return array of Long values.
*/
private static long[] getBlockStates(CompoundTag nbt, String subReg) {
return nbt.getCompound("Regions").getCompound(subReg).getLongArray("BlockStates");
}
/**
* Subregion don't have to be the same size as the enclosing size of the schematic. If they are smaller we check here if the current block is part of the subregion.
*
* @param x coord of the block relative to the minimum corner.
* @param y coord of the block relative to the minimum corner.
* @param z coord of the block relative to the minimum corner.
* @return if the current block is part of the subregion.
*/
private static boolean inSubregion(CompoundTag nbt, String subReg, int x, int y, int z) {
return x >= 0 && y >= 0 && z >= 0 &&
x < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("x")) &&
y < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("y")) &&
z < Math.abs(nbt.getCompound("Regions").getCompound(subReg).getCompound("Size").getInt("z"));
private static long getVolume(CompoundTag subReg) {
CompoundTag size = subReg.getCompound("Size");
return Math.abs(size.getInt("x") * size.getInt("y") * size.getInt("z"));
}
/**
* @param s axis.
* @return the lowest coordinate of that axis of the schematic.
*/
private int getMinOfSchematic(String s) {
private static int getMinOfSchematic(CompoundTag nbt, String s) {
int n = Integer.MAX_VALUE;
for (String subReg : getRegions(nbt)) {
n = Math.min(n, getMinOfSubregion(nbt, subReg, s));
for (CompoundTag subReg : getRegions(nbt)) {
n = Math.min(n, getMinOfSubregion(subReg, s));
}
return n;
}
@@ -190,18 +153,18 @@ public final class LitematicaSchematic extends StaticSchematic {
/**
* reads the file data.
*/
private void fillInSchematic() {
for (String subReg : getRegions(nbt)) {
ListTag usedBlockTypes = nbt.getCompound("Regions").getCompound(subReg).getList("BlockStatePalette", 10);
private void fillInSchematic(CompoundTag nbt) {
Vec3i offsetMinCorner = new Vec3i(getMinOfSchematic(nbt, "x"), getMinOfSchematic(nbt, "y"), getMinOfSchematic(nbt, "z"));
for (CompoundTag subReg : getRegions(nbt)) {
ListTag usedBlockTypes = subReg.getList("BlockStatePalette", 10);
BlockState[] blockList = getBlockList(usedBlockTypes);
int bitsPerBlock = getBitsPerBlock(usedBlockTypes.size());
long regionVolume = getVolume(nbt, subReg);
long[] blockStateArray = getBlockStates(nbt, subReg);
long regionVolume = getVolume(subReg);
long[] blockStateArray = subReg.getLongArray("BlockStates");
LitematicaBitArray bitArray = new LitematicaBitArray(bitsPerBlock, regionVolume, blockStateArray);
writeSubregionIntoSchematic(nbt, subReg, blockList, bitArray);
writeSubregionIntoSchematic(subReg, offsetMinCorner, blockList, bitArray);
}
}
@@ -211,65 +174,30 @@ public final class LitematicaSchematic extends StaticSchematic {
* @param blockList list with the different block types used in the schematic.
* @param bitArray bit array that holds the placement pattern.
*/
private void writeSubregionIntoSchematic(CompoundTag nbt, String subReg, BlockState[] blockList, LitematicaBitArray bitArray) {
Vec3i offsetSubregion = new Vec3i(getMinOfSubregion(nbt, subReg, "x"), getMinOfSubregion(nbt, subReg, "y"), getMinOfSubregion(nbt, subReg, "z"));
private void writeSubregionIntoSchematic(CompoundTag subReg, Vec3i offsetMinCorner, BlockState[] blockList, LitematicaBitArray bitArray) {
int offsetX = getMinOfSubregion(subReg, "x") - offsetMinCorner.getX();
int offsetY = getMinOfSubregion(subReg, "y") - offsetMinCorner.getY();
int offsetZ = getMinOfSubregion(subReg, "z") - offsetMinCorner.getZ();
CompoundTag size = subReg.getCompound("Size");
int sizeX = Math.abs(size.getInt("x"));
int sizeY = Math.abs(size.getInt("y"));
int sizeZ = Math.abs(size.getInt("z"));
BlockState[][][] states = new BlockState[sizeX][sizeZ][sizeY];
int index = 0;
for (int y = 0; y < this.y; y++) {
for (int z = 0; z < this.z; z++) {
for (int x = 0; x < this.x; x++) {
if (inSubregion(nbt, subReg, x, y, z)) {
this.states[x - (offsetMinCorner.getX() - offsetSubregion.getX())][z - (offsetMinCorner.getZ() - offsetSubregion.getZ())][y - (offsetMinCorner.getY() - offsetSubregion.getY())] = blockList[bitArray.getAt(index)];
index++;
}
for (int y = 0; y < sizeY; y++) {
for (int z = 0; z < sizeZ; z++) {
for (int x = 0; x < sizeX; x++) {
states[x][z][y] = blockList[bitArray.getAt(index)];
index++;
}
}
}
this.put(new StaticSchematic(states), offsetX, offsetY, offsetZ);
}
/**
* @return offset from the schematic origin to the minimum Corner as a Vec3i.
*/
public Vec3i getOffsetMinCorner() {
return offsetMinCorner;
}
/**
* @return x size of the schematic.
*/
public int getX() {
return this.x;
}
/**
* @return y size of the schematic.
*/
public int getY() {
return this.y;
}
/**
* @return z size of the schematic.
*/
public int getZ() {
return this.z;
}
/**
* @param x position relative to the minimum corner of the schematic.
* @param y position relative to the minimum corner of the schematic.
* @param z position relative to the minimum corner of the schematic.
* @param blockState new blockstate of the block at this position.
*/
public void setDirect(int x, int y, int z, BlockState blockState) {
this.states[x][z][y] = blockState;
}
/**
* @param rotated if the schematic is rotated by 90°.
* @return a copy of the schematic.
*/
public LitematicaSchematic getCopy(boolean rotated) {
return new LitematicaSchematic(nbt, rotated);
@Override
public BlockState getDirect(int x, int y, int z) {
return desiredState(x, y, z, null, Collections.emptyList());
}
/**

View File

@@ -17,15 +17,26 @@
package baritone.utils.schematic.litematica;
import baritone.utils.schematic.format.defaults.LitematicaSchematic;
import baritone.api.schematic.CompositeSchematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.utils.schematic.StaticSchematic;
import fi.dy.masa.litematica.Litematica;
import fi.dy.masa.litematica.data.DataManager;
import fi.dy.masa.litematica.schematic.placement.SchematicPlacement;
import fi.dy.masa.litematica.schematic.placement.SubRegionPlacement;
import fi.dy.masa.litematica.world.SchematicWorldHandler;
import fi.dy.masa.litematica.world.WorldSchematic;
import net.minecraft.core.BlockPos;
import net.minecraft.core.Vec3i;
import net.minecraft.util.Tuple;
import net.minecraft.world.level.Level;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import net.minecraft.world.level.block.state.BlockState;
import java.io.File;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
/**
* Helper class that provides access or processes data related to Litmatica schematics.
@@ -48,168 +59,98 @@ public final class LitematicaHelper {
}
/**
* @return if there are loaded schematics.
* @return if {@code i} is a valid placement index
*/
public static boolean hasLoadedSchematic() {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size() > 0;
public static boolean hasLoadedSchematic(int i) {
return 0 <= i && i < DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().size();
}
/**
* @param i index of the Schematic in the schematic placement list.
* @return the name of the requested schematic.
*/
public static String getName(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getName();
private static SchematicPlacement getPlacement(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i);
}
/**
* @param i index of the Schematic in the schematic placement list.
* @return the world coordinates of the schematic origin. This can but does not have to be the minimum corner.
*/
public static Vec3i getOrigin(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getOrigin();
}
/**
* @param i index of the Schematic in the schematic placement list.
* @return Filepath of the schematic file.
*/
public static File getSchematicFile(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getSchematicFile();
}
/**
* @param i index of the Schematic in the schematic placement list.
* @return rotation of the schematic placement.
*/
public static Rotation getRotation(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getRotation();
}
/**
* @param i index of the Schematic in the schematic placement list.
* @return the mirroring of the schematic placement.
*/
public static Mirror getMirror(int i) {
return DataManager.getSchematicPlacementManager().getAllSchematicsPlacements().get(i).getMirror();
}
/**
* @param schematic original schematic.
* @param i index of the Schematic in the schematic placement list.
* @return the minimum corner coordinates of the schematic, after the original schematic got rotated and mirrored.
*/
public static Vec3i getCorrectedOrigin(LitematicaSchematic schematic, int i) {
int x = LitematicaHelper.getOrigin(i).getX();
int y = LitematicaHelper.getOrigin(i).getY();
int z = LitematicaHelper.getOrigin(i).getZ();
int mx = schematic.getOffsetMinCorner().getX();
int my = schematic.getOffsetMinCorner().getY();
int mz = schematic.getOffsetMinCorner().getZ();
int sx = (schematic.getX() - 1) * -1;
int sz = (schematic.getZ() - 1) * -1;
Vec3i correctedOrigin;
Mirror mirror = LitematicaHelper.getMirror(i);
Rotation rotation = LitematicaHelper.getRotation(i);
//todo there has to be a better way to do this but i cant finde it atm
switch (mirror) {
case FRONT_BACK:
case LEFT_RIGHT:
switch ((mirror.ordinal() * 2 + rotation.ordinal()) % 4) {
case 1:
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + (sx - mx));
break;
case 2:
correctedOrigin = new Vec3i(x + mx, y + my, z + (sz - mz));
break;
case 3:
correctedOrigin = new Vec3i(x + mz, y + my, z + mx);
break;
default:
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + mz);
break;
}
break;
default:
switch (rotation) {
case CLOCKWISE_90:
correctedOrigin = new Vec3i(x + (sz - mz), y + my, z + mx);
break;
case CLOCKWISE_180:
correctedOrigin = new Vec3i(x + (sx - mx), y + my, z + (sz - mz));
break;
case COUNTERCLOCKWISE_90:
correctedOrigin = new Vec3i(x + mz, y + my, z + (sx - mx));
break;
default:
correctedOrigin = new Vec3i(x + mx, y + my, z + mz);
break;
}
}
return correctedOrigin;
}
/**
* @param in the xyz offsets of the block relative to the schematic minimum corner.
* @param sizeX size of the schematic in the x-axis direction.
* @param sizeZ size of the schematic in the z-axis direction.
* @param mirror the mirroring of the schematic placement.
* @return the corresponding xyz coordinates after mirroring them according to the given mirroring.
*/
public static Vec3i doMirroring(Vec3i in, int sizeX, int sizeZ, Mirror mirror) {
int xOut = in.getX();
int zOut = in.getZ();
private static Vec3i transform(Vec3i in, Mirror mirror, Rotation rotation) {
int x = in.getX();
int z = in.getZ();
if (mirror == Mirror.LEFT_RIGHT) {
zOut = sizeZ - in.getZ();
z = -z;
} else if (mirror == Mirror.FRONT_BACK) {
xOut = sizeX - in.getX();
x = -x;
}
switch (rotation) {
case CLOCKWISE_90:
return new Vec3i(-z, in.getY(), x);
case CLOCKWISE_180:
return new Vec3i(-x, in.getY(), -z);
case COUNTERCLOCKWISE_90:
return new Vec3i(z, in.getY(), -x);
default:
return new Vec3i(x, in.getY(), z);
}
return new Vec3i(xOut, in.getY(), zOut);
}
/**
* @param in the xyz offsets of the block relative to the schematic minimum corner.
* @param sizeX size of the schematic in the x-axis direction.
* @param sizeZ size of the schematic in the z-axis direction.
* @return the corresponding xyz coordinates after rotation them 90° clockwise.
* @param i index of the Schematic in the schematic placement list.
* @return The transformed schematic and the position of its minimum corner
*/
public static Vec3i rotate(Vec3i in, int sizeX, int sizeZ) {
return new Vec3i(sizeX - (sizeX - sizeZ) - in.getZ(), in.getY(), in.getX());
}
/**
* IDFK this just grew and it somehow works. If you understand how, pls tell me.
*
* @param schemIn give in the original schematic.
* @param i index of the Schematic in the schematic placement list.
* @return get it out rotated and mirrored.
*/
public static LitematicaSchematic blackMagicFuckery(LitematicaSchematic schemIn, int i) {
LitematicaSchematic tempSchem = schemIn.getCopy(LitematicaHelper.getRotation(i).ordinal() % 2 == 1);
for (int yCounter = 0; yCounter < schemIn.getY(); yCounter++) {
for (int zCounter = 0; zCounter < schemIn.getZ(); zCounter++) {
for (int xCounter = 0; xCounter < schemIn.getX(); xCounter++) {
Vec3i xyzHolder = new Vec3i(xCounter, yCounter, zCounter);
xyzHolder = LitematicaHelper.doMirroring(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1, LitematicaHelper.getMirror(i));
for (int turns = 0; turns < LitematicaHelper.getRotation(i).ordinal(); turns++) {
if ((turns % 2) == 0) {
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getX() - 1, schemIn.getZ() - 1);
} else {
xyzHolder = LitematicaHelper.rotate(xyzHolder, schemIn.getZ() - 1, schemIn.getX() - 1);
}
public static Tuple<IStaticSchematic, Vec3i> getSchematic(int i) {
SchematicPlacement placement = getPlacement(i);
int minX = Integer.MAX_VALUE;
int minY = Integer.MAX_VALUE;
int minZ = Integer.MAX_VALUE;
HashMap<Vec3i, StaticSchematic> subRegions = new HashMap<>();
Level schematicWorld = SchematicWorldHandler.getSchematicWorld();
for (Map.Entry<String, SubRegionPlacement> entry : placement.getEnabledRelativeSubRegionPlacements().entrySet()) {
SubRegionPlacement subPlacement = entry.getValue();
Vec3i pos = transform(subPlacement.getPos(), placement.getMirror(), placement.getRotation());
Vec3i size = placement.getSchematic().getAreaSize(entry.getKey());
size = transform(size, placement.getMirror(), placement.getRotation());
size = transform(size, subPlacement.getMirror(), subPlacement.getRotation());
int mx = Math.min(size.getX() + 1, 0);
int my = Math.min(size.getY() + 1, 0);
int mz = Math.min(size.getZ() + 1, 0);
minX = Math.min(minX, pos.getX() + mx);
minY = Math.min(minY, pos.getY() + my);
minZ = Math.min(minZ, pos.getZ() + mz);
BlockPos origin = placement.getOrigin().offset(pos).offset(mx, my, mz);
BlockState[][][] states = new BlockState[Math.abs(size.getX())][Math.abs(size.getZ())][Math.abs(size.getY())];
for (int x = 0; x < states.length; x++) {
for (int z = 0; z < states[x].length; z++) {
for (int y = 0; y < states[x][z].length; y++) {
states[x][z][y] = schematicWorld.getBlockState(origin.offset(x, y, z));
}
BlockState state = schemIn.getDirect(xCounter, yCounter, zCounter);
try {
state = state.mirror(LitematicaHelper.getMirror(i)).rotate(LitematicaHelper.getRotation(i));
} catch (NullPointerException e) {
//nothing to worry about it's just a hole in the schematic.
}
tempSchem.setDirect(xyzHolder.getX(), xyzHolder.getY(), xyzHolder.getZ(), state);
}
}
StaticSchematic schematic = new StaticSchematic(states);
subRegions.put(pos.offset(mx, my, mz), schematic);
}
return tempSchem;
LitematicaPlacementSchematic composite = new LitematicaPlacementSchematic(placement.getName());
for (Map.Entry<Vec3i, StaticSchematic> entry : subRegions.entrySet()) {
Vec3i pos = entry.getKey().offset(-minX, -minY, -minZ);
composite.put(entry.getValue(), pos.getX(), pos.getY(), pos.getZ());
}
return new Tuple<>(composite, placement.getOrigin().offset(minX, minY, minZ));
}
}
private static class LitematicaPlacementSchematic extends CompositeSchematic implements IStaticSchematic {
private final String name;
public LitematicaPlacementSchematic(String name) {
super(0, 0, 0);
this.name = name;
}
@Override
public BlockState getDirect(int x, int y, int z) {
if (inSchematic(x, y, z, null)) {
return desiredState(x, y, z, null, Collections.emptyList());
}
return null;
}
@Override
public String toString() {
return name;
}
}
}

View File

@@ -20,14 +20,8 @@ package fi.dy.masa.litematica.data;
import fi.dy.masa.litematica.schematic.placement.SchematicPlacementManager;
public class DataManager {
public static final DataManager INSTANCE = new DataManager();
private final SchematicPlacementManager schematicPlacementManager = new SchematicPlacementManager();
private static DataManager getInstance() {
return INSTANCE;
}
public static SchematicPlacementManager getSchematicPlacementManager() {
return getInstance().schematicPlacementManager;
throw new LinkageError();
}
}

View File

@@ -0,0 +1,27 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package fi.dy.masa.litematica.schematic;
import net.minecraft.core.BlockPos;
public class LitematicaSchematic {
public BlockPos getAreaSize(String name) {
throw new LinkageError();
}
}

View File

@@ -17,19 +17,35 @@
package fi.dy.masa.litematica.schematic.placement;
import com.google.common.collect.ImmutableMap;
import fi.dy.masa.litematica.schematic.LitematicaSchematic;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
public class SchematicPlacement extends SchematicPlacementUnloaded {
private Rotation rotation;
private Mirror mirror;
public class SchematicPlacement {
public String getName() {
throw new LinkageError();
}
public BlockPos getOrigin() {
throw new LinkageError();
}
public Rotation getRotation() {
return this.rotation;
throw new LinkageError();
}
public Mirror getMirror() {
return this.mirror;
throw new LinkageError();
}
public ImmutableMap<String, SubRegionPlacement> getEnabledRelativeSubRegionPlacements() {
throw new LinkageError();
}
public LitematicaSchematic getSchematic() {
throw new LinkageError();
}
}

View File

@@ -17,15 +17,13 @@
package fi.dy.masa.litematica.schematic.placement;
import java.util.ArrayList;
import java.util.List;
public class SchematicPlacementManager {
private final List<SchematicPlacement> schematicPlacements = new ArrayList<>();
//in case of a java.lang.NoSuchMethodError try change the name of this method to getAllSchematicPlacements()
//there are inconsistencies in the litematica mod about the naming of this method
public List<SchematicPlacement> getAllSchematicsPlacements() {
return schematicPlacements;
throw new LinkageError();
}
}

View File

@@ -18,26 +18,20 @@
package fi.dy.masa.litematica.schematic.placement;
import net.minecraft.core.BlockPos;
import net.minecraft.world.level.block.Mirror;
import net.minecraft.world.level.block.Rotation;
import javax.annotation.Nullable;
import java.io.File;
public class SubRegionPlacement {
public class SchematicPlacementUnloaded {
protected String name = "?";
@Nullable
protected File schematicFile;
protected BlockPos origin = BlockPos.ZERO;
public String getName() {
return this.name;
public BlockPos getPos() {
throw new LinkageError();
}
@Nullable
public File getSchematicFile() {
return this.schematicFile;
public Rotation getRotation() {
throw new LinkageError();
}
public BlockPos getOrigin() {
return this.origin;
public Mirror getMirror() {
throw new LinkageError();
}
}

View File

@@ -0,0 +1,25 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package fi.dy.masa.litematica.world;
public class SchematicWorldHandler {
public static WorldSchematic getSchematicWorld() {
throw new LinkageError();
}
}

View File

@@ -0,0 +1,27 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package fi.dy.masa.litematica.world;
import net.minecraft.world.level.Level;
public abstract class WorldSchematic extends Level {
private WorldSchematic() {
super(null, null, null, null, null, false, false, 0, 0);
throw new LinkageError();
}
}

View File

@@ -38,14 +38,14 @@ configurations {
}
dependencies {
implementation "org.spongepowered:mixin:0.8.5"
implementation "org.spongepowered:mixin:${project.mixin_version}"
// for some reason mixin isn't including these...
implementation "org.ow2.asm:asm:9.3"
implementation "org.ow2.asm:asm-tree:9.3"
implementation "org.ow2.asm:asm-commons:9.3"
implementation "org.ow2.asm:asm-util:9.3"
implementation "org.ow2.asm:asm-analysis:9.3"
implementation "org.ow2.asm:asm:${project.asm_version}"
implementation "org.ow2.asm:asm-tree:${project.asm_version}"
implementation "org.ow2.asm:asm-commons:${project.asm_version}"
implementation "org.ow2.asm:asm-util:${project.asm_version}"
implementation "org.ow2.asm:asm-analysis:${project.asm_version}"
implementation 'com.github.ImpactDevelopment:SimpleTweaker:1.2'

View File

@@ -1,105 +0,0 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import com.google.common.base.Strings;
import com.google.gson.GsonBuilder;
import com.mojang.authlib.Agent;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import net.minecraft.launchwrapper.Launch;
import java.io.File;
import java.lang.reflect.Field;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Based on GradleStart from ForgeGradle 2.3
*
* @author Brady
* @since 3/11/2019
*/
public class LaunchTesting {
public static void main(String[] args) {
Map<String, String> arguments = new HashMap<>();
hackNatives();
arguments.put("version", "BaritownedDeveloperEnvironment");
arguments.put("assetIndex", System.getenv("assetIndex"));
arguments.put("assetsDir", System.getenv().getOrDefault("assetDirectory", "assets"));
arguments.put("accessToken", "FML");
arguments.put("userProperties", "{}");
arguments.put("tweakClass", System.getenv("tweakClass"));
String password = System.getenv("password");
if (password != null && !password.isEmpty()) {
attemptLogin(arguments, System.getenv("username"), System.getenv("password"));
}
List<String> argsArray = new ArrayList<>();
arguments.forEach((k, v) -> {
argsArray.add("--" + k);
argsArray.add(v);
});
Launch.main(argsArray.toArray(new String[0]));
}
private static void hackNatives() {
String paths = System.getProperty("java.library.path");
String nativesDir = System.getenv().get("nativesDirectory");
if (Strings.isNullOrEmpty(paths))
paths = nativesDir;
else
paths += File.pathSeparator + nativesDir;
System.setProperty("java.library.path", paths);
// hack the classloader now.
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Throwable ignored) {}
}
private static void attemptLogin(Map<String, String> argMap, String username, String password) {
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) (new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1")).createUserAuthentication(Agent.MINECRAFT);
auth.setUsername(username);
auth.setPassword(password);
try {
auth.logIn();
} catch (AuthenticationException var4) {
throw new RuntimeException(var4);
}
argMap.put("accessToken", auth.getAuthenticatedToken());
argMap.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", ""));
argMap.put("username", auth.getSelectedProfile().getName());
argMap.put("userType", auth.getUserType().getName());
argMap.put("userProperties", (new GsonBuilder()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(auth.getUserProperties()));
}
}