Compare commits

...

160 Commits

Author SHA1 Message Date
Leijurv 8ac82ebe2a v1.2.2 2019-02-27 17:48:57 -08:00
Leijurv 0ed6ccab71 update some documentation 2019-02-27 15:46:28 -08:00
Leijurv bf25d7328e revalidate on goal update too 2019-02-27 12:23:05 -08:00
Leijurv a47b0c0581 rendering cleanup, fixes #317 2019-02-27 12:00:39 -08:00
Leijurv 596849c7e6 i am rarted 2019-02-26 19:51:20 -08:00
Leijurv 76914b7859 awesome 2019-02-26 19:50:35 -08:00
Leijurv 3dbbe053d7 teensy change 2019-02-26 19:45:20 -08:00
Brady c474cdb1f8 Working clicking goals 2019-02-26 21:41:08 -06:00
Leijurv 3de02cbf21 brady save me idk how to gl 2019-02-26 18:34:11 -08:00
Brady 26fefc70f0 Better update the badges 2019-02-26 17:29:50 -06:00
Brady 4086c9f4b5 Implement secondary license conditioning
Sorry fellas, no anime in this town.
2019-02-26 17:25:30 -06:00
Leijurv c947c77853 goodbye mc.objectMouseOver 2019-02-26 15:07:01 -08:00
Leijurv 9be44c0371 placement without unepic right click 2019-02-26 14:57:44 -08:00
Leijurv 5412fa6cfd cursed flowing 2019-02-25 20:35:06 -08:00
Leijurv 6e7320b954 v1.2.1 2019-02-25 18:07:55 -08:00
Leijurv fbb2d37634 allow placing against replacable blocks 2019-02-25 18:01:11 -08:00
Leijurv 7afe16fc10 dont reset every tick 2019-02-25 16:26:17 -08:00
Leijurv b19f241d81 override for the first tick 2019-02-25 15:06:55 -08:00
Leijurv 583ce80003 not reliable enough with jesus to jump from water over a gap 2019-02-24 13:57:33 -08:00
Leijurv 195c33407e cant walk through heads 2019-02-24 13:43:53 -08:00
Leijurv 600c5b77ad v1.2.0 2019-02-23 20:43:29 -08:00
Leijurv f1084fab76 come 2019-02-23 20:33:00 -08:00
Brady bd65e32407 Fix the failing build 2019-02-23 17:04:14 -06:00
Leijurv e4416f424a interesting 2019-02-23 14:13:27 -08:00
Leijurv 73ec110b22 not every player is a baritone 2019-02-23 14:03:47 -08:00
Brady 0bce801a3f Minor javadoc changes 2019-02-23 14:32:10 -06:00
Brady e8e00e8dfb CRLF -> LF
It was inconsistent across the board
2019-02-23 12:27:24 -06:00
Leijurv cc4335e48e better links 2019-02-22 23:32:23 -08:00
Leijurv 5427911da3 only api in javadoc i guess 2019-02-22 23:29:08 -08:00
Brady c808d5a42d Small build.gradle cleanup and README update 2019-02-22 18:12:04 -06:00
Leijurv 3b46dbd6a1 appease codacy 2019-02-22 14:05:29 -08:00
Leijurv e63b2f1bf1 unused arg 2019-02-22 13:58:03 -08:00
Leijurv d32e822057 settings overhaul 2019-02-22 12:13:19 -08:00
Leijurv 16dcd2f44d blocks on top of chests, fixes #299 2019-02-21 11:25:03 -08:00
Leijurv eb9f755b54 disable rendercachedchunks in singleplayer, fixes #331 2019-02-21 10:03:03 -08:00
Leijurv 29a9e6e1d1 fine, forward alias to thisway 2019-02-21 09:45:01 -08:00
Leijurv 1f52f706ed should fix anticheatcompat off on forge 2019-02-20 23:41:29 -08:00
Leijurv a72040f83d imagine breaking the build 2019-02-19 19:52:11 -08:00
Leijurv 84d8f826ff fine lol, fixes #340 2019-02-19 19:41:26 -08:00
Brady 70d216b29f Fix renderGoalXZBeacon path rendering incorrect color 2019-02-19 21:00:14 -06:00
Leijurv 66356d5334 hmm 2019-02-19 18:27:05 -08:00
Leijurv d9625dfe78 no longer needed crab rave 2019-02-19 18:24:12 -08:00
Leijurv 6d847577d8 somehow missed those 2019-02-19 18:22:59 -08:00
Leijurv 8fd687f9d7 more usage help 2019-02-19 15:04:18 -08:00
Leijurv f7a9380b9d v1.1.6 2019-02-19 14:53:43 -08:00
Leijurv 5617c595b2 public init 2019-02-19 14:43:48 -08:00
Leijurv 8770524679 fix weird angle forcing behavior, fixes #341 2019-02-19 14:29:08 -08:00
Leijurv a8ddb2fcf1 also disallow while breaking 2019-02-19 13:28:58 -08:00
Leijurv 76c4ca9ba6 fix path reliability after lateral movement 2019-02-19 12:55:58 -08:00
Leijurv ed2b0f0bb9 fix jump before place ascend 2019-02-19 12:44:29 -08:00
Leijurv 6702b44b3e reformatted and fixed stuck on break fall 2019-02-19 12:43:44 -08:00
Leijurv c486d8241e continue 2019-02-19 07:53:36 -08:00
Leijurv d2bb8c374e explain 2019-02-18 21:18:37 -08:00
Leijurv 530cecea5b it flows better this way 2019-02-17 21:41:54 -08:00
Leijurv 266e2dada9 cleanup 2019-02-16 20:49:38 -08:00
Leijurv 11af0a7aac v1.1.5 2019-02-15 21:36:34 -08:00
Leijurv 46c2d8f7c7 unneeded 2019-02-15 21:35:52 -08:00
Leijurv 38127011fb Merge pull request #336 from babbaj/master
Fix potential problems
2019-02-14 14:48:48 -08:00
Leijurv 89b5ce4b63 properly detect failure 2019-02-14 14:47:38 -08:00
babbaj 4fe9c180d5 Fix potential problems 2019-02-14 07:03:22 -05:00
Leijurv f094e83e4d codacy 2019-02-13 22:41:18 -08:00
Leijurv 5b6c9fc348 blacklist unreachable gettoblocks 2019-02-13 22:39:43 -08:00
Leijurv 3f1ee100bf only sprint ascends that are followed in the same direction 2019-02-13 22:39:34 -08:00
Leijurv 41b1106c72 sprint in water for real 2019-02-13 21:20:06 -08:00
Leijurv b27d95a615 proper fall overshooting 2019-02-13 21:11:13 -08:00
Leijurv 5b8a83853d add setting to sprint in water 2019-02-13 19:23:16 -08:00
Leijurv d0548b2715 add a warning 2019-02-13 18:39:26 -08:00
Leijurv bffeb9c862 forgot one extra check 2019-02-13 18:38:46 -08:00
Leijurv dbd760fbcb some polish on ascend sprinting 2019-02-13 18:26:30 -08:00
Leijurv a84b3bfc7a sprint through ascends whenever possible, fixes #149 2019-02-13 16:55:08 -08:00
Leijurv e8d3bf509c clarify 2019-02-13 16:33:27 -08:00
Leijurv b2583773d5 discard next segment properly 2019-02-13 16:30:53 -08:00
Leijurv 9ecd24c755 remove toxic cloud 2019-02-13 16:30:41 -08:00
Leijurv f1bacd6210 fix cancellation of unusable segments 2019-02-13 16:22:49 -08:00
Leijurv a21ec54d4f stop breaking block when you let go of left click lol 2019-02-13 14:05:14 -08:00
Leijurv 0b4efb24ae momentous occasion: turning that crap off 2019-02-13 13:57:33 -08:00
Leijurv c473914d05 fix flashing backwards, fixes #265 2019-02-13 13:54:50 -08:00
Leijurv 90a1fa8337 lol 2019-02-12 22:06:13 -08:00
Leijurv 99cb7f5142 crucial performance optimization 2019-02-12 21:36:53 -08:00
Leijurv 4026b850f8 dont spam debug chat 2019-02-12 18:34:58 -08:00
Leijurv aac7ebf6dd avoid creating callbackinfo at all costs 2019-02-12 18:32:03 -08:00
Leijurv 8d481ba394 lol 2019-02-12 09:58:44 -08:00
Leijurv 24fa75c24e did someone say more badges 2019-02-11 22:26:49 -08:00
Leijurv cf38d593b8 thanks leafeon 2019-02-11 22:20:59 -08:00
Leijurv 36f608c63c add epic gamer address 2019-02-11 19:21:08 -08:00
Leijurv 1d88564a72 clarify this setting since its got a similar name 2019-02-10 16:50:54 -08:00
Leijurv 503f2fb197 direct link to the top of the detail section since its not sorted alphabetically 2019-02-10 16:46:37 -08:00
Leijurv bb000c4e3f include diagonals, and better settings 2019-02-10 16:44:09 -08:00
Leijurv 4868ed7560 explain whats going on 2019-02-10 15:12:52 -08:00
Leijurv 7017e9e2ea crucial performance optimization 2019-02-10 15:10:44 -08:00
Leijurv a18eb90702 address glaring inconsistency 2019-02-10 13:49:28 -08:00
Leijurv 9d1d4fe0d9 typo 2019-02-10 10:44:04 -08:00
Leijurv 1a430dc2cf explain 2019-02-09 17:38:42 -08:00
Leijurv e37a09a1c8 makes mining faster, fixes #330 2019-02-08 12:08:34 -08:00
Leijurv d0d8b12fb8 add clickCancel, fixes #326 2019-02-07 17:18:14 -08:00
Leijurv 9a29f9ce57 better behavior on arrival and failure 2019-02-07 16:39:15 -08:00
Leijurv 42513e4b56 better check 2019-02-07 16:12:34 -08:00
Leijurv 67fa91abe8 fixes to descend, and goto coords 2019-02-07 15:55:39 -08:00
Leijurv 6faa7344aa properly discard orphan path segments 2019-02-07 14:11:18 -08:00
Leijurv c0761c0eef be more tolerant of alternate movement inputs 2019-02-07 10:46:32 -08:00
Leijurv 46f8829951 v1.1.4 2019-02-07 09:16:19 -08:00
Leijurv b484e6fa3f literally disable the entire thing 2019-02-06 21:00:53 -08:00
Leijurv aa8773a67e fixes to sprinting through descend and diagonal 2019-02-06 20:54:07 -08:00
Leijurv bf9ee918f3 5 artifacts and documentation 2019-02-06 12:50:42 -08:00
Leijurv 92ba76e7a1 since all settings are individually final, the class should be too 2019-02-06 10:23:01 -08:00
Leijurv 3326339263 lol that wasnt even right 2019-02-05 22:17:28 -08:00
Leijurv 52cafbc7aa add a little version thingy 2019-02-05 21:49:09 -08:00
Leijurv efb316de14 codacy 2019-02-05 18:11:33 -08:00
Leijurv 3cf944398f 😭 2019-02-05 14:03:32 -08:00
Leijurv d2bfd47039 how to check 2019-02-05 12:41:30 -08:00
Leijurv 920cb6556b a bit more 2019-02-05 12:38:39 -08:00
Leijurv cd3ae2a7f5 documentation overhaul 2019-02-05 12:34:29 -08:00
Leijurv b12fedb2d9 help 2019-02-05 11:08:12 -08:00
Leijurv 1cae7ad6b1 v1.1.3 2019-02-05 09:55:29 -08:00
Leijurv 7dd881aa9a latest forge works yay 2019-02-05 09:54:17 -08:00
Leijurv c7ad235110 v1.1.2 2019-02-05 09:38:33 -08:00
Leijurv a989547976 add proper setting for suppressing clicks 2019-02-05 09:37:42 -08:00
Leijurv fa75880626 v1.1.1 2019-02-05 08:25:30 -08:00
Leijurv 529895f970 was only needed for freecam anyway 2019-02-05 08:25:14 -08:00
Leijurv 3d5de440fd what a mess 2019-02-04 21:30:58 -08:00
Leijurv 568bb1b0e8 some forge info 2019-02-04 21:23:19 -08:00
Leijurv b9ae8306dd v1.1.0 2019-02-04 20:11:55 -08:00
Leijurv 4aededff46 allow prefix and non prefix control at the same time 2019-02-04 19:57:01 -08:00
Leijurv ed8f9863e3 spacing 3 2019-02-04 19:37:36 -08:00
Leijurv e85de55c8f spacing 2 2019-02-04 19:36:16 -08:00
Leijurv adbf927270 spacing 2019-02-04 19:35:22 -08:00
Leijurv dfe171a5c2 forge 2019-02-04 19:34:44 -08:00
Leijurv b55e449398 extra line 2019-02-04 19:01:50 -08:00
Leijurv 62b11c0a8a i'm legitimately sorry 2019-02-04 19:01:01 -08:00
Leijurv 90cb11f55e this is needed 2019-02-04 18:19:51 -08:00
Leijurv 40a66b0306 almost forge support 2019-02-04 18:05:05 -08:00
Leijurv 8c899698e0 explore for blocks, fixes #323 2019-02-04 16:27:32 -08:00
Leijurv 58fa1571f3 added more info 2019-02-04 15:43:02 -08:00
Leijurv 2cbe77aa04 many fixes 2019-02-04 15:24:27 -08:00
Leijurv a0c2935580 Merge branch 'master' into mega-cancer-rendering 2019-02-04 14:52:30 -08:00
Leijurv 798f25ff81 dont glitch weirdly when failing a parkour jump 2019-02-04 13:52:11 -08:00
Leijurv 57b2e360ca dont include current movement cost while deciding when to plan ahead 2019-02-04 13:27:35 -08:00
Leijurv ee23d59e11 now we can cache flowing water properly 2019-02-04 13:07:56 -08:00
Leijurv 04e7da9b73 lower walk into can be water, but not upper 2019-02-04 13:07:05 -08:00
Leijurv 5382d265f2 crucial performance optimization 2019-02-03 19:46:59 -08:00
Leijurv 0e1534613c appease codacy 2019-02-03 19:34:29 -08:00
Leijurv d799fac688 epicer gradle output 2019-02-03 19:27:28 -08:00
Leijurv 913247996e smh my head. who right clicks gradle tasks?? 2019-02-02 14:23:01 -08:00
Leijurv dc3bab26de 6 months =D 2019-02-01 22:54:14 -08:00
Leijurv 5c1cf050e2 im idiot 2019-01-31 20:27:14 -08:00
Leijurv 747bee41b7 holding control shouldnt make all bots sprint 2019-01-31 20:26:24 -08:00
Leijurv 246c00c773 dont repeat that 2019-01-31 19:19:44 -08:00
Leijurv b953da0341 more accurate isEmpty 2019-01-30 12:19:15 -08:00
Leijurv c2a6445c9e Merge branch 'master' into mega-cancer-rendering 2019-01-30 12:07:58 -08:00
Leijurv b177ae7ee6 proguard can just ignore GL14 reference actually 2019-01-30 11:57:54 -08:00
Leijurv 8947eff3b1 bsi might be old 2019-01-30 11:42:46 -08:00
Brady 06b3c5ddb5 LeijurvUtils 2019-01-30 12:42:26 -06:00
Leijurv 1968f47fc9 add a setting to play with 2019-01-29 19:44:23 -08:00
Leijurv 6a2cd9d3ba Merge branch 'master' into mega-cancer-rendering 2019-01-29 13:55:00 -08:00
Leijurv 9028564c10 only when the setting is enabled 2019-01-29 13:54:54 -08:00
Brady b471d7419e Replace most of the @Inject usages for cancer render with @Redirect 2019-01-29 12:41:14 -06:00
Leijurv 5179cfc5ba semitransparency working 2019-01-28 21:28:26 -08:00
Leijurv 784b2f541d lol 2019-01-28 19:02:07 -08:00
Leijurv 735cf47c35 actually works 2019-01-28 17:34:14 -08:00
Leijurv b005ce8e6b mega cancer render cached chunks 2019-01-17 18:54:37 -08:00
71 changed files with 2217 additions and 1273 deletions
+4 -4
View File
@@ -4,7 +4,7 @@
- **Block breaking** Baritone considers breaking blocks as part of its path. It also takes into account your current tool set and hot bar. For example, if you have a Eff V diamond pick, it may choose to mine through a stone barrier, while if you only had a wood pick it might be faster to climb over it. - **Block breaking** Baritone considers breaking blocks as part of its path. It also takes into account your current tool set and hot bar. For example, if you have a Eff V diamond pick, it may choose to mine through a stone barrier, while if you only had a wood pick it might be faster to climb over it.
- **Block placing** Baritone considers placing blocks as part of its path. This includes sneak-back-placing, pillaring, etc. It has a configurable penalty of placing a block (set to 1 second by default), to conserve its resources. The list of acceptable throwaway blocks is also configurable, and is cobble, dirt, or netherrack by default. <a href="https://www.youtube.com/watch?v=F6FbI1L9UmU">Example</a> - **Block placing** Baritone considers placing blocks as part of its path. This includes sneak-back-placing, pillaring, etc. It has a configurable penalty of placing a block (set to 1 second by default), to conserve its resources. The list of acceptable throwaway blocks is also configurable, and is cobble, dirt, or netherrack by default. <a href="https://www.youtube.com/watch?v=F6FbI1L9UmU">Example</a>
- **Falling** Baritone will fall up to 3 blocks onto solid ground (configurable, if you have Feather Falling and/or don't mind taking a little damage). If you have a water bucket on your hotbar, it will fall up to 23 blocks and place the bucket beneath it. It will fall an unlimited distance into existing still water. - **Falling** Baritone will fall up to 3 blocks onto solid ground (configurable, if you have Feather Falling and/or don't mind taking a little damage). If you have a water bucket on your hotbar, it will fall up to 23 blocks and place the bucket beneath it. It will fall an unlimited distance into existing still water.
- **Vines and ladders** Baritone understands how to climb and descend vines and ladders. There is experimental support for more advanced maneuvers, like strafing to a different ladder / vine column in midair (off by default, setting named `allowVines`). - **Vines and ladders** Baritone understands how to climb and descend vines and ladders. There is experimental support for more advanced maneuvers, like strafing to a different ladder / vine column in midair (off by default, setting named `allowVines`). Baritone can break its fall by grabbing ladders / vines midair, and understands when that is and isn't possible.
- **Opening fence gates and doors** - **Opening fence gates and doors**
- **Slabs and stairs** - **Slabs and stairs**
- **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore). - **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore).
@@ -22,9 +22,9 @@ Baritone uses A*, with some modifications:
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment. The cost is decreased heavily, but is still positive (this won't cause it to backtrack if it doesn't need to). This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a> - **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment. The cost is decreased heavily, but is still positive (this won't cause it to backtrack if it doesn't need to). This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a>
- **Backtrack detection and pausing** While path calculation happens on a separate thread, the main game thread has access to the latest node considered, and the best path so far (those are rendered light blue and dark blue respectively). When the current best path (rendered dark blue) passes through the player's current position on the current path segment, path execution is paused (if it's safe to do so), because there's no point continuing forward if we're about to turn around and go back that same way. Note that the current best path as reported by the path calculation thread takes into account the incremental cost backoff system, so it's accurate to what the path calculation thread will actually pick once it finishes. - **Backtrack detection and pausing** While path calculation happens on a separate thread, the main game thread has access to the latest node considered, and the best path so far (those are rendered light blue and dark blue respectively). When the current best path (rendered dark blue) passes through the player's current position on the current path segment, path execution is paused (if it's safe to do so), because there's no point continuing forward if we're about to turn around and go back that same way. Note that the current best path as reported by the path calculation thread takes into account the incremental cost backoff system, so it's accurate to what the path calculation thread will actually pick once it finishes.
# Configuring Baritone # Chat control
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>.
To change a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `pathTimeoutMS 250`). It's case insensitive. - [Baritone chat control usage](USAGE.md)
# Goals # Goals
The pathing goal can be set to any of these options: The pathing goal can be set to any of these options:
-88
View File
@@ -1,88 +0,0 @@
# Integration between Baritone and Impact
Impact 4.4 has Baritone included.
These instructions apply to Impact 4.3 (and potentially other "hacked clients").
To run Baritone on Vanilla, just follow the instructions in the README (it's `./gradlew runClient`).
## An Introduction
There are some basic steps to getting Baritone setup with Impact.
- Acquiring a build of Baritone
- Placing Baritone in the libraries directory
- Modifying the Impact Profile JSON to run baritone
- How to use Baritone
## Acquiring a build of Baritone
There are two methods of acquiring a build of Baritone
### Official Release (Not always up to date)
https://github.com/cabaletta/baritone/releases
For Impact 4.3, there is no Baritone integration yet, so you will want `baritone-standalone-X.Y.Z.jar`.
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone . && docker run --rm cabaletta/baritone cat /code/dist/checksums.txt` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
### Building Baritone yourself
You can either build Baritone through a command line or through IntelliJ's UI, information on that can be found [here](SETUP.md#building).
## Placing Baritone in the libraries directory
``/libraries`` is a neat directory in your <a href="https://minecraft.gamepedia.com/.minecraft">Minecraft Installation Directory</a>
that contains all of the dependencies that are required from the game and some mods. This is where we will be
putting baritone.
- Locate the ``libraries`` folder, it should be in the Minecraft Installation Directory
- Create 3 new subdirectories starting from ``libraries``
- ``cabaletta``
- ``baritone``
- ``X.Y.Z``
- Copy the build of Baritone that was acquired earlier, and place it into the ``X.Y.Z`` folder
- The full path should look like ``<Minecraft>/libraries/cabaletta/baritone/X.Y.Z/baritone-X.Y.Z.jar``
## Modifying the Impact Profile JSON to run baritone
The final step is "registering" the Baritone library with Impact, so that it loads on launch.
- Ensure your Minecraft launcher is closed
- Navigate back to the Minecraft Installation Directory
- Find the ``versions`` directory, and open in
- In here there should be a ``1.12.2-Impact_4.3`` folder.
- If you don't have any Impact folder or have a version older than 4.3, you can download Impact <a href="https://impactdevelopment.github.io">here</a>.
- Open the folder and inside there should be a file called ``1.12.2-Impact_4.3.json``
- Open the JSON file with a text editor that supports your system's line endings
- For example, Notepad on Windows likely will NOT work for this. You should instead use a Text Editor like
<a href="https://notepad-plus-plus.org/">Notepad++</a> if you're on Windows. (For other systems, I'm not sure
what would work the best so you may have to do some research.)
- Find the ``libraries`` array in the JSON. It should look something like this.
```
"libraries": [
{
"name": "net.minecraft:launchwrapper:1.12"
},
{
"name": "com.github.ImpactDevelopment:Impact:4.3-1.12.2",
"url": "https://impactdevelopment.github.io/maven/"
},
{
"name": "com.github.ImpactDeveloment:ClientAPI:3.0.2",
"url": "https://impactdevelopment.github.io/maven/"
},
...
```
- Create two new objects in the array, between the ``Impact`` and ``ClientAPI`` dependencies preferably.
```
{
"name": "cabaletta:baritone:X.Y.Z"
},
{
"name": "com.github.ImpactDevelopment:SimpleTweaker:1.2",
"url": "https://impactdevelopment.github.io/maven/"
},
```
- Now find the ``"minecraftArguments": "..."`` text near the top.
- At the very end of the quotes where it says ``--tweakClass clientapi.load.ClientTweaker"``, add on the following so it looks like:
- ``--tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine"``
- If you didn't close your launcher for this step, restart it now.
- You can now launch Impact 4.3 as normal, and Baritone should start up
## How to use Baritone
Instructions on how to use Baritone are limited, and you may have to read a little bit of code (Really nothing much
just plain English), you can view that <a href="https://github.com/cabaletta/baritone#chat-control">here</a>.
Binary file not shown.

After

Width:  |  Height:  |  Size: 6.7 KiB

+20 -9
View File
@@ -1,7 +1,7 @@
# Baritone # Baritone
[![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone) [![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone)
[![Release](https://img.shields.io/github/release/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/releases) [![Release](https://img.shields.io/github/release/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/releases)
[![License](https://img.shields.io/badge/license-LGPL--3.0-green.svg)](LICENSE) [![License](https://img.shields.io/badge/license-LGPL--3.0%20with%20anime%20exception-green.svg)](LICENSE)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a73d037823b64a5faf597a18d71e3400)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/a73d037823b64a5faf597a18d71e3400)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade)
[![HitCount](http://hits.dwyl.com/cabaletta/baritone.svg)](http://hits.dwyl.com/cabaletta/baritone) [![HitCount](http://hits.dwyl.com/cabaletta/baritone.svg)](http://hits.dwyl.com/cabaletta/baritone)
[![Known Vulnerabilities](https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle) [![Known Vulnerabilities](https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle)
@@ -11,6 +11,8 @@
[![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/) [![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/)
![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg) ![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg)
![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg) ![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg)
![](https://tokei.rs/b1/github/cabaletta/baritone?category=code)
![](https://tokei.rs/b1/github/cabaletta/baritone?category=files)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2) [![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2)
[![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/) [![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/)
[![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/) [![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/)
@@ -28,22 +30,31 @@ Baritone is the pathfinding system used in [Impact](https://impactdevelopment.gi
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/), This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths). the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Have committed at least once a day for the last 6 months =D 🦀
1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2
# Getting Started
Here are some links to help to get started: Here are some links to help to get started:
- [Features](FEATURES.md) - [Features](FEATURES.md)
- [Setup](SETUP.md) - [Installation & setup](SETUP.md)
- [Installation](INSTALL.md) - [API Javadocs](https://baritone.leijurv.com/)
- [Javadocs](https://baritone.leijurv.com/) - [Settings](https://baritone.leijurv.com/baritone/api/Settings.html#field.detail)
# Chat control - [Baritone chat control usage](USAGE.md)
[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java)
Quick start example: `thisway 1000` or `goal 70` to set the goal, `path` to actually start pathing. Also try `mine diamond_ore`. `cancel` to cancel. # API
# API example The API is heavily documented, you can find the Javadocs for the latest release [here](https://baritone.leijurv.com/).
Please note that usage of anything located outside of the ``baritone.api`` package is not supported by the API release
jar.
Below is an example of basic usage for changing some settings, and then pathing to a X/Z goal.
``` ```
BaritoneAPI.getSettings().allowSprint.value = true; BaritoneAPI.getSettings().allowSprint.value = true;
@@ -56,7 +67,7 @@ BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAnd
## Can I use Baritone as a library in my custom utility client? ## Can I use Baritone as a library in my custom utility client?
Sure! (As long as usage is in compliance with the LGPL 3 License) That's what it's for, sure! (As long as usage is in compliance with the LGPL 3 License)
## How is it so fast? ## How is it so fast?
+32 -13
View File
@@ -1,5 +1,35 @@
# Setup # Installation
## 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 `builder` branch for example, you'll have to build it yourself)
Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases)
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` 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).
**The Forge release can simply be added as a Forge mod.**
If another one of your Forge mods has a Baritone integration, you want `baritone-api-forge-VERSION.jar`. Otherwise, you want `baritone-standalone-forge-VERSION.jar`
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
- **Forge API**: Same as API, but packaged for Forge. This should be used where another mod has a Baritone integration.
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
- **Forge Standalone**: Same as Standalone, but packaged for Forge. This should be used when Baritone is your only Forge mod, or none of your other Forge mods integrate with Baritone.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
## More Info
To replace out Impact 4.5's Baritone build with a customized one, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.2/baritone-api-1.2.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.5/1.12.2-Impact_4.5.json`, find the line `"name": "cabaletta:baritone-api:1.2"`, remove the comma from the end, and **entirely remove the next line** (starts with `"url"`).
You can verify whether or not it worked by running `.b version` in chat (only valid in Impact). If it says `v1.2.0` then you didn't do it properly, and it's still running the version that came with 4.5.
## Build it yourself
- Clone or download Baritone - Clone or download Baritone
![Image](https://i.imgur.com/kbqBtoN.png) ![Image](https://i.imgur.com/kbqBtoN.png)
@@ -65,15 +95,4 @@ $ gradlew build
![Image](https://i.imgur.com/PE6r9iN.png) ![Image](https://i.imgur.com/PE6r9iN.png)
- Right click on **build** and press **Run** - Double click on **build** to run it
## Artifacts
Building Baritone will result in 3 artifacts created in the ``dist`` directory.
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
- **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.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
## More Info
To replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
+80
View File
@@ -0,0 +1,80 @@
(assuming you already have Baritone [set up](SETUP.md))
# Prefix
Baritone commands can by default be typed in the chatbox. However if you make a typo, like typing "gola 10000 10000" instead of goal it goes into public chat, which is bad.
Therefore you can use a prefix before your messages.
On Baritone v1.1.0 and newer: The prefix is `#` by default. Anything beginning with `#` isn't sent, and is only interpreted by Baritone.
For older than v1.1.0, `#` must be enabled by toggling on the `prefix` setting.
**Only** in Impact is `.b` also a valid prefix. In 4.4, `#` does **not** work, neither does saying the commands directly in chat. `#` works by default in 4.5 (not 4.4).
Other clients like Kami and Asuna have their own custom things (like `-path`), and can disable direct chat control entirely.
# Commands
**All** of these commands may need a prefix before them, as above ^.
`help` for (rudimentary) help. You can see what it says [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java#L53).
To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`.
Some common examples:
- `thisway 1000` then `path` to go in the direction you're facing for a thousand blocks
- `goal x y z` or `goal x z` or `goal y`, then `path` to go to a certain coordinate
- `goal` to set the goal to your player's feet
- `goal clear` to clear the goal
- `cancel` or `stop` to stop everything
- `goto portal` or `goto ender_chest` or `goto block_type` to go to a block. (in Impact, `.goto` is an alias for `.b goto` for the most part)
- `mine diamond_ore` to mine diamond ore (turn on the setting `legitMine` to only mine ores that it can actually see. It will explore randomly around y=11 until it finds them.)
- `follow playerName` to follow a player. `follow` to follow the entity you're looking at (only works if it hitting range). `followplayers` to follow any players in range (combine with Kill Aura for a fun time).
- `save waypointName` to save a waypoint. `goto waypointName` to go to it.
- `axis` to go to an axis or diagonal axis at y=120 (`axisHeight` is a configurable setting, defaults to 120).
- `invert` to invert the current goal and path. This gets as far away from it as possible, instead of as close as possible. For example, do `goal` then `invert` to run as far as possible from where you're standing at the start.
- `render` to rerender the world in case `renderCachedChunks` is being glitchy
- `version` to get the version of Baritone you're running
- `damn` daniel
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java).
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#field.detail">here</a>.
There are about a hundred settings, but here are some fun / interesting / important ones that you might want to look at changing in normal usage of Baritone. The documentation for each can be found at the above links.
- `allowBreak`
- `allowSprint`
- `allowPlace`
- `allowParkour`
- `allowParkourPlace`
- `renderCachedChunks` (and `cachedChunksOpacity`) <-- very fun but you need a beefy computer
- `avoidance`
- `legitMine`
- `followRadius`
# Troubleshooting / common issues
## Baritone highlights a block in green but gets completely stuck? Also I'm using Baritone with Future?
Baritone is trying to right click to place a block there, but it can't since there's a conflicting mixin. Baritone can't force click right click when Future is also installed. Left click **does work** on recent Baritone even with Future, however. For now, turn off `allowPlace` and Baritone will only search for paths that don't require placing blocks to complete. `allowBreak` can remain on.
## Why doesn't Baritone respond to any of my chat commands?
This could be one of many things.
First, make sure it's actually installed. An easy way to check is seeing if it created the folder `baritone` in your Minecraft folder.
Second, make sure that you're using the prefix properly, and that chat control is enabled in the way you expect.
For example, Impact disables direct chat control. (i.e. anything typed in chat without a prefix will be ignored and sent publicly). **This is a saved setting**, so if you run Impact once, `chatControl` will be off from then on, **even in other clients**.
So you'll need to use the `#` prefix or edit `baritone/settings.txt` in your Minecraft folder to undo that (specifically, remove the line `chatControl false` then restart your client).
## Why can I do `.goto x z` in Impact but nowhere else? Why can I do `-path to x z` in KAMI but nowhere else?
These are custom commands that they added; those aren't from Baritone.
The equivalent you're looking for is `goal x z` then `path`.
+12 -3
View File
@@ -16,7 +16,7 @@
*/ */
group 'baritone' group 'baritone'
version '1.0.0-hotfix-2' version '1.2.2'
buildscript { buildscript {
repositories { repositories {
@@ -95,7 +95,7 @@ dependencies {
} }
mixin { mixin {
defaultObfuscationEnv notch defaultObfuscationEnv searge
add sourceSets.launch, 'mixins.baritone.refmap.json' add sourceSets.launch, 'mixins.baritone.refmap.json'
} }
@@ -103,7 +103,7 @@ javadoc {
options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error
options.linkSource true options.linkSource true
options.encoding "UTF-8" // allow emoji in comments :^) options.encoding "UTF-8" // allow emoji in comments :^)
source += sourceSets.api.allJava source = sourceSets.api.allJava
classpath += sourceSets.api.compileClasspath classpath += sourceSets.api.compileClasspath
} }
@@ -111,6 +111,15 @@ jar {
from sourceSets.launch.output, sourceSets.api.output from sourceSets.launch.output, sourceSets.api.output
preserveFileTimestamps = false preserveFileTimestamps = false
reproducibleFileOrder = true reproducibleFileOrder = true
manifest {
attributes(
'MixinConfigs': 'mixins.baritone.json',
'Implementation-Title': 'Baritone',
'Implementation-Version': version
)
}
} }
task proguard(type: ProguardTask) { task proguard(type: ProguardTask) {
@@ -17,8 +17,6 @@
package baritone.gradle.task; package baritone.gradle.task;
import com.google.gson.JsonElement;
import com.google.gson.JsonParser;
import org.gradle.api.DefaultTask; import org.gradle.api.DefaultTask;
import java.io.File; import java.io.File;
@@ -26,7 +24,6 @@ import java.io.InputStream;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.nio.file.Paths; import java.nio.file.Paths;
import java.util.List;
/** /**
* @author Brady * @author Brady
@@ -34,8 +31,6 @@ import java.util.List;
*/ */
class BaritoneGradleTask extends DefaultTask { class BaritoneGradleTask extends DefaultTask {
protected static final JsonParser PARSER = new JsonParser();
protected static final String protected static final String
PROGUARD_ZIP = "proguard.zip", PROGUARD_ZIP = "proguard.zip",
PROGUARD_JAR = "proguard.jar", PROGUARD_JAR = "proguard.jar",
@@ -45,26 +40,28 @@ class BaritoneGradleTask extends DefaultTask {
PROGUARD_STANDALONE_CONFIG = "standalone.pro", PROGUARD_STANDALONE_CONFIG = "standalone.pro",
PROGUARD_EXPORT_PATH = "proguard_out.jar", PROGUARD_EXPORT_PATH = "proguard_out.jar",
VERSION_MANIFEST = "version_manifest.json",
TEMP_LIBRARY_DIR = "tempLibraries/", TEMP_LIBRARY_DIR = "tempLibraries/",
ARTIFACT_STANDARD = "%s-%s.jar", ARTIFACT_STANDARD = "%s-%s.jar",
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar", ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
ARTIFACT_API = "%s-api-%s.jar", ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar"; ARTIFACT_STANDALONE = "%s-standalone-%s.jar",
ARTIFACT_FORGE_API = "%s-api-forge-%s.jar",
ARTIFACT_FORGE_STANDALONE = "%s-standalone-forge-%s.jar";
protected String artifactName, artifactVersion; protected String artifactName, artifactVersion;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut; protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, artifactForgeApiPath, artifactForgeStandalonePath, proguardOut;
protected void verifyArtifacts() throws IllegalStateException { protected void verifyArtifacts() throws IllegalStateException {
this.artifactName = getProject().getName(); this.artifactName = getProject().getName();
this.artifactVersion = getProject().getVersion().toString(); this.artifactVersion = getProject().getVersion().toString();
this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD)); this.artifactPath = this.getBuildFile(formatVersion(ARTIFACT_STANDARD));
this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED)); this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API)); this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE)); this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API));
this.artifactForgeStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_STANDALONE));
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH); this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
@@ -95,8 +92,4 @@ class BaritoneGradleTask extends DefaultTask {
protected Path getBuildFile(String file) { protected Path getBuildFile(String file) {
return getRelativeFile("build/libs/" + file); return getRelativeFile("build/libs/" + file);
} }
protected JsonElement readJson(List<String> lines) {
return PARSER.parse(String.join("\n", lines));
}
} }
@@ -42,9 +42,11 @@ public class CreateDistTask extends BaritoneGradleTask {
super.verifyArtifacts(); super.verifyArtifacts();
// Define the distribution file paths // Define the distribution file paths
Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API)); Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE)); Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED)); Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
Path forgeApi = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_API));
Path forgeStandalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_STANDALONE));
// NIO will not automatically create directories // NIO will not automatically create directories
Path dir = getRelativeFile("dist/"); Path dir = getRelativeFile("dist/");
@@ -53,12 +55,14 @@ public class CreateDistTask extends BaritoneGradleTask {
} }
// Copy build jars to dist/ // Copy build jars to dist/
Files.copy(this.artifactApiPath, api, REPLACE_EXISTING); Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING); Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING); Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
Files.copy(this.artifactForgeApiPath, forgeApi, REPLACE_EXISTING);
Files.copy(this.artifactForgeStandalonePath, forgeStandalone, REPLACE_EXISTING);
// Calculate all checksums and format them like "shasum" // Calculate all checksums and format them like "shasum"
List<String> shasum = Stream.of(api, standalone, unoptimized) List<String> shasum = Stream.of(api, forgeApi, standalone, forgeStandalone, unoptimized)
.map(path -> sha1(path) + " " + path.getFileName().toString()) .map(path -> sha1(path) + " " + path.getFileName().toString())
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -59,6 +59,8 @@ public class ProguardTask extends BaritoneGradleTask {
private List<String> requiredLibraries; private List<String> requiredLibraries;
private File mixin;
@TaskAction @TaskAction
protected void exec() throws Exception { protected void exec() throws Exception {
super.verifyArtifacts(); super.verifyArtifacts();
@@ -79,7 +81,7 @@ public class ProguardTask extends BaritoneGradleTask {
Files.delete(this.artifactUnoptimizedPath); Files.delete(this.artifactUnoptimizedPath);
} }
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString()); Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Optional.empty());
} }
private void downloadProguard() throws Exception { private void downloadProguard() throws Exception {
@@ -173,10 +175,16 @@ public class ProguardTask extends BaritoneGradleTask {
// Find the library jar file, and copy it to tempLibraries // Find the library jar file, and copy it to tempLibraries
for (File file : pair.getLeft().files(pair.getRight())) { for (File file : pair.getLeft().files(pair.getRight())) {
if (file.getName().startsWith(lib)) { if (file.getName().startsWith(lib)) {
if (lib.contains("mixin")) {
mixin = file;
}
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING); Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
} }
} }
} }
if (mixin == null) {
throw new IllegalStateException("Unable to find mixin jar");
}
} }
// a bunch of epic stuff to get the path to the cached jar // a bunch of epic stuff to get the path to the cached jar
@@ -264,12 +272,14 @@ public class ProguardTask extends BaritoneGradleTask {
private void proguardApi() throws Exception { private void proguardApi() throws Exception {
runProguard(getTemporaryFile(PROGUARD_API_CONFIG)); runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString()); Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Optional.of(mixin));
} }
private void proguardStandalone() throws Exception { private void proguardStandalone() throws Exception {
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG)); runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString()); Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Optional.empty());
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Optional.of(mixin));
} }
private void cleanup() { private void cleanup() {
@@ -298,8 +308,8 @@ public class ProguardTask extends BaritoneGradleTask {
.start(); .start();
// We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this // We can't do output inherit process I/O with gradle for some reason and have it work, so we have to do this
this.printOutputLog(p.getInputStream()); this.printOutputLog(p.getInputStream(), System.out);
this.printOutputLog(p.getErrorStream()); this.printOutputLog(p.getErrorStream(), System.err);
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception // Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
int exitCode = p.waitFor(); int exitCode = p.waitFor();
@@ -308,12 +318,12 @@ public class ProguardTask extends BaritoneGradleTask {
} }
} }
private void printOutputLog(InputStream stream) { private void printOutputLog(InputStream stream, PrintStream outerr) {
new Thread(() -> { new Thread(() -> {
try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) { try (BufferedReader reader = new BufferedReader(new InputStreamReader(stream))) {
String line; String line;
while ((line = reader.readLine()) != null) { while ((line = reader.readLine()) != null) {
System.out.println(line); outerr.println(line);
} }
} catch (Exception e) { } catch (Exception e) {
e.printStackTrace(); e.printStackTrace();
@@ -22,10 +22,7 @@ import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonWriter; import com.google.gson.stream.JsonWriter;
import java.io.*; import java.io.*;
import java.util.ArrayList; import java.util.*;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
import java.util.jar.JarEntry; import java.util.jar.JarEntry;
import java.util.jar.JarFile; import java.util.jar.JarFile;
import java.util.jar.JarOutputStream; import java.util.jar.JarOutputStream;
@@ -39,7 +36,7 @@ import java.util.stream.Collectors;
*/ */
public class Determinizer { public class Determinizer {
public static void determinize(String inputPath, String outputPath) throws IOException { public static void determinize(String inputPath, String outputPath, Optional<File> toInclude) throws IOException {
System.out.println("Running Determinizer"); System.out.println("Running Determinizer");
System.out.println(" Input path: " + inputPath); System.out.println(" Input path: " + inputPath);
System.out.println(" Output path: " + outputPath); System.out.println(" Output path: " + outputPath);
@@ -66,10 +63,30 @@ public class Determinizer {
if (entry.getName().endsWith(".refmap.json")) { if (entry.getName().endsWith(".refmap.json")) {
JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject(); JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
jos.write(writeSorted(object).getBytes()); jos.write(writeSorted(object).getBytes());
} else if (entry.getName().equals("META-INF/MANIFEST.MF") && toInclude.isPresent()) { // only replace for forge jar
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
copy(jarFile.getInputStream(entry), cancer);
String manifest = new String(cancer.toByteArray());
if (!manifest.contains("baritone.launch.BaritoneTweaker")) {
throw new IllegalStateException("unable to replace");
}
manifest = manifest.replace("baritone.launch.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
jos.write(manifest.getBytes());
} else { } else {
copy(jarFile.getInputStream(entry), jos); copy(jarFile.getInputStream(entry), jos);
} }
} }
if (toInclude.isPresent()) {
try (JarFile mixin = new JarFile(toInclude.get())) {
for (JarEntry entry : mixin.stream().sorted(Comparator.comparing(JarEntry::getName)).collect(Collectors.toList())) {
if (entry.getName().startsWith("META-INF") && !entry.getName().startsWith("META-INF/services")) {
continue;
}
jos.putNextEntry(entry);
copy(mixin.getInputStream(entry), jos);
}
}
}
jos.finish(); jos.finish();
} }
} }
+3 -3
View File
@@ -12,15 +12,15 @@
-flattenpackagehierarchy -flattenpackagehierarchy
-repackageclasses 'baritone' -repackageclasses 'baritone'
# lwjgl is weird
-dontwarn org.lwjgl.**
-keep class baritone.api.** { *; } # this is the keep api -keep class baritone.api.** { *; } # this is the keep api
# service provider needs these class names # service provider needs these class names
-keep class baritone.BaritoneProvider -keep class baritone.BaritoneProvider
-keep class baritone.api.IBaritoneProvider -keep class baritone.api.IBaritoneProvider
# hack
-keep class baritone.utils.ExampleBaritoneControl { *; } # have to include this string to remove this keep in the standalone build: # this is the keep api
# setting names are reflected from field names, so keep field names # setting names are reflected from field names, so keep field names
-keepclassmembers class baritone.api.Settings { -keepclassmembers class baritone.api.Settings {
public <fields>; public <fields>;
+1 -3
View File
@@ -23,9 +23,7 @@ import java.util.Iterator;
import java.util.ServiceLoader; import java.util.ServiceLoader;
/** /**
* API exposure for various things implemented in Baritone. * Exposes the {@link IBaritoneProvider} instance and the {@link Settings} instance for API usage.
* <p>
* W.I.P
* *
* @author Brady * @author Brady
* @since 9/23/2018 * @since 9/23/2018
+56 -23
View File
@@ -22,10 +22,7 @@ import baritone.api.behavior.IPathingBehavior;
import baritone.api.cache.IWorldProvider; import baritone.api.cache.IWorldProvider;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.pathing.calc.IPathingControlManager; import baritone.api.pathing.calc.IPathingControlManager;
import baritone.api.process.ICustomGoalProcess; import baritone.api.process.*;
import baritone.api.process.IFollowProcess;
import baritone.api.process.IGetToBlockProcess;
import baritone.api.process.IMineProcess;
import baritone.api.utils.IInputOverrideHandler; import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
@@ -36,22 +33,13 @@ import baritone.api.utils.IPlayerContext;
public interface IBaritone { public interface IBaritone {
/** /**
* @return The {@link IFollowProcess} instance * Call as soon as Minecraft is ready, initializes all of the processes, behaviors, etc. This will
* @see IFollowProcess * only effectively be ran once, any additional calls are redundant because the initialization state
* is saved.
* <p>
* Or whenever your overeager utility client wants.
*/ */
IFollowProcess getFollowProcess(); void init();
/**
* @return The {@link ILookBehavior} instance
* @see ILookBehavior
*/
ILookBehavior getLookBehavior();
/**
* @return The {@link IMineProcess} instance
* @see IMineProcess
*/
IMineProcess getMineProcess();
/** /**
* @return The {@link IPathingBehavior} instance * @return The {@link IPathingBehavior} instance
@@ -59,21 +47,66 @@ public interface IBaritone {
*/ */
IPathingBehavior getPathingBehavior(); IPathingBehavior getPathingBehavior();
/**
* @return The {@link ILookBehavior} instance
* @see ILookBehavior
*/
ILookBehavior getLookBehavior();
/**
* @return The {@link IFollowProcess} instance
* @see IFollowProcess
*/
IFollowProcess getFollowProcess();
/**
* @return The {@link IMineProcess} instance
* @see IMineProcess
*/
IMineProcess getMineProcess();
/**
* @return The {@link ICustomGoalProcess} instance
* @see ICustomGoalProcess
*/
ICustomGoalProcess getCustomGoalProcess();
/**
* @return The {@link IGetToBlockProcess} instance
* @see IGetToBlockProcess
*/
IGetToBlockProcess getGetToBlockProcess();
/** /**
* @return The {@link IWorldProvider} instance * @return The {@link IWorldProvider} instance
* @see IWorldProvider * @see IWorldProvider
*/ */
IWorldProvider getWorldProvider(); IWorldProvider getWorldProvider();
/**
* Returns the {@link IPathingControlManager} for this {@link IBaritone} instance, which is responsible
* for managing the {@link IBaritoneProcess}es which control the {@link IPathingBehavior} state.
*
* @return The {@link IPathingControlManager} instance
* @see IPathingControlManager
*/
IPathingControlManager getPathingControlManager(); IPathingControlManager getPathingControlManager();
/**
* @return The {@link IInputOverrideHandler} instance
* @see IInputOverrideHandler
*/
IInputOverrideHandler getInputOverrideHandler(); IInputOverrideHandler getInputOverrideHandler();
ICustomGoalProcess getCustomGoalProcess(); /**
* @return The {@link IPlayerContext} instance
IGetToBlockProcess getGetToBlockProcess(); * @see IPlayerContext
*/
IPlayerContext getPlayerContext(); IPlayerContext getPlayerContext();
/**
* @return The {@link IEventBus} instance
* @see IEventBus
*/
IEventBus getGameEventHandler(); IEventBus getGameEventHandler();
} }
@@ -23,7 +23,9 @@ import net.minecraft.client.entity.EntityPlayerSP;
import java.util.List; import java.util.List;
/** /**
* @author Leijurv * Provides the present {@link IBaritone} instances
*
* @author leijurv
*/ */
public interface IBaritoneProvider { public interface IBaritoneProvider {
@@ -47,7 +49,8 @@ public interface IBaritoneProvider {
/** /**
* Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be * Provides the {@link IBaritone} instance for a given {@link EntityPlayerSP}. This will likely be
* replaced with {@code #getBaritoneForUser(IBaritoneUser)} when {@code bot-system} is merged. * replaced with or be overloaded in addition to {@code #getBaritoneForUser(IBaritoneUser)} when
* {@code bot-system} is merged into {@code master}.
* *
* @param player The player * @param player The player
* @return The {@link IBaritone} instance. * @return The {@link IBaritone} instance.
@@ -58,7 +61,7 @@ public interface IBaritoneProvider {
return baritone; return baritone;
} }
} }
throw new IllegalStateException("No baritone for player " + player); return null;
} }
/** /**
+79 -12
View File
@@ -17,6 +17,7 @@
package baritone.api; package baritone.api;
import baritone.api.utils.SettingsUtil;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.Item; import net.minecraft.item.Item;
@@ -29,7 +30,7 @@ import java.util.List;
import java.util.function.Consumer; import java.util.function.Consumer;
/** /**
* Baritone's settings * Baritone's settings. Settings apply to all Baritone instances.
* *
* @author leijurv * @author leijurv
*/ */
@@ -164,6 +165,16 @@ public final class Settings {
*/ */
public final Setting<Boolean> considerPotionEffects = new Setting<>(true); public final Setting<Boolean> considerPotionEffects = new Setting<>(true);
/**
* Sprint and jump a block early on ascends wherever possible
*/
public final Setting<Boolean> sprintAscends = new Setting<>(true);
/**
* How many ticks between right clicks are allowed. Default in game is 4
*/
public final Setting<Integer> rightClickSpeed = new Setting<>(4);
/** /**
* This is the big A* setting. * This is the big A* setting.
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path. * As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
@@ -277,7 +288,7 @@ public final class Settings {
/** /**
* Start planning the next path once the remaining movements tick estimates sum up to less than this value * Start planning the next path once the remaining movements tick estimates sum up to less than this value
*/ */
public final Setting<Integer> planningTickLookAhead = new Setting<>(150); public final Setting<Integer> planningTickLookahead = new Setting<>(150);
/** /**
* Default size of the Long2ObjectOpenHashMap used in pathing * Default size of the Long2ObjectOpenHashMap used in pathing
@@ -308,6 +319,8 @@ public final class Settings {
* Is it okay to sprint through a descend followed by a diagonal? * Is it okay to sprint through a descend followed by a diagonal?
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't * The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy. * lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
* <p>
* Note: this is *not* related to the allowDiagonalDescend setting, that is a completely different thing.
*/ */
public final Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true); public final Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
@@ -378,10 +391,17 @@ public final class Settings {
*/ */
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false); public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
/**
* Remember the contents of containers (chests, echests, furnaces)
* <p>
* Really buggy since the packet stuff is multithreaded badly thanks to brady
*/
public final Setting<Boolean> containerMemory = new Setting<>(false);
/** /**
* Print all the debug messages to chat * Print all the debug messages to chat
*/ */
public final Setting<Boolean> chatDebug = new Setting<>(true); public final Setting<Boolean> chatDebug = new Setting<>(false);
/** /**
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in * Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
@@ -459,10 +479,40 @@ public final class Settings {
*/ */
public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false); public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
/**
* Continue sprinting while in water
*/
public final Setting<Boolean> sprintInWater = new Setting<>(true);
/**
* When GetToBlockProcess fails to calculate a path, instead of just giving up, mark the closest instances
* of that block as "unreachable" and go towards the next closest
*/
public final Setting<Boolean> blacklistOnGetToBlockFailure = new Setting<>(true);
/**
* 😎 Render cached chunks as semitransparent. Doesn't work with OptiFine 😭 Rarely randomly crashes, see <a href="https://github.com/cabaletta/baritone/issues/327">this issue</a>.
* <p>
* Can be very useful on servers with low render distance. After enabling, you may need to reload the world in order for it to have an effect
* (e.g. disconnect and reconnect, enter then exit the nether, die and respawn, etc). This may literally kill your FPS and CPU because
* every chunk gets recompiled twice as much as normal, since the cached version comes into range, then the normal one comes from the server for real.
* <p>
* Note that flowing water is cached as AVOID, which is rendered as lava. As you get closer, you may therefore see lava falls being replaced with water falls.
* <p>
* SOLID is rendered as stone in the overworld, netherrack in the nether, and end stone in the end
*/
public final Setting<Boolean> renderCachedChunks = new Setting<>(false);
/**
* 0.0f = not visible, fully transparent
* 1.0f = fully opaque
*/
public final Setting<Float> cachedChunksOpacity = new Setting<>(0.5f);
/** /**
* Whether or not to use the "#" command prefix * Whether or not to use the "#" command prefix
*/ */
public final Setting<Boolean> prefix = new Setting<>(false); public final Setting<Boolean> prefixControl = new Setting<>(true);
/** /**
* Don't stop walking forward when you need to break blocks in your way * Don't stop walking forward when you need to break blocks in your way
@@ -485,6 +535,11 @@ public final class Settings {
*/ */
public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5); public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
/**
* When GetToBlock doesn't know any locations for the desired block, explore randomly instead of giving up.
*/
public final Setting<Boolean> exploreForBlocks = new Setting<>(true);
/** /**
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)? * While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
*/ */
@@ -522,6 +577,19 @@ public final class Settings {
*/ */
public final Setting<Integer> legitMineYLevel = new Setting<>(11); public final Setting<Integer> legitMineYLevel = new Setting<>(11);
/**
* Magically see ores that are separated diagonally from existing ores. Basically like mining around the ores that it finds
* in case there's one there touching it diagonally, except it checks it un-legit-ly without having the mine blocks to see it.
* You can decide whether this looks plausible or not.
* <p>
* This is disabled because it results in some weird behavior. For example, it can """see""" the top block of a vein of iron_ore
* through a lava lake. This isn't an issue normally since it won't consider anything touching lava, so it just ignores it.
* However, this setting expands that and allows it to see the entire vein so it'll mine under the lava lake to get the iron that
* it can reach without mining blocks adjacent to lava. This really defeats the purpose of legitMine since a player could never
* do that lol, so thats one reason why its disabled
*/
public final Setting<Boolean> legitMineIncludeDiagonals = new Setting<>(false);
/** /**
* When mining block of a certain type, try to mine two at once instead of one. * When mining block of a certain type, try to mine two at once instead of one.
* If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks * If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks
@@ -632,13 +700,7 @@ public final class Settings {
*/ */
public final List<Setting<?>> allSettings; public final List<Setting<?>> allSettings;
public void reset() { public final class Setting<T> {
for (Setting setting : allSettings) {
setting.value = setting.defaultValue;
}
}
public class Setting<T> {
public T value; public T value;
public final T defaultValue; public final T defaultValue;
private String name; private String name;
@@ -667,8 +729,13 @@ public final class Settings {
return klass; return klass;
} }
@Override
public String toString() { public String toString() {
return name + ": " + value; return SettingsUtil.settingToString(this);
}
public void reset() {
value = defaultValue;
} }
} }
@@ -18,8 +18,13 @@
package baritone.api.behavior; package baritone.api.behavior;
import baritone.api.event.listener.AbstractGameEventListener; import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.event.listener.IGameEventListener;
/** /**
* A behavior is simply a type that is able to listen to events.
*
* @see IGameEventListener
*
* @author Brady * @author Brady
* @since 9/23/2018 * @since 9/23/2018
*/ */
@@ -38,11 +38,24 @@ public interface IPathingBehavior extends IBehavior {
* @return The estimated remaining ticks in the current segment. * @return The estimated remaining ticks in the current segment.
*/ */
default Optional<Double> ticksRemainingInSegment() { default Optional<Double> ticksRemainingInSegment() {
return ticksRemainingInSegment(true);
}
/**
* Returns the estimated remaining ticks in the current pathing
* segment. Given that the return type is an optional, {@link Optional#empty()}
* will be returned in the case that there is no current segment being pathed.
*
* @param includeCurrentMovement whether or not to include the entirety of the cost of the currently executing movement in the total
* @return The estimated remaining ticks in the current segment.
*/
default Optional<Double> ticksRemainingInSegment(boolean includeCurrentMovement) {
IPathExecutor current = getCurrent(); IPathExecutor current = getCurrent();
if (current == null) { if (current == null) {
return Optional.empty(); return Optional.empty();
} }
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition())); int start = includeCurrentMovement ? current.getPosition() : current.getPosition() + 1;
return Optional.of(current.getPath().ticksRemainingFrom(start));
} }
/** /**
@@ -19,7 +19,6 @@ package baritone.api.utils;
import baritone.api.behavior.IBehavior; import baritone.api.behavior.IBehavior;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import net.minecraft.client.settings.KeyBinding;
/** /**
* @author Brady * @author Brady
@@ -27,8 +26,6 @@ import net.minecraft.client.settings.KeyBinding;
*/ */
public interface IInputOverrideHandler extends IBehavior { public interface IInputOverrideHandler extends IBehavior {
Boolean isInputForcedDown(KeyBinding key);
boolean isInputForcedDown(Input input); boolean isInputForcedDown(Input input);
void setInputForceState(Input input, boolean forced); void setInputForceState(Input input, boolean forced);
@@ -17,12 +17,17 @@
package baritone.api.utils; package baritone.api.utils;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType; import net.minecraft.world.GameType;
import net.minecraft.world.World;
/** /**
* @author Brady * @author Brady
@@ -43,4 +48,6 @@ public interface IPlayerController {
default double getBlockReachDistance() { default double getBlockReachDistance() {
return this.getGameType().isCreative() ? 5.0F : 4.5F; return this.getGameType().isCreative() ? 5.0F : 4.5F;
} }
EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand);
} }
+11 -2
View File
@@ -117,8 +117,12 @@ public class Rotation {
* @return are they really close * @return are they really close
*/ */
public boolean isReallyCloseTo(Rotation other) { public boolean isReallyCloseTo(Rotation other) {
float yawDiff = Math.abs(this.yaw - other.yaw); // you cant fool me return yawIsReallyClose(other) && Math.abs(this.pitch - other.pitch) < 0.01;
return (yawDiff < 0.01 || yawDiff > 359.9) && Math.abs(this.pitch - other.pitch) < 0.01; }
public boolean yawIsReallyClose(Rotation other) {
float yawDiff = Math.abs(normalizeYaw(yaw) - normalizeYaw(other.yaw)); // you cant fool me
return (yawDiff < 0.01 || yawDiff > 359.99);
} }
/** /**
@@ -147,4 +151,9 @@ public class Rotation {
} }
return newYaw; return newYaw;
} }
@Override
public String toString() {
return "Yaw: " + yaw + ", Pitch: " + pitch;
}
} }
@@ -78,6 +78,9 @@ public final class RotationUtils {
* @return The wrapped angles * @return The wrapped angles
*/ */
public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) { public static Rotation wrapAnglesToRelative(Rotation current, Rotation target) {
if (current.yawIsReallyClose(target)) {
return new Rotation(current.getYaw(), target.getPitch());
}
return target.subtract(current).normalize().add(current); return target.subtract(current).normalize().add(current);
} }
@@ -102,7 +105,7 @@ public final class RotationUtils {
* @param dest The destination position * @param dest The destination position
* @return The rotation from the origin to the destination * @return The rotation from the origin to the destination
*/ */
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) { private static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z}; double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
double yaw = MathHelper.atan2(delta[0], -delta[2]); double yaw = MathHelper.atan2(delta[0], -delta[2]);
double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]); double dist = Math.sqrt(delta[0] * delta[0] + delta[2] * delta[2]);
@@ -196,7 +199,7 @@ public final class RotationUtils {
* @return The optional rotation * @return The optional rotation
*/ */
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) { public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) {
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos); Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance); RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance);
//System.out.println(result); //System.out.println(result);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) { if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
@@ -27,10 +27,8 @@ import java.io.BufferedWriter;
import java.io.IOException; import java.io.IOException;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.ArrayList; import java.util.*;
import java.util.Collections; import java.util.List;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer; import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher; import java.util.regex.Matcher;
@@ -89,22 +87,8 @@ public class SettingsUtil {
public static synchronized void save(Settings settings) { public static synchronized void save(Settings settings) {
try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) { try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) {
for (Settings.Setting setting : settings.allSettings) { for (Settings.Setting setting : modifiedSettings(settings)) {
if (setting.get() == null) { out.write(settingToString(setting) + "\n");
System.out.println("NULL SETTING?" + setting.getName());
continue;
}
if (setting.getName().equals("logger")) {
continue; // NO
}
if (setting.value == setting.defaultValue) {
continue;
}
SettingsIO io = map.get(setting.getValueClass());
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting + " " + setting.getName());
}
out.write(setting.getName() + " " + io.toString.apply(setting.get()) + "\n");
} }
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Exception thrown while saving Baritone settings!"); System.out.println("Exception thrown while saving Baritone settings!");
@@ -112,7 +96,36 @@ public class SettingsUtil {
} }
} }
private static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException { public static List<Settings.Setting> modifiedSettings(Settings settings) {
List<Settings.Setting> modified = new ArrayList<>();
for (Settings.Setting setting : settings.allSettings) {
if (setting.get() == null) {
System.out.println("NULL SETTING?" + setting.getName());
continue;
}
if (setting.getName().equals("logger")) {
continue; // NO
}
if (setting.value == setting.defaultValue) {
continue;
}
modified.add(setting);
}
return modified;
}
public static String settingToString(Settings.Setting setting) throws IllegalStateException {
if (setting.getName().equals("logger")) {
return "logger";
}
SettingsIO io = map.get(setting.getValueClass());
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
}
return setting.getName() + " " + io.toString.apply(setting.get());
}
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
Settings.Setting setting = settings.byLowerName.get(settingName); Settings.Setting setting = settings.byLowerName.get(settingName);
if (setting == null) { if (setting == null) {
throw new IllegalStateException("No setting by that name"); throw new IllegalStateException("No setting by that name");
@@ -0,0 +1,52 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.ChunkRenderContainer;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import org.lwjgl.opengl.GL14;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(ChunkRenderContainer.class)
public class MixinChunkRenderContainer {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "preRenderChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/RenderChunk.getPosition()Lnet/minecraft/util/math/BlockPos;"
)
)
private BlockPos getPosition(RenderChunk renderChunkIn) {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
GlStateManager.enableAlpha();
GlStateManager.enableBlend();
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.get());
GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
}
return renderChunkIn.getPosition();
}
}
@@ -0,0 +1,57 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.ChunkRenderWorker;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(ChunkRenderWorker.class)
public abstract class MixinChunkRenderWorker {
@Shadow
protected abstract boolean isChunkExisting(BlockPos pos, World worldIn);
@Redirect(
method = "processTask",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/chunk/ChunkRenderWorker.isChunkExisting(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/world/World;)Z"
)
)
private boolean isChunkExisting(ChunkRenderWorker worker, BlockPos pos, World world) {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.isLoaded(pos.getX(), pos.getZ()) || this.isChunkExisting(pos, world);
}
}
return this.isChunkExisting(pos, world);
}
}
@@ -1,74 +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.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.RotationMoveEvent;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
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.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import static org.spongepowered.asm.lib.Opcodes.GETFIELD;
/**
* @author Brady
* @since 8/21/2018
*/
@Mixin(Entity.class)
public class MixinEntity {
@Shadow
public float rotationYaw;
/**
* Event called to override the movement direction when walking
*/
private RotationMoveEvent motionUpdateRotationEvent;
@Inject(
method = "moveRelative",
at = @At("HEAD")
)
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
// noinspection ConstantConditions
if (EntityPlayerSP.class.isInstance(this)) {
this.motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.motionUpdateRotationEvent);
}
}
@Redirect(
method = "moveRelative",
at = @At(
value = "FIELD",
opcode = GETFIELD,
target = "net/minecraft/entity/Entity.rotationYaw:F"
)
)
private float overrideYaw(Entity self) {
if (self instanceof EntityPlayerSP) {
return this.motionUpdateRotationEvent.getYaw();
}
return self.rotationYaw;
}
}
@@ -18,6 +18,7 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.RotationMoveEvent; import baritone.api.event.events.RotationMoveEvent;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
@@ -55,8 +56,11 @@ public abstract class MixinEntityLivingBase extends Entity {
private void preMoveRelative(CallbackInfo ci) { private void preMoveRelative(CallbackInfo ci) {
// noinspection ConstantConditions // noinspection ConstantConditions
if (EntityPlayerSP.class.isInstance(this)) { if (EntityPlayerSP.class.isInstance(this)) {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent); if (baritone != null) {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
}
} }
} }
@@ -69,9 +73,30 @@ public abstract class MixinEntityLivingBase extends Entity {
) )
) )
private float overrideYaw(EntityLivingBase self) { private float overrideYaw(EntityLivingBase self) {
if (self instanceof EntityPlayerSP) { if (self instanceof EntityPlayerSP && BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) != null) {
return this.jumpRotationEvent.getYaw(); return this.jumpRotationEvent.getYaw();
} }
return self.rotationYaw; return self.rotationYaw;
} }
@Redirect(
method = "travel",
at = @At(
value = "INVOKE",
target = "net/minecraft/entity/EntityLivingBase.moveRelative(FFFF)V"
)
)
private void travel(EntityLivingBase self, float strafe, float up, float forward, float friction) {
// noinspection ConstantConditions
if (!EntityPlayerSP.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this) == null) {
moveRelative(strafe, up, forward, friction);
return;
}
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
float originalYaw = this.rotationYaw;
this.rotationYaw = motionUpdateRotationEvent.getYaw();
this.moveRelative(strafe, up, forward, friction);
this.rotationYaw = originalYaw;
}
} }
@@ -18,7 +18,7 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.behavior.IPathingBehavior; import baritone.api.IBaritone;
import baritone.api.event.events.ChatEvent; import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.SprintStateEvent; import baritone.api.event.events.SprintStateEvent;
@@ -47,7 +47,11 @@ public class MixinEntityPlayerSP {
) )
private void sendChatMessage(String msg, CallbackInfo ci) { private void sendChatMessage(String msg, CallbackInfo ci) {
ChatEvent event = new ChatEvent(msg); ChatEvent event = new ChatEvent(msg);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onSendChatMessage(event); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone == null) {
return;
}
baritone.getGameEventHandler().onSendChatMessage(event);
if (event.isCancelled()) { if (event.isCancelled()) {
ci.cancel(); ci.cancel();
} }
@@ -63,7 +67,10 @@ public class MixinEntityPlayerSP {
) )
) )
private void onPreUpdate(CallbackInfo ci) { private void onPreUpdate(CallbackInfo ci) {
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE)); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
}
} }
@Inject( @Inject(
@@ -76,7 +83,10 @@ public class MixinEntityPlayerSP {
) )
) )
private void onPostUpdate(CallbackInfo ci) { private void onPostUpdate(CallbackInfo ci) {
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST)); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
}
} }
@Redirect( @Redirect(
@@ -87,8 +97,11 @@ public class MixinEntityPlayerSP {
) )
) )
private boolean isAllowFlying(PlayerCapabilities capabilities) { private boolean isAllowFlying(PlayerCapabilities capabilities) {
IPathingBehavior pathingBehavior = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getPathingBehavior(); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
return !pathingBehavior.isPathing() && capabilities.allowFlying; if (baritone == null) {
return capabilities.allowFlying;
}
return !baritone.getPathingBehavior().isPathing() && capabilities.allowFlying;
} }
@Redirect( @Redirect(
@@ -99,9 +112,20 @@ public class MixinEntityPlayerSP {
) )
) )
private boolean isKeyDown(KeyBinding keyBinding) { private boolean isKeyDown(KeyBinding keyBinding) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone == null) {
return keyBinding.isKeyDown();
}
SprintStateEvent event = new SprintStateEvent(); SprintStateEvent event = new SprintStateEvent();
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event); baritone.getGameEventHandler().onPlayerSprintState(event);
return event.getState() == null ? keyBinding.isKeyDown() : event.getState(); if (event.getState() != null) {
return event.getState();
}
if (baritone != BaritoneAPI.getProvider().getPrimaryBaritone()) {
// hitting control shouldn't make all bots sprint
return false;
}
return keyBinding.isKeyDown();
} }
@Inject( @Inject(
@@ -111,6 +135,9 @@ public class MixinEntityPlayerSP {
) )
) )
private void updateRidden(CallbackInfo cb) { private void updateRidden(CallbackInfo cb) {
((LookBehavior) BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getLookBehavior()).pig(); IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this);
if (baritone != null) {
((LookBehavior) baritone.getLookBehavior()).pig();
}
} }
} }
@@ -1,68 +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.mixins;
import baritone.api.BaritoneAPI;
import baritone.utils.Helper;
import net.minecraft.client.settings.KeyBinding;
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.CallbackInfoReturnable;
/**
* @author Brady
* @since 7/31/2018
*/
@Mixin(KeyBinding.class)
public class MixinKeyBinding {
@Shadow
private int pressTime;
@Inject(
method = "isKeyDown",
at = @At("HEAD"),
cancellable = true
)
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null) {
cir.setReturnValue(force); // :sunglasses:
}
}
@Inject(
method = "isPressed",
at = @At("HEAD"),
cancellable = true
)
private void isPressed(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null && !force) { // <-- cursed
if (pressTime > 0) {
Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you");
pressTime--;
}
cir.setReturnValue(force); // :sunglasses:
}
}
}
@@ -0,0 +1,89 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.ChunkCache;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 1/29/2019
*/
@Mixin(RenderChunk.class)
public class MixinRenderChunk {
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.isEmpty()Z"
)
)
private boolean isEmpty(ChunkCache chunkCache) {
if (!chunkCache.isEmpty()) {
return false;
}
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
BlockPos position = ((RenderChunk) (Object) this).getPosition();
// RenderChunk extends from -1,-1,-1 to +16,+16,+16
// then the constructor of ChunkCache extends it one more (presumably to get things like the connected status of fences? idk)
// so if ANY of the adjacent chunks are loaded, we are unempty
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
if (baritone.bsi.isLoaded(16 * dx + position.getX(), 16 * dz + position.getZ())) {
return false;
}
}
}
}
}
return true;
}
@Redirect(
method = "rebuildChunk",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/ChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
)
)
private IBlockState getBlockState(ChunkCache chunkCache, BlockPos pos) {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null) {
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
IPlayerContext ctx = baritone.getPlayerContext();
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
return baritone.bsi.get0(pos);
}
}
return chunkCache.getBlockState(pos);
}
}
@@ -0,0 +1,47 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.RenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(RenderList.class)
public class MixinRenderList {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void popMatrix() {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
GlStateManager.popMatrix();
}
}
@@ -0,0 +1,47 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.client.renderer.VboRenderList;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
import static org.lwjgl.opengl.GL11.*;
@Mixin(VboRenderList.class)
public class MixinVboRenderList {
@Redirect( // avoid creating CallbackInfo at all costs; this is called 40k times per second
method = "renderChunkLayer",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/renderer/GlStateManager.popMatrix()V"
)
)
private void popMatrix() {
if (Baritone.settings().renderCachedChunks.get() && Minecraft.getMinecraft().getIntegratedServer() == null) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
GlStateManager.popMatrix();
}
}
+5 -2
View File
@@ -12,14 +12,17 @@
"MixinBlockPos", "MixinBlockPos",
"MixinChunkProviderClient", "MixinChunkProviderClient",
"MixinChunkProviderServer", "MixinChunkProviderServer",
"MixinEntity", "MixinChunkRenderContainer",
"MixinChunkRenderWorker",
"MixinEntityLivingBase", "MixinEntityLivingBase",
"MixinEntityPlayerSP", "MixinEntityPlayerSP",
"MixinEntityRenderer", "MixinEntityRenderer",
"MixinKeyBinding",
"MixinMinecraft", "MixinMinecraft",
"MixinNetHandlerPlayClient", "MixinNetHandlerPlayClient",
"MixinNetworkManager", "MixinNetworkManager",
"MixinRenderChunk",
"MixinRenderList",
"MixinVboRenderList",
"MixinWorldClient" "MixinWorldClient"
] ]
} }
+4 -4
View File
@@ -29,10 +29,7 @@ import baritone.process.CustomGoalProcess;
import baritone.process.FollowProcess; import baritone.process.FollowProcess;
import baritone.process.GetToBlockProcess; import baritone.process.GetToBlockProcess;
import baritone.process.MineProcess; import baritone.process.MineProcess;
import baritone.utils.BaritoneAutoTest; import baritone.utils.*;
import baritone.utils.ExampleBaritoneControl;
import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
import baritone.utils.player.PrimaryPlayerContext; import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
@@ -89,10 +86,13 @@ public class Baritone implements IBaritone {
private IPlayerContext playerContext; private IPlayerContext playerContext;
private WorldProvider worldProvider; private WorldProvider worldProvider;
public BlockStateInterface bsi;
Baritone() { Baritone() {
this.gameEventHandler = new GameEventHandler(this); this.gameEventHandler = new GameEventHandler(this);
} }
@Override
public synchronized void init() { public synchronized void init() {
if (initialized) { if (initialized) {
return; return;
@@ -103,13 +103,13 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
@Override @Override
public void onPlayerRotationMove(RotationMoveEvent event) { public void onPlayerRotationMove(RotationMoveEvent event) {
if (this.target != null && !this.force) { if (this.target != null) {
event.setYaw(this.target.getYaw()); event.setYaw(this.target.getYaw());
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate() // If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
// Also the type has to be MOTION_UPDATE because that is called after JUMP // Also the type has to be MOTION_UPDATE because that is called after JUMP
if (!Baritone.settings().antiCheatCompatibility.get() && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE) { if (!Baritone.settings().antiCheatCompatibility.get() && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE && !this.force) {
this.target = null; this.target = null;
} }
} }
@@ -65,6 +65,9 @@ public final class MemoryBehavior extends Behavior {
@Override @Override
public synchronized void onTick(TickEvent event) { public synchronized void onTick(TickEvent event) {
if (!Baritone.settings().containerMemory.get()) {
return;
}
if (event.getType() == TickEvent.Type.OUT) { if (event.getType() == TickEvent.Type.OUT) {
enderChestWindowId = null; enderChestWindowId = null;
futureInventories.clear(); futureInventories.clear();
@@ -80,6 +83,9 @@ public final class MemoryBehavior extends Behavior {
@Override @Override
public synchronized void onSendPacket(PacketEvent event) { public synchronized void onSendPacket(PacketEvent event) {
if (!Baritone.settings().containerMemory.get()) {
return;
}
Packet p = event.getPacket(); Packet p = event.getPacket();
if (event.getState() == EventState.PRE) { if (event.getState() == EventState.PRE) {
@@ -116,6 +122,9 @@ public final class MemoryBehavior extends Behavior {
@Override @Override
public synchronized void onReceivePacket(PacketEvent event) { public synchronized void onReceivePacket(PacketEvent event) {
if (!Baritone.settings().containerMemory.get()) {
return;
}
Packet p = event.getPacket(); Packet p = event.getPacket();
if (event.getState() == EventState.PRE) { if (event.getState() == EventState.PRE) {
@@ -162,6 +171,9 @@ public final class MemoryBehavior extends Behavior {
private void updateInventory() { private void updateInventory() {
if (!Baritone.settings().containerMemory.get()) {
return;
}
int windowId = ctx.player().openContainer.windowId; int windowId = ctx.player().openContainer.windowId;
if (enderChestWindowId != null) { if (enderChestWindowId != null) {
if (windowId == enderChestWindowId) { if (windowId == enderChestWindowId) {
@@ -61,6 +61,8 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
private boolean lastAutoJump; private boolean lastAutoJump;
private BlockPos expectedSegmentStart;
private final LinkedBlockingQueue<PathEvent> toDispatch = new LinkedBlockingQueue<>(); private final LinkedBlockingQueue<PathEvent> toDispatch = new LinkedBlockingQueue<>();
public PathingBehavior(Baritone baritone) { public PathingBehavior(Baritone baritone) {
@@ -88,6 +90,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
baritone.getPathingControlManager().cancelEverything(); baritone.getPathingControlManager().cancelEverything();
return; return;
} }
expectedSegmentStart = pathStart();
baritone.getPathingControlManager().preTick(); baritone.getPathingControlManager().preTick();
tickPath(); tickPath();
dispatchEvents(); dispatchEvents();
@@ -111,11 +114,27 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
cancelRequested = false; cancelRequested = false;
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
} }
if (current == null) {
return;
}
safeToCancel = current.onTick();
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
synchronized (pathCalcLock) {
if (inProgress != null) {
// we are calculating
// are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
Optional<IPath> currentBest = inProgress.bestPathSoFar();
if ((current == null || !current.getPath().getDest().equals(calcFrom)) // if current ends in inProgress's start, then we're ok
&& !calcFrom.equals(ctx.playerFeet()) && !calcFrom.equals(expectedSegmentStart) // if current starts in our playerFeet or pathStart, then we're ok
&& (!currentBest.isPresent() || (!currentBest.get().positions().contains(ctx.playerFeet()) && !currentBest.get().positions().contains(expectedSegmentStart))) // if
) {
// when it was *just* started, currentBest will be empty so we need to also check calcFrom since that's always present
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
}
}
}
if (current == null) {
return;
}
safeToCancel = current.onTick();
if (current.failed() || current.finished()) { if (current.failed() || current.finished()) {
current = null; current = null;
if (goal == null || goal.isInGoal(ctx.playerFeet())) { if (goal == null || goal.isInGoal(ctx.playerFeet())) {
@@ -124,7 +143,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
next = null; next = null;
return; return;
} }
if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(pathStart())) { // can contain either one if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(expectedSegmentStart)) { // can contain either one
// if the current path failed, we may not actually be on the next one, so make sure // if the current path failed, we may not actually be on the next one, so make sure
logDebug("Discarding next path as it does not contain current position"); logDebug("Discarding next path as it does not contain current position");
// for example if we had a nicely planned ahead path that starts where current ends // for example if we had a nicely planned ahead path that starts where current ends
@@ -146,23 +165,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// at this point, current just ended, but we aren't in the goal and have no plan for the future // at this point, current just ended, but we aren't in the goal and have no plan for the future
synchronized (pathCalcLock) { synchronized (pathCalcLock) {
if (inProgress != null) { if (inProgress != null) {
// we are calculating queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
// are we calculating the right thing though? 🤔 return;
BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing
if (calcFrom.equals(ctx.playerFeet()) || calcFrom.equals(pathStart())) {
// cool and good
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
return;
}
// oh noes
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
} }
// we aren't calculating // we aren't calculating
queuePathEvent(PathEvent.CALC_STARTED); queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true); findPathInNewThread(expectedSegmentStart, true);
} }
return; return;
} }
@@ -193,8 +201,10 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// and this path doesn't get us all the way there // and this path doesn't get us all the way there
return; return;
} }
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) { if (ticksRemainingInSegment(false).get() < Baritone.settings().planningTickLookahead.get()) {
// and this path has 7.5 seconds or less left // and this path has 7.5 seconds or less left
// don't include the current movement so a very long last movement (e.g. descend) doesn't trip it up
// if we actually included current, it wouldn't start planning ahead until the last movement was done, if the last movement took more than 7.5 seconds on its own
logDebug("Path almost over. Planning ahead..."); logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false); findPathInNewThread(current.getPath().getDest(), false);
@@ -296,12 +306,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public void secretInternalSegmentCancel() { public void secretInternalSegmentCancel() {
queuePathEvent(PathEvent.CANCELED); queuePathEvent(PathEvent.CANCELED);
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
current = null; if (current != null) {
next = null; current = null;
next = null;
baritone.getInputOverrideHandler().clearAllKeys();
getInProgress().ifPresent(AbstractNodeCostSearch::cancel);
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock();
}
} }
baritone.getInputOverrideHandler().clearAllKeys();
getInProgress().ifPresent(AbstractNodeCostSearch::cancel);
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock();
} }
public void forceCancel() { // NOT exposed on public api public void forceCancel() { // NOT exposed on public api
@@ -333,7 +345,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return false; return false;
} }
queuePathEvent(PathEvent.CALC_STARTED); queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true); findPathInNewThread(expectedSegmentStart, true);
return true; return true;
} }
} }
@@ -373,7 +385,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} }
if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport) && MovementHelper.canWalkThrough(ctx, possibleSupport.up())) { if (MovementHelper.canWalkOn(ctx, possibleSupport.down()) && MovementHelper.canWalkThrough(ctx, possibleSupport) && MovementHelper.canWalkThrough(ctx, possibleSupport.up())) {
// this is plausible // this is plausible
logDebug("Faking path start assuming player is standing off the edge of a block"); //logDebug("Faking path start assuming player is standing off the edge of a block");
return possibleSupport; return possibleSupport;
} }
} }
@@ -382,7 +394,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// !onGround // !onGround
// we're in the middle of a jump // we're in the middle of a jump
if (MovementHelper.canWalkOn(ctx, feet.down().down())) { if (MovementHelper.canWalkOn(ctx, feet.down().down())) {
logDebug("Faking path start assuming player is midair and falling"); //logDebug("Faking path start assuming player is midair and falling");
return feet.down(); return feet.down();
} }
} }
@@ -436,8 +448,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p)); Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p));
if (current == null) { if (current == null) {
if (executor.isPresent()) { if (executor.isPresent()) {
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING); if (executor.get().getPath().positions().contains(expectedSegmentStart)) {
current = executor.get(); queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
current = executor.get();
} else {
logDebug("Warning: discarding orphan path segment with incorrect start");
}
} else { } else {
if (calcResult.getType() != PathCalculationResult.Type.CANCELLATION && calcResult.getType() != PathCalculationResult.Type.EXCEPTION) { if (calcResult.getType() != PathCalculationResult.Type.CANCELLATION && calcResult.getType() != PathCalculationResult.Type.EXCEPTION) {
// don't dispatch CALC_FAILED on cancellation // don't dispatch CALC_FAILED on cancellation
@@ -447,8 +463,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} else { } else {
if (next == null) { if (next == null) {
if (executor.isPresent()) { if (executor.isPresent()) {
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED); if (executor.get().getPath().getSrc().equals(current.getPath().getDest())) {
next = executor.get(); queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
next = executor.get();
} else {
logDebug("Warning: discarding orphan next segment with incorrect start");
}
} else { } else {
queuePathEvent(PathEvent.NEXT_CALC_FAILED); queuePathEvent(PathEvent.NEXT_CALC_FAILED);
} }
+1
View File
@@ -85,6 +85,7 @@ public final class CachedChunk {
temp.add(Blocks.END_GATEWAY); temp.add(Blocks.END_GATEWAY);
temp.add(Blocks.WEB); temp.add(Blocks.WEB);
temp.add(Blocks.NETHER_WART); temp.add(Blocks.NETHER_WART);
temp.add(Blocks.LADDER);
BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp); BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp);
} }
+1 -1
View File
@@ -45,7 +45,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
/** /**
* The maximum number of regions in any direction from (0,0) * The maximum number of regions in any direction from (0,0)
*/ */
private static final int REGION_MAX = 58594; private static final int REGION_MAX = 30_000_000 / 512 + 1;
/** /**
* A map of all of the cached regions. * A map of all of the cached regions.
+12 -8
View File
@@ -19,10 +19,7 @@ package baritone.cache;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.utils.pathing.PathingBlockType; import baritone.utils.pathing.PathingBlockType;
import net.minecraft.block.Block; import net.minecraft.block.*;
import net.minecraft.block.BlockDoublePlant;
import net.minecraft.block.BlockFlower;
import net.minecraft.block.BlockTallGrass;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
@@ -73,7 +70,7 @@ public final class ChunkPacker {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
int index = CachedChunk.getPositionIndex(x, y, z); int index = CachedChunk.getPositionIndex(x, y, z);
IBlockState state = bsc.get(x, y1, z); IBlockState state = bsc.get(x, y1, z);
boolean[] bits = getPathingBlockType(state).getBits(); boolean[] bits = getPathingBlockType(state, chunk, x, y, z).getBits();
bitSet.set(index, bits[0]); bitSet.set(index, bits[0]);
bitSet.set(index + 1, bits[1]); bitSet.set(index + 1, bits[1]);
Block block = state.getBlock(); Block block = state.getBlock();
@@ -122,14 +119,21 @@ public final class ChunkPacker {
return resourceCache.computeIfAbsent(name, n -> Block.getBlockFromName(n.contains(":") ? n : "minecraft:" + n)); return resourceCache.computeIfAbsent(name, n -> Block.getBlockFromName(n.contains(":") ? n : "minecraft:" + n));
} }
private static PathingBlockType getPathingBlockType(IBlockState state) { private static PathingBlockType getPathingBlockType(IBlockState state, Chunk chunk, int x, int y, int z) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) { if (block == Blocks.WATER || block == Blocks.FLOWING_WATER) {
// only water source blocks are plausibly usable, flowing water should be avoid // only water source blocks are plausibly usable, flowing water should be avoid
// FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
if (!MovementHelper.possiblyFlowing(state)) {
return PathingBlockType.WATER;
}
if (BlockLiquid.getSlopeAngle(chunk.getWorld(), new BlockPos(x + chunk.x << 4, y, z + chunk.z << 4), state.getMaterial(), state) != -1000.0F) {
return PathingBlockType.AVOID;
}
return PathingBlockType.WATER; return PathingBlockType.WATER;
} }
if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) { if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
return PathingBlockType.AVOID; return PathingBlockType.AVOID;
} }
// We used to do an AABB check here // We used to do an AABB check here
+4
View File
@@ -17,6 +17,7 @@
package baritone.cache; package baritone.cache;
import baritone.Baritone;
import baritone.api.cache.IContainerMemory; import baritone.api.cache.IContainerMemory;
import baritone.api.cache.IRememberedInventory; import baritone.api.cache.IRememberedInventory;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
@@ -69,6 +70,9 @@ public class ContainerMemory implements IContainerMemory {
} }
public synchronized void save() throws IOException { public synchronized void save() throws IOException {
if (!Baritone.settings().containerMemory.get()) {
return;
}
ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE); ByteBuf buf = Unpooled.buffer(0, Integer.MAX_VALUE);
PacketBuffer out = new PacketBuffer(buf); PacketBuffer out = new PacketBuffer(buf);
out.writeInt(inventories.size()); out.writeInt(inventories.size());
@@ -23,6 +23,7 @@ import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.event.listener.IGameEventListener; import baritone.api.event.listener.IGameEventListener;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
@@ -46,6 +47,15 @@ public final class GameEventHandler implements IEventBus, Helper {
@Override @Override
public final void onTick(TickEvent event) { public final void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.IN) {
try {
baritone.bsi = new BlockStateInterface(baritone.getPlayerContext(), true);
} catch (Exception ex) {
baritone.bsi = null;
}
} else {
baritone.bsi = null;
}
listeners.forEach(l -> l.onTick(event)); listeners.forEach(l -> l.onTick(event));
} }
@@ -153,7 +153,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) { if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
bestHeuristicSoFar[i] = heuristic; bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor; bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) { if (failing && getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
failing = false; failing = false;
} }
} }
@@ -160,7 +160,7 @@ public abstract class Movement implements IMovement, MovementHelper {
//i dont care if theres snow in the way!!!!!!! //i dont care if theres snow in the way!!!!!!!
//you dont own me!!!! //you dont own me!!!!
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(blockPos)), true) VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true)
); );
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block // don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
state.setInput(Input.CLICK_LEFT, true); state.setInput(Input.CLICK_LEFT, true);
@@ -40,6 +40,8 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import java.util.Optional;
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP; import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP;
/** /**
@@ -74,7 +76,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.AIR) { // early return for most common case if (block == Blocks.AIR) { // early return for most common case
return true; return true;
} }
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA) { if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull) {
return false; return false;
} }
if (block instanceof BlockDoor || block instanceof BlockFenceGate) { if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
@@ -107,7 +109,7 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
throw new IllegalStateException(); throw new IllegalStateException();
} }
if (isFlowing(state)) { if (isFlowing(x, y, z, state, bsi)) {
return false; // Don't walk through flowing liquids return false; // Don't walk through flowing liquids
} }
if (block instanceof BlockLiquid) { if (block instanceof BlockLiquid) {
@@ -157,7 +159,8 @@ public interface MovementHelper extends ActionCosts, Helper {
|| block instanceof BlockSnow || block instanceof BlockSnow
|| block instanceof BlockLiquid || block instanceof BlockLiquid
|| block instanceof BlockTrapDoor || block instanceof BlockTrapDoor
|| block instanceof BlockEndPortal) { || block instanceof BlockEndPortal
|| block instanceof BlockSkull) {
return false; return false;
} }
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters // door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
@@ -285,10 +288,10 @@ public interface MovementHelper extends ActionCosts, Helper {
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()" // since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability // BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
Block up = bsi.get0(x, y + 1, z).getBlock(); Block up = bsi.get0(x, y + 1, z).getBlock();
if (up == Blocks.WATERLILY) { if (up == Blocks.WATERLILY || up == Blocks.CARPET) {
return true; return true;
} }
if (isFlowing(state) || block == Blocks.FLOWING_WATER) { if (isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) {
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off // the only scenario in which we can walk on flowing water is if it's under still water with jesus off
return isWater(up) && !Baritone.settings().assumeWalkOnWater.get(); return isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
} }
@@ -439,11 +442,10 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) { static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) {
EntityPlayerSP player = ctx.player();
state.setTarget(new MovementTarget( state.setTarget(new MovementTarget(
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F), new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(pos), VecUtils.getBlockPosCenter(pos),
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch), ctx.playerRotations()).getYaw(), ctx.player().rotationPitch),
false false
)).setInput(Input.MOVE_FORWARD, true); )).setInput(Input.MOVE_FORWARD, true);
} }
@@ -486,15 +488,34 @@ public interface MovementHelper extends ActionCosts, Helper {
return BlockStateInterface.getBlock(ctx, p) instanceof BlockLiquid; return BlockStateInterface.getBlock(ctx, p) instanceof BlockLiquid;
} }
static boolean isFlowing(IBlockState state) { static boolean possiblyFlowing(IBlockState state) {
// Will be IFluidState in 1.13 // Will be IFluidState in 1.13
return state.getBlock() instanceof BlockLiquid return state.getBlock() instanceof BlockLiquid
&& state.getValue(BlockLiquid.LEVEL) != 0; && state.getValue(BlockLiquid.LEVEL) != 0;
} }
static boolean isFlowing(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
if (!(state.getBlock() instanceof BlockLiquid)) {
return false;
}
if (state.getValue(BlockLiquid.LEVEL) != 0) {
return true;
}
return possiblyFlowing(bsi.get0(x + 1, y, z))
|| possiblyFlowing(bsi.get0(x - 1, y, z))
|| possiblyFlowing(bsi.get0(x, y, z + 1))
|| possiblyFlowing(bsi.get0(x, y, z - 1));
}
static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown) { static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown) {
IPlayerContext ctx = baritone.getPlayerContext(); IPlayerContext ctx = baritone.getPlayerContext();
Optional<Rotation> direct = RotationUtils.reachable(ctx, placeAt); // we assume that if there is a block there, it must be replacable
boolean found = false; boolean found = false;
if (direct.isPresent()) {
state.setTarget(new MovementState.MovementTarget(direct.get(), true));
found = true;
}
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
BlockPos against1 = placeAt.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]); BlockPos against1 = placeAt.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (MovementHelper.canPlaceAgainst(ctx, against1)) { if (MovementHelper.canPlaceAgainst(ctx, against1)) {
@@ -181,14 +181,21 @@ public class MovementAscend extends Movement {
return state; return state;
} }
if (headBonkClear()) {
return state.setInput(Input.JUMP, true);
}
int xAxis = Math.abs(src.getX() - dest.getX()); // either 0 or 1 int xAxis = Math.abs(src.getX() - dest.getX()); // either 0 or 1
int zAxis = Math.abs(src.getZ() - dest.getZ()); // either 0 or 1 int zAxis = Math.abs(src.getZ() - dest.getZ()); // either 0 or 1
double flatDistToNext = xAxis * Math.abs((dest.getX() + 0.5D) - ctx.player().posX) + zAxis * Math.abs((dest.getZ() + 0.5D) - ctx.player().posZ); double flatDistToNext = xAxis * Math.abs((dest.getX() + 0.5D) - ctx.player().posX) + zAxis * Math.abs((dest.getZ() + 0.5D) - ctx.player().posZ);
double sideDist = zAxis * Math.abs((dest.getX() + 0.5D) - ctx.player().posX) + xAxis * Math.abs((dest.getZ() + 0.5D) - ctx.player().posZ); double sideDist = zAxis * Math.abs((dest.getX() + 0.5D) - ctx.player().posX) + xAxis * Math.abs((dest.getZ() + 0.5D) - ctx.player().posZ);
double lateralMotion = xAxis * ctx.player().motionZ + zAxis * ctx.player().motionX;
if (Math.abs(lateralMotion) > 0.1) {
return state;
}
if (headBonkClear()) {
return state.setInput(Input.JUMP, true);
}
// System.out.println(flatDistToNext + " " + sideDist); // System.out.println(flatDistToNext + " " + sideDist);
if (flatDistToNext > 1.2 || sideDist > 0.2) { if (flatDistToNext > 1.2 || sideDist > 0.2) {
return state; return state;
@@ -200,7 +207,7 @@ public class MovementAscend extends Movement {
return state.setInput(Input.JUMP, true); return state.setInput(Input.JUMP, true);
} }
private boolean headBonkClear() { public boolean headBonkClear() {
BetterBlockPos startUp = src.up(2); BetterBlockPos startUp = src.up(2);
for (int i = 0; i < 4; i++) { for (int i = 0; i < 4; i++) {
BetterBlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i)); BetterBlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i));
@@ -143,7 +143,7 @@ public class MovementDescend extends Movement {
if (context.assumeWalkOnWater) { if (context.assumeWalkOnWater) {
return false; // TODO fix return false; // TODO fix
} }
if (MovementHelper.isFlowing(ontoBlock)) { if (MovementHelper.isFlowing(destX, newY, destZ, ontoBlock, context.bsi)) {
return false; // TODO flowing check required here? return false; // TODO flowing check required here?
} }
if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) { if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) {
@@ -210,8 +210,8 @@ public class MovementDescend extends Movement {
}*/ }*/
} }
if (safeMode()) { if (safeMode()) {
double destX = (src.getX() + 0.5) * 0.19 + (dest.getX() + 0.5) * 0.81; double destX = (src.getX() + 0.5) * 0.17 + (dest.getX() + 0.5) * 0.83;
double destZ = (src.getZ() + 0.5) * 0.19 + (dest.getZ() + 0.5) * 0.81; double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83;
EntityPlayerSP player = ctx.player(); EntityPlayerSP player = ctx.player();
state.setTarget(new MovementState.MovementTarget( state.setTarget(new MovementState.MovementTarget(
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F), new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F),
@@ -245,6 +245,10 @@ public class MovementDescend extends Movement {
// (dest - src) + dest is offset 1 more in the same direction // (dest - src) + dest is offset 1 more in the same direction
// so it's the block we'd need to worry about running into if we decide to sprint straight through this descend // so it's the block we'd need to worry about running into if we decide to sprint straight through this descend
BlockPos into = dest.subtract(src.down()).add(dest); BlockPos into = dest.subtract(src.down()).add(dest);
if (skipToAscend()) {
// if dest extends into can't walk through, but the two above are can walk through, then we can overshoot and glitch in that weird way
return true;
}
for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(ctx, into.up(y)))) { if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(ctx, into.up(y)))) {
return true; return true;
@@ -252,4 +256,9 @@ public class MovementDescend extends Movement {
} }
return false; return false;
} }
public boolean skipToAscend() {
BlockPos into = dest.subtract(src.down()).add(dest);
return !MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into)) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up()) && MovementHelper.canWalkThrough(ctx, new BetterBlockPos(into).up(2));
}
} }
@@ -17,6 +17,7 @@
package baritone.pathing.movement.movements; package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.pathing.movement.MovementStatus; import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
@@ -114,7 +115,7 @@ public class MovementDiagonal extends Movement {
return; return;
} }
IBlockState pb3 = context.get(destX, y + 1, z); IBlockState pb3 = context.get(destX, y + 1, z);
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) { if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3.getBlock()))) {
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction // at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
return; return;
} }
@@ -123,7 +124,7 @@ public class MovementDiagonal extends Movement {
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible // and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
return; return;
} }
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) { if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1.getBlock()))) {
// and now that option B is fully calculated, see if we can edge around that way // and now that option B is fully calculated, see if we can edge around that way
return; return;
} }
@@ -173,13 +174,25 @@ public class MovementDiagonal extends Movement {
state.setStatus(MovementStatus.SUCCESS); state.setStatus(MovementStatus.SUCCESS);
return state; return state;
} }
if (!MovementHelper.isLiquid(ctx, ctx.playerFeet())) { if (sprint()) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }
MovementHelper.moveTowards(ctx, state, dest); MovementHelper.moveTowards(ctx, state, dest);
return state; return state;
} }
public boolean sprint() {
if (MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !Baritone.settings().sprintInWater.get()) {
return false;
}
for (int i = 0; i < 4; i++) {
if (!MovementHelper.canWalkThrough(ctx, positionsToBreak[i])) {
return false;
}
}
return true;
}
@Override @Override
protected boolean prepared(MovementState state) { protected boolean prepared(MovementState state) {
return true; return true;
@@ -78,7 +78,7 @@ public class MovementFall extends Movement {
} }
BlockPos playerFeet = ctx.playerFeet(); BlockPos playerFeet = ctx.playerFeet();
Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)); Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations());
Rotation targetRotation = null; Rotation targetRotation = null;
Block destBlock = ctx.world().getBlockState(dest).getBlock(); Block destBlock = ctx.world().getBlockState(dest).getBlock();
boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER; boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER;
@@ -141,7 +141,7 @@ public class MovementFall extends Movement {
} }
if (targetRotation == null) { if (targetRotation == null) {
Vec3d destCenterOffset = new Vec3d(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ()); Vec3d destCenterOffset = new Vec3d(destCenter.x + 0.125 * avoid.getX(), destCenter.y, destCenter.z + 0.125 * avoid.getZ());
state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset), false)); state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), destCenterOffset, ctx.playerRotations()), false));
} }
return state; return state;
} }
@@ -28,6 +28,7 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.BlockStairs; import net.minecraft.block.BlockStairs;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
@@ -85,7 +86,7 @@ public class MovementParkour extends Movement {
return; return;
} }
IBlockState standingOn = context.get(x, y - 1, z); IBlockState standingOn = context.get(x, y - 1, z);
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn)) { if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn) || standingOn.getBlock() instanceof BlockLiquid) {
return; return;
} }
int maxJump; int maxJump;
@@ -187,6 +188,11 @@ public class MovementParkour extends Movement {
logDebug("Pausing parkour since hand is active"); logDebug("Pausing parkour since hand is active");
return state; return state;
} }
if (ctx.playerFeet().y < src.y) {
// we have fallen
logDebug("sorry");
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (dist >= 4) { if (dist >= 4) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }
@@ -151,7 +151,7 @@ public class MovementPillar extends Movement {
IBlockState fromDown = BlockStateInterface.get(ctx, src); IBlockState fromDown = BlockStateInterface.get(ctx, src);
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(ctx, dest)) { if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(ctx, dest)) {
// stay centered while swimming up a water column // stay centered while swimming up a water column
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest)), false)); state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()), false));
Vec3d destCenter = VecUtils.getBlockPosCenter(dest); Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
if (Math.abs(ctx.player().posX - destCenter.x) > 0.2 || Math.abs(ctx.player().posZ - destCenter.z) > 0.2) { if (Math.abs(ctx.player().posX - destCenter.x) > 0.2 || Math.abs(ctx.player().posZ - destCenter.z) > 0.2) {
state.setInput(Input.MOVE_FORWARD, true); state.setInput(Input.MOVE_FORWARD, true);
@@ -226,7 +226,7 @@ public class MovementPillar extends Movement {
if (!(fr instanceof BlockAir || fr.isReplaceable(ctx.world(), src))) { if (!(fr instanceof BlockAir || fr.isReplaceable(ctx.world(), src))) {
state.setInput(Input.CLICK_LEFT, true); state.setInput(Input.CLICK_LEFT, true);
blockIsThere = false; blockIsThere = false;
} else if (ctx.player().isSneaking() && (Objects.equals(src.down(), ctx.objectMouseOver().getBlockPos()) || Objects.equals(src, ctx.objectMouseOver().getBlockPos()))) { } else if (ctx.player().isSneaking() && (Objects.equals(src.down(), ctx.objectMouseOver().getBlockPos()) || Objects.equals(src, ctx.objectMouseOver().getBlockPos())) && ctx.player().posY > dest.getY() + 0.1) {
state.setInput(Input.CLICK_RIGHT, true); state.setInput(Input.CLICK_RIGHT, true);
} }
} }
@@ -174,11 +174,11 @@ public class MovementTraverse extends Movement {
// combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break // combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break
// it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw // it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw
float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest)).getYaw(); float yawToDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), dest), ctx.playerRotations()).getYaw();
float pitchToBreak = state.getTarget().getRotation().get().getPitch(); float pitchToBreak = state.getTarget().getRotation().get().getPitch();
state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true)); state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true));
return state.setInput(Input.MOVE_FORWARD, true); return state.setInput(Input.MOVE_FORWARD, true).setInput(Input.SPRINT, true);
} }
//sneak may have been set to true in the PREPPING state while mining an adjacent block //sneak may have been set to true in the PREPPING state while mining an adjacent block
@@ -198,7 +198,7 @@ public class MovementTraverse extends Movement {
isDoorActuallyBlockingUs = true; isDoorActuallyBlockingUs = true;
} }
if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) { if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0])), true)) return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true); .setInput(Input.CLICK_RIGHT, true);
} }
} }
@@ -212,7 +212,7 @@ public class MovementTraverse extends Movement {
} }
if (blocked != null) { if (blocked != null) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked)), true)) return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked), ctx.playerRotations()), true))
.setInput(Input.CLICK_RIGHT, true); .setInput(Input.CLICK_RIGHT, true);
} }
} }
@@ -234,7 +234,7 @@ public class MovementTraverse extends Movement {
BlockPos into = dest.subtract(src).add(dest); BlockPos into = dest.subtract(src).add(dest);
Block intoBelow = BlockStateInterface.get(ctx, into).getBlock(); Block intoBelow = BlockStateInterface.get(ctx, into).getBlock();
Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock(); Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock();
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !MovementHelper.avoidWalkingInto(intoBelow) && !MovementHelper.avoidWalkingInto(intoAbove)) { if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, ctx.playerFeet()) || Baritone.settings().sprintInWater.get()) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock(); Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();
@@ -281,6 +281,8 @@ public class MovementTraverse extends Movement {
} }
return state; return state;
} }
default:
break;
} }
if (whereAmI.equals(dest)) { if (whereAmI.equals(dest)) {
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of // If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
@@ -25,6 +25,7 @@ import baritone.api.pathing.movement.MovementStatus;
import baritone.api.pathing.path.IPathExecutor; import baritone.api.pathing.path.IPathExecutor;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.VecUtils; import baritone.api.utils.VecUtils;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.behavior.PathingBehavior; import baritone.behavior.PathingBehavior;
@@ -39,6 +40,8 @@ import net.minecraft.block.BlockLiquid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.Tuple; import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.Vec3i;
import java.util.*; import java.util.*;
@@ -103,39 +106,31 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
BetterBlockPos whereShouldIBe = path.positions().get(pathPosition); BetterBlockPos whereShouldIBe = path.positions().get(pathPosition);
BetterBlockPos whereAmI = ctx.playerFeet(); BetterBlockPos whereAmI = ctx.playerFeet();
if (!whereShouldIBe.equals(whereAmI)) { if (!whereShouldIBe.equals(whereAmI) && !Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
if (pathPosition == 0 && whereAmI.equals(whereShouldIBe.up()) && Math.abs(ctx.player().motionY) < 0.1 && !(path.movements().get(0) instanceof MovementAscend) && !(path.movements().get(0) instanceof MovementPillar)) { if (whereAmI.equals(path.positions().get(i))) {
// avoid the Wrong Y coordinate bug logDebug("Skipping back " + (pathPosition - i) + " steps, to " + i);
// TODO add a timer here int previousPos = pathPosition;
new MovementDownward(behavior.baritone, whereAmI, whereShouldIBe).update(); pathPosition = Math.max(i - 1, 0); // previous step might not actually be done
return false; for (int j = pathPosition; j <= previousPos; j++) {
} path.movements().get(j).reset();
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
if (whereAmI.equals(path.positions().get(i))) {
logDebug("Skipping back " + (pathPosition - i) + " steps, to " + i);
int previousPos = pathPosition;
pathPosition = Math.max(i - 1, 0); // previous step might not actually be done
for (int j = pathPosition; j <= previousPos; j++) {
path.movements().get(j).reset();
}
onChangeInPathPosition();
return false;
} }
onChangeInPathPosition();
onTick();
return false;
} }
for (int i = pathPosition + 3; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing) }
// also don't check pathPosition+2 because reasons for (int i = pathPosition + 3; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
if (whereAmI.equals(path.positions().get(i))) { // also don't check pathPosition+2 because reasons
if (i - pathPosition > 2) { if (whereAmI.equals(path.positions().get(i))) {
logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i); if (i - pathPosition > 2) {
} logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i);
//System.out.println("Double skip sundae");
pathPosition = i - 1;
onChangeInPathPosition();
return false;
} }
//System.out.println("Double skip sundae");
pathPosition = i - 1;
onChangeInPathPosition();
onTick();
return false;
} }
} }
} }
@@ -195,17 +190,17 @@ public class PathExecutor implements IPathExecutor, Helper {
continue; continue;
} }
Movement m = (Movement) path.movements().get(i); Movement m = (Movement) path.movements().get(i);
HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak(bsi)); List<BlockPos> prevBreak = m.toBreak(bsi);
HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace(bsi)); List<BlockPos> prevPlace = m.toPlace(bsi);
HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto(bsi)); List<BlockPos> prevWalkInto = m.toWalkInto(bsi);
m.resetBlockCache(); m.resetBlockCache();
if (!prevBreak.equals(new HashSet<>(m.toBreak(bsi)))) { if (!prevBreak.equals(m.toBreak(bsi))) {
recalcBP = true; recalcBP = true;
} }
if (!prevPlace.equals(new HashSet<>(m.toPlace(bsi)))) { if (!prevPlace.equals(m.toPlace(bsi))) {
recalcBP = true; recalcBP = true;
} }
if (!prevWalkInto.equals(new HashSet<>(m.toWalkInto(bsi)))) { if (!prevWalkInto.equals(m.toWalkInto(bsi))) {
recalcBP = true; recalcBP = true;
} }
} }
@@ -249,6 +244,8 @@ public class PathExecutor implements IPathExecutor, Helper {
return true; return true;
} }
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) { if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) {
// don't do this if the movement was calculated while loaded
// that means that this isn't a cache error, it's just part of the path interfering with a later part
logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling."); logDebug("Original cost " + currentMovementOriginalCostEstimate + " current cost " + currentCost + ". Cancelling.");
cancel(); cancel();
return true; return true;
@@ -377,26 +374,43 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
private boolean shouldSprintNextTick() { private boolean shouldSprintNextTick() {
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint boolean requested = behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT);
if (!new CalculationContext(behavior.baritone).canSprint) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return false;
}
// if the movement requested sprinting, then we're done
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return true;
}
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us // we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false); behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it // first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint) {
return false;
}
IMovement current = path.movements().get(pathPosition); IMovement current = path.movements().get(pathPosition);
// traverse requests sprinting, so we need to do this check first
if (current instanceof MovementTraverse && pathPosition < path.length() - 3) {
IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && sprintableAscend(ctx, (MovementTraverse) current, (MovementAscend) next, path.movements().get(pathPosition + 2))) {
if (skipNow(ctx, current)) {
logDebug("Skipping traverse to straight ascend");
pathPosition++;
onChangeInPathPosition();
onTick();
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, true);
return true;
} else {
logDebug("Too far to the side to safely sprint ascend");
}
}
}
// if the movement requested sprinting, then we're done
if (requested) {
return true;
}
// however, descend and ascend don't request sprinting, because they don't know the context of what movement comes after it
if (current instanceof MovementDescend) { if (current instanceof MovementDescend) {
if (((MovementDescend) current).safeMode()) { if (((MovementDescend) current).safeMode() && !((MovementDescend) current).skipToAscend()) {
logDebug("Sprinting would be unsafe"); logDebug("Sprinting would be unsafe");
return false; return false;
} }
@@ -406,11 +420,13 @@ public class PathExecutor implements IPathExecutor, Helper {
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) { if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction // a descend then an ascend in the same direction
pathPosition++; pathPosition++;
onChangeInPathPosition();
onTick();
// okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric // okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric
logDebug("Skipping descend to straight ascend"); logDebug("Skipping descend to straight ascend");
return true; return true;
} }
if (canSprintInto(ctx, current, next)) { if (canSprintFromDescendInto(ctx, current, next)) {
if (ctx.playerFeet().equals(current.getDest())) { if (ctx.playerFeet().equals(current.getDest())) {
pathPosition++; pathPosition++;
onChangeInPathPosition(); onChangeInPathPosition();
@@ -430,11 +446,123 @@ public class PathExecutor implements IPathExecutor, Helper {
return true; return true;
} }
} }
if (pathPosition < path.length() - 2 && prev instanceof MovementTraverse && sprintableAscend(ctx, (MovementTraverse) prev, (MovementAscend) current, path.movements().get(pathPosition + 1))) {
return true;
}
}
if (current instanceof MovementFall) {
Tuple<Vec3d, BlockPos> data = overrideFall((MovementFall) current);
if (data != null) {
BlockPos fallDest = data.getSecond();
if (!path.positions().contains(fallDest)) {
throw new IllegalStateException();
}
if (ctx.playerFeet().equals(fallDest)) {
pathPosition = path.positions().indexOf(fallDest);
onChangeInPathPosition();
onTick();
return true;
}
clearKeys();
behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getFirst(), ctx.playerRotations()), false);
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
return true;
}
} }
return false; return false;
} }
private static boolean canSprintInto(IPlayerContext ctx, IMovement current, IMovement next) { private Tuple<Vec3d, BlockPos> overrideFall(MovementFall movement) {
Vec3i dir = movement.getDirection();
if (dir.getY() < -3) {
return null;
}
if (!movement.toBreakCached.isEmpty()) {
return null; // it's breaking
}
Vec3i flatDir = new Vec3i(dir.getX(), 0, dir.getZ());
int i;
outer:
for (i = pathPosition + 1; i < path.length() - 1 && i < pathPosition + 3; i++) {
IMovement next = path.movements().get(i);
if (!(next instanceof MovementTraverse)) {
break;
}
if (!flatDir.equals(next.getDirection())) {
break;
}
for (int y = next.getDest().y; y <= movement.getSrc().y + 1; y++) {
BlockPos chk = new BlockPos(next.getDest().x, y, next.getDest().z);
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) {
break outer;
}
}
if (!MovementHelper.canWalkOn(ctx, next.getDest().down())) {
break;
}
}
i--;
if (i == pathPosition) {
return null; // no valid extension exists
}
double len = i - pathPosition - 0.4;
return new Tuple<>(
new Vec3d(flatDir.getX() * len + movement.getDest().x + 0.5, movement.getDest().y, flatDir.getZ() * len + movement.getDest().z + 0.5),
movement.getDest().add(flatDir.getX() * (i - pathPosition), 0, flatDir.getZ() * (i - pathPosition)));
}
private static boolean skipNow(IPlayerContext ctx, IMovement current) {
double offTarget = Math.abs(current.getDirection().getX() * (current.getSrc().z + 0.5D - ctx.player().posZ)) + Math.abs(current.getDirection().getZ() * (current.getSrc().x + 0.5D - ctx.player().posX));
if (offTarget > 0.1) {
return false;
}
// we are centered
BlockPos headBonk = current.getSrc().subtract(current.getDirection()).up(2);
if (MovementHelper.fullyPassable(ctx.world().getBlockState(headBonk))) {
return true;
}
// wait 0.3
double flatDist = Math.abs(current.getDirection().getX() * (headBonk.getX() + 0.5D - ctx.player().posX)) + Math.abs(current.getDirection().getZ() * (headBonk.getZ() + 0.5 - ctx.player().posZ));
return flatDist > 0.8;
}
private static boolean sprintableAscend(IPlayerContext ctx, MovementTraverse current, MovementAscend next, IMovement nextnext) {
if (!Baritone.settings().sprintAscends.get()) {
return false;
}
if (!current.getDirection().equals(next.getDirection().down())) {
return false;
}
if (nextnext.getDirection().getX() != next.getDirection().getX() || nextnext.getDirection().getZ() != next.getDirection().getZ()) {
return false;
}
if (!MovementHelper.canWalkOn(ctx, current.getDest().down())) {
return false;
}
if (!MovementHelper.canWalkOn(ctx, next.getDest().down())) {
return false;
}
if (!next.toBreakCached.isEmpty()) {
return false; // it's breaking
}
for (int x = 0; x < 2; x++) {
for (int y = 0; y < 3; y++) {
BlockPos chk = current.getSrc().up(y);
if (x == 1) {
chk = chk.add(current.getDirection());
}
if (!MovementHelper.fullyPassable(ctx.world().getBlockState(chk))) {
return false;
}
}
}
if (MovementHelper.avoidWalkingInto(ctx.world().getBlockState(current.getSrc().up(3)).getBlock())) {
return false;
}
return !MovementHelper.avoidWalkingInto(ctx.world().getBlockState(next.getDest().up(2)).getBlock()); // codacy smh my head
}
private static boolean canSprintFromDescendInto(IPlayerContext ctx, IMovement current, IMovement next) {
if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) { if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) {
return true; return true;
} }
@@ -55,6 +55,9 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG
if (this.state == State.NONE) { if (this.state == State.NONE) {
this.state = State.GOAL_SET; this.state = State.GOAL_SET;
} }
if (this.state == State.EXECUTING) {
this.state = State.PATH_REQUESTED;
}
} }
@Override @Override
@@ -81,7 +84,7 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG
} }
return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL); return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL);
case PATH_REQUESTED: case PATH_REQUESTED:
PathingCommand ret = new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); PathingCommand ret = new PathingCommand(this.goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
this.state = State.EXECUTING; this.state = State.EXECUTING;
return ret; return ret;
case EXECUTING: case EXECUTING:
@@ -18,10 +18,7 @@
package baritone.process; package baritone.process;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.*;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.process.IGetToBlockProcess; import baritone.api.process.IGetToBlockProcess;
import baritone.api.process.PathingCommand; import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
@@ -35,15 +32,14 @@ import net.minecraft.init.Blocks;
import net.minecraft.inventory.ContainerPlayer; import net.minecraft.inventory.ContainerPlayer;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.ArrayList; import java.util.*;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess { public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
private Block gettingTo; private Block gettingTo;
private List<BlockPos> knownLocations; private List<BlockPos> knownLocations;
private List<BlockPos> blacklist; // locations we failed to calc to
private BlockPos start;
private int tickCount = 0; private int tickCount = 0;
@@ -55,6 +51,8 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
public void getToBlock(Block block) { public void getToBlock(Block block) {
onLostControl(); onLostControl();
gettingTo = block; gettingTo = block;
start = ctx.playerFeet();
blacklist = new ArrayList<>();
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
@@ -64,23 +62,38 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
@Override @Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { public synchronized PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (knownLocations == null) { if (knownLocations == null) {
rescan(new ArrayList<>(), new CalculationContext(baritone)); rescan(new ArrayList<>(), new CalculationContext(baritone));
} }
if (knownLocations.isEmpty()) { if (knownLocations.isEmpty()) {
if (Baritone.settings().exploreForBlocks.get() && !calcFailed) {
return new PathingCommand(new GoalRunAway(1, start) {
@Override
public boolean isInGoal(int x, int y, int z) {
return false;
}
}, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
}
logDirect("No known locations of " + gettingTo + ", canceling GetToBlock"); logDirect("No known locations of " + gettingTo + ", canceling GetToBlock");
if (isSafeToCancel) { if (isSafeToCancel) {
onLostControl(); onLostControl();
} }
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL); return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
Goal goal = new GoalComposite(knownLocations.stream().map(this::createGoal).toArray(Goal[]::new));
if (calcFailed) { if (calcFailed) {
logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock"); if (Baritone.settings().blacklistOnGetToBlockFailure.get()) {
if (isSafeToCancel) { logDirect("Unable to find any path to " + gettingTo + ", blacklisting presumably unreachable closest instances");
onLostControl(); blacklistClosest();
return onTick(false, isSafeToCancel); // gamer moment
} else {
logDirect("Unable to find any path to " + gettingTo + ", canceling GetToBlock");
if (isSafeToCancel) {
onLostControl();
}
return new PathingCommand(goal, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
@@ -88,24 +101,61 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
CalculationContext context = new CalculationContext(baritone, true); CalculationContext context = new CalculationContext(baritone, true);
Baritone.getExecutor().execute(() -> rescan(current, context)); Baritone.getExecutor().execute(() -> rescan(current, context));
} }
Goal goal = new GoalComposite(knownLocations.stream().map(this::createGoal).toArray(Goal[]::new));
if (goal.isInGoal(ctx.playerFeet()) && isSafeToCancel) { if (goal.isInGoal(ctx.playerFeet()) && isSafeToCancel) {
// we're there // we're there
if (rightClickOnArrival(gettingTo)) { if (rightClickOnArrival(gettingTo)) {
if (rightClick()) { if (rightClick()) {
onLostControl(); onLostControl();
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
} else { } else {
onLostControl(); onLostControl();
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
} }
return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH); return new PathingCommand(goal, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
} }
// blacklist the closest block and its adjacent blocks
public synchronized void blacklistClosest() {
List<BlockPos> newBlacklist = new ArrayList<>();
knownLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(newBlacklist::add);
outer:
while (true) {
for (BlockPos known : knownLocations) {
for (BlockPos blacklist : newBlacklist) {
if (areAdjacent(known, blacklist)) { // directly adjacent
newBlacklist.add(known);
knownLocations.remove(known);
continue outer;
}
}
}
// i can't do break; (codacy gets mad), and i can't do if(true){break}; (codacy gets mad)
// so i will do this
switch (newBlacklist.size()) {
default:
break outer;
}
}
logDebug("Blacklisting unreachable locations " + newBlacklist);
blacklist.addAll(newBlacklist);
}
// safer than direct double comparison from distanceSq
private boolean areAdjacent(BlockPos posA, BlockPos posB) {
int diffX = Math.abs(posA.getX() - posB.getX());
int diffY = Math.abs(posA.getY() - posB.getY());
int diffZ = Math.abs(posA.getZ() - posB.getZ());
return (diffX + diffY + diffZ) == 1;
}
@Override @Override
public void onLostControl() { public synchronized void onLostControl() {
gettingTo = null; gettingTo = null;
knownLocations = null; knownLocations = null;
start = null;
blacklist = null;
baritone.getInputOverrideHandler().clearAllKeys(); baritone.getInputOverrideHandler().clearAllKeys();
} }
@@ -114,12 +164,20 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
return "Get To Block " + gettingTo; return "Get To Block " + gettingTo;
} }
private void rescan(List<BlockPos> known, CalculationContext context) { private synchronized void rescan(List<BlockPos> known, CalculationContext context) {
knownLocations = MineProcess.searchWorld(context, Collections.singletonList(gettingTo), 64, known); List<BlockPos> positions = MineProcess.searchWorld(context, Collections.singletonList(gettingTo), 64, known);
positions.removeIf(blacklist::contains);
knownLocations = positions;
} }
private Goal createGoal(BlockPos pos) { private Goal createGoal(BlockPos pos) {
return walkIntoInsteadOfAdjacent(gettingTo) ? new GoalTwoBlocks(pos) : new GoalGetToBlock(pos); if (walkIntoInsteadOfAdjacent(gettingTo)) {
return new GoalTwoBlocks(pos);
}
if (blockOnTopMustBeRemoved(gettingTo) && baritone.bsi.get0(pos.up()).isBlockNormalCube()) {
return new GoalBlock(pos.up());
}
return new GoalGetToBlock(pos);
} }
private boolean rightClick() { private boolean rightClick() {
@@ -154,4 +212,12 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST; return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
} }
private boolean blockOnTopMustBeRemoved(Block block) {
if (!rightClickOnArrival(block)) { // only if we plan to actually open it on arrival
return false;
}
// only these chests; you can open a crafting table or furnace even with a block on top
return block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
}
} }
@@ -228,7 +228,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return prune(ctx, locs, mining, max); return prune(ctx, locs, mining, max);
} }
public void addNearby() { private void addNearby() {
knownOreLocations.addAll(droppedItemsScan(mining, ctx.world())); knownOreLocations.addAll(droppedItemsScan(mining, ctx.world()));
BlockPos playerFeet = ctx.playerFeet(); BlockPos playerFeet = ctx.playerFeet();
BlockStateInterface bsi = new BlockStateInterface(ctx); BlockStateInterface bsi = new BlockStateInterface(ctx);
@@ -239,8 +239,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) { for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
// crucial to only add blocks we can see because otherwise this // crucial to only add blocks we can see because otherwise this
// is an x-ray and it'll get caught // is an x-ray and it'll get caught
if (mining.contains(bsi.get0(x, y, z).getBlock()) && RotationUtils.reachable(ctx.player(), new BlockPos(x, y, z), fakedBlockReachDistance).isPresent()) { if (mining.contains(bsi.get0(x, y, z).getBlock())) {
knownOreLocations.add(new BlockPos(x, y, z)); BlockPos pos = new BlockPos(x, y, z);
if ((Baritone.settings().legitMineIncludeDiagonals.get() && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx.player(), pos, fakedBlockReachDistance).isPresent()) {
knownOreLocations.add(pos);
}
} }
} }
} }
@@ -250,12 +253,19 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) { public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world); List<BlockPos> dropped = droppedItemsScan(mining, ctx.world);
dropped.removeIf(drop -> {
for (BlockPos pos : locs2) {
if (pos.distanceSq(drop) <= 9 && mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx.bsi, pos)) { // TODO maybe drop also has to be supported? no lava below?
return true;
}
}
return false;
});
List<BlockPos> locs = locs2 List<BlockPos> locs = locs2
.stream() .stream()
.distinct() .distinct()
// remove any that are within loaded chunks that aren't actually what we want // remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos)) .filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
// remove any that are implausible to mine (encased in bedrock, or touching lava) // remove any that are implausible to mine (encased in bedrock, or touching lava)
@@ -115,7 +115,9 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
} }
// Setup Baritone's pathing goal and (if needed) begin pathing // Setup Baritone's pathing goal and (if needed) begin pathing
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(GOAL); if (!BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().isActive()) {
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(GOAL);
}
// If we have reached our goal, print a message and safely close the game // If we have reached our goal, print a message and safely close the game
if (GOAL.isInGoal(ctx.playerFeet())) { if (GOAL.isInGoal(ctx.playerFeet())) {
@@ -31,7 +31,7 @@ public final class BlockBreakHelper implements Helper {
private boolean didBreakLastTick; private boolean didBreakLastTick;
private IPlayerContext playerContext; private final IPlayerContext playerContext;
public BlockBreakHelper(IPlayerContext playerContext) { public BlockBreakHelper(IPlayerContext playerContext) {
this.playerContext = playerContext; this.playerContext = playerContext;
@@ -0,0 +1,53 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils;
import baritone.Baritone;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
public class BlockPlaceHelper implements Helper {
private final IPlayerContext ctx;
private int rightClickTimer;
public BlockPlaceHelper(IPlayerContext playerContext) {
this.ctx = playerContext;
}
public void tick(boolean rightClickRequested) {
if (rightClickTimer > 0) {
rightClickTimer--;
return;
}
RayTraceResult mouseOver = ctx.objectMouseOver();
BlockPos pos = mouseOver.getBlockPos();
if (!rightClickRequested || ctx.player().isRowingBoat() || pos == null || mouseOver.typeOfHit != RayTraceResult.Type.BLOCK) {
return;
}
rightClickTimer = Baritone.settings().rightClickSpeed.get();
for (EnumHand hand : EnumHand.values()) {
if (ctx.playerController().processRightClickBlock(ctx.player(), ctx.world(), pos, mouseOver.sideHit, mouseOver.hitVec, hand) == EnumActionResult.SUCCESS) {
ctx.player().swingArm(hand);
return;
}
}
}
}
@@ -24,6 +24,7 @@ import baritone.api.cache.IWaypoint;
import baritone.api.event.events.ChatEvent; import baritone.api.event.events.ChatEvent;
import baritone.api.pathing.goals.*; import baritone.api.pathing.goals.*;
import baritone.api.pathing.movement.ActionCosts; import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil; import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior; import baritone.behavior.Behavior;
import baritone.behavior.PathingBehavior; import baritone.behavior.PathingBehavior;
@@ -35,6 +36,7 @@ import baritone.pathing.movement.Moves;
import baritone.process.CustomGoalProcess; import baritone.process.CustomGoalProcess;
import baritone.utils.pathing.SegmentedCalculator; import baritone.utils.pathing.SegmentedCalculator;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
@@ -75,7 +77,8 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
"sethome - Sets \"home\"\n" + "sethome - Sets \"home\"\n" +
"home - Paths towards \"home\" \n" + "home - Paths towards \"home\" \n" +
"costs - (debug) all movement costs from current location\n" + "costs - (debug) all movement costs from current location\n" +
"damn - Daniel "; "damn - Daniel\n" +
"Go to https://github.com/cabaletta/baritone/blob/master/USAGE.md for more information";
private static final String COMMAND_PREFIX = "#"; private static final String COMMAND_PREFIX = "#";
@@ -85,21 +88,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
@Override @Override
public void onSendChatMessage(ChatEvent event) { public void onSendChatMessage(ChatEvent event) {
String msg = event.getMessage();
if (Baritone.settings().prefixControl.get() && msg.startsWith(COMMAND_PREFIX)) {
if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
logDirect("Invalid command");
}
event.cancel(); // always cancel if using prefixControl
return;
}
if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) { if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) {
return; return;
} }
String msg = event.getMessage(); if (runCommand(msg)) {
if (Baritone.settings().prefix.get()) { event.cancel();
if (msg.startsWith(COMMAND_PREFIX)) {
if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
logDirect("Invalid command");
}
event.cancel(); // always cancel if using prefix
}
} else {
if (runCommand(msg)) {
event.cancel();
}
} }
} }
@@ -116,12 +117,33 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
return true; return true;
} }
} }
if (msg.equals("baritone") || msg.equals("settings")) { if (msg.equals("baritone") || msg.equals("modifiedsettings") || msg.startsWith("settings m") || msg.equals("modified")) {
for (Settings.Setting<?> setting : Baritone.settings().allSettings) { logDirect("All settings that have been modified from their default values:");
for (Settings.Setting<?> setting : SettingsUtil.modifiedSettings(Baritone.settings())) {
logDirect(setting.toString()); logDirect(setting.toString());
} }
return true; return true;
} }
if (msg.startsWith("settings")) {
String rest = msg.substring("settings".length());
try {
int page = Integer.parseInt(rest.trim());
int min = page * 10;
int max = Math.min(Baritone.settings().allSettings.size(), (page + 1) * 10);
logDirect("Settings " + min + " to " + (max - 1) + ":");
for (int i = min; i < max; i++) {
logDirect(Baritone.settings().allSettings.get(i).toString());
}
} catch (Exception ex) { // NumberFormatException | ArrayIndexOutOfBoundsException and probably some others I'm forgetting lol
ex.printStackTrace();
logDirect("All settings:");
for (Settings.Setting<?> setting : Baritone.settings().allSettings) {
logDirect(setting.toString());
}
logDirect("To get one page of ten settings at a time, do settings <num>");
}
return true;
}
if (msg.equals("") || msg.equals("help") || msg.equals("?")) { if (msg.equals("") || msg.equals("help") || msg.equals("?")) {
for (String line : HELP_MSG.split("\n")) { for (String line : HELP_MSG.split("\n")) {
logDirect(line); logDirect(line);
@@ -129,31 +151,24 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
return true; return true;
} }
if (msg.contains(" ")) { if (msg.contains(" ")) {
String[] data = msg.split(" "); String settingName = msg.substring(0, msg.indexOf(' '));
if (data.length == 2) { String settingValue = msg.substring(msg.indexOf(' ') + 1);
Settings.Setting setting = Baritone.settings().byLowerName.get(data[0]); Settings.Setting setting = Baritone.settings().byLowerName.get(settingName);
if (setting != null) { if (setting != null) {
if (settingValue.equals("reset")) {
logDirect("Resetting setting " + settingName + " to default value.");
setting.reset();
} else {
try { try {
if (setting.value.getClass() == Long.class) { SettingsUtil.parseAndApply(Baritone.settings(), settingName, settingValue);
setting.value = Long.parseLong(data[1]); } catch (Exception ex) {
} logDirect("Unable to parse setting");
if (setting.value.getClass() == Integer.class) {
setting.value = Integer.parseInt(data[1]);
}
if (setting.value.getClass() == Double.class) {
setting.value = Double.parseDouble(data[1]);
}
if (setting.value.getClass() == Float.class) {
setting.value = Float.parseFloat(data[1]);
}
} catch (NumberFormatException e) {
logDirect("Unable to parse " + data[1]);
return true; return true;
} }
SettingsUtil.save(Baritone.settings());
logDirect(setting.toString());
return true;
} }
SettingsUtil.save(Baritone.settings());
logDirect(setting.toString());
return true;
} }
} }
if (Baritone.settings().byLowerName.containsKey(msg)) { if (Baritone.settings().byLowerName.containsKey(msg)) {
@@ -163,36 +178,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
if (msg.startsWith("goal")) { if (msg.startsWith("goal")) {
String[] params = msg.substring(4).trim().split(" "); String rest = msg.substring(4).trim();
if (params[0].equals("")) {
params = new String[]{};
}
Goal goal; Goal goal;
try { if (rest.equals("clear") || rest.equals("none")) {
switch (params.length) { goal = null;
case 0: } else {
goal = new GoalBlock(ctx.playerFeet()); String[] params = rest.split(" ");
break; if (params[0].equals("")) {
case 1: params = new String[]{};
if (params[0].equals("clear") || params[0].equals("none")) { }
goal = null; goal = parseGoal(params);
} else { if (goal == null) {
goal = new GoalYLevel(Integer.parseInt(params[0])); return true;
}
break;
case 2:
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
break;
case 3:
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
break;
default:
logDirect("unable to understand lol");
return true;
} }
} catch (NumberFormatException ex) {
logDirect("unable to parse integer " + ex);
return true;
} }
customGoalProcess.setGoal(goal); customGoalProcess.setGoal(goal);
logDirect("Goal: " + goal); logDirect("Goal: " + goal);
@@ -227,6 +225,15 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
return true; return true;
} }
if (msg.equals("version")) {
String version = ExampleBaritoneControl.class.getPackage().getImplementationVersion();
if (version == null) {
logDirect("No version detected. Either dev environment or broken install.");
} else {
logDirect("You are using Baritone v" + version);
}
return true;
}
if (msg.equals("repack") || msg.equals("rescan")) { if (msg.equals("repack") || msg.equals("rescan")) {
ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider(); ChunkProviderClient cli = (ChunkProviderClient) ctx.world().getChunkProvider();
int playerChunkX = ctx.playerFeet().getX() >> 4; int playerChunkX = ctx.playerFeet().getX() >> 4;
@@ -244,7 +251,12 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("Queued " + count + " chunks for repacking"); logDirect("Queued " + count + " chunks for repacking");
return true; return true;
} }
if (msg.equals("axis")) { if (msg.equals("come")) {
customGoalProcess.setGoalAndPath(new GoalBlock(new BlockPos(mc.getRenderViewEntity())));
logDirect("Coming");
return true;
}
if (msg.equals("axis") || msg.equals("highway")) {
customGoalProcess.setGoalAndPath(new GoalAxis()); customGoalProcess.setGoalAndPath(new GoalAxis());
return true; return true;
} }
@@ -285,10 +297,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
return true; return true;
} }
if (msg.equals("reset")) { if (msg.equals("reset")) {
Baritone.settings().reset(); for (Settings.Setting setting : Baritone.settings().allSettings) {
setting.reset();
}
SettingsUtil.save(Baritone.settings());
logDirect("Baritone settings reset"); logDirect("Baritone settings reset");
return true; return true;
} }
if (msg.equals("render")) {
BetterBlockPos pf = ctx.playerFeet();
Minecraft.getMinecraft().renderGlobal.markBlockRangeForRenderUpdate(pf.x - 500, pf.y - 500, pf.z - 500, pf.x + 500, pf.y + 500, pf.z + 500);
logDirect("okay");
return true;
}
if (msg.equals("echest")) { if (msg.equals("echest")) {
Optional<List<ItemStack>> contents = baritone.getMemoryBehavior().echest(); Optional<List<ItemStack>> contents = baritone.getMemoryBehavior().echest();
if (contents.isPresent()) { if (contents.isPresent()) {
@@ -386,7 +407,17 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("Started mining blocks of type " + Arrays.toString(blockTypes)); logDirect("Started mining blocks of type " + Arrays.toString(blockTypes));
return true; return true;
} }
if (msg.startsWith("thisway")) { if (msg.equals("click")) {
new Thread(() -> {
try {
Thread.sleep(100);
mc.addScheduledTask(() -> mc.displayGuiScreen(new GuiClickMeme()));
} catch (Exception ignored) {}
}).start();
logDirect("aight dude");
return true;
}
if (msg.startsWith("thisway") || msg.startsWith("forward")) {
try { try {
Goal goal = GoalXZ.fromDirection(ctx.playerFeetAsVec(), ctx.player().rotationYaw, Double.parseDouble(msg.substring(7).trim())); Goal goal = GoalXZ.fromDirection(ctx.playerFeetAsVec(), ctx.player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
customGoalProcess.setGoal(goal); customGoalProcess.setGoal(goal);
@@ -454,7 +485,11 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
if (block == null) { if (block == null) {
waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null); waypoint = baritone.getWorldProvider().getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
if (waypoint == null) { if (waypoint == null) {
logDirect("No locations for " + mining + " known, cancelling"); Goal goal = parseGoal(waypointType.split(" "));
if (goal != null) {
logDirect("Going to " + goal);
customGoalProcess.setGoalAndPath(goal);
}
return true; return true;
} }
} else { } else {
@@ -533,4 +568,31 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} }
} }
} }
private Goal parseGoal(String[] params) {
Goal goal;
try {
switch (params.length) {
case 0:
goal = new GoalBlock(ctx.playerFeet());
break;
case 1:
goal = new GoalYLevel(Integer.parseInt(params[0]));
break;
case 2:
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
break;
case 3:
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
break;
default:
logDirect("unable to understand lol");
return null;
}
} catch (NumberFormatException ex) {
logDirect("unable to parse integer " + ex);
return null;
}
return goal;
}
} }
@@ -0,0 +1,102 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalTwoBlocks;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.renderer.GlStateManager;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import org.lwjgl.BufferUtils;
import org.lwjgl.input.Mouse;
import org.lwjgl.opengl.Display;
import org.lwjgl.util.glu.GLU;
import java.awt.*;
import java.io.IOException;
import java.nio.FloatBuffer;
import java.nio.IntBuffer;
import java.util.Collections;
import static org.lwjgl.opengl.GL11.*;
public class GuiClickMeme extends GuiScreen {
// My name is Brady and I grant Leijurv permission to use this pasted code
private final FloatBuffer MODELVIEW = BufferUtils.createFloatBuffer(16);
private final FloatBuffer PROJECTION = BufferUtils.createFloatBuffer(16);
private final IntBuffer VIEWPORT = BufferUtils.createIntBuffer(16);
private final FloatBuffer TO_SCREEN_BUFFER = BufferUtils.createFloatBuffer(3);
private final FloatBuffer TO_WORLD_BUFFER = BufferUtils.createFloatBuffer(3);
private BlockPos meme;
@Override
public boolean doesGuiPauseGame() {
return false;
}
@Override
public void drawScreen(int mouseX, int mouseY, float partialTicks) {
int mx = Mouse.getX();
int my = Mouse.getY();
Vec3d near = toWorld(mx, my, 0);
Vec3d far = toWorld(mx, my, 1); // "Use 0.945 that's what stack overflow says" - Leijurv
if (near != null && far != null) {
Vec3d viewerPos = new Vec3d(mc.getRenderManager().viewerPosX, mc.getRenderManager().viewerPosY, mc.getRenderManager().viewerPosZ);
RayTraceResult result = mc.world.rayTraceBlocks(near.add(viewerPos), far.add(viewerPos), false, false, true);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
meme = result.getBlockPos();
}
}
}
@Override
protected void mouseClicked(int mouseX, int mouseY, int mouseButton) throws IOException {
super.mouseClicked(mouseX, mouseY, mouseButton);
if (mouseButton == 0) {
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalTwoBlocks(meme));
} else if (mouseButton == 1) {
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalBlock(meme.up()));
}
}
public void onRender(float partialTicks) {
GlStateManager.getFloat(GL_MODELVIEW_MATRIX, (FloatBuffer) MODELVIEW.clear());
GlStateManager.getFloat(GL_PROJECTION_MATRIX, (FloatBuffer) PROJECTION.clear());
GlStateManager.glGetInteger(GL_VIEWPORT, (IntBuffer) VIEWPORT.clear());
if (meme != null) {
Entity e = mc.getRenderViewEntity();
// drawSingleSelectionBox WHEN?
PathRenderer.drawManySelectionBoxes(e, Collections.singletonList(meme), Color.CYAN);
}
}
public Vec3d toWorld(double x, double y, double z) {
boolean result = GLU.gluUnProject((float) x, (float) y, (float) z, MODELVIEW, PROJECTION, VIEWPORT, (FloatBuffer) TO_WORLD_BUFFER.clear());
if (result) {
return new Vec3d(TO_WORLD_BUFFER.get(0), TO_WORLD_BUFFER.get(1), TO_WORLD_BUFFER.get(2));
}
return null;
}
}
@@ -24,8 +24,6 @@ import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.behavior.Behavior; import baritone.behavior.Behavior;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.MovementInput;
import net.minecraft.util.MovementInputFromOptions; import net.minecraft.util.MovementInputFromOptions;
import java.util.HashMap; import java.util.HashMap;
@@ -47,31 +45,12 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
private final Map<Input, Boolean> inputForceStateMap = new HashMap<>(); private final Map<Input, Boolean> inputForceStateMap = new HashMap<>();
private final BlockBreakHelper blockBreakHelper; private final BlockBreakHelper blockBreakHelper;
private final BlockPlaceHelper blockPlaceHelper;
public InputOverrideHandler(Baritone baritone) { public InputOverrideHandler(Baritone baritone) {
super(baritone); super(baritone);
this.blockBreakHelper = new BlockBreakHelper(baritone.getPlayerContext()); this.blockBreakHelper = new BlockBreakHelper(baritone.getPlayerContext());
} this.blockPlaceHelper = new BlockPlaceHelper(baritone.getPlayerContext());
/**
* Returns whether or not we are forcing down the specified {@link KeyBinding}.
*
* @param key The KeyBinding object
* @return Whether or not it is being forced down
*/
@Override
public final Boolean isInputForcedDown(KeyBinding key) {
Input input = Input.getInputForBind(key);
if (input == null || !inControl()) {
return null;
}
if (input == Input.CLICK_LEFT) {
return false;
}
if (input == Input.CLICK_RIGHT) {
return isInputForcedDown(Input.CLICK_RIGHT);
}
return null;
} }
/** /**
@@ -109,19 +88,27 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
if (event.getType() == TickEvent.Type.OUT) { if (event.getType() == TickEvent.Type.OUT) {
return; return;
} }
blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT)); if (isInputForcedDown(Input.CLICK_LEFT)) {
setInputForceState(Input.CLICK_RIGHT, false);
MovementInput desired = inControl()
? new PlayerMovementInput(this)
: new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
if (ctx.player().movementInput.getClass() != desired.getClass()) {
ctx.player().movementInput = desired; // only set it if it was previously incorrect
// gotta do it this way, or else it constantly thinks you're beginning a double tap W sprint lol
} }
blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT));
blockPlaceHelper.tick(isInputForcedDown(Input.CLICK_RIGHT));
if (inControl()) {
if (ctx.player().movementInput.getClass() != PlayerMovementInput.class) {
ctx.player().movementInput = new PlayerMovementInput(this);
}
} else {
if (ctx.player().movementInput.getClass() == PlayerMovementInput.class) { // allow other movement inputs that aren't this one, e.g. for a freecam
ctx.player().movementInput = new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
}
}
// only set it if it was previously incorrect
// gotta do it this way, or else it constantly thinks you're beginning a double tap W sprint lol
} }
private boolean inControl() { private boolean inControl() {
// if we are not primary (a bot) we should set the movementinput even when idle (not pathing)
return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone(); return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone();
} }
+24 -24
View File
@@ -57,10 +57,11 @@ public final class PathRenderer implements Helper {
private PathRenderer() {} private PathRenderer() {}
public static void render(RenderEvent event, PathingBehavior behavior) { public static void render(RenderEvent event, PathingBehavior behavior) {
// System.out.println("Render passing");
// System.out.println(event.getPartialTicks());
float partialTicks = event.getPartialTicks(); float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal(); Goal goal = behavior.getGoal();
if (mc.currentScreen instanceof GuiClickMeme) {
((GuiClickMeme) mc.currentScreen).onRender(partialTicks);
}
int thisPlayerDimension = behavior.baritone.getPlayerContext().world().provider.getDimensionType().getId(); int thisPlayerDimension = behavior.baritone.getPlayerContext().world().provider.getDimensionType().getId();
int currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().provider.getDimensionType().getId(); int currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().provider.getDimensionType().getId();
@@ -80,7 +81,7 @@ public final class PathRenderer implements Helper {
} }
if (goal != null && Baritone.settings().renderGoal.value) { if (goal != null && Baritone.settings().renderGoal.value) {
drawLitDankGoalBox(renderView, goal, partialTicks, Baritone.settings().colorGoalBox.get()); drawDankLitGoalBox(renderView, goal, partialTicks, Baritone.settings().colorGoalBox.get());
} }
if (!Baritone.settings().renderPath.get()) { if (!Baritone.settings().renderPath.get()) {
return; return;
@@ -104,9 +105,9 @@ public final class PathRenderer implements Helper {
//long split = System.nanoTime(); //long split = System.nanoTime();
if (current != null) { if (current != null) {
drawManySelectionBoxes(renderView, current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get()); drawManySelectionBoxes(renderView, current.toBreak(), Baritone.settings().colorBlocksToBreak.get());
drawManySelectionBoxes(renderView, current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get()); drawManySelectionBoxes(renderView, current.toPlace(), Baritone.settings().colorBlocksToPlace.get());
drawManySelectionBoxes(renderView, current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get()); drawManySelectionBoxes(renderView, current.toWalkInto(), Baritone.settings().colorBlocksToWalkInto.get());
} }
// If there is a path calculation currently running, render the path calculation process // If there is a path calculation currently running, render the path calculation process
@@ -117,7 +118,7 @@ public final class PathRenderer implements Helper {
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> { currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
drawPath(mr, 0, renderView, partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20); drawPath(mr, 0, renderView, partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get()); drawManySelectionBoxes(renderView, Collections.singletonList(mr.getDest()), Baritone.settings().colorMostRecentConsidered.get());
}); });
}); });
//long end = System.nanoTime(); //long end = System.nanoTime();
@@ -174,7 +175,7 @@ public final class PathRenderer implements Helper {
} }
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], alpha); GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], alpha);
} }
drawLine(player, x1, y1, z1, x2, y2, z2, partialTicks); drawLine(player, x1, y1, z1, x2, y2, z2);
tessellator.draw(); tessellator.draw();
} }
if (Baritone.settings().renderPathIgnoreDepth.get()) { if (Baritone.settings().renderPathIgnoreDepth.get()) {
@@ -186,10 +187,10 @@ public final class PathRenderer implements Helper {
GlStateManager.disableBlend(); GlStateManager.disableBlend();
} }
public static void drawLine(Entity player, double bp1x, double bp1y, double bp1z, double bp2x, double bp2y, double bp2z, float partialTicks) { public static void drawLine(Entity player, double bp1x, double bp1y, double bp1z, double bp2x, double bp2y, double bp2z) {
double d0 = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; double d0 = mc.getRenderManager().viewerPosX;
double d1 = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; double d1 = mc.getRenderManager().viewerPosY;
double d2 = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; double d2 = mc.getRenderManager().viewerPosZ;
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION); BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex(); BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex();
BUFFER.pos(bp2x + 0.5D - d0, bp2y + 0.5D - d1, bp2z + 0.5D - d2).endVertex(); BUFFER.pos(bp2x + 0.5D - d0, bp2y + 0.5D - d1, bp2z + 0.5D - d2).endVertex();
@@ -198,7 +199,7 @@ public final class PathRenderer implements Helper {
BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex(); BUFFER.pos(bp1x + 0.5D - d0, bp1y + 0.5D - d1, bp1z + 0.5D - d2).endVertex();
} }
public static void drawManySelectionBoxes(Entity player, Collection<BlockPos> positions, float partialTicks, Color color) { public static void drawManySelectionBoxes(Entity player, Collection<BlockPos> positions, Color color) {
GlStateManager.enableBlend(); GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0); GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F); GlStateManager.color(color.getColorComponents(null)[0], color.getColorComponents(null)[1], color.getColorComponents(null)[2], 0.4F);
@@ -212,10 +213,6 @@ public final class PathRenderer implements Helper {
float expand = 0.002F; float expand = 0.002F;
//BlockPos blockpos = movingObjectPositionIn.getBlockPos(); //BlockPos blockpos = movingObjectPositionIn.getBlockPos();
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
BlockStateInterface bsi = new BlockStateInterface(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()); // TODO this assumes same dimension between primary baritone and render view? is this safe? BlockStateInterface bsi = new BlockStateInterface(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()); // TODO this assumes same dimension between primary baritone and render view? is this safe?
positions.forEach(pos -> { positions.forEach(pos -> {
IBlockState state = bsi.get0(pos); IBlockState state = bsi.get0(pos);
@@ -225,7 +222,7 @@ public final class PathRenderer implements Helper {
} else { } else {
toDraw = state.getSelectedBoundingBox(player.world, pos); toDraw = state.getSelectedBoundingBox(player.world, pos);
} }
toDraw = toDraw.expand(expand, expand, expand).offset(-renderPosX, -renderPosY, -renderPosZ); toDraw = toDraw.expand(expand, expand, expand).offset(-mc.getRenderManager().viewerPosX, -mc.getRenderManager().viewerPosY, -mc.getRenderManager().viewerPosZ);
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION); BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex(); BUFFER.pos(toDraw.minX, toDraw.minY, toDraw.minZ).endVertex();
BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex(); BUFFER.pos(toDraw.maxX, toDraw.minY, toDraw.minZ).endVertex();
@@ -261,11 +258,10 @@ public final class PathRenderer implements Helper {
GlStateManager.disableBlend(); GlStateManager.disableBlend();
} }
public static void drawLitDankGoalBox(Entity player, Goal goal, float partialTicks, Color color) { public static void drawDankLitGoalBox(Entity player, Goal goal, float partialTicks, Color color) {
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks; double renderPosX = mc.getRenderManager().viewerPosX;
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks; double renderPosY = mc.getRenderManager().viewerPosY;
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks; double renderPosZ = mc.getRenderManager().viewerPosZ;
double minX; double minX;
double maxX; double maxX;
double minZ; double minZ;
@@ -297,6 +293,8 @@ public final class PathRenderer implements Helper {
GoalXZ goalPos = (GoalXZ) goal; GoalXZ goalPos = (GoalXZ) goal;
if (Baritone.settings().renderGoalXZBeacon.get()) { if (Baritone.settings().renderGoalXZBeacon.get()) {
glPushAttrib(GL_LIGHTING_BIT);
mc.getTextureManager().bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM); mc.getTextureManager().bindTexture(TileEntityBeaconRenderer.TEXTURE_BEACON_BEAM);
if (Baritone.settings().renderGoalIgnoreDepth.get()) { if (Baritone.settings().renderGoalIgnoreDepth.get()) {
@@ -318,6 +316,8 @@ public final class PathRenderer implements Helper {
if (Baritone.settings().renderGoalIgnoreDepth.get()) { if (Baritone.settings().renderGoalIgnoreDepth.get()) {
GlStateManager.enableDepth(); GlStateManager.enableDepth();
} }
glPopAttrib();
return; return;
} }
@@ -332,7 +332,7 @@ public final class PathRenderer implements Helper {
maxY = 256 - renderPosY; maxY = 256 - renderPosY;
} else if (goal instanceof GoalComposite) { } else if (goal instanceof GoalComposite) {
for (Goal g : ((GoalComposite) goal).goals()) { for (Goal g : ((GoalComposite) goal).goals()) {
drawLitDankGoalBox(player, g, partialTicks, color); drawDankLitGoalBox(player, g, partialTicks, color);
} }
return; return;
} else { } else {
@@ -82,6 +82,7 @@ public class PathingControlManager implements IPathingControlManager {
public void preTick() { public void preTick() {
inControlLastTick = inControlThisTick; inControlLastTick = inControlThisTick;
inControlThisTick = null;
PathingBehavior p = baritone.getPathingBehavior(); PathingBehavior p = baritone.getPathingBehavior();
command = executeProcesses(); command = executeProcesses();
if (command == null) { if (command == null) {
@@ -31,7 +31,7 @@ public class PlayerMovementInput extends MovementInput {
this.moveStrafe = 0.0F; this.moveStrafe = 0.0F;
this.moveForward = 0.0F; this.moveForward = 0.0F;
jump = handler.isInputForcedDown(Input.JUMP); // oppa jump = handler.isInputForcedDown(Input.JUMP); // oppa gangnam
if (this.forwardKeyDown = handler.isInputForcedDown(Input.MOVE_FORWARD)) { if (this.forwardKeyDown = handler.isInputForcedDown(Input.MOVE_FORWARD)) {
this.moveForward++; this.moveForward++;
@@ -21,6 +21,7 @@ import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldData; import baritone.api.cache.IWorldData;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.api.utils.IPlayerController; import baritone.api.utils.IPlayerController;
import baritone.api.utils.RayTraceUtils;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
@@ -58,6 +59,6 @@ public enum PrimaryPlayerContext implements IPlayerContext, Helper {
@Override @Override
public RayTraceResult objectMouseOver() { public RayTraceResult objectMouseOver() {
return mc.objectMouseOver; return RayTraceUtils.rayTraceTowards(player(), playerRotations(), playerController().getBlockReachDistance());
} }
} }
@@ -19,12 +19,18 @@ package baritone.utils.player;
import baritone.api.utils.IPlayerController; import baritone.api.utils.IPlayerController;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.entity.player.EntityPlayer; import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.world.GameType; import net.minecraft.world.GameType;
import net.minecraft.world.World;
/** /**
* Implementation of {@link IPlayerController} that chains to the primary player controller's methods * Implementation of {@link IPlayerController} that chains to the primary player controller's methods
@@ -60,4 +66,10 @@ public enum PrimaryPlayerController implements IPlayerController, Helper {
public GameType getGameType() { public GameType getGameType() {
return mc.playerController.getCurrentGameType(); return mc.playerController.getCurrentGameType();
} }
@Override
public EnumActionResult processRightClickBlock(EntityPlayerSP player, World world, BlockPos pos, EnumFacing direction, Vec3d vec, EnumHand hand) {
// primaryplayercontroller is always in a WorldClient so this is ok
return mc.playerController.processRightClickBlock(player, (WorldClient) world, pos, direction, vec, hand);
}
} }