Compare commits

..

203 Commits

Author SHA1 Message Date
Leijurv
125c8a6742 original blockpos for comparison 2018-09-09 13:56:40 -07:00
Leijurv
d8ca6cad4e i am an idiot 2: electric boogaloo 2018-09-09 13:19:48 -07:00
Leijurv
d29a37664c clarify error messages 2018-09-09 13:09:56 -07:00
Leijurv
4221c07d1f i don't know how i keep getting worldscanner wrong lol 2018-09-09 13:04:41 -07:00
Leijurv
6801d00d7e enable 1-skipback 2018-09-09 11:06:02 -07:00
Leijurv
7b712fe677 add synchronization, fixes #145 2018-09-09 11:00:57 -07:00
Leijurv
4a13b54e50 brady was right and I was wrong 2018-09-09 10:27:47 -07:00
Leijurv
ef4de2b159 oh look and another bug 2018-09-09 09:55:59 -07:00
Leijurv
44ece7c510 prevent double lookup 2018-09-09 09:54:09 -07:00
Leijurv
07b0e2cdbf block state interface cache region too 2018-09-09 09:50:19 -07:00
Leijurv
760f68cb05 instead of casting to BetterBlockPos at runtime, let the compiler verify that 2018-09-09 09:22:35 -07:00
Leijurv
dce51d856b more specific return type 2018-09-09 08:58:36 -07:00
Leijurv
a8ef421757 epic performance 2018-09-09 08:57:20 -07:00
Leijurv
b69acadca6 start of blockstateinterface overhaul 2018-09-09 08:53:15 -07:00
Leijurv
387e27e8de movementhelper overhaul 2018-09-09 08:11:33 -07:00
Leijurv
2533cbc2c1 Merge pull request #139 from cabaletta/parkour
Parkour
2018-09-09 07:27:08 -07:00
Leijurv
02ebc1947b actually disable by default 2018-09-09 07:18:03 -07:00
Leijurv
b31930ebd2 merge 2018-09-09 07:16:46 -07:00
Leijurv
83693525af Merge branch 'master' of github.com:cabaletta/baritone 2018-09-09 07:15:54 -07:00
Leijurv
489b9dea98 fix world scanner radius 2018-09-09 07:15:48 -07:00
Brady
b143dcff5f You can use it in COMPLIANCE 2018-09-09 00:27:24 -05:00
Brady
dfd2ef055e Merge pull request #142 from cabaletta/direct-invocation
direct invocation
2018-09-08 22:48:47 -05:00
Leijurv
b45a2c94ea direct invocation 2018-09-08 20:45:40 -07:00
Leijurv
fadb17f364 that was dumb 2018-09-08 14:16:54 -07:00
Leijurv
9577967da1 final 2018-09-08 08:15:10 -07:00
Leijurv
132e277388 { } 2018-09-07 21:32:25 -07:00
Leijurv
5ffd21dddc Merge branch 'master' into parkour 2018-09-07 20:45:10 -07:00
Leijurv
9052781889 smaller cuter boxes for goaltwoblocks 2018-09-07 20:45:00 -07:00
Leijurv
3261687ee0 render more goals, fixes #25 2018-09-07 20:44:50 -07:00
Leijurv
6ad9451798 smaller cuter boxes for goaltwoblocks 2018-09-07 20:43:12 -07:00
Leijurv
85babda97e render more goals, fixes #25 2018-09-07 18:23:32 -07:00
Leijurv
2d969b55ef fix world scanner radius 2018-09-07 18:23:05 -07:00
Brady
392395446d Merge pull request #96 from cabaletta/movement-duplicate-switch
Cleaned up 7 duplicate switch statements
2018-09-07 19:43:26 -05:00
Brady
d17cc96e90 Constructor fix 2018-09-07 19:40:15 -05:00
Brady
e5f8b5de5b Merge branch 'master' into movement-duplicate-switch 2018-09-07 19:36:06 -05:00
Brady
99323463e3 Fix improper treatment of unbreakable blocks 2018-09-07 19:00:36 -05:00
Leijurv
ead6edc574 merge 2018-09-07 13:35:14 -07:00
Leijurv
dcad5fb79e shouldn't be on master yet 2018-09-07 13:34:34 -07:00
Leijurv
439ff92727 crucial performance optimization 2018-09-07 13:33:51 -07:00
Leijurv
0d515b336f can get to block at eye level adjacent too 2018-09-07 10:50:49 -07:00
Leijurv
e51c729acb update in progress 2018-09-06 21:31:10 -07:00
Leijurv
9757422626 also check where we might hit our head 2018-09-06 10:14:41 -07:00
Leijurv
b746e56631 lol you can't jump with a ceiling above you 2018-09-06 10:13:50 -07:00
Leijurv
915b03a44e lol 2018-09-06 07:54:12 -07:00
Leijurv
5e063f56a2 merge master 2018-09-06 07:48:52 -07:00
Leijurv
63b04df95d parkour 2018-09-06 07:48:27 -07:00
Leijurv
8a7013d8d3 add readme for gradlew run 2018-09-05 21:31:36 -07:00
Leijurv
008422680d that should NOT have been there 2018-09-05 21:08:18 -07:00
Leijurv
db3aa5a714 lets allow it, fixes #137 2018-09-05 19:52:06 -07:00
Leijurv
de84a49391 fix tool set once and for all, fixes #136 2018-09-04 17:15:59 -07:00
Brady
2cf9a3a74b Fix bad refmap SourceSet link 2018-09-04 18:50:53 -05:00
Brady
bba2458f8e Separate "launch" into another SourceSet 2018-09-04 18:48:12 -05:00
Leijurv
a45f291d67 vine and ladder fixes 2018-09-04 16:19:23 -07:00
Brady
1e6599cc42 Consolidate plugins in build.gradle 2018-09-04 18:08:29 -05:00
Brady
40e86df080 Remove unnecessary abstract mixin class modifiers 2018-09-04 18:06:28 -05:00
Leijurv
d40418d344 move updateState after calculateCost for consistency with every other movement 2018-09-04 16:04:44 -07:00
Leijurv
81ffbddc94 start with more than one chunk 2018-09-04 16:02:31 -07:00
Leijurv
0c4fd39845 better error message 2018-09-04 15:53:11 -07:00
Leijurv
2bb01fdd20 decrease scan rate 2018-09-04 15:33:38 -07:00
Leijurv
69d8bd56fa rearranged loop order 2018-09-04 15:23:54 -07:00
Leijurv
e7d41ba4fc optimize chunk packer with extended block storage 2018-09-04 15:19:16 -07:00
Brady
8c9bb85d4b Fully separate dependency on launch package from other packages 2018-09-04 17:18:42 -05:00
Leijurv
4f07d655d6 don't scan empty 2018-09-04 15:08:21 -07:00
Leijurv
7cc23bc89b scan for uninteresting blocks in loaded chunks, fixes #99 2018-09-04 15:03:59 -07:00
Leijurv
0bd3f9f680 fix water fall logic 2018-09-04 13:57:56 -07:00
Leijurv
9f156e8e27 updated dropbox file name and link 2018-09-04 13:23:26 -07:00
Leijurv
288e57d275 fix warning 2018-09-04 13:20:49 -07:00
Leijurv
b8ee7f5b96 Merge branch 'slabs-stairs' 2018-09-04 10:07:08 -07:00
Leijurv
3fd1063e3c cache on block not blockstate 2018-09-04 10:06:48 -07:00
Leijurv
ebd4930fe4 fix horrendous typo 2018-09-04 09:57:19 -07:00
Leijurv
424113f052 don't sprint if hunger is too low 2018-09-04 09:55:56 -07:00
Leijurv
438392840b possible fix to concurrentmodificationexception on path start 2018-09-04 08:56:34 -07:00
Leijurv
f51bcc8b89 forgot null check 2018-09-04 08:51:58 -07:00
Leijurv
2452a69089 mine many block types at once 2018-09-04 08:50:42 -07:00
Leijurv
5cfb270a32 update proguard 2018-09-04 08:48:55 -07:00
Leijurv
c367297136 Merge branch 'master' into slabs-stairs 2018-09-03 20:42:57 -07:00
Leijurv
a2f0a1839a fix goal get to block 2018-09-03 20:42:28 -07:00
Leijurv
bfafca541f add proguard 2018-09-03 17:01:04 -07:00
Leijurv
07a9829865 accurate debug 2018-09-03 16:24:43 -07:00
Leijurv
dd1a20a047 final makes things faster 2018-09-03 16:14:14 -07:00
Leijurv
25c21df9fc Merge branch 'master' into slabs-stairs 2018-09-03 12:07:03 -07:00
Leijurv
53f2ab5901 fix badge link destination 2018-09-03 12:06:58 -07:00
Leijurv
fc0d4c67f2 merge 2018-09-03 12:05:18 -07:00
Leijurv
574fd05376 fix bucket check, fixes #128 2018-09-03 12:03:49 -07:00
Leijurv
21342d6ea5 Merge branch 'master' into slabs-stairs 2018-09-03 11:43:24 -07:00
Leijurv
4690bcb5ac add example 2018-09-03 11:43:17 -07:00
Leijurv
6eb293c97a update documentation 2018-09-03 11:33:02 -07:00
Leijurv
bfd41f9473 stairs 2018-09-03 11:27:59 -07:00
Brady
53d9d3da5e lol 2018-09-03 12:58:21 -05:00
Brady
ba7dc46442 Another Impact install update 2018-09-03 12:43:27 -05:00
Brady
da67c4aca9 Make some changes to the Impact installation 2018-09-03 12:42:00 -05:00
Leijurv
dcfc7a1bd6 added note 2018-09-03 10:13:11 -07:00
Leijurv
b3b9bb8aa5 prebuilt jar 2018-09-03 10:11:42 -07:00
Leijurv
c2fc241d89 impact integration instructions 2018-09-03 10:05:08 -07:00
Leijurv
4b2f98ccfd consolidate and simplify into MovementHelper.isBottomSlab 2018-09-03 09:50:26 -07:00
Leijurv
5151c77703 Move badge below header 2018-09-03 09:25:44 -07:00
Leijurv
7473e34602 check for top or double slab 2018-09-03 09:24:44 -07:00
Leijurv
d328438cf2 no falling onto half slab 2018-09-03 09:21:26 -07:00
Leijurv
16f88aa858 setting 2018-09-03 09:18:30 -07:00
Leijurv
bac07ce100 slabs 2018-09-03 09:15:18 -07:00
Brady
31a87a8938 Added travis badge to README 2018-09-02 23:26:57 -05:00
Brady
5dbf1014b3 Fix usage of characters that can't be mapped to ascii 2018-09-02 21:28:55 -05:00
Brady
12ec7ea990 Update README.md 2018-09-02 18:01:41 -05:00
Leijurv
7fd0d5799d travis start 2018-09-02 14:46:41 -07:00
Leijurv
a1aaaef67f include sponge in runtime 2018-09-02 14:46:03 -07:00
Leijurv
41c03cbf36 update readme 2018-09-02 14:19:21 -07:00
Leijurv
8c58dcb41f remove unused circle ci config 2018-09-02 14:13:41 -07:00
Leijurv
f75188b24d fix cost cache overwrite in path executor 2018-09-02 14:12:33 -07:00
Leijurv
c63ccc3dcb can walk through should be cached as air, fixes #124 2018-09-02 14:10:27 -07:00
Leijurv
da5460413c segment based timeout, and slowpath warning 2018-09-02 13:51:38 -07:00
Leijurv
9e272824c5 traverse should also break the block in the way 2018-09-02 13:34:15 -07:00
Leijurv
7ed13bf358 features 2018-09-02 13:05:09 -07:00
Leijurv
639ec38981 features 2018-09-02 13:05:09 -07:00
Brady
0e6d61e907 Consolidate rayTraceTowards into RayTraceUtils, fixes #121 2018-09-02 14:21:34 -05:00
Brady
115b8553b2 Make Baritone initialization listeners consumers 2018-09-02 14:18:17 -05:00
Leijurv
e8b108fde8 removePrefix 2018-09-02 12:06:00 -07:00
Leijurv
8d62f754a7 crucial performance optimization 2018-09-02 12:04:48 -07:00
Leijurv
5caa0542ba ascend should clear the replaceable block in the way 2018-09-02 11:48:10 -07:00
Leijurv
6389917898 more features 2018-09-02 11:39:13 -07:00
Leijurv
1cb25e29c7 add links 2018-09-02 11:25:44 -07:00
Leijurv
5ed40ff50d better list 2018-09-02 11:18:27 -07:00
Leijurv
1f73fe8c79 add link to features 2018-09-02 11:16:11 -07:00
Leijurv
262b33f322 pathing method and upcoming features 2018-09-02 11:14:57 -07:00
Leijurv
17b27af09f more features 2018-09-02 11:09:28 -07:00
Leijurv
f3bd50dc36 disable load boundary cutoff by default, fixes #114 2018-09-02 10:46:54 -07:00
Leijurv
e58c43305c typo 2018-09-02 10:45:07 -07:00
Leijurv
462ccad885 use initial estimate from calculation phase 2018-09-02 10:43:34 -07:00
Leijurv
3afd836822 only offset down if doing so would put us on solid ground 2018-09-02 09:22:51 -07:00
Leijurv
1f97daf391 clean up the clutter 2018-09-02 07:18:57 -07:00
Leijurv
2e22f1cf54 hopefully make currentlyRunning more resilient 2018-09-01 14:47:46 -07:00
Leijurv
e705f9808b add force cancel 2018-09-01 14:45:57 -07:00
Leijurv
8d46c36269 you can walk on chests 2018-09-01 13:20:27 -07:00
Leijurv
76cdad2223 properly place on soul sand, fixes #118 2018-09-01 12:47:43 -07:00
Leijurv
c0bc7b5ecd fix strange issue when exiting and entering the same world 2018-09-01 12:26:55 -07:00
Leijurv
aca487f97e fix behavior when all have been mined 2018-09-01 12:16:55 -07:00
Leijurv
e354227635 allow goto blocks that end in s 2018-09-01 11:31:42 -07:00
Leijurv
0b892e05cb goto next to block, not in it, fixes #116 2018-09-01 11:30:02 -07:00
Leijurv
3c25e2b685 fix part of oscillation 2018-09-01 11:19:42 -07:00
Leijurv
791eb886c0 bugfix 2018-08-31 16:50:25 -07:00
Leijurv
24c5c5d238 instant cancel when more than 3 blocks away 2018-08-31 15:21:59 -07:00
Leijurv
c08f0f1e4d Merge branch 'master' of github.com:cabaletta/baritone 2018-08-31 14:58:28 -07:00
Leijurv
3f688bc45e spam chat less 2018-08-31 14:58:23 -07:00
Brady
f10e010e20 GoalNear#toString 2018-08-31 16:32:15 -05:00
Leijurv
a93af3404b cache chunk in BlockStateInterface, fixes #113 2018-08-31 12:58:52 -07:00
leijurv
7cd0b186a9 lava hurts just as much as magma when cutting over 2018-08-31 08:13:16 -07:00
Leijurv
aa3a8338e6 stop sprinting off ledges, fixes #110 2018-08-30 16:43:12 -07:00
Brady
606581b044 Wrap immutable list in normal arraylist to fix errors with adding 2018-08-29 20:35:57 -05:00
Brady
1734caeed8 Minor MovementDiagonal cleanup 2018-08-29 18:59:22 -05:00
Brady
51593a95e4 Add soul sand sprinting cost, @leijurv should implement it im lazy 2018-08-29 18:56:36 -05:00
Brady
532024248f Actual soul sand walk cost, fixes #7 2018-08-29 18:53:37 -05:00
Brady
336b323697 Replace Math.X functions with MathHelper.X functions, fixes #111 2018-08-29 18:45:16 -05:00
Brady
4b41c6b1d7 Replace anonymous thread creation with runnable constructor 2018-08-29 18:32:16 -05:00
Brady
b073d591fb Fix non-monotonic elapsed time checks, fixes #108 2018-08-29 18:23:11 -05:00
Leijurv
be303f2e57 crucial performance optimization 2018-08-29 16:13:14 -07:00
Leijurv
95cda79ef1 small open set change 2018-08-29 15:35:41 -07:00
Leijurv
cebdd76ca7 node map performance, fixes #107 2018-08-29 13:51:17 -07:00
Leijurv
5c5507cc9e readme 2018-08-29 12:25:03 -07:00
Leijurv
0342136edc fix chunk cache check performance, fixes #106 2018-08-29 12:19:21 -07:00
Leijurv
81b0e14c9a more debug info 2018-08-29 11:53:37 -07:00
Leijurv
fb04ec6ff4 chunk check optimization 2018-08-29 11:29:26 -07:00
leijurv
8d1570a11b cherry pick 3x faster cache check 2018-08-28 21:16:27 -07:00
leijurv
e553ee93b8 20% improvement to cached chunk check performance 2018-08-28 21:11:10 -07:00
Leijurv
23cbef102d more debug info 2018-08-28 16:15:24 -07:00
Leijurv
340b1558e4 debug cosmetic improvements 2018-08-28 15:53:29 -07:00
Leijurv
f99abd6170 fix world event post not firing for exit 2018-08-28 15:24:43 -07:00
Leijurv
a3e5714e91 collect canPlaceAgainst into one place 2018-08-28 15:01:24 -07:00
Leijurv
d433cbb90b no more against array creation 2018-08-28 14:56:21 -07:00
Leijurv
a33b515871 fixed chunk packing bug 2018-08-28 14:15:20 -07:00
Leijurv
324c3a2705 S A N I K 2018-08-28 14:04:51 -07:00
Leijurv
801f942c30 S A N I K 2018-08-28 14:02:57 -07:00
Leijurv
4e531ec578 SANIK 2018-08-28 14:00:40 -07:00
Leijurv
804cad2776 sanik 2018-08-28 14:00:02 -07:00
Leijurv
ff83b42132 fix heightMap bug 2018-08-28 13:58:36 -07:00
Leijurv
557f2e48c3 no movement places more than one thing... 2018-08-28 13:41:44 -07:00
Leijurv
53d477d99a optimize diagonal 2018-08-28 13:29:32 -07:00
Leijurv
4836f044ba pillar logic 2018-08-28 13:24:34 -07:00
Leijurv
1dc0f5c3ad update logic 2018-08-28 12:53:01 -07:00
Leijurv
d4d2fb392a small optimization 2018-08-28 12:40:35 -07:00
Leijurv
890e5be0ed assumeWalkOnWater 2018-08-28 12:30:08 -07:00
Leijurv
bf05de1de7 can't use flowing water, so pack it as such 2018-08-28 12:23:54 -07:00
Leijurv
169eb1d0a3 more efficient check 2018-08-28 11:57:41 -07:00
Leijurv
01dbf75eca MineBehavior 2018-08-28 11:43:28 -07:00
Leijurv
c761a9b127 better chunk saving and loading 2018-08-28 11:28:36 -07:00
Leijurv
c0fb57825c cancel calculation in progress 2018-08-28 11:17:11 -07:00
Leijurv
df73e07923 Add comment, fixes #102 2018-08-28 10:04:25 -07:00
leijurv
09a146e0ce Merge branch 'master' of github.com:cabaletta/baritone 2018-08-28 08:56:06 -07:00
leijurv
46fefa9298 simplification support for more goal types 2018-08-28 08:55:56 -07:00
Leijurv
850beb6c08 really cancel 2018-08-28 07:29:41 -07:00
leijurv
c404258b00 Merge branch 'master' of github.com:cabaletta/baritone 2018-08-27 19:15:16 -07:00
leijurv
27a3adeceb FollowBehavior 2018-08-27 19:05:21 -07:00
Brady
65bfe466bb Clean up retrieving tags by string 2018-08-27 20:06:48 -05:00
leijurv
af3bc18079 add GoalNear 2018-08-27 18:00:11 -07:00
Brady
43b7aece74 Move events to api package 2018-08-27 19:37:21 -05:00
Brady
423087cc12 Add a way to hook into Baritone's post-init stage 2018-08-27 17:45:43 -05:00
Brady
8f8bedb1b0 If we're going to have a getter we might as well use it 2018-08-27 14:35:30 -05:00
Leijurv
9762fe73cf fix 2018-08-27 12:12:52 -07:00
Leijurv
fe8e9202e2 merge 2018-08-27 12:12:19 -07:00
Leijurv
aca6503ac6 readme 2018-08-27 12:02:51 -07:00
Brady
3da6b160db Include setup commands in the README 2018-08-27 13:59:36 -05:00
Brady
71e04ad104 Change the instructions in the README 2018-08-27 13:53:17 -05:00
Brady
92e0b842be Double frown? Let's be more positive! 2018-08-27 13:51:22 -05:00
Brady
3bf4b997b0 Rename getByValueType to getAllValuesByType 2018-08-27 13:39:36 -05:00
Brady
91c4d8292d Cleaned up 7 duplicate switch statements 2018-08-26 02:53:50 -05:00
107 changed files with 3042 additions and 1864 deletions

View File

@@ -1,43 +0,0 @@
# Java Gradle CircleCI 2.0 configuration file
#
# Check https://circleci.com/docs/2.0/language-java/ for more details
#
version: 2
jobs:
build:
docker:
# specify the version you desire here
- image: circleci/openjdk:8-jdk
# Specify service dependencies here if necessary
# CircleCI maintains a library of pre-built images
# documented at https://circleci.com/docs/2.0/circleci-images/
# - image: circleci/postgres:9.4
working_directory: ~/repo
environment:
# Customize the JVM maximum heap limit
JVM_OPTS: -Xmx3200m
TERM: dumb
steps:
- checkout
# Download and cache dependencies
- restore_cache:
keys:
- v1-dependencies-{{ checksum "build.gradle" }}
# fallback to using the latest cache if no exact match is found
- v1-dependencies-
- run: gradle dependencies
- save_cache:
paths:
- ~/.gradle
key: v1-dependencies-{{ checksum "build.gradle" }}
# run tests!
- run: gradle test

1
.travis.yml Normal file
View File

@@ -0,0 +1 @@
language: java

49
FEATURES.md Normal file
View File

