Compare commits

...

357 Commits

Author SHA1 Message Date
Leijurv 82d09a536d v1.3.1 2019-04-13 19:21:44 -07:00
Leijurv 6e49adea33 i WUV impact 2019-04-13 19:10:13 -07:00
Leijurv f85afdbc70 Merge branch 'master' into 1.13.2 2019-04-12 21:57:01 -07:00
Leijurv fcadf68c90 cool tunnel feature and various fixes 2019-04-12 17:42:50 -07:00
Leijurv 65cd6a92d3 allow saving enumfacing value 2019-04-11 16:42:04 -07:00
Leijurv a09bb0d538 build repeat option 2019-04-11 16:36:20 -07:00
Leijurv 2bf475d840 build in layers test 2019-04-11 15:17:26 -07:00
Leijurv 76cdaaace6 add todo 2019-04-10 23:45:52 -07:00
Leijurv ce59ef559f backport important world scanner fixes 2019-04-09 19:35:43 -07:00
Leijurv 563028a5b3 fix invalid player move packet, and a bunch of things in world scanner 2019-04-09 19:30:48 -07:00
Leijurv d5c317b88b Merge branch 'master' into 1.13.2 2019-04-09 18:17:53 -07:00
Leijurv fc3f183dce actually don't render the boxes if renderpath is false 2019-04-09 08:45:30 -07:00
Leijurv 6b6eea2d8c add renderSelectionBoxes, fixes #378 2019-04-08 20:32:47 -08:00
Leijurv e54652941b codacy 2019-04-07 17:44:23 -07:00
Leijurv 867c01ff86 crucial performance optimization 2019-04-06 21:50:22 -08:00
Leijurv 87a9e67ba8 dont reassign arg 2019-04-05 11:59:28 -07:00
Leijurv bf076f6246 privatize 2019-04-04 20:51:02 -08:00
Leijurv 75b54dfaec nullpointer is confusing 2019-04-03 23:19:32 -07:00
Leijurv 71a2219b07 move fields to the top 2019-04-02 21:40:33 -08:00
Leijurv ccc3de2d7c dawn of the 8th month 2019-04-01 23:30:33 -07:00
Leijurv af11e64cec combine nested 2019-03-31 20:22:17 -08:00
Leijurv 2c3dc5d6b1 add plea 2019-03-30 23:23:12 -07:00
Leijurv 71482cc984 explain for brainlets 2019-03-29 23:10:19 -07:00
Leijurv 3329db1dae these show the exact same info; remove one 2019-03-28 23:01:14 -07:00
Leijurv 926e2d5620 add resuming to builder, fixes #371 2019-03-27 17:32:02 -07:00
Leijurv d2de8828e7 did this 2019-03-26 23:01:07 -07:00
Leijurv 9fcae6560e better feature branch example 2019-03-25 21:03:19 -08:00
Leijurv 2e8fdd43ee no flowing 2019-03-24 13:53:19 -07:00
Leijurv 27e39c8083 update badges 2019-03-24 13:50:50 -07:00
Leijurv a8f373d568 fine; assumewalkonlava 2019-03-24 13:07:08 -07:00
Leijurv c59ec9da10 blank space 2019-03-23 22:17:40 -08:00
Leijurv 71491a7922 blank space 2019-03-23 22:17:40 -08:00
Leijurv 3a675836da Merge pull request #370 from babbaj/patch-1
use runAutoTest
2019-03-23 13:03:19 -07:00
babbaj 7e0fc81246 use runAutoTest 2019-03-23 15:55:16 -04:00
Leijurv f970f932c7 great 2019-03-23 10:52:03 -07:00
Leijurv 52d2741f52 and lets try making it fail delibrately 2019-03-23 10:31:36 -07:00
Leijurv 7bc6765cac rart 2019-03-23 10:13:14 -07:00
Leijurv 85b2aea6e9 where is this writing??? 2019-03-23 09:52:49 -07:00
Leijurv c6ba5481d9 one final attempt 2019-03-22 22:33:40 -07:00
Leijurv 81f47d5632 forgot file name lollll 2019-03-22 22:19:13 -07:00
Leijurv 9b1440ed2c that needs to be allowed 2019-03-22 22:07:12 -07:00
Leijurv 2a8dcee028 write to a file to indicate success 2019-03-22 22:05:27 -07:00
Leijurv 277ba3643c Merge branch 'master' into 1.13.2 2019-03-22 21:24:43 -07:00
Leijurv 170c2d35c2 perhaps updating debian will help 2019-03-22 21:17:20 -07:00
Leijurv e5fbaf60f3 shutdownminecraftapplet 2019-03-22 21:04:35 -07:00
Leijurv bc49b2d5ba add allowDownward, fixes #369 2019-03-22 15:50:23 -07:00
Leijurv ac1ac50158 add some builder commands to usage 2019-03-22 14:36:21 -07:00
Leijurv d4103a924d add two new awesome badges 2019-03-21 16:58:31 -07:00
Leijurv 0deb854e1b v1.3.0 2019-03-21 16:40:18 -07:00
Leijurv 8268e3ec1b Merge branch 'master' into 1.13.2 2019-03-21 15:51:36 -07:00
Leijurv bd64f73842 fix disconnect on arrival not firing for custom goal process 2019-03-21 15:44:20 -07:00
Leijurv cac653ddd9 little cleanup 2019-03-20 23:06:14 -07:00
Leijurv 04ff365890 what about if i delete two (2) empty lines 2019-03-20 23:03:06 -07:00
Leijurv 54ed6ce5a5 crucial code formatting 2019-03-20 22:55:40 -07:00
Brady 32ac46c8a9 Update PULL_REQUEST_TEMPLATE.md 2019-03-19 21:26:58 -05:00
Brady 7ab2cd2a45 Update ISSUE_TEMPLATE.md 2019-03-19 21:26:47 -05:00
Brady a07fae6cdd Update Code of Conduct to include templates 2019-03-19 21:25:58 -05:00
babbaj 3f6af51713 Create PULL_REQUEST_TEMPLATE.md 2019-03-19 21:23:05 -05:00
babbaj 8c4e778506 Create ISSUE_TEMPLATE.md 2019-03-19 21:23:05 -05:00
Leijurv 65902d556e v1.2.5 2019-03-19 18:22:22 -07:00
Leijurv af91da6a28 Merge branch 'master' into 1.13.2 2019-03-19 18:12:26 -07:00
Leijurv aada9731a6 more resiliency to invalid cache files 2019-03-19 18:10:53 -07:00
Leijurv 9a15a65ad5 not needed anymore 2019-03-19 13:59:56 -07:00
Leijurv 49658078b9 trapdoors cant be passed vertically in either state, thanks plutie 2019-03-18 22:38:06 -07:00
Leijurv bcd097c6cb we can cancel calc even if not safe to cancel pathing 2019-03-17 22:40:11 -08:00
Leijurv cfec67f1f9 wording 2019-03-16 23:23:20 -07:00
Leijurv 0cbe9f81c8 Merge branch 'master' into 1.13.2 2019-03-15 16:58:23 -07:00
Leijurv 42afd2dd54 maybe proper exit code 2019-03-15 16:49:36 -07:00
Leijurv aaaf0f8839 hey so what if we didnt do that 2019-03-15 16:40:15 -07:00
Leijurv 315929f31c hey so what if we didnt do that 2019-03-15 16:39:59 -07:00
Leijurv 358aa80280 docker time 2019-03-15 16:22:51 -07:00
Leijurv 1dd9e11994 documentation resigned 2019-03-15 16:19:07 -07:00
Leijurv 5a8f02c944 unscuff everything 2019-03-15 16:11:14 -07:00
Leijurv f248a5b677 make runClient work 2019-03-15 15:32:51 -07:00
Leijurv ee83471bf6 fix being unable to place or pick up water buckets 2019-03-15 14:26:38 -07:00
Leijurv 610fe6439f fix getting permanently stuck on vines 2019-03-15 14:25:43 -07:00
Leijurv e4a49c5529 fix launchtesting not found on runClient 2019-03-15 14:00:11 -07:00
Leijurv 449b44ba50 line 2019-03-14 16:32:14 -07:00
Leijurv a00eec402e i love retina wtf 2019-03-14 16:32:04 -07:00
Leijurv 717779f742 air is stupid 2019-03-14 16:06:32 -07:00
Leijurv bd1dcff385 allow ties for closest to explore to 2019-03-14 14:52:51 -07:00
Leijurv 6f843bd24d Merge branch 'master' into 1.13.2 2019-03-13 20:09:08 -07:00
Leijurv 226ede7ba2 crucial 2019-03-13 19:23:28 -07:00
Leijurv 89fb5cecd5 v1.2.4 2019-03-13 18:15:21 -07:00
Leijurv d79fbea433 scuffed air 2019-03-13 18:08:15 -07:00
Leijurv a75317cc2c workaround some scuff 2019-03-13 09:17:25 -07:00
Leijurv ee6df270ce relative coordinates 2019-03-13 08:50:04 -07:00
Leijurv e09541151f update clients 2019-03-12 23:29:08 -07:00
Leijurv 74e0552be0 unscuff water, thanks wwe 2019-03-12 23:10:06 -07:00
Leijurv 4d22c10ddb unscuff water, thanks wwe 2019-03-12 23:08:06 -07:00
Leijurv 1ea92a6092 😎 2019-03-12 22:49:23 -07:00
Leijurv 909ab553eb small cleanup 2019-03-12 22:08:17 -07:00
Leijurv 866408aece rename 2019-03-12 19:17:50 -07:00
Leijurv 2215f170df Merge branch 'builder' 2019-03-12 19:16:40 -07:00
Leijurv a5601fd89a nutty 2019-03-12 18:59:20 -07:00
Leijurv fa8f2632f5 dont jump while breaking 2019-03-12 18:58:35 -07:00
Leijurv 66eba84d06 consistent spacing 2019-03-12 18:54:36 -07:00
Leijurv 92e39b5d1d its over its done 2019-03-12 18:45:54 -07:00
Leijurv 0ddc47f473 i am rarted 2019-03-12 18:21:29 -07:00
Leijurv ddfeca6947 unproject click cursed 2019-03-12 18:00:30 -07:00
Leijurv 6bd2e90cfd crash when pathing near shulker boxes 2019-03-12 17:18:58 -07:00
Leijurv 82505ddb01 online mode via env 2019-03-12 17:18:52 -07:00
Leijurv 2790d1d308 Merge branch 'master' into 1.13.2 2019-03-12 16:19:06 -07:00
Leijurv 52d8d271f1 fix a meme with a path ending in water 2019-03-12 16:18:48 -07:00
Leijurv 11e503a022 many fixes 2019-03-12 16:17:43 -07:00
Leijurv b240e8420a whoops 2019-03-12 15:53:00 -07:00
Leijurv 25024b58de fix a bunch of scuff 2019-03-12 15:52:40 -07:00
Leijurv 6fe49380ba pwned 2019-03-12 15:42:25 -07:00
Leijurv 1f2e267e3d fix a bunch of scuff 2019-03-12 15:41:58 -07:00
Leijurv 4cf6783622 fix the tests 2019-03-12 09:38:05 -07:00
Brady 82d77a7bac Update MixinGradle to 0.6.2
Includes fix ensuring that the SRGs are generated prior to Mixin annotation processing
2019-03-12 01:43:03 -05:00
Leijurv ba31d209c9 except what if it compiled 2019-03-11 23:29:39 -07:00
Leijurv 7974d9135b Merge branch 'master' into builder 2019-03-11 23:26:05 -07:00
Brady 841a927033 Merge remote-tracking branch 'origin/master' into 1.13.2 2019-03-12 01:09:11 -05:00
Brady 5a16561954 Working 1.13.2 development environment
Including a couple bugfixes to bad 1.13.2 code!!!
2019-03-12 01:05:39 -05:00
Leijurv a5a795a22c lower case ok 2019-03-11 22:21:35 -07:00
Leijurv 416b5b66d2 break fewer beds 2019-03-11 20:57:46 -07:00
Leijurv 88e41f37b1 explain whats happening 2019-03-11 20:08:52 -07:00
Leijurv 7cfa837604 blacklistClosestOnFailure 2019-03-11 20:06:19 -07:00
Leijurv 6b7aca3081 force revalidate on control change 2019-03-11 19:23:41 -07:00
Leijurv 580af2ab06 processes tied in priority 2019-03-11 18:24:31 -07:00
Leijurv d144d30890 crucial clarification 2019-03-10 23:43:00 -07:00
Leijurv ecac546c6d actually trolling is fine 2019-03-09 23:15:03 -08:00
Brady e2cc51908b Notch builds 2019-03-08 23:18:00 -06:00
Brady 1390e04435 Add versions in parenthesis for todos to fix stuff 2019-03-08 15:14:52 -06:00
Brady 84d961cbab Fix usages of Setting#get() 2019-03-08 15:12:55 -06:00
Brady 87b9d3915c Fix compiler errors
unproject needs to be resolved
2019-03-08 15:03:58 -06:00
Brady c38d17563d Resolve merge conflicts
oh my god I should've updated my local branch before doing this
2019-03-08 14:44:49 -06:00
Brady 0c2af85ac0 Update to 1.13.2
Still need to setup method of launching, and Mixin support for ModLauncher
2019-03-08 14:30:43 -06:00
Leijurv 76297e8176 add click to usage 2019-03-08 08:43:28 -08:00
Leijurv d90f391b5e 7 lmao 2019-03-07 18:18:31 -08:00
Leijurv d80ae57964 disconnect on arrival 2019-03-06 22:44:57 -08:00
Leijurv 74d7483b3c explore 2019-03-05 12:26:52 -08:00
Leijurv b3c580e657 teensy javadoc 2019-03-04 21:49:21 -08:00
Leijurv 8050b69f2f no more .get 😎 2019-03-04 21:30:04 -08:00
Leijurv 459720c348 eh actually lets do the whole render distance! 2019-03-04 21:21:02 -08:00
Leijurv a73f5c1359 crapton of performance improvements 2019-03-04 21:20:13 -08:00
Leijurv 71cb0f6d36 fix a weird way of getting stuck on a ladder 2019-03-04 21:00:41 -08:00
Leijurv 0d15225b1d dont construct one unlesss we need to 2019-03-04 21:00:30 -08:00
Leijurv 826f3788d0 performance improvement and no allocation promise 2019-03-04 20:39:22 -08:00
Leijurv 2133ab39b7 better cache, needs more testing 2019-03-04 19:44:36 -08:00
Leijurv 558c14a375 little cleanup 2019-03-04 13:11:36 -08:00
Leijurv 882ac41291 player coords 2019-03-04 11:28:41 -08:00
Leijurv 66c7a3f513 this is really bad 2019-03-03 21:29:31 -08:00
Leijurv 5904441a7e ❤️ code of conduct 2019-03-02 22:40:42 -08:00
Leijurv c465228531 consistency with the previously existing anime policy 2019-03-02 21:44:20 -08:00
Leijurv 81b22019dd Create CODE_OF_CONDUCT.md 2019-03-02 21:43:18 -08:00
Leijurv 3e47d485f9 emphasize and clarify lol 2019-03-01 12:11:47 -08:00
Leijurv 701bc772a8 update impcat badge 2019-03-01 11:22:21 -08:00
Leijurv 3ae05b7348 worldedit 2019-02-28 15:26:09 -08:00
Leijurv 2e186019f5 Merge branch 'master' into builder 2019-02-28 12:32:29 -08:00
Leijurv 4c6f321cff clarify 2019-02-28 12:12:16 -08:00
Leijurv c72eb3e195 v1.2.3 2019-02-28 09:47:47 -08:00
Leijurv a4237bf1f9 tentative fix to descend, needs testing 2019-02-27 23:04:43 -08:00
Leijurv e767e34b92 well that was stupid, thanks thesmarttheorist 2019-02-27 22:15:54 -08:00
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 2b672998e1 fix two weird ways of getting stuck 2019-02-21 14:24:23 -08:00
Leijurv e18dc7c7e7 Merge branch 'master' into builder 2019-02-21 11:28:13 -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 bf12763a10 fix a bunch of bugs with placement 2019-02-20 08:08:52 -08:00
Leijurv 963641a818 trim big schematics 2019-02-19 22:50:03 -08:00
Leijurv 3e94d92fbd Merge branch 'master' into builder 2019-02-19 22:33:19 -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 ce73d34627 Merge branch 'master' into builder 2019-02-16 20:49:07 -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 d8348ad292 Merge branch 'master' into builder 2019-02-07 14:11:26 -08:00
Leijurv 6faa7344aa properly discard orphan path segments 2019-02-07 14:11:18 -08:00
Leijurv 299540725e a start on inventory movement 2019-02-07 13:59:37 -08:00
Leijurv 0ef08142fd trim spaces from schematic name 2019-02-07 13:12:44 -08:00
Leijurv c0761c0eef be more tolerant of alternate movement inputs 2019-02-07 10:46:32 -08:00
Leijurv 8694d926c4 remove unneeded printouts 2019-02-07 10:45:51 -08:00
Leijurv 46f8829951 v1.1.4 2019-02-07 09:16:19 -08:00
Leijurv 4c4bce3561 define origin 2019-02-06 22:10:52 -08:00
Leijurv 68e8717b5c Merge branch 'master' into builder 2019-02-06 21:05:14 -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 a822d3ef05 horrifying placement 2019-02-06 16:22:40 -08:00
Leijurv 311cf81e8a Merge branch 'master' into builder 2019-02-06 12:54:03 -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 5fb8a1d3d1 Merge branch 'master' into builder 2019-01-29 19:58:51 -08:00
Leijurv 306bd18a40 Merge branch 'master' into builder 2019-01-29 19:47:36 -08: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 847181ada4 Merge branch 'master' into builder 2019-01-24 21:00:52 -08:00
Leijurv 1c1fbe83ec idk lol 2019-01-19 22:12:54 -08:00
Leijurv ccd56e0368 Merge branch 'master' into builder 2019-01-19 16:36:42 -08:00
Leijurv b005ce8e6b mega cancer render cached chunks 2019-01-17 18:54:37 -08:00
Leijurv cef88cde20 epic super 2019-01-17 12:25:48 -08:00
Brady aa3833915b Repackage schematic implementations 2019-01-16 13:45:32 -06:00
Brady 0c0bbeff27 Minor AirSchematic access modifier change 2019-01-16 12:39:15 -06:00
Brady ceda14096c Builder Process API exposure
Professional style 💪
2019-01-15 22:07:06 -06:00
Leijurv d5b393d6bd area clear 2019-01-14 21:41:40 -08:00
Leijurv e2cdd6a7f9 builder with multiple materials 2019-01-14 19:49:26 -08:00
Leijurv 261d02e67b Merge branch 'master' into builder 2019-01-14 13:01:25 -08:00
Leijurv a6ce4694fc hotbar selection uwu 2019-01-12 19:51:21 -08:00
Leijurv 14bc65468a tweaks 2019-01-11 10:02:21 -08:00
Leijurv 56d109bf0a Merge pull request #310 from babbaj/builder
make code easy to understand
2019-01-11 10:00:54 -08:00
babbaj a965859095 make code easy to understand 2019-01-11 01:13:14 -05:00
Leijurv 863ae447b9 except we actually make it work 2019-01-10 18:15:05 -08:00
Leijurv 4dd922f1b5 Merge branch 'master' into builder 2019-01-10 17:27:23 -08:00
Leijurv f95dc40f4c consolidate triple duplicated placement code 2019-01-10 17:23:20 -08:00
Leijurv 81786f7a7c reuse calculationcontext for planning ahead next segment 2019-01-10 13:51:26 -08:00
Leijurv 1381d8d94c two small tweaks 2019-01-10 13:50:53 -08:00
Leijurv 1dca02517e disable backtrack cost favoring while building 2019-01-09 15:42:49 -08:00
Leijurv b109fc7420 fun =) 2019-01-09 15:07:06 -08:00
Leijurv c74c01271d better strategy 2019-01-09 14:36:44 -08:00
Leijurv 702b916948 preliminary schematic stuff 2019-01-08 20:45:02 -08:00
Leijurv 8ed2431f37 Merge branch 'master' into builder 2019-01-08 14:56:48 -08:00
Leijurv c45cbebcce fixed 2018-12-27 08:06:10 -10:00
Leijurv 251110c4f8 the start of something big 2018-12-25 21:07:17 -08:00
123 changed files with 5146 additions and 2343 deletions
+1
View File
@@ -0,0 +1 @@
<!-- No UwU's or OwO's allowed -->
+1
View File
@@ -0,0 +1 @@
<!-- No UwU's or OwO's allowed -->
+3 -1
View File
@@ -11,6 +11,8 @@ build/
classes/ classes/
*.class *.class
/out
# IntelliJ Files # IntelliJ Files
.idea/ .idea/
*.iml *.iml
@@ -18,4 +20,4 @@ classes/
# Copyright Files # Copyright Files
!/.idea/copyright/Baritone.xml !/.idea/copyright/Baritone.xml
!/.idea/copyright/profiles_settings.xml !/.idea/copyright/profiles_settings.xml
+1 -1
View File
@@ -10,7 +10,7 @@ install:
script: script:
- docker run --rm cabaletta/baritone ./gradlew javadoc - docker run --rm cabaletta/baritone ./gradlew javadoc
- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient" - docker run --name baritone cabaletta/baritone /bin/sh -c "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runAutoTest; cat /code/autotest/success"
- docker cp baritone:/code/dist dist - docker cp baritone:/code/dist dist
- ls dist - ls dist
- cat dist/checksums.txt - cat dist/checksums.txt
+83
View File
@@ -0,0 +1,83 @@
# Contributor Covenant Code of Conduct
## Our Pledge
In the interest of fostering an open and welcoming environment, we as
contributors and maintainers pledge to making participation in our project and
our community a harassment-free experience for everyone, regardless of age, body
size, disability, ethnicity, sex characteristics, gender identity and expression,
level of experience, education, socio-economic status, nationality, personal
appearance, race, religion, or sexual identity and orientation.
## Our Standards
Examples of behavior that contributes to creating a positive environment
include:
* No Anime
* Using welcoming and inclusive language
* Being respectful of differing viewpoints and experiences
* Gracefully accepting constructive criticism
* Focusing on what is best for the community
* Showing empathy towards other community members
Examples of unacceptable behavior by participants include:
* Anime
* The use of sexualized language or imagery and unwelcome sexual attention or
advances
* ~~Trolling, insulting/derogatory comments, and personal or political attacks~~
* Public or private harassment
* Publishing others' private information, such as a physical or electronic
address, without explicit permission
* Other conduct which could reasonably be considered inappropriate in a
professional setting
## Our Responsibilities
Project maintainers are responsible for clarifying the standards of acceptable
behavior and are expected to take appropriate and fair corrective action in
response to any instances of unacceptable behavior.
Project maintainers have the right and responsibility to remove, edit, or
reject comments, commits, code, wiki edits, issues, and other contributions
that are not aligned to this Code of Conduct, or to ban temporarily or
permanently any contributor for other behaviors that they deem inappropriate,
threatening, offensive, or harmful.
Project maintainers have the right and responsibility to immediately remove
without any sort of dispute any issues or pull requests that do not align
with their corresponding templates. Absolutely no leniancy shall be accepted
with these terms.
## Scope
This Code of Conduct applies both within project spaces and in public spaces
when an individual is representing the project or its community. Examples of
representing a project or community include using an official project e-mail
address, posting via an official social media account, or acting as an appointed
representative at an online or offline event. Representation of a project may be
further defined and clarified by project maintainers.
## Enforcement
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported by contacting the project team at complaints@leijurv.com. All
complaints will be reviewed and investigated and will result in a response that
is deemed necessary and appropriate to the circumstances. The project team is
obligated to maintain confidentiality with regard to the reporter of an incident.
Further details of specific enforcement policies may be posted separately.
Project maintainers who do not follow or enforce the Code of Conduct in good
faith may face temporary or permanent repercussions as determined by other
members of the project's leadership.
## Attribution
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
available at https://www.contributor-covenant.org/version/1/4/code-of-conduct.html
[homepage]: https://www.contributor-covenant.org
For answers to common questions about this code of conduct, see
https://www.contributor-covenant.org/faq
+5 -6
View File
@@ -1,17 +1,16 @@
FROM debian:jessie FROM debian:stretch
RUN echo 'deb http://deb.debian.org/debian jessie-backports main' > /etc/apt/sources.list.d/jessie-backports.list RUN echo 'deb http://deb.debian.org/debian stretch-backports main' > /etc/apt/sources.list.d/stretch-backports.list
ENV DEBIAN_FRONTEND noninteractive ENV DEBIAN_FRONTEND noninteractive
RUN apt update -y RUN apt update -y
RUN apt install --target-release jessie-backports \ RUN apt install \
openjdk-8-jdk \ openjdk-8-jdk \
ca-certificates-java \
--assume-yes --assume-yes
RUN apt install -qq --force-yes mesa-utils libgl1-mesa-glx libxcursor1 libxrandr2 libxxf86vm1 x11-xserver-utils xfonts-base xserver-common RUN apt install -qq --assume-yes mesa-utils libgl1-mesa-glx libxcursor1 libxrandr2 libxxf86vm1 x11-xserver-utils xfonts-base xserver-common
COPY . /code COPY . /code
@@ -21,4 +20,4 @@ WORKDIR /code
# source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173 # source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173
RUN dpkg -i scripts/xvfb_1.16.4-1_amd64.deb RUN dpkg -i scripts/xvfb_1.16.4-1_amd64.deb
RUN ./gradlew build RUN ./gradlew build
+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