@@ -0,0 +1,49 @@
# Pathing features
- **Long distance pathing and splicing** Baritone calculates paths in segments, and precalculates the next segment when the current one is about to end, so that it's moving towards the goal at all times.
- **Chunk caching** Baritone simplifies chunks to a compacted internal 2-bit representation (AIR, SOLID, WATER, AVOID) and stores them in RAM for better very-long-distance pathing. There is also an option to save these cached chunks to disk. <a href="https://www.youtube.com/watch?v=dyfYKSubhdc">Example</a>
- **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>
- **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`).
- **Opening fence gates and doors**
- **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).
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
- **Parkour** Sprint jumping over 1, 2, or 3 block gaps
# Pathing method
Baritone uses a modified version of A*.
- **Incremental cost backoff** Since most of the time Baritone only knows the terrain up to the render distance, it can't calculate a full path to the goal. Therefore it needs to select a segment to execute first (assuming it will calculate the next segment at the end of this one). It uses incremental cost backoff to select the best node by varying metrics, then paths to that node. This is unchanged from MineBot and I made a <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">write-up</a> that still applies. In essence, it keeps track of the best node by various increasing coefficients, then picks the node with the least coefficient that goes at least 5 blocks from the starting position.
- **Minimum improvement repropagation** The pathfinder ignores alternate routes that provide minimal improvements (less than 0.01 ticks of improvement), because the calculation cost of repropagating this to all connected nodes is much higher than the half-millisecond path time improvement it would get.
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment slightly, as a tiebreaker. 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>
# Configuring Baritone
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/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.
# Goals
The pathing goal can be set to any of these options:
- **GoalBlock** one specific block that the player should stand inside at foot level
- **GoalXZ** an X and a Z coordinate, used for long distance pathing
- **GoalYLevel** a Y coordinate
- **GoalTwoBlocks** a block position that the player should stand in, either at foot or eye level
- **GoalGetToBlock** a block position that the player should stand adjacent to, below, or on top of
- **GoalNear** a block position that the player should get within a certain radius of, used for following entities
And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one of which satisfies the goal. For example, `mine diamond_ore` creates a `GoalComposite` of `GoalTwoBlocks`s for every diamond ore location it knows of.
# Future features
Things it doesn't have yet
- Trapdoors
- Sprint jumping in a 1x2 corridor
- Parkour (jumping over gaps of any length) [IN PROGRESS]
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.
Things it may not ever have, from most likely to least likely =(
- Pigs
- Boats
- Horses (2x3 path instead of 1x2)
- Elytra

16
IMPACT.md Normal file
View File

@@ -0,0 +1,16 @@
# Integration between Baritone and Impact
Baritone will be in Impact 4.4 with nice integrations with its utility modules, but if you're impatient you can run Baritone on top of Impact 4.3 right now.
You can either build Baritone yourself, or download the jar from September 4 from <a href="https://www.dropbox.com/s/imc6xwwpwsh3i0y/baritone-1.0.0.jar?dl=0">here</a>
To build it yourself, clone and setup Baritone (instructions in main README.md). Then, build the jar. From the command line, it's `./gradlew build` (or `gradlew build` on Windows). In IntelliJ, you can just start the `build` task in the Gradle menu.
Copy the jar into place. It should be `build/libs/baritone-1.0.0.jar` in baritone. Copy it to your libraries in your Minecraft install. For example, on Mac I do `cp Documents/baritone/build/libs/baritone-1.0.0.jar Library/Application\ Support/minecraft/libraries/cabaletta/baritone/1.0.0/baritone-1.0.0.jar`. The first time you'll need to make the directory `cabaletta/baritone/1.0.0` in libraries first.
Then, we'll need to modify the Impact launch json. Open `minecraft/versions/1.12.2-Impact_4.3/1.12.2-Impact_4.3.json` or copy your existing installation and rename the version folder, json, and id in the json.
- Add the Baritone tweak class to line 7 "minecraftArguments" like so: `"minecraftArguments": " ... --tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine",`. You need the Optifine tweaker even though there is no Optifine involved, for reasons I don't quite understand.
- Add the Baritone library. Insert `{ "name": "cabaletta:baritone:1.0.0" },` between Impact and ClientAPI, which should be between lines 15 and 16.
Restart the Minecraft launcher, then load Impact 4.3 as normal, and it should now include Baritone.

View File

@@ -1,10 +1,57 @@
# Baritone
[![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone)
A Minecraft bot. 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.
<a href="https://github.com/cabaletta/baritone/blob/master/FEATURES.md">Features</a>
<a href="https://github.com/cabaletta/baritone/blob/master/IMPACT.md">Baritone + Impact</a>
# Setup
- Open the project in IntelliJ as a Gradle project
- Run the Gradle task `setupDecompWorkspace`
- Run the Gradle task `genIntellijRuns`
- Restart IntelliJ and import Gradle changes
- Select the "Minecraft Client" launch config and run
- Refresh the Gradle project (or just restart IntelliJ)
- Select the "Minecraft Client" launch config and run
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
Running Baritone:
```
$ gradlew run
```
Setting up for IntelliJ:
```
$ gradlew setupDecompWorkspace
$ gradlew --refresh-dependencies
$ gradlew genIntellijRuns
```
# Chat control
<a href="https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java">Defined here</a>
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 example
```
Baritone.settings().allowSprint.value = true;
Baritone.settings().pathTimeoutMS.value = 2000L;
PathingBehavior.INSTANCE.setGoal(new GoalXZ(10000, 20000));
PathingBehavior.INSTANCE.path();
```
# FAQ
## Can I use Baritone as a library in my hacked client?
Sure! (As long as usage is in compliance with the GPL 3 License)
## How is it so fast?
Magic

View File

@@ -38,14 +38,19 @@ buildscript {
}
apply plugin: 'java'
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = targetCompatibility = '1.8'
compileJava {
sourceCompatibility = targetCompatibility = '1.8'
}
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
apply plugin: 'org.spongepowered.mixin'
sourceSets {
launch {
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
}
}
minecraft {
version = '1.12.2'
@@ -65,7 +70,7 @@ repositories {
}
dependencies {
implementation ('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
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'
@@ -78,5 +83,9 @@ dependencies {
mixin {
defaultObfuscationEnv notch
add sourceSets.main, 'mixins.baritone.refmap.json'
add sourceSets.launch, 'mixins.baritone.refmap.json'
}
jar {
from sourceSets.launch.output
}

369
proguard.pro vendored Normal file
View File

@@ -0,0 +1,369 @@
-injars baritone-1.0.0.jar
-outjars Obfuscated
-keepattributes Signature
-keepattributes *Annotation*
-optimizationpasses 20
-verbose
-allowaccessmodification # anything not kept can be changed from public to private and inlined etc
-mergeinterfacesaggressively
-overloadaggressively
-dontusemixedcaseclassnames
# instead of obfing to a, b, c, obf to baritone.a, baritone.b, baritone.c so as to not conflict with mcp
-flattenpackagehierarchy
-repackageclasses 'baritone'
#-keep class baritone.behavior.** { *; }
#-keep class baritone.api.** { *; }
#-keep class baritone.* { *; }
#-keep class baritone.pathing.goals.** { *; }
# setting names are reflected from field names, so keep field names
-keepclassmembers class baritone.Settings {
public <fields>;
}
# need to keep mixin names
-keep class baritone.launch.** { *; }
# copy all necessary libraries into tempLibraries to build
-libraryjars '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/rt.jar'
-libraryjars 'tempLibraries/1.12.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/java-objc-bridge-1.0.0-natives-osx.jar'
-libraryjars 'tempLibraries/java-objc-bridge-1.0.0.jar'
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
-libraryjars 'tempLibraries/jinput-platform-2.0.5-natives-osx.jar'
-libraryjars 'tempLibraries/jna-4.4.0.jar'
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
-libraryjars 'tempLibraries/jsr305-3.0.1-sources.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'
-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar'
-libraryjars 'tempLibraries/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar'
-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.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.8-SNAPSHOT.jar'
-libraryjars 'tempLibraries/launchwrapper-1.12.jar'
# Keep - Applications. Keep all application classes, along with their 'main'
# methods.
-keepclasseswithmembers public class * {
public static void main(java.lang.String[]);
}
# Also keep - Enumerations. Keep the special static methods that are required in
# enumeration classes.
-keepclassmembers enum * {
public static **[] values();
public static ** valueOf(java.lang.String);
}
# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
-keep class * extends java.sql.Driver
# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
# along with the special 'createUI' method.
-keep class * extends javax.swing.plaf.ComponentUI {
public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
}
# Keep names - Native method names. Keep all native class/method names.
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
native <methods>;
}
# Remove - System method calls. Remove all invocations of System
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.System {
public static long currentTimeMillis();
static java.lang.Class getCallerClass();
public static int identityHashCode(java.lang.Object);
public static java.lang.SecurityManager getSecurityManager();
public static java.util.Properties getProperties();
public static java.lang.String getProperty(java.lang.String);
public static java.lang.String getenv(java.lang.String);
public static java.lang.String mapLibraryName(java.lang.String);
public static java.lang.String getProperty(java.lang.String,java.lang.String);
}
# Remove - Math method calls. Remove all invocations of Math
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.Math {
public static double sin(double);
public static double cos(double);
public static double tan(double);
public static double asin(double);
public static double acos(double);
public static double atan(double);
public static double toRadians(double);
public static double toDegrees(double);
public static double exp(double);
public static double log(double);
public static double log10(double);
public static double sqrt(double);
public static double cbrt(double);
public static double IEEEremainder(double,double);
public static double ceil(double);
public static double floor(double);
public static double rint(double);
public static double atan2(double,double);
public static double pow(double,double);
public static int round(float);
public static long round(double);
public static double random();
public static int abs(int);
public static long abs(long);
public static float abs(float);
public static double abs(double);
public static int max(int,int);
public static long max(long,long);
public static float max(float,float);
public static double max(double,double);
public static int min(int,int);
public static long min(long,long);
public static float min(float,float);
public static double min(double,double);
public static double ulp(double);
public static float ulp(float);
public static double signum(double);
public static float signum(float);
public static double sinh(double);
public static double cosh(double);
public static double tanh(double);
public static double hypot(double,double);
public static double expm1(double);
public static double log1p(double);
}
# Remove - Number method calls. Remove all invocations of Number
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.* extends java.lang.Number {
public static java.lang.String toString(byte);
public static java.lang.Byte valueOf(byte);
public static byte parseByte(java.lang.String);
public static byte parseByte(java.lang.String,int);
public static java.lang.Byte valueOf(java.lang.String,int);
public static java.lang.Byte valueOf(java.lang.String);
public static java.lang.Byte decode(java.lang.String);
public int compareTo(java.lang.Byte);
public static java.lang.String toString(short);
public static short parseShort(java.lang.String);
public static short parseShort(java.lang.String,int);
public static java.lang.Short valueOf(java.lang.String,int);
public static java.lang.Short valueOf(java.lang.String);
public static java.lang.Short valueOf(short);
public static java.lang.Short decode(java.lang.String);
public static short reverseBytes(short);
public int compareTo(java.lang.Short);
public static java.lang.String toString(int,int);
public static java.lang.String toHexString(int);
public static java.lang.String toOctalString(int);
public static java.lang.String toBinaryString(int);
public static java.lang.String toString(int);
public static int parseInt(java.lang.String,int);
public static int parseInt(java.lang.String);
public static java.lang.Integer valueOf(java.lang.String,int);
public static java.lang.Integer valueOf(java.lang.String);
public static java.lang.Integer valueOf(int);
public static java.lang.Integer getInteger(java.lang.String);
public static java.lang.Integer getInteger(java.lang.String,int);
public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer);
public static java.lang.Integer decode(java.lang.String);
public static int highestOneBit(int);
public static int lowestOneBit(int);
public static int numberOfLeadingZeros(int);
public static int numberOfTrailingZeros(int);
public static int bitCount(int);
public static int rotateLeft(int,int);
public static int rotateRight(int,int);
public static int reverse(int);
public static int signum(int);
public static int reverseBytes(int);
public int compareTo(java.lang.Integer);
public static java.lang.String toString(long,int);
public static java.lang.String toHexString(long);
public static java.lang.String toOctalString(long);
public static java.lang.String toBinaryString(long);
public static java.lang.String toString(long);
public static long parseLong(java.lang.String,int);
public static long parseLong(java.lang.String);
public static java.lang.Long valueOf(java.lang.String,int);
public static java.lang.Long valueOf(java.lang.String);
public static java.lang.Long valueOf(long);
public static java.lang.Long decode(java.lang.String);
public static java.lang.Long getLong(java.lang.String);
public static java.lang.Long getLong(java.lang.String,long);
public static java.lang.Long getLong(java.lang.String,java.lang.Long);
public static long highestOneBit(long);
public static long lowestOneBit(long);
public static int numberOfLeadingZeros(long);
public static int numberOfTrailingZeros(long);
public static int bitCount(long);
public static long rotateLeft(long,int);
public static long rotateRight(long,int);
public static long reverse(long);
public static int signum(long);
public static long reverseBytes(long);
public int compareTo(java.lang.Long);
public static java.lang.String toString(float);
public static java.lang.String toHexString(float);
public static java.lang.Float valueOf(java.lang.String);
public static java.lang.Float valueOf(float);
public static float parseFloat(java.lang.String);
public static boolean isNaN(float);
public static boolean isInfinite(float);
public static int floatToIntBits(float);
public static int floatToRawIntBits(float);
public static float intBitsToFloat(int);
public static int compare(float,float);
public boolean isNaN();
public boolean isInfinite();
public int compareTo(java.lang.Float);
public static java.lang.String toString(double);
public static java.lang.String toHexString(double);
public static java.lang.Double valueOf(java.lang.String);
public static java.lang.Double valueOf(double);
public static double parseDouble(java.lang.String);
public static boolean isNaN(double);
public static boolean isInfinite(double);
public static long doubleToLongBits(double);
public static long doubleToRawLongBits(double);
public static double longBitsToDouble(long);
public static int compare(double,double);
public boolean isNaN();
public boolean isInfinite();
public int compareTo(java.lang.Double);
public byte byteValue();
public short shortValue();
public int intValue();
public long longValue();
public float floatValue();
public double doubleValue();
public int compareTo(java.lang.Object);
public boolean equals(java.lang.Object);
public int hashCode();
public java.lang.String toString();
}
# Remove - String method calls. Remove all invocations of String
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.String {
public static java.lang.String copyValueOf(char[]);
public static java.lang.String copyValueOf(char[],int,int);
public static java.lang.String valueOf(boolean);
public static java.lang.String valueOf(char);
public static java.lang.String valueOf(char[]);
public static java.lang.String valueOf(char[],int,int);
public static java.lang.String valueOf(double);
public static java.lang.String valueOf(float);
public static java.lang.String valueOf(int);
public static java.lang.String valueOf(java.lang.Object);
public static java.lang.String valueOf(long);
public boolean contentEquals(java.lang.StringBuffer);
public boolean endsWith(java.lang.String);
public boolean equalsIgnoreCase(java.lang.String);
public boolean equals(java.lang.Object);
public boolean matches(java.lang.String);
public boolean regionMatches(boolean,int,java.lang.String,int,int);
public boolean regionMatches(int,java.lang.String,int,int);
public boolean startsWith(java.lang.String);
public boolean startsWith(java.lang.String,int);
public byte[] getBytes();
public byte[] getBytes(java.lang.String);
public char charAt(int);
public char[] toCharArray();
public int compareToIgnoreCase(java.lang.String);
public int compareTo(java.lang.Object);
public int compareTo(java.lang.String);
public int hashCode();
public int indexOf(int);
public int indexOf(int,int);
public int indexOf(java.lang.String);
public int indexOf(java.lang.String,int);
public int lastIndexOf(int);
public int lastIndexOf(int,int);
public int lastIndexOf(java.lang.String);
public int lastIndexOf(java.lang.String,int);
public int length();
public java.lang.CharSequence subSequence(int,int);
public java.lang.String concat(java.lang.String);
public java.lang.String replaceAll(java.lang.String,java.lang.String);
public java.lang.String replace(char,char);
public java.lang.String replaceFirst(java.lang.String,java.lang.String);
public java.lang.String[] split(java.lang.String);
public java.lang.String[] split(java.lang.String,int);
public java.lang.String substring(int);
public java.lang.String substring(int,int);
public java.lang.String toLowerCase();
public java.lang.String toLowerCase(java.util.Locale);
public java.lang.String toString();
public java.lang.String toUpperCase();
public java.lang.String toUpperCase(java.util.Locale);
public java.lang.String trim();
}
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuffer {
public java.lang.String toString();
public char charAt(int);
public int capacity();
public int codePointAt(int);
public int codePointBefore(int);
public int indexOf(java.lang.String,int);
public int lastIndexOf(java.lang.String);
public int lastIndexOf(java.lang.String,int);
public int length();
public java.lang.String substring(int);
public java.lang.String substring(int,int);
}
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
# methods without side effects whose return values are not used.
-assumenosideeffects public class java.lang.StringBuilder {
public java.lang.String toString();
public char charAt(int);
public int capacity();
public int codePointAt(int);
public int codePointBefore(int);
public int indexOf(java.lang.String,int);
public int lastIndexOf(java.lang.String);
public int lastIndexOf(java.lang.String,int);
public int length();
public java.lang.String substring(int);
public java.lang.String substring(int,int);
}

View File

@@ -1,71 +1,77 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 9:59 PM
*/
public class BaritoneTweaker implements ITweaker {
List<String> args;
@Override
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>(args);
if (gameDir != null) addArg("gameDir", gameDir.getAbsolutePath());
if (assetsDir != null) addArg("assetsDir", assetsDir.getAbsolutePath());
if (profile != null) addArg("version", profile);
}
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
MixinBootstrap.init();
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
Mixins.addConfiguration("mixins.baritone.json");
}
@Override
public final String getLaunchTarget() {
return "net.minecraft.client.main.Main";
}
@Override
public final String[] getLaunchArguments() {
return this.args.toArray(new String[0]);
}
private void addArg(String label, String value) {
if (!args.contains("--" + label) && value != null) {
this.args.add("--" + label);
this.args.add(value);
}
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import net.minecraft.launchwrapper.ITweaker;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.spongepowered.asm.launch.MixinBootstrap;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.asm.mixin.Mixins;
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 9:59 PM
*/
public class BaritoneTweaker implements ITweaker {
List<String> args;
@Override
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>(args);
if (gameDir != null) {
addArg("gameDir", gameDir.getAbsolutePath());
}
if (assetsDir != null) {
addArg("assetsDir", assetsDir.getAbsolutePath());
}
if (profile != null) {
addArg("version", profile);
}
}
@Override
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
MixinBootstrap.init();
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
Mixins.addConfiguration("mixins.baritone.json");
}
@Override
public final String getLaunchTarget() {
return "net.minecraft.client.main.Main";
}
@Override
public final String[] getLaunchArguments() {
return this.args.toArray(new String[0]);
}
private void addArg(String label, String value) {
if (!args.contains("--" + label) && value != null) {
this.args.add("--" + label);
this.args.add(value);
}
}
}

View File

@@ -1,44 +1,44 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 10:09 PM
*/
public class BaritoneTweakerForge extends BaritoneTweaker {
@Override
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>();
}
@Override
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
super.injectIntoClassLoader(classLoader);
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import net.minecraft.launchwrapper.LaunchClassLoader;
import org.spongepowered.asm.mixin.MixinEnvironment;
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 10:09 PM
*/
public class BaritoneTweakerForge extends BaritoneTweaker {
@Override
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>();
}
@Override
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
super.injectIntoClassLoader(classLoader);
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
}
}

View File

@@ -1,34 +1,34 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 10:10 PM
*/
public class BaritoneTweakerOptifine extends BaritoneTweaker {
@Override
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>();
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch;
import java.io.File;
import java.util.ArrayList;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018 10:10 PM
*/
public class BaritoneTweakerOptifine extends BaritoneTweaker {
@Override
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
this.args = new ArrayList<>();
}
}

View File

@@ -0,0 +1,58 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IAnvilChunkLoader;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import java.io.File;
/**
* @author Brady
* @since 9/4/2018
*/
@Mixin(AnvilChunkLoader.class)
public class MixinAnvilChunkLoader implements IAnvilChunkLoader {
@Shadow @Final private File chunkSaveLocation;
@Override
public File getChunkSaveLocation() {
return this.chunkSaveLocation;
}
}

View File

@@ -29,7 +29,7 @@ import javax.annotation.Nonnull;
* @since 8/25/2018
*/
@Mixin(BlockPos.class)
public abstract class MixinBlockPos extends Vec3i {
public class MixinBlockPos extends Vec3i {
public MixinBlockPos(int xIn, int yIn, int zIn) {
super(xIn, yIn, zIn);

View File

@@ -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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IChunkProviderServer;
import net.minecraft.world.chunk.storage.IChunkLoader;
import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
/**
* @author Brady
* @since 9/4/2018
*/
@Mixin(ChunkProviderServer.class)
public class MixinChunkProviderServer implements IChunkProviderServer {
@Shadow @Final private IChunkLoader chunkLoader;
@Override
public IChunkLoader getChunkLoader() {
return this.chunkLoader;
}
}

View File

@@ -18,8 +18,8 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.RelativeMoveEvent;
import baritone.event.events.type.EventState;
import baritone.api.event.events.RelativeMoveEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;

View File

@@ -18,9 +18,9 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.ChatEvent;
import baritone.event.events.PlayerUpdateEvent;
import baritone.event.events.type.EventState;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.entity.EntityPlayerSP;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -42,8 +42,9 @@ public class MixinEntityPlayerSP {
private void sendChatMessage(String msg, CallbackInfo ci) {
ChatEvent event = new ChatEvent(msg);
Baritone.INSTANCE.getGameEventHandler().onSendChatMessage(event);
if (event.isCancelled())
if (event.isCancelled()) {
ci.cancel();
}
}
@Inject(

View File

@@ -18,7 +18,7 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.RenderEvent;
import baritone.api.event.events.RenderEvent;
import net.minecraft.client.renderer.EntityRenderer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;

View File

@@ -1,44 +1,44 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.settings.GameSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 8/1/2018 12:28 AM
*/
@Mixin(GameSettings.class)
public class MixinGameSettings {
@Redirect(
method = "isKeyDown",
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private static boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.settings.GameSettings;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 8/1/2018 12:28 AM
*/
@Mixin(GameSettings.class)
public class MixinGameSettings {
@Redirect(
method = "isKeyDown",
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private static boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}

View File

@@ -1,47 +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 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.gui.inventory.GuiContainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 7/31/2018 10:47 PM
*/
@Mixin(GuiContainer.class)
public class MixinGuiContainer {
@Redirect(
method = {
"mouseClicked",
"mouseReleased"
},
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.gui.inventory.GuiContainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 7/31/2018 10:47 PM
*/
@Mixin(GuiContainer.class)
public class MixinGuiContainer {
@Redirect(
method = {
"mouseClicked",
"mouseReleased"
},
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}

View File

@@ -1,48 +1,48 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 7/31/2018 10:38 PM
*/
@Mixin(GuiScreen.class)
public class MixinGuiScreen {
@Redirect(
method = {
"isCtrlKeyDown",
"isShiftKeyDown",
"isAltKeyDown"
},
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private static boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.gui.GuiScreen;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 7/31/2018 10:38 PM
*/
@Mixin(GuiScreen.class)
public class MixinGuiScreen {
@Redirect(
method = {
"isCtrlKeyDown",
"isShiftKeyDown",
"isAltKeyDown"
},
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private static boolean isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
}

View File

@@ -1,43 +1,44 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.settings.KeyBinding;
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.CallbackInfoReturnable;
/**
* @author Brady
* @since 7/31/2018 11:44 PM
*/
@Mixin(KeyBinding.class)
public abstract class MixinKeyBinding {
@Inject(
method = "isKeyDown",
at = @At("HEAD"),
cancellable = true
)
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this))
cir.setReturnValue(true);
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU 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.settings.KeyBinding;
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.CallbackInfoReturnable;
/**
* @author Brady
* @since 7/31/2018 11:44 PM
*/
@Mixin(KeyBinding.class)
public class MixinKeyBinding {
@Inject(
method = "isKeyDown",
at = @At("HEAD"),
cancellable = true
)
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) {
cir.setReturnValue(true);
}
}
}

View File

@@ -1,174 +1,176 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.behavior.impl.PathingBehavior;
import baritone.event.events.BlockInteractEvent;
import baritone.event.events.TickEvent;
import baritone.event.events.WorldEvent;
import baritone.event.events.type.EventState;
import baritone.utils.ExampleBaritoneControl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.lib.Opcodes;
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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* @author Brady
* @since 7/31/2018 10:51 PM
*/
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow private int leftClickCounter;
@Shadow public EntityPlayerSP player;
@Shadow public WorldClient world;
@Inject(
method = "init",
at = @At("RETURN")
)
private void init(CallbackInfo ci) {
Baritone.INSTANCE.init();
ExampleBaritoneControl.INSTANCE.initAndRegister();
}
@Inject(
method = "runTick",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
ordinal = 5,
shift = At.Shift.BY,
by = -3
)
)
private void runTick(CallbackInfo ci) {
Minecraft mc = (Minecraft) (Object) this;
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
EventState.PRE,
(mc.player != null && mc.world != null)
? TickEvent.Type.IN
: TickEvent.Type.OUT
));
}
@Redirect(
method = "runTickKeyboard",
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private boolean Keyboard$isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
@Inject(
method = "processKeyBinds",
at = @At("HEAD")
)
private void runTickKeyboard(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("HEAD")
)
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
// If we're unloading the world but one doesn't exist, ignore it
if (this.world == null && world == null)
return;
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
new WorldEvent(
world,
EventState.PRE
)
);
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("RETURN")
)
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
// If we're unloading the world but one doesn't exist, ignore it
if (this.world == null && world == null)
return;
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
new WorldEvent(
world,
EventState.POST
)
);
}
@Redirect(
method = "runTick",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
)
)
private boolean isAllowUserInput(GuiScreen screen) {
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
}
@Inject(
method = "clickMouse",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
}
@Inject(
method = "rightClickMouse",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
}
}
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.event.events.BlockInteractEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.impl.PathingBehavior;
import baritone.utils.ExampleBaritoneControl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.lib.Opcodes;
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 org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**
* @author Brady
* @since 7/31/2018 10:51 PM
*/
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow
private int leftClickCounter;
@Shadow
public EntityPlayerSP player;
@Shadow
public WorldClient world;
@Inject(
method = "init",
at = @At("RETURN")
)
private void init(CallbackInfo ci) {
Baritone.INSTANCE.init();
ExampleBaritoneControl.INSTANCE.initAndRegister();
}
@Inject(
method = "runTick",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
ordinal = 5,
shift = At.Shift.BY,
by = -3
)
)
private void runTick(CallbackInfo ci) {
Minecraft mc = (Minecraft) (Object) this;
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
EventState.PRE,
(mc.player != null && mc.world != null)
? TickEvent.Type.IN
: TickEvent.Type.OUT
));
}
@Redirect(
method = "runTickKeyboard",
at = @At(
value = "INVOKE",
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
remap = false
)
)
private boolean Keyboard$isKeyDown(int keyCode) {
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
}
@Inject(
method = "processKeyBinds",
at = @At("HEAD")
)
private void runTickKeyboard(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("HEAD")
)
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
// If we're unloading the world but one doesn't exist, ignore it
if (this.world == null && world == null) {
return;
}
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
new WorldEvent(
world,
EventState.PRE
)
);
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("RETURN")
)
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
// still fire event for both null, as that means we've just finished exiting a world
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
new WorldEvent(
world,
EventState.POST
)
);
}
@Redirect(
method = "runTick",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
)
)
private boolean isAllowUserInput(GuiScreen screen) {
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
}
@Inject(
method = "clickMouse",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
}
@Inject(
method = "rightClickMouse",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
),
locals = LocalCapture.CAPTURE_FAILHARD
)
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
}
}

View File

@@ -18,8 +18,8 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.ChunkEvent;
import baritone.event.events.type.EventState;
import baritone.api.event.events.ChunkEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.network.NetHandlerPlayClient;
import net.minecraft.network.play.server.SPacketChunkData;
import net.minecraft.network.play.server.SPacketCombatEvent;

View File

@@ -18,8 +18,8 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.PacketEvent;
import baritone.event.events.type.EventState;
import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.type.EventState;
import io.netty.channel.Channel;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.concurrent.Future;
@@ -37,17 +37,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
* @since 8/6/2018 9:30 PM
*/
@Mixin(NetworkManager.class)
public abstract class MixinNetworkManager {
public class MixinNetworkManager {
@Shadow private Channel channel;
@Shadow protected abstract void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet<?> p_channelRead0_2_) throws Exception;
@Shadow
private Channel channel;
@Inject(
method = "dispatchPacket",
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) {
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket));
}
@@ -55,7 +54,7 @@ public abstract class MixinNetworkManager {
method = "dispatchPacket",
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) {
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket));
}
@@ -75,7 +74,8 @@ public abstract class MixinNetworkManager {
at = @At("RETURN")
)
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
if (this.channel.isOpen())
if (this.channel.isOpen()) {
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.POST, packet));
}
}
}

View File

@@ -18,8 +18,8 @@
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.ChunkEvent;
import baritone.event.events.type.EventState;
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;

View File

@@ -1,28 +1,26 @@
{
"required": true,
"package": "baritone.launch.mixins",
"refmap": "mixins.baritone.refmap.json",
"compatibilityLevel": "JAVA_8",
"verbose": false,
"injectors": {
"maxShiftBy": 2
},
"client": [
"MixinBlockPos",
"MixinEntity",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
"MixinGameSettings",
"MixinGuiContainer",
"MixinGuiScreen",
"MixinInventoryPlayer",
"MixinKeyBinding",
"MixinMinecraft",
"MixinNetHandlerPlayClient",
"MixinNetworkManager",
"MixinWorldClient",
"accessor.IAnvilChunkLoader",
"accessor.IChunkProviderServer"
]
{
"required": true,
"package": "baritone.launch.mixins",
"refmap": "mixins.baritone.refmap.json",
"compatibilityLevel": "JAVA_8",
"verbose": false,
"injectors": {
"maxShiftBy": 2
},
"client": [
"MixinAnvilChunkLoader",
"MixinBlockPos",
"MixinChunkProviderServer",
"MixinEntity",
"MixinEntityPlayerSP",
"MixinEntityRenderer",
"MixinGameSettings",
"MixinGuiContainer",
"MixinGuiScreen",
"MixinKeyBinding",
"MixinMinecraft",
"MixinNetHandlerPlayClient",
"MixinNetworkManager",
"MixinWorldClient"
]
}

View File

@@ -17,13 +17,9 @@
package baritone;
import baritone.api.event.GameEventHandler;
import baritone.behavior.Behavior;
import baritone.behavior.impl.LookBehavior;
import baritone.behavior.impl.MemoryBehavior;
import baritone.behavior.impl.PathingBehavior;
import baritone.behavior.impl.LocationTrackingBehavior;
import baritone.event.GameEventHandler;
import baritone.map.Map;
import baritone.behavior.impl.*;
import baritone.utils.InputOverrideHandler;
import net.minecraft.client.Minecraft;
@@ -32,6 +28,7 @@ import java.io.IOException;
import java.nio.file.Files;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* @author Brady
@@ -55,11 +52,20 @@ public enum Baritone {
private List<Behavior> behaviors;
private File dir;
/**
* List of consumers to be called after Baritone has initialized
*/
private List<Consumer<Baritone>> onInitConsumers;
/**
* Whether or not Baritone is active
*/
private boolean active;
Baritone() {
this.onInitConsumers = new ArrayList<>();
}
public synchronized void init() {
if (initialized) {
return;
@@ -72,10 +78,10 @@ public enum Baritone {
registerBehavior(PathingBehavior.INSTANCE);
registerBehavior(LookBehavior.INSTANCE);
registerBehavior(MemoryBehavior.INSTANCE);
registerBehavior(Map.INSTANCE);
registerBehavior(LocationTrackingBehavior.INSTANCE);
registerBehavior(FollowBehavior.INSTANCE);
registerBehavior(MineBehavior.INSTANCE);
}
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
if (!Files.exists(dir.toPath())) {
try {
@@ -85,6 +91,8 @@ public enum Baritone {
this.active = true;
this.initialized = true;
this.onInitConsumers.forEach(consumer -> consumer.accept(this));
}
public final boolean isInitialized() {
@@ -123,4 +131,8 @@ public enum Baritone {
public final File getDir() {
return this.dir;
}
public final void registerInitListener(Consumer<Baritone> runnable) {
this.onInitConsumers.add(runnable);
}
}

View File

@@ -56,14 +56,20 @@ public class Settings {
*/
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
/**
* Allow Baritone to assume it can walk on still water just like any other block.
* This functionality is assumed to be provided by a separate library that might have imported Baritone.
*/
public Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
/**
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
*/
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(Arrays.asList(
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
Item.getItemFromBlock(Blocks.DIRT),
Item.getItemFromBlock(Blocks.COBBLESTONE),
Item.getItemFromBlock(Blocks.NETHERRACK)
));
)));
/**
* Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real
@@ -71,6 +77,24 @@ public class Settings {
*/
public Setting<Boolean> allowVines = new Setting<>(false);
/**
* Slab behavior is complicated, disable this for higher path reliability. Leave enabled if you have bottom slabs
* everywhere in your base.
*/
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
/**
* You know what it is
* <p>
* But it's very unreliable and falls off when cornering like all the time so.
*/
public Setting<Boolean> allowParkour = new Setting<>(false);
/**
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
*/
public Setting<Boolean> considerPotionEffects = new Setting<>(true);
/**
* This is the big A* setting.
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
@@ -116,8 +140,9 @@ public class Settings {
/**
* After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is
* entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified.
* See issue #114 for why this is disabled.
*/
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(true);
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(false);
/**
* Stop 5 movements before anything that made the path COST_INF.
@@ -178,7 +203,12 @@ public class Settings {
/**
* Pathing can never take longer than this
*/
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
public Setting<Number> pathTimeoutMS = new Setting<>(2000L);
/**
* Planning ahead while executing a segment can never take longer than this
*/
public Setting<Number> planAheadTimeoutMS = new Setting<>(4000L);
/**
* For debugging, consider nodes much much slower
@@ -211,6 +241,11 @@ public class Settings {
*/
public Setting<Boolean> chatControl = new Setting<>(true);
/**
* A second override over chatControl to force it on
*/
public Setting<Boolean> removePrefix = new Setting<>(false);
/**
* Render the path
*/
@@ -323,10 +358,10 @@ public class Settings {
}
@SuppressWarnings("unchecked")
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
public <T> List<Setting<T>> getAllValuesByType(Class<T> klass) {
List<Setting<T>> result = new ArrayList<>();
for (Setting<?> setting : allSettings) {
if (setting.klass.equals(klass)) {
if (setting.getValueClass().equals(klass)) {
result.add((Setting<T>) setting);
}
}

View File

@@ -32,13 +32,14 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event;
package baritone.api.event;
import baritone.Baritone;
import baritone.api.event.events.*;
import baritone.api.event.events.type.EventState;
import baritone.api.event.listener.IGameEventListener;
import baritone.chunk.WorldProvider;
import baritone.event.events.*;
import baritone.event.events.type.EventState;
import baritone.event.listener.IGameEventListener;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.InputOverrideHandler;
import baritone.utils.interfaces.Toggleable;
@@ -47,8 +48,6 @@ import net.minecraft.world.chunk.Chunk;
import org.lwjgl.input.Keyboard;
import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer;
/**
* @author Brady
@@ -56,16 +55,24 @@ import java.util.function.Consumer;
*/
public final class GameEventHandler implements IGameEventListener, Helper {
private final List<IGameEventListener> listeners = new ArrayList<>();
private final ArrayList<IGameEventListener> listeners = new ArrayList<>();
@Override
public final void onTick(TickEvent event) {
dispatch(listener -> listener.onTick(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onTick(event);
}
});
}
@Override
public final void onPlayerUpdate(PlayerUpdateEvent event) {
dispatch(listener -> listener.onPlayerUpdate(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onPlayerUpdate(event);
}
});
}
@Override
@@ -79,17 +86,26 @@ public final class GameEventHandler implements IGameEventListener, Helper {
if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
int keyCode = keyBinding.getKeyCode();
if (keyCode < Keyboard.KEYBOARD_SIZE)
if (keyCode < Keyboard.KEYBOARD_SIZE) {
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
}
}
}
dispatch(IGameEventListener::onProcessKeyBinds);
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onProcessKeyBinds();
}
});
}
@Override
public final void onSendChatMessage(ChatEvent event) {
dispatch(listener -> listener.onSendChatMessage(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onSendChatMessage(event);
}
});
}
@Override
@@ -115,81 +131,104 @@ public final class GameEventHandler implements IGameEventListener, Helper {
}
dispatch(listener -> listener.onChunkEvent(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onChunkEvent(event);
}
});
}
@Override
public final void onRenderPass(RenderEvent event) {
/*
WorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> {
drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks());
})));
*/
dispatch(listener -> listener.onRenderPass(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onRenderPass(event);
}
});
}
@Override
public final void onWorldEvent(WorldEvent event) {
WorldProvider cache = WorldProvider.INSTANCE;
BlockStateInterface.clearCachedChunk();
switch (event.getState()) {
case PRE:
cache.closeWorld();
break;
case POST:
cache.closeWorld();
if (event.getWorld() != null)
if (event.getWorld() != null) {
cache.initWorld(event.getWorld());
}
break;
}
dispatch(listener -> listener.onWorldEvent(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onWorldEvent(event);
}
});
}
@Override
public final void onSendPacket(PacketEvent event) {
dispatch(listener -> listener.onSendPacket(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onSendPacket(event);
}
});
}
@Override
public final void onReceivePacket(PacketEvent event) {
dispatch(listener -> listener.onReceivePacket(event));
}
@Override
public final void onQueryItemSlotForBlocks(ItemSlotEvent event) {
dispatch(listener -> listener.onQueryItemSlotForBlocks(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onReceivePacket(event);
}
});
}
@Override
public void onPlayerRelativeMove(RelativeMoveEvent event) {
dispatch(listener -> listener.onPlayerRelativeMove(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onPlayerRelativeMove(event);
}
});
}
@Override
public void onBlockInteract(BlockInteractEvent event) {
dispatch(listener -> listener.onBlockInteract(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onBlockInteract(event);
}
});
}
@Override
public void onPlayerDeath() {
dispatch(IGameEventListener::onPlayerDeath);
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onPlayerDeath();
}
});
}
@Override
public void onPathEvent(PathEvent event) {
dispatch(listener -> listener.onPathEvent(event));
listeners.forEach(l -> {
if (canDispatch(l)) {
l.onPathEvent(event);
}
});
}
public final void registerEventListener(IGameEventListener listener) {
this.listeners.add(listener);
}
private void dispatch(Consumer<IGameEventListener> dispatchFunction) {
this.listeners.stream().filter(this::canDispatch).forEach(dispatchFunction);
}
private boolean canDispatch(IGameEventListener listener) {
return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled();
}

View File

@@ -15,7 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import net.minecraft.util.math.BlockPos;

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.Cancellable;
import baritone.api.event.events.type.Cancellable;
/**
* @author Brady

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
/**
* @author Brady

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.listener.IGameEventListener;
import baritone.api.event.listener.IGameEventListener;
/**
* Called in some cases where a player's inventory has it's current slot queried.

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
import net.minecraft.network.Packet;
/**

View File

@@ -15,7 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
public enum PathEvent {
CALC_STARTED,

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
/**
* @author Brady

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
/**
* @author Brady

View File

@@ -15,7 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
/**
* @author Brady

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
public final class TickEvent {

View File

@@ -15,9 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events;
package baritone.api.event.events;
import baritone.event.events.type.EventState;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.multiplayer.WorldClient;
/**

View File

@@ -15,7 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events.type;
package baritone.api.event.events.type;
/**
* @author Brady

View File

@@ -15,7 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.events.type;
package baritone.api.event.events.type;
/**
* @author Brady

View File

@@ -32,9 +32,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.listener;
package baritone.api.event.listener;
import baritone.event.events.*;
import baritone.api.event.events.*;
/**
* An implementation of {@link IGameEventListener} that has all methods
@@ -74,9 +74,6 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override
default void onReceivePacket(PacketEvent event) {}
@Override
default void onQueryItemSlotForBlocks(ItemSlotEvent event) {}
@Override
default void onPlayerRelativeMove(RelativeMoveEvent event) {}

View File

@@ -32,11 +32,10 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.event.listener;
package baritone.api.event.listener;
import baritone.event.events.*;
import baritone.api.event.events.*;
import io.netty.util.concurrent.GenericFutureListener;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiGameOver;
@@ -44,7 +43,6 @@ import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.renderer.EntityRenderer;
import net.minecraft.client.settings.GameSettings;
import net.minecraft.entity.Entity;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
import net.minecraft.util.text.ITextComponent;
@@ -120,14 +118,6 @@ public interface IGameEventListener {
*/
void onReceivePacket(PacketEvent event);
/**
* Run when a query is made for a player's inventory current slot in the context of blocks
*
* @see InventoryPlayer#getDestroySpeed(IBlockState)
* @see InventoryPlayer#canHarvestBlock(IBlockState)
*/
void onQueryItemSlotForBlocks(ItemSlotEvent event);
/**
* Run once per game tick from before and after the player's moveRelative method is called
*

View File

@@ -17,7 +17,7 @@
package baritone.behavior;
import baritone.event.listener.AbstractGameEventListener;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.utils.Helper;
import baritone.utils.interfaces.Toggleable;
@@ -52,8 +52,9 @@ public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
@Override
public final boolean setEnabled(boolean enabled) {
boolean newState = getNewState(this.enabled, enabled);
if (newState == this.enabled)
if (newState == this.enabled) {
return this.enabled;
}
if (this.enabled = newState) {
onStart();

View File

@@ -0,0 +1,60 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.behavior.impl;
import baritone.api.event.events.TickEvent;
import baritone.behavior.Behavior;
import baritone.pathing.goals.GoalNear;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
/**
* Follow an entity
*
* @author leijurv
*/
public class FollowBehavior extends Behavior {
public static final FollowBehavior INSTANCE = new FollowBehavior();
private FollowBehavior() {
}
Entity following;
@Override
public void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
return;
}
if (following == null) {
return;
}
// lol this is trashy but it works
PathingBehavior.INSTANCE.setGoal(new GoalNear(new BlockPos(following), 3));
PathingBehavior.INSTANCE.path();
}
public void follow(Entity follow) {
this.following = follow;
}
public void cancel() {
PathingBehavior.INSTANCE.cancel();
follow(null);
}
}

View File

@@ -20,7 +20,7 @@ package baritone.behavior.impl;
import baritone.behavior.Behavior;
import baritone.chunk.Waypoint;
import baritone.chunk.WorldProvider;
import baritone.event.events.BlockInteractEvent;
import baritone.api.event.events.BlockInteractEvent;
import baritone.utils.BlockStateInterface;
import net.minecraft.block.BlockBed;

View File

@@ -19,10 +19,9 @@ package baritone.behavior.impl;
import baritone.Baritone;
import baritone.Settings;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RelativeMoveEvent;
import baritone.behavior.Behavior;
import baritone.event.events.PlayerUpdateEvent;
import baritone.event.events.RelativeMoveEvent;
import baritone.event.events.type.EventState;
import baritone.utils.Rotation;
public class LookBehavior extends Behavior {
@@ -58,8 +57,9 @@ public class LookBehavior extends Behavior {
@Override
public void onPlayerUpdate(PlayerUpdateEvent event) {
if (this.target == null)
if (this.target == null) {
return;
}
// Whether or not we're going to silently set our angles
boolean silent = Baritone.settings().antiCheatCompatibility.get();
@@ -103,8 +103,9 @@ public class LookBehavior extends Behavior {
player().rotationYaw = this.lastYaw;
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
if (!Baritone.settings().antiCheatCompatibility.get())
if (!Baritone.settings().antiCheatCompatibility.get()) {
this.target = null;
}
break;
}
}

View File

@@ -17,10 +17,7 @@
package baritone.behavior.impl;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.Rotation;
import baritone.utils.Utils;
import baritone.utils.*;
import net.minecraft.block.BlockFire;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.math.*;
@@ -70,9 +67,10 @@ public final class LookBehaviorUtils implements Helper {
return Optional.of(new Rotation(mc.player.rotationYaw, mc.player.rotationPitch + 0.0001f));
}
Optional<Rotation> possibleRotation = reachableCenter(pos);
System.out.println("center: " + possibleRotation);
if (possibleRotation.isPresent())
//System.out.println("center: " + possibleRotation);
if (possibleRotation.isPresent()) {
return possibleRotation;
}
IBlockState state = BlockStateInterface.get(pos);
AxisAlignedBB aabb = state.getBoundingBox(mc.world, pos);
@@ -81,24 +79,13 @@ public final class LookBehaviorUtils implements Helper {
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
possibleRotation = reachableOffset(pos, new Vec3d(pos).add(xDiff, yDiff, zDiff));
if (possibleRotation.isPresent())
if (possibleRotation.isPresent()) {
return possibleRotation;
}
}
return Optional.empty();
}
private static RayTraceResult rayTraceTowards(Rotation rotation) {
double blockReachDistance = mc.playerController.getBlockReachDistance();
Vec3d start = mc.player.getPositionEyes(1.0F);
Vec3d direction = calcVec3dFromRotation(rotation);
Vec3d end = start.add(
direction.x * blockReachDistance,
direction.y * blockReachDistance,
direction.z * blockReachDistance
);
return mc.world.rayTraceBlocks(start, end, false, false, true);
}
/**
* Checks if coordinate is reachable with the given block-face rotation offset
*
@@ -108,7 +95,7 @@ public final class LookBehaviorUtils implements Helper {
*/
protected static Optional<Rotation> reachableOffset(BlockPos pos, Vec3d offsetPos) {
Rotation rotation = Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), offsetPos);
RayTraceResult result = rayTraceTowards(rotation);
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
System.out.println(result);
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
if (result.getBlockPos().equals(pos)) {

View File

@@ -1,9 +1,9 @@
package baritone.behavior.impl;
import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.Behavior;
import baritone.event.events.PacketEvent;
import baritone.event.events.PlayerUpdateEvent;
import baritone.event.events.type.EventState;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketCloseWindow;
@@ -38,8 +38,9 @@ public class MemoryBehavior extends Behavior {
@Override
public void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE)
if (event.getState() == EventState.PRE) {
updateInventory();
}
}
@Override
@@ -59,7 +60,7 @@ public class MemoryBehavior extends Behavior {
TileEntityLockable lockable = (TileEntityLockable) tileEntity;
int size = lockable.getSizeInventory();
this.futureInventories.add(new FutureInventory(System.currentTimeMillis(), size, lockable.getGuiID(), tileEntity.getPos()));
this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos()));
}
}
@@ -81,18 +82,18 @@ public class MemoryBehavior extends Behavior {
SPacketOpenWindow packet = event.cast();
// Remove any entries that were created over a second ago, this should make up for INSANE latency
this.futureInventories.removeIf(i -> System.currentTimeMillis() - i.time > 1000);
this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
this.futureInventories.stream()
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
.findFirst().ifPresent(matched -> {
// Remove the future inventory
this.futureInventories.remove(matched);
// Remove the future inventory
this.futureInventories.remove(matched);
// Setup the remembered inventory
RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
inventory.windowId = packet.getWindowId();
inventory.size = packet.getSlotCount();
// Setup the remembered inventory
RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
inventory.windowId = packet.getWindowId();
inventory.size = packet.getSlotCount();
});
}

View File

@@ -0,0 +1,111 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.behavior.impl;
import baritone.api.event.events.PathEvent;
import baritone.behavior.Behavior;
import baritone.chunk.CachedChunk;
import baritone.chunk.ChunkPacker;
import baritone.chunk.WorldProvider;
import baritone.chunk.WorldScanner;
import baritone.pathing.goals.Goal;
import baritone.pathing.goals.GoalComposite;
import baritone.pathing.goals.GoalTwoBlocks;
import baritone.utils.BlockStateInterface;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;
/**
* Mine blocks of a certain type
*
* @author leijurv
*/
public class MineBehavior extends Behavior {
public static final MineBehavior INSTANCE = new MineBehavior();
private MineBehavior() {
}
List<String> mining;
@Override
public void onPathEvent(PathEvent event) {
updateGoal();
}
public void updateGoal() {
if (mining == null) {
return;
}
List<BlockPos> locs = scanFor(mining, 64);
if (locs.isEmpty()) {
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
cancel();
return;
}
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new)));
PathingBehavior.INSTANCE.path();
}
public static List<BlockPos> scanFor(List<String> mining, int max) {
List<BlockPos> locs = new ArrayList<>();
List<String> uninteresting = new ArrayList<>();
//long b = System.currentTimeMillis();
for (String m : mining) {
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(ChunkPacker.stringToBlock(m))) {
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(m, 1, 1));
} else {
uninteresting.add(m);
}
}
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
if (!uninteresting.isEmpty()) {
//long before = System.currentTimeMillis();
locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max));
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
}
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
// remove any that are within loaded chunks that aren't actually what we want
locs.removeAll(locs.stream()
.filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk))
.filter(pos -> !mining.contains(ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).toLowerCase()))
.collect(Collectors.toList()));
if (locs.size() > max) {
locs = locs.subList(0, max);
}
return locs;
}
public void mine(String... mining) {
this.mining = mining == null || mining.length == 0 ? null : new ArrayList<>(Arrays.asList(mining));
updateGoal();
}
public void cancel() {
PathingBehavior.INSTANCE.cancel();
mine();
}
}

View File

@@ -18,17 +18,16 @@
package baritone.behavior.impl;
import baritone.Baritone;
import baritone.api.event.events.PathEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.events.TickEvent;
import baritone.behavior.Behavior;
import baritone.event.events.PathEvent;
import baritone.event.events.PlayerUpdateEvent;
import baritone.event.events.RenderEvent;
import baritone.event.events.TickEvent;
import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.calc.IPathFinder;
import baritone.pathing.goals.Goal;
import baritone.pathing.goals.GoalBlock;
import baritone.pathing.goals.GoalXZ;
import baritone.pathing.goals.*;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.IPath;
import baritone.pathing.path.PathExecutor;
import baritone.utils.BlockStateInterface;
@@ -196,27 +195,39 @@ public class PathingBehavior extends Behavior {
current = null;
next = null;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel);
}
public void path() {
/**
* 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 path() {
if (goal == null) {
return false;
}
if (goal.isInGoal(playerFeet())) {
return false;
}
synchronized (pathPlanLock) {
if (current != null) {
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
return;
return false;
}
synchronized (pathCalcLock) {
if (isPathCalcInProgress) {
return;
return false;
}
dispatchPathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true, Optional.empty());
return true;
}
}
}
public BlockPos pathStart() {
BlockPos feet = playerFeet();
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR)) {
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) {
return feet.down();
}
return feet;
@@ -293,18 +304,37 @@ public class PathingBehavior extends Behavior {
displayChatMessageRaw("no goal");
return Optional.empty();
}
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof GoalBlock) {
BlockPos pos = ((GoalBlock) goal).getGoalPos();
if (world().getChunk(pos) instanceof EmptyChunk) {
displayChatMessageRaw("Simplifying GoalBlock to GoalXZ due to distance");
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
BlockPos pos = null;
if (goal instanceof GoalBlock) {
pos = ((GoalBlock) goal).getGoalPos();
}
if (goal instanceof GoalTwoBlocks) {
pos = ((GoalTwoBlocks) goal).getGoalPos();
}
if (goal instanceof GoalNear) {
pos = ((GoalNear) goal).getGoalPos();
}
if (goal instanceof GoalGetToBlock) {
pos = ((GoalGetToBlock) goal).getGoalPos();
}
// TODO simplify each individual goal in a GoalComposite
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
displayChatMessageRaw("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
goal = new GoalXZ(pos.getX(), pos.getZ());
}
}
long timeout;
if (current == null) {
timeout = Baritone.settings().pathTimeoutMS.<Long>get();
} else {
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
}
try {
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
return pf.calculate();
return pf.calculate(timeout);
} catch (Exception e) {
displayChatMessageRaw("Exception: " + e);
displayChatMessageRaw("Pathing exception: " + e);
e.printStackTrace();
return Optional.empty();
}
@@ -359,8 +389,9 @@ public class PathingBehavior extends Behavior {
});
long end = System.nanoTime();
//System.out.println((end - split) + " " + (split - start));
// if (end - start > 0)
// if (end - start > 0) {
// System.out.println("Frame took " + (split - start) + " " + (end - split));
//}
}
}

View File

@@ -121,7 +121,10 @@ public final class CachedChunk implements IBlockTypeAccess {
if (heightMap[internalPos] == y) {
// we have this exact block, it's a surface block
IBlockState state = ChunkPacker.stringToBlock(overview[internalPos]).getDefaultState();
//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())) {
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));
}*/
return state;
}
PathingBlockType type = getType(x, y, z);
@@ -139,7 +142,8 @@ public final class CachedChunk implements IBlockTypeAccess {
int index = z << 4 | x;
heightMap[index] = 0;
for (int y = 256; y >= 0; y--) {
if (getType(x, y, z) != PathingBlockType.AIR) {
int i = getPositionIndex(x, y, z);
if (data.get(i) || data.get(i + 1)) {
heightMap[index] = y;
break;
}
@@ -183,7 +187,7 @@ public final class CachedChunk implements IBlockTypeAccess {
* @return The bit index
*/
public static int getPositionIndex(int x, int y, int z) {
return (x + (z << 4) + (y << 8)) * 2;
return (x << 1) | (z << 5) | (y << 9);
}
/**
@@ -195,7 +199,8 @@ public final class CachedChunk implements IBlockTypeAccess {
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
*/
private static void validateSize(BitSet data) {
if (data.size() > SIZE)
if (data.size() > SIZE) {
throw new IllegalArgumentException("BitSet of invalid length provided");
}
}
}

View File

@@ -77,6 +77,10 @@ public final class CachedRegion implements IBlockTypeAccess {
return null;
}
public final boolean isCached(int x, int z) {
return chunks[x >> 4][z >> 4] != null;
}
public final LinkedList<BlockPos> getLocationsOf(String block) {
LinkedList<BlockPos> res = new LinkedList<>();
for (int chunkX = 0; chunkX < 32; chunkX++) {
@@ -108,17 +112,19 @@ public final class CachedRegion implements IBlockTypeAccess {
}
try {
Path path = Paths.get(directory);
if (!Files.exists(path))
if (!Files.exists(path)) {
Files.createDirectories(path);
}
System.out.println("Saving region " + x + "," + z + " to disk " + path);
Path regionFile = getRegionFile(path, this.x, this.z);
if (!Files.exists(regionFile))
if (!Files.exists(regionFile)) {
Files.createFile(regionFile);
}
try (
FileOutputStream fileOut = new FileOutputStream(regionFile.toFile());
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut);
DataOutputStream out = new DataOutputStream(gzipOut);
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut, 16384);
DataOutputStream out = new DataOutputStream(gzipOut)
) {
out.writeInt(CACHED_REGION_MAGIC);
for (int z = 0; z < 32; z++) {
@@ -171,20 +177,22 @@ public final class CachedRegion implements IBlockTypeAccess {
public synchronized void load(String directory) {
try {
Path path = Paths.get(directory);
if (!Files.exists(path))
if (!Files.exists(path)) {
Files.createDirectories(path);
}
Path regionFile = getRegionFile(path, this.x, this.z);
if (!Files.exists(regionFile))
if (!Files.exists(regionFile)) {
return;
}
System.out.println("Loading region " + x + "," + z + " from disk " + path);
long start = System.currentTimeMillis();
long start = System.nanoTime() / 1000000L;
try (
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
GZIPInputStream gzipIn = new GZIPInputStream(fileIn);
DataInputStream in = new DataInputStream(gzipIn);
GZIPInputStream gzipIn = new GZIPInputStream(fileIn, 32768);
DataInputStream in = new DataInputStream(gzipIn)
) {
int magic = in.readInt();
if (magic != CACHED_REGION_MAGIC) {
@@ -262,7 +270,7 @@ public final class CachedRegion implements IBlockTypeAccess {
}
}
hasUnsavedChanges = false;
long end = System.currentTimeMillis();
long end = System.nanoTime() / 1000000L;
System.out.println("Loaded region successfully in " + (end - start) + "ms");
} catch (IOException ex) {
ex.printStackTrace();

View File

@@ -28,9 +28,10 @@ import net.minecraft.world.chunk.Chunk;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.LinkedBlockingQueue;
import java.util.function.Consumer;
/**
* @author Brady
@@ -59,28 +60,28 @@ public final class CachedWorld implements IBlockTypeAccess {
if (!Files.exists(directory)) {
try {
Files.createDirectories(directory);
} catch (IOException ignored) {}
} catch (IOException ignored) {
}
}
this.directory = directory.toString();
System.out.println("Cached world directory: " + directory);
// Insert an invalid region element
cachedRegions.put(0, null);
new PackerThread().start();
new Thread() {
public void run() {
try {
while (true) {
// since a region only saves if it's been modified since its last save
// saving every 10 minutes means that once it's time to exit
// we'll only have a couple regions to save
save();
Thread.sleep(600000);
}
} catch (InterruptedException e) {
e.printStackTrace();
new Thread(() -> {
try {
Thread.sleep(30000);
while (true) {
// since a region only saves if it's been modified since its last save
// saving every 10 minutes means that once it's time to exit
// we'll only have a couple regions to save
save();
Thread.sleep(600000);
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}.start();
}).start();
}
public final void queueForPacking(Chunk chunk) {
@@ -101,6 +102,17 @@ public final class CachedWorld implements IBlockTypeAccess {
return region.getBlock(x & 511, y, z & 511);
}
public final boolean isCached(BlockPos pos) {
int x = pos.getX();
int z = pos.getZ();
CachedRegion region = getRegion(x >> 9, z >> 9);
if (region == null) {
return false;
}
return region.isCached(x & 511, z & 511);
}
public final LinkedList<BlockPos> getLocationsOf(String block, int minimum, int maxRegionDistanceSq) {
LinkedList<BlockPos> res = new LinkedList<>();
int playerRegionX = playerFeet().getX() >> 9;
@@ -117,9 +129,11 @@ public final class CachedWorld implements IBlockTypeAccess {
int regionX = xoff + playerRegionX;
int regionZ = zoff + playerRegionZ;
CachedRegion region = getOrCreateRegion(regionX, regionZ);
if (region != null)
for (BlockPos pos : region.getLocationsOf(block))
if (region != null) {
for (BlockPos pos : region.getLocationsOf(block)) {
res.add(pos);
}
}
}
}
if (res.size() >= minimum) {
@@ -140,22 +154,28 @@ public final class CachedWorld implements IBlockTypeAccess {
System.out.println("Not saving to disk; chunk caching is disabled.");
return;
}
long start = System.currentTimeMillis();
this.cachedRegions.values().forEach(region -> {
if (region != null)
long start = System.nanoTime() / 1000000L;
allRegions().parallelStream().forEach(region -> {
if (region != null) {
region.save(this.directory);
}
});
long now = System.currentTimeMillis();
long now = System.nanoTime() / 1000000L;
System.out.println("World save took " + (now - start) + "ms");
}
private synchronized List<CachedRegion> allRegions() {
return new ArrayList<>(this.cachedRegions.values());
}
public final void reloadAllFromDisk() {
long start = System.currentTimeMillis();
this.cachedRegions.values().forEach(region -> {
if (region != null)
long start = System.nanoTime() / 1000000L;
allRegions().forEach(region -> {
if (region != null) {
region.load(this.directory);
}
});
long now = System.currentTimeMillis();
long now = System.nanoTime() / 1000000L;
System.out.println("World load took " + (now - start) + "ms");
}
@@ -166,7 +186,7 @@ public final class CachedWorld implements IBlockTypeAccess {
* @param regionZ The region Z coordinate
* @return The region located at the specified coordinates
*/
public final CachedRegion getRegion(int regionX, int regionZ) {
public final synchronized CachedRegion getRegion(int regionX, int regionZ) {
return cachedRegions.get(getRegionID(regionX, regionZ));
}
@@ -186,13 +206,6 @@ public final class CachedWorld implements IBlockTypeAccess {
});
}
public void forEachRegion(Consumer<CachedRegion> consumer) {
this.cachedRegions.forEach((id, r) -> {
if (r != null)
consumer.accept(r);
});
}
/**
* Returns the region ID based on the region coordinates. 0 will be
* returned if the specified region coordinates are out of bounds.
@@ -202,8 +215,9 @@ public final class CachedWorld implements IBlockTypeAccess {
* @return The region ID
*/
private long getRegionID(int regionX, int regionZ) {
if (!isRegionInWorld(regionX, regionZ))
if (!isRegionInWorld(regionX, regionZ)) {
return 0;
}
return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32;
}

View File

@@ -18,18 +18,19 @@
package baritone.chunk;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.pathing.PathingBlockType;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.block.BlockDoublePlant;
import net.minecraft.block.BlockFlower;
import net.minecraft.block.BlockTallGrass;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.*;
@@ -41,46 +42,86 @@ public final class ChunkPacker implements Helper {
private ChunkPacker() {}
private static BitSet originalPacker(Chunk chunk) {
BitSet bitSet = new BitSet(CachedChunk.SIZE);
for (int y = 0; y < 256; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int index = CachedChunk.getPositionIndex(x, y, z);
IBlockState state = chunk.getBlockState(x, y, z);
boolean[] bits = getPathingBlockType(state).getBits();
bitSet.set(index, bits[0]);
bitSet.set(index + 1, bits[1]);
}
}
}
return bitSet;
}
public static CachedChunk pack(Chunk chunk) {
long start = System.currentTimeMillis();
long start = System.nanoTime() / 1000000L;
Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
BitSet bitSet = new BitSet(CachedChunk.SIZE);
try {
for (int y = 0; y < 256; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int index = CachedChunk.getPositionIndex(x, y, z);
Block block = chunk.getBlockState(x, y, z).getBlock();
boolean[] bits = getPathingBlockType(block).getBits();
bitSet.set(index, bits[0]);
bitSet.set(index + 1, bits[1]);
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
String name = blockToString(block);
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) {
// 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
// the first 4 extended blocks storages will be full
// and the remaining 12 will be null
// since the index into the bitset is calculated from the x y and z
// and doesn't function as an append, we can entirely skip the scanning
// since a bitset is initialized to all zero, and air is saved as zeros
continue;
}
BlockStateContainer bsc = extendedblockstorage.getData();
int yReal = y0 << 4;
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y1 = 0; y1 < 16; y1++) {
int y = y1 | yReal;
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
int index = CachedChunk.getPositionIndex(x, y, z);
IBlockState state = bsc.get(x, y1, z);
boolean[] bits = getPathingBlockType(state).getBits();
bitSet.set(index, bits[0]);
bitSet.set(index + 1, bits[1]);
Block block = state.getBlock();
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
String name = blockToString(block);
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
}
}
}
}
}
/*if (!bitSet.equals(originalPacker(chunk))) {
throw new IllegalStateException();
}*/
} catch (Exception e) {
e.printStackTrace();
}
//System.out.println("Packed special blocks: " + specialBlocks);
long end = System.currentTimeMillis();
long end = System.nanoTime() / 1000000L;
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
String[] blockNames = new String[256];
for (int z = 0; z < 16; z++) {
outerLoop:
for (int x = 0; x < 16; x++) {
int height = chunk.getHeightValue(x, z);
IBlockState blockState = chunk.getBlockState(x, height, z);
for (int y = height; y > 0; y--) {
blockState = chunk.getBlockState(x, y, z);
if (getPathingBlockType(blockState.getBlock()) != PathingBlockType.AIR) {
break;
for (int y = 255; y >= 0; y--) {
int index = CachedChunk.getPositionIndex(x, y, z);
if (bitSet.get(index) || bitSet.get(index + 1)) {
String name = blockToString(chunk.getBlockState(x, y, z).getBlock());
blockNames[z << 4 | x] = name;
continue outerLoop;
}
}
String name = blockToString(blockState.getBlock());
blockNames[z << 4 | x] = name;
blockNames[z << 4 | x] = "air";
}
}
CachedChunk cached = new CachedChunk(chunk.x, chunk.z, bitSet, blockNames, specialBlocks);
@@ -104,19 +145,21 @@ public final class ChunkPacker implements Helper {
return Block.getBlockFromName(name);
}
private static PathingBlockType getPathingBlockType(Block block) {
if (BlockStateInterface.isWater(block)) {
private static PathingBlockType getPathingBlockType(IBlockState state) {
Block block = state.getBlock();
if (block.equals(Blocks.WATER)) {
// only water source blocks are plausibly usable, flowing water should be avoid
return PathingBlockType.WATER;
}
if (MovementHelper.avoidWalkingInto(block)) {
if (MovementHelper.avoidWalkingInto(block) || block.equals(Blocks.FLOWING_WATER) || MovementHelper.isBottomSlab(state)) {
return PathingBlockType.AVOID;
}
// We used to do an AABB check here
// 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
// this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors
if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant) {
if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) {
return PathingBlockType.AIR;
}

View File

@@ -17,12 +17,11 @@
package baritone.chunk;
import com.google.common.collect.ImmutableList;
import net.minecraft.util.math.BlockPos;
import org.apache.commons.lang3.ArrayUtils;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
import java.util.*;
/**
* A single waypoint
@@ -30,6 +29,7 @@ import java.util.Map;
* @author leijurv
*/
public class Waypoint {
public final String name;
public final Tag tag;
private final long creationTimestamp;
@@ -72,19 +72,21 @@ public class Waypoint {
}
public enum Tag {
HOME, DEATH, BED, USER;
HOME("home", "base"),
DEATH("death"),
BED("bed", "spawn"),
USER();
}
private static final List<Tag> TAG_LIST = ImmutableList.<Tag>builder().add(Tag.values()).build();
public static final Map<String, Tag> TAG_MAP;
private final String[] names;
static {
HashMap<String, Tag> map = new HashMap<>();
map.put("home", Tag.HOME);
map.put("base", Tag.HOME);
map.put("bed", Tag.BED);
map.put("spawn", Tag.BED);
map.put("death", Tag.DEATH);
TAG_MAP = Collections.unmodifiableMap(map);
Tag(String... names) {
this.names = names;
}
public static Tag fromString(String name) {
return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null);
}
}
}

View File

@@ -61,8 +61,9 @@ public class Waypoints {
waypoints.put(tag, new HashSet<>());
Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4");
if (!Files.exists(fileName))
if (!Files.exists(fileName)) {
return;
}
try (
FileInputStream fileIn = new FileInputStream(fileName.toFile());

View File

@@ -36,10 +36,6 @@ public class WorldData {
this.waypoints = new Waypoints(directory.resolve("waypoints"));
}
public Path getMapDirectory() {
return directory.resolve("map");
}
void onClose() {
new Thread() {
public void run() {

View File

@@ -18,9 +18,9 @@
package baritone.chunk;
import baritone.Baritone;
import baritone.launch.mixins.accessor.IAnvilChunkLoader;
import baritone.launch.mixins.accessor.IChunkProviderServer;
import baritone.utils.Helper;
import baritone.utils.accessor.IAnvilChunkLoader;
import baritone.utils.accessor.IChunkProviderServer;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.world.WorldServer;
@@ -69,7 +69,7 @@ public enum WorldProvider implements Helper {
directory = new File(directory, "baritone");
readme = directory;
} else {
//remote
directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP);
@@ -102,7 +102,8 @@ public enum WorldProvider implements Helper {
}
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
if (this.currentWorld != null)
if (this.currentWorld != null) {
currentWorldConsumer.accept(this.currentWorld);
}
}
}

View File

@@ -0,0 +1,100 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.chunk;
import baritone.utils.Helper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.LinkedList;
import java.util.List;
import java.util.stream.Collectors;
public enum WorldScanner implements Helper {
INSTANCE;
public List<BlockPos> scanLoadedChunks(List<String> blockTypes, int max) {
List<Block> asBlocks = blockTypes.stream().map(ChunkPacker::stringToBlock).collect(Collectors.toList());
if (asBlocks.contains(null)) {
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blockTypes.toString());
}
LinkedList<BlockPos> res = new LinkedList<>();
if (asBlocks.isEmpty()) {
return res;
}
ChunkProviderClient chunkProvider = world().getChunkProvider();
int playerChunkX = playerFeet().getX() >> 4;
int playerChunkZ = playerFeet().getZ() >> 4;
int searchRadiusSq = 0;
while (true) {
boolean allUnloaded = true;
for (int xoff = -searchRadiusSq; xoff <= searchRadiusSq; xoff++) {
for (int zoff = -searchRadiusSq; zoff <= searchRadiusSq; zoff++) {
int distance = xoff * xoff + zoff * zoff;
if (distance != searchRadiusSq) {
continue;
}
int chunkX = xoff + playerChunkX;
int chunkZ = zoff + playerChunkZ;
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
if (chunk == null) {
continue;
}
allUnloaded = false;
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
chunkX = chunkX << 4;
chunkZ = chunkZ << 4;
for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) {
continue;
}
int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (asBlocks.contains(state.getBlock())) {
res.add(new BlockPos(chunkX | x, yReal | y, chunkZ | z));
}
}
}
}
}
}
}
if (allUnloaded) {
return res;
}
if (res.size() >= max && searchRadiusSq > 26) {
return res;
}
searchRadiusSq++;
}
}
}

View File

@@ -1,62 +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 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.Baritone;
import baritone.event.events.ItemSlotEvent;
import net.minecraft.entity.player.InventoryPlayer;
import org.spongepowered.asm.lib.Opcodes;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Redirect;
/**
* @author Brady
* @since 8/20/2018
*/
@Mixin(InventoryPlayer.class)
public class MixinInventoryPlayer {
@Redirect(
method = "getDestroySpeed",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
)
)
private int getDestroySpeed$getCurrentItem(InventoryPlayer inventory) {
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
return event.getSlot();
}
@Redirect(
method = "canHarvestBlock",
at = @At(
value = "FIELD",
opcode = Opcodes.GETFIELD,
target = "net/minecraft/entity/player/InventoryPlayer.currentItem:I"
)
)
private int canHarvestBlock$getCurrentItem(InventoryPlayer inventory) {
ItemSlotEvent event = new ItemSlotEvent(inventory.currentItem);
Baritone.INSTANCE.getGameEventHandler().onQueryItemSlotForBlocks(event);
return event.getSlot();
}
}

View File

@@ -1,68 +0,0 @@
package baritone.map;
import baritone.behavior.Behavior;
import baritone.chunk.WorldProvider;
import baritone.event.events.ChunkEvent;
import net.minecraft.util.math.ChunkPos;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class Map extends Behavior {
public static final Map INSTANCE = new Map();
private BufferedImage fullImage = new BufferedImage(4080, 4080, BufferedImage.TYPE_INT_RGB);
private Map() {
try {
fullImage = ImageIO.read(getImagePath().toFile());
} catch (IOException ignored) { }
}
@Override
public void onChunkEvent(ChunkEvent event) {
if (event.getType() != ChunkEvent.Type.POPULATE)
return;
MapChunk map = new MapChunk(world().getChunk(event.getX(), event.getZ()));
stitchMapChunk(map);
if (world().getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ() - 1)) {
stitchMapChunk(new MapChunk(world().getChunk(event.getX(), event.getZ() - 1)));
}
}
private void stitchMapChunk(MapChunk map) {
ChunkPos pos = map.getChunk().getPos();
int startX = pos.x * 16 + (fullImage.getWidth() / 2) - 8;
int startZ = pos.z * 16 + (fullImage.getHeight() / 2) - 8;
Graphics graphics = fullImage.getGraphics();
graphics.drawImage(map.generateOverview(), startX, startZ, null);
}
public void writeImage() {
Path image = getImagePath();
if (!Files.exists(image.getParent())) {
try {
Files.createDirectory(image.getParent());
} catch (IOException e) {
e.printStackTrace();
}
}
try {
ImageIO.write(fullImage, "PNG", image.toFile());
} catch (IOException e) {
e.printStackTrace();
}
}
public Path getImagePath() {
return WorldProvider.INSTANCE.getCurrentWorld().getMapDirectory().resolve("full-map.png");
}
}

View File

@@ -1,135 +0,0 @@
package baritone.map;
import baritone.chunk.WorldProvider;
import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.material.MapColor;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.Chunk;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
public class MapChunk {
private Chunk chunk;
public MapChunk(Chunk chunk) {
this.chunk = chunk;
}
public BufferedImage generateOverview() {
BufferedImage bufferedImage = new BufferedImage(16, 16, BufferedImage.TYPE_INT_RGB);
for (int x = 0; x < 16; x++) {
for (int z = 0; z < 16; z++) {
bufferedImage.setRGB(x, z, getColor(x, z));
}
}
return bufferedImage;
}
public void writeImage() {
Path image = getImagePath();
if (!Files.exists(image.getParent())) {
try {
Files.createDirectory(image.getParent());
} catch (IOException e) {
e.printStackTrace();
}
}
BufferedImage bufferedImage = generateOverview();
try {
ImageIO.write(bufferedImage, "PNG", image.toFile());
} catch (IOException e) {
e.printStackTrace();
}
}
public Path getImagePath() {
return WorldProvider.INSTANCE.getCurrentWorld().getMapDirectory().resolve("chunk" + chunk.x + "-" + chunk.z + ".png");
}
public Chunk getChunk() {
return chunk;
}
/**
* getColor is a re-implementation of the Minecraft ItemMap's
* surface mapping system. This is significantly less convoluted
* than the poorly de-obfuscated code.
* <p>
* We perform shading of the given coordinate relative to the
* position one to the north of the coordinate, as can be seen
* in Minecraft's maps.
*
* @param x relative x coordinate to the start of the chunk
* @param z relative z coord.
* @return Integer RGB value with contextual shading
*/
private int getColor(int x, int z) {
int chunkX = chunk.getPos().getXStart() + x;
int chunkZ = chunk.getPos().getZStart() + z;
BlockPos blockPos = new BetterBlockPos(chunkX, chunk.getHeight(new BetterBlockPos(chunkX, 0, chunkZ)), chunkZ);
IBlockState blockState = BlockStateInterface.get(blockPos);
MapColor mapColor = blockState.getMapColor(chunk.getWorld(), blockPos);
// The chunk heightMap returns the first non-full block above the surface, including bushes.
// We have to check this and shift our block down by one if the color is "air" (as in, there's no real block there)
if (mapColor == MapColor.AIR) {
blockPos = blockPos.down();
blockState = BlockStateInterface.get(blockPos);
mapColor = blockState.getMapColor(chunk.getWorld(), blockPos);
}
Color color = new Color(mapColor.colorValue);
int red = color.getRed();
int green = color.getGreen();
int blue = color.getBlue();
// Now we get the proper block for the position one to the north.
BlockPos offset = blockPos.offset(EnumFacing.NORTH);
// If we are at the north border of the chunk, we need to get the next chunk
// to the north to ensure that we shade properly.
offset = chunk.getWorld().getChunk(offset).isLoaded() ? offset : offset.south();
// We adjust the height of the offset to the proper height value if the shading chunk is
// loaded, or the same as our target block if the shading chunk is not.
offset = new BlockPos(offset.getX(), chunk.getWorld().getChunk(offset).getHeight(offset), offset.getZ());
// And once again, check to make sure we have an actual colored block an not "air"
if (BlockStateInterface.get(offset).getMapColor(chunk.getWorld(), offset) == MapColor.AIR)
offset = offset.down();
float heightCoef;
// Check if we need to handle water depth shading
if (blockState.getMaterial().isLiquid()) {
heightCoef = 1.0f;
int i = 1;
// Iterate over the 4 layers of water shading and color proportional to the depth
for (; i < 5; i++) {
if (BlockStateInterface.get(blockPos.down(i * 2)).getMaterial().isLiquid()) {
heightCoef -= 0.075f;
} else {
break;
}
}
// Add checkerboard shading to the odd layers to give texture
if (i % 2 == 0)
heightCoef += 0.075f * (((x + z) % 2 == 0) ? -1 : 1);
} else {
// We start the heightCoef at 0.8 to darken the colors similar to vanilla Minecraft's.
heightCoef = 0.8f + (Math.signum(blockPos.getY() - offset.getY()) * 0.2f);
}
red = Math.min(255, (int) (red * heightCoef));
green = Math.min(255, (int) (green * heightCoef));
blue = Math.min(255, (int) (blue * heightCoef));
return new Color(red, green, blue).getRGB();
}
}

View File

@@ -18,9 +18,9 @@
package baritone.pathing.calc;
import baritone.Baritone;
import baritone.chunk.CachedWorld;
import baritone.chunk.WorldProvider;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.calc.openset.IOpenSet;
import baritone.pathing.goals.Goal;
import baritone.pathing.movement.ActionCosts;
import baritone.pathing.movement.CalculationContext;
@@ -28,12 +28,12 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.movements.*;
import baritone.pathing.path.IPath;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.Collection;
import java.util.HashSet;
@@ -47,19 +47,19 @@ import java.util.Random;
*/
public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
private final Optional<HashSet<BetterBlockPos>> favoredPositions;
private final Optional<HashSet<BlockPos>> favoredPositions;
public AStarPathFinder(BlockPos start, Goal goal, Optional<Collection<BetterBlockPos>> favoredPositions) {
public AStarPathFinder(BlockPos start, Goal goal, Optional<Collection<BlockPos>> favoredPositions) {
super(start, goal);
this.favoredPositions = favoredPositions.map(HashSet::new); // <-- okay this is epic
}
@Override
protected Optional<IPath> calculate0() {
protected Optional<IPath> calculate0(long timeout) {
startNode = getNodeAtPosition(start);
startNode.cost = 0;
startNode.combinedCost = startNode.estimatedCostToGoal;
IOpenSet openSet = new BinaryHeapOpenSet();
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode);
startNode.isOpen = true;
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
@@ -68,19 +68,26 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
bestHeuristicSoFar[i] = Double.MAX_VALUE;
}
CalculationContext calcContext = new CalculationContext();
HashSet<BetterBlockPos> favored = favoredPositions.orElse(null);
HashSet<BlockPos> favored = favoredPositions.orElse(null);
currentlyRunning = this;
long startTime = System.currentTimeMillis();
CachedWorld cachedWorld = Optional.ofNullable(WorldProvider.INSTANCE.getCurrentWorld()).map(w -> w.cache).orElse(null);
ChunkProviderClient chunkProvider = Minecraft.getMinecraft().world.getChunkProvider();
BlockStateInterface.clearCachedChunk();
long startTime = System.nanoTime() / 1000000L;
boolean slowPath = Baritone.settings().slowPath.get();
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS : Baritone.settings().pathTimeoutMS).<Long>get();
long lastPrintout = 0;
if (slowPath) {
displayChatMessageRaw("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms");
}
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout);
//long lastPrintout = 0;
int numNodes = 0;
int numMovementsConsidered = 0;
int numEmptyChunk = 0;
boolean favoring = favoredPositions.isPresent();
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.currentTimeMillis() < timeoutTime) {
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) {
if (slowPath) {
try {
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
@@ -90,41 +97,35 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
PathNode currentNode = openSet.removeLowest();
currentNode.isOpen = false;
mostRecentConsidered = currentNode;
BetterBlockPos currentNodePos = currentNode.pos;
BlockPos currentNodePos = currentNode.pos;
numNodes++;
if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second
System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far");
lastPrintout = System.currentTimeMillis();
}
if (goal.isInGoal(currentNodePos)) {
currentlyRunning = null;
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered");
return Optional.of(new Path(startNode, currentNode, numNodes));
}
//long constructStart = System.nanoTime();
Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at currentNodePos, in random order
shuffle(possibleMovements);
//long constructEnd = System.nanoTime();
//System.out.println(constructEnd - constructStart);
for (Movement movementToGetToNeighbor : possibleMovements) {
if (movementToGetToNeighbor == null) {
continue;
}
BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest();
boolean isPositionCached = false;
if (WorldProvider.INSTANCE.getCurrentWorld() != null) {
if (WorldProvider.INSTANCE.getCurrentWorld().cache.getBlock(dest) != null) {
isPositionCached = true;
BlockPos dest = movementToGetToNeighbor.getDest();
int chunkX = currentNodePos.getX() >> 4;
int chunkZ = currentNodePos.getZ() >> 4;
if (dest.getX() >> 4 != chunkX || dest.getZ() >> 4 != chunkZ) {
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
if (chunkProvider.getLoadedChunk(chunkX, chunkZ) == null) {
// see issue #106
if (cachedWorld == null || !cachedWorld.isCached(dest)) {
numEmptyChunk++;
continue;
}
}
}
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(dest) instanceof EmptyChunk) {
numEmptyChunk++;
continue;
}
//long costStart = System.nanoTime();
// TODO cache cost
double actionCost = movementToGetToNeighbor.getCost(calcContext);
//long costEnd = System.nanoTime();
//System.out.println(movementToGetToNeighbor.getClass() + "" + (costEnd - costStart));
numMovementsConsidered++;
if (actionCost >= ActionCosts.COST_INF) {
continue;
}
@@ -162,6 +163,9 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
for (int i = 0; i < bestSoFar.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (heuristic < bestHeuristicSoFar[i]) {
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
continue;
}
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
}
@@ -169,6 +173,13 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
}
}
}
if (cancelRequested) {
currentlyRunning = null;
return Optional.empty();
}
System.out.println(numMovementsConsidered + " movements considered");
System.out.println("Open set size: " + openSet.size());
System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second");
double bestDist = 0;
for (int i = 0; i < bestSoFar.length; i++) {
if (bestSoFar[i] == null) {
@@ -179,51 +190,55 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
displayChatMessageRaw("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i]);
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + dist + " blocks");
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
currentlyRunning = null;
return Optional.of(new Path(startNode, bestSoFar[i], numNodes));
}
}
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks =(");
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
displayChatMessageRaw("No path found =(");
currentlyRunning = null;
return Optional.empty();
}
public static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) {
public static Movement[] getConnectedPositions(BlockPos pos, CalculationContext calcContext) {
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
BetterBlockPos east = new BetterBlockPos(x + 1, y, z);
BetterBlockPos west = new BetterBlockPos(x - 1, y, z);
BetterBlockPos south = new BetterBlockPos(x, y, z + 1);
BetterBlockPos north = new BetterBlockPos(x, y, z - 1);
BlockPos east = new BlockPos(x + 1, y, z);
BlockPos west = new BlockPos(x - 1, y, z);
BlockPos south = new BlockPos(x, y, z + 1);
BlockPos north = new BlockPos(x, y, z - 1);
return new Movement[]{
new MovementTraverse(pos, east),
new MovementTraverse(pos, west),
new MovementTraverse(pos, north),
new MovementTraverse(pos, south),
new MovementAscend(pos, new BetterBlockPos(x + 1, y + 1, z)),
new MovementAscend(pos, new BetterBlockPos(x - 1, y + 1, z)),
new MovementAscend(pos, new BetterBlockPos(x, y + 1, z + 1)),
new MovementAscend(pos, new BetterBlockPos(x, y + 1, z - 1)),
new MovementAscend(pos, new BlockPos(x + 1, y + 1, z)),
new MovementAscend(pos, new BlockPos(x - 1, y + 1, z)),
new MovementAscend(pos, new BlockPos(x, y + 1, z + 1)),
new MovementAscend(pos, new BlockPos(x, y + 1, z - 1)),
MovementHelper.generateMovementFallOrDescend(pos, east, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, west, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, north, calcContext),
MovementHelper.generateMovementFallOrDescend(pos, south, calcContext),
new MovementDownward(pos, new BetterBlockPos(x, y - 1, z)),
new MovementDownward(pos, new BlockPos(x, y - 1, z)),
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST),
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST),
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST),
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST),
new MovementPillar(pos, new BetterBlockPos(x, y + 1, z))
new MovementPillar(pos, new BlockPos(x, y + 1, z)),
MovementParkour.calculate(pos, EnumFacing.NORTH),
MovementParkour.calculate(pos, EnumFacing.SOUTH),
MovementParkour.calculate(pos, EnumFacing.EAST),
MovementParkour.calculate(pos, EnumFacing.WEST),
};
}

View File

@@ -17,13 +17,12 @@
package baritone.pathing.calc;
import baritone.behavior.impl.PathingBehavior;
import baritone.pathing.goals.Goal;
import baritone.pathing.path.IPath;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
/**
@@ -38,11 +37,11 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
*/
protected static AbstractNodeCostSearch currentlyRunning = null;
protected final BetterBlockPos start;
protected final BlockPos start;
protected final Goal goal;
protected final Map<BetterBlockPos, PathNode> map;
private final HashMap<BlockPos, PathNode> map; // see issue #107
protected PathNode startNode;
@@ -52,6 +51,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
private volatile boolean isFinished;
protected boolean cancelRequested;
/**
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts).
@@ -65,21 +66,36 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
protected final static double MIN_DIST_PATH = 5;
AbstractNodeCostSearch(BlockPos start, Goal goal) {
this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
this.start = new BlockPos(start.getX(), start.getY(), start.getZ());
this.goal = goal;
this.map = new HashMap<>();
}
public synchronized Optional<IPath> calculate() {
public void cancel() {
cancelRequested = true;
}
public synchronized Optional<IPath> calculate(long timeout) {
if (isFinished) {
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
}
Optional<IPath> path = calculate0();
isFinished = true;
return path;
this.cancelRequested = false;
try {
Optional<IPath> path = calculate0(timeout);
isFinished = true;
return path;
} catch (Exception e) {
currentlyRunning = null;
isFinished = true;
if (e instanceof RuntimeException) {
throw (RuntimeException) e;
} else {
throw new RuntimeException(e);
}
}
}
protected abstract Optional<IPath> calculate0();
protected abstract Optional<IPath> calculate0(long timeout);
/**
* Determines the distance squared from the specified node to the start
@@ -104,8 +120,19 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* @param pos The pos to lookup
* @return The associated node
*/
protected PathNode getNodeAtPosition(BetterBlockPos pos) {
return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
protected PathNode getNodeAtPosition(BlockPos pos) {
// see issue #107
PathNode node = map.get(pos);
if (node == null) {
node = new PathNode(pos, goal);
map.put(pos, node);
}
return node;
}
public static void forceCancel() {
PathingBehavior.INSTANCE.cancel();
currentlyRunning = null;
}
@Override

View File

@@ -39,7 +39,7 @@ public interface IPathFinder {
*
* @return The final path
*/
Optional<IPath> calculate();
Optional<IPath> calculate(long timeout);
/**
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet

View File

@@ -19,7 +19,7 @@ package baritone.pathing.calc;
import baritone.pathing.movement.Movement;
import baritone.pathing.path.IPath;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
@@ -37,18 +37,18 @@ class Path implements IPath {
/**
* The start position of this path
*/
final BetterBlockPos start;
final BlockPos start;
/**
* The end position of this path
*/
final BetterBlockPos end;
final BlockPos end;
/**
* The blocks on the path. Guaranteed that path.get(0) equals start and
* path.get(path.size()-1) equals end
*/
final List<BetterBlockPos> path;
final List<BlockPos> path;
final List<Movement> movements;
@@ -75,7 +75,7 @@ class Path implements IPath {
throw new IllegalStateException();
}
PathNode current = end;
LinkedList<BetterBlockPos> tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2)
LinkedList<BlockPos> tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2)
LinkedList<Movement> tempMovements = new LinkedList<>(); // Instead, do it into a linked list, then convert at the end
while (!current.equals(start)) {
tempPath.addFirst(current.pos);
@@ -122,7 +122,7 @@ class Path implements IPath {
}
@Override
public List<BetterBlockPos> positions() {
public List<BlockPos> positions() {
return Collections.unmodifiableList(path);
}
@@ -132,12 +132,12 @@ class Path implements IPath {
}
@Override
public BetterBlockPos getSrc() {
public BlockPos getSrc() {
return start;
}
@Override
public BetterBlockPos getDest() {
public BlockPos getDest() {
return end;
}
}

View File

@@ -19,19 +19,19 @@ package baritone.pathing.calc;
import baritone.pathing.goals.Goal;
import baritone.pathing.movement.Movement;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
/**
* A node in the path, containing the cost and steps to get to it.
*
* @author leijurv
*/
public class PathNode {
public final class PathNode {
/**
* The position of this node
*/
final BetterBlockPos pos;
final BlockPos pos;
/**
* The goal it's going towards
@@ -78,7 +78,7 @@ public class PathNode {
*/
public int heapPosition;
public PathNode(BetterBlockPos pos, Goal goal) {
public PathNode(BlockPos pos, Goal goal) {
this.pos = pos;
this.previous = null;
this.cost = Short.MAX_VALUE;
@@ -103,8 +103,9 @@ public class PathNode {
// GOTTA GO FAST
// ALL THESE CHECKS ARE FOR PEOPLE WHO WANT SLOW CODE
// SKRT SKRT
//if (obj == null || !(obj instanceof PathNode))
//if (obj == null || !(obj instanceof PathNode)) {
// return false;
//}
//final PathNode other = (PathNode) obj;
//return Objects.equals(this.pos, other.pos) && Objects.equals(this.goal, other.goal);

View File

@@ -26,7 +26,7 @@ import java.util.Arrays;
*
* @author leijurv
*/
public class BinaryHeapOpenSet implements IOpenSet {
public final class BinaryHeapOpenSet implements IOpenSet {
/**
* The initial capacity of the heap (2^10)
@@ -52,6 +52,10 @@ public class BinaryHeapOpenSet implements IOpenSet {
this.array = new PathNode[size];
}
public int size() {
return size;
}
@Override
public final void insert(PathNode value) {
if (size >= array.length - 1) {
@@ -104,14 +108,13 @@ public class BinaryHeapOpenSet implements IOpenSet {
int smallerChild = 2;
double cost = val.combinedCost;
do {
int right = smallerChild + 1;
PathNode smallerChildNode = array[smallerChild];
double smallerChildCost = smallerChildNode.combinedCost;
if (right <= size) {
PathNode rightChildNode = array[right];
if (smallerChild < size) {
PathNode rightChildNode = array[smallerChild + 1];
double rightChildCost = rightChildNode.combinedCost;
if (smallerChildCost > rightChildCost) {
smallerChild = right;
smallerChild++;
smallerChildCost = rightChildCost;
smallerChildNode = rightChildNode;
}
@@ -124,8 +127,7 @@ public class BinaryHeapOpenSet implements IOpenSet {
val.heapPosition = smallerChild;
smallerChildNode.heapPosition = index;
index = smallerChild;
smallerChild = index << 1;
} while (smallerChild <= size);
} while ((smallerChild <<= 1) <= size);
return result;
}
}

View File

@@ -22,10 +22,11 @@ import baritone.pathing.calc.PathNode;
/**
* A linked list implementation of an open set. This is the original implementation from MineBot.
* It has incredibly fast insert performance, at the cost of O(n) removeLowest.
* It sucks. BinaryHeapOpenSet results in more than 10x more nodes considered in 4 seconds.
*
* @author leijurv
*/
public class LinkedListOpenSet implements IOpenSet {
class LinkedListOpenSet implements IOpenSet {
private Node first = null;
@Override

View File

@@ -17,6 +17,7 @@
package baritone.pathing.goals;
import baritone.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
/**
@@ -24,7 +25,7 @@ import net.minecraft.util.math.BlockPos;
*
* @author leijurv
*/
public class GoalBlock implements Goal {
public class GoalBlock implements Goal, IGoalRenderPos {
/**
* The X block position of this goal

View File

@@ -17,25 +17,48 @@
package baritone.pathing.goals;
import net.minecraft.util.EnumFacing;
import baritone.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.BlockPos;
/**
* Don't get into the block, but get directly adjacent to it. Useful for chests.
*
* @author avecowa
*/
public class GoalGetToBlock extends GoalComposite {
public class GoalGetToBlock implements Goal, IGoalRenderPos {
private final int x;
private final int y;
private final int z;
public GoalGetToBlock(BlockPos pos) {
super(adjacentBlocks(pos));
this.x = pos.getX();
this.y = pos.getY();
this.z = pos.getZ();
}
private static BlockPos[] adjacentBlocks(BlockPos pos) {
BlockPos[] sides = new BlockPos[6];
for (int i = 0; i < 6; i++) {
sides[i] = pos.offset(EnumFacing.values()[i]);
public BlockPos getGoalPos() {
return new BlockPos(x, y, z);
}
@Override
public boolean isInGoal(BlockPos pos) {
int xDiff = pos.getX() - this.x;
int yDiff = pos.getY() - this.y;
int zDiff = pos.getZ() - this.z;
if (yDiff < 0) {
yDiff++;
}
return sides;
return Math.abs(xDiff) + Math.abs(yDiff) + Math.abs(zDiff) <= 1;
}
@Override
public double heuristic(BlockPos pos) {
int xDiff = pos.getX() - this.x;
int yDiff = pos.getY() - this.y;
int zDiff = pos.getZ() - this.z;
return GoalBlock.calculate(xDiff, yDiff, zDiff);
}
}

View File

@@ -0,0 +1,65 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.pathing.goals;
import baritone.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
public class GoalNear implements Goal, IGoalRenderPos {
final int x;
final int y;
final int z;
final int rangeSq;
public GoalNear(BlockPos pos, int range) {
this.x = pos.getX();
this.y = pos.getY();
this.z = pos.getZ();
this.rangeSq = range * range;
}
@Override
public boolean isInGoal(BlockPos pos) {
int diffX = x - pos.getX();
int diffY = y - pos.getY();
int diffZ = z - pos.getZ();
return diffX * diffX + diffY * diffY + diffZ * diffZ <= rangeSq;
}
@Override
public double heuristic(BlockPos pos) {
int diffX = x - pos.getX();
int diffY = y - pos.getY();
int diffZ = z - pos.getZ();
return GoalBlock.calculate(diffX, diffY, diffZ);
}
public BlockPos getGoalPos() {
return new BlockPos(x, y, z);
}
@Override
public String toString() {
return "GoalNear{" +
"x=" + x +
", y=" + y +
", z=" + z +
", rangeSq=" + rangeSq +
'}';
}
}

View File

@@ -17,6 +17,7 @@
package baritone.pathing.goals;
import baritone.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
/**
@@ -25,7 +26,7 @@ import net.minecraft.util.math.BlockPos;
*
* @author leijurv
*/
public class GoalTwoBlocks implements Goal {
public class GoalTwoBlocks implements Goal, IGoalRenderPos {
/**
* The X block position of this goal
@@ -68,6 +69,10 @@ public class GoalTwoBlocks implements Goal {
return GoalBlock.calculate(xDiff, yDiff, zDiff);
}
public BlockPos getGoalPos() {
return new BlockPos(x, y, z);
}
@Override
public String toString() {
return "GoalTwoBlocks{x=" + x + ",y=" + y + ",z=" + z + "}";

View File

@@ -20,6 +20,7 @@ package baritone.pathing.goals;
import baritone.Baritone;
import baritone.utils.Utils;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import net.minecraft.util.math.Vec3d;
/**
@@ -88,9 +89,9 @@ public class GoalXZ implements Goal {
}
public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) {
double theta = Utils.degToRad(yaw);
double x = origin.x - Math.sin(theta) * distance;
double z = origin.z + Math.cos(theta) * distance;
float theta = (float) Utils.degToRad(yaw);
double x = origin.x - MathHelper.sin(theta) * distance;
double z = origin.z + MathHelper.cos(theta) * distance;
return new GoalXZ((int) x, (int) z);
}

View File

@@ -24,7 +24,8 @@ public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieI
*/
double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633
double WALK_ONE_IN_WATER_COST = 20 / 2.2;
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_IN_WATER_COST; // TODO issue #7
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 0.5; // 0.4 in BlockSoulSand but effectively about half
double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST / 0.75;
double LADDER_UP_ONE_COST = 20 / 2.35;
double LADDER_DOWN_ONE_COST = 20 / 3.0;
double SNEAK_ONE_BLOCK_COST = 20 / 1.3;

View File

@@ -46,7 +46,6 @@ public class CalculationContext implements Helper {
}
public CalculationContext(ToolSet toolSet) {
player().setSprinting(true);
this.toolSet = toolSet;
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();

View File

@@ -21,16 +21,11 @@ import baritone.Baritone;
import baritone.behavior.impl.LookBehavior;
import baritone.behavior.impl.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.pathing.movement.movements.MovementDownward;
import baritone.pathing.movement.movements.MovementPillar;
import baritone.pathing.movement.movements.MovementTraverse;
import baritone.utils.*;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockVine;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import java.util.ArrayList;
import java.util.Arrays;
@@ -41,6 +36,8 @@ import static baritone.utils.InputOverrideHandler.Input;
public abstract class Movement implements Helper, MovementHelper {
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
private MovementState currentState = new MovementState().setStatus(MovementStatus.PREPPING);
protected final BlockPos src;
@@ -53,44 +50,35 @@ public abstract class Movement implements Helper, MovementHelper {
protected final BlockPos[] positionsToBreak;
/**
* The positions where we need to place a block before this movement can ensue
* The position where we need to place a block before this movement can ensue
*/
protected final BlockPos[] positionsToPlace;
protected final BlockPos positionToPlace;
private boolean didBreakLastTick;
private Double cost;
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace) {
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos toPlace) {
this.src = src;
this.dest = dest;
this.positionsToBreak = toBreak;
this.positionsToPlace = toPlace;
this.positionToPlace = toPlace;
}
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace, Vec3d rotationTarget) {
this(src, dest, toBreak, toPlace);
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak) {
this(src, dest, toBreak, null);
}
public double getCost(CalculationContext context) {
if (cost == null) {
if (context == null)
if (context == null) {
context = new CalculationContext();
cost = calculateCost0(context);
}
cost = calculateCost(context);
}
return cost;
}
private double calculateCost0(CalculationContext context) {
if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) {
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) {
return COST_INF;
}
}
return calculateCost(context);
}
protected abstract double calculateCost(CalculationContext context);
public double recalculateCost() {
@@ -98,6 +86,14 @@ public abstract class Movement implements Helper, MovementHelper {
return getCost(null);
}
protected void override(double cost) {
this.cost = cost;
}
public double calculateCostWithoutCaching() {
return calculateCost(new CalculationContext());
}
/**
* Handles the execution of the latest Movement
* State, and offers a Status to the calling class.
@@ -138,13 +134,15 @@ public abstract class Movement implements Helper, MovementHelper {
});
latestState.getInputStates().replaceAll((input, forced) -> false);
if (!this.didBreakLastTick)
if (!this.didBreakLastTick) {
BlockBreakHelper.stopBreakingBlock();
}
currentState = latestState;
if (isFinished())
if (isFinished()) {
onFinish(latestState);
}
return currentState.getStatus();
}
@@ -159,7 +157,7 @@ public abstract class Movement implements Helper, MovementHelper {
somethingInTheWay = true;
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
if (reachable.isPresent()) {
player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos));
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
return false;
}
@@ -280,6 +278,11 @@ public abstract class Movement implements Helper, MovementHelper {
} else if (state.getStatus() == MovementStatus.PREPPING) {
state.setStatus(MovementStatus.WAITING);
}
if (state.getStatus() == MovementStatus.WAITING) {
state.setStatus(MovementStatus.RUNNING);
}
return state;
}
@@ -310,10 +313,8 @@ public abstract class Movement implements Helper, MovementHelper {
return toPlaceCached;
}
List<BlockPos> result = new ArrayList<>();
for (BlockPos positionToBreak : positionsToPlace) {
if (!MovementHelper.canWalkOn(positionToBreak)) {
result.add(positionToBreak);
}
if (positionToPlace != null && !MovementHelper.canWalkOn(positionToPlace)) {
result.add(positionToPlace);
}
toPlaceCached = result;
return result;

View File

@@ -23,6 +23,7 @@ import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.pathing.movement.movements.MovementDescend;
import baritone.pathing.movement.movements.MovementFall;
import baritone.utils.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.*;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.IBlockState;
@@ -48,16 +49,17 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean avoidBreaking(BlockPos pos, IBlockState state) {
Block b = state.getBlock();
BlockPos below = new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ());
return Blocks.ICE.equals(b) // ice becomes water, and water can mess up the path
int x = pos.getX();
int y = pos.getY();
int z = pos.getZ();
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|| b instanceof BlockSilverfish // obvious reasons
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ()))
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ()))
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1))
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1))
|| (!(b instanceof BlockLilyPad && BlockStateInterface.isWater(below)) && BlockStateInterface.isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid
// TODO revisit this. why is it not okay to break non-lilypads that are right above water?
// call BlockStateInterface.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|| BlockStateInterface.get(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side
|| BlockStateInterface.get(x + 1, y, z).getBlock() instanceof BlockLiquid
|| BlockStateInterface.get(x - 1, y, z).getBlock() instanceof BlockLiquid
|| BlockStateInterface.get(x, y, z + 1).getBlock() instanceof BlockLiquid
|| BlockStateInterface.get(x, y, z - 1).getBlock() instanceof BlockLiquid;
}
/**
@@ -72,10 +74,10 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
Block block = state.getBlock();
if (block instanceof BlockFire
|| block instanceof BlockTripWire
|| block instanceof BlockWeb
|| block instanceof BlockEndPortal) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire
if (block == Blocks.AIR) {
return true;
}
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL) {
return false;
}
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
@@ -93,10 +95,50 @@ public interface MovementHelper extends ActionCosts, Helper {
return true;
}
}
IBlockState up = BlockStateInterface.get(pos.up());
if (BlockStateInterface.isFlowing(state) || up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
if (BlockStateInterface.isFlowing(state)) {
return false; // Don't walk through flowing liquids
}
if (block instanceof BlockLiquid) {
if (Baritone.settings().assumeWalkOnWater.get()) {
return false;
}
IBlockState up = BlockStateInterface.get(pos.up());
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
return false;
}
}
return block.isPassable(mc.world, pos);
}
/**
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
* not including water, and not including ladders or vines or cobwebs (they slow us down)
*
* @return
*/
static boolean fullyPassable(BlockPos pos) {
return fullyPassable(pos, BlockStateInterface.get(pos));
}
static boolean fullyPassable(BlockPos pos, IBlockState state) {
Block block = state.getBlock();
if (block == Blocks.AIR) {
return true;
}
// exceptions - blocks that are isPassasble true, but we can't actually jump through
if (block == Blocks.FIRE
|| block == Blocks.TRIPWIRE
|| block == Blocks.WEB
|| block == Blocks.VINE
|| block == Blocks.LADDER
|| block instanceof BlockDoor
|| block instanceof BlockFenceGate
|| block instanceof BlockSnow
|| block instanceof BlockLiquid
|| block instanceof BlockTrapDoor
|| block instanceof BlockEndPortal) {
return false;
}
return block.isPassable(mc.world, pos);
}
@@ -121,30 +163,35 @@ public interface MovementHelper extends ActionCosts, Helper {
}
static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) {
if (playerPos.equals(doorPos))
if (playerPos.equals(doorPos)) {
return false;
}
IBlockState state = BlockStateInterface.get(doorPos);
if (!(state.getBlock() instanceof BlockDoor))
if (!(state.getBlock() instanceof BlockDoor)) {
return true;
}
return isHorizontalBlockPassable(doorPos, state, playerPos, BlockDoor.OPEN);
}
static boolean isGatePassable(BlockPos gatePos, BlockPos playerPos) {
if (playerPos.equals(gatePos))
if (playerPos.equals(gatePos)) {
return false;
}
IBlockState state = BlockStateInterface.get(gatePos);
if (!(state.getBlock() instanceof BlockFenceGate))
if (!(state.getBlock() instanceof BlockFenceGate)) {
return true;
}
return isHorizontalBlockPassable(gatePos, state, playerPos, BlockFenceGate.OPEN);
}
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) {
if (playerPos.equals(blockPos))
if (playerPos.equals(blockPos)) {
return false;
}
EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis();
boolean open = blockState.getValue(propertyOpen);
@@ -163,10 +210,11 @@ public interface MovementHelper extends ActionCosts, Helper {
static boolean avoidWalkingInto(Block block) {
return BlockStateInterface.isLava(block)
|| block instanceof BlockCactus
|| block instanceof BlockFire
|| block instanceof BlockEndPortal
|| block instanceof BlockWeb;
|| block == Blocks.MAGMA
|| block == Blocks.CACTUS
|| block == Blocks.FIRE
|| block == Blocks.END_PORTAL
|| block == Blocks.WEB;
}
/**
@@ -178,34 +226,63 @@ public interface MovementHelper extends ActionCosts, Helper {
*/
static boolean canWalkOn(BlockPos pos, IBlockState state) {
Block block = state.getBlock();
if (block instanceof BlockLadder || (Baritone.settings().allowVines.get() && block instanceof BlockVine)) { // TODO reconsider this
if (block == Blocks.AIR || block == Blocks.MAGMA) {
return false;
}
if (state.isBlockNormalCube()) {
if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) {
throw new IllegalStateException();
}
return true;
}
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this
return true;
}
if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) {
return true;
}
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
return true;
}
if (BlockStateInterface.isWater(block)) {
Block up = BlockStateInterface.get(pos.up()).getBlock();
if (up instanceof BlockLilyPad) {
return true;
}
if (BlockStateInterface.isFlowing(state)) {
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
}
// 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
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
}
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
return true;
}
if (Blocks.FARMLAND.equals(block) || Blocks.GRASS_PATH.equals(block)) {
if (block instanceof BlockSlab) {
if (!Baritone.settings().allowWalkOnBottomSlab.get()) {
if (((BlockSlab) block).isDouble()) {
return true;
}
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
}
return true;
}
if (block instanceof BlockAir) {
return false;
if (block instanceof BlockStairs) {
return true;
}
if (BlockStateInterface.isWater(block)) {
Block up = BlockStateInterface.get(pos.up()).getBlock();
return BlockStateInterface.isWater(up) || up instanceof BlockLilyPad; // You can only walk on water if there is water above it
}
if (Blocks.MAGMA.equals(block)) {
return false;
}
return state.isBlockNormalCube() && !BlockStateInterface.isLava(block);
return false;
}
static boolean canWalkOn(BlockPos pos) {
return canWalkOn(pos, BlockStateInterface.get(pos));
}
static boolean canFall(BlockPos pos) {
return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling;
static boolean canPlaceAgainst(BlockPos pos) {
IBlockState state = BlockStateInterface.get(pos);
// 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
return state.isBlockNormalCube();
}
static double getMiningDurationTicks(CalculationContext context, BlockPos position, boolean includeFalling) {
@@ -215,7 +292,7 @@ public interface MovementHelper extends ActionCosts, Helper {
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state, boolean includeFalling) {
Block block = state.getBlock();
if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough?
if (!canWalkThrough(position, state)) {
if (!context.allowBreak()) {
return COST_INF;
}
@@ -223,7 +300,12 @@ public interface MovementHelper extends ActionCosts, Helper {
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 result = m / context.getToolSet().getStrVsBlock(state, position);
double strVsBlock = context.getToolSet().getStrVsBlock(state);
if (strVsBlock < 0) {
return COST_INF;
}
double result = m / strVsBlock;
if (includeFalling) {
BlockPos up = position.up();
IBlockState above = BlockStateInterface.get(up);
@@ -236,6 +318,16 @@ public interface MovementHelper extends ActionCosts, Helper {
return 0; // we won't actually mine it, so don't check fallings above
}
static boolean isBottomSlab(IBlockState state) {
return state.getBlock() instanceof BlockSlab
&& !((BlockSlab) state.getBlock()).isDouble()
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
}
static boolean isBottomSlab(BlockPos pos) {
return isBottomSlab(BlockStateInterface.get(pos));
}
/**
* The entity the player is currently looking at
*
@@ -326,6 +418,7 @@ public interface MovementHelper extends ActionCosts, Helper {
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
// we can't cost shortcut descend because !canWalkThrough doesn't mean canWalkOn
}
// we're clear for a fall 2

View File

@@ -26,6 +26,7 @@ import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState;
@@ -39,29 +40,10 @@ import java.util.Objects;
public class MovementAscend extends Movement {
private BlockPos[] against = new BlockPos[3];
private int ticksWithoutPlacement = 0;
public MovementAscend(BlockPos src, BlockPos dest) {
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, new BlockPos[]{dest.down()});
BlockPos placementLocation = positionsToPlace[0]; // dest.down()
int i = 0;
if (!placementLocation.north().equals(src))
against[i++] = placementLocation.north();
if (!placementLocation.south().equals(src))
against[i++] = placementLocation.south();
if (!placementLocation.east().equals(src))
against[i++] = placementLocation.east();
if (!placementLocation.west().equals(src))
against[i] = placementLocation.west();
// TODO: add ability to place against .down() as well as the cardinal directions
// useful for when you are starting a staircase without anything to place against
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, dest.down());
}
@Override
@@ -72,16 +54,34 @@ public class MovementAscend extends Movement {
@Override
protected double calculateCost(CalculationContext context) {
IBlockState toPlace = BlockStateInterface.get(positionsToPlace[0]);
if (!MovementHelper.canWalkOn(positionsToPlace[0], toPlace)) {
IBlockState srcDown = BlockStateInterface.get(src.down());
if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) {
return COST_INF;
}
// we can jump from soul sand, but not from a bottom slab
boolean jumpingFromBottomSlab = MovementHelper.isBottomSlab(srcDown);
IBlockState toPlace = BlockStateInterface.get(positionToPlace);
boolean jumpingToBottomSlab = MovementHelper.isBottomSlab(toPlace);
if (jumpingFromBottomSlab && !jumpingToBottomSlab) {
return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab
}
if (!MovementHelper.canWalkOn(positionToPlace, toPlace)) {
if (!context.hasThrowaway()) {
return COST_INF;
}
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionsToPlace[0], toPlace)) {
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) {
return COST_INF;
}
for (BlockPos against1 : against) {
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
// TODO: add ability to place against .down() as well as the cardinal directions
// useful for when you are starting a staircase without anything to place against
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
for (int i = 0; i < 4; i++) {
BlockPos against1 = positionToPlace.offset(HORIZONTALS[i]);
if (against1.equals(src)) {
continue;
}
if (MovementHelper.canPlaceAgainst(against1)) {
return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
}
}
@@ -108,9 +108,11 @@ public class MovementAscend extends Movement {
// it's possible srcUp is AIR from the start, and srcUp2 is falling
// and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us
}
// TODO maybe change behavior if src.down() is soul sand?
double walk = WALK_ONE_BLOCK_COST;
if (toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
if (jumpingToBottomSlab && !jumpingFromBottomSlab) {
return walk + getTotalHardnessOfBlocksToBreak(context); // we don't hit space we just walk into the slab
}
if (!jumpingToBottomSlab && toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
}
// we hit space immediately on entering this action
@@ -122,22 +124,22 @@ public class MovementAscend extends Movement {
super.updateState(state);
// TODO incorporate some behavior from ActionClimb (specifically how it waited until it was at most 1.2 blocks away before starting to jump
// for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly)
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
if (playerFeet().equals(dest)) {
return state.setStatus(MovementStatus.SUCCESS);
}
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
for (BlockPos anAgainst : against) {
if (BlockStateInterface.get(anAgainst).isBlockNormalCube()) {
IBlockState jumpingOnto = BlockStateInterface.get(positionToPlace);
if (!MovementHelper.canWalkOn(positionToPlace, jumpingOnto)) {
for (int i = 0; i < 4; i++) {
BlockPos anAgainst = positionToPlace.offset(HORIZONTALS[i]);
if (anAgainst.equals(src)) {
continue;
}
if (MovementHelper.canPlaceAgainst(anAgainst)) {
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
return state.setStatus(MovementStatus.UNREACHABLE);
}
@@ -148,16 +150,18 @@ public class MovementAscend extends Movement {
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionsToPlace[0])) {
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionToPlace)) {
ticksWithoutPlacement++;
state.setInput(InputOverrideHandler.Input.SNEAK, true);
if (player().isSneaking()) {
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
if (ticksWithoutPlacement > 20) {
// After 20 ticks without placement, we might be standing in the way, move back
if (ticksWithoutPlacement > 10) {
// After 10 ticks without placement, we might be standing in the way, move back
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
}
} else {
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); // break whatever replaceable block is in the way
}
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
});
@@ -167,6 +171,11 @@ public class MovementAscend extends Movement {
return state.setStatus(MovementStatus.UNREACHABLE);
}
MovementHelper.moveTowards(state, dest);
if (MovementHelper.isBottomSlab(jumpingOnto)) {
if (!MovementHelper.isBottomSlab(src.down())) {
return state; // don't jump while walking from a non double slab into a bottom slab
}
}
if (headBonkClear()) {
return state.setInput(InputOverrideHandler.Input.JUMP, true);

View File

@@ -24,16 +24,15 @@ import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockVine;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
public class MovementDescend extends Movement {
public MovementDescend(BlockPos start, BlockPos end) {
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, new BlockPos[]{end.down()});
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, end.down());
}
@Override
@@ -44,18 +43,22 @@ public class MovementDescend extends Movement {
@Override
protected double calculateCost(CalculationContext context) {
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
return COST_INF;
}
if (!MovementHelper.canWalkOn(positionToPlace)) {
return COST_INF;
}
Block tmp1 = BlockStateInterface.get(dest).getBlock();
if (tmp1 instanceof BlockLadder || tmp1 instanceof BlockVine) {
if (tmp1 == Blocks.LADDER || tmp1 == Blocks.VINE) {
return COST_INF;
}
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
double walk = WALK_OFF_BLOCK_COST;
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
if (fromDown == Blocks.SOUL_SAND) {
// use this ratio to apply the soul sand speed penalty to our 0.8 block distance
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
walk = WALK_ONE_OVER_SOUL_SAND_COST;
}
return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context);
}
@@ -65,13 +68,8 @@ public class MovementDescend extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
BlockPos playerFeet = playerFeet();

View File

@@ -23,6 +23,8 @@ import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.BlockMagma;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
@@ -41,80 +43,60 @@ public class MovementDiagonal extends Movement {
// super(start, start.offset(dir1).offset(dir2), new BlockPos[]{start.offset(dir1), start.offset(dir1).up(), start.offset(dir2), start.offset(dir2).up(), start.offset(dir1).offset(dir2), start.offset(dir1).offset(dir2).up()}, new BlockPos[]{start.offset(dir1).offset(dir2).down()});
}
public MovementDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) {
private MovementDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) {
this(start, dir1.offset(drr2), dir1, dir2);
}
public MovementDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) {
super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}, new BlockPos[]{end.down()});
}
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementState.MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
}
if (playerFeet().equals(dest)) {
state.setStatus(MovementState.MovementStatus.SUCCESS);
return state;
}
if (!BlockStateInterface.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
MovementHelper.moveTowards(state, dest);
return state;
private MovementDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) {
super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()});
}
@Override
protected double calculateCost(CalculationContext context) {
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
return COST_INF;
}
if (!MovementHelper.canWalkThrough(positionsToBreak[4]) || !MovementHelper.canWalkThrough(positionsToBreak[5])) {
return COST_INF;
}
IBlockState destWalkOn = BlockStateInterface.get(positionsToPlace[0]);
if (!MovementHelper.canWalkOn(positionsToPlace[0], destWalkOn)) {
BlockPos destDown = dest.down();
IBlockState destWalkOn = BlockStateInterface.get(destDown);
if (!MovementHelper.canWalkOn(destDown, destWalkOn)) {
return COST_INF;
}
double multiplier = WALK_ONE_BLOCK_COST;
// For either possible soul sand, that affects half of our walking
if (destWalkOn.getBlock().equals(Blocks.SOUL_SAND)) {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
}
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
if (fromDown == Blocks.SOUL_SAND) {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
}
if (BlockStateInterface.get(positionsToBreak[2].down()).getBlock() instanceof BlockMagma) {
Block cuttingOver1 = BlockStateInterface.get(positionsToBreak[2].down()).getBlock();
if (cuttingOver1 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver1)) {
return COST_INF;
}
if (BlockStateInterface.get(positionsToBreak[4].down()).getBlock() instanceof BlockMagma) {
Block cuttingOver2 = BlockStateInterface.get(positionsToBreak[4].down()).getBlock();
if (cuttingOver2 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver2)) {
return COST_INF;
}
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], true);
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], true);
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
IBlockState pb2 = BlockStateInterface.get(positionsToBreak[2]);
IBlockState pb3 = BlockStateInterface.get(positionsToBreak[3]);
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, true);
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], pb2, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], pb3, true);
if (optionA != 0 && optionB != 0) {
return COST_INF;
}
if (optionA == 0) {
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[2]))) {
return COST_INF;
}
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[3]))) {
if (MovementHelper.avoidWalkingInto(pb2.getBlock()) || MovementHelper.avoidWalkingInto(pb3.getBlock())) {
return COST_INF;
}
}
if (optionB == 0) {
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[0]))) {
return COST_INF;
}
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[1]))) {
if (MovementHelper.avoidWalkingInto(pb0.getBlock()) || MovementHelper.avoidWalkingInto(pb1.getBlock())) {
return COST_INF;
}
}
@@ -135,6 +117,24 @@ public class MovementDiagonal extends Movement {
return multiplier * SQRT_2;
}
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
return state;
}
if (playerFeet().equals(dest)) {
state.setStatus(MovementState.MovementStatus.SUCCESS);
return state;
}
if (!BlockStateInterface.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
MovementHelper.moveTowards(state, dest);
return state;
}
@Override
protected boolean prepared(MovementState state) {
return true;

View File

@@ -22,10 +22,10 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.BlockVine;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
public class MovementDownward extends Movement {
@@ -33,7 +33,7 @@ public class MovementDownward extends Movement {
private int numTicks = 0;
public MovementDownward(BlockPos start, BlockPos end) {
super(start, end, new BlockPos[]{end}, new BlockPos[0]);
super(start, end, new BlockPos[]{end});
}
@Override
@@ -49,7 +49,7 @@ public class MovementDownward extends Movement {
}
IBlockState d = BlockStateInterface.get(dest);
Block td = d.getBlock();
boolean ladder = td instanceof BlockLadder || td instanceof BlockVine;
boolean ladder = td == Blocks.LADDER || td == Blocks.VINE;
if (ladder) {
return LADDER_DOWN_ONE_COST;
} else {
@@ -61,13 +61,8 @@ public class MovementDownward extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementState.MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
return state;
}
if (playerFeet().equals(dest)) {

View File

@@ -25,7 +25,12 @@ import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.*;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.init.Items;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
@@ -38,14 +43,22 @@ public class MovementFall extends Movement {
private static final ItemStack STACK_BUCKET_EMPTY = new ItemStack(Items.BUCKET);
public MovementFall(BlockPos src, BlockPos dest) {
super(src, dest, MovementFall.buildPositionsToBreak(src, dest), new BlockPos[]{dest.down()});
super(src, dest, MovementFall.buildPositionsToBreak(src, dest));
}
@Override
protected double calculateCost(CalculationContext context) {
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
return COST_INF;
}
IBlockState fallOnto = BlockStateInterface.get(dest.down());
if (!MovementHelper.canWalkOn(dest.down(), fallOnto)) {
return COST_INF;
}
if (MovementHelper.isBottomSlab(fallOnto)) {
return COST_INF; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
}
double placeBucketCost = 0.0;
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > context.maxFallHeightNoWater()) {
if (!context.hasWaterBucket()) {
@@ -84,19 +97,14 @@ public class MovementFall extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
BlockPos playerFeet = playerFeet();
Rotation targetRotation = null;
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
if (!player().inventory.hasItemStack(STACK_BUCKET_WATER) || world().provider.isNether()) {
if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) {
state.setStatus(MovementStatus.UNREACHABLE);
return state;
}
@@ -117,9 +125,8 @@ public class MovementFall extends Movement {
} else {
state.setTarget(new MovementTarget(Utils.calcRotationFromVec3d(playerHead(), Utils.getBlockPosCenter(dest)), false));
}
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 // lilypads
|| BlockStateInterface.isWater(dest))) {
if (BlockStateInterface.isWater(dest) && player().inventory.hasItemStack(STACK_BUCKET_EMPTY)) {
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || BlockStateInterface.isWater(dest))) { // 0.094 because lilypads
if (BlockStateInterface.isWater(dest) && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
if (player().motionY >= 0) {
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);

View File

@@ -0,0 +1,151 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
public class MovementParkour extends Movement {
final EnumFacing direction;
final int dist;
private MovementParkour(BlockPos src, int dist, EnumFacing dir) {
super(src, src.offset(dir, dist), new BlockPos[]{});
this.direction = dir;
this.dist = dist;
super.override(costFromJumpDistance(dist));
}
public static MovementParkour calculate(BlockPos src, EnumFacing dir) {
if (!Baritone.settings().allowParkour.get()) {
return null;
}
IBlockState standingOn = BlockStateInterface.get(src.down());
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
return null;
}
BlockPos adjBlock = src.down().offset(dir);
IBlockState adj = BlockStateInterface.get(adjBlock);
if (MovementHelper.avoidWalkingInto(adj.getBlock())) { // magma sucks
return null;
}
if (MovementHelper.canWalkOn(adjBlock, adj)) { // don't parkour if we could just traverse (for now)
return null;
}
if (!MovementHelper.fullyPassable(src.offset(dir))) {
return null;
}
if (!MovementHelper.fullyPassable(src.up().offset(dir))) {
return null;
}
for (int i = 2; i <= 4; i++) {
BlockPos dest = src.offset(dir, i);
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
for (int y = 0; y < 4; y++) {
if (!MovementHelper.fullyPassable(dest.up(y))) {
return null;
}
}
if (MovementHelper.canWalkOn(dest.down())) {
return new MovementParkour(src, i, dir);
}
}
return null;
}
private static double costFromJumpDistance(int dist) {
switch (dist) {
case 2:
return WALK_ONE_BLOCK_COST * 2; // IDK LOL
case 3:
return WALK_ONE_BLOCK_COST * 3;
case 4:
return SPRINT_ONE_BLOCK_COST * 4;
}
throw new IllegalStateException("LOL");
}
@Override
protected double calculateCost(CalculationContext context) {
if (!MovementHelper.canWalkOn(dest.down())) {
return COST_INF;
}
if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(src.down().offset(direction)).getBlock())) {
return COST_INF;
}
for (int i = 1; i <= 4; i++) {
BlockPos d = src.offset(direction, i);
for (int y = 0; y < 4; y++) {
if (!MovementHelper.fullyPassable(d.up(y))) {
return COST_INF;
}
}
if (d.equals(dest)) {
return costFromJumpDistance(i);
}
}
throw new IllegalStateException("invalid jump distance?");
}
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementState.MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
}
if (dist >= 4) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
MovementHelper.moveTowards(state, dest);
if (playerFeet().equals(dest)) {
if (player().posY - playerFeet().getY() < 0.01) {
state.setStatus(MovementState.MovementStatus.SUCCESS);
}
} else if (!playerFeet().equals(src)) {
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
state.setInput(InputOverrideHandler.Input.JUMP, true);
} else {
state.setInput(InputOverrideHandler.Input.SPRINT, false);
if (playerFeet().equals(src.offset(direction, -1))) {
MovementHelper.moveTowards(state, src);
} else {
MovementHelper.moveTowards(state, src.offset(direction, -1));
}
}
}
return state;
}
}

View File

@@ -25,17 +25,17 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Rotation;
import baritone.utils.Utils;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.util.math.BlockPos;
public class MovementPillar extends Movement {
private int numTicks = 0;
public MovementPillar(BlockPos start, BlockPos end) {
super(start, end, new BlockPos[]{start.up(2)}, new BlockPos[]{start});
super(start, end, new BlockPos[]{start.up(2)}, start);
}
@Override
@@ -48,11 +48,16 @@ public class MovementPillar extends Movement {
protected double calculateCost(CalculationContext context) {
Block fromDown = BlockStateInterface.get(src).getBlock();
boolean ladder = fromDown instanceof BlockLadder || fromDown instanceof BlockVine;
Block fromDownDown = BlockStateInterface.get(src.down()).getBlock();
IBlockState fromDownDown = BlockStateInterface.get(src.down());
if (!ladder) {
if (fromDownDown instanceof BlockLadder || fromDownDown instanceof BlockVine) {
if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) {
return COST_INF;
}
if (fromDownDown.getBlock() instanceof BlockSlab) {
if (!((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
}
}
}
if (!context.hasThrowaway() && !ladder) {
return COST_INF;
@@ -63,6 +68,9 @@ public class MovementPillar extends Movement {
}
}
double hardness = getTotalHardnessOfBlocksToBreak(context);
if (hardness >= COST_INF) {
return COST_INF;
}
if (hardness != 0) {
Block tmp = BlockStateInterface.get(src.up(2)).getBlock();
if (tmp instanceof BlockLadder || tmp instanceof BlockVine) {
@@ -70,15 +78,22 @@ public class MovementPillar extends Movement {
} else {
BlockPos chkPos = src.up(3);
IBlockState check = BlockStateInterface.get(chkPos);
if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check) || check.getBlock() instanceof BlockFalling) {//if the block above where we want to break is not a full block, don't do it
// TODO why does canWalkThrough mean this action is COST_INF?
// BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava
// but I don't understand why canWalkThrough makes it impossible
return COST_INF;
if (check.getBlock() instanceof BlockFalling) {
// see MovementAscend's identical check for breaking a falling block above our head
if (!(tmp instanceof BlockFalling) || !(BlockStateInterface.get(src.up(1)).getBlock() instanceof BlockFalling)) {
return COST_INF;
}
}
// this is commented because it may have had a purpose, but it's very unclear what it was. it's from the minebot era.
//if (!MovementHelper.canWalkOn(chkPos, check) || MovementHelper.canWalkThrough(chkPos, check)) {//if the block above where we want to break is not a full block, don't do it
// TODO why does canWalkThrough mean this action is COST_INF?
// BlockFalling makes sense, and !canWalkOn deals with weird cases like if it were lava
// but I don't understand why canWalkThrough makes it impossible
// return COST_INF;
//}
}
}
if (fromDown instanceof BlockLiquid || fromDownDown instanceof BlockLiquid) {//can't pillar on water or in water
if (fromDown instanceof BlockLiquid || fromDownDown.getBlock() instanceof BlockLiquid) {//can't pillar on water or in water
return COST_INF;
}
if (ladder) {
@@ -107,13 +122,8 @@ public class MovementPillar extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementState.MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
return state;
}
IBlockState fromDown = BlockStateInterface.get(src);
@@ -121,7 +131,7 @@ public class MovementPillar extends Movement {
boolean vine = fromDown.getBlock() instanceof BlockVine;
if (!ladder) {
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
Utils.getBlockPosCenter(positionsToPlace[0]),
Utils.getBlockPosCenter(positionToPlace),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
}
@@ -133,9 +143,12 @@ public class MovementPillar extends Movement {
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
}
if (playerFeet().equals(against.up()) || playerFeet().equals(dest))
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
}
if (MovementHelper.isBottomSlab(src.down())) {
state.setInput(InputOverrideHandler.Input.JUMP, true);
}
/*
if (thePlayer.getPosition0().getX() != from.getX() || thePlayer.getPosition0().getZ() != from.getZ()) {
Baritone.moveTowardsBlock(from);
@@ -157,7 +170,7 @@ public class MovementPillar extends Movement {
state.setInput(InputOverrideHandler.Input.SNEAK, true);
// Otherwise jump
if (numTicks > 40) {
if (numTicks > 20) {
double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5);
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
@@ -188,4 +201,4 @@ public class MovementPillar extends Movement {
return state;
}
}
}

View File

@@ -25,6 +25,7 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
@@ -37,30 +38,13 @@ import java.util.Objects;
public class MovementTraverse extends Movement {
private BlockPos[] against = new BlockPos[3];
/**
* Did we have to place a bridge block or was it always there
*/
private boolean wasTheBridgeBlockAlwaysThere = true;
public MovementTraverse(BlockPos from, BlockPos to) {
super(from, to, new BlockPos[]{to.up(), to}, new BlockPos[]{to.down()});
int i = 0;
if (!to.north().equals(from))
against[i++] = to.north().down();
if (!to.south().equals(from))
against[i++] = to.south().down();
if (!to.east().equals(from))
against[i++] = to.east().down();
if (!to.west().equals(from))
against[i] = to.west().down();
//note: do NOT add ability to place against .down().down()
super(from, to, new BlockPos[]{to.up(), to}, to.down());
}
@Override
@@ -73,20 +57,26 @@ public class MovementTraverse extends Movement {
protected double calculateCost(CalculationContext context) {
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
IBlockState destOn = BlockStateInterface.get(positionsToPlace[0]);
if (MovementHelper.canWalkOn(positionsToPlace[0], destOn)) {//this is a walk, not a bridge
IBlockState destOn = BlockStateInterface.get(positionToPlace);
Block srcDown = BlockStateInterface.getBlock(src.down());
if (MovementHelper.canWalkOn(positionToPlace, destOn)) {//this is a walk, not a bridge
double WC = WALK_ONE_BLOCK_COST;
if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) {
WC = WALK_ONE_IN_WATER_COST;
} else {
if (Blocks.SOUL_SAND.equals(destOn.getBlock())) {
if (destOn.getBlock() == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
}
if (Blocks.SOUL_SAND.equals(BlockStateInterface.get(src.down()).getBlock())) {
if (srcDown == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
}
}
if (MovementHelper.canWalkThrough(positionsToBreak[0], pb0) && MovementHelper.canWalkThrough(positionsToBreak[1], pb1)) {
double hardness1 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, true);
if (hardness1 >= COST_INF) {
return COST_INF;
}
double hardness2 = MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, false);
if (hardness1 == 0 && hardness2 == 0) {
if (WC == WALK_ONE_BLOCK_COST && context.canSprint()) {
// If there's nothing in the way, and this isn't water or soul sand, and we aren't sneak placing
// We can sprint =D
@@ -94,28 +84,36 @@ public class MovementTraverse extends Movement {
}
return WC;
}
// double hardness1 = blocksToBreak[0].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[0]);
// double hardness2 = blocksToBreak[1].getBlockHardness(Minecraft.getMinecraft().world, positionsToBreak[1]);
// Out.log("Can't walk through " + blocksToBreak[0] + " (hardness" + hardness1 + ") or " + blocksToBreak[1] + " (hardness " + hardness2 + ")");
return WC + getTotalHardnessOfBlocksToBreak(context);
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
hardness1 *= 5;
hardness2 *= 5;
}
return WC + hardness1 + hardness2;
} else {//this is a bridge, so we need to place a block
Block srcDown = BlockStateInterface.get(src.down()).getBlock();
if (srcDown instanceof BlockLadder || srcDown instanceof BlockVine) {
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
return COST_INF;
}
IBlockState pp0 = BlockStateInterface.get(positionsToPlace[0]);
if (pp0.getBlock().equals(Blocks.AIR) || (!BlockStateInterface.isWater(pp0.getBlock()) && MovementHelper.isReplacable(positionsToPlace[0], pp0))) {
if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(positionToPlace, destOn)) {
boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock());
if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) {
return COST_INF;
}
if (!context.hasThrowaway()) {
return COST_INF;
}
double WC = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock()) ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST;
for (BlockPos against1 : against) {
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
double WC = throughWater ? WALK_ONE_IN_WATER_COST : WALK_ONE_BLOCK_COST;
for (int i = 0; i < 4; i++) {
BlockPos against1 = dest.offset(HORIZONTALS[i]);
if (against1.equals(src)) {
continue;
}
against1 = against1.down();
if (MovementHelper.canPlaceAgainst(against1)) {
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
}
}
if (Blocks.SOUL_SAND.equals(srcDown)) {
return COST_INF; // can't sneak and backplace against soul sand =/
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && !((BlockSlab) srcDown).isDouble())) {
return COST_INF; // can't sneak and backplace against soul sand or half slabs =/
}
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are placing, we are sneaking
return WC + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
@@ -128,14 +126,10 @@ public class MovementTraverse extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
switch (state.getStatus()) {
case WAITING:
state.setStatus(MovementState.MovementStatus.RUNNING);
case RUNNING:
break;
default:
return state;
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
return state;
}
state.setInput(InputOverrideHandler.Input.SNEAK, false);
Block fd = BlockStateInterface.get(src.down()).getBlock();
boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine;
@@ -174,7 +168,7 @@ public class MovementTraverse extends Movement {
}
}
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionsToPlace[0]) || ladder;
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(positionToPlace) || ladder;
BlockPos whereAmI = playerFeet();
if (whereAmI.getY() != dest.getY() && !ladder) {
displayChatMessageRaw("Wrong Y coordinate");
@@ -193,7 +187,7 @@ public class MovementTraverse extends Movement {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
if (ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
if (whereAmI.getY() != dest.getY() && ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
new MovementPillar(dest.down(), dest).updateState(state); // i'm sorry
return state;
}
@@ -201,13 +195,29 @@ public class MovementTraverse extends Movement {
return state;
} else {
wasTheBridgeBlockAlwaysThere = false;
for (BlockPos against1 : against) {
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
for (int i = 0; i < 4; i++) {
BlockPos against1 = dest.offset(HORIZONTALS[i]);
if (against1.equals(src)) {
continue;
}
against1 = against1.down();
if (MovementHelper.canPlaceAgainst(against1)) {
if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block
displayChatMessageRaw("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
}
state.setInput(InputOverrideHandler.Input.SNEAK, true);
Block standingOn = BlockStateInterface.get(playerFeet().down()).getBlock();
if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof BlockSlab) { // see issue #118
double dist = Math.max(Math.abs(dest.getX() + 0.5 - player().posX), Math.abs(dest.getZ() + 0.5 - player().posZ));
if (dist < 0.85) { // 0.5 + 0.3 + epsilon
MovementHelper.moveTowards(state, dest);
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, false);
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
return state;
}
}
state.setInput(InputOverrideHandler.Input.MOVE_BACK, false);
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D;
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
@@ -215,7 +225,7 @@ public class MovementTraverse extends Movement {
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), against1) && Minecraft.getMinecraft().player.isSneaking()) {
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
if (LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
} else {
// Out.gui("Wrong. " + side + " " + LookBehaviorUtils.getSelectedBlock().get().offset(side) + " " + positionsToPlace[0], Out.Mode.Debug);
@@ -247,7 +257,7 @@ public class MovementTraverse extends Movement {
return state;
}
// Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt());
return state;
return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
} else {
MovementHelper.moveTowards(state, positionsToBreak[0]);
return state;
@@ -255,4 +265,15 @@ public class MovementTraverse extends Movement {
}
}
}
@Override
protected boolean prepared(MovementState state) {
if (playerFeet().equals(src) || playerFeet().equals(src.down())) {
Block block = BlockStateInterface.getBlock(src.down());
if (block == Blocks.LADDER || block == Blocks.VINE) {
state.setInput(InputOverrideHandler.Input.SNEAK, true);
}
}
return super.prepared(state);
}
}

View File

@@ -18,14 +18,14 @@
package baritone.pathing.path;
import baritone.pathing.movement.Movement;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import java.util.Collections;
import java.util.List;
public class CutoffPath implements IPath {
final List<BetterBlockPos> path;
final List<BlockPos> path;
final List<Movement> movements;
@@ -43,7 +43,7 @@ public class CutoffPath implements IPath {
}
@Override
public List<BetterBlockPos> positions() {
public List<BlockPos> positions() {
return Collections.unmodifiableList(path);
}

View File

@@ -22,7 +22,7 @@ import baritone.pathing.goals.Goal;
import baritone.pathing.movement.Movement;
import baritone.utils.Helper;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
@@ -47,7 +47,7 @@ public interface IPath extends Helper {
* All positions along the way.
* Should begin with the same as getSrc and end with the same as getDest
*/
List<BetterBlockPos> positions();
List<BlockPos> positions();
/**
* Number of positions in this path
@@ -65,7 +65,7 @@ public interface IPath extends Helper {
* @return
*/
default Movement subsequentMovement(BlockPos currentPosition) {
List<BetterBlockPos> pos = positions();
List<BlockPos> pos = positions();
List<Movement> movements = movements();
for (int i = 0; i < pos.size(); i++) {
if (currentPosition.equals(pos.get(i))) {
@@ -101,15 +101,15 @@ public interface IPath extends Helper {
/**
* Where does this path start
*/
default BetterBlockPos getSrc() {
default BlockPos getSrc() {
return positions().get(0);
}
/**
* Where does this path end
*/
default BetterBlockPos getDest() {
List<BetterBlockPos> pos = positions();
default BlockPos getDest() {
List<BlockPos> pos = positions();
return pos.get(pos.size() - 1);
}

View File

@@ -18,12 +18,11 @@
package baritone.pathing.path;
import baritone.Baritone;
import baritone.event.events.TickEvent;
import baritone.pathing.movement.ActionCosts;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementState;
import baritone.api.event.events.TickEvent;
import baritone.pathing.movement.*;
import baritone.pathing.movement.movements.MovementDescend;
import baritone.pathing.movement.movements.MovementDiagonal;
import baritone.pathing.movement.movements.MovementFall;
import baritone.pathing.movement.movements.MovementTraverse;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
@@ -45,8 +44,9 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*;
* @author leijurv
*/
public class PathExecutor implements Helper {
private static final double MAX_MAX_DIST_FROM_PATH = 3;
private static final double MAX_DIST_FROM_PATH = 2;
private static final double MAX_TICKS_AWAY = 200; // ten seconds
private static final double MAX_TICKS_AWAY = 200; // ten seconds. ok to decrease this, but it must be at least 110, see issue #102
private final IPath path;
private int pathPosition;
private int ticksAway;
@@ -90,7 +90,7 @@ public class PathExecutor implements Helper {
if (!whereShouldIBe.equals(whereAmI)) {
//System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 2 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
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))) {
displayChatMessageRaw("Skipping back " + (pathPosition - i) + " steps, to " + i);
int previousPos = pathPosition;
@@ -131,6 +131,17 @@ public class PathExecutor implements Helper {
} else {
ticksAway = 0;
}
if (distanceFromPath > MAX_MAX_DIST_FROM_PATH) {
if (!(path.movements().get(pathPosition) instanceof MovementFall)) { // might be midair
if (pathPosition == 0 || !(path.movements().get(pathPosition - 1) instanceof MovementFall)) { // might have overshot the landing
displayChatMessageRaw("too far from path");
pathPosition = path.length() + 3;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
failed = true;
return false;
}
}
}
//this commented block is literally cursed.
/*Out.log(actions.get(pathPosition));
if (pathPosition < actions.size() - 1) {//if there are two ActionBridges in a row and they are at right angles, walk diagonally. This makes it so you walk at 45 degrees along a zigzag path instead of doing inefficient zigging and zagging
@@ -163,7 +174,7 @@ public class PathExecutor implements Helper {
}
}
}*/
long start = System.currentTimeMillis();
long start = System.nanoTime() / 1000000L;
for (int i = pathPosition - 10; i < pathPosition + 10; i++) {
if (i >= 0 && i < path.movements().size()) {
Movement m = path.movements().get(i);
@@ -198,24 +209,17 @@ public class PathExecutor implements Helper {
toWalkInto = newWalkInto;
recalcBP = false;
}
long end = System.currentTimeMillis();
long end = System.nanoTime() / 1000000L;
if (end - start > 0) {
//displayChatMessageRaw("Recalculating break and place took " + (end - start) + "ms");
}
Movement movement = path.movements().get(pathPosition);
double currentCost = movement.recalculateCost();
if (currentCost >= ActionCosts.COST_INF) {
displayChatMessageRaw("Something has changed in the world and this movement has become impossible. Cancelling.");
pathPosition = path.length() + 3;
failed = true;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
return true;
}
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
costEstimateIndex = pathPosition;
currentMovementInitialCostEstimate = currentCost; // do this only once, when the movement starts
// 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
currentMovementInitialCostEstimate = movement.getCost(null);
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
if (path.movements().get(pathPosition + i).recalculateCost() >= ActionCosts.COST_INF) {
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF) {
displayChatMessageRaw("Something has changed in the world and a future movement has become impossible. Cancelling.");
pathPosition = path.length() + 3;
failed = true;
@@ -224,6 +228,14 @@ public class PathExecutor implements Helper {
}
}
}
double currentCost = movement.recalculateCost();
if (currentCost >= ActionCosts.COST_INF) {
displayChatMessageRaw("Something has changed in the world and this movement has become impossible. Cancelling.");
pathPosition = path.length() + 3;
failed = true;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
return true;
}
MovementState.MovementStatus movementStatus = movement.update();
if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
displayChatMessageRaw("Movement returns status " + movementStatus);
@@ -259,7 +271,7 @@ public class PathExecutor implements Helper {
}
private void sprintIfRequested() {
if (!Baritone.settings().allowSprint.get()) {
if (!new CalculationContext().canSprint()) {
player().setSprinting(false);
return;
}
@@ -285,7 +297,7 @@ public class PathExecutor implements Helper {
}
}
if (next instanceof MovementTraverse) {
if (next.getDirection().down().equals(movement.getDirection())) {
if (next.getDirection().down().equals(movement.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
if (playerFeet().equals(movement.getDest())) {
pathPosition++;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();

View File

@@ -18,50 +18,92 @@
package baritone.utils;
import baritone.Baritone;
import baritone.chunk.CachedRegion;
import baritone.chunk.WorldData;
import baritone.chunk.WorldProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.Chunk;
/**
* Wraps get for chuck caching capability
*
* @author leijurv
*/
public class BlockStateInterface implements Helper {
public static IBlockState get(BlockPos pos) { // wrappers for chunk caching capability
private static Chunk prev = null;
private static CachedRegion prevCached = null;
private static IBlockState AIR = Blocks.AIR.getDefaultState();
public static final Block waterFlowing = Blocks.FLOWING_WATER;
public static final Block waterStill = Blocks.WATER;
public static final Block lavaFlowing = Blocks.FLOWING_LAVA;
public static final Block lavaStill = Blocks.LAVA;
public static IBlockState get(BlockPos pos) {
return get(pos.getX(), pos.getY(), pos.getZ());
}
public static IBlockState get(int x, int y, int z) {
// Invalid vertical position
if (pos.getY() < 0 || pos.getY() >= 256)
return Blocks.AIR.getDefaultState();
if (y < 0 || y >= 256) {
return AIR;
}
if (!Baritone.settings().pathThroughCachedOnly.get()) {
Chunk chunk = mc.world.getChunk(pos);
if (chunk.isLoaded()) {
return chunk.getBlockState(pos);
Chunk cached = prev;
// there's great cache locality in block state lookups
// generally it's within each movement
// if it's the same chunk as last time
// we can just skip the mc.world.getChunk lookup
// which is a Long2ObjectOpenHashMap.get
if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) {
return cached.getBlockState(x, y, z);
}
Chunk chunk = mc.world.getChunk(x >> 4, z >> 4);
if (chunk.isLoaded()) {
prev = chunk;
return chunk.getBlockState(x, y, z);
}
}
// same idea here, skip the Long2ObjectOpenHashMap.get if at all possible
// except here, it's 512x512 tiles instead of 16x16, so even better repetition
CachedRegion cached = prevCached;
if (cached != null && cached.getX() == x >> 9 && cached.getZ() == z >> 9) {
IBlockState type = cached.getBlock(x & 511, y, z & 511);
if (type == null) {
return AIR;
}
return type;
}
WorldData world = WorldProvider.INSTANCE.getCurrentWorld();
if (world != null) {
IBlockState type = world.cache.getBlock(pos);
if (type != null) {
return type;
CachedRegion region = world.cache.getRegion(x >> 9, z >> 9);
if (region != null) {
prevCached = region;
IBlockState type = region.getBlock(x & 511, y, z & 511);
if (type != null) {
return type;
}
}
}
return AIR;
}
return Blocks.AIR.getDefaultState();
public static void clearCachedChunk() {
prev = null;
prevCached = null;
}
public static Block getBlock(BlockPos pos) {
return get(pos).getBlock();
}
public static final Block waterFlowing = Blocks.FLOWING_WATER;
public static final Block waterStill = Blocks.WATER;
public static final Block lavaFlowing = Blocks.FLOWING_LAVA;
public static final Block lavaStill = Blocks.LAVA;
/**
* Returns whether or not the specified block is
@@ -71,7 +113,7 @@ public class BlockStateInterface implements Helper {
* @return Whether or not the block is water
*/
public static boolean isWater(Block b) {
return waterFlowing.equals(b) || waterStill.equals(b);
return b == waterFlowing || b == waterStill;
}
/**
@@ -86,7 +128,7 @@ public class BlockStateInterface implements Helper {
}
public static boolean isLava(Block b) {
return lavaFlowing.equals(b) || lavaStill.equals(b);
return b == lavaFlowing || b == lavaStill;
}
/**
@@ -105,18 +147,4 @@ public class BlockStateInterface implements Helper {
&& state.getPropertyKeys().contains(BlockLiquid.LEVEL)
&& state.getValue(BlockLiquid.LEVEL) != 0;
}
public static boolean isAir(BlockPos pos) {
return BlockStateInterface.getBlock(pos).equals(Blocks.AIR);
}
public static boolean isAir(IBlockState state) {
return state.getBlock().equals(Blocks.AIR);
}
static boolean canFall(BlockPos pos) {
return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling;
}
}

View File

@@ -19,25 +19,27 @@ package baritone.utils;
import baritone.Baritone;
import baritone.Settings;
import baritone.api.event.events.ChatEvent;
import baritone.behavior.Behavior;
import baritone.behavior.impl.FollowBehavior;
import baritone.behavior.impl.MineBehavior;
import baritone.behavior.impl.PathingBehavior;
import baritone.chunk.ChunkPacker;
import baritone.chunk.Waypoint;
import baritone.chunk.WorldProvider;
import baritone.event.events.ChatEvent;
import baritone.map.Map;
import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.goals.*;
import baritone.pathing.movement.ActionCosts;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.Block;
import baritone.pathing.movement.MovementHelper;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.*;
import java.util.stream.Collectors;
public class ExampleBaritoneControl extends Behavior {
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
@@ -53,7 +55,9 @@ public class ExampleBaritoneControl extends Behavior {
@Override
public void onSendChatMessage(ChatEvent event) {
if (!Baritone.settings().chatControl.get()) {
return;
if (!Baritone.settings().removePrefix.get()) {
return;
}
}
String msg = event.getMessage();
if (Baritone.settings().prefix.get()) {
@@ -100,16 +104,34 @@ public class ExampleBaritoneControl extends Behavior {
return;
}
if (msg.equals("path")) {
PathingBehavior.INSTANCE.path();
if (!PathingBehavior.INSTANCE.path()) {
if (PathingBehavior.INSTANCE.getGoal() == null) {
displayChatMessageRaw("No goal.");
} else {
if (PathingBehavior.INSTANCE.getGoal().isInGoal(playerFeet())) {
displayChatMessageRaw("Already in goal");
} else {
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
}
}
}
event.cancel();
return;
}
if (msg.toLowerCase().equals("cancel")) {
PathingBehavior.INSTANCE.cancel();
FollowBehavior.INSTANCE.cancel();
MineBehavior.INSTANCE.cancel();
event.cancel();
displayChatMessageRaw("ok canceled");
return;
}
if (msg.toLowerCase().equals("forcecancel")) {
AbstractNodeCostSearch.forceCancel();
event.cancel();
displayChatMessageRaw("ok force canceled");
return;
}
if (msg.toLowerCase().equals("invert")) {
Goal goal = PathingBehavior.INSTANCE.getGoal();
BlockPos runAwayFrom;
@@ -128,7 +150,21 @@ public class ExampleBaritoneControl extends Behavior {
return false;
}
});
PathingBehavior.INSTANCE.path();
if (!PathingBehavior.INSTANCE.path()) {
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
}
event.cancel();
return;
}
if (msg.toLowerCase().equals("follow")) {
Optional<Entity> entity = MovementHelper.whatEntityAmILookingAt();
if (!entity.isPresent()) {
displayChatMessageRaw("You aren't looking at an entity bruh");
event.cancel();
return;
}
FollowBehavior.INSTANCE.follow(entity.get());
displayChatMessageRaw("Following " + entity.get());
event.cancel();
return;
}
@@ -158,28 +194,16 @@ public class ExampleBaritoneControl extends Behavior {
return;
}
if (msg.toLowerCase().startsWith("mine")) {
String blockType = msg.toLowerCase().substring(4).trim();
List<BlockPos> locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(blockType, 1, 1));
if (locs.isEmpty()) {
displayChatMessageRaw("No locations known");
event.cancel();
return;
String[] blockTypes = msg.toLowerCase().substring(4).trim().split(" ");
for (String s : blockTypes) {
if (ChunkPacker.stringToBlock(s) == null) {
displayChatMessageRaw(s + " isn't a valid block name");
event.cancel();
return;
}
}
BlockPos playerFeet = playerFeet();
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
// remove any that are within loaded chunks that aren't actually what we want
locs.removeAll(locs.stream()
.filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk))
.filter(pos -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(blockType))
.collect(Collectors.toList()));
if (locs.size() > 30) {
displayChatMessageRaw("Pathing to any of closest 30");
locs = locs.subList(0, 30);
}
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new)));
PathingBehavior.INSTANCE.path();
MineBehavior.INSTANCE.mine(blockTypes);
displayChatMessageRaw("Started mining blocks of type " + Arrays.toString(blockTypes));
event.cancel();
return;
}
@@ -196,7 +220,7 @@ public class ExampleBaritoneControl extends Behavior {
// for example, "show deaths"
waypointType = waypointType.substring(0, waypointType.length() - 1);
}
Waypoint.Tag tag = Waypoint.TAG_MAP.get(waypointType);
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
if (tag == null) {
displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
event.cancel();
@@ -215,14 +239,26 @@ public class ExampleBaritoneControl extends Behavior {
}
if (msg.toLowerCase().startsWith("goto")) {
String waypointType = msg.toLowerCase().substring(4).trim();
if (waypointType.endsWith("s")) {
if (waypointType.endsWith("s") && Waypoint.Tag.fromString(waypointType.substring(0, waypointType.length() - 1)) != null) {
// for example, "show deaths"
waypointType = waypointType.substring(0, waypointType.length() - 1);
}
Waypoint.Tag tag = Waypoint.TAG_MAP.get(waypointType);
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
if (tag == null) {
displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
String mining = waypointType;
//displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
event.cancel();
if (ChunkPacker.stringToBlock(mining) == null) {
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
return;
}
List<BlockPos> locs = MineBehavior.scanFor(Arrays.asList(mining), 64);
if (locs.isEmpty()) {
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
return;
}
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
PathingBehavior.INSTANCE.path();
return;
}
Waypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().waypoints.getMostRecentByTag(tag);
@@ -233,7 +269,11 @@ public class ExampleBaritoneControl extends Behavior {
}
Goal goal = new GoalBlock(waypoint.location);
PathingBehavior.INSTANCE.setGoal(goal);
PathingBehavior.INSTANCE.path();
if (!PathingBehavior.INSTANCE.path()) {
if (!goal.isInGoal(playerFeet())) {
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
}
}
event.cancel();
return;
}
@@ -272,8 +312,11 @@ public class ExampleBaritoneControl extends Behavior {
return;
}
if (msg.toLowerCase().equals("costs")) {
Movement[] movements = AStarPathFinder.getConnectedPositions(new BetterBlockPos(playerFeet()), new CalculationContext());
Movement[] movements = AStarPathFinder.getConnectedPositions(new BlockPos(playerFeet()), new CalculationContext());
List<Movement> moves = new ArrayList<>(Arrays.asList(movements));
while (moves.contains(null)) {
moves.remove(null);
}
moves.sort(Comparator.comparingDouble(movement -> movement.getCost(new CalculationContext())));
for (Movement move : moves) {
String[] parts = move.getClass().toString().split("\\.");
@@ -287,7 +330,7 @@ public class ExampleBaritoneControl extends Behavior {
event.cancel();
return;
}
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getByValueType(Boolean.class);
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getAllValuesByType(Boolean.class);
for (Settings.Setting<Boolean> setting : toggleable) {
if (msg.equalsIgnoreCase(setting.getName())) {
setting.value ^= true;
@@ -329,9 +372,6 @@ public class ExampleBaritoneControl extends Behavior {
}
}
}
if (msg.toLowerCase().equals("map")) {
Map.INSTANCE.writeImage();
}
if (Baritone.settings().byLowerName.containsKey(msg.toLowerCase())) {
Settings.Setting<?> setting = Baritone.settings().byLowerName.get(msg.toLowerCase());
displayChatMessageRaw(setting.toString());

View File

@@ -18,6 +18,7 @@
package baritone.utils;
import baritone.Baritone;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.WorldClient;
@@ -33,7 +34,13 @@ import net.minecraft.util.text.TextFormatting;
*/
public interface Helper {
ITextComponent MESSAGE_PREFIX = new TextComponentString("§5[§dBaritone§5]§7");
ITextComponent MESSAGE_PREFIX = new TextComponentString(String.format(
"%s[%sBaritone%s]%s",
TextFormatting.DARK_PURPLE,
TextFormatting.LIGHT_PURPLE,
TextFormatting.DARK_PURPLE,
TextFormatting.GRAY
));
Minecraft mc = Minecraft.getMinecraft();
@@ -47,10 +54,11 @@ public interface Helper {
default BlockPos playerFeet() {
// TODO find a better way to deal with soul sand!!!!!
return new BlockPos(player().posX, player().posY + 0.1251, player().posZ);
/*if (BlockStateInterface.get(feet).getBlock().equals(Blocks.SOUL_SAND) && player().posY > feet.getY() + 0.874999) {
BlockPos feet = new BlockPos(player().posX, player().posY + 0.1251, player().posZ);
if (BlockStateInterface.get(feet).getBlock() instanceof BlockSlab) {
return feet.up();
}*/
}
return feet;
}
default Vec3d playerFeetAsVec() {

View File

@@ -19,10 +19,12 @@ package baritone.utils;
import baritone.Baritone;
import baritone.pathing.goals.Goal;
import baritone.pathing.goals.GoalBlock;
import baritone.pathing.goals.GoalComposite;
import baritone.pathing.goals.GoalTwoBlocks;
import baritone.pathing.goals.GoalXZ;
import baritone.pathing.path.IPath;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
@@ -34,6 +36,7 @@ import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
import java.awt.*;
import java.util.Collection;
@@ -60,7 +63,7 @@ public final class PathRenderer implements Helper {
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
List<BetterBlockPos> positions = path.positions();
List<BlockPos> positions = path.positions();
int next;
Tessellator tessellator = Tessellator.getInstance();
fadeStart += startIndex;
@@ -182,17 +185,25 @@ public final class PathRenderer implements Helper {
double maxY;
double y1;
double y2;
if (goal instanceof GoalBlock) {
BlockPos goalPos = ((GoalBlock) goal).getGoalPos();
if (goal instanceof IGoalRenderPos) {
BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos();
minX = goalPos.getX() + 0.002 - renderPosX;
maxX = goalPos.getX() + 1 - 0.002 - renderPosX;
minZ = goalPos.getZ() + 0.002 - renderPosZ;
maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ;
double y = Math.sin((System.currentTimeMillis() % 2000L) / 2000F * Math.PI * 2);
double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
if (goal instanceof GoalTwoBlocks) {
y /= 2;
}
y1 = 1 + y + goalPos.getY() - renderPosY;
y2 = 1 - y + goalPos.getY() - renderPosY;
minY = goalPos.getY() - renderPosY;
maxY = minY + 2;
if (goal instanceof GoalTwoBlocks) {
y1 -= 0.5;
y2 -= 0.5;
maxY--;
}
} else if (goal instanceof GoalXZ) {
GoalXZ goalPos = (GoalXZ) goal;
@@ -205,8 +216,12 @@ public final class PathRenderer implements Helper {
y2 = 0;
minY = 0 - renderPosY;
maxY = 256 - renderPosY;
} else if (goal instanceof GoalComposite) {
for (Goal g : ((GoalComposite) goal).goals()) {
drawLitDankGoalBox(player, g, partialTicks, color);
}
return;
} else {
// TODO GoalComposite
return;
}

View File

@@ -18,6 +18,9 @@
package baritone.utils;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import static baritone.behavior.impl.LookBehaviorUtils.calcVec3dFromRotation;
/**
* @author Brady
@@ -44,4 +47,16 @@ public final class RayTraceUtils implements Helper {
return result;
}
public static RayTraceResult rayTraceTowards(Rotation rotation) {
double blockReachDistance = mc.playerController.getBlockReachDistance();
Vec3d start = mc.player.getPositionEyes(1.0F);
Vec3d direction = calcVec3dFromRotation(rotation);
Vec3d end = start.add(
direction.x * blockReachDistance,
direction.y * blockReachDistance,
direction.z * blockReachDistance
);
return mc.world.rayTraceBlocks(start, end, false, false, true);
}
}

View File

@@ -18,92 +18,33 @@
package baritone.utils;
import baritone.Baritone;
import baritone.event.events.ItemSlotEvent;
import baritone.event.listener.AbstractGameEventListener;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.item.Item;
import net.minecraft.item.ItemAir;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Enchantments;
import net.minecraft.init.MobEffects;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
/**
* A cached list of the best tools on the hotbar for any block
*
* @author avecowa, Brady
* @author avecowa, Brady, leijurv
*/
public class ToolSet implements Helper {
/**
* Instance of the internal event listener used to hook into Baritone's event bus
*/
private static final InternalEventListener INTERNAL_EVENT_LISTENER = new InternalEventListener();
static {
Baritone.INSTANCE.getGameEventHandler().registerEventListener(INTERNAL_EVENT_LISTENER);
}
/**
* A list of tools on the hotbar that should be considered.
* Note that if there are no tools on the hotbar this list will still have one (null) entry.
*/
private List<ItemTool> tools;
/**
* A mapping from the tools array to what hotbar slots the tool is actually in.
* tools.get(i) will be on your hotbar in slot slots.get(i)
*/
private List<Byte> slots;
/**
* A mapping from a block to which tool index is best for it.
* The values in this map are *not* hotbar slots indexes, they need to be looked up in slots
* in order to be converted into hotbar slots.
*/
private Map<Block, Byte> slotCache = new HashMap<>();
/**
* A cache mapping a {@link IBlockState} to how long it will take to break
* A cache mapping a {@link Block} to how long it will take to break
* with this toolset, given the optimum tool is used.
*/
private Map<IBlockState, Double> breakStrengthCache = new HashMap<>();
private Map<Block, Double> breakStrengthCache = new HashMap<>();
/**
* Create a toolset from the current player's inventory (but don't calculate any hardness values just yet)
*/
public ToolSet() {
EntityPlayerSP p = Minecraft.getMinecraft().player;
NonNullList<ItemStack> inv = p.inventory.mainInventory;
tools = new ArrayList<>();
slots = new ArrayList<>();
boolean fnull = false;
for (byte i = 0; i < 9; i++) {
if (!fnull || ((!(inv.get(i).getItem() instanceof ItemAir)) && inv.get(i).getItem() instanceof ItemTool)) {
tools.add(inv.get(i).getItem() instanceof ItemTool ? (ItemTool) inv.get(i).getItem() : null);
slots.add(i);
fnull |= (inv.get(i).getItem() instanceof ItemAir) || (!inv.get(i).getItem().isDamageable());
}
}
}
/**
* A caching wrapper around getBestToolIndex
*
* @param state the blockstate to be mined
* @return get which tool on the hotbar is best for mining it
*/
public Item getBestTool(IBlockState state) {
return tools.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
}
public ToolSet() {}
/**
* Calculate which tool on the hotbar is best for mining
@@ -111,15 +52,11 @@ public class ToolSet implements Helper {
* @param b the blockstate to be mined
* @return a byte indicating the index in the tools array that worked best
*/
private byte getBestToolIndex(IBlockState b) {
public byte getBestSlot(IBlockState b) {
byte best = 0;
float value = -1;
for (byte i = 0; i < tools.size(); i++) {
Item item = tools.get(i);
if (item == null)
continue;
float v = item.getDestroySpeed(new ItemStack(item), b);
double value = -1;
for (byte i = 0; i < 9; i++) {
double v = calculateStrVsBlock(i, b);
if (v > value || value == -1) {
value = v;
best = i;
@@ -128,62 +65,66 @@ public class ToolSet implements Helper {
return best;
}
/**
* Get which hotbar slot should be selected for fastest mining
*
* @param state the blockstate to be mined
* @return a byte indicating which hotbar slot worked best
*/
public byte getBestSlot(IBlockState state) {
return slots.get(slotCache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
}
/**
* Using the best tool on the hotbar, how long would it take to mine this block
*
* @param state the blockstate to be mined
* @param pos the blockpos to be mined
* @return how long it would take in ticks
*/
public double getStrVsBlock(IBlockState state, BlockPos pos) {
return this.breakStrengthCache.computeIfAbsent(state, s -> calculateStrVsBlock(s, pos));
public double getStrVsBlock(IBlockState state) {
return this.breakStrengthCache.computeIfAbsent(state.getBlock(), b -> calculateStrVsBlock(getBestSlot(state), state));
}
/**
* Calculates how long would it take to mine the specified block given the best tool
* in this toolset is used.
* in this toolset is used. A negative value is returned if the specified block is unbreakable.
*
* @param state the blockstate to be mined
* @param pos the blockpos to be mined
* @return how long it would take in ticks
*/
private double calculateStrVsBlock(IBlockState state, BlockPos pos) {
private double calculateStrVsBlock(byte slot, IBlockState state) {
// Calculate the slot with the best item
byte slot = this.getBestSlot(state);
ItemStack contents = player().inventory.getStackInSlot(slot);
INTERNAL_EVENT_LISTENER.setOverrideSlot(slot);
// Calculate the relative hardness of the block to the player
float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos);
// Restore the old slot
INTERNAL_EVENT_LISTENER.setOverrideSlot(-1);
return hardness;
}
private static final class InternalEventListener implements AbstractGameEventListener {
private int overrideSlot;
@Override
public void onQueryItemSlotForBlocks(ItemSlotEvent event) {
if (this.overrideSlot >= 0)
event.setSlot(this.overrideSlot);
float blockHard = state.getBlockHardness(null, null);
if (blockHard < 0) {
return -1;
}
final void setOverrideSlot(int overrideSlot) {
this.overrideSlot = overrideSlot;
float speed = contents.getDestroySpeed(state);
if (speed > 1) {
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents);
if (effLevel > 0 && !contents.isEmpty()) {
speed += effLevel * effLevel + 1;
}
}
if (Baritone.settings().considerPotionEffects.get()) {
if (player().isPotionActive(MobEffects.HASTE)) {
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
}
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
case 0:
speed *= 0.3;
break;
case 1:
speed *= 0.09;
break;
case 2:
speed *= 0.0027;
break;
default:
speed *= 0.00081;
break;
}
}
}
speed /= blockHard;
if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) {
return speed / 30;
} else {
return speed / 100;
}
}
}

View File

@@ -54,9 +54,9 @@ public final class Utils {
*/
public static Rotation calcRotationFromVec3d(Vec3d orig, Vec3d dest) {
double[] delta = {orig.x - dest.x, orig.y - dest.y, orig.z - dest.z};
double yaw = Math.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 pitch = Math.atan2(delta[1], dist);
double pitch = MathHelper.atan2(delta[1], dist);
return new Rotation(
(float) radToDeg(yaw),
(float) radToDeg(pitch)

View File

@@ -15,11 +15,7 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins.accessor;
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
package baritone.utils.accessor;
import java.io.File;
@@ -27,8 +23,7 @@ import java.io.File;
* @author Brady
* @since 8/4/2018 11:36 AM
*/
@Mixin(AnvilChunkLoader.class)
public interface IAnvilChunkLoader {
@Accessor File getChunkSaveLocation();
File getChunkSaveLocation();
}

View File

@@ -15,19 +15,15 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins.accessor;
package baritone.utils.accessor;
import net.minecraft.world.chunk.storage.IChunkLoader;
import net.minecraft.world.gen.ChunkProviderServer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.gen.Accessor;
/**
* @author Brady
* @since 8/4/2018 11:33 AM
*/
@Mixin(ChunkProviderServer.class)
public interface IChunkProviderServer {
@Accessor IChunkLoader getChunkLoader();
IChunkLoader getChunkLoader();
}

View File

@@ -0,0 +1,24 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.interfaces;
import net.minecraft.util.math.BlockPos;
public interface IGoalRenderPos {
BlockPos getGoalPos();
}

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