+28 -16
View File
@@ -1,9 +1,10 @@
# 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)
[![Code of Conduct](https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg?style=flat)](https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md)
[![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)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cabaletta/baritone/issues) [![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cabaletta/baritone/issues)
[![Issues](https://img.shields.io/github/issues/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues/) [![Issues](https://img.shields.io/github/issues/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues/)
@@ -11,39 +12,50 @@
[![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)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2) ![](https://tokei.rs/b1/github/cabaletta/baritone?category=code)
[![Minecraft](https://img.shields.io/badge/MC-1.13.2-brightgreen.svg)](https://minecraft.gamepedia.com/1.13.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/)
[![Asuna integration](https://img.shields.io/badge/Asuna%20integration-builder%20branch-brightgreen.svg)](https://github.com/EmotionalLove/Asuna/) [![Impact integration](https://img.shields.io/badge/Impact%20integration-v1.2.5%20/%20v1.3.0-brightgreen.svg)](https://impactdevelopment.github.io/)
[![Impact integration](https://img.shields.io/badge/Impact%20integration-v1.0.0--hotfix--4-green.svg)](https://impactdevelopment.github.io/) [![WWE integration](https://img.shields.io/badge/WWE%20%22integration%22-master%3F-green.svg)](https://wweclient.com/)
[![KAMI integration](https://img.shields.io/badge/KAMI%20integration-v1.0.0-orange.svg)](https://github.com/zeroeightysix/KAMI/) [![KAMI integration](https://img.shields.io/badge/KAMI%20integration-v1.0.0-red.svg)](https://github.com/zeroeightysix/KAMI/)
[![WWE integration](https://img.shields.io/badge/WWE%20%22integration%22-v1.0.0%3F%3F%20smh%20license%20violations-orange.svg)](https://wweclient.com/)
[![Future integration](https://img.shields.io/badge/Future%20integration-Soon™%3F%3F%3F-red.svg)](https://futureclient.net/) [![Future integration](https://img.shields.io/badge/Future%20integration-Soon™%3F%3F%3F-red.svg)](https://futureclient.net/)
[![ForgeHax integration](https://img.shields.io/badge/ForgeHax%20integration-Soon™-red.svg)](https://github.com/fr1kin/ForgeHax) [![ForgeHax integration](https://img.shields.io/badge/ForgeHax%20integration-Soon™-red.svg)](https://github.com/fr1kin/ForgeHax)
[![forthebadge](https://forthebadge.com/images/badges/built-with-swag.svg)](http://forthebadge.com)
[![forthebadge](https://forthebadge.com/images/badges/mom-made-pizza-rolls.svg)](http://forthebadge.com)
A Minecraft pathfinder bot. A Minecraft pathfinder bot.
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do. Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
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.9, 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 8 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,11 +68,11 @@ 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?
Magic. (Hours of [Leijurv](https://github.com/leijurv) enduring excruciating pain) Magic. (Hours of [leijurv](https://github.com/leijurv) enduring excruciating pain)
## Why is it called Baritone? ## Why is it called Baritone?
+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 `backfill-2` 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 & **rename** `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.2/baritone-api-1.2.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.5/1.12.2-Impact_4.5.json`, find the line `"name": "cabaletta:baritone-api:1.2"`, remove the comma from the end, and **entirely remove the NEXT line** (starts with `"url"`). **Restart your launcher** then load as normal.
You can verify whether or not it worked by running `.b version` in chat (only valid in Impact). It should print out the version that you downloaded. Note: The version that comes with 4.5 is `v1.2.3`.
## 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"`).
+82
View File
@@ -0,0 +1,82 @@
(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.)
- `click` to click your destination on the screen. left click to path into it, right click to path on top of it. left click and drag to clear an area.
- `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
- `build` to build a schematic. `build blah` will load `schematics/blah.schematic` and build it with the origin being your player feet. `build blah x y z` to set the origin. Any of those can be relative to your player (`~ 69 ~-420` would build at x=player x, y=69, z=player z-420).
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`.
+187 -123
View File
@@ -1,123 +1,187 @@
/* /*
* This file is part of Baritone. * This file is part of Baritone.
* *
* Baritone is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Baritone is distributed in the hope that it will be useful, * Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
group 'baritone' group 'baritone'
version '1.0.0-hotfix-2' version '1.3.1'
buildscript { buildscript {
repositories { repositories {
maven { jcenter()
name = 'forge' maven {
url = 'http://files.minecraftforge.net/maven' name = 'forge'
} url = 'http://files.minecraftforge.net/maven'
maven { }
name = 'SpongePowered' maven {
url = 'http://repo.spongepowered.org/maven' name = 'impactdevelopment-repo'
} url = 'https://impactdevelopment.github.io/maven/'
jcenter() }
} }
dependencies { dependencies {
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT' classpath group: 'com.github.ImpactDevelopment', name: 'ForgeGradle', version: '3.0.115'
classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT' classpath group: 'com.github.ImpactDevelopment', name: 'MixinGradle', version: '0.6.2'
} }
} }
import baritone.gradle.task.CreateDistTask
import baritone.gradle.task.CreateDistTask import baritone.gradle.task.ProguardTask
import baritone.gradle.task.ProguardTask import org.apache.tools.ant.taskdefs.condition.Os
apply plugin: 'java' apply plugin: 'java'
apply plugin: 'net.minecraftforge.gradle.tweaker-client' apply plugin: 'net.minecraftforge.gradle'
apply plugin: 'org.spongepowered.mixin' apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = '1.8'
compileJava { compileJava {
sourceCompatibility = targetCompatibility = '1.8' sourceCompatibility = targetCompatibility = '1.8'
options.encoding = "UTF-8" // allow emoji in comments :^) options.encoding = "UTF-8" // allow emoji in comments :^)
} }
sourceSets { sourceSets {
launch { api {
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output compileClasspath += main.compileClasspath
} }
} main {
compileClasspath += api.output
minecraft { }
version = '1.12.2' test {
mappings = 'stable_39' compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
tweakClass = 'baritone.launch.BaritoneTweaker' runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
runDir = 'run' }
launch {
// The sources jar should use SRG names not MCP to ensure compatibility with all mappings compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
makeObfSourceJar = true runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
} }
}
repositories {
mavenCentral() task sourceJar(type: Jar, dependsOn: classes) {
classifier = 'sources'
maven { from sourceSets.api.allSource
name = 'spongepowered-repo' }
url = 'http://repo.spongepowered.org/maven/'
} minecraft {
mappings channel: 'snapshot', version: '20190307-1.13.1'
maven { reobfMappings 'notch'
name = 'impactdevelopment-repo'
url = 'https://impactdevelopment.github.io/maven/' runs {
} client {
} workingDirectory project.file('run')
source sourceSets.launch
dependencies {
runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2') main 'baritone.launch.LaunchTesting'
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
// Mixin includes a lot of dependencies that are too up-to-date environment 'assetIndex', '{asset_index}'
exclude module: 'launchwrapper' environment 'assetDirectory', downloadAssets.output
exclude module: 'guava' environment 'nativesDirectory', extractNatives.output
exclude module: 'gson'
exclude module: 'commons-io' environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
exclude module: 'log4j-core'
} if (Os.isFamily(Os.FAMILY_MAC)) {
testImplementation 'junit:junit:4.12' jvmArgs "-XstartOnFirstThread"
} }
}
mixin {
defaultObfuscationEnv notch autoTest {
add sourceSets.launch, 'mixins.baritone.refmap.json' workingDirectory project.file('autotest')
} source sourceSets.launch
javadoc { main 'baritone.launch.LaunchTesting'
options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error
options.linkSource true environment 'assetIndex', '{asset_index}'
options.encoding "UTF-8" // allow emoji in comments :^) environment 'assetDirectory', downloadAssets.output
source += sourceSets.api.allJava environment 'nativesDirectory', extractNatives.output
classpath += sourceSets.api.compileClasspath
} environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
environment 'BARITONE_AUTO_TEST', 'true'
jar {
from sourceSets.launch.output, sourceSets.api.output if (Os.isFamily(Os.FAMILY_MAC)) {
preserveFileTimestamps = false jvmArgs "-XstartOnFirstThread"
reproducibleFileOrder = true }
} }
}
task proguard(type: ProguardTask) { }
url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip'
extract 'proguard6.0.3/lib/proguard.jar' repositories {
} mavenCentral()
task createDist(type: CreateDistTask, dependsOn: proguard) maven {
name = 'spongepowered-repo'
build.finalizedBy(createDist) url = 'http://repo.spongepowered.org/maven/'
}
maven {
name = 'impactdevelopment-repo'
url = 'https://impactdevelopment.github.io/maven/'
}
}
dependencies {
minecraft 'com.github.ImpactDevelopment:Vanilla:1.13.2'
runtime launchCompile('net.minecraft:launchwrapper:1.12') {
exclude module: 'lwjgl'
}
runtime launchCompile('org.ow2.asm:asm-debug-all:5.2')
runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2')
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
// Mixin includes a lot of dependencies that are too up-to-date
exclude module: 'launchwrapper'
exclude module: 'guava'
exclude module: 'gson'
exclude module: 'commons-io'
exclude module: 'log4j-core'
}
testImplementation 'junit:junit:4.12'
}
mixin {
defaultObfuscationEnv searge
add sourceSets.launch, 'mixins.baritone.refmap.json'
}
javadoc {
options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error
options.linkSource true
options.encoding "UTF-8" // allow emoji in comments :^)
source = sourceSets.api.allJava
classpath += sourceSets.api.compileClasspath
}
jar {
from sourceSets.launch.output, sourceSets.api.output
preserveFileTimestamps = false
reproducibleFileOrder = true
manifest {
attributes(
'MixinConfigs': 'mixins.baritone.json',
'Implementation-Title': 'Baritone',
'Implementation-Version': version
)
}
}
task proguard(type: ProguardTask) {
url 'https://downloads.sourceforge.net/project/proguard/proguard/6.0/proguard6.0.3.zip'
extract 'proguard6.0.3/lib/proguard.jar'
}
task createDist(type: CreateDistTask, dependsOn: proguard)
build.finalizedBy(createDist)
@@ -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,14 +40,10 @@ 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", ARTIFACT_STANDARD = "%s-%s.jar",
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
TEMP_LIBRARY_DIR = "tempLibraries/", ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
ARTIFACT_STANDARD = "%s-%s.jar",
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
protected String artifactName, artifactVersion; protected String artifactName, artifactVersion;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut; protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
@@ -61,10 +52,10 @@ class BaritoneGradleTask extends DefaultTask {
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.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH); this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
@@ -95,8 +86,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,9 @@ 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));
// NIO will not automatically create directories // NIO will not automatically create directories
Path dir = getRelativeFile("dist/"); Path dir = getRelativeFile("dist/");
@@ -53,9 +53,9 @@ 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);
// 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, standalone, unoptimized)
@@ -18,26 +18,18 @@
package baritone.gradle.task; package baritone.gradle.task;
import baritone.gradle.util.Determinizer; import baritone.gradle.util.Determinizer;
import baritone.gradle.util.MappingType;
import baritone.gradle.util.ReobfWrapper;
import org.apache.commons.io.IOUtils; import org.apache.commons.io.IOUtils;
import org.gradle.api.NamedDomainObjectContainer; import org.gradle.api.plugins.JavaPluginConvention;
import org.gradle.api.artifacts.Configuration;
import org.gradle.api.artifacts.Dependency;
import org.gradle.api.internal.plugins.DefaultConvention;
import org.gradle.api.tasks.Input; import org.gradle.api.tasks.Input;
import org.gradle.api.tasks.TaskAction; import org.gradle.api.tasks.TaskAction;
import org.gradle.internal.Pair;
import java.io.*; import java.io.*;
import java.lang.reflect.Field;
import java.net.URL; import java.net.URL;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; import java.nio.file.Path;
import java.util.*; import java.util.ArrayList;
import java.util.regex.Matcher; import java.util.List;
import java.util.regex.Pattern; import java.util.stream.Stream;
import java.util.stream.Collectors;
import java.util.zip.ZipEntry; import java.util.zip.ZipEntry;
import java.util.zip.ZipFile; import java.util.zip.ZipFile;
@@ -49,16 +41,12 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
*/ */
public class ProguardTask extends BaritoneGradleTask { public class ProguardTask extends BaritoneGradleTask {
private static final Pattern TEMP_LIBRARY_PATTERN = Pattern.compile("-libraryjars 'tempLibraries\\/([a-zA-Z0-9/_\\-\\.]+)\\.jar'");
@Input @Input
private String url; private String url;
@Input @Input
private String extract; private String extract;
private List<String> requiredLibraries;
@TaskAction @TaskAction
protected void exec() throws Exception { protected void exec() throws Exception {
super.verifyArtifacts(); super.verifyArtifacts();
@@ -68,7 +56,6 @@ public class ProguardTask extends BaritoneGradleTask {
downloadProguard(); downloadProguard();
extractProguard(); extractProguard();
generateConfigs(); generateConfigs();
acquireDependencies();
proguardApi(); proguardApi();
proguardStandalone(); proguardStandalone();
cleanup(); cleanup();
@@ -112,6 +99,19 @@ public class ProguardTask extends BaritoneGradleTask {
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", ""); String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
template.add(2, "-libraryjars '" + out + "'"); template.add(2, "-libraryjars '" + out + "'");
// Discover all of the libraries that we will need to acquire from gradle
acquireDependencies().forEach(f -> {
if (f.toString().endsWith("-recomp.jar")) {
// remove MCP mapped jar
return;
}
if (f.toString().endsWith("client-extra.jar")) {
// go from the extra to the original downloaded client
f = new File(f.getParentFile(), "client.jar");
}
template.add(2, "-libraryjars '" + f + "'");
});
// API config doesn't require any changes from the changes that we made to the template // API config doesn't require any changes from the changes that we made to the template
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template); Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
@@ -119,147 +119,10 @@ public class ProguardTask extends BaritoneGradleTask {
List<String> standalone = new ArrayList<>(template); List<String> standalone = new ArrayList<>(template);
standalone.removeIf(s -> s.contains("# this is the keep api")); standalone.removeIf(s -> s.contains("# this is the keep api"));
Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone); Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
// Discover all of the libraries that we will need to acquire from gradle
this.requiredLibraries = new ArrayList<>();
template.forEach(line -> {
if (!line.startsWith("#")) {
Matcher m = TEMP_LIBRARY_PATTERN.matcher(line);
if (m.find()) {
this.requiredLibraries.add(m.group(1));
}
}
});
} }
private void acquireDependencies() throws Exception { private Stream<File> acquireDependencies() {
return getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName("launch").getRuntimeClasspath().getFiles().stream().filter(File::isFile);
// Create a map of all of the dependencies that we are able to access in this project
// Likely a better way to do this, I just pair the dependency with the first valid configuration
Map<String, Pair<Configuration, Dependency>> dependencyLookupMap = new HashMap<>();
getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config ->
config.getAllDependencies().forEach(dependency ->
dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency))));
// Create the directory if it doesn't already exist
Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR);
if (!Files.exists(tempLibraries)) {
Files.createDirectory(tempLibraries);
}
// Iterate the required libraries to copy them to tempLibraries
for (String lib : this.requiredLibraries) {
// copy from the forgegradle cache
if (lib.equals("minecraft")) {
Path cachedJar = getMinecraftJar();
Path inTempDir = getTemporaryFile("tempLibraries/minecraft.jar");
// TODO: maybe try not to copy every time
Files.copy(cachedJar, inTempDir, REPLACE_EXISTING);
continue;
}
// Find a configuration/dependency pair that matches the desired library
Pair<Configuration, Dependency> pair = null;
for (Map.Entry<String, Pair<Configuration, Dependency>> entry : dependencyLookupMap.entrySet()) {
if (entry.getKey().startsWith(lib)) {
pair = entry.getValue();
}
}
// The pair must be non-null
Objects.requireNonNull(pair);
// Find the library jar file, and copy it to tempLibraries
for (File file : pair.getLeft().files(pair.getRight())) {
if (file.getName().startsWith(lib)) {
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
}
}
}
}
// a bunch of epic stuff to get the path to the cached jar
private Path getMinecraftJar() throws Exception {
MappingType mappingType;
try {
mappingType = getMappingType();
} catch (Exception e) {
System.err.println("Failed to get mapping type, assuming NOTCH.");
mappingType = MappingType.NOTCH;
}
String suffix;
switch (mappingType) {
case NOTCH:
suffix = "";
break;
case SEARGE:
suffix = "-srgBin";
break;
case CUSTOM:
throw new IllegalStateException("Custom mappings not supported!");
default:
throw new IllegalStateException("Unknown mapping type: " + mappingType);
}
DefaultConvention convention = (DefaultConvention) this.getProject().getConvention();
Object extension = convention.getAsMap().get("minecraft");
Objects.requireNonNull(extension);
// for some reason cant use Class.forName
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed
Field f_replacer = class_baseExtension.getDeclaredField("replacer");
f_replacer.setAccessible(true);
Object replacer = f_replacer.get(extension);
Class<?> class_replacementProvider = replacer.getClass();
Field replacement_replaceMap = class_replacementProvider.getDeclaredField("replaceMap");
replacement_replaceMap.setAccessible(true);
Map<String, Object> replacements = (Map) replacement_replaceMap.get(replacer);
String cacheDir = replacements.get("CACHE_DIR").toString() + "/net/minecraft";
String mcVersion = replacements.get("MC_VERSION").toString();
String mcpInsert = replacements.get("MAPPING_CHANNEL").toString() + "/" + replacements.get("MAPPING_VERSION").toString();
String fullJarName = "minecraft-" + mcVersion + suffix + ".jar";
String baseDir = String.format("%s/minecraft/%s/", cacheDir, mcVersion);
String jarPath;
if (mappingType == MappingType.SEARGE) {
jarPath = String.format("%s/%s/%s", baseDir, mcpInsert, fullJarName);
} else {
jarPath = baseDir + fullJarName;
}
jarPath = jarPath
.replace("/", File.separator)
.replace("\\", File.separator); // hecking regex
return new File(jarPath).toPath();
}
// throws IllegalStateException if mapping type is ambiguous or it fails to find it
private MappingType getMappingType() {
// if it fails to find this then its probably a forgegradle version problem
Set<Object> reobf = (NamedDomainObjectContainer<Object>) this.getProject().getExtensions().getByName("reobf");
List<MappingType> mappingTypes = getUsedMappingTypes(reobf);
long mappingTypesUsed = mappingTypes.size();
if (mappingTypesUsed == 0) {
throw new IllegalStateException("Failed to find mapping type (no jar task?)");
}
if (mappingTypesUsed > 1) {
throw new IllegalStateException("Ambiguous mapping type (multiple jars with different mapping types?)");
}
return mappingTypes.get(0);
}
private List<MappingType> getUsedMappingTypes(Set<Object> reobf) {
return reobf.stream()
.map(ReobfWrapper::new)
.map(ReobfWrapper::getMappingType)
.distinct()
.collect(Collectors.toList());
} }
private void proguardApi() throws Exception { private void proguardApi() throws Exception {
@@ -298,8 +161,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 +171,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();
@@ -1,63 +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.gradle.util;
import java.lang.reflect.Field;
import java.util.Objects;
/**
* All credits go to AsmLibGradle and its contributors.
*
* @see <a href="https://github.com/pozzed/AsmLibGradle/blob/8f917dbc3939eab7a3d9daf54d9d285fdf34f4b2/src/main/java/net/futureclient/asmlib/forgegradle/ReobfWrapper.java">Original Source</a>
*/
public class ReobfWrapper {
private final Object instance;
private final Class<?> type;
public ReobfWrapper(Object instance) {
this.instance = instance;
Objects.requireNonNull(instance);
this.type = instance.getClass();
}
public String getName() {
try {
Field nameField = type.getDeclaredField("name");
nameField.setAccessible(true);
return (String) nameField.get(this.instance);
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}
public MappingType getMappingType() {
try {
Field enumField = type.getDeclaredField("mappingType");
enumField.setAccessible(true);
Enum<?> aEnum = (Enum<?>) enumField.get(this.instance);
MappingType mappingType = MappingType.values()[aEnum.ordinal()];
if (!aEnum.name().equals(mappingType.name())) {
throw new IllegalStateException("ForgeGradle ReobfMappingType is not equivalent to MappingType (version error?)");
}
return mappingType;
} catch (ReflectiveOperationException ex) {
throw new IllegalStateException(ex);
}
}
}
+6 -6
View File
@@ -1,6 +1,6 @@
#Tue Jul 31 21:56:56 PDT 2018 #Tue Jul 31 21:56:56 PDT 2018
distributionBase=GRADLE_USER_HOME distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip distributionUrl=https\://services.gradle.org/distributions/gradle-4.9-all.zip
Vendored
+84 -84
View File
@@ -1,84 +1,84 @@
@if "%DEBUG%" == "" @echo off @if "%DEBUG%" == "" @echo off
@rem ########################################################################## @rem ##########################################################################
@rem @rem
@rem Gradle startup script for Windows @rem Gradle startup script for Windows
@rem @rem
@rem ########################################################################## @rem ##########################################################################
@rem Set local scope for the variables with windows NT shell @rem Set local scope for the variables with windows NT shell
if "%OS%"=="Windows_NT" setlocal if "%OS%"=="Windows_NT" setlocal
set DIRNAME=%~dp0 set DIRNAME=%~dp0
if "%DIRNAME%" == "" set DIRNAME=. if "%DIRNAME%" == "" set DIRNAME=.
set APP_BASE_NAME=%~n0 set APP_BASE_NAME=%~n0
set APP_HOME=%DIRNAME% set APP_HOME=%DIRNAME%
@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script. @rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
set DEFAULT_JVM_OPTS= set DEFAULT_JVM_OPTS=
@rem Find java.exe @rem Find java.exe
if defined JAVA_HOME goto findJavaFromJavaHome if defined JAVA_HOME goto findJavaFromJavaHome
set JAVA_EXE=java.exe set JAVA_EXE=java.exe
%JAVA_EXE% -version >NUL 2>&1 %JAVA_EXE% -version >NUL 2>&1
if "%ERRORLEVEL%" == "0" goto init if "%ERRORLEVEL%" == "0" goto init
echo. echo.
echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH. echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
echo. echo.
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. echo location of your Java installation.
goto fail goto fail
:findJavaFromJavaHome :findJavaFromJavaHome
set JAVA_HOME=%JAVA_HOME:"=% set JAVA_HOME=%JAVA_HOME:"=%
set JAVA_EXE=%JAVA_HOME%/bin/java.exe set JAVA_EXE=%JAVA_HOME%/bin/java.exe
if exist "%JAVA_EXE%" goto init if exist "%JAVA_EXE%" goto init
echo. echo.
echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME% echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
echo. echo.
echo Please set the JAVA_HOME variable in your environment to match the echo Please set the JAVA_HOME variable in your environment to match the
echo location of your Java installation. echo location of your Java installation.
goto fail goto fail
:init :init
@rem Get command-line arguments, handling Windows variants @rem Get command-line arguments, handling Windows variants
if not "%OS%" == "Windows_NT" goto win9xME_args if not "%OS%" == "Windows_NT" goto win9xME_args
:win9xME_args :win9xME_args
@rem Slurp the command line arguments. @rem Slurp the command line arguments.
set CMD_LINE_ARGS= set CMD_LINE_ARGS=
set _SKIP=2 set _SKIP=2
:win9xME_args_slurp :win9xME_args_slurp
if "x%~1" == "x" goto execute if "x%~1" == "x" goto execute
set CMD_LINE_ARGS=%* set CMD_LINE_ARGS=%*
:execute :execute
@rem Setup the command line @rem Setup the command line
set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
@rem Execute Gradle @rem Execute Gradle
"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS% "%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %CMD_LINE_ARGS%
:end :end
@rem End local scope for the variables with windows NT shell @rem End local scope for the variables with windows NT shell
if "%ERRORLEVEL%"=="0" goto mainEnd if "%ERRORLEVEL%"=="0" goto mainEnd
:fail :fail
rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
rem the _cmd.exe /c_ return code! rem the _cmd.exe /c_ return code!
if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1 if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
exit /b 1 exit /b 1
:mainEnd :mainEnd
if "%OS%"=="Windows_NT" endlocal if "%OS%"=="Windows_NT" endlocal
:omega :omega
+5 -53
View File
@@ -12,15 +12,17 @@
-flattenpackagehierarchy -flattenpackagehierarchy
-repackageclasses 'baritone' -repackageclasses 'baritone'
# lwjgl is weird
-dontwarn org.lwjgl.**
# also lwjgl lol
-dontwarn module-info
-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>;
@@ -29,56 +31,6 @@
# need to keep mixin names # need to keep mixin names
-keep class baritone.launch.** { *; } -keep class baritone.launch.** { *; }
# copy all necessary libraries into tempLibraries to build
# The correct jar will be copied from the forgegradle cache based on the mapping type being compiled with
-libraryjars 'tempLibraries/minecraft.jar'
-libraryjars 'tempLibraries/SimpleTweaker-1.2.jar'
-libraryjars 'tempLibraries/authlib-1.5.25.jar'
-libraryjars 'tempLibraries/codecjorbis-20101023.jar'
-libraryjars 'tempLibraries/codecwav-20101023.jar'
-libraryjars 'tempLibraries/commons-codec-1.10.jar'
-libraryjars 'tempLibraries/commons-compress-1.8.1.jar'
-libraryjars 'tempLibraries/commons-io-2.5.jar'
-libraryjars 'tempLibraries/commons-lang3-3.5.jar'
-libraryjars 'tempLibraries/commons-logging-1.1.3.jar'
-libraryjars 'tempLibraries/fastutil-7.1.0.jar'
-libraryjars 'tempLibraries/gson-2.8.0.jar'
-libraryjars 'tempLibraries/guava-21.0.jar'
-libraryjars 'tempLibraries/httpclient-4.3.3.jar'
-libraryjars 'tempLibraries/httpcore-4.3.2.jar'
-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar'
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
-libraryjars 'tempLibraries/jna-4.4.0.jar'
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
-libraryjars 'tempLibraries/jsr305-3.0.1.jar'
-libraryjars 'tempLibraries/jutils-1.0.0.jar'
-libraryjars 'tempLibraries/libraryjavasound-20101123.jar'
-libraryjars 'tempLibraries/librarylwjglopenal-20100824.jar'
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
-libraryjars 'tempLibraries/log4j-core-2.8.1.jar'
# startsWith is used to check the library, and mac/linux differ in which version they use
# this is FINE
-libraryjars 'tempLibraries/lwjgl-.jar'
-libraryjars 'tempLibraries/lwjgl_util-.jar'
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
-libraryjars 'tempLibraries/oshi-core-1.1.jar'
-libraryjars 'tempLibraries/patchy-1.1.jar'
-libraryjars 'tempLibraries/platform-3.4.0.jar'
-libraryjars 'tempLibraries/realms-1.10.22.jar'
-libraryjars 'tempLibraries/soundsystem-20120107.jar'
-libraryjars 'tempLibraries/text2speech-1.10.3.jar'
-libraryjars 'tempLibraries/mixin-0.7.11-SNAPSHOT.jar'
-libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist?
# Keep - Applications. Keep all application classes, along with their 'main' # Keep - Applications. Keep all application classes, along with their 'main'
# methods. # methods.
-keepclasseswithmembers public class * { -keepclasseswithmembers public class * {
+19 -19
View File
@@ -1,19 +1,19 @@
/* /*
* This file is part of Baritone. * This file is part of Baritone.
* *
* Baritone is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Baritone is distributed in the hope that it will be useful, * Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
rootProject.name = 'baritone' rootProject.name = 'baritone'
+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
+62 -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,72 @@ 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 IBuilderProcess} instance
* @see IBuilderProcess
*/
IBuilderProcess getBuilderProcess();
/**
* @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;
} }
/** /**
+150 -21
View File
@@ -17,9 +17,11 @@
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;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.text.ITextComponent; import net.minecraft.util.text.ITextComponent;
import java.awt.*; import java.awt.*;
@@ -29,7 +31,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
*/ */
@@ -57,7 +59,9 @@ public final class Settings {
/** /**
* It doesn't actually take twenty ticks to place a block, this cost is so high * It doesn't actually take twenty ticks to place a block, this cost is so high
* because we want to generally conserve blocks which might be limited * because we want to generally conserve blocks which might be limited.
* <p>
* Decrease to make Baritone more often consider paths that would require placing blocks
*/ */
public final Setting<Double> blockPlacementPenalty = new Setting<>(20D); public final Setting<Double> blockPlacementPenalty = new Setting<>(20D);
@@ -90,6 +94,11 @@ public final class Settings {
*/ */
public final Setting<Boolean> assumeWalkOnWater = new Setting<>(false); public final Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
/**
* If you have Fire Resistance and Jesus then I guess you could turn this on lol
*/
public final Setting<Boolean> assumeWalkOnLava = new Setting<>(false);
/** /**
* Assume step functionality; don't jump on an Ascend. * Assume step functionality; don't jump on an Ascend.
*/ */
@@ -107,7 +116,7 @@ public final class Settings {
/** /**
* If true, parkour is allowed to make jumps when standing on blocks at the maximum height, so player feet is y=256 * If true, parkour is allowed to make jumps when standing on blocks at the maximum height, so player feet is y=256
* <p> * <p>
* Defaults to false because this fails on constantiam * Defaults to false because this fails on constantiam. Please let me know if this is ever disabled. Please.
*/ */
public final Setting<Boolean> allowJumpAt256 = new Setting<>(false); public final Setting<Boolean> allowJumpAt256 = new Setting<>(false);
@@ -120,13 +129,20 @@ public final class Settings {
*/ */
public final Setting<Boolean> allowDiagonalDescend = new Setting<>(false); public final Setting<Boolean> allowDiagonalDescend = new Setting<>(false);
/**
* Allow mining the block directly beneath its feet
* <p>
* Turn this off to force it to make more staircases and less shafts
*/
public final Setting<Boolean> allowDownward = new Setting<>(true);
/** /**
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.) * Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
*/ */
public final Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList( public final Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
Item.getItemFromBlock(Blocks.DIRT), Blocks.DIRT.asItem(),
Item.getItemFromBlock(Blocks.COBBLESTONE), Blocks.COBBLESTONE.asItem(),
Item.getItemFromBlock(Blocks.NETHERRACK) Blocks.NETHERRACK.asItem()
))); )));
/** /**
@@ -164,6 +180,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 +303,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 +334,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 +406,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
@@ -404,6 +439,11 @@ public final class Settings {
*/ */
public final Setting<Boolean> renderGoal = new Setting<>(true); public final Setting<Boolean> renderGoal = new Setting<>(true);
/**
* Render selection boxes
*/
public final Setting<Boolean> renderSelectionBoxes = new Setting<>(true);
/** /**
* Ignore depth when rendering the goal * Ignore depth when rendering the goal
*/ */
@@ -459,10 +499,42 @@ 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 or MineProcess fails to calculate a path, instead of just giving up, mark the closest instance
* of that block as "unreachable" and go towards the next closest. GetToBlock expands this seaarch to the whole "vein"; MineProcess does not.
* This is because MineProcess finds individual impossible blocks (like one block in a vein that has gravel on top then lava, so it can't break)
* Whereas GetToBlock should blacklist the whole "vein" if it can't get to any of them.
*/
public final Setting<Boolean> blacklistClosestOnFailure = 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 +557,31 @@ public final class Settings {
*/ */
public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5); public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
/**
* After finding this many instances of the target block in the cache, it will stop expanding outward the chunk search.
*/
public final Setting<Integer> maxCachedWorldScanCount = new Setting<>(10);
/**
* 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);
/**
* Don't consider the next layer in builder until the current one is done
*/
public final Setting<Boolean> buildInLayers = new Setting<>(false);
/**
* How far to move before repeating the build. -1 for the size of the build in that axis. 0 to disable
*/
public final Setting<Integer> buildRepeatDistance=new Setting<>(0);
/**
* What direction te repeat the build in
*/
public final Setting<EnumFacing> buildRepeatDirection = new Setting<>(EnumFacing.NORTH);
/** /**
* 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)?
*/ */
@@ -510,6 +607,11 @@ public final class Settings {
*/ */
public final Setting<Integer> axisHeight = new Setting<>(120); public final Setting<Integer> axisHeight = new Setting<>(120);
/**
* Disconnect from the server upon arriving at your goal
*/
public final Setting<Boolean> disconnectOnArrival = new Setting<>(false);
/** /**
* Disallow MineBehavior from using X-Ray to see where the ores are. Turn this option on to force it to mine "legit" * Disallow MineBehavior from using X-Ray to see where the ores are. Turn this option on to force it to mine "legit"
* where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player * where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player
@@ -522,6 +624,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
@@ -552,6 +667,13 @@ public final class Settings {
*/ */
public final Setting<Integer> followRadius = new Setting<>(3); public final Setting<Integer> followRadius = new Setting<>(3);
/**
* true = exploration uses pythagorean distance to choose closest uncached chunk
* <p>
* false = exploration uses manhattan / taxicab distance to choose
*/
public final Setting<Boolean> exploreUsePythagorean = new Setting<>(false);
/** /**
* Cached chunks (regardless of if they're in RAM or saved to disk) expire and are deleted after this number of seconds * Cached chunks (regardless of if they're in RAM or saved to disk) expire and are deleted after this number of seconds
* -1 to disable * -1 to disable
@@ -579,7 +701,7 @@ public final class Settings {
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting * via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
* {@link Setting#value}; * {@link Setting#value};
*/ */
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage); public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getInstance().ingameGUI.getChatGUI()::printChatMessage);
/** /**
* The color of the current path * The color of the current path
@@ -632,13 +754,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;
@@ -654,9 +770,14 @@ public final class Settings {
this.klass = (Class<T>) value.getClass(); this.klass = (Class<T>) value.getClass();
} }
@SuppressWarnings("unchecked") /**
public final <K extends T> K get() { * Deprecated! Please use .value directly instead
return (K) value; *
* @return the current setting value
*/
@Deprecated
public final T get() {
return value;
} }
public final String getName() { public final String getName() {
@@ -667,8 +788,16 @@ public final class Settings {
return klass; return klass;
} }
@Override
public String toString() { public String toString() {
return name + ": " + value; return SettingsUtil.settingToString(this);
}
/**
* Reset this setting to its default value
*/
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));
} }
/** /**
+2 -2
View File
@@ -20,7 +20,7 @@ package baritone.api.cache;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import java.util.LinkedList; import java.util.ArrayList;
/** /**
* @author Brady * @author Brady
@@ -68,7 +68,7 @@ public interface ICachedWorld {
* @param maxRegionDistanceSq The maximum region distance, squared * @param maxRegionDistanceSq The maximum region distance, squared
* @return The locations found that match the special block * @return The locations found that match the special block
*/ */
LinkedList<BlockPos> getLocationsOf(String block, int maximum, int centerX, int centerZ, int maxRegionDistanceSq); ArrayList<BlockPos> getLocationsOf(String block, int maximum, int centerX, int centerZ, int maxRegionDistanceSq);
/** /**
* Reloads all of the cached regions in this world from disk. Anything that is not saved * Reloads all of the cached regions in this world from disk. Anything that is not saved
@@ -18,12 +18,11 @@
package baritone.api.event.listener; package baritone.api.event.listener;
import baritone.api.event.events.*; import baritone.api.event.events.*;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiGameOver; import net.minecraft.client.gui.GuiGameOver;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.WorldClient; import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.network.Packet; import net.minecraft.network.Packet;
@@ -45,7 +44,7 @@ public interface IGameEventListener {
* Run once per game tick from before and after the player rotation is sent to the server. * Run once per game tick from before and after the player rotation is sent to the server.
* *
* @param event The event * @param event The event
* @see EntityPlayerSP#onUpdate() * @see EntityPlayerSP#tick()
*/ */
void onPlayerUpdate(PlayerUpdateEvent event); void onPlayerUpdate(PlayerUpdateEvent event);
@@ -61,14 +60,11 @@ public interface IGameEventListener {
* Runs before and after whenever a chunk is either loaded, unloaded, or populated. * Runs before and after whenever a chunk is either loaded, unloaded, or populated.
* *
* @param event The event * @param event The event
* @see WorldClient#doPreChunk(int, int, boolean)
*/ */
void onChunkEvent(ChunkEvent event); void onChunkEvent(ChunkEvent event);
/** /**
* Runs once per world render pass. Two passes are made when {@link GameSettings#anaglyph} is on. * Runs once per world render pass.
* <p>
* <b>Note:</b> {@link GameSettings#anaglyph} has been removed in Minecraft 1.13
* *
* @param event The event * @param event The event
*/ */
@@ -78,7 +74,7 @@ public interface IGameEventListener {
* Runs before and after whenever a new world is loaded * Runs before and after whenever a new world is loaded
* *
* @param event The event * @param event The event
* @see Minecraft#loadWorld(WorldClient, String) * @see Minecraft#loadWorld(WorldClient, GuiScreen)
*/ */
void onWorldEvent(WorldEvent event); void onWorldEvent(WorldEvent event);
@@ -87,7 +83,6 @@ public interface IGameEventListener {
* *
* @param event The event * @param event The event
* @see Packet * @see Packet
* @see GenericFutureListener
*/ */
void onSendPacket(PacketEvent event); void onSendPacket(PacketEvent event);
@@ -96,7 +91,6 @@ public interface IGameEventListener {
* *
* @param event The event * @param event The event
* @see Packet * @see Packet
* @see GenericFutureListener
*/ */
void onReceivePacket(PacketEvent event); void onReceivePacket(PacketEvent event);
@@ -110,10 +104,10 @@ public interface IGameEventListener {
void onPlayerRotationMove(RotationMoveEvent event); void onPlayerRotationMove(RotationMoveEvent event);
/** /**
* Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#onLivingUpdate} * Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#livingTick}
* *
* @param event The event * @param event The event
* @see EntityPlayerSP#onLivingUpdate() * @see EntityPlayerSP#livingTick()
*/ */
void onPlayerSprintState(SprintStateEvent event); void onPlayerSprintState(SprintStateEvent event);
@@ -25,7 +25,7 @@ public class GoalAxis implements Goal {
@Override @Override
public boolean isInGoal(int x, int y, int z) { public boolean isInGoal(int x, int y, int z) {
return y == BaritoneAPI.getSettings().axisHeight.get() && (x == 0 || z == 0 || Math.abs(x) == Math.abs(z)); return y == BaritoneAPI.getSettings().axisHeight.value && (x == 0 || z == 0 || Math.abs(x) == Math.abs(z));
} }
@Override @Override
@@ -39,7 +39,7 @@ public class GoalAxis implements Goal {
double flatAxisDistance = Math.min(x, Math.min(z, diff * SQRT_2_OVER_2)); double flatAxisDistance = Math.min(x, Math.min(z, diff * SQRT_2_OVER_2));
return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.get() + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.get(), y); return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.value + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.value, y);
} }
@Override @Override
@@ -30,17 +30,17 @@ public class GoalBlock implements Goal, IGoalRenderPos {
/** /**
* The X block position of this goal * The X block position of this goal
*/ */
private final int x; public final int x;
/** /**
* The Y block position of this goal * The Y block position of this goal
*/ */
private final int y; public final int y;
/** /**
* The Z block position of this goal * The Z block position of this goal
*/ */
private final int z; public final int z;
public GoalBlock(BlockPos pos) { public GoalBlock(BlockPos pos) {
this(pos.getX(), pos.getY(), pos.getZ()); this(pos.getX(), pos.getY(), pos.getZ());
@@ -28,9 +28,9 @@ import net.minecraft.util.math.BlockPos;
*/ */
public class GoalGetToBlock implements Goal, IGoalRenderPos { public class GoalGetToBlock implements Goal, IGoalRenderPos {
private final int x; public final int x;
private final int y; public final int y;
private final int z; public final int z;
public GoalGetToBlock(BlockPos pos) { public GoalGetToBlock(BlockPos pos) {
this.x = pos.getX(); this.x = pos.getX();
@@ -61,6 +61,6 @@ public class GoalNear implements Goal, IGoalRenderPos {
", y=" + y + ", y=" + y +
", z=" + z + ", z=" + z +
", rangeSq=" + rangeSq + ", rangeSq=" + rangeSq +
'}'; "}";
} }
} }
@@ -0,0 +1,76 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.goals;
import baritone.api.BaritoneAPI;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
/**
* Dig a tunnel in a certain direction, but if you have to deviate from the path, go back to where you started
*/
public class GoalStrictDirection implements Goal {
public final int x;
public final int y;
public final int z;
public final int dx;
public final int dz;
public GoalStrictDirection(BlockPos origin, EnumFacing direction) {
x = origin.getX();
y = origin.getY();
z = origin.getZ();
dx = direction.getXOffset();
dz = direction.getZOffset();
if (dx == 0 && dz == 0) {
throw new IllegalArgumentException(direction + "");
}
}
@Override
public boolean isInGoal(int x, int y, int z) {
return false;
}
@Override
public double heuristic(int x, int y, int z) {
int distanceFromStartInDesiredDirection = (x - this.x) * dx + (z - this.z) * dz;
int distanceFromStartInIncorrectDirection = Math.abs((x - this.x) * dz) + Math.abs((z - this.z) * dx);
int verticalDistanceFromStart = Math.abs(y - this.y);
// we want heuristic to decrease as desiredDirection increases
double heuristic = -distanceFromStartInDesiredDirection * 100;
heuristic += distanceFromStartInIncorrectDirection * 1000;
heuristic += verticalDistanceFromStart * 1000;
return heuristic;
}
@Override
public String toString() {
return "GoalStrictDirection{" +
"x=" + x +
", y=" + y +
", z=" + z +
", dx=" + dx +
", dz=" + dz +
"}";
}
}
@@ -80,7 +80,7 @@ public class GoalXZ implements Goal {
diagonal = z; diagonal = z;
} }
diagonal *= SQRT_2; diagonal *= SQRT_2;
return (diagonal + straight) * BaritoneAPI.getSettings().costHeuristic.get(); // big TODO tune return (diagonal + straight) * BaritoneAPI.getSettings().costHeuristic.value; // big TODO tune
} }
public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) { public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) {
@@ -45,10 +45,6 @@ public interface IMovement {
*/ */
boolean safeToCancel(); boolean safeToCancel();
double recalculateCost();
double calculateCostWithoutCaching();
boolean calculatedWhileLoaded(); boolean calculatedWhileLoaded();
BetterBlockPos getSrc(); BetterBlockPos getSrc();
@@ -35,6 +35,16 @@ import baritone.api.event.events.PathEvent;
*/ */
public interface IBaritoneProcess { public interface IBaritoneProcess {
/**
* Default priority. Most normal processes should have this value.
* <p>
* Some examples of processes that should have different values might include some kind of automated mob avoidance
* that would be temporary and would forcefully take control. Same for something that pauses pathing for auto eat, etc.
* <p>
* The value is -1 beacuse that's what Impact 4.5's beta auto walk returns and I want to tie with it.
*/
double DEFAULT_PRIORITY = -1;
/** /**
* Would this process like to be in control? * Would this process like to be in control?
* *
@@ -82,12 +92,23 @@ public interface IBaritoneProcess {
* *
* @return A double representing the priority * @return A double representing the priority
*/ */
double priority(); default double priority() {
return DEFAULT_PRIORITY;
}
/** /**
* Returns a user-friendly name for this process. Suitable for a HUD. * Returns a user-friendly name for this process. Suitable for a HUD.
* *
* @return A display name that's suitable for a HUD * @return A display name that's suitable for a HUD
*/ */
String displayName(); default String displayName() {
if (!isActive()) {
// i love it when impcat's scuffed HUD calls displayName for inactive processes for 1 tick too long
// causing NPEs when the displayname relies on fields that become null when inactive
return "INACTIVE";
}
return displayName0();
}
String displayName0();
} }
@@ -0,0 +1,49 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.process;
import baritone.api.utils.ISchematic;
import net.minecraft.util.math.Vec3i;
import java.io.File;
/**
* @author Brady
* @since 1/15/2019
*/
public interface IBuilderProcess extends IBaritoneProcess {
/**
* Requests a build for the specified schematic, labeled as specified, with the specified origin.
*
* @param name A user-friendly name for the schematic
* @param schematic The object representation of the schematic
* @param origin The origin position of the schematic being built
*/
void build(String name, ISchematic schematic, Vec3i origin);
/**
* Requests a build for the specified schematic, labeled as specified, with the specified origin.
*
* @param name A user-friendly name for the schematic
* @param schematic The file path of the schematic
* @param origin The origin position of the schematic being built
* @return Whether or not the schematic was able to load from file
*/
boolean build(String name, File schematic, Vec3i origin);
}
@@ -53,4 +53,9 @@ public class PathingCommand {
this.goal = goal; this.goal = goal;
this.commandType = commandType; this.commandType = commandType;
} }
@Override
public String toString() {
return commandType + " " + goal;
}
} }
@@ -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);
@@ -71,7 +71,7 @@ public interface IPlayerContext {
* @return The position of the highlighted block * @return The position of the highlighted block
*/ */
default Optional<BlockPos> getSelectedBlock() { default Optional<BlockPos> getSelectedBlock() {
if (objectMouseOver() != null && objectMouseOver().typeOfHit == RayTraceResult.Type.BLOCK) { if (objectMouseOver() != null && objectMouseOver().type == RayTraceResult.Type.BLOCK) {
return Optional.of(objectMouseOver().getBlockPos()); return Optional.of(objectMouseOver().getBlockPos());
} }
return Optional.empty(); return Optional.empty();
@@ -83,8 +83,8 @@ public interface IPlayerContext {
* @return The entity * @return The entity
*/ */
default Optional<Entity> getSelectedEntity() { default Optional<Entity> getSelectedEntity() {
if (objectMouseOver() != null && objectMouseOver().typeOfHit == RayTraceResult.Type.ENTITY) { if (objectMouseOver() != null && objectMouseOver().type == RayTraceResult.Type.ENTITY) {
return Optional.of(objectMouseOver().entityHit); return Optional.of(objectMouseOver().entity);
} }
return Optional.empty(); return Optional.empty();
} }
@@ -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,8 @@ 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);
EnumActionResult processRightClick(EntityPlayerSP player, World world, EnumHand hand);
} }
@@ -0,0 +1,85 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
/**
* Basic representation of a schematic. Provides the dimensions and
* the desired statefor a given position relative to the origin.
*
* @author leijurv
*/
public interface ISchematic {
/**
* Does the block at this coordinate matter to the schematic?
* <p>
* Normally just a check for if the coordinate is in the cube.
* <p>
* However, in the case of something like a map art, anything that's below the level of the map art doesn't matter,
* so this function should return false in that case. (i.e. it doesn't really have to be air below the art blocks)
*
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @return Whether or not the specified position is within the bounds of this schematic
*/
default boolean inSchematic(int x, int y, int z) {
return x >= 0 && x < widthX() && y >= 0 && y < heightY() && z >= 0 && z < lengthZ();
}
default int size(EnumFacing.Axis axis) {
switch (axis) {
case X:
return widthX();
case Y:
return heightY();
case Z:
return lengthZ();
default:
throw new UnsupportedOperationException(axis + "");
}
}
/**
* Returns the desired block state at a given (X, Y, Z) position relative to the origin (0, 0, 0).
*
* @param x The x position of the block, relative to the origin
* @param y The y position of the block, relative to the origin
* @param z The z position of the block, relative to the origin
* @return The desired block state at the specified position
*/
IBlockState desiredState(int x, int y, int z);
/**
* @return The width (X axis length) of this schematic
*/
int widthX();
/**
* @return The height (Y axis length) of this schematic
*/
int heightY();
/**
* @return The length (Z axis length) of this schematic
*/
int lengthZ();
}
@@ -18,6 +18,7 @@
package baritone.api.utils; package baritone.api.utils;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.math.RayTraceFluidMode;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -40,13 +41,13 @@ public final class RayTraceUtils {
* @return The calculated raytrace result * @return The calculated raytrace result
*/ */
public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) { public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) {
Vec3d start = entity.getPositionEyes(1.0F); Vec3d start = entity.getEyePosition(1.0F);
Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation); Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation);
Vec3d end = start.add( Vec3d end = start.add(
direction.x * blockReachDistance, direction.x * blockReachDistance,
direction.y * blockReachDistance, direction.y * blockReachDistance,
direction.z * blockReachDistance direction.z * blockReachDistance
); );
return entity.world.rayTraceBlocks(start, end, false, false, true); return entity.world.rayTraceBlocks(start, end, RayTraceFluidMode.NEVER, false, true);
} }
} }
+14 -2
View File
@@ -36,6 +36,9 @@ public class Rotation {
public Rotation(float yaw, float pitch) { public Rotation(float yaw, float pitch) {
this.yaw = yaw; this.yaw = yaw;
this.pitch = pitch; this.pitch = pitch;
if (Float.isInfinite(yaw) || Float.isNaN(yaw) || Float.isInfinite(pitch) || Float.isNaN(pitch)) {
throw new IllegalStateException(yaw + " " + pitch);
}
} }
/** /**
@@ -117,8 +120,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 +154,9 @@ public class Rotation {
} }
return newYaw; return newYaw;
} }
@Override
public String toString() {
return "Yaw: " + yaw + ", Pitch: " + pitch;
}
} }
@@ -23,7 +23,13 @@ import net.minecraft.block.BlockFire;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.math.*; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.util.math.shapes.VoxelShapes;
import java.util.Optional; import java.util.Optional;
@@ -78,6 +84,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 +111,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]);
@@ -171,11 +180,14 @@ public final class RotationUtils {
} }
IBlockState state = entity.world.getBlockState(pos); IBlockState state = entity.world.getBlockState(pos);
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos); VoxelShape shape = state.getShape(entity.world, pos);
if (shape.isEmpty()) {
shape = VoxelShapes.fullCube();
}
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) { for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x); double xDiff = shape.getStart(EnumFacing.Axis.X) * sideOffset.x + shape.getEnd(EnumFacing.Axis.X) * (1 - sideOffset.x);
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y); double yDiff = shape.getStart(EnumFacing.Axis.Y) * sideOffset.y + shape.getEnd(EnumFacing.Axis.Y) * (1 - sideOffset.y);
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z); double zDiff = shape.getStart(EnumFacing.Axis.Z) * sideOffset.z + shape.getEnd(EnumFacing.Axis.Z) * (1 - sideOffset.z);
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance); possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance);
if (possibleRotation.isPresent()) { if (possibleRotation.isPresent()) {
return possibleRotation; return possibleRotation;
@@ -196,10 +208,10 @@ 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.getEyePosition(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.type == RayTraceResult.Type.BLOCK) {
if (result.getBlockPos().equals(pos)) { if (result.getBlockPos().equals(pos)) {
return Optional.of(rotation); return Optional.of(rotation);
} }
@@ -18,8 +18,11 @@
package baritone.api.utils; package baritone.api.utils;
import baritone.api.Settings; import baritone.api.Settings;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.IRegistry;
import java.awt.*; import java.awt.*;
import java.io.BufferedReader; import java.io.BufferedReader;
@@ -27,10 +30,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;
@@ -38,11 +39,9 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static net.minecraft.client.Minecraft.getMinecraft;
public class SettingsUtil { public class SettingsUtil {
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt"); private static final Path SETTINGS_PATH = Minecraft.getInstance().gameDir.toPath().resolve("baritone").resolve("settings.txt");
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces
private static final Map<Class<?>, SettingsIO> map; private static final Map<Class<?>, SettingsIO> map;
@@ -89,22 +88,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 +97,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.value == 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.value);
}
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");
@@ -133,8 +147,9 @@ public class SettingsUtil {
FLOAT(Float.class, Float::parseFloat), FLOAT(Float.class, Float::parseFloat),
LONG(Long.class, Long::parseLong), LONG(Long.class, Long::parseLong),
ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(Item::getByNameOrId).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList<Item>) list).stream().map(Item.REGISTRY::getNameForObject).map(ResourceLocation::toString).collect(Collectors.joining(","))), ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(ResourceLocation::new).map(IRegistry.ITEM::get).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList<Item>) list).stream().map(IRegistry.ITEM::getKey).map(ResourceLocation::toString).collect(Collectors.joining(","))),
COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()); COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()),
ENUMFACING(EnumFacing.class, EnumFacing::byName);
Class<?> klass; Class<?> klass;
+12 -5
View File
@@ -20,9 +20,10 @@ package baritone.api.utils;
import net.minecraft.block.BlockFire; import net.minecraft.block.BlockFire;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.math.AxisAlignedBB; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import net.minecraft.util.math.shapes.VoxelShape;
import net.minecraft.world.World; import net.minecraft.world.World;
/** /**
@@ -43,10 +44,16 @@ public final class VecUtils {
*/ */
public static Vec3d calculateBlockCenter(World world, BlockPos pos) { public static Vec3d calculateBlockCenter(World world, BlockPos pos) {
IBlockState b = world.getBlockState(pos); IBlockState b = world.getBlockState(pos);
AxisAlignedBB bbox = b.getBoundingBox(world, pos); VoxelShape shape = b.getCollisionShape(world, pos);
double xDiff = (bbox.minX + bbox.maxX) / 2; if (shape.isEmpty()) {
double yDiff = (bbox.minY + bbox.maxY) / 2; return getBlockPosCenter(pos);
double zDiff = (bbox.minZ + bbox.maxZ) / 2; }
double xDiff = (shape.getStart(EnumFacing.Axis.X) + shape.getEnd(EnumFacing.Axis.X)) / 2;
double yDiff = (shape.getStart(EnumFacing.Axis.Y) + shape.getEnd(EnumFacing.Axis.Y)) / 2;
double zDiff = (shape.getStart(EnumFacing.Axis.Z) + shape.getEnd(EnumFacing.Axis.Z)) / 2;
if (Double.isNaN(xDiff) || Double.isNaN(yDiff) || Double.isNaN(zDiff)) {
throw new IllegalStateException(b + " " + pos + " " + shape);
}
if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out
yDiff = 0; yDiff = 0;
} }
@@ -17,15 +17,6 @@
package baritone.api.utils.input; package baritone.api.utils.input;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.settings.KeyBinding;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/** /**
* An {@link Enum} representing the inputs that control the player's * An {@link Enum} representing the inputs that control the player's
* behavior. This includes moving, interacting with blocks, jumping, * behavior. This includes moving, interacting with blocks, jumping,
@@ -36,84 +27,45 @@ public enum Input {
/** /**
* The move forward input * The move forward input
*/ */
MOVE_FORWARD(s -> s.keyBindForward), MOVE_FORWARD,
/** /**
* The move back input * The move back input
*/ */
MOVE_BACK(s -> s.keyBindBack), MOVE_BACK,
/** /**
* The move left input * The move left input
*/ */
MOVE_LEFT(s -> s.keyBindLeft), MOVE_LEFT,
/** /**
* The move right input * The move right input
*/ */
MOVE_RIGHT(s -> s.keyBindRight), MOVE_RIGHT,
/** /**
* The attack input * The attack input
*/ */
CLICK_LEFT(s -> s.keyBindAttack), CLICK_LEFT,
/** /**
* The use item input * The use item input
*/ */
CLICK_RIGHT(s -> s.keyBindUseItem), CLICK_RIGHT,
/** /**
* The jump input * The jump input
*/ */
JUMP(s -> s.keyBindJump), JUMP,
/** /**
* The sneak input * The sneak input
*/ */
SNEAK(s -> s.keyBindSneak), SNEAK,
/** /**
* The sprint input * The sprint input
*/ */
SPRINT(s -> s.keyBindSprint); SPRINT
/**
* Map of {@link KeyBinding} to {@link Input}. Values should be queried through {@link #getInputForBind(KeyBinding)}
*/
private static final Map<KeyBinding, Input> bindToInputMap = new HashMap<>();
/**
* The actual game {@link KeyBinding} being forced.
*/
private final KeyBinding keyBinding;
Input(Function<GameSettings, KeyBinding> keyBindingMapper) {
/*
Here, a Function is used because referring to a static field in this enum for the game instance,
as it was before, wouldn't be possible in an Enum constructor unless the static field was in an
interface that this class implemented. (Helper acted as this interface) I didn't feel like making
an interface with a game instance field just to not have to do this.
*/
this.keyBinding = keyBindingMapper.apply(Minecraft.getMinecraft().gameSettings);
}
/**
* @return The actual game {@link KeyBinding} being forced.
*/
public final KeyBinding getKeyBinding() {
return this.keyBinding;
}
/**
* Finds the {@link Input} constant that is associated with the specified {@link KeyBinding}.
*
* @param binding The {@link KeyBinding} to find the associated {@link Input} for
* @return The {@link Input} associated with the specified {@link KeyBinding}
*/
public static Input getInputForBind(KeyBinding binding) {
return bindToInputMap.computeIfAbsent(binding, b -> Arrays.stream(values()).filter(input -> input.keyBinding == b).findFirst().orElse(null));
}
} }
@@ -0,0 +1,105 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import com.google.common.base.Strings;
import com.google.gson.GsonBuilder;
import com.mojang.authlib.Agent;
import com.mojang.authlib.exceptions.AuthenticationException;
import com.mojang.authlib.properties.PropertyMap;
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
import net.minecraft.launchwrapper.Launch;
import java.io.File;
import java.lang.reflect.Field;
import java.net.Proxy;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* Based on GradleStart from ForgeGradle 2.3
*
* @author Brady
* @since 3/11/2019
*/
public class LaunchTesting {
public static void main(String[] args) {
Map<String, String> arguments = new HashMap<>();
hackNatives();
arguments.put("version", "BaritownedDeveloperEnvironment");
arguments.put("assetIndex", System.getenv("assetIndex"));
arguments.put("assetsDir", System.getenv().getOrDefault("assetDirectory", "assets"));
arguments.put("accessToken", "FML");
arguments.put("userProperties", "{}");
arguments.put("tweakClass", System.getenv("tweakClass"));
String password = System.getenv("password");
if (password != null && !password.isEmpty()) {
attemptLogin(arguments, System.getenv("username"), System.getenv("password"));
}
List<String> argsArray = new ArrayList<>();
arguments.forEach((k, v) -> {
argsArray.add("--" + k);
argsArray.add(v);
});
Launch.main(argsArray.toArray(new String[0]));
}
private static void hackNatives() {
String paths = System.getProperty("java.library.path");
String nativesDir = System.getenv().get("nativesDirectory");
if (Strings.isNullOrEmpty(paths))
paths = nativesDir;
else
paths += File.pathSeparator + nativesDir;
System.setProperty("java.library.path", paths);
// hack the classloader now.
try {
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
sysPathsField.setAccessible(true);
sysPathsField.set(null, null);
} catch (Throwable ignored) {}
}
private static void attemptLogin(Map<String, String> argMap, String username, String password) {
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) (new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1")).createUserAuthentication(Agent.MINECRAFT);
auth.setUsername(username);
auth.setPassword(password);
try {
auth.logIn();
} catch (AuthenticationException var4) {
throw new RuntimeException(var4);
}
argMap.put("accessToken", auth.getAuthenticatedToken());
argMap.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", ""));
argMap.put("username", auth.getSelectedProfile().getName());
argMap.put("userType", auth.getUserType().getName());
argMap.put("userProperties", (new GsonBuilder()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(auth.getUserProperties()));
}
}
@@ -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.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.*;
import static org.lwjgl.opengl.GL14.*;
@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.value && Minecraft.getInstance().getIntegratedServer() == null && Minecraft.getInstance().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
GlStateManager.enableAlphaTest();
GlStateManager.enableBlend();
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.value);
GlStateManager.blendFuncSeparate(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.value && Minecraft.getInstance().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,10 +18,12 @@
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;
import net.minecraft.entity.EntityLivingBase; import net.minecraft.entity.EntityLivingBase;
import net.minecraft.entity.EntityType;
import net.minecraft.world.World; import net.minecraft.world.World;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
@@ -43,9 +45,8 @@ public abstract class MixinEntityLivingBase extends Entity {
*/ */
private RotationMoveEvent jumpRotationEvent; private RotationMoveEvent jumpRotationEvent;
public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) { public MixinEntityLivingBase(EntityType<?> entityTypeIn, World worldIn) {
super(worldIn); super(entityTypeIn, worldIn);
this.jumpRotationEvent = jumpRotationEvent;
} }
@Inject( @Inject(
@@ -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,27 +47,34 @@ 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();
} }
} }
@Inject( @Inject(
method = "onUpdate", method = "tick",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/client/entity/EntityPlayerSP.isRiding()Z", target = "net/minecraft/client/entity/EntityPlayerSP.isPassenger()Z",
shift = At.Shift.BY, shift = At.Shift.BY,
by = -3 by = -3
) )
) )
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(
method = "onUpdate", method = "tick",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V", target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
@@ -76,32 +83,49 @@ 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(
method = "onLivingUpdate", method = "livingTick",
at = @At( at = @At(
value = "FIELD", value = "FIELD",
target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z" target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z"
) )
) )
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(
method = "onLivingUpdate", method = "livingTick",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/client/settings/KeyBinding.isKeyDown()Z" target = "net/minecraft/client/settings/KeyBinding.isKeyDown()Z"
) )
) )
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();
}
} }
} }
@@ -20,24 +20,24 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.event.events.RenderEvent; import baritone.api.event.events.RenderEvent;
import net.minecraft.client.renderer.EntityRenderer; import net.minecraft.client.renderer.GameRenderer;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo; import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@Mixin(EntityRenderer.class) @Mixin(GameRenderer.class)
public class MixinEntityRenderer { public class MixinGameRenderer {
@Inject( @Inject(
method = "renderWorldPass", method = "updateCameraAndRender(FJ)V",
at = @At( at = @At(
value = "INVOKE_STRING", value = "INVOKE_STRING",
target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V", target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
args = {"ldc=hand"} args = {"ldc=hand"}
) )
) )
private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) { private void renderWorldPass(float partialTicks, long finishTimeNano, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) { for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks)); ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks));
} }
@@ -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:
}
}
}
@@ -97,10 +97,10 @@ public class MixinMinecraft {
} }
@Inject( @Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Lnet/minecraft/client/gui/GuiScreen;)V",
at = @At("HEAD") at = @At("HEAD")
) )
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { private void preLoadWorld(WorldClient world, GuiScreen loadingScreen, CallbackInfo ci) {
// If we're unloading the world but one doesn't exist, ignore it // If we're unloading the world but one doesn't exist, ignore it
if (this.world == null && world == null) { if (this.world == null && world == null) {
return; return;
@@ -117,10 +117,10 @@ public class MixinMinecraft {
} }
@Inject( @Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Lnet/minecraft/client/gui/GuiScreen;)V",
at = @At("RETURN") at = @At("RETURN")
) )
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) { private void postLoadWorld(WorldClient world, GuiScreen loadingScreen, CallbackInfo ci) {
// still fire event for both null, as that means we've just finished exiting a world // still fire event for both null, as that means we've just finished exiting a world
// mc.world changing is only the primary baritone // mc.world changing is only the primary baritone
@@ -24,6 +24,7 @@ import baritone.api.event.events.type.EventState;
import net.minecraft.client.network.NetHandlerPlayClient; import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketChunkData; import net.minecraft.network.play.server.SPacketChunkData;
import net.minecraft.network.play.server.SPacketCombatEvent; import net.minecraft.network.play.server.SPacketCombatEvent;
import net.minecraft.network.play.server.SPacketUnloadChunk;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
@@ -40,7 +41,7 @@ public class MixinNetHandlerPlayClient {
method = "handleChunkData", method = "handleChunkData",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/world/chunk/Chunk.read(Lnet/minecraft/network/PacketBuffer;IZ)V" target = "net/minecraft/client/multiplayer/ChunkProviderClient.func_212474_a(IILnet/minecraft/network/PacketBuffer;IZ)Lnet/minecraft/world/chunk/Chunk;"
) )
) )
private void preRead(SPacketChunkData packetIn, CallbackInfo ci) { private void preRead(SPacketChunkData packetIn, CallbackInfo ci) {
@@ -77,6 +78,34 @@ public class MixinNetHandlerPlayClient {
} }
} }
@Inject(
method = "processChunkUnload",
at = @At("HEAD")
)
private void preChunkUnload(SPacketUnloadChunk packet, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.PRE, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
);
}
}
}
@Inject(
method = "processChunkUnload",
at = @At("RETURN")
)
private void postChunkUnload(SPacketUnloadChunk packet, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(EventState.POST, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
);
}
}
}
@Inject( @Inject(
method = "handleCombatEvent", method = "handleCombatEvent",
at = @At( at = @At(
@@ -53,7 +53,7 @@ public class MixinNetworkManager {
method = "dispatchPacket", method = "dispatchPacket",
at = @At("HEAD") at = @At("HEAD")
) )
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) { private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>> futureListeners, CallbackInfo ci) {
if (this.direction != EnumPacketDirection.CLIENTBOUND) { if (this.direction != EnumPacketDirection.CLIENTBOUND) {
return; return;
} }
@@ -69,7 +69,7 @@ public class MixinNetworkManager {
method = "dispatchPacket", method = "dispatchPacket",
at = @At("RETURN") at = @At("RETURN")
) )
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) { private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>> futureListeners, CallbackInfo ci) {
if (this.direction != EnumPacketDirection.CLIENTBOUND) { if (this.direction != EnumPacketDirection.CLIENTBOUND) {
return; return;
} }
@@ -85,7 +85,7 @@ public class MixinNetworkManager {
method = "channelRead0", method = "channelRead0",
at = @At( at = @At(
value = "INVOKE", value = "INVOKE",
target = "net/minecraft/network/Packet.processPacket(Lnet/minecraft/network/INetHandler;)V" target = "net/minecraft/network/NetworkManager.processPacket(Lnet/minecraft/network/Packet;Lnet/minecraft/network/INetHandler;)V"
) )
) )
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) { private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
@@ -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.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.chunk.RenderChunk;
import net.minecraft.client.renderer.chunk.RenderChunkCache;
import net.minecraft.util.math.BlockPos;
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/client/renderer/chunk/RenderChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
)
)
private IBlockState getBlockState(RenderChunkCache chunkCache, BlockPos pos) {
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().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.chunk.RenderChunkCache;
import net.minecraft.world.chunk.Chunk;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
@Mixin(RenderChunkCache.class)
public class MixinRenderChunkCache {
@Redirect(
method = "generateCache",
at = @At(
value = "INVOKE",
target = "net/minecraft/world/chunk/Chunk.isEmptyBetween(II)Z"
)
)
private static boolean isEmpty(Chunk chunk, int yStart, int yEnd) {
if (!chunk.isEmptyBetween(yStart, yEnd)) {
return false;
}
if (chunk.isEmpty() && Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
return false;
}
return true;
}
}
@@ -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.value && Minecraft.getInstance().getIntegratedServer() == null) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.blendFuncSeparate(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.value && Minecraft.getInstance().getIntegratedServer() == null) {
// reset the blend func to normal (not dependent on constant alpha)
GlStateManager.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
}
GlStateManager.popMatrix();
}
}
@@ -1,75 +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.IBaritone;
import baritone.api.event.events.ChunkEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.multiplayer.WorldClient;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
* @author Brady
* @since 8/2/2018
*/
@Mixin(WorldClient.class)
public class MixinWorldClient {
@Inject(
method = "doPreChunk",
at = @At("HEAD")
)
private void preDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(
EventState.PRE,
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
chunkX,
chunkZ
)
);
}
}
}
@Inject(
method = "doPreChunk",
at = @At("RETURN")
)
private void postDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
ibaritone.getGameEventHandler().onChunkEvent(
new ChunkEvent(
EventState.POST,
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
chunkX,
chunkZ
)
);
}
}
}
}
+7 -4
View File
@@ -12,14 +12,17 @@
"MixinBlockPos", "MixinBlockPos",
"MixinChunkProviderClient", "MixinChunkProviderClient",
"MixinChunkProviderServer", "MixinChunkProviderServer",
"MixinEntity", "MixinChunkRenderContainer",
"MixinChunkRenderWorker",
"MixinEntityLivingBase", "MixinEntityLivingBase",
"MixinEntityPlayerSP", "MixinEntityPlayerSP",
"MixinEntityRenderer", "MixinGameRenderer",
"MixinKeyBinding",
"MixinMinecraft", "MixinMinecraft",
"MixinNetHandlerPlayClient", "MixinNetHandlerPlayClient",
"MixinNetworkManager", "MixinNetworkManager",
"MixinWorldClient" "MixinRenderChunk",
"MixinRenderChunkCache",
"MixinRenderList",
"MixinVboRenderList"
] ]
} }
+226 -211
View File
@@ -1,211 +1,226 @@
/* /*
* This file is part of Baritone. * This file is part of Baritone.
* *
* Baritone is free software: you can redistribute it and/or modify * 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 * 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 * the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version. * (at your option) any later version.
* *
* Baritone is distributed in the hope that it will be useful, * Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of * but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details. * GNU Lesser General Public License for more details.
* *
* You should have received a copy of the GNU Lesser General Public License * You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>. * along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/ */
package baritone; package baritone;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.IBaritone; import baritone.api.IBaritone;
import baritone.api.Settings; import baritone.api.Settings;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.behavior.*; import baritone.behavior.*;
import baritone.cache.WorldProvider; import baritone.cache.WorldProvider;
import baritone.event.GameEventHandler; import baritone.event.GameEventHandler;
import baritone.process.CustomGoalProcess; import baritone.process.*;
import baritone.process.FollowProcess; import baritone.utils.*;
import baritone.process.GetToBlockProcess; import baritone.utils.player.PrimaryPlayerContext;
import baritone.process.MineProcess; import net.minecraft.client.Minecraft;
import baritone.utils.BaritoneAutoTest;
import baritone.utils.ExampleBaritoneControl; import java.io.File;
import baritone.utils.InputOverrideHandler; import java.io.IOException;
import baritone.utils.PathingControlManager; import java.nio.file.Files;
import baritone.utils.player.PrimaryPlayerContext; import java.util.ArrayList;
import net.minecraft.client.Minecraft; import java.util.List;
import java.util.concurrent.Executor;
import java.io.File; import java.util.concurrent.SynchronousQueue;
import java.io.IOException; import java.util.concurrent.ThreadPoolExecutor;
import java.nio.file.Files; import java.util.concurrent.TimeUnit;
import java.util.ArrayList;
import java.util.List; /**
import java.util.concurrent.Executor; * @author Brady
import java.util.concurrent.SynchronousQueue; * @since 7/31/2018
import java.util.concurrent.ThreadPoolExecutor; */
import java.util.concurrent.TimeUnit; public class Baritone implements IBaritone {
/** private static ThreadPoolExecutor threadPool;
* @author Brady private static File dir;
* @since 7/31/2018
*/ static {
public class Baritone implements IBaritone { threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
private static ThreadPoolExecutor threadPool; dir = new File(Minecraft.getInstance().gameDir, "baritone");
private static File dir; if (!Files.exists(dir.toPath())) {
try {
static { Files.createDirectories(dir.toPath());
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>()); } catch (IOException ignored) {}
}
dir = new File(Minecraft.getMinecraft().gameDir, "baritone"); }
if (!Files.exists(dir.toPath())) {
try { /**
Files.createDirectories(dir.toPath()); * Whether or not {@link Baritone#init()} has been called yet
} catch (IOException ignored) {} */
} private boolean initialized;
}
private GameEventHandler gameEventHandler;
/**
* Whether or not {@link Baritone#init()} has been called yet private List<Behavior> behaviors;
*/ private PathingBehavior pathingBehavior;
private boolean initialized; private LookBehavior lookBehavior;
private MemoryBehavior memoryBehavior;
private GameEventHandler gameEventHandler; private InventoryBehavior inventoryBehavior;
private InputOverrideHandler inputOverrideHandler;
private List<Behavior> behaviors;
private PathingBehavior pathingBehavior; private FollowProcess followProcess;
private LookBehavior lookBehavior; private MineProcess mineProcess;
private MemoryBehavior memoryBehavior; private GetToBlockProcess getToBlockProcess;
private InputOverrideHandler inputOverrideHandler; private CustomGoalProcess customGoalProcess;
private BuilderProcess builderProcess;
private FollowProcess followProcess; private ExploreProcess exploreProcess;
private MineProcess mineProcess;
private GetToBlockProcess getToBlockProcess; private PathingControlManager pathingControlManager;
private CustomGoalProcess customGoalProcess;
private IPlayerContext playerContext;
private PathingControlManager pathingControlManager; private WorldProvider worldProvider;
private IPlayerContext playerContext; public BlockStateInterface bsi;
private WorldProvider worldProvider;
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;
} }
// Define this before behaviors try and get it, or else it will be null and the builds will fail! // Define this before behaviors try and get it, or else it will be null and the builds will fail!
this.playerContext = PrimaryPlayerContext.INSTANCE; this.playerContext = PrimaryPlayerContext.INSTANCE;
this.behaviors = new ArrayList<>(); this.behaviors = new ArrayList<>();
{ {
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist // the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
pathingBehavior = new PathingBehavior(this); pathingBehavior = new PathingBehavior(this);
lookBehavior = new LookBehavior(this); lookBehavior = new LookBehavior(this);
memoryBehavior = new MemoryBehavior(this); memoryBehavior = new MemoryBehavior(this);
new InventoryBehavior(this); inventoryBehavior = new InventoryBehavior(this);
inputOverrideHandler = new InputOverrideHandler(this); inputOverrideHandler = new InputOverrideHandler(this);
new ExampleBaritoneControl(this); new ExampleBaritoneControl(this);
} }
this.pathingControlManager = new PathingControlManager(this); this.pathingControlManager = new PathingControlManager(this);
{ {
followProcess = new FollowProcess(this); followProcess = new FollowProcess(this);
mineProcess = new MineProcess(this); mineProcess = new MineProcess(this);
customGoalProcess = new CustomGoalProcess(this); // very high iq customGoalProcess = new CustomGoalProcess(this); // very high iq
getToBlockProcess = new GetToBlockProcess(this); getToBlockProcess = new GetToBlockProcess(this);
} builderProcess = new BuilderProcess(this);
exploreProcess = new ExploreProcess(this);
this.worldProvider = new WorldProvider(); }
if (BaritoneAutoTest.ENABLE_AUTO_TEST) { this.worldProvider = new WorldProvider();
this.gameEventHandler.registerEventListener(BaritoneAutoTest.INSTANCE);
} if (BaritoneAutoTest.ENABLE_AUTO_TEST) {
this.gameEventHandler.registerEventListener(BaritoneAutoTest.INSTANCE);
this.initialized = true; }
}
this.initialized = true;
@Override }
public PathingControlManager getPathingControlManager() {
return this.pathingControlManager; @Override
} public PathingControlManager getPathingControlManager() {
return this.pathingControlManager;
public List<Behavior> getBehaviors() { }
return this.behaviors;
} public List<Behavior> getBehaviors() {
return this.behaviors;
public void registerBehavior(Behavior behavior) { }
this.behaviors.add(behavior);
this.gameEventHandler.registerEventListener(behavior); public void registerBehavior(Behavior behavior) {
} this.behaviors.add(behavior);
this.gameEventHandler.registerEventListener(behavior);
@Override }
public InputOverrideHandler getInputOverrideHandler() {
return this.inputOverrideHandler; @Override
} public InputOverrideHandler getInputOverrideHandler() {
return this.inputOverrideHandler;
@Override }
public CustomGoalProcess getCustomGoalProcess() { // Iffy
return this.customGoalProcess; @Override
} public CustomGoalProcess getCustomGoalProcess() { // Iffy
return this.customGoalProcess;
@Override }
public GetToBlockProcess getGetToBlockProcess() { // Iffy
return this.getToBlockProcess; @Override
} public GetToBlockProcess getGetToBlockProcess() { // Iffy
return this.getToBlockProcess;
@Override }
public IPlayerContext getPlayerContext() {
return this.playerContext; @Override
} public IPlayerContext getPlayerContext() {
return this.playerContext;
public MemoryBehavior getMemoryBehavior() { }
return this.memoryBehavior;
} public MemoryBehavior getMemoryBehavior() {
return this.memoryBehavior;
@Override }
public FollowProcess getFollowProcess() {
return this.followProcess; @Override
} public FollowProcess getFollowProcess() {
return this.followProcess;
@Override }
public LookBehavior getLookBehavior() {
return this.lookBehavior; @Override
} public BuilderProcess getBuilderProcess() {
return this.builderProcess;
@Override }
public MineProcess getMineProcess() {
return this.mineProcess; public InventoryBehavior getInventoryBehavior() {
} return this.inventoryBehavior;
}
@Override
public PathingBehavior getPathingBehavior() { @Override
return this.pathingBehavior; public LookBehavior getLookBehavior() {
} return this.lookBehavior;
}
@Override
public WorldProvider getWorldProvider() { public ExploreProcess getExploreProcess() {
return this.worldProvider; return this.exploreProcess;
} }
@Override @Override
public IEventBus getGameEventHandler() { public MineProcess getMineProcess() {
return this.gameEventHandler; return this.mineProcess;
} }
public static Settings settings() { @Override
return BaritoneAPI.getSettings(); public PathingBehavior getPathingBehavior() {
} return this.pathingBehavior;
}
public static File getDir() {
return dir; @Override
} public WorldProvider getWorldProvider() {
return this.worldProvider;
public static Executor getExecutor() { }
return threadPool;
} @Override
} public IEventBus getGameEventHandler() {
return this.gameEventHandler;
}
public static Settings settings() {
return BaritoneAPI.getSettings();
}
public static File getDir() {
return dir;
}
public static Executor getExecutor() {
return threadPool;
}
}
@@ -21,13 +21,18 @@ import baritone.Baritone;
import baritone.api.event.events.TickEvent; import baritone.api.event.events.TickEvent;
import baritone.utils.ToolSet; import baritone.utils.ToolSet;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.inventory.ClickType; import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemPickaxe; import net.minecraft.item.*;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
import net.minecraft.util.NonNullList; import net.minecraft.util.NonNullList;
import java.util.ArrayList;
import java.util.OptionalInt;
import java.util.Random;
import java.util.function.Predicate;
public class InventoryBehavior extends Behavior { public class InventoryBehavior extends Behavior {
public InventoryBehavior(Baritone baritone) { public InventoryBehavior(Baritone baritone) {
super(baritone); super(baritone);
@@ -35,7 +40,7 @@ public class InventoryBehavior extends Behavior {
@Override @Override
public void onTick(TickEvent event) { public void onTick(TickEvent event) {
if (!Baritone.settings().allowInventory.get()) { if (!Baritone.settings().allowInventory.value) {
return; return;
} }
if (event.getType() == TickEvent.Type.OUT) { if (event.getType() == TickEvent.Type.OUT) {
@@ -54,6 +59,34 @@ public class InventoryBehavior extends Behavior {
} }
} }
public void attemptToPutOnHotbar(int inMainInvy, Predicate<Integer> disallowedHotbar) {
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
if (destination.isPresent()) {
swapWithHotBar(inMainInvy, destination.getAsInt());
}
}
public OptionalInt getTempHotbarSlot(Predicate<Integer> disallowedHotbar) {
// we're using 0 and 8 for pickaxe and throwaway
ArrayList<Integer> candidates = new ArrayList<>();
for (int i = 1; i < 8; i++) {
if (ctx.player().inventory.mainInventory.get(i).isEmpty() && !disallowedHotbar.test(i)) {
candidates.add(i);
}
}
if (candidates.isEmpty()) {
for (int i = 1; i < 8; i++) {
if (!disallowedHotbar.test(i)) {
candidates.add(i);
}
}
}
if (candidates.isEmpty()) {
return OptionalInt.empty();
}
return OptionalInt.of(candidates.get(new Random().nextInt(candidates.size())));
}
private void swapWithHotBar(int inInventory, int inHotbar) { private void swapWithHotBar(int inInventory, int inHotbar) {
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player()); ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
} }
@@ -61,7 +94,7 @@ public class InventoryBehavior extends Behavior {
private int firstValidThrowaway() { // TODO offhand idk private int firstValidThrowaway() { // TODO offhand idk
NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory; NonNullList<ItemStack> invy = ctx.player().inventory.mainInventory;
for (int i = 0; i < invy.size(); i++) { for (int i = 0; i < invy.size(); i++) {
if (Baritone.settings().acceptableThrowawayItems.get().contains(invy.get(i).getItem())) { if (Baritone.settings().acceptableThrowawayItems.value.contains(invy.get(i).getItem())) {
return i; return i;
} }
} }
@@ -87,4 +120,62 @@ public class InventoryBehavior extends Behavior {
} }
return bestInd; return bestInd;
} }
public boolean hasGenericThrowaway() {
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
if (throwaway(false, item::equals)) {
return true;
}
}
return false;
}
public boolean selectThrowawayForLocation(int x, int y, int z) {
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z);
if (maybe != null && throwaway(true, item -> item instanceof ItemBlock && ((ItemBlock) item).getBlock().equals(maybe.getBlock()))) {
return true; // gotem
}
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
if (throwaway(true, item::equals)) {
return true;
}
}
return false;
}
private boolean throwaway(boolean select, Predicate<? super Item> desired) {
EntityPlayerSP p = ctx.player();
NonNullList<ItemStack> inv = p.inventory.mainInventory;
for (byte i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
// this usage of settings() is okay because it's only called once during pathing
// (while creating the CalculationContext at the very beginning)
// and then it's called during execution
// since this function is never called during cost calculation, we don't need to migrate
// acceptableThrowawayItems to the CalculationContext
if (desired.test(item.getItem())) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
if (desired.test(p.inventory.offHandInventory.get(0).getItem())) {
// main hand takes precedence over off hand
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
// so we need to select in the main hand something that doesn't right click
// so not a shovel, not a hoe, not a block, etc
for (byte i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
}
return false;
}
} }
@@ -28,9 +28,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
/** /**
* Target's values are as follows: * Target's values are as follows:
* <p>
* getFirst() -> yaw
* getSecond() -> pitch
*/ */
private Rotation target; private Rotation target;
@@ -53,7 +50,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
@Override @Override
public void updateTarget(Rotation target, boolean force) { public void updateTarget(Rotation target, boolean force) {
this.target = target; this.target = target;
this.force = force || !Baritone.settings().freeLook.get(); this.force = force || !Baritone.settings().freeLook.value;
} }
@Override @Override
@@ -63,7 +60,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
} }
// Whether or not we're going to silently set our angles // Whether or not we're going to silently set our angles
boolean silent = Baritone.settings().antiCheatCompatibility.get() && !this.force; boolean silent = Baritone.settings().antiCheatCompatibility.value && !this.force;
switch (event.getState()) { switch (event.getState()) {
case PRE: { case PRE: {
@@ -72,7 +69,7 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
float oldPitch = ctx.player().rotationPitch; float oldPitch = ctx.player().rotationPitch;
float desiredPitch = this.target.getPitch(); float desiredPitch = this.target.getPitch();
ctx.player().rotationPitch = desiredPitch; ctx.player().rotationPitch = desiredPitch;
if (desiredPitch == oldPitch) { if (desiredPitch == oldPitch && !Baritone.settings().freeLook.value) {
nudgeToLevel(); nudgeToLevel();
} }
this.target = null; this.target = null;
@@ -103,13 +100,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.value && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE && !this.force) {
this.target = null; this.target = null;
} }
} }
@@ -25,7 +25,6 @@ import baritone.api.event.events.TickEvent;
import baritone.api.event.events.type.EventState; import baritone.api.event.events.type.EventState;
import baritone.cache.ContainerMemory; import baritone.cache.ContainerMemory;
import baritone.cache.Waypoint; import baritone.cache.Waypoint;
import baritone.pathing.movement.CalculationContext;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockBed; import net.minecraft.block.BlockBed;
@@ -65,6 +64,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.value) {
return;
}
if (event.getType() == TickEvent.Type.OUT) { if (event.getType() == TickEvent.Type.OUT) {
enderChestWindowId = null; enderChestWindowId = null;
futureInventories.clear(); futureInventories.clear();
@@ -80,6 +82,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.value) {
return;
}
Packet p = event.getPacket(); Packet p = event.getPacket();
if (event.getState() == EventState.PRE) { if (event.getState() == EventState.PRE) {
@@ -116,6 +121,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.value) {
return;
}
Packet p = event.getPacket(); Packet p = event.getPacket();
if (event.getState() == EventState.PRE) { if (event.getState() == EventState.PRE) {
@@ -162,6 +170,9 @@ public final class MemoryBehavior extends Behavior {
private void updateInventory() { private void updateInventory() {
if (!Baritone.settings().containerMemory.value) {
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) {
@@ -184,7 +195,7 @@ public final class MemoryBehavior extends Behavior {
} }
private BlockPos neighboringConnectedBlock(BlockPos in) { private BlockPos neighboringConnectedBlock(BlockPos in) {
BlockStateInterface bsi = new CalculationContext(baritone).bsi; BlockStateInterface bsi = baritone.bsi;
Block block = bsi.get0(in).getBlock(); Block block = bsi.get0(in).getBlock();
if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) { if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) {
return null; // other things that have contents, but can be placed adjacent without combining return null; // other things that have contents, but can be placed adjacent without combining
@@ -23,6 +23,7 @@ import baritone.api.event.events.*;
import baritone.api.pathing.calc.IPath; import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ; import baritone.api.pathing.goals.GoalXZ;
import baritone.api.process.PathingCommand;
import baritone.api.utils.BetterBlockPos; import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.PathCalculationResult; import baritone.api.utils.PathCalculationResult;
import baritone.api.utils.interfaces.IGoalRenderPos; import baritone.api.utils.interfaces.IGoalRenderPos;
@@ -33,6 +34,7 @@ import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.PathExecutor; import baritone.pathing.path.PathExecutor;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.PathRenderer; import baritone.utils.PathRenderer;
import baritone.utils.PathingCommandContext;
import baritone.utils.pathing.Favoring; import baritone.utils.pathing.Favoring;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -48,9 +50,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
private PathExecutor next; private PathExecutor next;
private Goal goal; private Goal goal;
private CalculationContext context;
private boolean safeToCancel; private boolean safeToCancel;
private boolean pauseRequestedLastTick; private boolean pauseRequestedLastTick;
private boolean unpausedLastTick;
private boolean cancelRequested; private boolean cancelRequested;
private boolean calcFailedLastTick; private boolean calcFailedLastTick;
@@ -61,6 +65,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 +94,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();
@@ -103,28 +110,51 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
private void tickPath() { private void tickPath() {
if (pauseRequestedLastTick && safeToCancel) { if (pauseRequestedLastTick && safeToCancel) {
pauseRequestedLastTick = false; pauseRequestedLastTick = false;
baritone.getInputOverrideHandler().clearAllKeys(); if (unpausedLastTick) {
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock(); baritone.getInputOverrideHandler().clearAllKeys();
baritone.getInputOverrideHandler().getBlockBreakHelper().stopBreakingBlock();
}
unpausedLastTick = false;
return; return;
} }
unpausedLastTick = true;
if (cancelRequested) { if (cancelRequested) {
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())) {
logDebug("All done. At " + goal); logDebug("All done. At " + goal);
queuePathEvent(PathEvent.AT_GOAL); queuePathEvent(PathEvent.AT_GOAL);
next = null; next = null;
if (Baritone.settings().disconnectOnArrival.value) {
ctx.world().sendQuittingDisconnectingPacket();
}
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 +176,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, context);
} }
return; return;
} }
@@ -193,11 +212,13 @@ 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.value) {
// 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, context);
} }
} }
} }
@@ -224,9 +245,32 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
this.goal = goal; this.goal = goal;
} }
public boolean secretInternalSetGoalAndPath(Goal goal) { public boolean secretInternalSetGoalAndPath(PathingCommand command) {
secretInternalSetGoal(goal); secretInternalSetGoal(command.goal);
return secretInternalPath(); if (command instanceof PathingCommandContext) {
context = ((PathingCommandContext) command).desiredCalcContext;
} else {
context = new CalculationContext(baritone, true);
}
if (goal == null) {
return false;
}
if (goal.isInGoal(ctx.playerFeet()) || goal.isInGoal(expectedSegmentStart)) {
return false;
}
synchronized (pathPlanLock) {
if (current != null) {
return false;
}
synchronized (pathCalcLock) {
if (inProgress != null) {
return false;
}
queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(expectedSegmentStart, true, context);
return true;
}
}
} }
@Override @Override
@@ -281,6 +325,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public void softCancelIfSafe() { public void softCancelIfSafe() {
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
getInProgress().ifPresent(AbstractNodeCostSearch::cancel); // only cancel ours
if (!isSafeToCancel()) { if (!isSafeToCancel()) {
return; return;
} }
@@ -288,7 +333,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
next = null; next = null;
} }
cancelRequested = true; cancelRequested = true;
getInProgress().ifPresent(AbstractNodeCostSearch::cancel); // only cancel ours
// do everything BUT clear keys // do everything BUT clear keys
} }
@@ -296,12 +340,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; getInProgress().ifPresent(AbstractNodeCostSearch::cancel);
next = null; if (current != null) {
current = null;
next = null;
baritone.getInputOverrideHandler().clearAllKeys();
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
@@ -312,39 +358,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} }
} }
/**
* Start calculating a path if we aren't already
*
* @return true if this call started path calculation, false if it was already calculating or executing a path
*/
public boolean secretInternalPath() {
if (goal == null) {
return false;
}
if (goal.isInGoal(ctx.playerFeet())) {
return false;
}
synchronized (pathPlanLock) {
if (current != null) {
return false;
}
synchronized (pathCalcLock) {
if (inProgress != null) {
return false;
}
queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true);
return true;
}
}
}
public void secretCursedFunctionDoNotCall(IPath path) { public void secretCursedFunctionDoNotCall(IPath path) {
synchronized (pathPlanLock) { synchronized (pathPlanLock) {
current = new PathExecutor(this, path); current = new PathExecutor(this, path);
} }
} }
public CalculationContext secretInternalGetCalculationContext() {
return context;
}
/** /**
* See issue #209 * See issue #209
* *
@@ -373,7 +396,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 +405,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();
} }
} }
@@ -396,7 +419,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
* @param start * @param start
* @param talkAboutIt * @param talkAboutIt
*/ */
private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt) { private void findPathInNewThread(final BlockPos start, final boolean talkAboutIt, CalculationContext context) {
// this must be called with synchronization on pathCalcLock! // this must be called with synchronization on pathCalcLock!
// actually, we can check this, muahaha // actually, we can check this, muahaha
if (!Thread.holdsLock(pathCalcLock)) { if (!Thread.holdsLock(pathCalcLock)) {
@@ -406,6 +429,9 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (inProgress != null) { if (inProgress != null) {
throw new IllegalStateException("Already doing it"); // should have been checked by caller throw new IllegalStateException("Already doing it"); // should have been checked by caller
} }
if (!context.safeForThreadedUse) {
throw new IllegalStateException("Improper context thread safety level");
}
Goal goal = this.goal; Goal goal = this.goal;
if (goal == null) { if (goal == null) {
logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller logDebug("no goal"); // TODO should this be an exception too? definitely should be checked by caller
@@ -414,13 +440,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
long primaryTimeout; long primaryTimeout;
long failureTimeout; long failureTimeout;
if (current == null) { if (current == null) {
primaryTimeout = Baritone.settings().primaryTimeoutMS.get(); primaryTimeout = Baritone.settings().primaryTimeoutMS.value;
failureTimeout = Baritone.settings().failureTimeoutMS.get(); failureTimeout = Baritone.settings().failureTimeoutMS.value;
} else { } else {
primaryTimeout = Baritone.settings().planAheadPrimaryTimeoutMS.get(); primaryTimeout = Baritone.settings().planAheadPrimaryTimeoutMS.value;
failureTimeout = Baritone.settings().planAheadFailureTimeoutMS.get(); failureTimeout = Baritone.settings().planAheadFailureTimeoutMS.value;
} }
CalculationContext context = new CalculationContext(baritone, true); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context); AbstractNodeCostSearch pathfinder = createPathfinder(start, goal, current == null ? null : current.getPath(), context);
if (!Objects.equals(pathfinder.getGoal(), goal)) { // will return the exact same object if simplification didn't happen if (!Objects.equals(pathfinder.getGoal(), goal)) { // will return the exact same object if simplification didn't happen
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance"); logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
@@ -436,8 +461,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 +476,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);
} }
@@ -474,13 +507,13 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) { public static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
Goal transformed = goal; Goal transformed = goal;
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) { if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) {
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos(); BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
if (!context.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ())) { if (!context.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ())) {
transformed = new GoalXZ(pos.getX(), pos.getZ()); transformed = new GoalXZ(pos.getX(), pos.getZ());
} }
} }
Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous); Favoring favoring = new Favoring(context.getBaritone().getPlayerContext(), previous, context);
return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context); return new AStarPathFinder(start.getX(), start.getY(), start.getZ(), transformed, favoring, context);
} }
+78 -15
View File
@@ -18,6 +18,7 @@
package baritone.cache; package baritone.cache;
import baritone.utils.pathing.PathingBlockType; import baritone.utils.pathing.PathingBlockType;
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
@@ -52,9 +53,10 @@ public final class CachedChunk {
temp.add(Blocks.TRAPPED_CHEST); temp.add(Blocks.TRAPPED_CHEST);
temp.add(Blocks.END_PORTAL); temp.add(Blocks.END_PORTAL);
temp.add(Blocks.END_PORTAL_FRAME); temp.add(Blocks.END_PORTAL_FRAME);
temp.add(Blocks.MOB_SPAWNER); temp.add(Blocks.SPAWNER);
temp.add(Blocks.BARRIER); temp.add(Blocks.BARRIER);
temp.add(Blocks.OBSERVER); temp.add(Blocks.OBSERVER);
temp.add(Blocks.WHITE_SHULKER_BOX); temp.add(Blocks.WHITE_SHULKER_BOX);
temp.add(Blocks.ORANGE_SHULKER_BOX); temp.add(Blocks.ORANGE_SHULKER_BOX);
temp.add(Blocks.MAGENTA_SHULKER_BOX); temp.add(Blocks.MAGENTA_SHULKER_BOX);
@@ -63,7 +65,7 @@ public final class CachedChunk {
temp.add(Blocks.LIME_SHULKER_BOX); temp.add(Blocks.LIME_SHULKER_BOX);
temp.add(Blocks.PINK_SHULKER_BOX); temp.add(Blocks.PINK_SHULKER_BOX);
temp.add(Blocks.GRAY_SHULKER_BOX); temp.add(Blocks.GRAY_SHULKER_BOX);
temp.add(Blocks.SILVER_SHULKER_BOX); temp.add(Blocks.LIGHT_GRAY_SHULKER_BOX);
temp.add(Blocks.CYAN_SHULKER_BOX); temp.add(Blocks.CYAN_SHULKER_BOX);
temp.add(Blocks.PURPLE_SHULKER_BOX); temp.add(Blocks.PURPLE_SHULKER_BOX);
temp.add(Blocks.BLUE_SHULKER_BOX); temp.add(Blocks.BLUE_SHULKER_BOX);
@@ -71,21 +73,57 @@ public final class CachedChunk {
temp.add(Blocks.GREEN_SHULKER_BOX); temp.add(Blocks.GREEN_SHULKER_BOX);
temp.add(Blocks.RED_SHULKER_BOX); temp.add(Blocks.RED_SHULKER_BOX);
temp.add(Blocks.BLACK_SHULKER_BOX); temp.add(Blocks.BLACK_SHULKER_BOX);
temp.add(Blocks.PORTAL);
temp.add(Blocks.NETHER_PORTAL);
temp.add(Blocks.HOPPER); temp.add(Blocks.HOPPER);
temp.add(Blocks.BEACON); temp.add(Blocks.BEACON);
temp.add(Blocks.BREWING_STAND); temp.add(Blocks.BREWING_STAND);
temp.add(Blocks.SKULL);
// TODO: Maybe add a predicate for blocks to keep track of?
// This should really not need to happen
temp.add(Blocks.CREEPER_HEAD);
temp.add(Blocks.CREEPER_WALL_HEAD);
temp.add(Blocks.DRAGON_HEAD);
temp.add(Blocks.DRAGON_WALL_HEAD);
temp.add(Blocks.PLAYER_HEAD);
temp.add(Blocks.PLAYER_WALL_HEAD);
temp.add(Blocks.ZOMBIE_HEAD);
temp.add(Blocks.ZOMBIE_WALL_HEAD);
temp.add(Blocks.SKELETON_SKULL);
temp.add(Blocks.SKELETON_WALL_SKULL);
temp.add(Blocks.WITHER_SKELETON_SKULL);
temp.add(Blocks.WITHER_SKELETON_WALL_SKULL);
temp.add(Blocks.ENCHANTING_TABLE); temp.add(Blocks.ENCHANTING_TABLE);
temp.add(Blocks.ANVIL); temp.add(Blocks.ANVIL);
temp.add(Blocks.LIT_FURNACE);
temp.add(Blocks.BED); temp.add(Blocks.WHITE_BED);
temp.add(Blocks.ORANGE_BED);
temp.add(Blocks.MAGENTA_BED);
temp.add(Blocks.LIGHT_BLUE_BED);
temp.add(Blocks.YELLOW_BED);
temp.add(Blocks.LIME_BED);
temp.add(Blocks.PINK_BED);
temp.add(Blocks.GRAY_BED);
temp.add(Blocks.LIGHT_GRAY_BED);
temp.add(Blocks.CYAN_BED);
temp.add(Blocks.PURPLE_BED);
temp.add(Blocks.BLUE_BED);
temp.add(Blocks.BROWN_BED);
temp.add(Blocks.GREEN_BED);
temp.add(Blocks.RED_BED);
temp.add(Blocks.BLACK_BED);
temp.add(Blocks.DRAGON_EGG); temp.add(Blocks.DRAGON_EGG);
temp.add(Blocks.JUKEBOX); temp.add(Blocks.JUKEBOX);
temp.add(Blocks.END_GATEWAY); temp.add(Blocks.END_GATEWAY);
temp.add(Blocks.WEB); temp.add(Blocks.COBWEB);
temp.add(Blocks.NETHER_WART); temp.add(Blocks.NETHER_WART);
temp.add(Blocks.LADDER);
temp.add(Blocks.VINE);
BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp); BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp);
// TODO: Lit Furnaces
} }
/** /**
@@ -117,6 +155,8 @@ public final class CachedChunk {
*/ */
private final BitSet data; private final BitSet data;
private final Int2ObjectOpenHashMap<String> special;
/** /**
* The block names of each surface level block for generating an overview * The block names of each surface level block for generating an overview
*/ */
@@ -138,28 +178,51 @@ public final class CachedChunk {
this.heightMap = new int[256]; this.heightMap = new int[256];
this.specialBlockLocations = specialBlockLocations; this.specialBlockLocations = specialBlockLocations;
this.cacheTimestamp = cacheTimestamp; this.cacheTimestamp = cacheTimestamp;
if (specialBlockLocations.isEmpty()) {
this.special = null;
} else {
this.special = new Int2ObjectOpenHashMap<>();
setSpecial();
}
calculateHeightMap(); calculateHeightMap();
} }
private final void setSpecial() {
for (Map.Entry<String, List<BlockPos>> entry : specialBlockLocations.entrySet()) {
for (BlockPos pos : entry.getValue()) {
special.put(getPositionIndex(pos.getX(), pos.getY(), pos.getZ()), entry.getKey());
}
}
}
public final IBlockState getBlock(int x, int y, int z, int dimension) { public final IBlockState getBlock(int x, int y, int z, int dimension) {
int index = getPositionIndex(x, y, z);
PathingBlockType type = getType(index);
int internalPos = z << 4 | x; int internalPos = z << 4 | x;
if (heightMap[internalPos] == y) { if (heightMap[internalPos] == y && type != PathingBlockType.AVOID) {
// if the top block in a column is water, we cache it as AVOID but we don't want to just return default state water (which is not flowing) beacuse then it would try to path through it
// we have this exact block, it's a surface block // we have this exact block, it's a surface block
/*System.out.println("Saying that " + x + "," + y + "," + z + " is " + state); /*System.out.println("Saying that " + x + "," + y + "," + z + " is " + state);
if (!Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) { if (!Minecraft.getInstance().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) {
throw new IllegalStateException("failed " + Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16)); throw new IllegalStateException("failed " + Minecraft.getInstance().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16));
}*/ }*/
return overview[internalPos]; return overview[internalPos];
} }
PathingBlockType type = getType(x, y, z); if (special != null) {
String str = special.get(index);
if (str != null) {
return ChunkPacker.stringToBlockRequired(str).getDefaultState();
}
}
if (type == PathingBlockType.SOLID && y == 127 && dimension == -1) { if (type == PathingBlockType.SOLID && y == 127 && dimension == -1) {
return Blocks.BEDROCK.getDefaultState(); return Blocks.BEDROCK.getDefaultState();
} }
return ChunkPacker.pathingTypeToBlock(type, dimension); return ChunkPacker.pathingTypeToBlock(type, dimension);
} }
private PathingBlockType getType(int x, int y, int z) { private PathingBlockType getType(int index) {
int index = getPositionIndex(x, y, z);
return PathingBlockType.fromBits(data.get(index), data.get(index + 1)); return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
} }
@@ -187,11 +250,11 @@ public final class CachedChunk {
return specialBlockLocations; return specialBlockLocations;
} }
public final LinkedList<BlockPos> getAbsoluteBlocks(String blockType) { public final ArrayList<BlockPos> getAbsoluteBlocks(String blockType) {
if (specialBlockLocations.get(blockType) == null) { if (specialBlockLocations.get(blockType) == null) {
return null; return null;
} }
LinkedList<BlockPos> res = new LinkedList<>(); ArrayList<BlockPos> res = new ArrayList<>();
for (BlockPos pos : specialBlockLocations.get(blockType)) { for (BlockPos pos : specialBlockLocations.get(blockType)) {
res.add(new BlockPos(pos.getX() + x * 16, pos.getY(), pos.getZ() + z * 16)); res.add(new BlockPos(pos.getX() + x * 16, pos.getY(), pos.getZ() + z * 16));
} }
+8 -10
View File
@@ -87,19 +87,16 @@ public final class CachedRegion implements ICachedRegion {
return chunks[x >> 4][z >> 4] != null; return chunks[x >> 4][z >> 4] != null;
} }
public final LinkedList<BlockPos> getLocationsOf(String block) { public final ArrayList<BlockPos> getLocationsOf(String block) {
LinkedList<BlockPos> res = new LinkedList<>(); ArrayList<BlockPos> res = new ArrayList<>();
for (int chunkX = 0; chunkX < 32; chunkX++) { for (int chunkX = 0; chunkX < 32; chunkX++) {
for (int chunkZ = 0; chunkZ < 32; chunkZ++) { for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
if (chunks[chunkX][chunkZ] == null) { if (chunks[chunkX][chunkZ] == null) {
continue; continue;
} }
List<BlockPos> locs = chunks[chunkX][chunkZ].getAbsoluteBlocks(block); ArrayList<BlockPos> locs = chunks[chunkX][chunkZ].getAbsoluteBlocks(block);
if (locs == null) { if (locs != null) {
continue; res.addAll(locs);
}
for (BlockPos pos : locs) {
res.add(pos);
} }
} }
} }
@@ -243,7 +240,7 @@ public final class CachedRegion implements ICachedRegion {
for (int z = 0; z < 32; z++) { for (int z = 0; z < 32; z++) {
if (present[x][z]) { if (present[x][z]) {
for (int i = 0; i < 256; i++) { for (int i = 0; i < 256; i++) {
overview[x][z][i] = ChunkPacker.stringToBlock(in.readUTF()).getDefaultState(); overview[x][z][i] = ChunkPacker.stringToBlockRequired(in.readUTF()).getDefaultState();
} }
} }
} }
@@ -258,6 +255,7 @@ public final class CachedRegion implements ICachedRegion {
int numSpecialBlockTypes = in.readShort() & 0xffff; int numSpecialBlockTypes = in.readShort() & 0xffff;
for (int i = 0; i < numSpecialBlockTypes; i++) { for (int i = 0; i < numSpecialBlockTypes; i++) {
String blockName = in.readUTF(); String blockName = in.readUTF();
ChunkPacker.stringToBlockRequired(blockName);
List<BlockPos> locs = new ArrayList<>(); List<BlockPos> locs = new ArrayList<>();
location[x][z].put(blockName, locs); location[x][z].put(blockName, locs);
int numLocations = in.readShort() & 0xffff; int numLocations = in.readShort() & 0xffff;
@@ -306,7 +304,7 @@ public final class CachedRegion implements ICachedRegion {
} }
public synchronized final void removeExpired() { public synchronized final void removeExpired() {
long expiry = Baritone.settings().cachedChunksExpirySeconds.get(); long expiry = Baritone.settings().cachedChunksExpirySeconds.value;
if (expiry < 0) { if (expiry < 0) {
return; return;
} }
+10 -9
View File
@@ -32,7 +32,6 @@ 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.ArrayList;
import java.util.LinkedList;
import java.util.List; import java.util.List;
import java.util.concurrent.LinkedBlockingQueue; import java.util.concurrent.LinkedBlockingQueue;
@@ -45,7 +44,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.
@@ -71,8 +70,6 @@ public final class CachedWorld implements ICachedWorld, Helper {
this.directory = directory.toString(); this.directory = directory.toString();
this.dimension = dimension; this.dimension = dimension;
System.out.println("Cached world directory: " + directory); System.out.println("Cached world directory: " + directory);
// Insert an invalid region element
cachedRegions.put(0, null);
Baritone.getExecutor().execute(new PackerThread()); Baritone.getExecutor().execute(new PackerThread());
Baritone.getExecutor().execute(() -> { Baritone.getExecutor().execute(() -> {
try { try {
@@ -108,9 +105,13 @@ public final class CachedWorld implements ICachedWorld, Helper {
return region.isCached(blockX & 511, blockZ & 511); return region.isCached(blockX & 511, blockZ & 511);
} }
public final boolean regionLoaded(int blockX, int blockZ) {
return getRegion(blockX >> 9, blockZ >> 9) != null;
}
@Override @Override
public final LinkedList<BlockPos> getLocationsOf(String block, int maximum, int centerX, int centerZ, int maxRegionDistanceSq) { public final ArrayList<BlockPos> getLocationsOf(String block, int maximum, int centerX, int centerZ, int maxRegionDistanceSq) {
LinkedList<BlockPos> res = new LinkedList<>(); ArrayList<BlockPos> res = new ArrayList<>();
int centerRegionX = centerX >> 9; int centerRegionX = centerX >> 9;
int centerRegionZ = centerZ >> 9; int centerRegionZ = centerZ >> 9;
@@ -127,7 +128,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
CachedRegion region = getOrCreateRegion(regionX, regionZ); CachedRegion region = getOrCreateRegion(regionX, regionZ);
if (region != null) { if (region != null) {
// TODO: 100% verify if this or addAll is faster. // TODO: 100% verify if this or addAll is faster.
region.getLocationsOf(block).forEach(res::add); res.addAll(region.getLocationsOf(block));
} }
} }
} }
@@ -146,7 +147,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
@Override @Override
public final void save() { public final void save() {
if (!Baritone.settings().chunkCaching.get()) { if (!Baritone.settings().chunkCaching.value) {
System.out.println("Not saving to disk; chunk caching is disabled."); System.out.println("Not saving to disk; chunk caching is disabled.");
allRegions().forEach(region -> { allRegions().forEach(region -> {
if (region != null) { if (region != null) {
@@ -171,7 +172,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
* Delete regions that are too far from the player * Delete regions that are too far from the player
*/ */
private synchronized void prune() { private synchronized void prune() {
if (!Baritone.settings().pruneRegionsFromRAM.get()) { if (!Baritone.settings().pruneRegionsFromRAM.value) {
return; return;
} }
BlockPos pruneCenter = guessPosition(); BlockPos pruneCenter = guessPosition();
+40 -17
View File
@@ -19,17 +19,16 @@ 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;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import net.minecraft.util.registry.IRegistry;
import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.ChunkSection;
import java.util.*; import java.util.*;
@@ -49,9 +48,9 @@ public final class ChunkPacker {
Map<String, List<BlockPos>> specialBlocks = new HashMap<>(); Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
BitSet bitSet = new BitSet(CachedChunk.SIZE); BitSet bitSet = new BitSet(CachedChunk.SIZE);
try { try {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); ChunkSection[] chunkInternalStorageArray = chunk.getSections();
for (int y0 = 0; y0 < 16; y0++) { for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; ChunkSection extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) { if (extendedblockstorage == null) {
// any 16x16x16 area that's all air will have null storage // any 16x16x16 area that's all air will have null storage
// for example, in an ocean biome, with air from y=64 to y=256 // for example, in an ocean biome, with air from y=64 to y=256
@@ -63,7 +62,7 @@ public final class ChunkPacker {
// since a bitset is initialized to all zero, and air is saved as zeros // since a bitset is initialized to all zero, and air is saved as zeros
continue; continue;
} }
BlockStateContainer bsc = extendedblockstorage.getData(); BlockStateContainer<IBlockState> bsc = extendedblockstorage.getData();
int yReal = y0 << 4; int yReal = y0 << 4;
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x; // the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order // for better cache locality, iterate in that order
@@ -73,7 +72,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();
@@ -93,7 +92,8 @@ public final class ChunkPacker {
IBlockState[] blocks = new IBlockState[256]; IBlockState[] blocks = new IBlockState[256];
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html https:
//www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
for (int y = 255; y >= 0; y--) { for (int y = 255; y >= 0; y--) {
int index = CachedChunk.getPositionIndex(x, y, z); int index = CachedChunk.getPositionIndex(x, y, z);
@@ -109,7 +109,7 @@ public final class ChunkPacker {
} }
public static String blockToString(Block block) { public static String blockToString(Block block) {
ResourceLocation loc = Block.REGISTRY.getNameForObject(block); ResourceLocation loc = IRegistry.BLOCK.getKey(block);
String name = loc.getPath(); // normally, only write the part after the minecraft: String name = loc.getPath(); // normally, only write the part after the minecraft:
if (!loc.getNamespace().equals("minecraft")) { if (!loc.getNamespace().equals("minecraft")) {
// Baritone is running on top of forge with mods installed, perhaps? // Baritone is running on top of forge with mods installed, perhaps?
@@ -118,25 +118,48 @@ public final class ChunkPacker {
return name; return name;
} }
public static Block stringToBlock(String name) { public static Block stringToBlockRequired(String name) {
return resourceCache.computeIfAbsent(name, n -> Block.getBlockFromName(n.contains(":") ? n : "minecraft:" + n)); if (name.equals("lit_redstone_ore")) {
return stringToBlockRequired("redstone_ore");
}
Block block = stringToBlockNullable(name);
Objects.requireNonNull(block);
return block;
} }
private static PathingBlockType getPathingBlockType(IBlockState state) { public static Block stringToBlockNullable(String name) {
return resourceCache.computeIfAbsent(name, n -> IRegistry.BLOCK.get(new ResourceLocation(n.contains(":") ? n : "minecraft:" + n)));
}
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 (MovementHelper.isWater(state)) {
// 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.AVOID;
}
if (x == 0 || x == 15 || z == 0 || z == 15) {
Vec3d flow = state.getFluidState().getFlow(chunk.getWorld(), new BlockPos(x + chunk.x << 4, y, z + chunk.z << 4));
if (flow.x != 0.0 || flow.z != 0.0) {
return PathingBlockType.WATER;
}
return PathingBlockType.AVOID;
}
if (MovementHelper.possiblyFlowing(chunk.getBlockState(x + 1, y, z)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x - 1, y, z)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z + 1)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z - 1))) {
return PathingBlockType.AVOID;
}
return PathingBlockType.WATER; return PathingBlockType.WATER;
} }
if (MovementHelper.avoidWalkingInto(block) || block == Blocks.FLOWING_WATER || MovementHelper.isBottomSlab(state)) { if (MovementHelper.avoidWalkingInto(state) || 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
// however, this failed in the nether when you were near a nether fortress // however, this failed in the nether when you were near a nether fortress
// because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape // because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape
// this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors // this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors
if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) { if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) {
return PathingBlockType.AIR; return PathingBlockType.AIR;
} }
+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.value) {
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());
+4 -3
View File
@@ -24,6 +24,7 @@ import baritone.utils.accessor.IAnvilChunkLoader;
import baritone.utils.accessor.IChunkProviderServer; import baritone.utils.accessor.IChunkProviderServer;
import net.minecraft.server.integrated.IntegratedServer; import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.world.WorldServer; import net.minecraft.world.WorldServer;
import net.minecraft.world.dimension.DimensionType;
import org.apache.commons.lang3.SystemUtils; import org.apache.commons.lang3.SystemUtils;
import java.io.File; import java.io.File;
@@ -55,7 +56,7 @@ public class WorldProvider implements IWorldProvider, Helper {
* *
* @param dimension The ID of the world's dimension * @param dimension The ID of the world's dimension
*/ */
public final void initWorld(int dimension) { public final void initWorld(DimensionType dimension) {
File directory; File directory;
File readme; File readme;
@@ -92,7 +93,7 @@ public class WorldProvider implements IWorldProvider, Helper {
} catch (IOException ignored) {} } catch (IOException ignored) {}
// We will actually store the world data in a subfolder: "DIM<id>" // We will actually store the world data in a subfolder: "DIM<id>"
Path dir = new File(directory, "DIM" + dimension).toPath(); Path dir = new File(directory, "DIM" + dimension.getId()).toPath();
if (!Files.exists(dir)) { if (!Files.exists(dir)) {
try { try {
Files.createDirectories(dir); Files.createDirectories(dir);
@@ -101,7 +102,7 @@ public class WorldProvider implements IWorldProvider, Helper {
System.out.println("Baritone world data dir: " + dir); System.out.println("Baritone world data dir: " + dir);
synchronized (worldCache) { synchronized (worldCache) {
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension)); this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension.getId()));
} }
} }
+33 -17
View File
@@ -26,17 +26,17 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos; import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.BlockStateContainer; import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.ChunkSection;
import java.util.ArrayList; import java.util.*;
import java.util.Collection; import java.util.stream.IntStream;
import java.util.Collections;
import java.util.List;
public enum WorldScanner implements IWorldScanner { public enum WorldScanner implements IWorldScanner {
INSTANCE; INSTANCE;
private static final int[] DEFAULT_COORDINATE_ITERATION_ORDER = IntStream.range(0, 16).toArray();
@Override @Override
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) { public List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) {
if (blocks.contains(null)) { if (blocks.contains(null)) {
@@ -53,6 +53,9 @@ public enum WorldScanner implements IWorldScanner {
int playerChunkZ = ctx.playerFeet().getZ() >> 4; int playerChunkZ = ctx.playerFeet().getZ() >> 4;
int playerY = ctx.playerFeet().getY(); int playerY = ctx.playerFeet().getY();
int playerYBlockStateContainerIndex = playerY >> 4;
int[] coordinateIterationOrder = IntStream.range(0, 16).boxed().sorted(Comparator.comparingInt(y -> Math.abs(y - playerYBlockStateContainerIndex))).mapToInt(x -> x).toArray();
int searchRadiusSq = 0; int searchRadiusSq = 0;
boolean foundWithinY = false; boolean foundWithinY = false;
while (true) { while (true) {
@@ -67,12 +70,14 @@ public enum WorldScanner implements IWorldScanner {
foundChunks = true; foundChunks = true;
int chunkX = xoff + playerChunkX; int chunkX = xoff + playerChunkX;
int chunkZ = zoff + playerChunkZ; int chunkZ = zoff + playerChunkZ;
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ); Chunk chunk = chunkProvider.getChunk(chunkX, chunkZ, false, false);
if (chunk == null) { if (chunk == null) {
continue; continue;
} }
allUnloaded = false; allUnloaded = false;
scanChunkInto(chunkX << 4, chunkZ << 4, chunk, blocks, res, max, yLevelThreshold, playerY); if (scanChunkInto(chunkX << 4, chunkZ << 4, chunk, blocks, res, max, yLevelThreshold, playerY, coordinateIterationOrder)) {
foundWithinY = true;
}
} }
} }
if ((allUnloaded && foundChunks) if ((allUnloaded && foundChunks)
@@ -92,7 +97,7 @@ public enum WorldScanner implements IWorldScanner {
} }
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider(); ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z); Chunk chunk = chunkProvider.getChunk(pos.x, pos.z, false, false);
int playerY = ctx.playerFeet().getY(); int playerY = ctx.playerFeet().getY();
if (chunk == null || chunk.isEmpty()) { if (chunk == null || chunk.isEmpty()) {
@@ -100,19 +105,21 @@ public enum WorldScanner implements IWorldScanner {
} }
ArrayList<BlockPos> res = new ArrayList<>(); ArrayList<BlockPos> res = new ArrayList<>();
scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY); scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY, DEFAULT_COORDINATE_ITERATION_ORDER);
return res; return res;
} }
public void scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY) { private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); ChunkSection[] chunkInternalStorageArray = chunk.getSections();
for (int y0 = 0; y0 < 16; y0++) { boolean foundWithinY = false;
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; for (int yIndex = 0; yIndex < 16; yIndex++) {
int y0 = coordinateIterationOrder[yIndex];
ChunkSection extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) { if (extendedblockstorage == null) {
continue; continue;
} }
int yReal = y0 << 4; int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData(); BlockStateContainer<IBlockState> bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x; // the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order // for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
@@ -121,14 +128,23 @@ public enum WorldScanner implements IWorldScanner {
IBlockState state = bsc.get(x, y, z); IBlockState state = bsc.get(x, y, z);
if (search.contains(state.getBlock())) { if (search.contains(state.getBlock())) {
int yy = yReal | y; int yy = yReal | y;
result.add(new BlockPos(chunkX | x, yy, chunkZ | z)); if (result.size() >= max) {
if (result.size() >= max && Math.abs(yy - playerY) < yLevelThreshold) { if (Math.abs(yy - playerY) < yLevelThreshold) {
return; foundWithinY = true;
} else {
if (foundWithinY) {
// have found within Y in this chunk, so don't need to consider outside Y
// TODO continue iteration to one more sorted Y coordinate block
return true;
}
}
} }
result.add(new BlockPos(chunkX | x, yy, chunkZ | z));
} }
} }
} }
} }
} }
return foundWithinY;
} }
} }
@@ -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));
} }
@@ -74,7 +84,7 @@ public final class GameEventHandler implements IEventBus, Helper {
// to make sure the chunk being unloaded is already loaded. // to make sure the chunk being unloaded is already loaded.
boolean isPreUnload = state == EventState.PRE boolean isPreUnload = state == EventState.PRE
&& type == ChunkEvent.Type.UNLOAD && type == ChunkEvent.Type.UNLOAD
&& world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ()); && world.getChunkProvider().getChunk(event.getX(), event.getZ(), false, false) != null;
if (isPostPopulate || isPreUnload) { if (isPostPopulate || isPreUnload) {
baritone.getWorldProvider().ifWorldLoaded(worldData -> { baritone.getWorldProvider().ifWorldLoaded(worldData -> {
@@ -99,7 +109,7 @@ public final class GameEventHandler implements IEventBus, Helper {
if (event.getState() == EventState.POST) { if (event.getState() == EventState.POST) {
cache.closeWorld(); cache.closeWorld();
if (event.getWorld() != null) { if (event.getWorld() != null) {
cache.initWorld(event.getWorld().provider.getDimensionType().getId()); cache.initWorld(event.getWorld().getDimension().getType());
} }
} }
@@ -62,20 +62,20 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
MutableMoveResult res = new MutableMoveResult(); MutableMoveResult res = new MutableMoveResult();
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder()); BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis(); long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.get(); boolean slowPath = Baritone.settings().slowPath.value;
if (slowPath) { if (slowPath) {
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms"); logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.value + "ms instead of " + primaryTimeout + "ms");
} }
long primaryTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : primaryTimeout); long primaryTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.value : primaryTimeout);
long failureTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : failureTimeout); long failureTimeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.value : failureTimeout);
boolean failing = true; boolean failing = true;
int numNodes = 0; int numNodes = 0;
int numMovementsConsidered = 0; int numMovementsConsidered = 0;
int numEmptyChunk = 0; int numEmptyChunk = 0;
boolean isFavoring = !favoring.isEmpty(); boolean isFavoring = !favoring.isEmpty();
int timeCheckInterval = 1 << 6; int timeCheckInterval = 1 << 6;
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.value; // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0; double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.value ? MIN_IMPROVEMENT : 0;
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) { while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond) if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds) long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
@@ -85,7 +85,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
} }
if (slowPath) { if (slowPath) {
try { try {
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get()); Thread.sleep(Baritone.settings().slowPathTimeDelayMS.value);
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
} }
} }
@@ -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;
} }
} }
@@ -87,7 +87,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
this.startZ = startZ; this.startZ = startZ;
this.goal = goal; this.goal = goal;
this.context = context; this.context = context;
this.map = new Long2ObjectOpenHashMap<>(Baritone.settings().pathingMapDefaultSize.value, Baritone.settings().pathingMapLoadFactor.get()); this.map = new Long2ObjectOpenHashMap<>(Baritone.settings().pathingMapDefaultSize.value, Baritone.settings().pathingMapLoadFactor.value);
} }
public void cancel() { public void cancel() {
@@ -34,6 +34,8 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
/** /**
* @author Brady * @author Brady
* @since 8/7/2018 * @since 8/7/2018
@@ -42,6 +44,7 @@ public class CalculationContext {
private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET); private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET);
public final boolean safeForThreadedUse;
public final IBaritone baritone; public final IBaritone baritone;
public final World world; public final World world;
public final WorldData worldData; public final WorldData worldData;
@@ -50,18 +53,20 @@ public class CalculationContext {
public final boolean hasWaterBucket; public final boolean hasWaterBucket;
public final boolean hasThrowaway; public final boolean hasThrowaway;
public final boolean canSprint; public final boolean canSprint;
public final double placeBlockCost; protected final double placeBlockCost; // protected because you should call the function instead
public final boolean allowBreak; public final boolean allowBreak;
public final boolean allowParkour; public final boolean allowParkour;
public final boolean allowParkourPlace; public final boolean allowParkourPlace;
public final boolean allowJumpAt256; public final boolean allowJumpAt256;
public final boolean assumeWalkOnWater; public final boolean assumeWalkOnWater;
public final boolean allowDiagonalDescend; public final boolean allowDiagonalDescend;
public final boolean allowDownward;
public final int maxFallHeightNoWater; public final int maxFallHeightNoWater;
public final int maxFallHeightBucket; public final int maxFallHeightBucket;
public final double waterWalkSpeed; public final double waterWalkSpeed;
public final double breakBlockAdditionalCost; public final double breakBlockAdditionalCost;
public final double jumpPenalty; public double backtrackCostFavoringCoefficient;
public double jumpPenalty;
public final double walkOnWaterOnePenalty; public final double walkOnWaterOnePenalty;
public final BetterWorldBorder worldBorder; public final BetterWorldBorder worldBorder;
@@ -70,33 +75,36 @@ public class CalculationContext {
} }
public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) {
this.safeForThreadedUse = forUseOnAnotherThread;
this.baritone = baritone; this.baritone = baritone;
EntityPlayerSP player = baritone.getPlayerContext().player(); EntityPlayerSP player = baritone.getPlayerContext().player();
this.world = baritone.getPlayerContext().world(); this.world = baritone.getPlayerContext().world();
this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld(); this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld();
this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread); // TODO TODO TODO this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread);
this.toolSet = new ToolSet(player); this.toolSet = new ToolSet(player);
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(baritone.getPlayerContext(), false); this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway();
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether(); this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.getDimension().isNether();
this.canSprint = Baritone.settings().allowSprint.get() && player.getFoodStats().getFoodLevel() > 6; this.canSprint = Baritone.settings().allowSprint.value && player.getFoodStats().getFoodLevel() > 6;
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get(); this.placeBlockCost = Baritone.settings().blockPlacementPenalty.value;
this.allowBreak = Baritone.settings().allowBreak.get(); this.allowBreak = Baritone.settings().allowBreak.value;
this.allowParkour = Baritone.settings().allowParkour.get(); this.allowParkour = Baritone.settings().allowParkour.value;
this.allowParkourPlace = Baritone.settings().allowParkourPlace.get(); this.allowParkourPlace = Baritone.settings().allowParkourPlace.value;
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.get(); this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.get(); this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value;
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.get(); this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value;
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get(); this.allowDownward = Baritone.settings().allowDownward.value;
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get(); this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.value;
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.value;
int depth = EnchantmentHelper.getDepthStriderModifier(player); int depth = EnchantmentHelper.getDepthStriderModifier(player);
if (depth > 3) { if (depth > 3) {
depth = 3; depth = 3;
} }
float mult = depth / 3.0F; float mult = depth / 3.0F;
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult; this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult;
this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.get(); this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.value;
this.jumpPenalty = Baritone.settings().jumpPenalty.get(); this.backtrackCostFavoringCoefficient = Baritone.settings().backtrackCostFavoringCoefficient.value;
this.walkOnWaterOnePenalty = Baritone.settings().walkOnWaterOnePenalty.get(); this.jumpPenalty = Baritone.settings().jumpPenalty.value;
this.walkOnWaterOnePenalty = Baritone.settings().walkOnWaterOnePenalty.value;
// why cache these things here, why not let the movements just get directly from settings? // why cache these things here, why not let the movements just get directly from settings?
// because if some movements are calculated one way and others are calculated another way, // because if some movements are calculated one way and others are calculated another way,
// then you get a wildly inconsistent path that isn't optimal for either scenario. // then you get a wildly inconsistent path that isn't optimal for either scenario.
@@ -123,21 +131,32 @@ public class CalculationContext {
return get(x, y, z).getBlock(); return get(x, y, z).getBlock();
} }
public boolean canPlaceThrowawayAt(int x, int y, int z) { public double costOfPlacingAt(int x, int y, int z) {
if (!hasThrowaway) { // only true if allowPlace is true, see constructor if (!hasThrowaway) { // only true if allowPlace is true, see constructor
return false; return COST_INF;
} }
if (isPossiblyProtected(x, y, z)) { if (isPossiblyProtected(x, y, z)) {
return false; return COST_INF;
} }
return worldBorder.canPlaceAt(x, z); // TODO perhaps MovementHelper.canPlaceAgainst could also use this? if (!worldBorder.canPlaceAt(x, z)) {
// TODO perhaps MovementHelper.canPlaceAgainst could also use this?
return COST_INF;
}
return placeBlockCost;
} }
public boolean canBreakAt(int x, int y, int z) { public double breakCostMultiplierAt(int x, int y, int z) {
if (!allowBreak) { if (!allowBreak) {
return false; return COST_INF;
} }
return !isPossiblyProtected(x, y, z); if (isPossiblyProtected(x, y, z)) {
return COST_INF;
}
return 1;
}
public double placeBucketCost() {
return placeBlockCost; // shrug
} }
public boolean isPossiblyProtected(int x, int y, int z) { public boolean isPossiblyProtected(int x, int y, int z) {
@@ -23,7 +23,6 @@ import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.*; import baritone.api.utils.*;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import net.minecraft.block.BlockLiquid;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
@@ -34,7 +33,7 @@ import java.util.Optional;
public abstract class Movement implements IMovement, MovementHelper { public abstract class Movement implements IMovement, MovementHelper {
protected static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN}; public static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
protected final IBaritone baritone; protected final IBaritone baritone;
protected final IPlayerContext ctx; protected final IPlayerContext ctx;
@@ -76,31 +75,28 @@ public abstract class Movement implements IMovement, MovementHelper {
this(baritone, src, dest, toBreak, null); this(baritone, src, dest, toBreak, null);
} }
@Override public double getCost() throws NullPointerException {
public double getCost() { return cost;
}
public double getCost(CalculationContext context) {
if (cost == null) { if (cost == null) {
cost = calculateCost(new CalculationContext(baritone)); cost = calculateCost(context);
} }
return cost; return cost;
} }
public abstract double calculateCost(CalculationContext context); public abstract double calculateCost(CalculationContext context);
@Override public double recalculateCost(CalculationContext context) {
public double recalculateCost() {
cost = null; cost = null;
return getCost(); return getCost(context);
} }
public void override(double cost) { public void override(double cost) {
this.cost = cost; this.cost = cost;
} }
@Override
public double calculateCostWithoutCaching() {
return calculateCost(new CalculationContext(baritone));
}
/** /**
* Handles the execution of the latest Movement * Handles the execution of the latest Movement
* State, and offers a Status to the calling class. * State, and offers a Status to the calling class.
@@ -109,7 +105,7 @@ public abstract class Movement implements IMovement, MovementHelper {
*/ */
@Override @Override
public MovementStatus update() { public MovementStatus update() {
ctx.player().capabilities.isFlying = false; ctx.player().abilities.isFlying = false;
currentState = updateState(currentState); currentState = updateState(currentState);
if (MovementHelper.isLiquid(ctx, ctx.playerFeet())) { if (MovementHelper.isLiquid(ctx, ctx.playerFeet())) {
currentState.setInput(Input.JUMP, true); currentState.setInput(Input.JUMP, true);
@@ -143,7 +139,7 @@ public abstract class Movement implements IMovement, MovementHelper {
} }
boolean somethingInTheWay = false; boolean somethingInTheWay = false;
for (BetterBlockPos blockPos : positionsToBreak) { for (BetterBlockPos blockPos : positionsToBreak) {
if (!MovementHelper.canWalkThrough(ctx, blockPos) && !(BlockStateInterface.getBlock(ctx, blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try if (!MovementHelper.canWalkThrough(ctx, blockPos)) { // can't break air, so don't try
somethingInTheWay = true; somethingInTheWay = true;
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance()); Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) { if (reachable.isPresent()) {
@@ -159,8 +155,8 @@ public abstract class Movement implements IMovement, MovementHelper {
//i'm doing it anyway //i'm doing it anyway
//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().getEyePosition(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);
@@ -28,18 +28,23 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.ToolSet; import baritone.utils.ToolSet;
import net.minecraft.block.*; import net.minecraft.block.*;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.fluid.FlowingFluid;
import net.minecraft.fluid.Fluid;
import net.minecraft.fluid.IFluidState;
import net.minecraft.fluid.WaterFluid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.item.ItemPickaxe; import net.minecraft.init.Fluids;
import net.minecraft.item.ItemStack; import net.minecraft.pathfinding.PathType;
import net.minecraft.state.BooleanProperty;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos; 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;
/** /**
@@ -54,11 +59,11 @@ public interface MovementHelper extends ActionCosts, Helper {
return b == Blocks.ICE // ice becomes water, and water can mess up the path return b == Blocks.ICE // ice becomes water, and water can mess up the path
|| b instanceof BlockSilverfish // obvious reasons || b instanceof BlockSilverfish // obvious reasons
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason // call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|| bsi.get0(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side || !bsi.get0(x, y + 1, z).getFluidState().isEmpty()//don't break anything touching liquid on any side
|| bsi.get0(x + 1, y, z).getBlock() instanceof BlockLiquid || !bsi.get0(x + 1, y, z).getFluidState().isEmpty()
|| bsi.get0(x - 1, y, z).getBlock() instanceof BlockLiquid || !bsi.get0(x - 1, y, z).getFluidState().isEmpty()
|| bsi.get0(x, y, z + 1).getBlock() instanceof BlockLiquid || !bsi.get0(x, y, z + 1).getFluidState().isEmpty()
|| bsi.get0(x, y, z - 1).getBlock() instanceof BlockLiquid; || !bsi.get0(x, y, z - 1).getFluidState().isEmpty();
} }
static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) { static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) {
@@ -71,10 +76,10 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case if (block instanceof BlockAir) { // 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.COBWEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block == Blocks.BUBBLE_COLUMN || block instanceof BlockShulkerBox || block instanceof BlockSlab || block instanceof BlockTrapDoor) {
return false; return false;
} }
if (block instanceof BlockDoor || block instanceof BlockFenceGate) { if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
@@ -83,9 +88,10 @@ public interface MovementHelper extends ActionCosts, Helper {
// be opened by just interacting. // be opened by just interacting.
return block != Blocks.IRON_DOOR; return block != Blocks.IRON_DOOR;
} }
boolean snow = block instanceof BlockSnow; if (block instanceof BlockCarpet) {
boolean trapdoor = block instanceof BlockTrapDoor; return canWalkOn(bsi, x, y - 1, z);
if (snow || trapdoor) { }
if (block instanceof BlockSnowLayer) {
// we've already checked doors and fence gates // we've already checked doors and fence gates
// so the only remaining dynamic isPassables are snow and trapdoor // so the only remaining dynamic isPassables are snow and trapdoor
// if they're cached as a top block, we don't know their metadata // if they're cached as a top block, we don't know their metadata
@@ -93,37 +99,32 @@ public interface MovementHelper extends ActionCosts, Helper {
if (!bsi.worldContainsLoadedChunk(x, z)) { if (!bsi.worldContainsLoadedChunk(x, z)) {
return true; return true;
} }
if (snow) { // the check in BlockSnow.isPassable is layers < 5
// the check in BlockSnow.isPassable is layers < 5 // while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling
// while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling if (state.get(BlockSnowLayer.LAYERS) >= 3) {
if (state.getValue(BlockSnow.LAYERS) >= 3) { return false;
return false;
}
// ok, it's low enough we could walk through it, but is it supported?
return canWalkOn(bsi, x, y - 1, z);
} }
if (trapdoor) { // ok, it's low enough we could walk through it, but is it supported?
return !state.getValue(BlockTrapDoor.OPEN); // see BlockTrapDoor.isPassable return canWalkOn(bsi, x, y - 1, z);
}
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) { IFluidState fluidState = state.getFluidState();
if (Baritone.settings().assumeWalkOnWater.get()) { if (fluidState.getFluid() instanceof WaterFluid) {
if (Baritone.settings().assumeWalkOnWater.value) {
return false; return false;
} }
IBlockState up = bsi.get0(x, y + 1, z); IBlockState up = bsi.get0(x, y + 1, z);
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) { if (!up.getFluidState().isEmpty() || up.getBlock() instanceof BlockLilyPad) {
return false; return false;
} }
return block == Blocks.WATER || block == Blocks.FLOWING_WATER; return true;
} }
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;" // every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
// has already been accounted for above // has already been accounted for above
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null // therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
return block.isPassable(null, null); return state.allowsMovement(null, null, PathType.LAND);
} }
/** /**
@@ -142,26 +143,28 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean fullyPassable(IBlockState state) { static boolean fullyPassable(IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.AIR) { // early return for most common case if (block instanceof BlockAir) { // early return for most common case
return true; return true;
} }
// exceptions - blocks that are isPassable true, but we can't actually jump through // exceptions - blocks that are isPassable true, but we can't actually jump through
if (block == Blocks.FIRE if (block == Blocks.FIRE
|| block == Blocks.TRIPWIRE || block == Blocks.TRIPWIRE
|| block == Blocks.WEB || block == Blocks.COBWEB
|| block == Blocks.VINE || block == Blocks.VINE
|| block == Blocks.LADDER || block == Blocks.LADDER
|| block == Blocks.COCOA || block == Blocks.COCOA
|| block instanceof BlockDoor || block instanceof BlockDoor
|| block instanceof BlockFenceGate || block instanceof BlockFenceGate
|| block instanceof BlockSnow || block instanceof BlockSnow
|| block instanceof BlockLiquid || !state.getFluidState().isEmpty()
|| block instanceof BlockTrapDoor || block instanceof BlockTrapDoor
|| block instanceof BlockEndPortal) { || block instanceof BlockEndPortal
|| block instanceof BlockSkull
|| block instanceof BlockShulkerBox) {
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
return block.isPassable(null, null); return state.allowsMovement(null, null, PathType.LAND);
} }
static boolean isReplacable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) { static boolean isReplacable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
@@ -176,20 +179,19 @@ public interface MovementHelper extends ActionCosts, Helper {
* } * }
*/ */
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.AIR || isWater(block)) { if (block instanceof BlockAir) {
// early return for common cases hehe // early return for common cases hehe
return true; return true;
} }
if (block instanceof BlockSnow) { if (block instanceof BlockSnowLayer) {
// as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible) // as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
if (!bsi.worldContainsLoadedChunk(x, z)) { if (!bsi.worldContainsLoadedChunk(x, z)) {
return true; return true;
} }
return state.getValue(BlockSnow.LAYERS) == 1; return state.get(BlockSnowLayer.LAYERS) == 1;
} }
if (block instanceof BlockDoublePlant) { if (block == Blocks.LARGE_FERN || block == Blocks.TALL_GRASS) {
BlockDoublePlant.EnumPlantType kek = state.getValue(BlockDoublePlant.VARIANT); return true;
return kek == BlockDoublePlant.EnumPlantType.FERN || kek == BlockDoublePlant.EnumPlantType.GRASS;
} }
return state.getMaterial().isReplaceable(); return state.getMaterial().isReplaceable();
} }
@@ -217,16 +219,16 @@ public interface MovementHelper extends ActionCosts, Helper {
return true; return true;
} }
return state.getValue(BlockFenceGate.OPEN); return state.get(BlockFenceGate.OPEN);
} }
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) { static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, BooleanProperty propertyOpen) {
if (playerPos.equals(blockPos)) { if (playerPos.equals(blockPos)) {
return false; return false;
} }
EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis(); EnumFacing.Axis facing = blockState.get(BlockHorizontal.HORIZONTAL_FACING).getAxis();
boolean open = blockState.getValue(propertyOpen); boolean open = blockState.get(propertyOpen);
EnumFacing.Axis playerFacing; EnumFacing.Axis playerFacing;
if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) { if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) {
@@ -240,14 +242,15 @@ public interface MovementHelper extends ActionCosts, Helper {
return (facing == playerFacing) == open; return (facing == playerFacing) == open;
} }
static boolean avoidWalkingInto(Block block) { static boolean avoidWalkingInto(IBlockState state) {
return block instanceof BlockLiquid Block block = state.getBlock();
|| block instanceof BlockDynamicLiquid return !state.getFluidState().isEmpty()
|| block == Blocks.MAGMA || block == Blocks.MAGMA_BLOCK
|| block == Blocks.CACTUS || block == Blocks.CACTUS
|| block == Blocks.FIRE || block == Blocks.FIRE
|| block == Blocks.END_PORTAL || block == Blocks.END_PORTAL
|| block == Blocks.WEB; || block == Blocks.COBWEB
|| block == Blocks.BUBBLE_COLUMN;
} }
/** /**
@@ -264,7 +267,7 @@ public interface MovementHelper extends ActionCosts, Helper {
*/ */
static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) { static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
Block block = state.getBlock(); Block block = state.getBlock();
if (block == Blocks.AIR || block == Blocks.MAGMA) { if (block instanceof BlockAir || block == Blocks.MAGMA_BLOCK || block == Blocks.BUBBLE_COLUMN) {
// early return for most common case (air) // early return for most common case (air)
// plus magma, which is a normal cube but it hurts you // plus magma, which is a normal cube but it hurts you
return false; return false;
@@ -272,7 +275,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (state.isBlockNormalCube()) { if (state.isBlockNormalCube()) {
return true; return true;
} }
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.value)) { // TODO reconsider this
return true; return true;
} }
if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) { if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) {
@@ -281,30 +284,31 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) { if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
return true; return true;
} }
if (isWater(block)) { if (isWater(state)) {
// 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(); IBlockState upState = bsi.get0(x, y + 1, z);
if (up == Blocks.WATERLILY) { Block up = upState.getBlock();
if (up == Blocks.LILY_PAD || up instanceof BlockCarpet) {
return true; return true;
} }
if (isFlowing(state) || block == Blocks.FLOWING_WATER) { if (isFlowing(x, y, z, state, bsi) || upState.getFluidState().getFluid() == Fluids.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(upState) && !Baritone.settings().assumeWalkOnWater.value;
} }
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it // if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
// if assumeWalkOnWater is off, we can only walk on water if there is water above it // if assumeWalkOnWater is off, we can only walk on water if there is water above it
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.get(); return isWater(upState) ^ Baritone.settings().assumeWalkOnWater.value;
} }
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) { if (Baritone.settings().assumeWalkOnLava.value && isLava(state) && !isFlowing(x, y, z, state, bsi)) {
return true;
}
if (block == Blocks.GLASS || block instanceof BlockStainedGlass) {
return true; return true;
} }
if (block instanceof BlockSlab) { if (block instanceof BlockSlab) {
if (!Baritone.settings().allowWalkOnBottomSlab.get()) { if (!Baritone.settings().allowWalkOnBottomSlab.value) {
if (((BlockSlab) block).isDouble()) { return state.isTopSolid();
return true;
}
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
} }
return true; return true;
} }
@@ -324,20 +328,22 @@ public interface MovementHelper extends ActionCosts, Helper {
} }
static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z) { static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z) {
return canPlaceAgainst(bsi.get0(x, y, z)); return canPlaceAgainst(bsi, x, y, z, bsi.get0(x, y, z));
} }
static boolean canPlaceAgainst(BlockStateInterface bsi, BlockPos pos) { static boolean canPlaceAgainst(BlockStateInterface bsi, BlockPos pos) {
return canPlaceAgainst(bsi.get0(pos.getX(), pos.getY(), pos.getZ())); return canPlaceAgainst(bsi, pos.getX(), pos.getY(), pos.getZ());
} }
static boolean canPlaceAgainst(IPlayerContext ctx, BlockPos pos) { static boolean canPlaceAgainst(IPlayerContext ctx, BlockPos pos) {
return canPlaceAgainst(new BlockStateInterface(ctx), pos); return canPlaceAgainst(new BlockStateInterface(ctx), pos);
} }
static boolean canPlaceAgainst(IBlockState state) { static boolean canPlaceAgainst(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
// TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it // can we look at the center of a side face of this block and likely be able to place?
return state.isBlockNormalCube(); // (thats how this check is used)
// therefore dont include weird things that we technically could place against (like carpet) but practically can't
return state.isBlockNormalCube() || state.isFullCube() || state.getBlock() == Blocks.GLASS || state.getBlock() instanceof BlockStainedGlass;
} }
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) { static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
@@ -347,13 +353,14 @@ public interface MovementHelper extends ActionCosts, Helper {
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) { static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
Block block = state.getBlock(); Block block = state.getBlock();
if (!canWalkThrough(context.bsi, x, y, z, state)) { if (!canWalkThrough(context.bsi, x, y, z, state)) {
if (!context.canBreakAt(x, y, z)) { double mult = context.breakCostMultiplierAt(x, y, z);
if (mult >= COST_INF) {
return COST_INF; return COST_INF;
} }
if (avoidBreaking(context.bsi, x, y, z, state)) { if (avoidBreaking(context.bsi, x, y, z, state)) {
return COST_INF; return COST_INF;
} }
if (block instanceof BlockLiquid) { if (!state.getFluidState().isEmpty()) {
return COST_INF; return COST_INF;
} }
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
@@ -364,6 +371,7 @@ public interface MovementHelper extends ActionCosts, Helper {
double result = m / strVsBlock; double result = m / strVsBlock;
result += context.breakBlockAdditionalCost; result += context.breakBlockAdditionalCost;
result *= mult;
if (includeFalling) { if (includeFalling) {
IBlockState above = context.get(x, y + 1, z); IBlockState above = context.get(x, y + 1, z);
if (above.getBlock() instanceof BlockFalling) { if (above.getBlock() instanceof BlockFalling) {
@@ -377,8 +385,7 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean isBottomSlab(IBlockState state) { static boolean isBottomSlab(IBlockState state) {
return state.getBlock() instanceof BlockSlab return state.getBlock() instanceof BlockSlab
&& !((BlockSlab) state.getBlock()).isDouble() && state.get(BlockSlab.TYPE) == SlabType.BOTTOM;
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
} }
/** /**
@@ -402,48 +409,11 @@ public interface MovementHelper extends ActionCosts, Helper {
ctx.player().inventory.currentItem = ts.getBestSlot(b.getBlock()); ctx.player().inventory.currentItem = ts.getBestSlot(b.getBlock());
} }
static boolean throwaway(IPlayerContext ctx, boolean select) {
EntityPlayerSP p = ctx.player();
NonNullList<ItemStack> inv = p.inventory.mainInventory;
for (byte i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
// this usage of settings() is okay because it's only called once during pathing
// (while creating the CalculationContext at the very beginning)
// and then it's called during execution
// since this function is never called during cost calculation, we don't need to migrate
// acceptableThrowawayItems to the CalculationContext
if (Baritone.settings().acceptableThrowawayItems.get().contains(item.getItem())) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
if (Baritone.settings().acceptableThrowawayItems.get().contains(p.inventory.offHandInventory.get(0).getItem())) {
// main hand takes precedence over off hand
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
// so we need to select in the main hand something that doesn't right click
// so not a shovel, not a hoe, not a block, etc
for (byte i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
}
return false;
}
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);
} }
@@ -452,11 +422,12 @@ public interface MovementHelper extends ActionCosts, Helper {
* Returns whether or not the specified block is * Returns whether or not the specified block is
* water, regardless of whether or not it is flowing. * water, regardless of whether or not it is flowing.
* *
* @param b The block * @param state The block state
* @return Whether or not the block is water * @return Whether or not the block is water
*/ */
static boolean isWater(Block b) { static boolean isWater(IBlockState state) {
return b == Blocks.FLOWING_WATER || b == Blocks.WATER; Fluid f = state.getFluidState().getFluid();
return f == Fluids.WATER || f == Fluids.FLOWING_WATER;
} }
/** /**
@@ -468,11 +439,12 @@ public interface MovementHelper extends ActionCosts, Helper {
* @return Whether or not the block is water * @return Whether or not the block is water
*/ */
static boolean isWater(IPlayerContext ctx, BlockPos bp) { static boolean isWater(IPlayerContext ctx, BlockPos bp) {
return isWater(BlockStateInterface.getBlock(ctx, bp)); return isWater(BlockStateInterface.get(ctx, bp));
} }
static boolean isLava(Block b) { static boolean isLava(IBlockState state) {
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA; Fluid f = state.getFluidState().getFluid();
return f == Fluids.LAVA || f == Fluids.FLOWING_LAVA;
} }
/** /**
@@ -483,23 +455,46 @@ public interface MovementHelper extends ActionCosts, Helper {
* @return Whether or not the block is a liquid * @return Whether or not the block is a liquid
*/ */
static boolean isLiquid(IPlayerContext ctx, BlockPos p) { static boolean isLiquid(IPlayerContext ctx, BlockPos p) {
return BlockStateInterface.getBlock(ctx, p) instanceof BlockLiquid; return isLiquid(BlockStateInterface.get(ctx, p));
} }
static boolean isFlowing(IBlockState state) { static boolean isLiquid(IBlockState blockState) {
// Will be IFluidState in 1.13 return !blockState.getFluidState().isEmpty();
return state.getBlock() instanceof BlockLiquid
&& state.getValue(BlockLiquid.LEVEL) != 0;
} }
static boolean possiblyFlowing(IBlockState state) {
IFluidState fluidState = state.getFluidState();
return fluidState.getFluid() instanceof FlowingFluid
&& fluidState.getFluid().getLevel(fluidState) != 8;
}
static boolean isFlowing(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
IFluidState fluidState = state.getFluidState();
if (!(fluidState.getFluid() instanceof FlowingFluid)) {
return false;
}
if (fluidState.getFluid().getLevel(fluidState) != 8) {
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)) {
//if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block
if (!throwaway(ctx, true)) {
Helper.HELPER.logDebug("bb pls get me some blocks. dirt or cobble"); Helper.HELPER.logDebug("bb pls get me some blocks. dirt or cobble");
state.setStatus(MovementStatus.UNREACHABLE); state.setStatus(MovementStatus.UNREACHABLE);
return PlaceResult.NO_OPTION; return PlaceResult.NO_OPTION;
@@ -509,7 +504,7 @@ public interface MovementHelper extends ActionCosts, Helper {
double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D; double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D;
Rotation place = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations()); Rotation place = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations());
RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance()); RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance());
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) { if (res != null && res.type == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) {
state.setTarget(new MovementState.MovementTarget(place, true)); state.setTarget(new MovementState.MovementTarget(place, true));
found = true; found = true;
@@ -53,14 +53,16 @@ public class MovementAscend extends Movement {
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
IBlockState toPlace = context.get(destX, y, destZ); IBlockState toPlace = context.get(destX, y, destZ);
boolean hasToPlace = false; double additionalPlacementCost = 0;
if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) { if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) {
if (!context.canPlaceThrowawayAt(destX, y, destZ)) { additionalPlacementCost = context.costOfPlacingAt(destX, y, destZ);
if (additionalPlacementCost >= COST_INF) {
return COST_INF; return COST_INF;
} }
if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi)) { if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi)) {
return COST_INF; return COST_INF;
} }
boolean foundPlaceOption = false;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset(); int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
int againstY = y + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset(); int againstY = y + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
@@ -69,11 +71,11 @@ public class MovementAscend extends Movement {
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
hasToPlace = true; foundPlaceOption = true;
break; break;
} }
} }
if (!hasToPlace) { // didn't find a valid place =( if (!foundPlaceOption) { // didn't find a valid place =(
return COST_INF; return COST_INF;
} }
} }
@@ -124,10 +126,7 @@ public class MovementAscend extends Movement {
walk += context.jumpPenalty; walk += context.jumpPenalty;
} }
double totalCost = walk; double totalCost = walk + additionalPlacementCost;
if (hasToPlace) {
totalCost += context.placeBlockCost;
}
// start with srcUp2 since we already have its state // start with srcUp2 since we already have its state
// includeFalling isn't needed because of the falling check above -- if srcUp3 is falling we will have already exited with COST_INF if we'd actually have to break it // includeFalling isn't needed because of the falling check above -- if srcUp3 is falling we will have already exited with COST_INF if we'd actually have to break it
totalCost += MovementHelper.getMiningDurationTicks(context, x, y + 2, z, srcUp2, false); totalCost += MovementHelper.getMiningDurationTicks(context, x, y + 2, z, srcUp2, false);
@@ -155,6 +154,10 @@ public class MovementAscend extends Movement {
return state.setStatus(MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
if (ctx.playerFeet().y < src.y) {
return state.setStatus(MovementStatus.UNREACHABLE);
}
IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace); IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace);
if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) { if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) {
ticksWithoutPlacement++; ticksWithoutPlacement++;
@@ -176,20 +179,25 @@ public class MovementAscend extends Movement {
return state; // don't jump while walking from a non double slab into a bottom slab return state; // don't jump while walking from a non double slab into a bottom slab
} }
if (Baritone.settings().assumeStep.get() || ctx.playerFeet().equals(src.up())) { if (Baritone.settings().assumeStep.value || ctx.playerFeet().equals(src.up())) {
// no need to hit space if we're already jumping // no need to hit space if we're already jumping
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);
// System.out.println(flatDistToNext + " " + sideDist);
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);
}
if (flatDistToNext > 1.2 || sideDist > 0.2) { if (flatDistToNext > 1.2 || sideDist > 0.2) {
return state; return state;
} }
@@ -200,7 +208,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));
@@ -211,4 +219,10 @@ public class MovementAscend extends Movement {
} }
return true; return true;
} }
@Override
public boolean safeToCancel(MovementState state) {
// if we had to place, don't allow pause
return state.getStatus() != MovementStatus.RUNNING || ticksWithoutPlacement == 0;
}
} }
@@ -122,7 +122,7 @@ public class MovementDescend extends Movement {
// and potentially replace the water we're going to fall into // and potentially replace the water we're going to fall into
return false; return false;
} }
if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) { if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below)) {
return false; return false;
} }
double costSoFar = 0; double costSoFar = 0;
@@ -137,13 +137,14 @@ public class MovementDescend extends Movement {
IBlockState ontoBlock = context.get(destX, newY, destZ); IBlockState ontoBlock = context.get(destX, newY, destZ);
int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar; double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar;
if ((ontoBlock.getBlock() == Blocks.WATER || ontoBlock.getBlock() == Blocks.FLOWING_WATER) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { if (MovementHelper.isWater(ontoBlock)) {
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad if (!MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works) return false;
}
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)) {
@@ -186,7 +187,7 @@ public class MovementDescend extends Movement {
res.x = destX; res.x = destX;
res.y = newY + 1;// this is the block we're falling onto, so dest is +1 res.y = newY + 1;// this is the block we're falling onto, so dest is +1
res.z = destZ; res.z = destZ;
res.cost = tentativeCost + context.placeBlockCost; res.cost = tentativeCost + context.placeBucketCost();
return true; return true;
} else { } else {
return false; return false;
@@ -202,7 +203,8 @@ public class MovementDescend extends Movement {
} }
BlockPos playerFeet = ctx.playerFeet(); BlockPos playerFeet = ctx.playerFeet();
if (playerFeet.equals(dest) && (MovementHelper.isLiquid(ctx, dest) || ctx.player().posY - playerFeet.getY() < 0.094)) { // lilypads BlockPos fakeDest = new BlockPos(dest.getX() * 2 - src.getX(), dest.getY(), dest.getZ() * 2 - src.getZ());
if ((playerFeet.equals(dest) || playerFeet.equals(fakeDest)) && (MovementHelper.isLiquid(ctx, dest) || ctx.player().posY - dest.getY() < 0.5)) { // lilypads
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately // Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
return state.setStatus(MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
/* else { /* else {
@@ -210,11 +212,11 @@ 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.getEyePosition(1.0F),
new Vec3d(destX, dest.getY(), destZ), new Vec3d(destX, dest.getY(), destZ),
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch), new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
false false
@@ -228,12 +230,8 @@ public class MovementDescend extends Movement {
double z = ctx.player().posZ - (src.getZ() + 0.5); double z = ctx.player().posZ - (src.getZ() + 0.5);
double fromStart = Math.sqrt(x * x + z * z); double fromStart = Math.sqrt(x * x + z * z);
if (!playerFeet.equals(dest) || ab > 0.25) { if (!playerFeet.equals(dest) || ab > 0.25) {
BlockPos fakeDest = new BlockPos(dest.getX() * 2 - src.getX(), dest.getY(), dest.getZ() * 2 - src.getZ()); if (numTicks++ < 20 && fromStart < 1.25) {
if (numTicks++ < 20) {
MovementHelper.moveTowards(ctx, state, fakeDest); MovementHelper.moveTowards(ctx, state, fakeDest);
if (fromStart > 1.25) {
state.getTarget().rotation = new Rotation(state.getTarget().rotation.getYaw() + 180F, state.getTarget().rotation.getPitch());
}
} else { } else {
MovementHelper.moveTowards(ctx, state, dest); MovementHelper.moveTowards(ctx, state, dest);
} }
@@ -245,11 +243,20 @@ 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.get(ctx, into.up(y)))) {
return true; return true;
} }
} }
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;
@@ -90,12 +91,12 @@ public class MovementDiagonal extends Movement {
if (fromDown == Blocks.SOUL_SAND) { if (fromDown == Blocks.SOUL_SAND) {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
} }
Block cuttingOver1 = context.get(x, y - 1, destZ).getBlock(); IBlockState cuttingOver1 = context.get(x, y - 1, destZ);
if (cuttingOver1 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver1)) { if (cuttingOver1.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver1)) {
return; return;
} }
Block cuttingOver2 = context.get(destX, y - 1, z).getBlock(); IBlockState cuttingOver2 = context.get(destX, y - 1, z);
if (cuttingOver2 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver2)) { if (cuttingOver2.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver2)) {
return; return;
} }
IBlockState pb0 = context.get(x, y, destZ); IBlockState pb0 = context.get(x, y, destZ);
@@ -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) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3))) {
// 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,13 +124,14 @@ 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) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1))) {
// 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;
} }
boolean water = false; boolean water = false;
Block startIn = context.getBlock(x, y, z); IBlockState startState = context.get(x, y, z);
if (MovementHelper.isWater(startIn) || MovementHelper.isWater(destInto.getBlock())) { Block startIn = startState.getBlock();
if (MovementHelper.isWater(startState) || MovementHelper.isWater(destInto)) {
// Ignore previous multiplier // Ignore previous multiplier
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water // Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
// Not even touching the blocks below // Not even touching the blocks below
@@ -173,13 +175,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.value) {
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;
@@ -48,6 +48,9 @@ public class MovementDownward extends Movement {
} }
public static double cost(CalculationContext context, int x, int y, int z) { public static double cost(CalculationContext context, int x, int y, int z) {
if (!context.allowDownward) {
return COST_INF;
}
if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) { if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) {
return COST_INF; return COST_INF;
} }
@@ -34,6 +34,7 @@ import net.minecraft.block.Block;
import net.minecraft.block.BlockLadder; import net.minecraft.block.BlockLadder;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.InventoryPlayer; import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.fluid.WaterFluid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Items; import net.minecraft.init.Items;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
@@ -78,12 +79,13 @@ 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(); IBlockState destState = ctx.world().getBlockState(dest);
boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER; Block destBlock = destState.getBlock();
boolean isWater = destState.getFluidState().getFluid() instanceof WaterFluid;
if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) { if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) {
if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) { if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().getDimension().isNether()) {
return state.setStatus(MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
@@ -93,7 +95,7 @@ public class MovementFall extends Movement {
targetRotation = new Rotation(toDest.getYaw(), 90.0F); targetRotation = new Rotation(toDest.getYaw(), 90.0F);
RayTraceResult trace = ctx.objectMouseOver(); RayTraceResult trace = ctx.objectMouseOver();
if (trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK && (trace.getBlockPos().equals(dest) || trace.getBlockPos().equals(dest.down()))) { if (trace != null && trace.type == RayTraceResult.Type.BLOCK && (trace.getBlockPos().equals(dest) || trace.getBlockPos().equals(dest.down()))) {
state.setInput(Input.CLICK_RIGHT, true); state.setInput(Input.CLICK_RIGHT, true);
} }
} }
@@ -141,7 +143,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;
} }
@@ -150,7 +152,7 @@ public class MovementFall extends Movement {
for (int i = 0; i < 15; i++) { for (int i = 0; i < 15; i++) {
IBlockState state = ctx.world().getBlockState(ctx.playerFeet().down(i)); IBlockState state = ctx.world().getBlockState(ctx.playerFeet().down(i));
if (state.getBlock() == Blocks.LADDER) { if (state.getBlock() == Blocks.LADDER) {
return state.getValue(BlockLadder.FACING); return state.get(BlockLadder.FACING);
} }
} }
return null; return null;
@@ -30,7 +30,9 @@ import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block; import net.minecraft.block.Block;
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.fluid.WaterFluid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Fluids;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
public class MovementParkour extends Movement { public class MovementParkour extends Movement {
@@ -72,7 +74,7 @@ public class MovementParkour extends Movement {
// second most common case -- we could just traverse not parkour // second most common case -- we could just traverse not parkour
return; return;
} }
if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks if (MovementHelper.avoidWalkingInto(adj) && !(adj.getFluidState().getFluid() instanceof WaterFluid)) { // magma sucks
return; return;
} }
if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) { if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) {
@@ -85,7 +87,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.getFluidState().getFluid() != Fluids.EMPTY) {
return; return;
} }
int maxJump; int maxJump;
@@ -119,9 +121,11 @@ public class MovementParkour extends Movement {
if (!context.allowParkourPlace) { if (!context.allowParkourPlace) {
return; return;
} }
// time 2 pop off with that dank skynet parkour place
int destX = x + 4 * xDiff; int destX = x + 4 * xDiff;
int destZ = z + 4 * zDiff; int destZ = z + 4 * zDiff;
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) { double placeCost = context.costOfPlacingAt(destX, y - 1, destZ);
if (placeCost >= COST_INF) {
return; return;
} }
IBlockState toReplace = context.get(destX, y - 1, destZ); IBlockState toReplace = context.get(destX, y - 1, destZ);
@@ -139,7 +143,7 @@ public class MovementParkour extends Movement {
res.x = destX; res.x = destX;
res.y = y; res.y = y;
res.z = destZ; res.z = destZ;
res.cost = costFromJumpDistance(4) + context.placeBlockCost + context.jumpPenalty; res.cost = costFromJumpDistance(4) + placeCost + context.jumpPenalty;
return; return;
} }
} }
@@ -187,6 +191,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);
} }
@@ -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;
@@ -36,6 +37,7 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
import java.util.Objects; import java.util.Objects;
import java.util.Optional;
public class MovementPillar extends Movement { public class MovementPillar extends Movement {
@@ -49,14 +51,15 @@ public class MovementPillar extends Movement {
} }
public static double cost(CalculationContext context, int x, int y, int z) { public static double cost(CalculationContext context, int x, int y, int z) {
Block from = context.get(x, y, z).getBlock(); IBlockState fromState = context.get(x, y, z);
Block from = fromState.getBlock();
boolean ladder = from == Blocks.LADDER || from == Blocks.VINE; boolean ladder = from == Blocks.LADDER || from == Blocks.VINE;
IBlockState fromDown = context.get(x, y - 1, z); IBlockState fromDown = context.get(x, y - 1, z);
if (!ladder) { if (!ladder) {
if (fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE) { if (fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE) {
return COST_INF; // can't pillar from a ladder or vine onto something that isn't also climbable return COST_INF; // can't pillar from a ladder or vine onto something that isn't also climbable
} }
if (fromDown.getBlock() instanceof BlockSlab && !((BlockSlab) fromDown.getBlock()).isDouble() && fromDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) { if (fromDown.getBlock() instanceof BlockSlab && !fromDown.isTopSolid()) {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder return COST_INF; // can't pillar up from a bottom slab onto a non ladder
} }
} }
@@ -68,17 +71,25 @@ public class MovementPillar extends Movement {
if (toBreakBlock instanceof BlockFenceGate) { // see issue #172 if (toBreakBlock instanceof BlockFenceGate) { // see issue #172
return COST_INF; return COST_INF;
} }
Block srcUp = null; IBlockState srcUp = null;
if (MovementHelper.isWater(toBreakBlock) && MovementHelper.isWater(from)) { // TODO should this also be allowed if toBreakBlock is air? if (MovementHelper.isWater(toBreak) && MovementHelper.isWater(fromState)) { // TODO should this also be allowed if toBreakBlock is air?
srcUp = context.get(x, y + 1, z).getBlock(); srcUp = context.get(x, y + 1, z);
if (MovementHelper.isWater(srcUp)) { if (MovementHelper.isWater(srcUp)) {
return LADDER_UP_ONE_COST; // allow ascending pillars of water, but only if we're already in one return LADDER_UP_ONE_COST; // allow ascending pillars of water, but only if we're already in one
} }
} }
if (!ladder && !context.canPlaceThrowawayAt(x, y, z)) { // we need to place a block where we started to jump on it double placeCost = 0;
return COST_INF; if (!ladder) {
// we need to place a block where we started to jump on it
placeCost = context.costOfPlacingAt(x, y, z);
if (placeCost >= COST_INF) {
return COST_INF;
}
if (fromDown.getBlock() instanceof BlockAir) {
placeCost += 0.1; // slightly (1/200th of a second) penalize pillaring on what's currently air
}
} }
if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && context.assumeWalkOnWater)) { if ((MovementHelper.isLiquid(fromState) && !MovementHelper.canPlaceAgainst(context.bsi, x, y - 1, z, fromDown)) || (MovementHelper.isLiquid(fromDown) && context.assumeWalkOnWater)) {
// otherwise, if we're standing in water, we cannot pillar // otherwise, if we're standing in water, we cannot pillar
// if we're standing on water and assumeWalkOnWater is true, we cannot pillar // if we're standing on water and assumeWalkOnWater is true, we cannot pillar
// if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again // if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again
@@ -96,9 +107,9 @@ public class MovementPillar extends Movement {
if (check.getBlock() instanceof BlockFalling) { if (check.getBlock() instanceof BlockFalling) {
// see MovementAscend's identical check for breaking a falling block above our head // see MovementAscend's identical check for breaking a falling block above our head
if (srcUp == null) { if (srcUp == null) {
srcUp = context.get(x, y + 1, z).getBlock(); srcUp = context.get(x, y + 1, z);
} }
if (!(toBreakBlock instanceof BlockFalling) || !(srcUp instanceof BlockFalling)) { if (!(toBreakBlock instanceof BlockFalling) || !(srcUp.getBlock() instanceof BlockFalling)) {
return COST_INF; return COST_INF;
} }
} }
@@ -114,7 +125,7 @@ public class MovementPillar extends Movement {
if (ladder) { if (ladder) {
return LADDER_UP_ONE_COST + hardness * 5; return LADDER_UP_ONE_COST + hardness * 5;
} else { } else {
return JUMP_ONE_BLOCK_COST + context.placeBlockCost + context.jumpPenalty + hardness; return JUMP_ONE_BLOCK_COST + placeCost + context.jumpPenalty + hardness;
} }
} }
@@ -148,10 +159,14 @@ public class MovementPillar extends Movement {
return state; return state;
} }
if (ctx.playerFeet().y < src.y) {
return state.setStatus(MovementStatus.UNREACHABLE);
}
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) && 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);
@@ -163,7 +178,7 @@ public class MovementPillar extends Movement {
} }
boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE; boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE;
boolean vine = fromDown.getBlock() == Blocks.VINE; boolean vine = fromDown.getBlock() == Blocks.VINE;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getEyePosition(1.0F),
VecUtils.getBlockPosCenter(positionToPlace), VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch)); new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
if (!ladder) { if (!ladder) {
@@ -172,7 +187,7 @@ public class MovementPillar extends Movement {
boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder; boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder;
if (ladder) { if (ladder) {
BlockPos against = vine ? getAgainst(new CalculationContext(baritone), src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite()); BlockPos against = vine ? getAgainst(new CalculationContext(baritone), src) : src.offset(fromDown.get(BlockLadder.FACING).getOpposite());
if (against == null) { if (against == null) {
logDebug("Unable to climb vines"); logDebug("Unable to climb vines");
return state.setStatus(MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
@@ -194,7 +209,7 @@ public class MovementPillar extends Movement {
return state; return state;
} else { } else {
// Get ready to place a throwaway block // Get ready to place a throwaway block
if (!MovementHelper.throwaway(ctx, true)) { if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(src.x, src.y, src.z)) {
return state.setStatus(MovementStatus.UNREACHABLE); return state.setStatus(MovementStatus.UNREACHABLE);
} }
@@ -222,11 +237,18 @@ public class MovementPillar extends Movement {
if (!blockIsThere) { if (!blockIsThere) {
Block fr = BlockStateInterface.get(ctx, src).getBlock(); IBlockState frState = BlockStateInterface.get(ctx, src);
if (!(fr instanceof BlockAir || fr.isReplaceable(ctx.world(), src))) { Block fr = frState.getBlock();
// TODO: Evaluate usage of getMaterial().isReplaceable()
if (!(fr instanceof BlockAir || frState.getMaterial().isReplaceable())) {
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), src, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
state.setTarget(new MovementState.MovementTarget(reachable.get(), true));
}
state.setInput(Input.JUMP, false); // breaking is like 5x slower when you're jumping
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);
} }
} }
@@ -30,12 +30,11 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import net.minecraft.block.Block; import net.minecraft.block.*;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockFenceGate;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.fluid.WaterFluid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.state.properties.SlabType;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d; import net.minecraft.util.math.Vec3d;
@@ -67,11 +66,12 @@ public class MovementTraverse extends Movement {
IBlockState pb0 = context.get(destX, y + 1, destZ); IBlockState pb0 = context.get(destX, y + 1, destZ);
IBlockState pb1 = context.get(destX, y, destZ); IBlockState pb1 = context.get(destX, y, destZ);
IBlockState destOn = context.get(destX, y - 1, destZ); IBlockState destOn = context.get(destX, y - 1, destZ);
Block srcDown = context.getBlock(x, y - 1, z); IBlockState down = context.get(x, y - 1, z);
Block srcDown = down.getBlock();
if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
double WC = WALK_ONE_BLOCK_COST; double WC = WALK_ONE_BLOCK_COST;
boolean water = false; boolean water = false;
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) { if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) {
WC = context.waterWalkSpeed; WC = context.waterWalkSpeed;
water = true; water = true;
} else { } else {
@@ -108,12 +108,13 @@ public class MovementTraverse extends Movement {
return COST_INF; return COST_INF;
} }
if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) { if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) {
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock()); boolean throughWater = MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1);
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) { if (MovementHelper.isWater(destOn) && throughWater) {
// this happens when assume walk on water is true and this is a traverse in water, which isn't allowed // this happens when assume walk on water is true and this is a traverse in water, which isn't allowed
return COST_INF; return COST_INF;
} }
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) { double placeCost = context.costOfPlacingAt(destX, y - 1, destZ);
if (placeCost >= COST_INF) {
return COST_INF; return COST_INF;
} }
double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false); double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false);
@@ -130,18 +131,18 @@ public class MovementTraverse extends Movement {
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option
return WC + context.placeBlockCost + hardness1 + hardness2; return WC + placeCost + hardness1 + hardness2;
} }
} }
// now that we've checked all possible directions to side place, we actually need to backplace // now that we've checked all possible directions to side place, we actually need to backplace
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && !((BlockSlab) srcDown).isDouble())) { if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && down.get(BlockSlab.TYPE) != SlabType.DOUBLE)) {
return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/ return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/
} }
if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) { if (down.getFluidState() instanceof WaterFluid) {
return COST_INF; // this is obviously impossible return COST_INF; // this is obviously impossible
} }
WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol
return WC + context.placeBlockCost + hardness1 + hardness2; return WC + placeCost + hardness1 + hardness2;
} }
return COST_INF; return COST_INF;
} }
@@ -150,9 +151,11 @@ public class MovementTraverse extends Movement {
@Override @Override
public MovementState updateState(MovementState state) { public MovementState updateState(MovementState state) {
super.updateState(state); super.updateState(state);
IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]);
if (state.getStatus() != MovementStatus.RUNNING) { if (state.getStatus() != MovementStatus.RUNNING) {
// if the setting is enabled // if the setting is enabled
if (!Baritone.settings().walkWhileBreaking.get()) { if (!Baritone.settings().walkWhileBreaking.value) {
return state; return state;
} }
// and if we're prepping (aka mining the block in front) // and if we're prepping (aka mining the block in front)
@@ -160,10 +163,10 @@ public class MovementTraverse extends Movement {
return state; return state;
} }
// and if it's fine to walk into the blocks in front // and if it's fine to walk into the blocks in front
if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(ctx, positionsToBreak[0]).getBlock())) { if (MovementHelper.avoidWalkingInto(pb0)) {
return state; return state;
} }
if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(ctx, positionsToBreak[1]).getBlock())) { if (MovementHelper.avoidWalkingInto(pb1)) {
return state; return state;
} }
// and we aren't already pressed up against the block // and we aren't already pressed up against the block
@@ -174,11 +177,15 @@ 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();
if ((pb0.isFullCube() || pb0.getBlock() instanceof BlockAir && (pb1.isFullCube() || pb1.getBlock() instanceof BlockAir))) {
// in the meantime, before we're right up against the block, we can break efficiently at this angle
pitchToBreak = 26;
}
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
@@ -186,8 +193,6 @@ public class MovementTraverse extends Movement {
Block fd = BlockStateInterface.get(ctx, src.down()).getBlock(); Block fd = BlockStateInterface.get(ctx, src.down()).getBlock();
boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE; boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE;
IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]);
boolean door = pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor; boolean door = pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor;
if (door) { if (door) {
@@ -198,7 +203,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 +217,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);
} }
} }
@@ -231,10 +236,17 @@ public class MovementTraverse extends Movement {
if (ctx.playerFeet().equals(dest)) { if (ctx.playerFeet().equals(dest)) {
return state.setStatus(MovementStatus.SUCCESS); return state.setStatus(MovementStatus.SUCCESS);
} }
Block low = BlockStateInterface.get(ctx, src).getBlock();
Block high = BlockStateInterface.get(ctx, src.up()).getBlock();
if (ctx.player().posY > src.y + 0.1D && !ctx.player().onGround && (low == Blocks.VINE || low == Blocks.LADDER || high == Blocks.VINE || high == Blocks.LADDER)) {
// hitting W could cause us to climb the ladder instead of going forward
// wait until we're on the ground
return state;
}
BlockPos into = dest.subtract(src).add(dest); BlockPos into = dest.subtract(src).add(dest);
Block intoBelow = BlockStateInterface.get(ctx, into).getBlock(); IBlockState intoBelow = BlockStateInterface.get(ctx, into);
Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock(); IBlockState intoAbove = BlockStateInterface.get(ctx, into.up());
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !MovementHelper.avoidWalkingInto(intoBelow) && !MovementHelper.avoidWalkingInto(intoAbove)) { if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, ctx.playerFeet()) || Baritone.settings().sprintInWater.value) && (!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();
@@ -257,12 +269,12 @@ public class MovementTraverse extends Movement {
} }
double dist1 = Math.max(Math.abs(ctx.player().posX - (dest.getX() + 0.5D)), Math.abs(ctx.player().posZ - (dest.getZ() + 0.5D))); double dist1 = Math.max(Math.abs(ctx.player().posX - (dest.getX() + 0.5D)), Math.abs(ctx.player().posZ - (dest.getZ() + 0.5D)));
PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false); PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false);
if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.get()) { if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.value) {
state.setInput(Input.SNEAK, true); state.setInput(Input.SNEAK, true);
} }
switch (p) { switch (p) {
case READY_TO_PLACE: { case READY_TO_PLACE: {
if (ctx.player().isSneaking() || Baritone.settings().assumeSafeWalk.get()) { if (ctx.player().isSneaking() || Baritone.settings().assumeSafeWalk.value) {
state.setInput(Input.CLICK_RIGHT, true); state.setInput(Input.CLICK_RIGHT, true);
} }
return state; return state;
@@ -281,6 +293,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
@@ -334,4 +348,4 @@ public class MovementTraverse extends Movement {
} }
return super.prepared(state); return super.prepared(state);
} }
} }
@@ -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;
@@ -35,10 +36,12 @@ import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.movements.*; import baritone.pathing.movement.movements.*;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.block.BlockLiquid;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.init.Fluids;
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,46 +106,38 @@ 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;
} }
} }
} }
Tuple<Double, BlockPos> status = closestPathPos(path); Tuple<Double, BlockPos> status = closestPathPos(path);
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) { if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
ticksAway++; ticksAway++;
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH); System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getA() + ". Threshold: " + MAX_DIST_FROM_PATH);
if (ticksAway > MAX_TICKS_AWAY) { if (ticksAway > MAX_TICKS_AWAY) {
logDebug("Too far away from path for too long, cancelling path"); logDebug("Too far away from path for too long, cancelling path");
cancel(); cancel();
@@ -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;
} }
} }
@@ -234,21 +229,23 @@ public class PathExecutor implements IPathExecutor, Helper {
costEstimateIndex = pathPosition; costEstimateIndex = pathPosition;
// do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now // do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now
currentMovementOriginalCostEstimate = movement.getCost(); currentMovementOriginalCostEstimate = movement.getCost();
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) { for (int i = 1; i < Baritone.settings().costVerificationLookahead.value && pathPosition + i < path.length() - 1; i++) {
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF && canCancel) { if (((Movement) path.movements().get(pathPosition + i)).calculateCost(behavior.secretInternalGetCalculationContext()) >= ActionCosts.COST_INF && canCancel) {
logDebug("Something has changed in the world and a future movement has become impossible. Cancelling."); logDebug("Something has changed in the world and a future movement has become impossible. Cancelling.");
cancel(); cancel();
return true; return true;
} }
} }
} }
double currentCost = movement.recalculateCost(); double currentCost = ((Movement) movement).recalculateCost(behavior.secretInternalGetCalculationContext());
if (currentCost >= ActionCosts.COST_INF && canCancel) { if (currentCost >= ActionCosts.COST_INF && canCancel) {
logDebug("Something has changed in the world and this movement has become impossible. Cancelling."); logDebug("Something has changed in the world and this movement has become impossible. Cancelling.");
cancel(); cancel();
return true; return true;
} }
if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.get() && canCancel) { if (!movement.calculatedWhileLoaded() && currentCost - currentMovementOriginalCostEstimate > Baritone.settings().maxCostIncrease.value && 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;
@@ -276,7 +273,7 @@ public class PathExecutor implements IPathExecutor, Helper {
ctx.player().setSprinting(false); // letting go of control doesn't make you stop sprinting actually ctx.player().setSprinting(false); // letting go of control doesn't make you stop sprinting actually
} }
ticksOnCurrent++; ticksOnCurrent++;
if (ticksOnCurrent > currentMovementOriginalCostEstimate + Baritone.settings().movementTimeoutTicks.get()) { if (ticksOnCurrent > currentMovementOriginalCostEstimate + Baritone.settings().movementTimeoutTicks.value) {
// only cancel if the total time has exceeded the initial estimate // only cancel if the total time has exceeded the initial estimate
// as you break the blocks required, the remaining cost goes down, to the point where // as you break the blocks required, the remaining cost goes down, to the point where
// ticksOnCurrent is greater than recalculateCost + 100 // ticksOnCurrent is greater than recalculateCost + 100
@@ -336,7 +333,7 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
private boolean possiblyOffPath(Tuple<Double, BlockPos> status, double leniency) { private boolean possiblyOffPath(Tuple<Double, BlockPos> status, double leniency) {
double distanceFromPath = status.getFirst(); double distanceFromPath = status.getA();
if (distanceFromPath > leniency) { if (distanceFromPath > leniency) {
// when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path // when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path
if (path.movements().get(pathPosition) instanceof MovementFall) { if (path.movements().get(pathPosition) instanceof MovementFall) {
@@ -356,7 +353,7 @@ public class PathExecutor implements IPathExecutor, Helper {
* @return Whether or not it was possible to snap to the current player feet * @return Whether or not it was possible to snap to the current player feet
*/ */
public boolean snipsnapifpossible() { public boolean snipsnapifpossible() {
if (!ctx.player().onGround && !(ctx.world().getBlockState(ctx.playerFeet()).getBlock() instanceof BlockLiquid)) { if (!ctx.player().onGround && ctx.world().getFluidState(ctx.playerFeet()).isEmpty()) {
// if we're falling in the air, and not in water, don't splice // if we're falling in the air, and not in water, don't splice
return false; return false;
} else { } else {
@@ -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,18 +446,130 @@ 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.getB();
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.getA(), 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.value) {
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)))) {
return false;
}
return !MovementHelper.avoidWalkingInto(ctx.world().getBlockState(next.getDest().up(2))); // 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;
} }
if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(ctx, next.getDest().down())) { if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(ctx, next.getDest().down())) {
return true; return true;
} }
return next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get(); return next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.value;
} }
private void onChangeInPathPosition() { private void onChangeInPathPosition() {
@@ -484,8 +612,8 @@ public class PathExecutor implements IPathExecutor, Helper {
} }
private PathExecutor cutIfTooLong() { private PathExecutor cutIfTooLong() {
if (pathPosition > Baritone.settings().maxPathHistoryLength.get()) { if (pathPosition > Baritone.settings().maxPathHistoryLength.value) {
int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.get(); int cutoffAmt = Baritone.settings().pathHistoryCutoffAmount.value;
CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1); CutoffPath newPath = new CutoffPath(path, cutoffAmt, path.length() - 1);
if (!newPath.getDest().equals(path.getDest())) { if (!newPath.getDest().equals(path.getDest())) {
throw new IllegalStateException(); throw new IllegalStateException();
@@ -0,0 +1,734 @@
/*
* 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.process;
import baritone.Baritone;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.process.IBuilderProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.PathingCommandContext;
import baritone.utils.schematic.AirSchematic;
import baritone.utils.schematic.Schematic;
import net.minecraft.block.BlockAir;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.item.BlockItemUseContext;
import net.minecraft.item.ItemBlock;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemUseContext;
import net.minecraft.nbt.CompressedStreamTools;
import net.minecraft.nbt.NBTTagCompound;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.*;
import net.minecraft.util.math.shapes.VoxelShape;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
public class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
private HashSet<BetterBlockPos> incorrectPositions;
private String name;
private ISchematic realSchematic;
private ISchematic schematic;
private Vec3i origin;
private int ticks;
private boolean paused;
private int layer;
public BuilderProcess(Baritone baritone) {
super(baritone);
}
public boolean build(String schematicFile, BlockPos origin) {
File file = new File(new File(Minecraft.getInstance().gameDir, "schematics"), schematicFile);
System.out.println(file + " " + file.exists());
return build(schematicFile, file, origin);
}
@Override
public void build(String name, ISchematic schematic, Vec3i origin) {
this.name = name;
this.schematic = schematic;
this.realSchematic = null;
this.origin = origin;
this.paused = false;
this.layer = 0;
}
public void resume() {
paused = false;
}
@Override
public boolean build(String name, File schematic, Vec3i origin) {
NBTTagCompound tag;
try (FileInputStream fileIn = new FileInputStream(schematic)) {
tag = CompressedStreamTools.readCompressed(fileIn);
} catch (IOException e) {
e.printStackTrace();
return false;
}
if (tag == null) {
return false;
}
build(name, parse(tag), origin);
return true;
}
public void clearArea(BlockPos corner1, BlockPos corner2) {
BlockPos origin = new BlockPos(Math.min(corner1.getX(), corner2.getX()), Math.min(corner1.getY(), corner2.getY()), Math.min(corner1.getZ(), corner2.getZ()));
int widthX = Math.abs(corner1.getX() - corner2.getX()) + 1;
int heightY = Math.abs(corner1.getY() - corner2.getY()) + 1;
int lengthZ = Math.abs(corner1.getZ() - corner2.getZ()) + 1;
build("clear area", new AirSchematic(widthX, heightY, lengthZ), origin);
}
private static ISchematic parse(NBTTagCompound schematic) {
return new Schematic(schematic);
}
@Override
public boolean isActive() {
return schematic != null;
}
public IBlockState placeAt(int x, int y, int z) {
if (!isActive()) {
return null;
}
if (!schematic.inSchematic(x - origin.getX(), y - origin.getY(), z - origin.getZ())) {
return null;
}
IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ());
if (state.getBlock() instanceof BlockAir) {
return null;
}
return state;
}
public Optional<Tuple<BetterBlockPos, Rotation>> toBreakNearPlayer(BuilderCalculationContext bcc) {
BetterBlockPos center = ctx.playerFeet();
for (int dx = -5; dx <= 5; dx++) {
for (int dy = 0; dy <= 5; dy++) {
for (int dz = -5; dz <= 5; dz++) {
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired == null) {
continue; // irrelevant
}
IBlockState curr = bcc.bsi.get0(x, y, z);
if (!(curr.getBlock() instanceof BlockAir) && !valid(curr, desired)) {
BetterBlockPos pos = new BetterBlockPos(x, y, z);
Optional<Rotation> rot = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
if (rot.isPresent()) {
return Optional.of(new Tuple<>(pos, rot.get()));
}
}
}
}
}
return Optional.empty();
}
public class Placement {
private final int hotbarSelection;
private final BlockPos placeAgainst;
private final EnumFacing side;
private final Rotation rot;
public Placement(int hotbarSelection, BlockPos placeAgainst, EnumFacing side, Rotation rot) {
this.hotbarSelection = hotbarSelection;
this.placeAgainst = placeAgainst;
this.side = side;
this.rot = rot;
}
}
public Optional<Placement> searchForPlacables(BuilderCalculationContext bcc, List<IBlockState> desirableOnHotbar) {
BetterBlockPos center = ctx.playerFeet();
for (int dx = -5; dx <= 5; dx++) {
for (int dy = -5; dy <= 1; dy++) {
for (int dz = -5; dz <= 5; dz++) {
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired == null) {
continue; // irrelevant
}
IBlockState curr = bcc.bsi.get0(x, y, z);
if (MovementHelper.isReplacable(x, y, z, curr, bcc.bsi) && !valid(curr, desired)) {
if (dy == 1 && bcc.bsi.get0(x, y + 1, z).getBlock() instanceof BlockAir) {
continue;
}
desirableOnHotbar.add(desired);
Optional<Placement> opt = possibleToPlace(desired, x, y, z, bcc.bsi);
if (opt.isPresent()) {
return opt;
}
}
}
}
}
return Optional.empty();
}
public boolean placementPlausible(BlockPos pos, IBlockState state) {
VoxelShape voxelshape = state.getCollisionShape(ctx.world(), pos);
return voxelshape.isEmpty() || ctx.world().checkNoEntityCollision(null, voxelshape.withOffset(pos.getX(), pos.getY(), pos.getZ()));
}
public Optional<Placement> possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
for (EnumFacing against : EnumFacing.values()) {
BetterBlockPos placeAgainstPos = new BetterBlockPos(x, y, z).offset(against);
IBlockState placeAgainstState = bsi.get0(placeAgainstPos);
if (MovementHelper.isReplacable(placeAgainstPos.x, placeAgainstPos.y, placeAgainstPos.z, placeAgainstState, bsi)) {
continue;
}
if (!toPlace.isValidPosition(ctx.world(), new BetterBlockPos(x, y, z))) {
continue;
}
if (!placementPlausible(new BetterBlockPos(x, y, z), toPlace)) {
continue;
}
AxisAlignedBB aabb = placeAgainstState.getShape(ctx.world(), placeAgainstPos).getBoundingBox();
for (Vec3d placementMultiplier : aabbSideMultipliers(against)) {
double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x);
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z);
Rotation rot = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(placeX, placeY, placeZ), ctx.playerRotations());
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance());
if (result != null && result.type == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);
if (hotbar.isPresent()) {
return Optional.of(new Placement(hotbar.getAsInt(), placeAgainstPos, against.getOpposite(), rot));
}
}
}
}
return Optional.empty();
}
public OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
for (int i = 0; i < 9; i++) {
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
if (stack.isEmpty() || !(stack.getItem() instanceof ItemBlock)) {
continue;
}
float originalYaw = ctx.player().rotationYaw;
float originalPitch = ctx.player().rotationPitch;
// the state depends on the facing of the player sometimes
ctx.player().rotationYaw = rot.getYaw();
ctx.player().rotationPitch = rot.getPitch();
BlockItemUseContext meme = new BlockItemUseContext(new ItemUseContext(
ctx.player(),
stack,
result.getBlockPos().offset(result.sideHit),
result.sideHit,
(float) result.hitVec.x - result.getBlockPos().getX(),
(float) result.hitVec.y - result.getBlockPos().getY(),
(float) result.hitVec.z - result.getBlockPos().getZ()
));
IBlockState wouldBePlaced = ((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(meme);
ctx.player().rotationYaw = originalYaw;
ctx.player().rotationPitch = originalPitch;
if (wouldBePlaced == null) {
continue;
}
if (!meme.canPlace()) {
continue;
}
if (valid(wouldBePlaced, desired)) {
return OptionalInt.of(i);
}
}
return OptionalInt.empty();
}
private static Vec3d[] aabbSideMultipliers(EnumFacing side) {
switch (side) {
case UP:
return new Vec3d[]{new Vec3d(0.5, 1, 0.5), new Vec3d(0.1, 1, 0.5), new Vec3d(0.9, 1, 0.5), new Vec3d(0.5, 1, 0.1), new Vec3d(0.5, 1, 0.9)};
case DOWN:
return new Vec3d[]{new Vec3d(0.5, 0, 0.5), new Vec3d(0.1, 0, 0.5), new Vec3d(0.9, 0, 0.5), new Vec3d(0.5, 0, 0.1), new Vec3d(0.5, 0, 0.9)};
case NORTH:
case SOUTH:
case EAST:
case WEST:
double x = side.getXOffset() == 0 ? 0.5 : (1 + side.getXOffset()) / 2D;
double z = side.getZOffset() == 0 ? 0.5 : (1 + side.getZOffset()) / 2D;
return new Vec3d[]{new Vec3d(x, 0.25, z), new Vec3d(x, 0.75, z)};
default: // null
throw new IllegalStateException();
}
}
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (baritone.getInputOverrideHandler().isInputForcedDown(Input.CLICK_LEFT)) {
ticks = 5;
} else {
ticks--;
}
baritone.getInputOverrideHandler().clearAllKeys();
if (paused) {
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
if (Baritone.settings().buildInLayers.value) {
if (realSchematic == null) {
realSchematic = schematic;
}
schematic = new ISchematic() {
@Override
public IBlockState desiredState(int x, int y, int z) {
return realSchematic.desiredState(x, y, z);
}
@Override
public int widthX() {
return realSchematic.widthX();
}
@Override
public int heightY() {
return layer;
}
@Override
public int lengthZ() {
return realSchematic.lengthZ();
}
};
}
BuilderCalculationContext bcc = new BuilderCalculationContext();
if (!recalc(bcc)) {
if (Baritone.settings().buildInLayers.value && layer < realSchematic.heightY()) {
logDirect("Starting layer " + layer);
layer++;
return onTick(calcFailed, isSafeToCancel);
}
int distance = Baritone.settings().buildRepeatDistance.value;
EnumFacing direction = Baritone.settings().buildRepeatDirection.value;
if (distance == 0) {
logDirect("Done building");
onLostControl();
return null;
}
// build repeat time
if (distance == -1) {
distance = schematic.size(direction.getAxis());
}
layer = 0;
origin = new BlockPos(origin).offset(direction, distance);
logDirect("Repeating build " + distance + " blocks to the " + direction + ", new origin is " + origin);
}
trim(bcc);
Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc);
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) {
// we'd like to pause to break this block
// only change look direction if it's safe (don't want to fuck up an in progress parkour for example
Rotation rot = toBreak.get().getB();
BetterBlockPos pos = toBreak.get().getA();
baritone.getLookBehavior().updateTarget(rot, true);
MovementHelper.switchToBestToolFor(ctx, bcc.get(pos));
if (ctx.player().isSneaking()) {
// really horrible bug where a block is visible for breaking while sneaking but not otherwise
// so you can't see it, it goes to place something else, sneaks, then the next tick it tries to break
// and is unable since it's unsneaked in the intermediary tick
baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true);
}
if (Objects.equals(ctx.objectMouseOver().getBlockPos(), pos) || ctx.playerRotations().isReallyCloseTo(rot)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
}
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
List<IBlockState> desirableOnHotbar = new ArrayList<>();
Optional<Placement> toPlace = searchForPlacables(bcc, desirableOnHotbar);
if (toPlace.isPresent() && isSafeToCancel && ctx.player().onGround && ticks <= 0) {
Rotation rot = toPlace.get().rot;
baritone.getLookBehavior().updateTarget(rot, true);
ctx.player().inventory.currentItem = toPlace.get().hotbarSelection;
baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true);
if ((Objects.equals(ctx.objectMouseOver().getBlockPos(), toPlace.get().placeAgainst) && ctx.objectMouseOver().sideHit.equals(toPlace.get().side)) || ctx.playerRotations().isReallyCloseTo(rot)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
}
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
List<IBlockState> approxPlacable = placable(36);
if (Baritone.settings().allowInventory.value) {
ArrayList<Integer> usefulSlots = new ArrayList<>();
List<IBlockState> noValidHotbarOption = new ArrayList<>();
outer:
for (IBlockState desired : desirableOnHotbar) {
for (int i = 0; i < 9; i++) {
if (valid(approxPlacable.get(i), desired)) {
usefulSlots.add(i);
continue outer;
}
}
noValidHotbarOption.add(desired);
}
outer:
for (int i = 9; i < 36; i++) {
for (IBlockState desired : noValidHotbarOption) {
if (valid(approxPlacable.get(i), desired)) {
baritone.getInventoryBehavior().attemptToPutOnHotbar(i, usefulSlots::contains);
break outer;
}
}
}
}
Goal goal = assemble(bcc, approxPlacable.subList(0, 9));
if (goal == null) {
goal = assemble(bcc, approxPlacable); // we're far away, so assume that we have our whole inventory to recalculate placable properly
if (goal == null) {
logDirect("Unable to do it. Pausing. resume to resume, cancel to cancel");
paused = true;
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
}
return new PathingCommandContext(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH, bcc);
}
public boolean recalc(BuilderCalculationContext bcc) {
if (incorrectPositions == null) {
incorrectPositions = new HashSet<>();
fullRecalc(bcc);
if (incorrectPositions.isEmpty()) {
return false;
}
}
recalcNearby(bcc);
if (incorrectPositions.isEmpty()) {
fullRecalc(bcc);
}
return !incorrectPositions.isEmpty();
}
public void trim(BuilderCalculationContext bcc) {
HashSet<BetterBlockPos> copy = new HashSet<>(incorrectPositions);
copy.removeIf(pos -> pos.distanceSq(ctx.player().posX, ctx.player().posY, ctx.player().posZ) > 200);
if (!copy.isEmpty()) {
incorrectPositions = copy;
}
}
public void recalcNearby(BuilderCalculationContext bcc) {
BetterBlockPos center = ctx.playerFeet();
for (int dx = -5; dx <= 5; dx++) {
for (int dy = -5; dy <= 5; dy++) {
for (int dz = -5; dz <= 5; dz++) {
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired != null) {
// we care about this position
if (valid(bcc.bsi.get0(x, y, z), desired)) {
incorrectPositions.remove(new BetterBlockPos(x, y, z));
} else {
incorrectPositions.add(new BetterBlockPos(x, y, z));
}
}
}
}
}
}
public void fullRecalc(BuilderCalculationContext bcc) {
incorrectPositions = new HashSet<>();
for (int y = 0; y < schematic.heightY(); y++) {
for (int z = 0; z < schematic.lengthZ(); z++) {
for (int x = 0; x < schematic.widthX(); x++) {
if (schematic.inSchematic(x, y, z) && !valid(bcc.bsi.get0(x + origin.getX(), y + origin.getY(), z + origin.getZ()), schematic.desiredState(x, y, z))) {
incorrectPositions.add(new BetterBlockPos(x + origin.getX(), y + origin.getY(), z + origin.getZ()));
}
}
}
}
}
private Goal assemble(BuilderCalculationContext bcc, List<IBlockState> approxPlacable) {
List<BetterBlockPos> placable = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() instanceof BlockAir && approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))).collect(Collectors.toList());
Goal[] toBreak = incorrectPositions.stream().filter(pos -> !(bcc.bsi.get0(pos).getBlock() instanceof BlockAir)).map(GoalBreak::new).toArray(Goal[]::new);
Goal[] toPlace = placable.stream().filter(pos -> !placable.contains(pos.down()) && !placable.contains(pos.down(2))).map(pos -> placementgoal(pos, bcc)).toArray(Goal[]::new);
if (toPlace.length != 0) {
return new JankyGoalComposite(new GoalComposite(toPlace), new GoalComposite(toBreak));
}
if (toBreak.length == 0) {
return null;
}
return new GoalComposite(toBreak);
}
public static class JankyGoalComposite implements Goal {
private final Goal primary;
private final Goal fallback;
public JankyGoalComposite(Goal primary, Goal fallback) {
this.primary = primary;
this.fallback = fallback;
}
@Override
public boolean isInGoal(int x, int y, int z) {
return primary.isInGoal(x, y, z) || fallback.isInGoal(x, y, z);
}
@Override
public double heuristic(int x, int y, int z) {
return primary.heuristic(x, y, z);
}
@Override
public String toString() {
return "JankyComposite Primary: " + primary + " Fallback: " + fallback;
}
}
public static class GoalBreak extends GoalGetToBlock {
public GoalBreak(BlockPos pos) {
super(pos);
}
@Override
public boolean isInGoal(int x, int y, int z) {
// can't stand right on top of a block, that might not work (what if it's unsupported, can't break then)
if (y > this.y) {
return false;
}
// but any other adjacent works for breaking, including inside or below
return super.isInGoal(x, y, z);
}
}
public Goal placementgoal(BlockPos pos, BuilderCalculationContext bcc) {
if (!(ctx.world().getBlockState(pos).getBlock() instanceof BlockAir)) {
return new GoalPlace(pos);
}
boolean allowSameLevel = !(ctx.world().getBlockState(pos.up()).getBlock() instanceof BlockAir);
for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP) {
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && placementPlausible(pos, bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ()))) {
return new GoalAdjacent(pos, allowSameLevel);
}
}
return new GoalPlace(pos);
}
public static class GoalAdjacent extends GoalGetToBlock {
private boolean allowSameLevel;
public GoalAdjacent(BlockPos pos, boolean allowSameLevel) {
super(pos);
this.allowSameLevel = allowSameLevel;
}
public boolean isInGoal(int x, int y, int z) {
if (x == this.x && y == this.y && z == this.z) {
return false;
}
if (!allowSameLevel && y == this.y - 1) {
return false;
}
if (y < this.y - 1) {
return false;
}
return super.isInGoal(x, y, z);
}
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
}
public static class GoalPlace extends GoalBlock {
public GoalPlace(BlockPos placeAt) {
super(placeAt.up());
}
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
}
@Override
public void onLostControl() {
incorrectPositions = null;
name = null;
schematic = null;
realSchematic = null;
layer = 0;
paused = false;
}
@Override
public String displayName0() {
return paused ? "Builder Paused" : "Building " + name;
}
public List<IBlockState> placable(int size) {
List<IBlockState> result = new ArrayList<>();
for (int i = 0; i < size; i++) {
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
if (stack.isEmpty() || !(stack.getItem() instanceof ItemBlock)) {
result.add(Blocks.AIR.getDefaultState());
continue;
}
// <toxic cloud>
result.add(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(new BlockItemUseContext(new ItemUseContext(ctx.player(), stack, ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ))));
// </toxic cloud>
}
return result;
}
public boolean valid(IBlockState current, IBlockState desired) {
if (desired == null) {
return true;
}
if (current.getBlock() instanceof BlockAir && desired.getBlock() instanceof BlockAir) {
return true;
}
// TODO more complicated comparison logic I guess
return current.equals(desired);
}
public class BuilderCalculationContext extends CalculationContext {
private final List<IBlockState> placable;
private final ISchematic schematic;
private final int originX;
private final int originY;
private final int originZ;
public BuilderCalculationContext() {
super(BuilderProcess.this.baritone, true); // wew lad
this.placable = placable(9);
this.schematic = BuilderProcess.this.schematic;
this.originX = origin.getX();
this.originY = origin.getY();
this.originZ = origin.getZ();
this.jumpPenalty += 10;
this.backtrackCostFavoringCoefficient = 1;
}
private IBlockState getSchematic(int x, int y, int z) {
if (schematic.inSchematic(x - originX, y - originY, z - originZ)) {
return schematic.desiredState(x - originX, y - originY, z - originZ);
} else {
return null;
}
}
@Override
public double costOfPlacingAt(int x, int y, int z) {
if (isPossiblyProtected(x, y, z) || !worldBorder.canPlaceAt(x, z)) { // make calculation fail properly if we can't build
return COST_INF;
}
IBlockState sch = getSchematic(x, y, z);
if (sch != null) {
// TODO this can return true even when allowPlace is off.... is that an issue?
if (sch.getBlock() instanceof BlockAir) {
// we want this to be air, but they're asking if they can place here
// this won't be a schematic block, this will be a throwaway
return placeBlockCost * 2; // we're going to have to break it eventually
}
if (placable.contains(sch)) {
return 0; // thats right we gonna make it FREE to place a block where it should go in a structure
// no place block penalty at all 😎
// i'm such an idiot that i just tried to copy and paste the epic gamer moment emoji too
// get added to unicode when?
}
if (!hasThrowaway) {
return COST_INF;
}
// we want it to be something that we don't have
// even more of a pain to place something wrong
return placeBlockCost * 3;
} else {
if (hasThrowaway) {
return placeBlockCost;
} else {
return COST_INF;
}
}
}
@Override
public double breakCostMultiplierAt(int x, int y, int z) {
if (!allowBreak || isPossiblyProtected(x, y, z)) {
return COST_INF;
}
IBlockState sch = getSchematic(x, y, z);
if (sch != null) {
if (sch.getBlock() instanceof BlockAir) {
// it should be air
// regardless of current contents, we can break it
return 1;
}
// it should be a real block
// is it already that block?
if (valid(bsi.get0(x, y, z), sch)) {
return 3;
} else {
// can break if it's wrong
// would be great to return less than 1 here, but that would actually make the cost calculation messed up
// since we're breaking a block, if we underestimate the cost, then it'll fail when it really takes the correct amount of time
return 1;
}
// TODO do blocks in render distace only?
// TODO allow breaking blocks that we have a tool to harvest and immediately place back?
} else {
return 1; // why not lol
}
}
}
}
@@ -24,8 +24,6 @@ import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType; import baritone.api.process.PathingCommandType;
import baritone.utils.BaritoneProcessHelper; import baritone.utils.BaritoneProcessHelper;
import java.util.Objects;
/** /**
* As set by ExampleBaritoneControl or something idk * As set by ExampleBaritoneControl or something idk
* *
@@ -46,7 +44,7 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG
private State state; private State state;
public CustomGoalProcess(Baritone baritone) { public CustomGoalProcess(Baritone baritone) {
super(baritone, 3); super(baritone);
} }
@Override @Override
@@ -55,6 +53,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
@@ -76,20 +77,23 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
switch (this.state) { switch (this.state) {
case GOAL_SET: case GOAL_SET:
if (!baritone.getPathingBehavior().isPathing() && Objects.equals(baritone.getPathingBehavior().getGoal() + "", this.goal + "")) {
this.state = State.NONE;
}
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); // return FORCE_REVALIDATE_GOAL_AND_PATH just once
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:
if (calcFailed) { if (calcFailed) {
onLostControl(); onLostControl();
return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
if (this.goal == null || this.goal.isInGoal(ctx.playerFeet())) { if (this.goal == null || (this.goal.isInGoal(ctx.playerFeet()) && this.goal.isInGoal(baritone.getPathingBehavior().pathStart()))) {
onLostControl(); // we're there xd onLostControl(); // we're there xd
if (Baritone.settings().disconnectOnArrival.value) {
ctx.world().sendQuittingDisconnectingPacket();
}
return new PathingCommand(this.goal, PathingCommandType.CANCEL_AND_SET_GOAL);
} }
return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH); return new PathingCommand(this.goal, PathingCommandType.SET_GOAL_AND_PATH);
default: default:
@@ -104,7 +108,7 @@ public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomG
} }
@Override @Override
public String displayName() { public String displayName0() {
return "Custom Goal " + this.goal; return "Custom Goal " + this.goal;
} }
@@ -0,0 +1,109 @@
/*
* 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.process;
import baritone.Baritone;
import baritone.api.cache.ICachedWorld;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.cache.CachedWorld;
import baritone.utils.BaritoneProcessHelper;
import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
import java.util.List;
public class ExploreProcess extends BaritoneProcessHelper {
private BlockPos explorationOrigin;
public ExploreProcess(Baritone baritone) {
super(baritone);
}
@Override
public boolean isActive() {
return explorationOrigin != null;
}
public void explore(int centerX, int centerZ) {
explorationOrigin = new BlockPos(centerX, 0, centerZ);
}
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (calcFailed) {
logDirect("Failed");
onLostControl();
return null;
}
Goal[] closestUncached = closestUncachedChunks(explorationOrigin);
if (closestUncached == null) {
logDebug("awaiting region load from disk");
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
System.out.println("Closest uncached: " + closestUncached);
return new PathingCommand(new GoalComposite(closestUncached), PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
}
private Goal[] closestUncachedChunks(BlockPos center) {
int chunkX = center.getX() >> 4;
int chunkZ = center.getZ() >> 4;
ICachedWorld cache = baritone.getWorldProvider().getCurrentWorld().getCachedWorld();
for (int dist = 0; ; dist++) {
List<BlockPos> centers = new ArrayList<>();
for (int dx = -dist; dx <= dist; dx++) {
for (int dz = -dist; dz <= dist; dz++) {
int trueDist = Baritone.settings().exploreUsePythagorean.value ? dx * dx + dz * dz : Math.abs(dx) + Math.abs(dz);
if (trueDist != dist) {
continue; // not considering this one just yet in our expanding search
}
int centerX = (chunkX + dx) * 16 + 8;
int centerZ = (chunkZ + dz) * 18 + 8;
if (cache.isCached(centerX, centerZ)) {
continue;
}
if (!((CachedWorld) cache).regionLoaded(centerX, centerZ)) {
Baritone.getExecutor().execute(() -> {
((CachedWorld) cache).tryLoadFromDisk(centerX >> 9, centerZ >> 9);
});
return null; // we still need to load regions from disk in order to decide properly
}
centers.add(new BlockPos(centerX, 0, centerZ));
}
}
if (!centers.isEmpty()) {
return centers.stream().map(pos -> new GoalXZ(pos.getX(), pos.getZ())).toArray(Goal[]::new);
}
}
}
@Override
public void onLostControl() {
explorationOrigin = null;
}
@Override
public String displayName0() {
return "Exploring around " + explorationOrigin + ", currently going to " + new GoalComposite(closestUncachedChunks(explorationOrigin));
}
}
@@ -46,7 +46,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
private List<Entity> cache; private List<Entity> cache;
public FollowProcess(Baritone baritone) { public FollowProcess(Baritone baritone) {
super(baritone, 1); super(baritone);
} }
@Override @Override
@@ -58,13 +58,13 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
private Goal towards(Entity following) { private Goal towards(Entity following) {
BlockPos pos; BlockPos pos;
if (Baritone.settings().followOffsetDistance.get() == 0) { if (Baritone.settings().followOffsetDistance.value == 0) {
pos = new BlockPos(following); pos = new BlockPos(following);
} else { } else {
GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get()); GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.value, Baritone.settings().followOffsetDistance.value);
pos = new BlockPos(g.getX(), following.posY, g.getZ()); pos = new BlockPos(g.getX(), following.posY, g.getZ());
} }
return new GoalNear(pos, Baritone.settings().followRadius.get()); return new GoalNear(pos, Baritone.settings().followRadius.value);
} }
@@ -72,7 +72,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
if (entity == null) { if (entity == null) {
return false; return false;
} }
if (entity.isDead) { if (!entity.isAlive()) {
return false; return false;
} }
if (entity.equals(ctx.player())) { if (entity.equals(ctx.player())) {
@@ -101,8 +101,8 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
} }
@Override @Override
public String displayName() { public String displayName0() {
return "Follow " + cache; return "Following " + cache;
} }
@Override @Override
@@ -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,26 +32,27 @@ 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;
public GetToBlockProcess(Baritone baritone) { public GetToBlockProcess(Baritone baritone) {
super(baritone, 2); super(baritone);
} }
@Override @Override
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,62 +62,125 @@ 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.value && !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().blacklistClosestOnFailure.value) {
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.value;
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
List<BlockPos> current = new ArrayList<>(knownLocations); List<BlockPos> current = new ArrayList<>(knownLocations);
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()) && goal.isInGoal(baritone.getPathingBehavior().pathStart()) && 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();
} }
@Override @Override
public String displayName() { public String displayName0() {
return "Get To Block " + gettingTo; if (knownLocations.isEmpty()) {
return "Exploring randomly to find " + gettingTo + ", no known locations";
}
return "Get To " + gettingTo + ", " + knownLocations.size() + " known locations";
} }
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, blacklist);
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() {
@@ -142,16 +203,24 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
private boolean walkIntoInsteadOfAdjacent(Block block) { private boolean walkIntoInsteadOfAdjacent(Block block) {
if (!Baritone.settings().enterPortal.get()) { if (!Baritone.settings().enterPortal.value) {
return false; return false;
} }
return block == Blocks.PORTAL; return block == Blocks.NETHER_PORTAL;
} }
private boolean rightClickOnArrival(Block block) { private boolean rightClickOnArrival(Block block) {
if (!Baritone.settings().rightClickContainerOnArrival.get()) { if (!Baritone.settings().rightClickContainerOnArrival.value) {
return false; return false;
} }
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST; return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.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;
}
} }
+54 -30
View File
@@ -32,6 +32,7 @@ import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper; import baritone.utils.BaritoneProcessHelper;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem; import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
@@ -54,13 +55,14 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
private List<Block> mining; private List<Block> mining;
private List<BlockPos> knownOreLocations; private List<BlockPos> knownOreLocations;
private List<BlockPos> blacklist; // inaccessible
private BlockPos branchPoint; private BlockPos branchPoint;
private GoalRunAway branchPointRunaway; private GoalRunAway branchPointRunaway;
private int desiredQuantity; private int desiredQuantity;
private int tickCount; private int tickCount;
public MineProcess(Baritone baritone) { public MineProcess(Baritone baritone) {
super(baritone, 0); super(baritone);
} }
@Override @Override
@@ -71,27 +73,34 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
@Override @Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) { public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (desiredQuantity > 0) { if (desiredQuantity > 0) {
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0); Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), ctx.world(), null, 0).asItem();
int curr = ctx.player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum(); int curr = ctx.player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum();
System.out.println("Currently have " + curr + " " + item); System.out.println("Currently have " + curr + " " + item);
if (curr >= desiredQuantity) { if (curr >= desiredQuantity) {
logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1))); logDirect("Have " + curr + " " + item.getDisplayName(new ItemStack(item, 1)));
cancel(); cancel();
return null; return null;
} }
} }
if (calcFailed) { boolean shouldCancel = calcFailed;
if (calcFailed && !knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
logDirect("Unable to find any path to " + mining + ", blacklisting presumably unreachable closest instance...");
knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(blacklist::add);
knownOreLocations.removeIf(blacklist::contains);
shouldCancel = false; // 😎
}
if (shouldCancel) {
logDirect("Unable to find any path to " + mining + ", canceling Mine"); logDirect("Unable to find any path to " + mining + ", canceling Mine");
cancel(); cancel();
return null; return null;
} }
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get(); int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value;
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
List<BlockPos> curr = new ArrayList<>(knownOreLocations); List<BlockPos> curr = new ArrayList<>(knownOreLocations);
CalculationContext context = new CalculationContext(baritone, true); CalculationContext context = new CalculationContext(baritone, true);
Baritone.getExecutor().execute(() -> rescan(curr, context)); Baritone.getExecutor().execute(() -> rescan(curr, context));
} }
if (Baritone.settings().legitMine.get()) { if (Baritone.settings().legitMine.value) {
addNearby(); addNearby();
} }
PathingCommand command = updateGoal(); PathingCommand command = updateGoal();
@@ -110,15 +119,15 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
} }
@Override @Override
public String displayName() { public String displayName0() {
return "Mine " + mining; return "Mine " + mining;
} }
private PathingCommand updateGoal() { private PathingCommand updateGoal() {
boolean legit = Baritone.settings().legitMine.get(); boolean legit = Baritone.settings().legitMine.value;
List<BlockPos> locs = knownOreLocations; List<BlockPos> locs = knownOreLocations;
if (!locs.isEmpty()) { if (!locs.isEmpty()) {
List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT); List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, blacklist);
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final // can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new)); Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new));
knownOreLocations = locs2; knownOreLocations = locs2;
@@ -129,7 +138,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return null; return null;
} }
// only in non-Xray mode (aka legit mode) do we do this // only in non-Xray mode (aka legit mode) do we do this
int y = Baritone.settings().legitMineYLevel.get(); int y = Baritone.settings().legitMineYLevel.value;
if (branchPoint == null) { if (branchPoint == null) {
/*if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) { /*if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
// cool, path is over and we are at desired y // cool, path is over and we are at desired y
@@ -157,13 +166,13 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
if (mining == null) { if (mining == null) {
return; return;
} }
if (Baritone.settings().legitMine.get()) { if (Baritone.settings().legitMine.value) {
return; return;
} }
List<BlockPos> locs = searchWorld(context, mining, ORE_LOCATIONS_COUNT, already); List<BlockPos> locs = searchWorld(context, mining, ORE_LOCATIONS_COUNT, already, blacklist);
locs.addAll(droppedItemsScan(mining, ctx.world())); locs.addAll(droppedItemsScan(mining, ctx.world()));
if (locs.isEmpty()) { if (locs.isEmpty()) {
logDebug("No locations for " + mining + " known, cancelling"); logDirect("No locations for " + mining + " known, cancelling");
cancel(); cancel();
return; return;
} }
@@ -171,24 +180,24 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
} }
private static Goal coalesce(IPlayerContext ctx, BlockPos loc, List<BlockPos> locs) { private static Goal coalesce(IPlayerContext ctx, BlockPos loc, List<BlockPos> locs) {
if (!Baritone.settings().forceInternalMining.get()) { if (!Baritone.settings().forceInternalMining.value) {
return new GoalTwoBlocks(loc); return new GoalTwoBlocks(loc);
} }
// Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of) // Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of)
boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(ctx, loc.up()) == Blocks.AIR); boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.value && BlockStateInterface.getBlock(ctx, loc.up()) instanceof BlockAir);
boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.get() && BlockStateInterface.getBlock(ctx, loc.down()) == Blocks.AIR); boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.value && BlockStateInterface.getBlock(ctx, loc.down()) instanceof BlockAir);
return upwardGoal == downwardGoal ? new GoalTwoBlocks(loc) : upwardGoal ? new GoalBlock(loc) : new GoalBlock(loc.down()); return upwardGoal == downwardGoal ? new GoalTwoBlocks(loc) : upwardGoal ? new GoalBlock(loc) : new GoalBlock(loc.down());
} }
public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) { public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) {
if (!Baritone.settings().mineScanDroppedItems.get()) { if (!Baritone.settings().mineScanDroppedItems.value) {
return new ArrayList<>(); return new ArrayList<>();
} }
Set<Item> searchingFor = new HashSet<>(); Set<Item> searchingFor = new HashSet<>();
for (Block block : mining) { for (Block block : mining) {
Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0); Item drop = block.getItemDropped(block.getDefaultState(), world, null, 0).asItem();
Item ore = Item.getItemFromBlock(block); Item ore = block.asItem();
searchingFor.add(drop); searchingFor.add(drop);
searchingFor.add(ore); searchingFor.add(ore);
} }
@@ -204,31 +213,33 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return ret; return ret;
} }
public static List<BlockPos> searchWorld(CalculationContext ctx, List<Block> mining, int max, List<BlockPos> alreadyKnown) { public static List<BlockPos> searchWorld(CalculationContext ctx, List<Block> mining, int max, List<BlockPos> alreadyKnown, List<BlockPos> blacklist) {
List<BlockPos> locs = new ArrayList<>(); List<BlockPos> locs = new ArrayList<>();
List<Block> uninteresting = new ArrayList<>(); List<Block> uninteresting = new ArrayList<>();
//long b = System.currentTimeMillis(); //long b = System.currentTimeMillis();
for (Block m : mining) { for (Block m : mining) {
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) { if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2)); // maxRegionDistanceSq 2 means adjacent directly or adjacent diagonally; nothing further than that
locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), Baritone.settings().maxCachedWorldScanCount.value, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
} else { } else {
uninteresting.add(m); uninteresting.add(m);
} }
} }
locs = prune(ctx, locs, mining, max, blacklist);
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms"); //System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
if (locs.isEmpty()) { if (locs.isEmpty()) {
uninteresting = mining; uninteresting = mining;
} }
if (!uninteresting.isEmpty()) { if (!uninteresting.isEmpty()) {
//long before = System.currentTimeMillis(); //long before = System.currentTimeMillis();
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx.getBaritone().getPlayerContext(), uninteresting, max, 10, 26)); locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx.getBaritone().getPlayerContext(), uninteresting, max, 10, 32)); // maxSearchRadius is NOT sq
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms"); //System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
} }
locs.addAll(alreadyKnown); locs.addAll(alreadyKnown);
return prune(ctx, locs, mining, max); return prune(ctx, locs, mining, max, blacklist);
} }
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,28 +250,40 @@ 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.value && 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);
}
} }
} }
} }
} }
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, mining, ORE_LOCATIONS_COUNT); knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, mining, ORE_LOCATIONS_COUNT, blacklist);
} }
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) { private static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max, List<BlockPos> blacklist) {
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)
.filter(pos -> MineProcess.plausibleToBreak(ctx.bsi, pos)) .filter(pos -> MineProcess.plausibleToBreak(ctx.bsi, pos))
.filter(pos -> !blacklist.contains(pos))
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq)) .sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -281,7 +304,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
@Override @Override
public void mineByName(int quantity, String... blocks) { public void mineByName(int quantity, String... blocks) {
mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).toArray(Block[]::new)); mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlockRequired).toArray(Block[]::new));
} }
@Override @Override
@@ -289,6 +312,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks); this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks);
this.desiredQuantity = quantity; this.desiredQuantity = quantity;
this.knownOreLocations = new ArrayList<>(); this.knownOreLocations = new ArrayList<>();
this.blacklist = new ArrayList<>();
this.branchPoint = null; this.branchPoint = null;
this.branchPointRunaway = null; this.branchPointRunaway = null;
if (mining != null) { if (mining != null) {
@@ -23,14 +23,21 @@ import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import net.minecraft.client.GameSettings;
import net.minecraft.client.Minecraft; import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMainMenu; import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.client.tutorial.TutorialSteps; import net.minecraft.client.tutorial.TutorialSteps;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.HttpUtil;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType; import net.minecraft.world.GameType;
import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType; import net.minecraft.world.WorldType;
import net.minecraft.world.dimension.DimensionType;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
/** /**
* Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific * Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific
@@ -88,11 +95,13 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings); mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings);
} }
IntegratedServer server = mc.getIntegratedServer();
// If the integrated server is launched and the world has initialized, set the spawn point // If the integrated server is launched and the world has initialized, set the spawn point
// to our defined starting position // to our defined starting position
if (mc.getIntegratedServer() != null && mc.getIntegratedServer().worlds[0] != null) { if (server != null && server.getWorld(DimensionType.OVERWORLD) != null) {
mc.getIntegratedServer().worlds[0].setSpawnPoint(STARTING_POSITION); server.getWorld(DimensionType.OVERWORLD).setSpawnPoint(STARTING_POSITION);
mc.getIntegratedServer().worlds[0].getGameRules().setOrCreateGameRule("spawnRadius", "0"); server.getWorld(DimensionType.OVERWORLD).getGameRules().setOrCreateGameRule("spawnRadius", "0", server);
} }
if (event.getType() == TickEvent.Type.IN) { // If we're in-game if (event.getType() == TickEvent.Type.IN) { // If we're in-game
@@ -100,7 +109,7 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
// Force the integrated server to share the world to LAN so that // Force the integrated server to share the world to LAN so that
// the ingame pause menu gui doesn't actually pause our game // the ingame pause menu gui doesn't actually pause our game
if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) { if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) {
mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false); mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false, HttpUtil.getSuitableLanPort());
} }
// For the first 200 ticks, wait for the world to generate // For the first 200 ticks, wait for the world to generate
@@ -115,12 +124,23 @@ 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())) {
System.out.println("Successfully pathed to " + ctx.playerFeet() + " in " + event.getCount() + " ticks"); System.out.println("Successfully pathed to " + ctx.playerFeet() + " in " + event.getCount() + " ticks");
try {
File file = new File("success");
System.out.println("Writing success to " + file.getAbsolutePath());
Files.write(file.getAbsoluteFile().toPath(), "Success!".getBytes());
} catch (IOException e) {
e.printStackTrace();
}
mc.shutdown(); mc.shutdown();
mc.shutdownMinecraftApplet();
System.exit(0);
} }
// If we have exceeded the expected number of ticks to complete the pathing // If we have exceeded the expected number of ticks to complete the pathing

Some files were not shown because too many files have changed in this diff Show More