Compare commits

...

146 Commits

Author SHA1 Message Date
Leijurv
dbfb44d049 deprecate 1.16.5 2023-08-14 13:40:28 -07:00
Leijurv
9df406de6b v1.6.5 2023-08-14 13:34:38 -07:00
leijurv
8ceb89d021 Merge pull request #4028 from ZacSharp/1.16.5-update
Merge master into 1.16.5
2023-07-05 11:47:27 -07:00
ZacSharp
8e58dd9e64 Merge branch '1.15.2' into 1.16.5 2023-07-04 16:48:41 +02:00
ZacSharp
45abbb7fa1 Merge branch '1.14.4' into 1.15.2 2023-07-04 16:48:36 +02:00
ZacSharp
1d983d5fdc Merge branch '1.13.2' into 1.14.4 2023-07-04 16:48:31 +02:00
ZacSharp
be54b8ee5b Merge branch 'master' into 1.13.2 2023-07-04 16:47:58 +02:00
Brady
6654476da4 Make blockFreeLook depend on freeLook 2023-07-02 19:59:26 -05:00
Leijurv
8211ae4af5 memory leaks are joever 2023-06-29 21:59:31 -07:00
Brady
15f4253b3d Clamp pitch to normal range 2023-06-24 21:48:44 -07:00
leijurv
24b0bd2edf Merge pull request #4019 from ZacSharp/pr/misc/rotation/fixMouseStuck
Fix getting stuck due to impossible rotations
2023-06-23 21:59:34 -07:00
ZacSharp
e3a1ac85cc Fix waiting for impossible rotations 2023-06-23 04:22:35 +02:00
leijurv
1ea071de09 Merge pull request #4015 from cabaletta/pr/deterministicLookTarget
API for rotations produced by LookBehavior
2023-06-22 19:21:02 -07:00
Brady
c9a18caf49 Register LookBehavior first
Since there's no event priority system, this is necessary to ensure anything else listening to the PRE `TickEvent` can accurately simulate rotations.
2023-06-22 20:38:00 -05:00
Brady
bfae100cb9 Create ITickableAimProcessor 2023-06-22 20:35:22 -05:00
leijurv
0dd38ca65a Merge pull request #4012 from ZacSharp/pr/commands/usableTabCompletion
Fix tab completion with brigadier
2023-06-21 18:54:20 -07:00
leijurv
b0ebbf4dfb Merge pull request #4007 from ZacSharp/pr/schematics/mask/fixBinaryOperatorMaskOOB
Don't call `partOfMask` out of bounds in `BinaryOperatorMask`
2023-06-21 18:53:58 -07:00
leijurv
9d12a4ba3d Merge pull request #4008 from ZacSharp/pr/pathing/goals/implHashCode
Implement `hashCode` for goals
2023-06-21 18:53:36 -07:00
leijurv
6dc953631b Merge pull request #4006 from ZacSharp/pr/blockOptionalMeta/tabCompleteProperties
Tab completion improvements
2023-06-21 18:53:06 -07:00
Brady
0682e63707 Apply processor to RotationMoveEvent 2023-06-21 17:39:04 -05:00
Brady
7e426bd2e8 AimProcessor API 2023-06-21 17:35:47 -05:00
Brady
367ce5fa17 cherry pick Allow freeLook when using elytra 2023-06-21 14:55:40 -05:00
ZacSharp
41d730fb04 Forgot to include target pos 2023-06-20 03:20:44 +02:00
ZacSharp
30278a1c52 Implement hashCode for goals 2023-06-20 02:44:29 +02:00
ZacSharp
d87d1ab9b5 Don't call partOfMask out of bounds 2023-06-20 02:00:08 +02:00
ZacSharp
31c9072970 Forgot to git add 2023-06-20 01:36:09 +02:00
ZacSharp
f7a20a3acf Don't swallow random exceptions, don't bother with CommandExceptions 2023-06-20 01:32:18 +02:00
ZacSharp
b111fd2f3e Don't construct malformed ResourceLocations
Later mc versions throw an exception when you construct a malformed `ResourceLocation`.
2023-06-20 00:02:56 +02:00
ZacSharp
84777c2437 Don't complete more than what's supported 2023-06-20 00:01:33 +02:00
ZacSharp
13742df877 Complete the last argument, not the first one 2023-06-20 00:00:52 +02:00
ZacSharp
f55f7f19b4 Tab complete the datatype which will be parsed 2023-06-19 23:50:42 +02:00
ZacSharp
e43200865c Move this to the right place 2023-06-19 23:48:07 +02:00
ZacSharp
1de2d55965 Tab complete block properties 2023-06-19 23:05:46 +02:00
Leijurv
6c8f2698d6 cherry pick remainWithExistingLookDirection from fork 2023-06-18 19:31:51 -07:00
leijurv
411c43d90e Merge pull request #3992 from ZacSharp/pr/blockOptionalMeta/useStackHashesInBlockOptionalMetaLookup
Actually use stack hashes
2023-06-18 17:25:53 -07:00
leijurv
bac5fd7438 Merge pull request #3999 from ZacSharp/pr/setting/tabCompleteSetingsLoadPath
Tab complete the file argument for `#settings load`
2023-06-18 17:25:27 -07:00
Brady Hahn
4df31a3fbb Merge pull request #4000 from ZacSharp/pr/selection/fixHorizontalCylinders
Fix `CylinderMask` with horizontal alignment
2023-06-18 19:02:07 -05:00
ZacSharp
5fd915ab8a Tab complete the file argument for #settings load 2023-06-18 22:27:57 +02:00
ZacSharp
6aeb73b5bd Fix CylinderMask with horizontal alignment 2023-06-18 19:18:46 +02:00
leijurv
a665605a5a Merge pull request #3991 from ZacSharp/pr/guiclick/fixSelectionPreview
Fix `GuiClick` not rendering the outline of the selection being made
2023-06-16 20:29:25 -07:00
ZacSharp
e00e0032b4 Actually use stack hashes 2023-06-17 01:40:19 +02:00
ZacSharp
f1bf1e8663 Use IRenderer setup methods 2023-06-17 00:36:35 +02:00
ZacSharp
ef4cdfd646 Fix render bug caused by color bug fix 2023-06-16 19:22:37 +02:00
leijurv
c86643874d Merge pull request #3936 from ZacSharp/pr/builder/fixPlaceableComparison
Fix considering states unplaceable regardless of buildIgnoreProperties
2023-06-15 19:36:25 -07:00
Brady
26a2945696 remove comment 2023-06-14 19:13:07 -05:00
leijurv
04b09fbfbd Merge pull request #3985 from cabaletta/pr/deprecateHelperMc
Deprecate `Helper.mc`
2023-06-14 16:20:38 -07:00
Brady
f14caa3778 Fix cringe shift by injector 2023-06-14 17:32:47 -05:00
Brady
ea9245ad26 missed that 😩 2023-06-14 14:23:24 -05:00
Brady
8534e1ba55 💚 appease codacy 2023-06-14 14:04:34 -05:00
Brady
ae66004b80 Custom registration of Baritone instances from Minecraft 2023-06-14 13:52:27 -05:00
Brady
5b39c0dd96 Remove getMinecraft() from BlockStateInterface 2023-06-14 12:18:50 -05:00
Brady
2db2d8be59 Steal BaritoneList from bot-system 2023-06-14 02:00:10 -05:00
Brady
75d47bb110 Fix all usages of Helper.mc 2023-06-14 01:53:29 -05:00
leijurv
3662b3fdf1 nope 2023-06-13 21:33:12 -07:00
leijurv
b03d31e990 will github let me do this 2023-06-13 21:32:57 -07:00
leijurv
54f0a3c14c marginally better 2023-06-13 21:32:21 -07:00
leijurv
6a80b0d4ff forgot github markdown is stupid 2023-06-13 21:31:49 -07:00
leijurv
5e724c1e3a making these clickable was a mistake 2023-06-13 21:31:10 -07:00
leijurv
88e604426c 1.20.1 2023-06-13 21:30:31 -07:00
Brady
dd7b492b0c registerBehavior is called explicitly now 2023-06-13 23:21:20 -05:00
Brady
c7f4e366e2 Remove mc references from WorldProvider
Also refactored a bit, should be a lot easier to merge upwards to new game versions
2023-06-13 23:07:26 -05:00
Brady
382f82b0e0 Move Minecraft to IPlayerContext 2023-06-13 21:17:42 -05:00
Brady
ab3d9e9c47 I LOVE final 2023-06-13 21:13:34 -05:00
Brady
714ebb2c2d Deprecate Helper.mc and begin to replace usages 2023-06-13 18:24:31 -05:00
leijurv
1b254a4811 Merge pull request #3979 from cabaletta/pr/feature/blockFreeLook
Allow free looking when breaking and placing blocks
2023-06-13 10:32:18 -07:00
Brady
76fe0d14d3 Simplify some player context references 2023-06-12 21:13:10 -05:00
Brady
2022d33d03 Fix incorrect references to player and world 2023-06-12 21:12:49 -05:00
Brady
c8b8deb3d6 Ensure angle delta is producible with mouse movement 2023-06-12 21:04:30 -05:00
Brady
4885d49d20 Reorganize code 2023-06-12 20:00:03 -05:00
Brady
13fc58933d Don't bother returning serverRotations if no free look 2023-06-12 19:03:03 -05:00
Brady
c217a34f13 🐛 fix batch render color bug by backporting 1.17+ render code 2023-06-12 17:06:11 -05:00
leijurv
15182cb151 Merge pull request #3984 from cabaletta/pr/bugfix/censorCoordinatesRecalc
Fix `censorCoordinates` recalc bug
2023-06-12 14:57:02 -07:00
Brady
8a65a1cfc5 🐛 fix incorrect comparison operator 2023-06-12 16:52:20 -05:00
Brady
5bdd5b0c0d 👌 appease leijurv 2023-06-12 16:50:02 -05:00
Brady
7da802a238 Fix censorCoordinates recalc bug
Adds `equals` and `toString` implementations where needed
Replaces `toString` equality check with actual `equals` check in `forceRevalidate`
2023-06-12 16:21:05 -05:00
leijurv
e334aae608 Merge pull request #3974 from cabaletta/pr/sel-shape-masks
Add sphere and cylinder build commands to sel
2023-06-12 12:57:01 -07:00
leijurv
c48a9d98b4 Merge pull request #3982 from cabaletta/pr/batchRender
Batch Rendering
2023-06-12 12:56:05 -07:00
Brady
ed34ae73c0 Fix Mode.NONE target invalidation 2023-06-12 13:46:10 -05:00
Brady
c8a0ae9e10 Do nudgeToLevel and randomLooking when using freeLook 2023-06-12 13:44:08 -05:00
Brady
67a085c95f Batch together GL_LINES draw calls 2023-06-12 13:16:37 -05:00
Brady
1d5ee079b4 Read serverRotation from packet and invalidate on world load 2023-06-12 12:11:50 -05:00
Brady
bb36ebfc0c Use IPlayerContext for all RotationUtils methods
Deprecates all old overloads
2023-06-11 20:09:37 -05:00
Brady
a7d15d1e32 Consistent naming and comments for clarification 2023-06-11 18:43:48 -05:00
Brady
4317dca024 Determine target mode (client/server) in updateTarget 2023-06-11 18:35:34 -05:00
Brady
77ca36c794 Use playerRotations in reachableOffset 2023-06-11 15:49:04 -05:00
Brady
a09e63d6aa appease codacy 2023-06-11 13:14:52 -05:00
Brady
fbe28e397e Make setting disabled by default 2023-06-11 12:38:13 -05:00
Brady
364ae87ef8 Add blockFreeLook setting 2023-06-11 12:36:53 -05:00
Brady
ffd00080f2 Mask binary operators 2023-06-11 11:27:51 -05:00
Brady
94d757104b Clean ups 2023-06-11 11:24:31 -05:00
Brady
9729e63d98 Create and utilize new Mask type
Added factory method to `MaskSchematic` for creation using a `Mask`
Sort-of mocks the schematic structure, without the block states ofc
2023-06-09 17:25:29 -05:00
Brady
f232bbdb15 Clean up formatting 2023-06-08 16:36:32 -05:00
Brady
26574b4a9b Add optional axis parameter for #sel cyl 2023-06-08 16:32:33 -05:00
Brady
a1b1ef88cf Use a Supplier to mimic a switch expression 2023-06-08 15:46:32 -05:00
Brady
b6c52cd8e1 Cache mask in a boolean[][][] 2023-06-08 11:52:13 -05:00
Brady
34abbfb5da appease codacy 2023-06-07 17:38:26 -05:00
Brady
0d14bde583 Working sphere/cylinder build commands for #sel 2023-06-07 16:31:52 -05:00
leijurv
4b0a8eb166 Merge pull request #3966 from cabaletta/pr/setting-metadata
Setting Field Metadata
2023-06-04 16:59:14 -07:00
Brady
80ec9023ce Replace JAVA_ONLY_SETTINGS array with @JavaOnly annotation 2023-06-04 12:31:34 -05:00
leijurv
5dd10b6e81 Merge pull request #3946 from ZacSharp/pr/farm/addCocoa
Make cocoa farmable
2023-05-23 17:31:06 -07:00
leijurv
415fa048ba Merge pull request #3924 from ZacSharp/pr/blockOptionalMetaProperties
Extend BlockOptionalMeta parsing to parse block properties
2023-05-23 15:57:10 -07:00
leijurv
a1661e94b5 Merge pull request #3923 from ZacSharp/pr/mine/maxYLevelWhileMining
 Add maxYLevelWhileMining setting
2023-05-23 15:56:11 -07:00
ZacSharp
c45a714b77 Fix considering states unplaceable even if buildIgnoreProperties allows it 2023-05-08 03:51:38 +02:00
ZacSharp
271c2ff636 Extend BlockOptionalMeta parsing to parse block properties 2023-04-24 23:49:23 +02:00
ZacSharp
e4cd35ac33 Add maxYLevelWhileMining setting 2023-04-24 23:11:55 +02:00
ZacSharp
e8a4a9fdac Make cocoa farmable 2023-04-24 16:23:38 +02:00
leijurv
5f2eadbfa6 download links for 1.19.2 2023-04-11 20:36:29 -07:00
leijurv
35ab687d5e 1.9.3 download links 2023-04-11 16:00:22 -07:00
leijurv
3ff2bd4f17 Merge pull request #3908 from wagyourtail/patch-3
Update Setup.md
2023-04-11 14:47:59 -07:00
Wagyourtail
f334b3b765 update setup.md 2023-04-10 18:40:48 -07:00
leijurv
ff1732011e vid is outdated and doesn't get to the point fast enough, so let's move it lower down 2023-03-20 22:07:51 -07:00
leijurv
c5721fb7e3 Merge pull request #3878 from wagyourtail/1.12/fix-wp-c
make wp c not throw npe on invalid tag name
2023-03-14 18:40:41 -07:00
leijurv
3200d976d7 1.19.4 2023-03-14 18:35:15 -07:00
Wagyourtail
6698505dd8 make wp c not throw npe on invalid tag name 2023-03-13 15:31:18 -07:00
Leijurv
790a4f6769 command to load settings from a specific file 2023-03-01 00:25:49 -08:00
leijurv
c9d7a5bea6 kami blue to lambda 2023-02-28 23:56:34 -08:00
Leijurv
f1ead19b6e option to only move inventory when stationary 2023-02-28 23:44:33 -08:00
ZacSharp
9efc512253 Make tab completion usable
Now behaves almost identical to vanilla tab completion
2023-02-19 19:27:39 +01:00
Leijurv
174bdd2307 overhaul readme 2023-02-18 16:42:05 -08:00
Leijurv
1e7e504650 v1.6.4 2023-02-18 15:37:37 -08:00
Leijurv
814c17522a changed it back to the old way by manually renaming the release files 2023-02-18 15:20:50 -08:00
Leijurv
b622adf300 ugh why was this changed since 1.18 2023-02-18 15:13:15 -08:00
Leijurv
c1b58f8a01 link 1.19 2023-02-18 15:12:17 -08:00
leijurv
c1a9621dfa Merge pull request #3768 from wagyourtail/1.12/fasterworldscanner
replace the world scanner with a 500x faster one
2023-01-28 10:18:59 -08:00
Wagyourtail
6de266a106 remove extra method call 2023-01-28 01:39:58 -07:00
Wagyourtail
334d9c119b remove the allocation of an intlist per section 2023-01-28 00:44:54 -07:00
leijurv
1a2c30b4e3 Merge pull request #3803 from Entropy5/master
Litematica x BuildOnlySelection support
2023-01-27 23:34:35 -08:00
Entropy5
413cc1469f zac suggestion (number 2), test ongoing 2023-01-27 14:23:08 +01:00
Wagyourtail
7404414e7a less impure 2023-01-20 23:43:00 -07:00
Entropy5
49b1f3528b Merge remote-tracking branch 'origin/master' 2023-01-17 06:33:09 +01:00
Entropy5
26cceede15 litematica support for buildonlyselection, mostly rycbars 2023-01-17 06:33:01 +01:00
Wagyourtail
b71c9e776a oops didn't mean to commit that 2022-12-28 01:09:46 -07:00
Wagyourtail
746faf6df6 faster section reorder 2022-12-28 01:05:17 -07:00
Wagyourtail
a367031fe2 Revert "sacrifice a bit of speed for better block ordering"
This reverts commit e55db05f20.
2022-12-28 00:03:58 -07:00
Wagyourtail
853dadd906 Merge remote-tracking branch 'origin/master' into 1.12/fasterworldscanner 2022-12-27 23:58:13 -07:00
Wagyourtail
e55db05f20 sacrifice a bit of speed for better block ordering 2022-12-27 23:30:35 -07:00
Wagyourtail
98a748afb3 fix stream limit. immutable's in BOML 2022-12-27 22:42:38 -07:00
William Gray
c04eb066cb Update src/main/java/baritone/cache/FasterWorldScanner.java
Co-authored-by: ZacSharp <68165024+ZacSharp@users.noreply.github.com>
2022-12-28 01:06:10 +00:00
Wagyourtail
6260c6d3d7 apply suggestions 2022-12-24 12:11:26 -07:00
Wagyourtail
ce1fb49252 spiral always pick closest chunk first now 2022-12-24 11:52:48 -07:00
Wagyourtail
ecdec87e7a fix using wrong functions in scan 2022-12-24 11:43:54 -07:00
Wagyourtail
96f432d2d5 add comment 2022-12-23 17:26:46 -07:00
Wagyourtail
0ae59755e3 make limit not happen if it shouldn't 2022-12-23 17:25:23 -07:00
Wagyourtail
12b596e536 fix spiral 2022-12-23 17:10:37 -07:00
Wagyourtail
0b6088cd2d fix getting the block from the pallete, and change the chunk scan order to spiral out 2022-12-23 16:58:10 -07:00
Wagyourtail
1736f2ffc7 replace the world scanner with a 500x faster one 2022-12-23 16:34:49 -07:00
105 changed files with 3138 additions and 805 deletions

130
README.md
View File

@@ -1,129 +1 @@
# Baritone
<p align="center">
<a href="https://github.com/cabaletta/baritone/releases/"><img src="https://img.shields.io/github/downloads/cabaletta/baritone/total.svg" alt="GitHub All Releases"/></a>
</p>
<p align="center">
<a href="https://github.com/cabaletta/baritone/tree/master"><img src="https://img.shields.io/badge/MC-1.12.2-brightgreen.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.13.2"><img src="https://img.shields.io/badge/MC-1.13.2-yellow.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.14.4"><img src="https://img.shields.io/badge/MC-1.14.4-yellow.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.15.2"><img src="https://img.shields.io/badge/MC-1.15.2-yellow.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.16.5"><img src="https://img.shields.io/badge/MC-1.16.5-brightgreen.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.17.1"><img src="https://img.shields.io/badge/MC-1.17.1-brightgreen.svg" alt="Minecraft"/></a>
<a href="https://github.com/cabaletta/baritone/tree/1.18.2"><img src="https://img.shields.io/badge/MC-1.18.2-brightgreen.svg" alt="Minecraft"/></a>
</p>
<p align="center">
<a href="https://travis-ci.com/cabaletta/baritone/"><img src="https://travis-ci.com/cabaletta/baritone.svg?branch=master" alt="Build Status"/></a>
<a href="https://github.com/cabaletta/baritone/releases/"><img src="https://img.shields.io/github/release/cabaletta/baritone.svg" alt="Release"/></a>
<a href="LICENSE"><img src="https://img.shields.io/badge/license-LGPL--3.0%20with%20anime%20exception-green.svg" alt="License"/></a>
<a href="https://www.codacy.com/gh/cabaletta/baritone/dashboard?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade"><img src="https://app.codacy.com/project/badge/Grade/cadab857dab049438b6e28b3cfc5570e" alt="Codacy Badge"/></a>
<a href="https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md"><img src="https://img.shields.io/badge/%E2%9D%A4-code%20of%20conduct-blue.svg?style=flat" alt="Code of Conduct"/></a>
<a href="https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle"><img src="https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle" alt="Known Vulnerabilities"/></a>
<a href="https://github.com/cabaletta/baritone/issues/"><img src="https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat" alt="Contributions welcome"/></a>
<a href="https://github.com/cabaletta/baritone/issues/"><img src="https://img.shields.io/github/issues/cabaletta/baritone.svg" alt="Issues"/></a>
<a href="https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed"><img src="https://img.shields.io/github/issues-closed/cabaletta/baritone.svg" alt="GitHub issues-closed"/></a>
<a href="https://github.com/cabaletta/baritone/pulls/"><img src="https://img.shields.io/github/issues-pr/cabaletta/baritone.svg" alt="Pull Requests"/></a>
<a href="https://github.com/cabaletta/baritone/graphs/contributors/"><img src="https://img.shields.io/github/contributors/cabaletta/baritone.svg" alt="GitHub contributors"/></a>
<a href="https://github.com/cabaletta/baritone/commit/"><img src="https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg" alt="GitHub commits"/></a>
<img src="https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg" alt="Code size"/>
<img src="https://img.shields.io/github/repo-size/cabaletta/baritone.svg" alt="GitHub repo size"/>
<img src="https://tokei.rs/b1/github/cabaletta/baritone?category=code" alt="Lines of Code"/>
</p>
<p align="center">
<a href="https://impactclient.net/"><img src="https://img.shields.io/badge/Impact%20integration-v1.2.14%20/%20v1.3.8%20/%20v1.4.6%20/%20v1.5.3%20/%20v1.6.3-brightgreen.svg" alt="Impact integration"/></a>
<a href="https://github.com/kami-blue/client"><img src="https://img.shields.io/badge/KAMI%20Blue%20integration-v1.2.14--master-green" alt="KAMI Blue integration"/></a>
<a href="https://github.com/fr1kin/ForgeHax/"><img src="https://img.shields.io/badge/ForgeHax%20%22integration%22-scuffed-yellow.svg" alt="ForgeHax integration"/></a>
<a href="https://aristois.net/"><img src="https://img.shields.io/badge/Aristois%20add--on%20integration-v1.6.3-green.svg" alt="Aristois add-on integration"/></a>
<a href="https://rootnet.dev/"><img src="https://img.shields.io/badge/rootNET%20integration-v1.2.14-green.svg" alt="rootNET integration"/></a>
<a href="https://futureclient.net/"><img src="https://img.shields.io/badge/Future%20integration-v1.2.12%20%2F%20v1.3.6%20%2F%20v1.4.4-red" alt="Future integration"/></a>
<a href="https://rusherhack.org/"><img src="https://img.shields.io/badge/RusherHack%20integration-v1.2.14-green" alt="RusherHack integration"/></a>
</p>
<p align="center">
<a href="http://forthebadge.com/"><img src="https://forthebadge.com/images/badges/built-with-swag.svg" alt="forthebadge"/></a>
<a href="http://forthebadge.com/"><img src="https://forthebadge.com/images/badges/mom-made-pizza-rolls.svg" alt="forthebadge"/></a>
</p>
A Minecraft pathfinder bot.
[**Baritone Discord Server**](http://discord.gg/s6fRBAUpmr)
Baritone is the pathfinding system used in [Impact](https://impactclient.net/) since 4.4. There's a [showcase video](https://youtu.be/CZkLXWo4Fg4) made by @Adovin#0730 on Baritone which I recommend. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a (very old!) video I made showing off what it can do.
[Tutorial playlist](https://www.youtube.com/playlist?list=PLnwnJ1qsS7CoQl9Si-RTluuzCo_4Oulpa)
The easiest way to install Baritone is to install [Impact](https://impactclient.net/), which comes with Baritone. The second easiest way (for 1.12.2 only) is to
install the v1.2.* `api-forge` jar from [releases](https://github.com/cabaletta/baritone/releases). **For 1.12.2 Forge, just click
[here](https://github.com/cabaletta/baritone/releases/download/v1.2.17/baritone-api-forge-1.2.17.jar)**. Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
For 1.16.5, [click here](https://www.youtube.com/watch?v=_4eVJ9Qz2J8) and see description. If you need Forge or Fabric 1.16.5, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.6.3) and get the `api-forge` or `api-fabric` jar. **For 1.16.5 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.6.3/baritone-api-fabric-1.6.3.jar)**.
If you need Forge or Fabric 1.17.1, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.7.2) and get the `api-forge` or `api-fabric` jar. **For 1.17.1 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.7.2/baritone-api-fabric-1.7.2.jar)**.
If you need Forge or Fabric 1.18.2, look [here](https://github.com/cabaletta/baritone/releases/tag/v1.8.3) and get the `api-forge` or `api-fabric` jar. **For 1.18.2 Fabric, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.8.3/baritone-api-fabric-1.8.3.jar)**. **For 1.18.2 Forge, just click [here](https://github.com/cabaletta/baritone/releases/download/v1.8.3/baritone-api-forge-1.8.3.jar)**.
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2 onwards. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Have committed at least once a day from Aug 1, 2018, to Aug 1, 2019.
1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2
# Getting Started
Here are some links to help to get started:
- [Features](FEATURES.md)
- [Installation & setup](SETUP.md)
- [API Javadocs](https://baritone.leijurv.com/)
- [Settings](https://baritone.leijurv.com/baritone/api/Settings.html#field.detail)
- [Usage (chat control)](USAGE.md)
## Stars over time
[![Stargazers over time](https://starchart.cc/cabaletta/baritone.svg)](https://starchart.cc/cabaletta/baritone)
# API
The API is heavily documented, you can find the Javadocs for the latest release [here](https://baritone.leijurv.com/).
Please note that usage of anything located outside of the ``baritone.api`` package is not supported by the API release
jar.
Below is an example of basic usage for changing some settings, and then pathing to an X/Z goal.
```java
BaritoneAPI.getSettings().allowSprint.value = true;
BaritoneAPI.getSettings().primaryTimeoutMS.value = 2000L;
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalXZ(10000, 20000));
```
# FAQ
## Can I use Baritone as a library in my custom utility client?
That's what it's for, sure! (As long as usage complies with the LGPL 3.0 License)
## How is it so fast?
Magic. (Hours of [leijurv](https://github.com/leijurv/) enduring excruciating pain)
### Additional Special Thanks To:
![YourKit-Logo](https://www.yourkit.com/images/yklogo.png)
YourKit supports open source projects with innovative and intelligent tools for monitoring and profiling Java and .NET applications.
YourKit is the creator of the [YourKit Java Profiler](https://www.yourkit.com/java/profiler/), [YourKit .NET Profiler](https://www.yourkit.com/.net/profiler/), and [YourKit YouMonitor](https://www.yourkit.com/youmonitor/).
We thank them for granting Baritone an OSS license so that we can make our software the best it can be.
## Why is it called Baritone?
It's named for FitMC's deep sultry voice.
This branch of Baritone is deprecated. It will no longer recieve updates. Updates to older versions of Minecraft will not be merged into this branch, even if a newer branch is not deprecated (this branch will be skipped). Bug reports that only affect deprecated branches will not be addressed.

View File

@@ -43,13 +43,13 @@ If another one of your Forge mods has a Baritone integration, you want `baritone
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
If you have errors with a package missing please make sure you have setup your environment, and are using Oracle JDK 8 for 1.12.2-1.16.5, JDK 16 for 1.17.1, and JDK 17 for 1.18.1.
If you have errors with a package missing please make sure you have setup your environment, and are using Oracle JDK 8 for 1.12.2-1.16.5, JDK 16+ for 1.17.1, and JDK 17+ for 1.18.1.
To check which java you are using do
`java -version` in a command prompt or terminal.
If you are using anything above OpenJDK 8 for 1.12.2-1.16.5, it might not work because the Java distributions above JDK 8 using may not have the needed javax classes.
Open JDK download: https://openjdk.java.net/install/
Download java: https://adoptium.net/
#### macOS guide
In order to get JDK 8, Try running the following command:
`% /usr/libexec/java_home -V`
@@ -66,68 +66,13 @@ In order to get JDK 8 running in the **current terminal window** you will have t
To add OpenJDK 8 to your PATH add the export line to the end of your `.zshrc / .bashrc` if you want it to apply to each new terminal. If you're using bash change the .bachrc and if you're using zsh change the .zshrc
Setting up the Environment:
### Building Baritone
```
$ gradlew setupDecompWorkspace
$ gradlew --refresh-dependencies
```
These tasks depend on the minecraft version, but are (for the most part) standard for building mods.
Building Baritone:
```
$ gradlew build
```
For minecraft 1.15.2+, run the following instead to include the Forge jars:
```
$ gradlew build -Pbaritone.forge_build
```
Do this instead for Fabric jars:
```
$ gradlew build -Pbaritone.fabric_build
```
Running Baritone:
```
$ gradlew runClient
```
For information on how to build baritone, see [Building Baritone](#building-baritone)
for more details, see [the build ci action](/.github/workflows/gradle_build.yml)
## IntelliJ
- Open the project in IntelliJ as a Gradle project
![Image](https://i.imgur.com/jw7Q6vY.png)
- Run the Gradle tasks `setupDecompWorkspace` then `genIntellijRuns`
![Image](https://i.imgur.com/QEfVvWP.png)
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
![Image](https://i.imgur.com/3V7EdWr.png)
- Select the "Minecraft Client" launch config
![Image](https://i.imgur.com/1qz2QGV.png)
- Click on ``Edit Configurations...`` from the same dropdown and select the "Minecraft Client" config
![Image](https://i.imgur.com/s4ly0ZF.png)
- In `Edit Configurations...` you need to select `baritone_launch` for `Use classpath of module:`.
![Image](https://i.imgur.com/hrLhG9u.png)
## IntelliJ
- Navigate to the gradle tasks on the right tab as follows
![Image](https://i.imgur.com/PE6r9iN.png)
- Double click on **build** to run it
- depending on the minecraft version, you may need to run `setupDecompWorkspace` or `genIntellijRuns` in order to get everything working

View File

@@ -16,7 +16,7 @@
*/
group 'baritone'
version '1.6.3'
version '1.6.5'
buildscript {
repositories {

View File

@@ -32,7 +32,7 @@ public final class BaritoneAPI {
static {
settings = new Settings();
SettingsUtil.readAndApply(settings);
SettingsUtil.readAndApply(settings, SettingsUtil.SETTINGS_DEFAULT_NAME);
try {
provider = (IBaritoneProvider) Class.forName("baritone.BaritoneProvider").newInstance();

View File

@@ -21,6 +21,7 @@ import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommand;
import baritone.api.command.ICommandSystem;
import baritone.api.schematic.ISchematicSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import java.util.List;
@@ -52,15 +53,13 @@ public interface IBaritoneProvider {
List<IBaritone> getAllBaritones();
/**
* Provides the {@link IBaritone} instance for a given {@link ClientPlayerEntity}. This will likely be
* replaced with or be overloaded in addition to {@code #getBaritoneForUser(IBaritoneUser)} when
* {@code bot-system} is merged into {@code master}.
* Provides the {@link IBaritone} instance for a given {@link ClientPlayerEntity}.
*
* @param player The player
* @return The {@link IBaritone} instance.
*/
default IBaritone getBaritoneForPlayer(ClientPlayerEntity player) {
for (IBaritone baritone : getAllBaritones()) {
for (IBaritone baritone : this.getAllBaritones()) {
if (Objects.equals(player, baritone.getPlayerContext().player())) {
return baritone;
}
@@ -68,6 +67,39 @@ public interface IBaritoneProvider {
return null;
}
/**
* Provides the {@link IBaritone} instance for a given {@link Minecraft}.
*
* @param minecraft The minecraft
* @return The {@link IBaritone} instance.
*/
default IBaritone getBaritoneForMinecraft(Minecraft minecraft) {
for (IBaritone baritone : this.getAllBaritones()) {
if (Objects.equals(minecraft, baritone.getPlayerContext().minecraft())) {
return baritone;
}
}
return null;
}
/**
* Creates and registers a new {@link IBaritone} instance using the specified {@link Minecraft}. The existing
* instance is returned if already registered.
*
* @param minecraft The minecraft
* @return The {@link IBaritone} instance
*/
IBaritone createBaritone(Minecraft minecraft);
/**
* Destroys and removes the specified {@link IBaritone} instance. If the specified instance is the
* {@link #getPrimaryBaritone() primary baritone}, this operation has no effect and will return {@code false}.
*
* @param baritone The baritone instance to remove
* @return Whether the baritone instance was removed
*/
boolean destroyBaritone(IBaritone baritone);
/**
* Returns the {@link IWorldScanner} instance. This is not a type returned by
* {@link IBaritone} implementation, because it is not linked with {@link IBaritone}.

View File

@@ -29,6 +29,10 @@ import net.minecraft.util.math.vector.Vector3i;
import net.minecraft.util.text.ITextComponent;
import java.awt.*;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
import java.lang.reflect.Field;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
@@ -69,6 +73,16 @@ public final class Settings {
*/
public final Setting<Boolean> allowInventory = new Setting<>(false);
/**
* Wait this many ticks between InventoryBehavior moving inventory items
*/
public final Setting<Integer> ticksBetweenInventoryMoves = new Setting<>(1);
/**
* Come to a halt before doing any inventory moves. Intended for anticheat such as 2b2t
*/
public final Setting<Boolean> inventoryMoveOnlyIfStationary = new Setting<>(false);
/**
* Disable baritone's auto-tool at runtime, but still assume that another mod will provide auto tool functionality
* <p>
@@ -610,6 +624,13 @@ public final class Settings {
*/
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(true);
/**
* The chunk packer queue can never grow to larger than this, if it does, the oldest chunks are discarded
* <p>
* The newest chunks are kept, so that if you're moving in a straight line quickly then stop, your immediate render distance is still included
*/
public final Setting<Integer> chunkPackerQueueMaxSize = new Setting<>(2000);
/**
* Fill in blocks behind you
*/
@@ -711,6 +732,17 @@ public final class Settings {
*/
public final Setting<Boolean> freeLook = new Setting<>(true);
/**
* Break and place blocks without having to force the client-sided rotations. Requires {@link #freeLook}.
*/
public final Setting<Boolean> blockFreeLook = new Setting<>(false);
/**
* When true, the player will remain with its existing look direction as often as possible.
* Although, in some cases this can get it stuck, hence this setting to disable that behavior.
*/
public final Setting<Boolean> remainWithExistingLookDirection = new Setting<>(true);
/**
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
* <p>
@@ -845,6 +877,11 @@ public final class Settings {
*/
public final Setting<Integer> minYLevelWhileMining = new Setting<>(0);
/**
* Sets the maximum y level to mine ores at.
*/
public final Setting<Integer> maxYLevelWhileMining = new Setting<>(255); // 1.17+ defaults to maximum possible world height
/**
* This will only allow baritone to mine exposed ores, can be used to stop ore obfuscators on servers that use them.
*/
@@ -1141,6 +1178,7 @@ public final class Settings {
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
* {@link Setting#value};
*/
@JavaOnly
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(msg -> Minecraft.getInstance().ingameGUI.getChatGUI().printChatMessage(msg));
/**
@@ -1148,6 +1186,7 @@ public final class Settings {
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
* {@link Setting#value};
*/
@JavaOnly
public final Setting<BiConsumer<String, Boolean>> notifier = new Setting<>(NotificationHelper::notify);
/**
@@ -1155,6 +1194,7 @@ public final class Settings {
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
* {@link Setting#value};
*/
@JavaOnly
public final Setting<BiConsumer<ITextComponent, ITextComponent>> toaster = new Setting<>(BaritoneToast::addOrUpdate);
/**
@@ -1304,6 +1344,7 @@ public final class Settings {
public T value;
public final T defaultValue;
private String name;
private boolean javaOnly;
@SuppressWarnings("unchecked")
private Setting(T value) {
@@ -1312,6 +1353,7 @@ public final class Settings {
}
this.value = value;
this.defaultValue = value;
this.javaOnly = false;
}
/**
@@ -1348,8 +1390,25 @@ public final class Settings {
public final Type getType() {
return settingTypes.get(this);
}
/**
* This should always be the same as whether the setting can be parsed from or serialized to a string; in other
* words, the only way to modify it is by writing to {@link #value} programatically.
*
* @return {@code true} if the setting can not be set or read by the user
*/
public boolean isJavaOnly() {
return javaOnly;
}
}
/**
* Marks a {@link Setting} field as being {@link Setting#isJavaOnly() Java-only}
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
private @interface JavaOnly {}
// here be dragons
Settings() {
@@ -1365,6 +1424,7 @@ public final class Settings {
Setting<?> setting = (Setting<?>) field.get(this);
String name = field.getName();
setting.name = name;
setting.javaOnly = field.isAnnotationPresent(JavaOnly.class);
name = name.toLowerCase();
if (tmpByName.containsKey(name)) {
throw new IllegalStateException("Duplicate setting name");

View File

@@ -17,6 +17,8 @@
package baritone.api.behavior;
import baritone.api.Settings;
import baritone.api.behavior.look.IAimProcessor;
import baritone.api.utils.Rotation;
/**
@@ -26,14 +28,23 @@ import baritone.api.utils.Rotation;
public interface ILookBehavior extends IBehavior {
/**
* Updates the current {@link ILookBehavior} target to target
* the specified rotations on the next tick. If force is {@code true},
* then freeLook will be overriden and angles will be set regardless.
* If any sort of block interaction is required, force should be {@code true},
* otherwise, it should be {@code false};
* Updates the current {@link ILookBehavior} target to target the specified rotations on the next tick. If any sort
* of block interaction is required, {@code blockInteract} should be {@code true}. It is not guaranteed that the
* rotations set by the caller will be the exact rotations expressed by the client (This is due to settings like
* {@link Settings#randomLooking}). If the rotations produced by this behavior are required, then the
* {@link #getAimProcessor() aim processor} should be used.
*
* @param rotation The target rotations
* @param force Whether or not to "force" the rotations
* @param rotation The target rotations
* @param blockInteract Whether the target rotations are needed for a block interaction
*/
void updateTarget(Rotation rotation, boolean force);
void updateTarget(Rotation rotation, boolean blockInteract);
/**
* The aim processor instance for this {@link ILookBehavior}, which is responsible for applying additional,
* deterministic transformations to the target rotation set by {@link #updateTarget}.
*
* @return The aim processor
* @see IAimProcessor#fork
*/
IAimProcessor getAimProcessor();
}

View File

@@ -0,0 +1,45 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.behavior.look;
import baritone.api.utils.Rotation;
/**
* @author Brady
*/
public interface IAimProcessor {
/**
* Returns the actual rotation that will be used when the desired rotation is requested. The returned rotation
* always reflects what would happen in the upcoming tick. In other words, it is a pure function, and no internal
* state changes. If simulation of the rotation states beyond the next tick is required, then a
* {@link IAimProcessor#fork fork} should be created.
*
* @param desired The desired rotation to set
* @return The actual rotation
*/
Rotation peekRotation(Rotation desired);
/**
* Returns a copy of this {@link IAimProcessor} which has its own internal state and is manually tickable.
*
* @return The forked processor
* @see ITickableAimProcessor
*/
ITickableAimProcessor fork();
}

View File

@@ -0,0 +1,47 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.behavior.look;
import baritone.api.utils.Rotation;
/**
* @author Brady
*/
public interface ITickableAimProcessor extends IAimProcessor {
/**
* Advances the internal state of this aim processor by a single tick.
*/
void tick();
/**
* Calls {@link #tick()} the specified number of times.
*
* @param ticks The number of calls
*/
void advance(int ticks);
/**
* Returns the actual rotation as provided by {@link #peekRotation(Rotation)}, and then automatically advances the
* internal state by one {@link #tick() tick}.
*
* @param rotation The desired rotation to set
* @return The actual rotation
*/
Rotation nextRotation(Rotation rotation);
}

View File

@@ -17,6 +17,8 @@
package baritone.api.cache;
import java.util.function.Consumer;
/**
* @author Brady
* @since 9/24/2018
@@ -29,4 +31,11 @@ public interface IWorldProvider {
* @return The current world data
*/
IWorldData getCurrentWorld();
default void ifWorldLoaded(Consumer<IWorldData> callback) {
final IWorldData currentWorld = this.getCurrentWorld();
if (currentWorld != null) {
callback.accept(currentWorld);
}
}
}

View File

@@ -23,11 +23,17 @@ import net.minecraft.block.Block;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import java.util.regex.Pattern;
import java.util.stream.Stream;
public enum BlockById implements IDatatypeFor<Block> {
INSTANCE;
/**
* Matches (domain:)?name? where domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ respectively.
*/
private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?[a-z0-9/_.-]*");
@Override
public Block get(IDatatypeContext ctx) throws CommandException {
ResourceLocation id = new ResourceLocation(ctx.getConsumer().getString());
@@ -40,13 +46,19 @@ public enum BlockById implements IDatatypeFor<Block> {
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
String arg = ctx.getConsumer().getString();
if (!PATTERN.matcher(arg).matches()) {
return Stream.empty();
}
return new TabCompleteHelper()
.append(
Registry.BLOCK.keySet()
.stream()
.map(Object::toString)
)
.filterPrefixNamespaced(ctx.getConsumer().getString())
.filterPrefixNamespaced(arg)
.sortAlphabetically()
.stream();
}

View File

@@ -0,0 +1,43 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import net.minecraft.util.Direction;
import java.util.Locale;
import java.util.stream.Stream;
public enum ForAxis implements IDatatypeFor<Direction.Axis> {
INSTANCE;
@Override
public Direction.Axis get(IDatatypeContext ctx) throws CommandException {
return Direction.Axis.valueOf(ctx.getConsumer().getString().toUpperCase(Locale.US));
}
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
return new TabCompleteHelper()
.append(Stream.of(Direction.Axis.values())
.map(Direction.Axis::getString).map(String::toLowerCase))
.filterPrefix(ctx.getConsumer().getString())
.stream();
}
}

View File

@@ -18,20 +18,137 @@
package baritone.api.command.datatypes;
import baritone.api.command.exception.CommandException;
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.utils.BlockOptionalMeta;
import net.minecraft.block.Block;
import net.minecraft.state.Property;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.registry.Registry;
import java.util.Set;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum ForBlockOptionalMeta implements IDatatypeFor<BlockOptionalMeta> {
INSTANCE;
/**
* Matches (domain:)?name([(property=value)*])? but the input can be truncated at any position.
* domain and name are [a-z0-9_.-]+ and [a-z0-9/_.-]+ because that's what mc 1.13+ accepts.
* property and value use the same format as domain.
*/
// Good luck reading this.
private static Pattern PATTERN = Pattern.compile("(?:[a-z0-9_.-]+:)?(?:[a-z0-9/_.-]+(?:\\[(?:(?:[a-z0-9_.-]+=[a-z0-9_.-]+,)*(?:[a-z0-9_.-]+(?:=(?:[a-z0-9_.-]+(?:\\])?)?)?)?|\\])?)?)?");
@Override
public BlockOptionalMeta get(IDatatypeContext ctx) throws CommandException {
return new BlockOptionalMeta(ctx.getConsumer().getString());
}
@Override
public Stream<String> tabComplete(IDatatypeContext ctx) {
return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
public Stream<String> tabComplete(IDatatypeContext ctx) throws CommandException {
String arg = ctx.getConsumer().peekString();
if (!PATTERN.matcher(arg).matches()) {
// Invalid format; we can't complete this.
ctx.getConsumer().getString();
return Stream.empty();
}
if (arg.endsWith("]")) {
// We are already done.
ctx.getConsumer().getString();
return Stream.empty();
}
if (!arg.contains("[")) {
// no properties so we are completing the block id
return ctx.getConsumer().tabCompleteDatatype(BlockById.INSTANCE);
}
ctx.getConsumer().getString();
// destructuring assignment? Please?
String blockId, properties;
{
String[] parts = splitLast(arg, '[');
blockId = parts[0];
properties = parts[1];
}
Block block = Registry.BLOCK.getOptional(new ResourceLocation(blockId)).orElse(null);
if (block == null) {
// This block doesn't exist so there's no properties to complete.
return Stream.empty();
}
String leadingProperties, lastProperty;
{
String[] parts = splitLast(properties, ',');
leadingProperties = parts[0];
lastProperty = parts[1];
}
if (!lastProperty.contains("=")) {
// The last property-value pair doesn't have a value yet so we are completing its name
Set<String> usedProps = Stream.of(leadingProperties.split(","))
.map(pair -> pair.split("=")[0])
.collect(Collectors.toSet());
String prefix = arg.substring(0, arg.length() - lastProperty.length());
return new TabCompleteHelper()
.append(
block.getStateContainer()
.getProperties()
.stream()
.map(Property::getName)
)
.filter(prop -> !usedProps.contains(prop))
.filterPrefix(lastProperty)
.sortAlphabetically()
.map(prop -> prefix + prop)
.stream();
}
String lastName, lastValue;
{
String[] parts = splitLast(lastProperty, '=');
lastName = parts[0];
lastValue = parts[1];
}
// We are completing the value of a property
String prefix = arg.substring(0, arg.length() - lastValue.length());
Property<?> property = block.getStateContainer().getProperty(lastName);
if (property == null) {
// The property does not exist so there's no values to complete
return Stream.empty();
}
return new TabCompleteHelper()
.append(getValues(property))
.filterPrefix(lastValue)
.sortAlphabetically()
.map(val -> prefix + val)
.stream();
}
/**
* Always returns exactly two strings.
* If the separator is not found the FIRST returned string is empty.
*/
private static String[] splitLast(String string, char chr) {
int idx = string.lastIndexOf(chr);
if (idx == -1) {
return new String[]{"", string};
}
return new String[]{string.substring(0, idx), string.substring(idx + 1)};
}
// this shouldn't need to be a separate method?
private static <T extends Comparable<T>> Stream<String> getValues(Property<T> property) {
return property.getAllowedValues().stream().map(property::getName);
}
}

View File

@@ -19,6 +19,8 @@ package baritone.api.command.datatypes;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.api.utils.Helper;
import net.minecraft.client.Minecraft;
import java.io.File;
import java.io.IOException;
@@ -30,8 +32,6 @@ import java.util.Locale;
import java.util.Objects;
import java.util.stream.Stream;
import static baritone.api.utils.Helper.HELPER;
public enum RelativeFile implements IDatatypePost<File, File> {
INSTANCE;
@@ -93,8 +93,13 @@ public enum RelativeFile implements IDatatypePost<File, File> {
.filter(s -> !s.contains(" "));
}
@Deprecated
public static File gameDir() {
File gameDir = HELPER.mc.gameDir.getAbsoluteFile();
return gameDir(Helper.mc);
}
public static File gameDir(Minecraft mc) {
File gameDir = mc.gameDir.getAbsoluteFile();
if (gameDir.getName().equals(".")) {
return gameDir.getParentFile();
}

View File

@@ -253,7 +253,7 @@ public class TabCompleteHelper {
public TabCompleteHelper addSettings() {
return append(
BaritoneAPI.getSettings().allSettings.stream()
.filter(s -> !SettingsUtil.javaOnlySetting(s))
.filter(s -> !s.isJavaOnly())
.map(Settings.Setting::getName)
.sorted(String.CASE_INSENSITIVE_ORDER)
);

View File

@@ -17,6 +17,7 @@
package baritone.api.event.events;
import baritone.api.utils.Rotation;
import net.minecraft.entity.Entity;
import net.minecraft.entity.LivingEntity;
import net.minecraft.util.math.vector.Vector3d;
@@ -32,14 +33,27 @@ public final class RotationMoveEvent {
*/
private final Type type;
private final Rotation original;
/**
* The yaw rotation
*/
private float yaw;
public RotationMoveEvent(Type type, float yaw) {
/**
* The pitch rotation
*/
private float pitch;
public RotationMoveEvent(Type type, float yaw, float pitch) {
this.type = type;
this.original = new Rotation(yaw, pitch);
this.yaw = yaw;
this.pitch = pitch;
}
public Rotation getOriginal() {
return this.original;
}
/**
@@ -47,21 +61,37 @@ public final class RotationMoveEvent {
*
* @param yaw Yaw rotation
*/
public final void setYaw(float yaw) {
public void setYaw(float yaw) {
this.yaw = yaw;
}
/**
* @return The yaw rotation
*/
public final float getYaw() {
public float getYaw() {
return this.yaw;
}
/**
* Set the pitch movement rotation
*
* @param pitch Pitch rotation
*/
public void setPitch(float pitch) {
this.pitch = pitch;
}
/**
* @return The pitch rotation
*/
public float getPitch() {
return pitch;
}
/**
* @return The type of the event
*/
public final Type getType() {
public Type getType() {
return this.type;
}

View File

@@ -42,6 +42,16 @@ public class GoalAxis implements Goal {
return flatAxisDistance * BaritoneAPI.getSettings().costHeuristic.value + GoalYLevel.calculate(BaritoneAPI.getSettings().axisHeight.value, y);
}
@Override
public boolean equals(Object o) {
return o.getClass() == GoalAxis.class;
}
@Override
public int hashCode() {
return 201385781;
}
@Override
public String toString() {
return "GoalAxis";

View File

@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -66,6 +67,26 @@ public class GoalBlock implements Goal, IGoalRenderPos {
return calculate(xDiff, yDiff, zDiff);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalBlock goal = (GoalBlock) o;
return x == goal.x
&& y == goal.y
&& z == goal.z;
}
@Override
public int hashCode() {
return (int) BetterBlockPos.longHash(x, y, z) * 905165533;
}
@Override
public String toString() {
return String.format(

View File

@@ -67,6 +67,24 @@ public class GoalComposite implements Goal {
return min;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalComposite goal = (GoalComposite) o;
return Arrays.equals(goals, goal.goals);
}
@Override
public int hashCode() {
return Arrays.hashCode(goals);
}
@Override
public String toString() {
return "GoalComposite" + Arrays.toString(goals);

View File

@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -60,6 +61,26 @@ public class GoalGetToBlock implements Goal, IGoalRenderPos {
return GoalBlock.calculate(xDiff, yDiff < 0 ? yDiff + 1 : yDiff, zDiff);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalGetToBlock goal = (GoalGetToBlock) o;
return x == goal.x
&& y == goal.y
&& z == goal.z;
}
@Override
public int hashCode() {
return (int) BetterBlockPos.longHash(x, y, z) * -49639096;
}
@Override
public String toString() {
return String.format(

View File

@@ -17,6 +17,8 @@
package baritone.api.pathing.goals;
import java.util.Objects;
/**
* Invert any goal.
* <p>
@@ -50,6 +52,24 @@ public class GoalInverted implements Goal {
return Double.NEGATIVE_INFINITY;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalInverted goal = (GoalInverted) o;
return Objects.equals(origin, goal.origin);
}
@Override
public int hashCode() {
return origin.hashCode() * 495796690;
}
@Override
public String toString() {
return String.format("GoalInverted{%s}", origin.toString());

View File

@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import it.unimi.dsi.fastutil.doubles.DoubleIterator;
@@ -86,6 +87,27 @@ public class GoalNear implements Goal, IGoalRenderPos {
return new BlockPos(x, y, z);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalNear goal = (GoalNear) o;
return x == goal.x
&& y == goal.y
&& z == goal.z
&& rangeSq == goal.rangeSq;
}
@Override
public int hashCode() {
return (int) BetterBlockPos.longHash(x, y, z) + rangeSq;
}
@Override
public String toString() {
return String.format(

View File

@@ -23,6 +23,7 @@ import it.unimi.dsi.fastutil.doubles.DoubleOpenHashSet;
import net.minecraft.util.math.BlockPos;
import java.util.Arrays;
import java.util.Objects;
/**
* Useful for automated combat (retreating specifically)
@@ -124,6 +125,29 @@ public class GoalRunAway implements Goal {
return maxInside;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalRunAway goal = (GoalRunAway) o;
return distanceSq == goal.distanceSq
&& Arrays.equals(from, goal.from)
&& Objects.equals(maintainY, goal.maintainY);
}
@Override
public int hashCode() {
int hash = Arrays.hashCode(from);
hash = hash * 1196803141 + distanceSq;
hash = hash * -2053788840 + maintainY;
return hash;
}
@Override
public String toString() {
if (maintainY != null) {

View File

@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import net.minecraft.util.Direction;
import net.minecraft.util.math.BlockPos;
@@ -69,6 +70,31 @@ public class GoalStrictDirection implements Goal {
return Double.NEGATIVE_INFINITY;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalStrictDirection goal = (GoalStrictDirection) o;
return x == goal.x
&& y == goal.y
&& z == goal.z
&& dx == goal.dx
&& dz == goal.dz;
}
@Override
public int hashCode() {
int hash = (int) BetterBlockPos.longHash(x, y, z);
hash = hash * 630627507 + dx;
hash = hash * -283028380 + dz;
return hash;
}
@Override
public String toString() {
return String.format(

View File

@@ -17,6 +17,7 @@
package baritone.api.pathing.goals;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.SettingsUtil;
import baritone.api.utils.interfaces.IGoalRenderPos;
import net.minecraft.util.math.BlockPos;
@@ -72,6 +73,26 @@ public class GoalTwoBlocks implements Goal, IGoalRenderPos {
return new BlockPos(x, y, z);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalTwoBlocks goal = (GoalTwoBlocks) o;
return x == goal.x
&& y == goal.y
&& z == goal.z;
}
@Override
public int hashCode() {
return (int) BetterBlockPos.longHash(x, y, z) * 516508351;
}
@Override
public String toString() {
return String.format(

View File

@@ -64,6 +64,27 @@ public class GoalXZ implements Goal {
return calculate(xDiff, zDiff);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalXZ goal = (GoalXZ) o;
return x == goal.x && z == goal.z;
}
@Override
public int hashCode() {
int hash = 1791873246;
hash = hash * 222601791 + x;
hash = hash * -1331679453 + z;
return hash;
}
@Override
public String toString() {
return String.format(

View File

@@ -58,6 +58,24 @@ public class GoalYLevel implements Goal, ActionCosts {
return 0;
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
GoalYLevel goal = (GoalYLevel) o;
return level == goal.level;
}
@Override
public int hashCode() {
return level * 1271009915;
}
@Override
public String toString() {
return String.format(

View File

@@ -51,6 +51,7 @@ public interface IBuilderProcess extends IBaritoneProcess {
*/
boolean build(String name, File schematic, Vector3i origin);
@Deprecated
default boolean build(String schematicFile, BlockPos origin) {
File file = new File(new File(Minecraft.getInstance().gameDir, "schematics"), schematicFile);
return build(schematicFile, file, origin);

View File

@@ -17,6 +17,7 @@
package baritone.api.schematic;
import baritone.api.schematic.mask.Mask;
import net.minecraft.block.BlockState;
import java.util.List;
@@ -41,4 +42,14 @@ public abstract class MaskSchematic extends AbstractSchematic {
public BlockState desiredState(int x, int y, int z, BlockState current, List<BlockState> approxPlaceable) {
return schematic.desiredState(x, y, z, current, approxPlaceable);
}
public static MaskSchematic create(ISchematic schematic, Mask function) {
return new MaskSchematic(schematic) {
@Override
protected boolean partOfMask(int x, int y, int z, BlockState currentState) {
return function.partOfMask(x, y, z, currentState);
}
};
}
}

View File

@@ -0,0 +1,49 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask;
/**
* @author Brady
*/
public abstract class AbstractMask implements Mask {
private final int widthX;
private final int heightY;
private final int lengthZ;
public AbstractMask(int widthX, int heightY, int lengthZ) {
this.widthX = widthX;
this.heightY = heightY;
this.lengthZ = lengthZ;
}
@Override
public int widthX() {
return this.widthX;
}
@Override
public int heightY() {
return this.heightY;
}
@Override
public int lengthZ() {
return this.lengthZ;
}
}

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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask;
import baritone.api.schematic.mask.operator.BinaryOperatorMask;
import baritone.api.schematic.mask.operator.NotMask;
import baritone.api.utils.BooleanBinaryOperators;
import net.minecraft.block.BlockState;
/**
* @author Brady
*/
public interface Mask {
/**
* @param x The relative x position of the block
* @param y The relative y position of the block
* @param z The relative z position of the block
* @param currentState The current state of that block in the world, may be {@code null}
* @return Whether the given position is included in this mask
*/
boolean partOfMask(int x, int y, int z, BlockState currentState);
int widthX();
int heightY();
int lengthZ();
default Mask not() {
return new NotMask(this);
}
default Mask union(Mask other) {
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.OR);
}
default Mask intersection(Mask other) {
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.AND);
}
default Mask xor(Mask other) {
return new BinaryOperatorMask(this, other, BooleanBinaryOperators.XOR);
}
}

View File

@@ -0,0 +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 Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask;
/**
* @author Brady
*/
final class PreComputedMask extends AbstractMask implements StaticMask {
private final boolean[][][] mask;
public PreComputedMask(StaticMask mask) {
super(mask.widthX(), mask.heightY(), mask.lengthZ());
this.mask = new boolean[this.heightY()][this.lengthZ()][this.widthX()];
for (int y = 0; y < this.heightY(); y++) {
for (int z = 0; z < this.lengthZ(); z++) {
for (int x = 0; x < this.widthX(); x++) {
this.mask[y][z][x] = mask.partOfMask(x, y, z);
}
}
}
}
@Override
public boolean partOfMask(int x, int y, int z) {
return this.mask[y][z][x];
}
}

View File

@@ -0,0 +1,82 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask;
import baritone.api.schematic.mask.operator.BinaryOperatorMask;
import baritone.api.schematic.mask.operator.NotMask;
import baritone.api.utils.BooleanBinaryOperators;
import net.minecraft.block.BlockState;
/**
* A mask that is context-free. In other words, it doesn't require the current block state to determine if a relative
* position is a part of the mask.
*
* @author Brady
*/
public interface StaticMask extends Mask {
/**
* Determines if a given relative coordinate is included in this mask, without the need for the current block state.
*
* @param x The relative x position of the block
* @param y The relative y position of the block
* @param z The relative z position of the block
* @return Whether the given position is included in this mask
*/
boolean partOfMask(int x, int y, int z);
/**
* Implements the parent {@link Mask#partOfMask partOfMask function} by calling the static function
* provided in this functional interface without needing the {@link BlockState} argument. This {@code default}
* implementation should <b><u>NOT</u></b> be overriden.
*
* @param x The relative x position of the block
* @param y The relative y position of the block
* @param z The relative z position of the block
* @param currentState The current state of that block in the world, may be {@code null}
* @return Whether the given position is included in this mask
*/
@Override
default boolean partOfMask(int x, int y, int z, BlockState currentState) {
return this.partOfMask(x, y, z);
}
@Override
default StaticMask not() {
return new NotMask.Static(this);
}
default StaticMask union(StaticMask other) {
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.OR);
}
default StaticMask intersection(StaticMask other) {
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.AND);
}
default StaticMask xor(StaticMask other) {
return new BinaryOperatorMask.Static(this, other, BooleanBinaryOperators.XOR);
}
/**
* Returns a pre-computed mask using {@code this} function, with the specified size parameters.
*/
default StaticMask compute() {
return new PreComputedMask(this);
}
}

View File

@@ -0,0 +1,79 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask.operator;
import baritone.api.schematic.mask.AbstractMask;
import baritone.api.schematic.mask.Mask;
import baritone.api.schematic.mask.StaticMask;
import baritone.api.utils.BooleanBinaryOperator;
import net.minecraft.block.BlockState;
/**
* @author Brady
*/
public final class BinaryOperatorMask extends AbstractMask {
private final Mask a;
private final Mask b;
private final BooleanBinaryOperator operator;
public BinaryOperatorMask(Mask a, Mask b, BooleanBinaryOperator operator) {
super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
this.a = a;
this.b = b;
this.operator = operator;
}
@Override
public boolean partOfMask(int x, int y, int z, BlockState currentState) {
return this.operator.applyAsBoolean(
partOfMask(a, x, y, z, currentState),
partOfMask(b, x, y, z, currentState)
);
}
private static boolean partOfMask(Mask mask, int x, int y, int z, BlockState currentState) {
return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.partOfMask(x, y, z, currentState);
}
public static final class Static extends AbstractMask implements StaticMask {
private final StaticMask a;
private final StaticMask b;
private final BooleanBinaryOperator operator;
public Static(StaticMask a, StaticMask b, BooleanBinaryOperator operator) {
super(Math.max(a.widthX(), b.widthX()), Math.max(a.heightY(), b.heightY()), Math.max(a.lengthZ(), b.lengthZ()));
this.a = a;
this.b = b;
this.operator = operator;
}
@Override
public boolean partOfMask(int x, int y, int z) {
return this.operator.applyAsBoolean(
partOfMask(a, x, y, z),
partOfMask(b, x, y, z)
);
}
private static boolean partOfMask(StaticMask mask, int x, int y, int z) {
return x < mask.widthX() && y < mask.heightY() && z < mask.lengthZ() && mask.partOfMask(x, y, z);
}
}
}

View File

@@ -0,0 +1,56 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask.operator;
import baritone.api.schematic.mask.AbstractMask;
import baritone.api.schematic.mask.Mask;
import baritone.api.schematic.mask.StaticMask;
import net.minecraft.block.BlockState;
/**
* @author Brady
*/
public final class NotMask extends AbstractMask {
private final Mask source;
public NotMask(Mask source) {
super(source.widthX(), source.heightY(), source.lengthZ());
this.source = source;
}
@Override
public boolean partOfMask(int x, int y, int z, BlockState currentState) {
return !this.source.partOfMask(x, y, z, currentState);
}
public static final class Static extends AbstractMask implements StaticMask {
private final StaticMask source;
public Static(StaticMask source) {
super(source.widthX(), source.heightY(), source.lengthZ());
this.source = source;
}
@Override
public boolean partOfMask(int x, int y, int z) {
return !this.source.partOfMask(x, y, z);
}
}
}

View File

@@ -0,0 +1,69 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask.shape;
import baritone.api.schematic.mask.AbstractMask;
import baritone.api.schematic.mask.StaticMask;
import net.minecraft.util.Direction;
/**
* @author Brady
*/
public final class CylinderMask extends AbstractMask implements StaticMask {
private final double centerA;
private final double centerB;
private final double radiusSqA;
private final double radiusSqB;
private final boolean filled;
private final Direction.Axis alignment;
public CylinderMask(int widthX, int heightY, int lengthZ, boolean filled, Direction.Axis alignment) {
super(widthX, heightY, lengthZ);
this.centerA = this.getA(widthX, heightY, alignment) / 2.0;
this.centerB = this.getB(heightY, lengthZ, alignment) / 2.0;
this.radiusSqA = (this.centerA - 1) * (this.centerA - 1);
this.radiusSqB = (this.centerB - 1) * (this.centerB - 1);
this.filled = filled;
this.alignment = alignment;
}
@Override
public boolean partOfMask(int x, int y, int z) {
double da = Math.abs((this.getA(x, y, this.alignment) + 0.5) - this.centerA);
double db = Math.abs((this.getB(y, z, this.alignment) + 0.5) - this.centerB);
if (this.outside(da, db)) {
return false;
}
return this.filled
|| this.outside(da + 1, db)
|| this.outside(da, db + 1);
}
private boolean outside(double da, double db) {
return da * da / this.radiusSqA + db * db / this.radiusSqB > 1;
}
private static int getA(int x, int y, Direction.Axis alignment) {
return alignment == Direction.Axis.X ? y : x;
}
private static int getB(int y, int z, Direction.Axis alignment) {
return alignment == Direction.Axis.Z ? y : z;
}
}

View File

@@ -0,0 +1,64 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.schematic.mask.shape;
import baritone.api.schematic.mask.AbstractMask;
import baritone.api.schematic.mask.StaticMask;
/**
* @author Brady
*/
public final class SphereMask extends AbstractMask implements StaticMask {
private final double centerX;
private final double centerY;
private final double centerZ;
private final double radiusSqX;
private final double radiusSqY;
private final double radiusSqZ;
private final boolean filled;
public SphereMask(int widthX, int heightY, int lengthZ, boolean filled) {
super(widthX, heightY, lengthZ);
this.centerX = widthX / 2.0;
this.centerY = heightY / 2.0;
this.centerZ = lengthZ / 2.0;
this.radiusSqX = this.centerX * this.centerX;
this.radiusSqY = this.centerY * this.centerY;
this.radiusSqZ = this.centerZ * this.centerZ;
this.filled = filled;
}
@Override
public boolean partOfMask(int x, int y, int z) {
double dx = Math.abs((x + 0.5) - this.centerX);
double dy = Math.abs((y + 0.5) - this.centerY);
double dz = Math.abs((z + 0.5) - this.centerZ);
if (this.outside(dx, dy, dz)) {
return false;
}
return this.filled
|| this.outside(dx + 1, dy, dz)
|| this.outside(dx, dy + 1, dz)
|| this.outside(dx, dy, dz + 1);
}
private boolean outside(double dx, double dy, double dz) {
return dx * dx / this.radiusSqX + dy * dy / this.radiusSqY + dz * dz / this.radiusSqZ > 1;
}
}

View File

@@ -18,6 +18,7 @@
package baritone.api.utils;
import baritone.api.utils.accessor.IItemStack;
import com.google.common.collect.ImmutableMap;
import com.google.common.collect.ImmutableSet;
import io.netty.util.concurrent.ThreadPerTaskExecutor;
import net.minecraft.block.Block;
@@ -26,53 +27,95 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.loot.*;
import net.minecraft.resources.*;
import net.minecraft.state.Property;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.Unit;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
import javax.annotation.Nonnull;
import java.util.*;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Random;
import java.util.Set;
import java.util.concurrent.CompletableFuture;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
public final class BlockOptionalMeta {
// id or id[] or id[properties] where id and properties are any text with at least one character
private static final Pattern PATTERN = Pattern.compile("^(?<id>.+?)(?:\\[(?<properties>.+?)?\\])?$");
private final Block block;
private final String propertiesDescription; // exists so toString() can return something more useful than a list of all blockstates
private final Set<BlockState> blockstates;
private final ImmutableSet<Integer> stateHashes;
private final ImmutableSet<Integer> stackHashes;
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
private final Set<Integer> stateHashes;
private final Set<Integer> stackHashes;
private static LootTableManager manager;
private static LootPredicateManager predicate = new LootPredicateManager();
private static Map<Block, List<Item>> drops = new HashMap<>();
public BlockOptionalMeta(@Nonnull Block block) {
this.block = block;
this.blockstates = getStates(block);
this.propertiesDescription = "{}";
this.blockstates = getStates(block, Collections.emptyMap());
this.stateHashes = getStateHashes(blockstates);
this.stackHashes = getStackHashes(blockstates);
}
public BlockOptionalMeta(@Nonnull String selector) {
Matcher matcher = pattern.matcher(selector);
Matcher matcher = PATTERN.matcher(selector);
if (!matcher.find()) {
throw new IllegalArgumentException("invalid block selector");
}
MatchResult matchResult = matcher.toMatchResult();
block = BlockUtils.stringToBlockRequired(matcher.group("id"));
block = BlockUtils.stringToBlockRequired(matchResult.group(1));
blockstates = getStates(block);
String props = matcher.group("properties");
Map<Property<?>, ?> properties = props == null || props.equals("") ? Collections.emptyMap() : parseProperties(block, props);
propertiesDescription = props == null ? "{}" : "{" + props.replace("=", ":") + "}";
blockstates = getStates(block, properties);
stateHashes = getStateHashes(blockstates);
stackHashes = getStackHashes(blockstates);
}
private static Set<BlockState> getStates(@Nonnull Block block) {
return new HashSet<>(block.getStateContainer().getValidStates());
private static <C extends Comparable<C>, P extends Property<C>> P castToIProperty(Object value) {
//noinspection unchecked
return (P) value;
}
private static Map<Property<?>, ?> parseProperties(Block block, String raw) {
ImmutableMap.Builder<Property<?>, Object> builder = ImmutableMap.builder();
for (String pair : raw.split(",")) {
String[] parts = pair.split("=");
if (parts.length != 2) {
throw new IllegalArgumentException(String.format("\"%s\" is not a valid property-value pair", pair));
}
String rawKey = parts[0];
String rawValue = parts[1];
Property<?> key = block.getStateContainer().getProperty(rawKey);
Comparable<?> value = castToIProperty(key).parseValue(rawValue)
.orElseThrow(() -> new IllegalArgumentException(String.format(
"\"%s\" is not a valid value for %s on %s",
rawValue, key, block
)));
builder.put(key, value);
}
return builder.build();
}
private static Set<BlockState> getStates(@Nonnull Block block, @Nonnull Map<Property<?>, ?> properties) {
return block.getStateContainer().getValidStates().stream()
.filter(blockstate -> properties.entrySet().stream().allMatch(entry ->
blockstate.get(entry.getKey()) == entry.getValue()
))
.collect(Collectors.toSet());
}
private static ImmutableSet<Integer> getStateHashes(Set<BlockState> blockstates) {
@@ -120,7 +163,7 @@ public final class BlockOptionalMeta {
@Override
public String toString() {
return String.format("BlockOptionalMeta{block=%s}", block);
return String.format("BlockOptionalMeta{block=%s,properties=%s}", block, propertiesDescription);
}
public BlockState getAnyBlockState() {
@@ -131,6 +174,14 @@ public final class BlockOptionalMeta {
return null;
}
public Set<BlockState> getAllBlockStates() {
return blockstates;
}
public Set<Integer> stackHashes() {
return stackHashes;
}
public static LootTableManager getManager() {
if (manager == null) {
ResourcePackList rpl = new ResourcePackList(ResourcePackInfo::new, new ServerPackFinder());

View File

@@ -17,68 +17,70 @@
package baritone.api.utils;
import baritone.api.utils.accessor.IItemStack;
import com.google.common.collect.ImmutableSet;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.item.ItemStack;
import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
public class BlockOptionalMetaLookup {
private final ImmutableSet<Block> blockSet;
private final ImmutableSet<BlockState> blockStateSet;
private final ImmutableSet<Integer> stackHashes;
private final BlockOptionalMeta[] boms;
public BlockOptionalMetaLookup(BlockOptionalMeta... boms) {
this.boms = boms;
Set<Block> blocks = new HashSet<>();
Set<BlockState> blockStates = new HashSet<>();
Set<Integer> stacks = new HashSet<>();
for (BlockOptionalMeta bom : boms) {
blocks.add(bom.getBlock());
blockStates.addAll(bom.getAllBlockStates());
stacks.addAll(bom.stackHashes());
}
this.blockSet = ImmutableSet.copyOf(blocks);
this.blockStateSet = ImmutableSet.copyOf(blockStates);
this.stackHashes = ImmutableSet.copyOf(stacks);
}
public BlockOptionalMetaLookup(Block... blocks) {
this.boms = Stream.of(blocks)
this(Stream.of(blocks)
.map(BlockOptionalMeta::new)
.toArray(BlockOptionalMeta[]::new);
.toArray(BlockOptionalMeta[]::new));
}
public BlockOptionalMetaLookup(List<Block> blocks) {
this.boms = blocks.stream()
this(blocks.stream()
.map(BlockOptionalMeta::new)
.toArray(BlockOptionalMeta[]::new);
.toArray(BlockOptionalMeta[]::new));
}
public BlockOptionalMetaLookup(String... blocks) {
this.boms = Stream.of(blocks)
this(Stream.of(blocks)
.map(BlockOptionalMeta::new)
.toArray(BlockOptionalMeta[]::new);
.toArray(BlockOptionalMeta[]::new));
}
public boolean has(Block block) {
for (BlockOptionalMeta bom : boms) {
if (bom.getBlock() == block) {
return true;
}
}
return false;
return blockSet.contains(block);
}
public boolean has(BlockState state) {
for (BlockOptionalMeta bom : boms) {
if (bom.matches(state)) {
return true;
}
}
return false;
return blockStateSet.contains(state);
}
public boolean has(ItemStack stack) {
for (BlockOptionalMeta bom : boms) {
if (bom.matches(stack)) {
return true;
}
}
return false;
int hash = ((IItemStack) (Object) stack).getBaritoneHash();
hash -= stack.getDamage();
return stackHashes.contains(hash);
}
public List<BlockOptionalMeta> blocks() {

View File

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

View File

@@ -0,0 +1,38 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils;
/**
* @author Brady
*/
public enum BooleanBinaryOperators implements BooleanBinaryOperator {
OR((a, b) -> a || b),
AND((a, b) -> a && b),
XOR((a, b) -> a ^ b);
private final BooleanBinaryOperator op;
BooleanBinaryOperators(BooleanBinaryOperator op) {
this.op = op;
}
@Override
public boolean applyAsBoolean(boolean a, boolean b) {
return this.op.applyAsBoolean(a, b);
}
}

View File

@@ -43,8 +43,10 @@ public interface Helper {
Helper HELPER = new Helper() {};
/**
* Instance of the game
* The main game instance returned by {@link Minecraft#getInstance()}.
* Deprecated since {@link IPlayerContext#minecraft()} should be used instead (In the majority of cases).
*/
@Deprecated
Minecraft mc = Minecraft.getInstance();
static ITextComponent getPrefix() {
@@ -71,7 +73,7 @@ public interface Helper {
* @param message The message to display in the popup
*/
default void logToast(ITextComponent title, ITextComponent message) {
mc.execute(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
Minecraft.getInstance().execute(() -> BaritoneAPI.getSettings().toaster.value.accept(title, message));
}
/**
@@ -132,7 +134,7 @@ public interface Helper {
* @param error Whether to log as an error
*/
default void logNotificationDirect(String message, boolean error) {
mc.execute(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
Minecraft.getInstance().execute(() -> BaritoneAPI.getSettings().notifier.value.accept(message, error));
}
/**
@@ -165,7 +167,7 @@ public interface Helper {
if (logAsToast) {
logToast(getPrefix(), component);
} else {
mc.execute(() -> BaritoneAPI.getSettings().logger.value.accept(component));
Minecraft.getInstance().execute(() -> BaritoneAPI.getSettings().logger.value.accept(component));
}
}

View File

@@ -19,6 +19,7 @@ package baritone.api.utils;
import baritone.api.cache.IWorldData;
import net.minecraft.block.SlabBlock;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.world.ClientWorld;
import net.minecraft.entity.Entity;
@@ -38,6 +39,8 @@ import java.util.stream.StreamSupport;
*/
public interface IPlayerContext {
Minecraft minecraft();
ClientPlayerEntity player();
IPlayerController playerController();
@@ -86,6 +89,8 @@ public interface IPlayerContext {
return new Vector3d(player().getPositionVec().x, player().getPositionVec().y + player().getEyeHeight(), player().getPositionVec().z);
}
BetterBlockPos viewerPos();
default Rotation playerRotations() {
return new Rotation(player().rotationYaw, player().rotationPitch);
}

View File

@@ -26,12 +26,12 @@ public class Rotation {
/**
* The yaw angle of this Rotation
*/
private float yaw;
private final float yaw;
/**
* The pitch angle of this Rotation
*/
private float pitch;
private final float pitch;
public Rotation(float yaw, float pitch) {
this.yaw = yaw;
@@ -113,6 +113,10 @@ public class Rotation {
);
}
public Rotation withPitch(float pitch) {
return new Rotation(this.yaw, pitch);
}
/**
* Is really close to
*

View File

@@ -141,14 +141,14 @@ public final class RotationUtils {
* @param ctx Context for the viewing entity
* @param pos The target block position
* @return The optional rotation
* @see #reachable(ClientPlayerEntity, BlockPos, double)
* @see #reachable(IPlayerContext, BlockPos, double)
*/
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos) {
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
return reachable(ctx, pos, false);
}
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, boolean wouldSneak) {
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
return reachable(ctx, pos, ctx.playerController().getBlockReachDistance(), wouldSneak);
}
/**
@@ -158,18 +158,17 @@ public final class RotationUtils {
* side that is reachable. The return type will be {@link Optional#empty()} if the entity is
* unable to reach any of the sides of the block.
*
* @param entity The viewing entity
* @param ctx Context for the viewing entity
* @param pos The target block position
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
public static Optional<Rotation> reachable(ClientPlayerEntity entity, BlockPos pos, double blockReachDistance) {
return reachable(entity, pos, blockReachDistance, false);
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance) {
return reachable(ctx, pos, blockReachDistance, false);
}
public static Optional<Rotation> reachable(ClientPlayerEntity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
if (baritone.getPlayerContext().isLookingAt(pos)) {
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
if (BaritoneAPI.getSettings().remainWithExistingLookDirection.value && ctx.isLookingAt(pos)) {
/*
* why add 0.0001?
* to indicate that we actually have a desired pitch
@@ -180,10 +179,10 @@ public final class RotationUtils {
*
* or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level
*/
Rotation hypothetical = new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F);
Rotation hypothetical = ctx.playerRotations().add(new Rotation(0, 0.0001F));
if (wouldSneak) {
// the concern here is: what if we're looking at it now, but as soon as we start sneaking we no longer are
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, hypothetical, blockReachDistance, true);
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), hypothetical, blockReachDistance, true);
if (result != null && result.getType() == RayTraceResult.Type.BLOCK && ((BlockRayTraceResult) result).getPos().equals(pos)) {
return Optional.of(hypothetical); // yes, if we sneaked we would still be looking at the block
}
@@ -191,14 +190,14 @@ public final class RotationUtils {
return Optional.of(hypothetical);
}
}
Optional<Rotation> possibleRotation = reachableCenter(entity, pos, blockReachDistance, wouldSneak);
Optional<Rotation> possibleRotation = reachableCenter(ctx, pos, blockReachDistance, wouldSneak);
//System.out.println("center: " + possibleRotation);
if (possibleRotation.isPresent()) {
return possibleRotation;
}
BlockState state = entity.world.getBlockState(pos);
VoxelShape shape = state.getShape(entity.world, pos);
BlockState state = ctx.world().getBlockState(pos);
VoxelShape shape = state.getShape(ctx.world(), pos);
if (shape.isEmpty()) {
shape = VoxelShapes.fullCube();
}
@@ -206,7 +205,7 @@ public final class RotationUtils {
double xDiff = shape.getStart(Direction.Axis.X) * sideOffset.x + shape.getEnd(Direction.Axis.X) * (1 - sideOffset.x);
double yDiff = shape.getStart(Direction.Axis.Y) * sideOffset.y + shape.getEnd(Direction.Axis.Y) * (1 - sideOffset.y);
double zDiff = shape.getStart(Direction.Axis.Z) * sideOffset.z + shape.getEnd(Direction.Axis.Z) * (1 - sideOffset.z);
possibleRotation = reachableOffset(entity, pos, new Vector3d(pos.getX(), pos.getY(), pos.getZ()).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
possibleRotation = reachableOffset(ctx, pos, new Vector3d(pos.getX(), pos.getY(), pos.getZ()).add(xDiff, yDiff, zDiff), blockReachDistance, wouldSneak);
if (possibleRotation.isPresent()) {
return possibleRotation;
}
@@ -219,12 +218,55 @@ public final class RotationUtils {
* the given offsetted position. The return type will be {@link Optional#empty()} if
* the entity is unable to reach the block with the offset applied.
*
* @param entity The viewing entity
* @param ctx Context for the viewing entity
* @param pos The target block position
* @param offsetPos The position of the block with the offset applied.
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
public static Optional<Rotation> reachableOffset(IPlayerContext ctx, BlockPos pos, Vector3d offsetPos, double blockReachDistance, boolean wouldSneak) {
Vector3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.player().getEyePosition(1.0F);
Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, ctx.playerRotations());
Rotation actualRotation = BaritoneAPI.getProvider().getBaritoneForPlayer(ctx.player()).getLookBehavior().getAimProcessor().peekRotation(rotation);
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), actualRotation, blockReachDistance, wouldSneak);
//System.out.println(result);
if (result != null && result.getType() == RayTraceResult.Type.BLOCK) {
if (((BlockRayTraceResult) result).getPos().equals(pos)) {
return Optional.of(rotation);
}
if (ctx.world().getBlockState(pos).getBlock() instanceof AbstractFireBlock && ((BlockRayTraceResult) result).getPos().equals(pos.down())) {
return Optional.of(rotation);
}
}
return Optional.empty();
}
/**
* Determines if the specified entity is able to reach the specified block where it is
* looking at the direct center of it's hitbox.
*
* @param ctx Context for the viewing entity
* @param pos The target block position
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
public static Optional<Rotation> reachableCenter(IPlayerContext ctx, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
return reachableOffset(ctx, pos, VecUtils.calculateBlockCenter(ctx.world(), pos), blockReachDistance, wouldSneak);
}
@Deprecated
public static Optional<Rotation> reachable(ClientPlayerEntity entity, BlockPos pos, double blockReachDistance) {
return reachable(entity, pos, blockReachDistance, false);
}
@Deprecated
public static Optional<Rotation> reachable(ClientPlayerEntity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
IPlayerContext ctx = baritone.getPlayerContext();
return reachable(ctx, pos, blockReachDistance, wouldSneak);
}
@Deprecated
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vector3d offsetPos, double blockReachDistance, boolean wouldSneak) {
Vector3d eyes = wouldSneak ? RayTraceUtils.inferSneakingEyePosition(entity) : entity.getEyePosition(1.0F);
Rotation rotation = calcRotationFromVec3d(eyes, offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
@@ -241,15 +283,7 @@ public final class RotationUtils {
return Optional.empty();
}
/**
* Determines if the specified entity is able to reach the specified block where it is
* looking at the direct center of it's hitbox.
*
* @param entity The viewing entity
* @param pos The target block position
* @param blockReachDistance The block reach distance of the entity
* @return The optional rotation
*/
@Deprecated
public static Optional<Rotation> reachableCenter(Entity entity, BlockPos pos, double blockReachDistance, boolean wouldSneak) {
return reachableOffset(entity, pos, VecUtils.calculateBlockCenter(entity.world, pos), blockReachDistance, wouldSneak);
}

View File

@@ -47,12 +47,10 @@ import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SettingsUtil {
private static final Path SETTINGS_PATH = Minecraft.getInstance().gameDir.toPath().resolve("baritone").resolve("settings.txt");
public static final String SETTINGS_DEFAULT_NAME = "settings.txt";
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>.+)"); // key and value split by the first space
private static final String[] JAVA_ONLY_SETTINGS = {"logger", "notifier", "toaster"};
private static boolean isComment(String line) {
@@ -71,12 +69,12 @@ public class SettingsUtil {
}
}
public static void readAndApply(Settings settings) {
public static void readAndApply(Settings settings, String settingsName) {
try {
forEachLine(SETTINGS_PATH, line -> {
forEachLine(settingsByName(settingsName), line -> {
Matcher matcher = SETTING_PATTERN.matcher(line);
if (!matcher.matches()) {
System.out.println("Invalid syntax in setting file: " + line);
Helper.HELPER.logDirect("Invalid syntax in setting file: " + line);
return;
}
@@ -85,29 +83,33 @@ public class SettingsUtil {
try {
parseAndApply(settings, settingName, settingValue);
} catch (Exception ex) {
System.out.println("Unable to parse line " + line);
Helper.HELPER.logDirect("Unable to parse line " + line);
ex.printStackTrace();
}
});
} catch (NoSuchFileException ignored) {
System.out.println("Baritone settings file not found, resetting.");
Helper.HELPER.logDirect("Baritone settings file not found, resetting.");
} catch (Exception ex) {
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
Helper.HELPER.logDirect("Exception while reading Baritone settings, some settings may be reset to default values!");
ex.printStackTrace();
}
}
public static synchronized void save(Settings settings) {
try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) {
try (BufferedWriter out = Files.newBufferedWriter(settingsByName(SETTINGS_DEFAULT_NAME))) {
for (Settings.Setting setting : modifiedSettings(settings)) {
out.write(settingToString(setting) + "\n");
}
} catch (Exception ex) {
System.out.println("Exception thrown while saving Baritone settings!");
Helper.HELPER.logDirect("Exception thrown while saving Baritone settings!");
ex.printStackTrace();
}
}
private static Path settingsByName(String name) {
return Minecraft.getInstance().gameDir.toPath().resolve("baritone").resolve(name);
}
public static List<Settings.Setting> modifiedSettings(Settings settings) {
List<Settings.Setting> modified = new ArrayList<>();
for (Settings.Setting setting : settings.allSettings) {
@@ -115,7 +117,7 @@ public class SettingsUtil {
System.out.println("NULL SETTING?" + setting.getName());
continue;
}
if (javaOnlySetting(setting)) {
if (setting.isJavaOnly()) {
continue; // NO
}
if (setting.value == setting.defaultValue) {
@@ -169,7 +171,7 @@ public class SettingsUtil {
}
public static String settingToString(Settings.Setting setting) throws IllegalStateException {
if (javaOnlySetting(setting)) {
if (setting.isJavaOnly()) {
return setting.getName();
}
@@ -177,18 +179,14 @@ public class SettingsUtil {
}
/**
* This should always be the same as whether the setting can be parsed from or serialized to a string
* Deprecated. Use {@link Settings.Setting#isJavaOnly()} instead.
*
* @param setting The Setting
* @return true if the setting can not be set or read by the user
*/
@Deprecated
public static boolean javaOnlySetting(Settings.Setting setting) {
for (String name : JAVA_ONLY_SETTINGS) { // no JAVA_ONLY_SETTINGS.contains(...) because that would be case sensitive
if (setting.getName().equalsIgnoreCase(name)) {
return true;
}
}
return false;
return setting.isJavaOnly();
}
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {

View File

@@ -19,6 +19,7 @@ package baritone.api.utils.gui;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.platform.GlStateManager;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.toasts.IToast;
import net.minecraft.client.gui.toasts.ToastGui;
import net.minecraft.util.ResourceLocation;
@@ -74,6 +75,6 @@ public class BaritoneToast implements IToast {
}
public static void addOrUpdate(ITextComponent title, ITextComponent subtitle) {
addOrUpdate(net.minecraft.client.Minecraft.getInstance().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
addOrUpdate(Minecraft.getInstance().getToastGui(), title, subtitle, baritone.api.BaritoneAPI.getSettings().toastTimer.value);
}
}

View File

@@ -0,0 +1,46 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IBitArray;
import net.minecraft.util.BitArray;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BitArray.class)
public abstract class MixinBitArray implements IBitArray {
@Shadow
@Final
private int bitsPerEntry;
@Shadow
@Final
private long maxEntryValue;
@Override
public long getMaxEntryValue() {
return maxEntryValue;
}
@Override
public int getBitsPerEntry() {
return bitsPerEntry;
}
}

View File

@@ -61,9 +61,8 @@ public class MixinClientPlayerEntity {
method = "tick",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/player/ClientPlayerEntity.isPassenger()Z",
shift = At.Shift.BY,
by = -3
target = "net/minecraft/client/entity/player/AbstractClientPlayerEntity.tick()V",
shift = At.Shift.AFTER
)
)
private void onPreUpdate(CallbackInfo ci) {
@@ -73,22 +72,6 @@ public class MixinClientPlayerEntity {
}
}
@Inject(
method = "tick",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/entity/player/ClientPlayerEntity.onUpdateWalkingPlayer()V",
shift = At.Shift.BY,
by = 2
)
)
private void onPostUpdate(CallbackInfo ci) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
}
}
@Redirect(
method = "livingTick",
at = @At(

View File

@@ -19,6 +19,7 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.TabCompleteEvent;
import com.mojang.brigadier.ParseResults;
import com.mojang.brigadier.context.StringRange;
import com.mojang.brigadier.suggestion.Suggestion;
import com.mojang.brigadier.suggestion.Suggestions;
@@ -51,9 +52,18 @@ public class MixinCommandSuggestionHelper {
@Final
private List<String> exceptionList;
@Shadow
private ParseResults parseResults;
@Shadow
private CompletableFuture<Suggestions> suggestionsFuture;
@Shadow
private CommandSuggestionHelper.Suggestions suggestions;
@Shadow
boolean isApplyingSuggestion;
@Inject(
method = "init",
at = @At("HEAD"),
@@ -74,27 +84,32 @@ public class MixinCommandSuggestionHelper {
if (event.completions != null) {
ci.cancel();
this.parseResults = null; // stop coloring
if (this.isApplyingSuggestion) { // Supress suggestions update when cycling suggestions.
return;
}
this.inputField.setSuggestion(null); // clear old suggestions
this.suggestions = null;
// TODO: Support populating the command usage
this.exceptionList.clear();
if (event.completions.length == 0) {
this.suggestionsFuture = Suggestions.empty();
} else {
int offset = this.inputField.getText().endsWith(" ")
? this.inputField.getCursorPosition()
: this.inputField.getText().lastIndexOf(" ") + 1; // If there is no space this is still 0 haha yes
StringRange range = StringRange.between(prefix.lastIndexOf(" ") + 1, prefix.length()); // if there is no space this starts at 0
List<Suggestion> suggestionList = Stream.of(event.completions)
.map(s -> new Suggestion(StringRange.between(offset, offset + s.length()), s))
.map(s -> new Suggestion(range, s))
.collect(Collectors.toList());
Suggestions suggestions = new Suggestions(
StringRange.between(offset, offset + suggestionList.stream().mapToInt(s -> s.getText().length()).max().orElse(0)),
suggestionList);
Suggestions suggestions = new Suggestions(range, suggestionList);
this.suggestionsFuture = new CompletableFuture<>();
this.suggestionsFuture.complete(suggestions);
}
((CommandSuggestionHelper) (Object) this).updateSuggestions(true); // actually populate the suggestions list from the suggestions future
}
}
}

View File

@@ -23,6 +23,7 @@ import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
@@ -33,21 +34,25 @@ public class MixinEntity {
@Shadow
private float rotationYaw;
float yawRestore;
@Shadow
private float rotationPitch;
@Unique
private RotationMoveEvent motionUpdateRotationEvent;
@Inject(
method = "moveRelative",
at = @At("HEAD")
)
private void moveRelativeHead(CallbackInfo info) {
this.yawRestore = this.rotationYaw;
// noinspection ConstantConditions
if (!ClientPlayerEntity.class.isInstance(this) || BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this) == null) {
return;
}
RotationMoveEvent motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
this.motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this).getGameEventHandler().onPlayerRotationMove(motionUpdateRotationEvent);
this.rotationYaw = motionUpdateRotationEvent.getYaw();
this.rotationYaw = this.motionUpdateRotationEvent.getYaw();
this.rotationPitch = this.motionUpdateRotationEvent.getPitch();
}
@Inject(
@@ -55,6 +60,10 @@ public class MixinEntity {
at = @At("RETURN")
)
private void moveRelativeReturn(CallbackInfo info) {
this.rotationYaw = this.yawRestore;
if (this.motionUpdateRotationEvent != null) {
this.rotationYaw = this.motionUpdateRotationEvent.getOriginal().getYaw();
this.rotationPitch = this.motionUpdateRotationEvent.getOriginal().getPitch();
this.motionUpdateRotationEvent = null;
}
}
}

View File

@@ -25,12 +25,16 @@ import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityType;
import net.minecraft.entity.LivingEntity;
import net.minecraft.world.World;
import net.minecraft.util.math.vector.Vector3d;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import java.util.Optional;
import static org.objectweb.asm.Opcodes.GETFIELD;
/**
@@ -43,8 +47,12 @@ public abstract class MixinLivingEntity extends Entity {
/**
* Event called to override the movement direction when jumping
*/
@Unique
private RotationMoveEvent jumpRotationEvent;
@Unique
private RotationMoveEvent elytraRotationEvent;
public MixinLivingEntity(EntityType<?> entityTypeIn, World worldIn) {
super(entityTypeIn, worldIn);
}
@@ -54,14 +62,10 @@ public abstract class MixinLivingEntity extends Entity {
at = @At("HEAD")
)
private void preMoveRelative(CallbackInfo ci) {
// noinspection ConstantConditions
if (ClientPlayerEntity.class.isInstance(this)) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this);
if (baritone != null) {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
}
}
this.getBaritone().ifPresent(baritone -> {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw, this.rotationPitch);
baritone.getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
});
}
@Redirect(
@@ -79,5 +83,45 @@ public abstract class MixinLivingEntity extends Entity {
return self.rotationYaw;
}
@Inject(
method = "travel",
at = @At(
value = "INVOKE",
target = "net/minecraft/entity/LivingEntity.getLookVec()Lnet/minecraft/util/math/vector/Vector3d;"
)
)
private void onPreElytraMove(Vector3d direction, CallbackInfo ci) {
this.getBaritone().ifPresent(baritone -> {
this.elytraRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw, this.rotationPitch);
baritone.getGameEventHandler().onPlayerRotationMove(this.elytraRotationEvent);
this.rotationYaw = this.elytraRotationEvent.getYaw();
this.rotationPitch = this.elytraRotationEvent.getPitch();
});
}
@Inject(
method = "travel",
at = @At(
value = "INVOKE",
target = "net/minecraft/entity/Entity.move(Lnet/minecraft/entity/MoverType;Lnet/minecraft/util/math/vector/Vector3d;)V",
shift = At.Shift.AFTER
)
)
private void onPostElytraMove(float strafe, float vertical, float forward, CallbackInfo ci) {
if (this.elytraRotationEvent != null) {
this.rotationYaw = this.elytraRotationEvent.getOriginal().getYaw();
this.rotationPitch = this.elytraRotationEvent.getOriginal().getPitch();
this.elytraRotationEvent = null;
}
}
@Unique
private Optional<IBaritone> getBaritone() {
// noinspection ConstantConditions
if (ClientPlayerEntity.class.isInstance(this)) {
return Optional.ofNullable(BaritoneAPI.getProvider().getBaritoneForPlayer((ClientPlayerEntity) (Object) this));
} else {
return Optional.empty();
}
}
}

View File

@@ -19,6 +19,7 @@ package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
@@ -79,7 +80,21 @@ public class MixinMinecraft {
baritone.getGameEventHandler().onTick(tickProvider.apply(EventState.PRE, type));
}
}
@Inject(
method = "runTick",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/world/ClientWorld.tickEntities()V",
shift = At.Shift.AFTER
)
)
private void postUpdateEntities(CallbackInfo ci) {
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(this.player);
if (baritone != null) {
baritone.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
}
}
@Inject(

View File

@@ -0,0 +1,45 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IPalettedContainer;
import net.minecraft.util.BitArray;
import net.minecraft.util.palette.IPalette;
import net.minecraft.util.palette.PalettedContainer;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(PalettedContainer.class)
public abstract class MixinPalettedContainer<T> implements IPalettedContainer<T> {
@Shadow
protected BitArray storage;
@Shadow
protected IPalette<T> palette;
@Override
public IPalette<T> getPalette() {
return palette;
}
@Override
public BitArray getStorage() {
return storage;
}
}

View File

@@ -8,6 +8,7 @@
"maxShiftBy": 2
},
"client": [
"MixinBitArray",
"MixinChunkArray",
"MixinClientChunkProvider",
"MixinClientPlayerEntity",
@@ -20,6 +21,7 @@
"MixinLootContext",
"MixinMinecraft",
"MixinNetworkManager",
"MixinPalettedContainer",
"MixinPlayerController",
"MixinScreen",
"MixinSodiumChunkProvider",

View File

@@ -20,8 +20,9 @@ package baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.behavior.IBehavior;
import baritone.api.event.listener.IEventBus;
import baritone.api.utils.Helper;
import baritone.api.process.IBaritoneProcess;
import baritone.api.utils.IPlayerContext;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
@@ -33,16 +34,17 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.GuiClick;
import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
import baritone.utils.player.PrimaryPlayerContext;
import baritone.utils.player.BaritonePlayerContext;
import net.minecraft.client.Minecraft;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Function;
/**
* @author Brady
@@ -50,87 +52,101 @@ import java.util.concurrent.TimeUnit;
*/
public class Baritone implements IBaritone {
private static ThreadPoolExecutor threadPool;
private static File dir;
private static final ThreadPoolExecutor threadPool;
static {
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
dir = new File(Minecraft.getInstance().gameDir, "baritone");
if (!Files.exists(dir.toPath())) {
try {
Files.createDirectories(dir.toPath());
} catch (IOException ignored) {}
}
}
private GameEventHandler gameEventHandler;
private final Minecraft mc;
private final Path directory;
private PathingBehavior pathingBehavior;
private LookBehavior lookBehavior;
private InventoryBehavior inventoryBehavior;
private WaypointBehavior waypointBehavior;
private InputOverrideHandler inputOverrideHandler;
private final GameEventHandler gameEventHandler;
private FollowProcess followProcess;
private MineProcess mineProcess;
private GetToBlockProcess getToBlockProcess;
private CustomGoalProcess customGoalProcess;
private BuilderProcess builderProcess;
private ExploreProcess exploreProcess;
private BackfillProcess backfillProcess;
private FarmProcess farmProcess;
private final PathingBehavior pathingBehavior;
private final LookBehavior lookBehavior;
private final InventoryBehavior inventoryBehavior;
private final InputOverrideHandler inputOverrideHandler;
private PathingControlManager pathingControlManager;
private SelectionManager selectionManager;
private CommandManager commandManager;
private final FollowProcess followProcess;
private final MineProcess mineProcess;
private final GetToBlockProcess getToBlockProcess;
private final CustomGoalProcess customGoalProcess;
private final BuilderProcess builderProcess;
private final ExploreProcess exploreProcess;
private final FarmProcess farmProcess;
private final InventoryPauserProcess inventoryPauserProcess;
private IPlayerContext playerContext;
private WorldProvider worldProvider;
private final PathingControlManager pathingControlManager;
private final SelectionManager selectionManager;
private final CommandManager commandManager;
private final IPlayerContext playerContext;
private final WorldProvider worldProvider;
public BlockStateInterface bsi;
Baritone() {
Baritone(Minecraft mc) {
this.mc = mc;
this.gameEventHandler = new GameEventHandler(this);
this.directory = mc.gameDir.toPath().resolve("baritone");
if (!Files.exists(this.directory)) {
try {
Files.createDirectories(this.directory);
} catch (IOException ignored) {}
}
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
this.playerContext = PrimaryPlayerContext.INSTANCE;
this.playerContext = new BaritonePlayerContext(this, mc);
{
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
pathingBehavior = new PathingBehavior(this);
lookBehavior = new LookBehavior(this);
inventoryBehavior = new InventoryBehavior(this);
inputOverrideHandler = new InputOverrideHandler(this);
waypointBehavior = new WaypointBehavior(this);
this.lookBehavior = this.registerBehavior(LookBehavior::new);
this.pathingBehavior = this.registerBehavior(PathingBehavior::new);
this.inventoryBehavior = this.registerBehavior(InventoryBehavior::new);
this.inputOverrideHandler = this.registerBehavior(InputOverrideHandler::new);
this.registerBehavior(WaypointBehavior::new);
}
this.pathingControlManager = new PathingControlManager(this);
{
this.pathingControlManager.registerProcess(followProcess = new FollowProcess(this));
this.pathingControlManager.registerProcess(mineProcess = new MineProcess(this));
this.pathingControlManager.registerProcess(customGoalProcess = new CustomGoalProcess(this)); // very high iq
this.pathingControlManager.registerProcess(getToBlockProcess = new GetToBlockProcess(this));
this.pathingControlManager.registerProcess(builderProcess = new BuilderProcess(this));
this.pathingControlManager.registerProcess(exploreProcess = new ExploreProcess(this));
this.pathingControlManager.registerProcess(backfillProcess = new BackfillProcess(this));
this.pathingControlManager.registerProcess(farmProcess = new FarmProcess(this));
this.followProcess = this.registerProcess(FollowProcess::new);
this.mineProcess = this.registerProcess(MineProcess::new);
this.customGoalProcess = this.registerProcess(CustomGoalProcess::new); // very high iq
this.getToBlockProcess = this.registerProcess(GetToBlockProcess::new);
this.builderProcess = this.registerProcess(BuilderProcess::new);
this.exploreProcess = this.registerProcess(ExploreProcess::new);
this.farmProcess = this.registerProcess(FarmProcess::new);
this.inventoryPauserProcess = this.registerProcess(InventoryPauserProcess::new);
this.registerProcess(BackfillProcess::new);
}
this.worldProvider = new WorldProvider();
this.worldProvider = new WorldProvider(this);
this.selectionManager = new SelectionManager(this);
this.commandManager = new CommandManager(this);
}
public void registerBehavior(IBehavior behavior) {
this.gameEventHandler.registerEventListener(behavior);
}
public <T extends IBehavior> T registerBehavior(Function<Baritone, T> constructor) {
final T behavior = constructor.apply(this);
this.registerBehavior(behavior);
return behavior;
}
public <T extends IBaritoneProcess> T registerProcess(Function<Baritone, T> constructor) {
final T behavior = constructor.apply(this);
this.pathingControlManager.registerProcess(behavior);
return behavior;
}
@Override
public PathingControlManager getPathingControlManager() {
return this.pathingControlManager;
}
public void registerBehavior(Behavior behavior) {
this.gameEventHandler.registerEventListener(behavior);
}
@Override
public InputOverrideHandler getInputOverrideHandler() {
return this.inputOverrideHandler;
@@ -170,6 +186,7 @@ public class Baritone implements IBaritone {
return this.lookBehavior;
}
@Override
public ExploreProcess getExploreProcess() {
return this.exploreProcess;
}
@@ -179,10 +196,15 @@ public class Baritone implements IBaritone {
return this.mineProcess;
}
@Override
public FarmProcess getFarmProcess() {
return this.farmProcess;
}
public InventoryPauserProcess getInventoryPauserProcess() {
return this.inventoryPauserProcess;
}
@Override
public PathingBehavior getPathingBehavior() {
return this.pathingBehavior;
@@ -213,19 +235,19 @@ public class Baritone implements IBaritone {
new Thread(() -> {
try {
Thread.sleep(100);
Helper.mc.execute(() -> Helper.mc.displayGuiScreen(new GuiClick()));
mc.execute(() -> mc.displayGuiScreen(new GuiClick()));
} catch (Exception ignored) {}
}).start();
}
public Path getDirectory() {
return this.directory;
}
public static Settings settings() {
return BaritoneAPI.getSettings();
}
public static File getDir() {
return dir;
}
public static Executor getExecutor() {
return threadPool;
}

View File

@@ -22,13 +22,15 @@ import baritone.api.IBaritoneProvider;
import baritone.api.cache.IWorldScanner;
import baritone.api.command.ICommandSystem;
import baritone.api.schematic.ISchematicSystem;
import baritone.cache.WorldScanner;
import baritone.cache.FasterWorldScanner;
import baritone.command.CommandSystem;
import baritone.command.ExampleBaritoneControl;
import baritone.utils.schematic.SchematicSystem;
import net.minecraft.client.Minecraft;
import java.util.Collections;
import java.util.List;
import java.util.concurrent.CopyOnWriteArrayList;
/**
* @author Brady
@@ -36,30 +38,45 @@ import java.util.List;
*/
public final class BaritoneProvider implements IBaritoneProvider {
private final Baritone primary;
private final List<IBaritone> all;
private final List<IBaritone> allView;
{
this.primary = new Baritone();
this.all = Collections.singletonList(this.primary);
public BaritoneProvider() {
this.all = new CopyOnWriteArrayList<>();
this.allView = Collections.unmodifiableList(this.all);
// Setup chat control, just for the primary instance
new ExampleBaritoneControl(this.primary);
final Baritone primary = (Baritone) this.createBaritone(Minecraft.getInstance());
primary.registerBehavior(ExampleBaritoneControl::new);
}
@Override
public IBaritone getPrimaryBaritone() {
return primary;
return this.all.get(0);
}
@Override
public List<IBaritone> getAllBaritones() {
return all;
return this.allView;
}
@Override
public synchronized IBaritone createBaritone(Minecraft minecraft) {
IBaritone baritone = this.getBaritoneForMinecraft(minecraft);
if (baritone == null) {
this.all.add(baritone = new Baritone(minecraft));
}
return baritone;
}
@Override
public synchronized boolean destroyBaritone(IBaritone baritone) {
return baritone != this.getPrimaryBaritone() && this.all.remove(baritone);
}
@Override
public IWorldScanner getWorldScanner() {
return WorldScanner.INSTANCE;
return FasterWorldScanner.INSTANCE;
}
@Override

View File

@@ -35,6 +35,5 @@ public class Behavior implements IBehavior {
protected Behavior(Baritone baritone) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
baritone.registerBehavior(this);
}
}

View File

@@ -19,6 +19,7 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.event.events.TickEvent;
import baritone.api.utils.Helper;
import baritone.utils.ToolSet;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
@@ -37,7 +38,10 @@ import java.util.OptionalInt;
import java.util.Random;
import java.util.function.Predicate;
public final class InventoryBehavior extends Behavior {
public final class InventoryBehavior extends Behavior implements Helper {
int ticksSinceLastInventoryMove;
int[] lastTickRequestedMove; // not everything asks every tick, so remember the request while coming to a halt
public InventoryBehavior(Baritone baritone) {
super(baritone);
@@ -55,20 +59,28 @@ public final class InventoryBehavior extends Behavior {
// we have a crafting table or a chest or something open
return;
}
ticksSinceLastInventoryMove++;
if (firstValidThrowaway() >= 9) { // aka there are none on the hotbar, but there are some in main inventory
swapWithHotBar(firstValidThrowaway(), 8);
requestSwapWithHotBar(firstValidThrowaway(), 8);
}
int pick = bestToolAgainst(Blocks.STONE, PickaxeItem.class);
if (pick >= 9) {
swapWithHotBar(pick, 0);
requestSwapWithHotBar(pick, 0);
}
if (lastTickRequestedMove != null) {
logDebug("Remembering to move " + lastTickRequestedMove[0] + " " + lastTickRequestedMove[1] + " from a previous tick");
requestSwapWithHotBar(lastTickRequestedMove[0], lastTickRequestedMove[1]);
}
}
public void attemptToPutOnHotbar(int inMainInvy, Predicate<Integer> disallowedHotbar) {
public boolean attemptToPutOnHotbar(int inMainInvy, Predicate<Integer> disallowedHotbar) {
OptionalInt destination = getTempHotbarSlot(disallowedHotbar);
if (destination.isPresent()) {
swapWithHotBar(inMainInvy, destination.getAsInt());
if (!requestSwapWithHotBar(inMainInvy, destination.getAsInt())) {
return false;
}
}
return true;
}
public OptionalInt getTempHotbarSlot(Predicate<Integer> disallowedHotbar) {
@@ -92,8 +104,20 @@ public final class InventoryBehavior extends Behavior {
return OptionalInt.of(candidates.get(new Random().nextInt(candidates.size())));
}
private void swapWithHotBar(int inInventory, int inHotbar) {
private boolean requestSwapWithHotBar(int inInventory, int inHotbar) {
lastTickRequestedMove = new int[]{inInventory, inHotbar};
if (ticksSinceLastInventoryMove < Baritone.settings().ticksBetweenInventoryMoves.value) {
logDebug("Inventory move requested but delaying " + ticksSinceLastInventoryMove + " " + Baritone.settings().ticksBetweenInventoryMoves.value);
return false;
}
if (Baritone.settings().inventoryMoveOnlyIfStationary.value && !baritone.getInventoryPauserProcess().stationaryForInventoryMove()) {
logDebug("Inventory move requested but delaying until stationary");
return false;
}
ctx.playerController().windowClick(ctx.player().container.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
ticksSinceLastInventoryMove = 0;
lastTickRequestedMove = null;
return true;
}
private int firstValidThrowaway() { // TODO offhand idk
@@ -195,8 +219,8 @@ public final class InventoryBehavior extends Behavior {
if (allowInventory) {
for (int i = 9; i < 36; i++) {
if (desired.test(inv.get(i))) {
swapWithHotBar(i, 7);
if (select) {
requestSwapWithHotBar(i, 7);
p.inventory.currentItem = 7;
}
return true;

View File

@@ -20,44 +20,57 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.Settings;
import baritone.api.behavior.ILookBehavior;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RotationMoveEvent;
import baritone.api.behavior.look.IAimProcessor;
import baritone.api.behavior.look.ITickableAimProcessor;
import baritone.api.event.events.*;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.Rotation;
import baritone.behavior.look.ForkableRandom;
import net.minecraft.network.play.client.CPlayerPacket;
import java.util.Optional;
public final class LookBehavior extends Behavior implements ILookBehavior {
/**
* Target's values are as follows:
* The current look target, may be {@code null}.
*/
private Rotation target;
private Target target;
/**
* Whether or not rotations are currently being forced
* The rotation known to the server. Returned by {@link #getEffectiveRotation()} for use in {@link IPlayerContext}.
*/
private boolean force;
private Rotation serverRotation;
/**
* The last player yaw angle. Used when free looking
* The last player rotation. Used to restore the player's angle when using free look.
*
* @see Settings#freeLook
*/
private float lastYaw;
private Rotation prevRotation;
private final AimProcessor processor;
public LookBehavior(Baritone baritone) {
super(baritone);
this.processor = new AimProcessor(baritone.getPlayerContext());
}
@Override
public void updateTarget(Rotation target, boolean force) {
this.target = target;
if (!force) {
double rand = Math.random() - 0.5;
if (Math.abs(rand) < 0.1) {
rand *= 4;
}
this.target = new Rotation(this.target.getYaw() + (float) (rand * Baritone.settings().randomLooking113.value), this.target.getPitch());
public void updateTarget(Rotation rotation, boolean blockInteract) {
this.target = new Target(rotation, blockInteract);
}
@Override
public IAimProcessor getAimProcessor() {
return this.processor;
}
@Override
public void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.IN) {
this.processor.tick();
}
this.force = force || !Baritone.settings().freeLook.value;
}
@Override
@@ -65,35 +78,30 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
if (this.target == null) {
return;
}
// Whether or not we're going to silently set our angles
boolean silent = Baritone.settings().antiCheatCompatibility.value && !this.force;
switch (event.getState()) {
case PRE: {
if (this.force) {
ctx.player().rotationYaw = this.target.getYaw();
float oldPitch = ctx.player().rotationPitch;
float desiredPitch = this.target.getPitch();
ctx.player().rotationPitch = desiredPitch;
ctx.player().rotationYaw += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
ctx.player().rotationPitch += (Math.random() - 0.5) * Baritone.settings().randomLooking.value;
if (desiredPitch == oldPitch && !Baritone.settings().freeLook.value) {
nudgeToLevel();
}
this.target = null;
if (this.target.mode == Target.Mode.NONE) {
// Just return for PRE, we still want to set target to null on POST
return;
}
if (silent) {
this.lastYaw = ctx.player().rotationYaw;
ctx.player().rotationYaw = this.target.getYaw();
if (this.target.mode == Target.Mode.SERVER) {
this.prevRotation = new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch);
}
final Rotation actual = this.processor.peekRotation(this.target.rotation);
ctx.player().rotationYaw = actual.getYaw();
ctx.player().rotationPitch = actual.getPitch();
break;
}
case POST: {
if (silent) {
ctx.player().rotationYaw = this.lastYaw;
this.target = null;
// Reset the player's rotations back to their original values
if (this.prevRotation != null) {
ctx.player().rotationYaw = this.prevRotation.getYaw();
ctx.player().rotationPitch = this.prevRotation.getPitch();
this.prevRotation = null;
}
// The target is done being used for this game tick, so it can be invalidated
this.target = null;
break;
}
default:
@@ -101,34 +109,224 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
}
}
@Override
public void onSendPacket(PacketEvent event) {
if (!(event.getPacket() instanceof CPlayerPacket)) {
return;
}
final CPlayerPacket packet = (CPlayerPacket) event.getPacket();
if (packet instanceof CPlayerPacket.RotationPacket || packet instanceof CPlayerPacket.PositionRotationPacket) {
this.serverRotation = new Rotation(packet.getYaw(0.0f), packet.getPitch(0.0f));
}
}
@Override
public void onWorldEvent(WorldEvent event) {
this.serverRotation = null;
this.target = null;
}
public void pig() {
if (this.target != null) {
ctx.player().rotationYaw = this.target.getYaw();
final Rotation actual = this.processor.peekRotation(this.target.rotation);
ctx.player().rotationYaw = actual.getYaw();
}
}
public Optional<Rotation> getEffectiveRotation() {
if (Baritone.settings().freeLook.value) {
return Optional.ofNullable(this.serverRotation);
}
// If freeLook isn't on, just defer to the player's actual rotations
return Optional.empty();
}
@Override
public void onPlayerRotationMove(RotationMoveEvent event) {
if (this.target != null) {
final Rotation actual = this.processor.peekRotation(this.target.rotation);
event.setYaw(actual.getYaw());
event.setPitch(actual.getPitch());
}
}
event.setYaw(this.target.getYaw());
private static final class AimProcessor extends AbstractAimProcessor {
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
// Also the type has to be MOTION_UPDATE because that is called after JUMP
if (!Baritone.settings().antiCheatCompatibility.value && event.getType() == RotationMoveEvent.Type.MOTION_UPDATE && !this.force) {
this.target = null;
public AimProcessor(final IPlayerContext ctx) {
super(ctx);
}
@Override
protected Rotation getPrevRotation() {
// Implementation will use LookBehavior.serverRotation
return ctx.playerRotations();
}
}
private static abstract class AbstractAimProcessor implements ITickableAimProcessor {
protected final IPlayerContext ctx;
private final ForkableRandom rand;
private double randomYawOffset;
private double randomPitchOffset;
public AbstractAimProcessor(IPlayerContext ctx) {
this.ctx = ctx;
this.rand = new ForkableRandom();
}
private AbstractAimProcessor(final AbstractAimProcessor source) {
this.ctx = source.ctx;
this.rand = source.rand.fork();
this.randomYawOffset = source.randomYawOffset;
this.randomPitchOffset = source.randomPitchOffset;
}
@Override
public final Rotation peekRotation(final Rotation rotation) {
final Rotation prev = this.getPrevRotation();
float desiredYaw = rotation.getYaw();
float desiredPitch = rotation.getPitch();
// In other words, the target doesn't care about the pitch, so it used playerRotations().getPitch()
// and it's safe to adjust it to a normal level
if (desiredPitch == prev.getPitch()) {
desiredPitch = nudgeToLevel(desiredPitch);
}
desiredYaw += this.randomYawOffset;
desiredPitch += this.randomPitchOffset;
return new Rotation(
this.calculateMouseMove(prev.getYaw(), desiredYaw),
this.calculateMouseMove(prev.getPitch(), desiredPitch)
).clamp();
}
@Override
public final void tick() {
// randomLooking
this.randomYawOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
this.randomPitchOffset = (this.rand.nextDouble() - 0.5) * Baritone.settings().randomLooking.value;
// randomLooking113
double random = this.rand.nextDouble() - 0.5;
if (Math.abs(random) < 0.1) {
random *= 4;
}
this.randomYawOffset += random * Baritone.settings().randomLooking113.value;
}
@Override
public final void advance(int ticks) {
for (int i = 0; i < ticks; i++) {
this.tick();
}
}
@Override
public Rotation nextRotation(final Rotation rotation) {
final Rotation actual = this.peekRotation(rotation);
this.tick();
return actual;
}
@Override
public final ITickableAimProcessor fork() {
return new AbstractAimProcessor(this) {
private Rotation prev = AbstractAimProcessor.this.getPrevRotation();
@Override
public Rotation nextRotation(final Rotation rotation) {
return (this.prev = super.nextRotation(rotation));
}
@Override
protected Rotation getPrevRotation() {
return this.prev;
}
};
}
protected abstract Rotation getPrevRotation();
/**
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
*/
private float nudgeToLevel(float pitch) {
if (pitch < -20) {
return pitch + 1;
} else if (pitch > 10) {
return pitch - 1;
}
return pitch;
}
// The game uses rotation = (float) ((double) rotation + delta) so we'll do that as well
private float calculateMouseMove(float current, float target) {
final double delta = target - current;
final double deltaPx = angleToMouse(delta); // yes, even the mouse movements use double
return (float) ((double) current + mouseToAngle(deltaPx));
}
private double angleToMouse(double angleDelta) {
final double minAngleChange = mouseToAngle(1);
return Math.round(angleDelta / minAngleChange);
}
private double mouseToAngle(double mouseDelta) {
// casting float literals to double gets us the precise values used by mc
final double f = ctx.minecraft().gameSettings.mouseSensitivity * (double) 0.6f + (double) 0.2f;
return mouseDelta * f * f * f * 8.0d * 0.15d;
}
}
private static class Target {
public final Rotation rotation;
public final Mode mode;
public Target(Rotation rotation, boolean blockInteract) {
this.rotation = rotation;
this.mode = Mode.resolve(blockInteract);
}
enum Mode {
/**
* Rotation will be set client-side and is visual to the player
*/
CLIENT,
/**
* Rotation will be set server-side and is silent to the player
*/
SERVER,
/**
* Rotation will remain unaffected on both the client and server
*/
NONE;
static Mode resolve(boolean blockInteract) {
final Settings settings = Baritone.settings();
final boolean antiCheat = settings.antiCheatCompatibility.value;
final boolean blockFreeLook = settings.blockFreeLook.value;
final boolean freeLook = settings.freeLook.value;
if (!freeLook) return CLIENT;
if (!blockFreeLook && blockInteract) return CLIENT;
// Regardless of if antiCheatCompatibility is enabled, if a blockInteract is requested then the player
// rotation needs to be set somehow, otherwise Baritone will halt since objectMouseOver() will just be
// whatever the player is mousing over visually. Let's just settle for setting it silently.
if (antiCheat || blockInteract) return SERVER;
// Pathing regularly without antiCheatCompatibility, don't set the player rotation
return NONE;
}
}
}
/**
* Nudges the player's pitch to a regular level. (Between {@code -20} and {@code 10}, increments are by {@code 1})
*/
private void nudgeToLevel() {
if (ctx.player().rotationPitch < -20) {
ctx.player().rotationPitch++;
} else if (ctx.player().rotationPitch > 10) {
ctx.player().rotationPitch--;
}
}
}

View File

@@ -239,11 +239,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (current != null) {
switch (event.getState()) {
case PRE:
lastAutoJump = mc.gameSettings.autoJump;
mc.gameSettings.autoJump = false;
lastAutoJump = ctx.minecraft().gameSettings.autoJump;
ctx.minecraft().gameSettings.autoJump = false;
break;
case POST:
mc.gameSettings.autoJump = lastAutoJump;
ctx.minecraft().gameSettings.autoJump = lastAutoJump;
break;
default:
break;

View File

@@ -0,0 +1,85 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.behavior.look;
import java.util.Arrays;
import java.util.concurrent.atomic.AtomicLong;
import java.util.function.LongSupplier;
/**
* Implementation of Xoroshiro256++
* <p>
* Extended to produce random double-precision floating point numbers, and allow copies to be spawned via {@link #fork},
* which share the same internal state as the source object.
*
* @author Brady
*/
public final class ForkableRandom {
private static final double DOUBLE_UNIT = 0x1.0p-53;
private final long[] s;
public ForkableRandom() {
this(System.nanoTime() ^ System.currentTimeMillis());
}
public ForkableRandom(long seedIn) {
final AtomicLong seed = new AtomicLong(seedIn);
final LongSupplier splitmix64 = () -> {
long z = seed.addAndGet(0x9e3779b97f4a7c15L);
z = (z ^ (z >>> 30)) * 0xbf58476d1ce4e5b9L;
z = (z ^ (z >>> 27)) * 0x94d049bb133111ebL;
return z ^ (z >>> 31);
};
this.s = new long[] {
splitmix64.getAsLong(),
splitmix64.getAsLong(),
splitmix64.getAsLong(),
splitmix64.getAsLong()
};
}
private ForkableRandom(long[] s) {
this.s = s;
}
public double nextDouble() {
return (this.next() >>> 11) * DOUBLE_UNIT;
}
public long next() {
final long result = rotl(this.s[0] + this.s[3], 23) + this.s[0];
final long t = this.s[1] << 17;
this.s[2] ^= this.s[0];
this.s[3] ^= this.s[1];
this.s[1] ^= this.s[2];
this.s[0] ^= this.s[3];
this.s[2] ^= t;
this.s[3] = rotl(this.s[3], 45);
return result;
}
public ForkableRandom fork() {
return new ForkableRandom(Arrays.copyOf(this.s, 4));
}
private static long rotl(long x, int k) {
return (x << k) | (x >>> (64 - k));
}
}

View File

@@ -309,6 +309,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
try {
ChunkPos pos = toPackQueue.take();
Chunk chunk = toPackMap.remove(pos);
if (toPackQueue.size() > Baritone.settings().chunkPackerQueueMaxSize.value) {
continue;
}
CachedChunk cached = ChunkPacker.pack(chunk);
CachedWorld.this.updateCachedChunk(cached);
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);

View File

@@ -0,0 +1,261 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.cache;
import baritone.api.cache.ICachedWorld;
import baritone.api.cache.IWorldScanner;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.BlockOptionalMetaLookup;
import baritone.api.utils.IPlayerContext;
import baritone.utils.accessor.IBitArray;
import baritone.utils.accessor.IPalettedContainer;
import io.netty.buffer.Unpooled;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.network.PacketBuffer;
import net.minecraft.util.BitArray;
import net.minecraft.util.ObjectIntIdentityMap;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.util.palette.IPalette;
import net.minecraft.util.palette.PalettedContainer;
import net.minecraft.util.palette.IdentityPalette;
import net.minecraft.world.chunk.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public enum FasterWorldScanner implements IWorldScanner {
INSTANCE;
@Override
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) {
assert ctx.world() != null;
if (maxSearchRadius < 0) {
throw new IllegalArgumentException("chunkRange must be >= 0");
}
return scanChunksInternal(ctx, filter, getChunkRange(ctx.playerFeet().x >> 4, ctx.playerFeet().z >> 4, maxSearchRadius), max);
}
@Override
public List<BlockPos> scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) {
Stream<BlockPos> stream = scanChunkInternal(ctx, filter, pos);
if (max >= 0) {
stream = stream.limit(max);
}
return stream.collect(Collectors.toList());
}
@Override
public int repack(IPlayerContext ctx) {
return this.repack(ctx, 40);
}
@Override
public int repack(IPlayerContext ctx, int range) {
AbstractChunkProvider chunkProvider = ctx.world().getChunkProvider();
ICachedWorld cachedWorld = ctx.worldData().getCachedWorld();
BetterBlockPos playerPos = ctx.playerFeet();
int playerChunkX = playerPos.getX() >> 4;
int playerChunkZ = playerPos.getZ() >> 4;
int minX = playerChunkX - range;
int minZ = playerChunkZ - range;
int maxX = playerChunkX + range;
int maxZ = playerChunkZ + range;
int queued = 0;
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
Chunk chunk = chunkProvider.getChunk(x, z, false);
if (chunk != null && !chunk.isEmpty()) {
queued++;
cachedWorld.queueForPacking(chunk);
}
}
}
return queued;
}
// ordered in a way that the closest blocks are generally first
public static List<ChunkPos> getChunkRange(int centerX, int centerZ, int chunkRadius) {
List<ChunkPos> chunks = new ArrayList<>();
// spiral out
chunks.add(new ChunkPos(centerX, centerZ));
for (int i = 1; i < chunkRadius; i++) {
for (int j = 0; j <= i; j++) {
chunks.add(new ChunkPos(centerX - j, centerZ - i));
if (j != 0) {
chunks.add(new ChunkPos(centerX + j, centerZ - i));
chunks.add(new ChunkPos(centerX - j, centerZ + i));
}
chunks.add(new ChunkPos(centerX + j, centerZ + i));
if (j != i) {
chunks.add(new ChunkPos(centerX - i, centerZ - j));
chunks.add(new ChunkPos(centerX + i, centerZ - j));
if (j != 0) {
chunks.add(new ChunkPos(centerX - i, centerZ + j));
chunks.add(new ChunkPos(centerX + i, centerZ + j));
}
}
}
}
return chunks;
}
private List<BlockPos> scanChunksInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, List<ChunkPos> chunkPositions, int maxBlocks) {
assert ctx.world() != null;
try {
// p -> scanChunkInternal(ctx, lookup, p)
Stream<BlockPos> posStream = chunkPositions.parallelStream().flatMap(p -> scanChunkInternal(ctx, lookup, p));
if (maxBlocks >= 0) {
// WARNING: this can be expensive if maxBlocks is large...
// see limit's javadoc
posStream = posStream.limit(maxBlocks);
}
return posStream.collect(Collectors.toList());
} catch (Exception e) {
e.printStackTrace();
throw e;
}
}
private Stream<BlockPos> scanChunkInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, ChunkPos pos) {
AbstractChunkProvider chunkProvider = ctx.world().getChunkProvider();
// if chunk is not loaded, return empty stream
if (!chunkProvider.chunkExists(pos.x, pos.z)) {
return Stream.empty();
}
long chunkX = (long) pos.x << 4;
long chunkZ = (long) pos.z << 4;
int playerSectionY = ctx.playerFeet().y >> 4;
return collectChunkSections(lookup, chunkProvider.getChunk(pos.x, pos.z, false), chunkX, chunkZ, playerSectionY).stream();
}
private List<BlockPos> collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, long chunkX, long chunkZ, int playerSection) {
// iterate over sections relative to player
List<BlockPos> blocks = new ArrayList<>();
ChunkSection[] sections = chunk.getSections();
int l = sections.length;
int i = playerSection - 1;
int j = playerSection;
for (; i >= 0 || j < l; ++j, --i) {
if (j < l) {
visitSection(lookup, sections[j], blocks, chunkX, chunkZ);
}
if (i >= 0) {
visitSection(lookup, sections[i], blocks, chunkX, chunkZ);
}
}
return blocks;
}
private void visitSection(BlockOptionalMetaLookup lookup, ChunkSection section, List<BlockPos> blocks, long chunkX, long chunkZ) {
if (section == null || section.isEmpty()) {
return;
}
PalettedContainer<BlockState> sectionContainer = section.getData();
//this won't work if the PaletteStorage is of the type EmptyPaletteStorage
if (((IPalettedContainer<BlockState>) sectionContainer).getStorage() == null) {
return;
}
boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IPalettedContainer<BlockState>) sectionContainer).getPalette());
if (isInFilter.length == 0) {
return;
}
BitArray array = ((IPalettedContainer<BlockState>) section.getData()).getStorage();
long[] longArray = array.getBackingLongArray();
int arraySize = array.size();
int bitsPerEntry = ((IBitArray) array).getBitsPerEntry();
long maxEntryValue = ((IBitArray) array).getMaxEntryValue();
int yOffset = section.getYLocation();
for (int i = 0, idx = 0; i < longArray.length && idx < arraySize; ++i) {
long l = longArray[i];
for (int offset = 0; offset <= (64 - bitsPerEntry) && idx < arraySize; offset += bitsPerEntry, ++idx) {
int value = (int) ((l >> offset) & maxEntryValue);
if (isInFilter[value]) {
//noinspection DuplicateExpressions
blocks.add(new BlockPos(
chunkX + ((idx & 255) & 15),
yOffset + (idx >> 8),
chunkZ + ((idx & 255) >> 4)
));
}
}
}
}
private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IPalette<BlockState> palette) {
boolean commonBlockFound = false;
ObjectIntIdentityMap<BlockState> paletteMap = getPalette(palette);
int size = paletteMap.size();
boolean[] isInFilter = new boolean[size];
for (int i = 0; i < size; i++) {
BlockState state = paletteMap.getByValue(i);
if (lookup.has(state)) {
isInFilter[i] = true;
commonBlockFound = true;
} else {
isInFilter[i] = false;
}
}
if (!commonBlockFound) {
return new boolean[0];
}
return isInFilter;
}
/**
* cheats to get the actual map of id -> blockstate from the various palette implementations
*/
private static ObjectIntIdentityMap<BlockState> getPalette(IPalette<BlockState> palette) {
if (palette instanceof IdentityPalette) {
return Block.BLOCK_STATE_IDS;
} else {
PacketBuffer buf = new PacketBuffer(Unpooled.buffer());
palette.write(buf);
int size = buf.readVarInt();
ObjectIntIdentityMap<BlockState> states = new ObjectIntIdentityMap<>();
for (int i = 0; i < size; i++) {
BlockState state = Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt());
assert state != null;
states.put(state, i);
}
return states;
}
}
}

View File

@@ -19,100 +19,83 @@ package baritone.cache;
import baritone.Baritone;
import baritone.api.cache.IWorldProvider;
import baritone.api.utils.Helper;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.util.RegistryKey;
import net.minecraft.world.DimensionType;
import baritone.api.utils.IPlayerContext;
import net.minecraft.client.multiplayer.ServerData;
import net.minecraft.util.Tuple;
import net.minecraft.world.World;
import net.minecraft.world.storage.FolderName;
import org.apache.commons.lang3.SystemUtils;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.Optional;
/**
* @author Brady
* @since 8/4/2018
*/
public class WorldProvider implements IWorldProvider, Helper {
public class WorldProvider implements IWorldProvider {
private static final Map<Path, WorldData> worldCache = new HashMap<>(); // this is how the bots have the same cached world
private static final Map<Path, WorldData> worldCache = new HashMap<>();
private final Baritone baritone;
private final IPlayerContext ctx;
private WorldData currentWorld;
private World mcWorld; // this let's us detect a broken load/unload hook
/**
* This lets us detect a broken load/unload hook.
* @see #detectAndHandleBrokenLoading()
*/
private World mcWorld;
public WorldProvider(Baritone baritone) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
}
@Override
public final WorldData getCurrentWorld() {
detectAndHandleBrokenLoading();
this.detectAndHandleBrokenLoading();
return this.currentWorld;
}
/**
* Called when a new world is initialized to discover the
*
* @param world The world's Registry Data
* @param world The new world
*/
public final void initWorld(RegistryKey<World> world) {
File directory;
File readme;
public final void initWorld(World world) {
this.getSaveDirectories(world).ifPresent(dirs -> {
final Path worldDir = dirs.getA();
final Path readmeDir = dirs.getB();
IntegratedServer integratedServer = mc.getIntegratedServer();
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
if (mc.isSingleplayer()) {
directory = DimensionType.getDimensionFolder(world, integratedServer.func_240776_a_(FolderName.DOT).toFile());
// Gets the "depth" of this directory relative the the game's run directory, 2 is the location of the world
if (directory.toPath().relativize(mc.gameDir.toPath()).getNameCount() != 2) {
// subdirectory of the main save directory for this world
directory = directory.getParentFile();
}
directory = new File(directory, "baritone");
readme = directory;
} else { // Otherwise, the server must be remote...
String folderName;
if (mc.getCurrentServerData() != null) {
folderName = mc.isConnectedToRealms() ? "realms" : mc.getCurrentServerData().serverIP;
} else {
//replaymod causes null currentServerData and false singleplayer.
System.out.println("World seems to be a replay. Not loading Baritone cache.");
currentWorld = null;
mcWorld = mc.world;
return;
}
if (SystemUtils.IS_OS_WINDOWS) {
folderName = folderName.replace(":", "_");
}
directory = new File(Baritone.getDir(), folderName);
readme = Baritone.getDir();
}
// lol wtf is this baritone folder in my minecraft save?
try (FileOutputStream out = new FileOutputStream(new File(readme, "readme.txt"))) {
// good thing we have a readme
out.write("https://github.com/cabaletta/baritone\n".getBytes());
} catch (IOException ignored) {}
// We will actually store the world data in a subfolder: "DIM<id>"
Path dir = DimensionType.getDimensionFolder(world, directory).toPath();
if (!Files.exists(dir)) {
try {
Files.createDirectories(dir);
// lol wtf is this baritone folder in my minecraft save?
// good thing we have a readme
Files.createDirectories(readmeDir);
Files.write(
readmeDir.resolve("readme.txt"),
"https://github.com/cabaletta/baritone\n".getBytes(StandardCharsets.US_ASCII)
);
} catch (IOException ignored) {}
}
System.out.println("Baritone world data dir: " + dir);
synchronized (worldCache) {
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, world));
}
this.mcWorld = mc.world;
// We will actually store the world data in a subfolder: "DIM<id>"
final Path worldDataDir = this.getWorldDataDirectory(worldDir, world);
try {
Files.createDirectories(worldDataDir);
} catch (IOException ignored) {}
System.out.println("Baritone world data dir: " + worldDataDir);
synchronized (worldCache) {
this.currentWorld = worldCache.computeIfAbsent(worldDataDir, d -> new WorldData(d, world.getDimensionKey()));
}
this.mcWorld = ctx.world();
});
}
public final void closeWorld() {
@@ -125,26 +108,71 @@ public class WorldProvider implements IWorldProvider, Helper {
world.onClose();
}
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
detectAndHandleBrokenLoading();
if (this.currentWorld != null) {
currentWorldConsumer.accept(this.currentWorld);
}
private Path getWorldDataDirectory(Path parent, World world) {
return DimensionType.getDimensionFolder(world.getDimensionKey(), parent.toFile()).toPath();
}
private final void detectAndHandleBrokenLoading() {
if (this.mcWorld != mc.world) {
/**
* @param world The world
* @return An {@link Optional} containing the world's baritone dir and readme dir, or {@link Optional#empty()} if
* the world isn't valid for caching.
*/
private Optional<Tuple<Path, Path>> getSaveDirectories(World world) {
Path worldDir;
Path readmeDir;
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
if (ctx.minecraft().isSingleplayer()) {
worldDir = ctx.minecraft().getIntegratedServer().func_240776_a_(FolderName.DOT);
// Gets the "depth" of this directory relative to the game's run directory, 2 is the location of the world
if (worldDir.relativize(ctx.minecraft().gameDir.toPath()).getNameCount() != 2) {
// subdirectory of the main save directory for this world
worldDir = worldDir.getParent();
}
worldDir = worldDir.resolve("baritone");
readmeDir = worldDir;
} else { // Otherwise, the server must be remote...
String folderName;
final ServerData serverData = ctx.minecraft().getCurrentServerData();
if (serverData != null) {
folderName = ctx.minecraft().isConnectedToRealms() ? "realms" : serverData.serverIP;
} else {
//replaymod causes null currentServerData and false singleplayer.
System.out.println("World seems to be a replay. Not loading Baritone cache.");
currentWorld = null;
mcWorld = ctx.world();
return Optional.empty();
}
if (SystemUtils.IS_OS_WINDOWS) {
folderName = folderName.replace(":", "_");
}
// TODO: This should probably be in "baritone/servers"
worldDir = baritone.getDirectory().resolve(folderName);
// Just write the readme to the baritone directory instead of each server save in it
readmeDir = baritone.getDirectory();
}
return Optional.of(new Tuple<>(worldDir, readmeDir));
}
/**
* Why does this exist instead of fixing the event? Some mods break the event. Lol.
*/
private void detectAndHandleBrokenLoading() {
if (this.mcWorld != ctx.world()) {
if (this.currentWorld != null) {
System.out.println("mc.world unloaded unnoticed! Unloading Baritone cache now.");
closeWorld();
}
if (mc.world != null) {
if (ctx.world() != null) {
System.out.println("mc.world loaded unnoticed! Loading Baritone cache now.");
initWorld(mc.world.getDimensionKey());
initWorld(ctx.world());
}
} else if (currentWorld == null && mc.world != null && (mc.isSingleplayer() || mc.getCurrentServerData() != null)) {
} else if (this.currentWorld == null && ctx.world() != null && (ctx.minecraft().isSingleplayer() || ctx.minecraft().getCurrentServerData() != null)) {
System.out.println("Retrying to load Baritone cache");
initWorld(mc.world.getDimensionKey());
initWorld(ctx.world());
}
}
}

View File

@@ -17,8 +17,8 @@
package baritone.command;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.command.argument.ICommandArgument;
import baritone.api.command.exception.CommandNotEnoughArgumentsException;
@@ -27,9 +27,9 @@ import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.command.manager.ICommandManager;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.TabCompleteEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.utils.Helper;
import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior;
import baritone.command.argument.ArgConsumer;
import baritone.command.argument.CommandArguments;
import baritone.command.manager.CommandManager;
@@ -49,14 +49,14 @@ import java.util.stream.Stream;
import static baritone.api.command.IBaritoneChatControl.FORCE_COMMAND_PREFIX;
public class ExampleBaritoneControl implements Helper, AbstractGameEventListener {
public class ExampleBaritoneControl extends Behavior implements Helper {
private static final Settings settings = BaritoneAPI.getSettings();
private final ICommandManager manager;
public ExampleBaritoneControl(IBaritone baritone) {
public ExampleBaritoneControl(Baritone baritone) {
super(baritone);
this.manager = baritone.getCommandManager();
baritone.getGameEventHandler().registerEventListener(this);
}
@Override
@@ -100,7 +100,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
return false;
} else if (msg.trim().equalsIgnoreCase("orderpizza")) {
try {
((IGuiScreen) mc.currentScreen).openLinkInvoker(new URI("https://www.dominos.com/en/pages/order/"));
((IGuiScreen) ctx.minecraft().currentScreen).openLinkInvoker(new URI("https://www.dominos.com/en/pages/order/"));
} catch (NullPointerException | URISyntaxException ignored) {}
return false;
}
@@ -124,7 +124,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
}
} else if (argc.hasExactlyOne()) {
for (Settings.Setting setting : settings.allSettings) {
if (SettingsUtil.javaOnlySetting(setting)) {
if (setting.isJavaOnly()) {
continue;
}
if (setting.getName().equalsIgnoreCase(pair.getA())) {
@@ -177,7 +177,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
.stream();
}
Settings.Setting setting = settings.byLowerName.get(argc.getString().toLowerCase(Locale.US));
if (setting != null && !SettingsUtil.javaOnlySetting(setting)) {
if (setting != null && !setting.isJavaOnly()) {
if (setting.getValueClass() == Boolean.class) {
TabCompleteHelper helper = new TabCompleteHelper();
if ((Boolean) setting.value) {

View File

@@ -380,6 +380,8 @@ public class ArgConsumer implements IArgConsumer {
public <T extends IDatatype> Stream<String> tabCompleteDatatype(T datatype) {
try {
return datatype.tabComplete(this.context);
} catch (CommandException ignored) {
// NOP
} catch (Exception e) {
e.printStackTrace();
}

View File

@@ -35,10 +35,11 @@ import java.util.stream.Stream;
public class BuildCommand extends Command {
private static final File schematicsDir = new File(mc.gameDir, "schematics");
private final File schematicsDir;
public BuildCommand(IBaritone baritone) {
super(baritone, "build");
this.schematicsDir = new File(baritone.getPlayerContext().minecraft().gameDir, "schematics");
}
@Override

View File

@@ -21,9 +21,7 @@ import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.pathing.goals.GoalBlock;
import net.minecraft.entity.Entity;
import java.util.Arrays;
import java.util.List;
@@ -38,11 +36,7 @@ public class ComeCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
Entity entity = mc.getRenderViewEntity();
if (entity == null) {
throw new CommandInvalidStateException("render view entity is null");
}
baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(entity.getPosition()));
baritone.getCustomGoalProcess().setGoalAndPath(new GoalBlock(ctx.viewerPos()));
logDirect("Coming");
}

View File

@@ -41,7 +41,7 @@ public class ExploreFilterCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(2);
File file = args.getDatatypePost(RelativeFile.INSTANCE, mc.gameDir.getAbsoluteFile().getParentFile());
File file = args.getDatatypePost(RelativeFile.INSTANCE, ctx.minecraft().gameDir.getAbsoluteFile().getParentFile());
boolean invert = false;
if (args.hasAny()) {
if (args.getString().equalsIgnoreCase("invert")) {
@@ -65,7 +65,7 @@ public class ExploreFilterCommand extends Command {
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
if (args.hasExactlyOne()) {
return RelativeFile.tabComplete(args, RelativeFile.gameDir());
return RelativeFile.tabComplete(args, RelativeFile.gameDir(ctx.minecraft()));
}
return Stream.empty();
}

View File

@@ -51,7 +51,7 @@ public class GoalCommand extends Command {
}
} else {
args.requireMax(3);
BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
BetterBlockPos origin = ctx.playerFeet();
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
goalProcess.setGoal(goal);
logDirect(String.format("Goal: %s", goal.toString()));

View File

@@ -20,7 +20,6 @@ package baritone.command.defaults;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.datatypes.BlockById;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.datatypes.RelativeCoordinate;
import baritone.api.command.datatypes.RelativeGoal;
@@ -46,7 +45,7 @@ public class GotoCommand extends Command {
// is no need to handle the case of empty arguments.
if (args.peekDatatypeOrNull(RelativeCoordinate.INSTANCE) != null) {
args.requireMax(3);
BetterBlockPos origin = baritone.getPlayerContext().playerFeet();
BetterBlockPos origin = ctx.playerFeet();
Goal goal = args.getDatatypePost(RelativeGoal.INSTANCE, origin);
logDirect(String.format("Going to: %s", goal.toString()));
baritone.getCustomGoalProcess().setGoalAndPath(goal);
@@ -61,7 +60,8 @@ public class GotoCommand extends Command {
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
// since it's either a goal or a block, I don't think we can tab complete properly?
// so just tab complete for the block variant
return args.tabCompleteDatatype(BlockById.INSTANCE);
args.requireMax(1);
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
}
@Override

View File

@@ -17,14 +17,13 @@
package baritone.command.defaults;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.datatypes.BlockById;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.exception.CommandException;
import baritone.api.utils.BlockOptionalMeta;
import baritone.cache.WorldScanner;
import java.util.ArrayList;
import java.util.Arrays;
@@ -45,14 +44,18 @@ public class MineCommand extends Command {
while (args.hasAny()) {
boms.add(args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE));
}
WorldScanner.INSTANCE.repack(ctx);
BaritoneAPI.getProvider().getWorldScanner().repack(ctx);
logDirect(String.format("Mining %s", boms.toString()));
baritone.getMineProcess().mine(quantity, boms.toArray(new BlockOptionalMeta[0]));
}
@Override
public Stream<String> tabComplete(String label, IArgConsumer args) {
return args.tabCompleteDatatype(BlockById.INSTANCE);
public Stream<String> tabComplete(String label, IArgConsumer args) throws CommandException {
args.getAsOrDefault(Integer.class, 0);
while (args.has(2)) {
args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
}
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
}
@Override

View File

@@ -17,12 +17,12 @@
package baritone.command.defaults;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.api.process.ICustomGoalProcess;
import baritone.cache.WorldScanner;
import java.util.Arrays;
import java.util.List;
@@ -38,7 +38,7 @@ public class PathCommand extends Command {
public void execute(String label, IArgConsumer args) throws CommandException {
ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
args.requireMax(0);
WorldScanner.INSTANCE.repack(ctx);
BaritoneAPI.getProvider().getWorldScanner().repack(ctx);
customGoalProcess.path();
logDirect("Now pathing");
}

View File

@@ -37,8 +37,8 @@ public class RenderCommand extends Command {
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
BetterBlockPos origin = ctx.playerFeet();
int renderDistance = (mc.gameSettings.renderDistanceChunks + 1) * 16;
mc.worldRenderer.markBlockRangeForRenderUpdate(
int renderDistance = (ctx.minecraft().gameSettings.renderDistanceChunks + 1) * 16;
ctx.minecraft().worldRenderer.markBlockRangeForRenderUpdate(
origin.x - renderDistance,
0,
origin.z - renderDistance,

View File

@@ -17,11 +17,11 @@
package baritone.command.defaults;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.exception.CommandException;
import baritone.cache.WorldScanner;
import java.util.Arrays;
import java.util.List;
@@ -36,7 +36,7 @@ public class RepackCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
args.requireMax(0);
logDirect(String.format("Queued %d chunks for repacking", WorldScanner.INSTANCE.repack(ctx)));
logDirect(String.format("Queued %d chunks for repacking", BaritoneAPI.getProvider().getWorldScanner().repack(ctx)));
}
@Override

View File

@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.datatypes.ForAxis;
import baritone.api.command.datatypes.ForBlockOptionalMeta;
import baritone.api.command.datatypes.ForDirection;
import baritone.api.command.datatypes.RelativeBlockPos;
@@ -31,6 +32,8 @@ import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.schematic.*;
import baritone.api.schematic.mask.shape.CylinderMask;
import baritone.api.schematic.mask.shape.SphereMask;
import baritone.api.selection.ISelection;
import baritone.api.selection.ISelectionManager;
import baritone.api.utils.BetterBlockPos;
@@ -49,6 +52,7 @@ import java.awt.*;
import java.util.List;
import java.util.*;
import java.util.function.Function;
import java.util.function.UnaryOperator;
import java.util.stream.Stream;
public class SelCommand extends Command {
@@ -71,7 +75,7 @@ public class SelCommand extends Command {
float lineWidth = Baritone.settings().selectionLineWidth.value;
boolean ignoreDepth = Baritone.settings().renderSelectionIgnoreDepth.value;
IRenderer.startLines(color, opacity, lineWidth, ignoreDepth);
IRenderer.drawAABB(event.getModelViewStack(), new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
IRenderer.emitAABB(event.getModelViewStack(), new AxisAlignedBB(pos1, pos1.add(1, 1, 1)));
IRenderer.endLines(ignoreDepth);
}
});
@@ -87,7 +91,7 @@ public class SelCommand extends Command {
if (action == Action.POS2 && pos1 == null) {
throw new CommandInvalidStateException("Set pos1 first before using pos2");
}
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(mc.getRenderViewEntity().getPosition()) : ctx.playerFeet();
BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
if (action == Action.POS1) {
@@ -116,11 +120,13 @@ public class SelCommand extends Command {
logDirect("Undid pos2");
}
}
} else if (action == Action.SET || action == Action.WALLS || action == Action.SHELL || action == Action.CLEARAREA || action == Action.REPLACE) {
} else if (action.isFillAction()) {
BlockOptionalMeta type = action == Action.CLEARAREA
? new BlockOptionalMeta(Blocks.AIR)
: args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
BlockOptionalMetaLookup replaces = null;
final BlockOptionalMetaLookup replaces; // Action.REPLACE
final Direction.Axis alignment; // Action.(H)CYLINDER
if (action == Action.REPLACE) {
args.requireMin(1);
List<BlockOptionalMeta> replacesList = new ArrayList<>();
@@ -130,8 +136,15 @@ public class SelCommand extends Command {
}
type = args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE);
replaces = new BlockOptionalMetaLookup(replacesList.toArray(new BlockOptionalMeta[0]));
alignment = null;
} else if (action == Action.CYLINDER || action == Action.HCYLINDER) {
args.requireMax(1);
alignment = args.hasAny() ? args.getDatatypeFor(ForAxis.INSTANCE) : Direction.Axis.Y;
replaces = null;
} else {
args.requireMax(0);
replaces = null;
alignment = null;
}
ISelection[] selections = manager.getSelections();
if (selections.length == 0) {
@@ -150,20 +163,41 @@ public class SelCommand extends Command {
for (ISelection selection : selections) {
Vector3i size = selection.size();
BetterBlockPos min = selection.min();
ISchematic schematic = new FillSchematic(size.getX(), size.getY(), size.getZ(), type);
if (action == Action.WALLS) {
schematic = new WallsSchematic(schematic);
} else if (action == Action.SHELL) {
schematic = new ShellSchematic(schematic);
} else if (action == Action.REPLACE) {
schematic = new ReplaceSchematic(schematic, replaces);
}
// Java 8 so no switch expressions 😿
UnaryOperator<ISchematic> create = fill -> {
final int w = fill.widthX();
final int h = fill.heightY();
final int l = fill.lengthZ();
switch (action) {
case WALLS:
return new WallsSchematic(fill);
case SHELL:
return new ShellSchematic(fill);
case REPLACE:
return new ReplaceSchematic(fill, replaces);
case SPHERE:
return MaskSchematic.create(fill, new SphereMask(w, h, l, true).compute());
case HSPHERE:
return MaskSchematic.create(fill, new SphereMask(w, h, l, false).compute());
case CYLINDER:
return MaskSchematic.create(fill, new CylinderMask(w, h, l, true, alignment).compute());
case HCYLINDER:
return MaskSchematic.create(fill, new CylinderMask(w, h, l, false, alignment).compute());
default:
// Silent fail
return fill;
}
};
ISchematic schematic = create.apply(new FillSchematic(size.getX(), size.getY(), size.getZ(), type));
composite.put(schematic, min.x - origin.x, min.y - origin.y, min.z - origin.z);
}
baritone.getBuilderProcess().build("Fill", composite, origin);
logDirect("Filling now");
} else if (action == Action.COPY) {
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(mc.getRenderViewEntity().getPosition()) : ctx.playerFeet();
BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
ISelection[] selections = manager.getSelections();
@@ -204,7 +238,7 @@ public class SelCommand extends Command {
clipboardOffset = origin.subtract(pos);
logDirect("Selection copied");
} else if (action == Action.PASTE) {
BetterBlockPos playerPos = mc.getRenderViewEntity() != null ? BetterBlockPos.from(mc.getRenderViewEntity().getPosition()) : ctx.playerFeet();
BetterBlockPos playerPos = ctx.viewerPos();
BetterBlockPos pos = args.hasAny() ? args.getDatatypePost(RelativeBlockPos.INSTANCE, playerPos) : playerPos;
args.requireMax(0);
if (clipboard == null) {
@@ -253,12 +287,15 @@ public class SelCommand extends Command {
if (args.hasAtMost(3)) {
return args.tabCompleteDatatype(RelativeBlockPos.INSTANCE);
}
} else if (action == Action.SET || action == Action.WALLS || action == Action.CLEARAREA || action == Action.REPLACE) {
} else if (action.isFillAction()) {
if (args.hasExactlyOne() || action == Action.REPLACE) {
while (args.has(2)) {
args.get();
}
return args.tabCompleteDatatype(ForBlockOptionalMeta.INSTANCE);
} else if (args.hasExactly(2) && (action == Action.CYLINDER || action == Action.HCYLINDER)) {
args.get();
return args.tabCompleteDatatype(ForAxis.INSTANCE);
}
} else if (action == Action.EXPAND || action == Action.CONTRACT || action == Action.SHIFT) {
if (args.hasExactlyOne()) {
@@ -304,6 +341,10 @@ public class SelCommand extends Command {
"> sel set/fill/s/f [block] - Completely fill all selections with a block.",
"> sel walls/w [block] - Fill in the walls of the selection with a specified block.",
"> sel shell/shl [block] - The same as walls, but fills in a ceiling and floor too.",
"> sel sphere/sph [block] - Fills the selection with a sphere bounded by the sides.",
"> sel hsphere/hsph [block] - The same as sphere, but hollow.",
"> sel cylinder/cyl [block] <axis> - Fills the selection with a cylinder bounded by the sides, oriented about the given axis. (default=y)",
"> sel hcylinder/hcyl [block] <axis> - The same as cylinder, but hollow.",
"> sel cleararea/ca - Basically 'set air'.",
"> sel replace/r <blocks...> <with> - Replaces blocks with another block.",
"> sel copy/cp <x> <y> <z> - Copy the selected area relative to the specified or your position.",
@@ -323,6 +364,10 @@ public class SelCommand extends Command {
SET("set", "fill", "s", "f"),
WALLS("walls", "w"),
SHELL("shell", "shl"),
SPHERE("sphere", "sph"),
HSPHERE("hsphere", "hsph"),
CYLINDER("cylinder", "cyl"),
HCYLINDER("hcylinder", "hcyl"),
CLEARAREA("cleararea", "ca"),
REPLACE("replace", "r"),
EXPAND("expand", "ex"),
@@ -354,6 +399,18 @@ public class SelCommand extends Command {
}
return names.toArray(new String[0]);
}
public final boolean isFillAction() {
return this == SET
|| this == WALLS
|| this == SHELL
|| this == SPHERE
|| this == HSPHERE
|| this == CYLINDER
|| this == HCYLINDER
|| this == CLEARAREA
|| this == REPLACE;
}
}
enum TransformTarget {

View File

@@ -22,12 +22,14 @@ import baritone.api.IBaritone;
import baritone.api.Settings;
import baritone.api.command.Command;
import baritone.api.command.argument.IArgConsumer;
import baritone.api.command.datatypes.RelativeFile;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandInvalidStateException;
import baritone.api.command.exception.CommandInvalidTypeException;
import baritone.api.command.helpers.Paginator;
import baritone.api.command.helpers.TabCompleteHelper;
import baritone.api.utils.SettingsUtil;
import net.minecraft.client.Minecraft;
import net.minecraft.util.text.StringTextComponent;
import net.minecraft.util.text.TextComponent;
import net.minecraft.util.text.TextFormatting;
@@ -57,6 +59,18 @@ public class SetCommand extends Command {
logDirect("Settings saved");
return;
}
if (Arrays.asList("load", "ld").contains(arg)) {
String file = SETTINGS_DEFAULT_NAME;
if (args.hasAny()) {
file = args.getString();
}
// reset to defaults
SettingsUtil.modifiedSettings(Baritone.settings()).forEach(Settings.Setting::reset);
// then load from disk
SettingsUtil.readAndApply(Baritone.settings(), file);
logDirect("Settings reloaded from " + file);
return;
}
boolean viewModified = Arrays.asList("m", "mod", "modified").contains(arg);
boolean viewAll = Arrays.asList("all", "l", "list").contains(arg);
boolean paginate = viewModified || viewAll;
@@ -65,7 +79,7 @@ public class SetCommand extends Command {
args.requireMax(1);
List<? extends Settings.Setting> toPaginate =
(viewModified ? SettingsUtil.modifiedSettings(Baritone.settings()) : Baritone.settings().allSettings).stream()
.filter(s -> !javaOnlySetting(s))
.filter(s -> !s.isJavaOnly())
.filter(s -> s.getName().toLowerCase(Locale.US).contains(search.toLowerCase(Locale.US)))
.sorted((s1, s2) -> String.CASE_INSENSITIVE_ORDER.compare(s1.getName(), s2.getName()))
.collect(Collectors.toList());
@@ -129,7 +143,7 @@ public class SetCommand extends Command {
if (setting == null) {
throw new CommandInvalidTypeException(args.consumed(), "a valid setting");
}
if (javaOnlySetting(setting)) {
if (setting.isJavaOnly()) {
// ideally it would act as if the setting didn't exist
// but users will see it in Settings.java or its javadoc
// so at some point we have to tell them or they will see it as a bug
@@ -209,6 +223,9 @@ public class SetCommand extends Command {
.addToggleableSettings()
.filterPrefix(args.getString())
.stream();
} else if (Arrays.asList("ld", "load").contains(arg.toLowerCase(Locale.US))) {
// settings always use the directory of the main Minecraft instance
return RelativeFile.tabComplete(args, Minecraft.getInstance().gameDir.toPath().resolve("baritone").toFile());
}
Settings.Setting setting = Baritone.settings().byLowerName.get(arg.toLowerCase(Locale.US));
if (setting != null) {
@@ -228,7 +245,7 @@ public class SetCommand extends Command {
return new TabCompleteHelper()
.addSettings()
.sortAlphabetically()
.prepend("list", "modified", "reset", "toggle", "save")
.prepend("list", "modified", "reset", "toggle", "save", "load")
.filterPrefix(arg)
.stream();
}
@@ -255,7 +272,9 @@ public class SetCommand extends Command {
"> set reset all - Reset ALL SETTINGS to their defaults",
"> set reset <setting> - Reset a setting to its default",
"> set toggle <setting> - Toggle a boolean setting",
"> set save - Save all settings (this is automatic tho)"
"> set save - Save all settings (this is automatic tho)",
"> set load - Load settings from settings.txt",
"> set load [filename] - Load settings from another file in your minecraft/baritone"
);
}
}

View File

@@ -38,13 +38,13 @@ public class SurfaceCommand extends Command {
@Override
public void execute(String label, IArgConsumer args) throws CommandException {
final BetterBlockPos playerPos = baritone.getPlayerContext().playerFeet();
final int surfaceLevel = baritone.getPlayerContext().world().getSeaLevel();
final int worldHeight = baritone.getPlayerContext().world().getHeight();
final BetterBlockPos playerPos = ctx.playerFeet();
final int surfaceLevel = ctx.world().getSeaLevel();
final int worldHeight = ctx.world().getHeight();
// Ensure this command will not run if you are above the surface level and the block above you is air
// As this would imply that your are already on the open surface
if (playerPos.getY() > surfaceLevel && mc.world.getBlockState(playerPos.up()).getBlock() instanceof AirBlock) {
if (playerPos.getY() > surfaceLevel && ctx.world().getBlockState(playerPos.up()).getBlock() instanceof AirBlock) {
logDirect("Already at surface");
return;
}
@@ -54,7 +54,7 @@ public class SurfaceCommand extends Command {
for (int currentIteratedY = startingYPos; currentIteratedY < worldHeight; currentIteratedY++) {
final BetterBlockPos newPos = new BetterBlockPos(playerPos.getX(), currentIteratedY, playerPos.getZ());
if (!(mc.world.getBlockState(newPos).getBlock() instanceof AirBlock) && newPos.getY() > playerPos.getY()) {
if (!(ctx.world().getBlockState(newPos).getBlock() instanceof AirBlock) && newPos.getY() > playerPos.getY()) {
Goal goal = new GoalBlock(newPos.up());
logDirect(String.format("Going to: %s", goal.toString()));
baritone.getCustomGoalProcess().setGoalAndPath(goal);

View File

@@ -150,7 +150,11 @@ public class WaypointsCommand extends Command {
logDirect(component);
} else if (action == Action.CLEAR) {
args.requireMax(1);
IWaypoint.Tag tag = IWaypoint.Tag.getByName(args.getString());
String name = args.getString();
IWaypoint.Tag tag = IWaypoint.Tag.getByName(name);
if (tag == null) {
throw new CommandInvalidStateException("Invalid tag, \"" + name + "\"");
}
IWaypoint[] waypoints = ForWaypoints.getWaypointsByTag(this.baritone, tag);
for (IWaypoint waypoint : waypoints) {
ForWaypoints.waypoints(this.baritone).removeWaypoint(waypoint);

View File

@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.command.ICommand;
import baritone.api.command.argument.ICommandArgument;
import baritone.api.command.exception.CommandException;
import baritone.api.command.exception.CommandUnhandledException;
import baritone.api.command.exception.ICommandException;
import baritone.api.command.helpers.TabCompleteHelper;
@@ -153,9 +154,12 @@ public class CommandManager implements ICommandManager {
private Stream<String> tabComplete() {
try {
return this.command.tabComplete(this.label, this.args);
} catch (CommandException ignored) {
// NOP
} catch (Throwable t) {
return Stream.empty();
t.printStackTrace();
}
return Stream.empty();
}
}
}

View File

@@ -115,7 +115,7 @@ public final class GameEventHandler implements IEventBus, Helper {
if (event.getState() == EventState.POST) {
cache.closeWorld();
if (event.getWorld() != null) {
cache.initWorld(event.getWorld().getDimensionKey());
cache.initWorld(event.getWorld());
}
}

View File

@@ -91,8 +91,8 @@ public class CalculationContext {
this.baritone = baritone;
ClientPlayerEntity player = baritone.getPlayerContext().player();
this.world = baritone.getPlayerContext().world();
this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld();
this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread);
this.worldData = (WorldData) baritone.getPlayerContext().worldData();
this.bsi = new BlockStateInterface(baritone.getPlayerContext(), forUseOnAnotherThread);
this.toolSet = new ToolSet(player);
this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway();
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && PlayerInventory.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && world.getDimensionKey() != World.THE_NETHER;

View File

@@ -163,7 +163,7 @@ public abstract class Movement implements IMovement, MovementHelper {
if (!MovementHelper.canWalkThrough(ctx, blockPos)) { // can't break air, so don't try
somethingInTheWay = true;
MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, blockPos));
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance());
Optional<Rotation> reachable = RotationUtils.reachable(ctx, blockPos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
Rotation rotTowardsBlock = reachable.get();
state.setTarget(new MovementState.MovementTarget(rotTowardsBlock, true));

View File

@@ -637,9 +637,9 @@ public interface MovementHelper extends ActionCosts, Helper {
static void moveTowards(IPlayerContext ctx, MovementState state, BlockPos pos) {
state.setTarget(new MovementTarget(
new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(pos),
ctx.playerRotations()).getYaw(), ctx.player().rotationPitch),
ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()),
false
)).setInput(Input.MOVE_FORWARD, true);
}
@@ -744,7 +744,8 @@ public interface MovementHelper extends ActionCosts, Helper {
double faceY = (placeAt.getY() + against1.getY() + 0.5D) * 0.5D;
double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D;
Rotation place = RotationUtils.calcRotationFromVec3d(wouldSneak ? RayTraceUtils.inferSneakingEyePosition(ctx.player()) : ctx.playerHead(), new Vector3d(faceX, faceY, faceZ), ctx.playerRotations());
RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance(), wouldSneak);
Rotation actual = baritone.getLookBehavior().getAimProcessor().peekRotation(place);
RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), actual, ctx.playerController().getBlockReachDistance(), wouldSneak);
if (res != null && res.getType() == RayTraceResult.Type.BLOCK && ((BlockRayTraceResult) res).getPos().equals(against1) && ((BlockRayTraceResult) res).getPos().offset(((BlockRayTraceResult) res).getFace()).equals(placeAt)) {
state.setTarget(new MovementState.MovementTarget(place, true));
found = true;

View File

@@ -20,7 +20,6 @@ package baritone.pathing.movement.movements;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
@@ -31,10 +30,9 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.MutableMoveResult;
import com.google.common.collect.ImmutableSet;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.block.BlockState;
import net.minecraft.block.FallingBlock;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.vector.Vector3d;
@@ -234,11 +232,10 @@ public class MovementDescend extends Movement {
if (safeMode()) {
double destX = (src.getX() + 0.5) * 0.17 + (dest.getX() + 0.5) * 0.83;
double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83;
ClientPlayerEntity player = ctx.player();
state.setTarget(new MovementState.MovementTarget(
new Rotation(RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
new Vector3d(destX, dest.getY(), destZ),
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
ctx.playerRotations()).withPitch(ctx.playerRotations().getPitch()),
false
)).setInput(Input.MOVE_FORWARD, true);
return state;

View File

@@ -188,9 +188,9 @@ public class MovementPillar extends Movement {
boolean vine = fromDown.getBlock() == Blocks.VINE;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.playerHead(),
VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
ctx.playerRotations());
if (!ladder) {
state.setTarget(new MovementState.MovementTarget(new Rotation(ctx.player().rotationYaw, rotation.getPitch()), true));
state.setTarget(new MovementState.MovementTarget(ctx.playerRotations().withPitch(rotation.getPitch()), true));
}
boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder;
@@ -249,7 +249,7 @@ public class MovementPillar extends Movement {
Block fr = frState.getBlock();
// TODO: Evaluate usage of getMaterial().isReplaceable()
if (!(fr instanceof AirBlock || frState.getMaterial().isReplaceable())) {
RotationUtils.reachable(ctx.player(), src, ctx.playerController().getBlockReachDistance())
RotationUtils.reachable(ctx, src, ctx.playerController().getBlockReachDistance())
.map(rot -> new MovementState.MovementTarget(rot, true))
.ifPresent(state::setTarget);
state.setInput(Input.JUMP, false); // breaking is like 5x slower when you're jumping

View File

@@ -30,10 +30,7 @@ import baritone.api.schematic.ISchematic;
import baritone.api.schematic.IStaticSchematic;
import baritone.api.schematic.SubstituteSchematic;
import baritone.api.schematic.format.ISchematicFormat;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
@@ -163,7 +160,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
if (!format.isPresent()) {
return false;
}
ISchematic parsed;
try {
parsed = format.get().parse(new FileInputStream(schematic));
@@ -171,20 +167,22 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
e.printStackTrace();
return false;
}
if (Baritone.settings().mapArtMode.value) {
parsed = new MapArtSchematic((IStaticSchematic) parsed);
}
if (Baritone.settings().buildOnlySelection.value) {
parsed = new SelectionSchematic(parsed, origin, baritone.getSelectionManager().getSelections());
}
parsed = applyMapArtAndSelection(origin, (IStaticSchematic) parsed);
build(name, parsed, origin);
return true;
}
private ISchematic applyMapArtAndSelection(Vector3i origin, IStaticSchematic parsed) {
ISchematic schematic = parsed;
if (Baritone.settings().mapArtMode.value) {
schematic = new MapArtSchematic(parsed);
}
if (Baritone.settings().buildOnlySelection.value) {
schematic = new SelectionSchematic(schematic, origin, baritone.getSelectionManager().getSelections());
}
return schematic;
}
@Override
public void buildOpenSchematic() {
if (SchematicaHelper.isSchematicaPresent()) {
@@ -218,7 +216,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
try {
LitematicaSchematic schematic1 = new LitematicaSchematic(CompressedStreamTools.readCompressed(Files.newInputStream(LitematicaHelper.getSchematicFile(i).toPath())), false);
Vector3i correctedOrigin = LitematicaHelper.getCorrectedOrigin(schematic1, i);
LitematicaSchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
ISchematic schematic2 = LitematicaHelper.blackMagicFuckery(schematic1, i);
schematic2 = applyMapArtAndSelection(origin, (IStaticSchematic) schematic2);
build(name, schematic2, correctedOrigin);
} catch (Exception e) {
logDirect("Schematic File could not be loaded.");
@@ -282,7 +281,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
BlockState curr = bcc.bsi.get0(x, y, z);
if (!(curr.getBlock() instanceof AirBlock) && !(curr.getBlock() == Blocks.WATER || curr.getBlock() == Blocks.LAVA) && !valid(curr, desired, false)) {
BetterBlockPos pos = new BetterBlockPos(x, y, z);
Optional<Rotation> rot = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos, ctx.playerController().getBlockReachDistance());
if (rot.isPresent()) {
return Optional.of(new Tuple<>(pos, rot.get()));
}
@@ -361,9 +360,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z);
Rotation rot = RotationUtils.calcRotationFromVec3d(RayTraceUtils.inferSneakingEyePosition(ctx.player()), new Vector3d(placeX, placeY, placeZ), ctx.playerRotations());
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance(), true);
Rotation actualRot = baritone.getLookBehavior().getAimProcessor().peekRotation(rot);
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), actualRot, ctx.playerController().getBlockReachDistance(), true);
if (result != null && result.getType() == RayTraceResult.Type.BLOCK && ((BlockRayTraceResult) result).getPos().equals(placeAgainstPos) && ((BlockRayTraceResult) result).getFace() == against.getOpposite()) {
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, actualRot);
if (hotbar.isPresent()) {
return Optional.of(new Placement(hotbar.getAsInt(), placeAgainstPos, against.getOpposite(), rot));
}
@@ -573,7 +573,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
for (int i = 9; i < 36; i++) {
for (BlockState desired : noValidHotbarOption) {
if (valid(approxPlaceable.get(i), desired, true)) {
baritone.getInventoryBehavior().attemptToPutOnHotbar(i, usefulSlots::contains);
if (!baritone.getInventoryBehavior().attemptToPutOnHotbar(i, usefulSlots::contains)) {
// awaiting inventory move, so pause
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
break outer;
}
}
@@ -699,7 +702,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
incorrectPositions.forEach(pos -> {
BlockState state = bcc.bsi.get0(pos);
if (state.getBlock() instanceof AirBlock) {
if (approxPlaceable.contains(bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
if (containsBlockState(approxPlaceable, bcc.getSchematic(pos.x, pos.y, pos.z, state))) {
placeable.add(pos);
} else {
BlockState desired = bcc.getSchematic(pos.x, pos.y, pos.z, state);
@@ -772,6 +775,28 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return primary.heuristic(x, y, z);
}
@Override
public boolean equals(Object o) {
if (this == o) {
return true;
}
if (o == null || getClass() != o.getClass()) {
return false;
}
JankyGoalComposite goal = (JankyGoalComposite) o;
return Objects.equals(primary, goal.primary)
&& Objects.equals(fallback, goal.fallback);
}
@Override
public int hashCode() {
int hash = -1701079641;
hash = hash * 1196141026 + primary.hashCode();
hash = hash * -80327868 + fallback.hashCode();
return hash;
}
@Override
public String toString() {
return "JankyComposite Primary: " + primary + " Fallback: " + fallback;
@@ -793,6 +818,21 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
// but any other adjacent works for breaking, including inside or below
return super.isInGoal(x, y, z);
}
@Override
public String toString() {
return String.format(
"GoalBreak{x=%s,y=%s,z=%s}",
SettingsUtil.maybeCensor(x),
SettingsUtil.maybeCensor(y),
SettingsUtil.maybeCensor(z)
);
}
@Override
public int hashCode() {
return super.hashCode() * 1636324008;
}
}
private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
@@ -836,6 +876,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
this.allowSameLevel = allowSameLevel;
}
@Override
public boolean isInGoal(int x, int y, int z) {
if (x == this.x && y == this.y && z == this.z) {
return false;
@@ -852,10 +893,41 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return super.isInGoal(x, y, z);
}
@Override
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
@Override
public boolean equals(Object o) {
if (!super.equals(o)) {
return false;
}
GoalAdjacent goal = (GoalAdjacent) o;
return allowSameLevel == goal.allowSameLevel
&& Objects.equals(no, goal.no);
}
@Override
public int hashCode() {
int hash = 806368046;
hash = hash * 1412661222 + super.hashCode();
hash = hash * 1730799370 + (int) BetterBlockPos.longHash(no.getX(), no.getY(), no.getZ());
hash = hash * 260592149 + (allowSameLevel ? -1314802005 : 1565710265);
return hash;
}
@Override
public String toString() {
return String.format(
"GoalAdjacent{x=%s,y=%s,z=%s}",
SettingsUtil.maybeCensor(x),
SettingsUtil.maybeCensor(y),
SettingsUtil.maybeCensor(z)
);
}
}
public static class GoalPlace extends GoalBlock {
@@ -864,10 +936,26 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
super(placeAt.up());
}
@Override
public double heuristic(int x, int y, int z) {
// prioritize lower y coordinates
return this.y * 100 + super.heuristic(x, y, z);
}
@Override
public int hashCode() {
return super.hashCode() * 1910811835;
}
@Override
public String toString() {
return String.format(
"GoalPlace{x=%s,y=%s,z=%s}",
SettingsUtil.maybeCensor(x),
SettingsUtil.maybeCensor(y),
SettingsUtil.maybeCensor(z)
);
}
}
@Override
@@ -941,6 +1029,15 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
return true;
}
private boolean containsBlockState(Collection<BlockState> states, BlockState state) {
for (BlockState testee : states) {
if (sameBlockstate(testee, state)) {
return true;
}
}
return false;
}
private boolean valid(BlockState current, BlockState desired, boolean itemVerify) {
if (desired == null) {
return true;

View File

@@ -18,8 +18,10 @@
package baritone.process;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalGetToBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.process.IFarmProcess;
import baritone.api.process.PathingCommand;
@@ -28,7 +30,6 @@ import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.cache.WorldScanner;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper;
import net.minecraft.block.*;
@@ -82,6 +83,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
Items.POTATO,
Items.CARROT,
Items.NETHER_WART,
Items.COCOA_BEANS,
Blocks.SUGAR_CANE.asItem(),
Blocks.CACTUS.asItem()
);
@@ -115,6 +117,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
PUMPKIN(Blocks.PUMPKIN, state -> true),
MELON(Blocks.MELON, state -> true),
NETHERWART(Blocks.NETHER_WART, state -> state.get(NetherWartBlock.AGE) >= 3),
COCOA(Blocks.COCOA, state -> state.get(CocoaBlock.AGE) >= 2),
SUGARCANE(Blocks.SUGAR_CANE, null) {
@Override
public boolean readyToHarvest(World world, BlockPos pos, BlockState state) {
@@ -172,6 +175,10 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
return !stack.isEmpty() && stack.getItem().equals(Items.NETHER_WART);
}
private boolean isCocoa(ItemStack stack) {
return !stack.isEmpty() && stack.getItem().equals(Items.COCOA_BEANS);
}
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
ArrayList<Block> scan = new ArrayList<>();
@@ -180,13 +187,14 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
if (Baritone.settings().replantCrops.value) {
scan.add(Blocks.FARMLAND);
scan.add(Blocks.JUNGLE_LOG);
if (Baritone.settings().replantNetherWart.value) {
scan.add(Blocks.SOUL_SAND);
}
}
if (Baritone.settings().mineGoalUpdateInterval.value != 0 && tickCount++ % Baritone.settings().mineGoalUpdateInterval.value == 0) {
Baritone.getExecutor().execute(() -> locations = WorldScanner.INSTANCE.scanChunkRadius(ctx, scan, 256, 10, 10));
Baritone.getExecutor().execute(() -> locations = BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius(ctx, scan, 256, 10, 10));
}
if (locations == null) {
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
@@ -195,6 +203,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
List<BlockPos> openFarmland = new ArrayList<>();
List<BlockPos> bonemealable = new ArrayList<>();
List<BlockPos> openSoulsand = new ArrayList<>();
List<BlockPos> openLog = new ArrayList<>();
for (BlockPos pos : locations) {
//check if the target block is out of range.
if (range != 0 && pos.distanceSq(center) > range * range) {
@@ -215,6 +224,15 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
continue;
}
if (state.getBlock() == Blocks.JUNGLE_LOG) {
for (Direction direction : Direction.Plane.HORIZONTAL) {
if (ctx.world().getBlockState(pos.offset(direction)).getBlock() instanceof AirBlock) {
openLog.add(pos);
break;
}
}
continue;
}
if (readyForHarvest(ctx.world(), pos, state)) {
toBreak.add(pos);
continue;
@@ -243,7 +261,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
both.addAll(openSoulsand);
for (BlockPos pos : both) {
boolean soulsand = openSoulsand.contains(pos);
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx.player(), pos, new Vector3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, new Vector3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result instanceof BlockRayTraceResult && ((BlockRayTraceResult) result).getFace() == Direction.UP) {
@@ -255,6 +273,25 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
}
}
for (BlockPos pos : openLog) {
for (Direction dir : Direction.Plane.HORIZONTAL) {
if (!(ctx.world().getBlockState(pos.offset(dir)).getBlock() instanceof AirBlock)) {
continue;
}
Vector3d faceCenter = Vector3d.copyCentered(pos).add(Vector3d.copy(dir.getDirectionVec()).scale(0.5));
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx, pos, faceCenter, ctx.playerController().getBlockReachDistance(), false);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isCocoa)) {
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
if (result instanceof BlockRayTraceResult && ((BlockRayTraceResult) result).getFace() == dir) {
baritone.getLookBehavior().updateTarget(rot.get(), true);
if (ctx.isLookingAt(pos)) {
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
}
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
}
}
}
for (BlockPos pos : bonemealable) {
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isBoneMeal)) {
@@ -289,6 +326,15 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
goalz.add(new GoalBlock(pos.up()));
}
}
if (baritone.getInventoryBehavior().throwaway(false, this::isCocoa)) {
for (BlockPos pos : openLog) {
for (Direction direction : Direction.Plane.HORIZONTAL) {
if (ctx.world().getBlockState(pos.offset(direction)).getBlock() instanceof AirBlock) {
goalz.add(new GoalGetToBlock(pos.offset(direction)));
}
}
}
}
if (baritone.getInventoryBehavior().throwaway(false, this::isBoneMeal)) {
for (BlockPos pos : bonemealable) {
goalz.add(new GoalBlock(pos));

View File

@@ -211,7 +211,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
private boolean rightClick() {
for (BlockPos pos : knownLocations) {
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
Optional<Rotation> reachable = RotationUtils.reachable(ctx, pos, ctx.playerController().getBlockReachDistance());
if (reachable.isPresent()) {
baritone.getLookBehavior().updateTarget(reachable.get(), true);
if (knownLocations.contains(ctx.getSelectedBlock().orElse(null))) {

View File

@@ -0,0 +1,90 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.process;
import baritone.Baritone;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.utils.BaritoneProcessHelper;
public class InventoryPauserProcess extends BaritoneProcessHelper {
boolean pauseRequestedLastTick;
boolean safeToCancelLastTick;
int ticksOfStationary;
public InventoryPauserProcess(Baritone baritone) {
super(baritone);
}
@Override
public boolean isActive() {
if (ctx.player() == null || ctx.world() == null) {
return false;
}
return true;
}
private double motion() {
return ctx.player().getMotion().mul(1, 0, 1).length();
}
private boolean stationaryNow() {
return motion() < 0.00001;
}
public boolean stationaryForInventoryMove() {
pauseRequestedLastTick = true;
return safeToCancelLastTick && ticksOfStationary > 1;
}
@Override
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
//logDebug(pauseRequestedLastTick + " " + safeToCancelLastTick + " " + ticksOfStationary);
safeToCancelLastTick = isSafeToCancel;
if (pauseRequestedLastTick) {
pauseRequestedLastTick = false;
if (stationaryNow()) {
ticksOfStationary++;
}
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
}
ticksOfStationary = 0;
return new PathingCommand(null, PathingCommandType.DEFER);
}
@Override
public void onLostControl() {
}
@Override
public String displayName0() {
return "inventory pauser";
}
@Override
public double priority() {
return 5.1; // slightly higher than backfill
}
@Override
public boolean isTemporary() {
return true;
}
}

View File

@@ -18,6 +18,7 @@
package baritone.process;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.goals.*;
import baritone.api.process.IMineProcess;
import baritone.api.process.PathingCommand;
@@ -25,7 +26,6 @@ import baritone.api.process.PathingCommandType;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.cache.CachedChunk;
import baritone.cache.WorldScanner;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper;
@@ -320,6 +320,26 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
int zDiff = z - this.z;
return GoalBlock.calculate(xDiff, yDiff < -1 ? yDiff + 2 : yDiff == -1 ? 0 : yDiff, zDiff);
}
@Override
public boolean equals(Object o) {
return super.equals(o);
}
@Override
public int hashCode() {
return super.hashCode() * 393857768;
}
@Override
public String toString() {
return String.format(
"GoalThreeBlocks{x=%s,y=%s,z=%s}",
SettingsUtil.maybeCensor(x),
SettingsUtil.maybeCensor(y),
SettingsUtil.maybeCensor(z)
);
}
}
public List<BlockPos> droppedItemsScan() {
@@ -363,7 +383,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
locs = prune(ctx, locs, filter, max, blacklist, dropped);
if (!untracked.isEmpty() || (Baritone.settings().extendCacheOnThreshold.value && locs.size() < max)) {
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(
locs.addAll(BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius(
ctx.getBaritone().getPlayerContext(),
filter,
max,
@@ -398,7 +418,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
// is an x-ray and it'll get caught
if (filter.has(bsi.get0(x, y, z))) {
BlockPos pos = new BlockPos(x, y, z);
if ((Baritone.settings().legitMineIncludeDiagonals.value && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx.player(), pos, fakedBlockReachDistance).isPresent()) {
if ((Baritone.settings().legitMineIncludeDiagonals.value && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx, pos, fakedBlockReachDistance).isPresent()) {
knownOreLocations.add(pos);
}
}
@@ -438,6 +458,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
.filter(pos -> pos.getY() >= Baritone.settings().minYLevelWhileMining.value)
.filter(pos -> pos.getY() <= Baritone.settings().maxYLevelWhileMining.value)
.filter(pos -> !blacklist.contains(pos))
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().player().getPosition()::distanceSq))

View File

@@ -24,27 +24,27 @@ public class SelectionRenderer implements IRenderer, AbstractGameEventListener {
boolean ignoreDepth = settings.renderSelectionIgnoreDepth.value;
float lineWidth = settings.selectionLineWidth.value;
if (!settings.renderSelection.value) {
if (!settings.renderSelection.value || selections.length == 0) {
return;
}
IRenderer.startLines(settings.colorSelection.value, opacity, lineWidth, ignoreDepth);
for (ISelection selection : selections) {
IRenderer.drawAABB(stack, selection.aabb(), SELECTION_BOX_EXPANSION);
IRenderer.emitAABB(stack, selection.aabb(), SELECTION_BOX_EXPANSION);
}
if (settings.renderSelectionCorners.value) {
IRenderer.glColor(settings.colorSelectionPos1.value, opacity);
for (ISelection selection : selections) {
IRenderer.drawAABB(stack, new AxisAlignedBB(selection.pos1(), selection.pos1().add(1, 1, 1)));
IRenderer.emitAABB(stack, new AxisAlignedBB(selection.pos1(), selection.pos1().add(1, 1, 1)));
}
IRenderer.glColor(settings.colorSelectionPos2.value, opacity);
for (ISelection selection : selections) {
IRenderer.drawAABB(stack, new AxisAlignedBB(selection.pos2(), selection.pos2().add(1, 1, 1)));
IRenderer.emitAABB(stack, new AxisAlignedBB(selection.pos2(), selection.pos2().add(1, 1, 1)));
}
}

View File

@@ -17,7 +17,6 @@
package baritone.utils;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockRayTraceResult;
@@ -27,7 +26,7 @@ import net.minecraft.util.math.RayTraceResult;
* @author Brady
* @since 8/25/2018
*/
public final class BlockBreakHelper implements Helper {
public final class BlockBreakHelper {
private final IPlayerContext ctx;
private boolean didBreakLastTick;

View File

@@ -18,14 +18,13 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.ActionResultType;
import net.minecraft.util.Hand;
import net.minecraft.util.math.BlockRayTraceResult;
import net.minecraft.util.math.RayTraceResult;
public class BlockPlaceHelper implements Helper {
public class BlockPlaceHelper {
private final IPlayerContext ctx;
private int rightClickTimer;

View File

@@ -28,7 +28,6 @@ import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import net.minecraft.block.Block;
import net.minecraft.block.BlockState;
import net.minecraft.block.Blocks;
import net.minecraft.client.Minecraft;
import net.minecraft.client.multiplayer.ClientChunkProvider;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.IBlockReader;
@@ -46,7 +45,6 @@ public class BlockStateInterface {
private final ClientChunkProvider provider;
private final WorldData worldData;
protected final IBlockReader world;
public final BlockPos.Mutable isPassableBlockPos;
public final IBlockReader access;
public final BetterWorldBorder worldBorder;
@@ -63,20 +61,16 @@ public class BlockStateInterface {
}
public BlockStateInterface(IPlayerContext ctx, boolean copyLoadedChunks) {
this(ctx.world(), (WorldData) ctx.worldData(), copyLoadedChunks);
}
public BlockStateInterface(World world, WorldData worldData, boolean copyLoadedChunks) {
this.world = world;
final World world = ctx.world();
this.worldBorder = new BetterWorldBorder(world.getWorldBorder());
this.worldData = worldData;
this.worldData = (WorldData) ctx.worldData();
if (copyLoadedChunks) {
this.provider = ((IClientChunkProvider) world.getChunkProvider()).createThreadSafeCopy();
} else {
this.provider = (ClientChunkProvider) world.getChunkProvider();
}
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.value;
if (!Minecraft.getInstance().isOnExecutionThread()) {
if (!ctx.minecraft().isOnExecutionThread()) {
throw new IllegalStateException();
}
this.isPassableBlockPos = new BlockPos.Mutable();

View File

@@ -23,7 +23,6 @@ import baritone.api.pathing.goals.GoalBlock;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Helper;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.entity.player.ClientPlayerEntity;
import net.minecraft.client.gui.screen.Screen;
import net.minecraft.entity.Entity;
@@ -123,21 +122,11 @@ public class GuiClick extends Screen implements Helper {
// drawSingleSelectionBox WHEN?
PathRenderer.drawManySelectionBoxes(modelViewStack, e, Collections.singletonList(currentMouseOver), Color.CYAN);
if (clickStart != null && !clickStart.equals(currentMouseOver)) {
RenderSystem.enableBlend();
RenderSystem.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
RenderSystem.color4f(Color.RED.getColorComponents(null)[0], Color.RED.getColorComponents(null)[1], Color.RED.getColorComponents(null)[2], 0.4F);
RenderSystem.lineWidth(Baritone.settings().pathRenderLineWidthPixels.value);
RenderSystem.disableTexture();
RenderSystem.depthMask(false);
RenderSystem.disableDepthTest();
IRenderer.startLines(Color.RED, Baritone.settings().pathRenderLineWidthPixels.value, true);
BetterBlockPos a = new BetterBlockPos(currentMouseOver);
BetterBlockPos b = new BetterBlockPos(clickStart);
IRenderer.drawAABB(modelViewStack, new AxisAlignedBB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
RenderSystem.enableDepthTest();
RenderSystem.depthMask(true);
RenderSystem.enableTexture();
RenderSystem.disableBlend();
IRenderer.emitAABB(modelViewStack, new AxisAlignedBB(Math.min(a.x, b.x), Math.min(a.y, b.y), Math.min(a.z, b.z), Math.max(a.x, b.x) + 1, Math.max(a.y, b.y) + 1, Math.max(a.z, b.z) + 1));
IRenderer.endLines(true);
}
}
}

View File

@@ -19,12 +19,13 @@ package baritone.utils;
import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import baritone.api.utils.Helper;
import baritone.utils.accessor.IEntityRenderManager;
import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.client.Minecraft;
import net.minecraft.client.renderer.BufferBuilder;
import net.minecraft.client.renderer.Tessellator;
import net.minecraft.client.renderer.texture.TextureManager;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.util.math.AxisAlignedBB;
import net.minecraft.util.math.vector.Matrix4f;
@@ -37,12 +38,18 @@ public interface IRenderer {
Tessellator tessellator = Tessellator.getInstance();
BufferBuilder buffer = tessellator.getBuffer();
IEntityRenderManager renderManager = (IEntityRenderManager) Helper.mc.getRenderManager();
IEntityRenderManager renderManager = (IEntityRenderManager) Minecraft.getInstance().getRenderManager();
TextureManager textureManager = Minecraft.getInstance().getTextureManager();
Settings settings = BaritoneAPI.getSettings();
float[] color = new float[] {1.0F, 1.0F, 1.0F, 255.0F};
static void glColor(Color color, float alpha) {
float[] colorComponents = color.getColorComponents(null);
RenderSystem.color4f(colorComponents[0], colorComponents[1], colorComponents[2], alpha);
IRenderer.color[0] = colorComponents[0];
IRenderer.color[1] = colorComponents[1];
IRenderer.color[2] = colorComponents[2];
IRenderer.color[3] = alpha;
}
static void startLines(Color color, float alpha, float lineWidth, boolean ignoreDepth) {
@@ -56,6 +63,7 @@ public interface IRenderer {
if (ignoreDepth) {
RenderSystem.disableDepthTest();
}
buffer.begin(GL_LINES, DefaultVertexFormats.POSITION_COLOR);
}
static void startLines(Color color, float lineWidth, boolean ignoreDepth) {
@@ -63,6 +71,7 @@ public interface IRenderer {
}
static void endLines(boolean ignoredDepth) {
tessellator.draw();
if (ignoredDepth) {
RenderSystem.enableDepthTest();
}
@@ -72,42 +81,46 @@ public interface IRenderer {
RenderSystem.disableBlend();
}
static void drawAABB(MatrixStack stack, AxisAlignedBB aabb) {
static void emitAABB(MatrixStack stack, AxisAlignedBB aabb) {
AxisAlignedBB toDraw = aabb.offset(-renderManager.renderPosX(), -renderManager.renderPosY(), -renderManager.renderPosZ());
Matrix4f matrix4f = stack.getLast().getMatrix();
buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
// bottom
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
// top
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
// corners
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).endVertex();
tessellator.draw();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.maxX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.minY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) toDraw.minX, (float) toDraw.maxY, (float) toDraw.maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
}
static void drawAABB(MatrixStack stack, AxisAlignedBB aabb, double expand) {
drawAABB(stack, aabb.grow(expand, expand, expand));
static void emitAABB(MatrixStack stack, AxisAlignedBB aabb, double expand) {
emitAABB(stack, aabb.grow(expand, expand, expand));
}
static void drawAABB(MatrixStack stack, AxisAlignedBB aabb) {
buffer.begin(GL_LINES, DefaultVertexFormats.POSITION_COLOR);
emitAABB(stack, aabb);
tessellator.draw();
}
}

View File

@@ -23,7 +23,6 @@ import baritone.api.event.events.TickEvent;
import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input;
import baritone.behavior.Behavior;
import net.minecraft.client.Minecraft;
import net.minecraft.util.MovementInputFromOptions;
import java.util.HashMap;
@@ -100,7 +99,7 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
}
} else {
if (ctx.player().movementInput.getClass() == PlayerMovementInput.class) { // allow other movement inputs that aren't this one, e.g. for a freecam
ctx.player().movementInput = new MovementInputFromOptions(Minecraft.getInstance().gameSettings);
ctx.player().movementInput = new MovementInputFromOptions(ctx.minecraft().gameSettings);
}
}
// only set it if it was previously incorrect

View File

@@ -22,7 +22,7 @@ import baritone.api.event.events.RenderEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.*;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Helper;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.behavior.PathingBehavior;
import baritone.pathing.path.PathExecutor;
@@ -30,7 +30,6 @@ import com.mojang.blaze3d.matrix.MatrixStack;
import com.mojang.blaze3d.systems.RenderSystem;
import net.minecraft.block.BlockState;
import net.minecraft.client.renderer.tileentity.BeaconTileEntityRenderer;
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
import net.minecraft.entity.Entity;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.math.AxisAlignedBB;
@@ -42,6 +41,7 @@ import net.minecraft.util.math.vector.Matrix4f;
import net.minecraft.world.DimensionType;
import java.awt.*;
import java.util.Arrays;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
@@ -52,7 +52,7 @@ import static org.lwjgl.opengl.GL11.*;
* @author Brady
* @since 8/9/2018
*/
public final class PathRenderer implements IRenderer, Helper {
public final class PathRenderer implements IRenderer {
private static final ResourceLocation TEXTURE_BEACON_BEAM = new ResourceLocation("textures/entity/beacon_beam.png");
@@ -72,31 +72,27 @@ public final class PathRenderer implements IRenderer, Helper {
}
public static void render(RenderEvent event, PathingBehavior behavior) {
float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal();
if (Helper.mc.currentScreen instanceof GuiClick) {
((GuiClick) Helper.mc.currentScreen).onRender(event.getModelViewStack(), event.getProjectionMatrix());
final IPlayerContext ctx = behavior.ctx;
if (ctx.world() == null) {
return;
}
if (ctx.minecraft().currentScreen instanceof GuiClick) {
((GuiClick) ctx.minecraft().currentScreen).onRender(event.getModelViewStack(), event.getProjectionMatrix());
}
DimensionType thisPlayerDimension = behavior.baritone.getPlayerContext().world().getDimensionType();
DimensionType currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().getDimensionType();
final float partialTicks = event.getPartialTicks();
final Goal goal = behavior.getGoal();
final DimensionType thisPlayerDimension = ctx.world().getDimensionType();
final DimensionType currentRenderViewDimension = BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world().getDimensionType();
if (thisPlayerDimension != currentRenderViewDimension) {
// this is a path for a bot in a different dimension, don't render it
return;
}
Entity renderView = Helper.mc.getRenderViewEntity();
if (renderView.world != BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext().world()) {
System.out.println("I have no idea what's going on");
System.out.println("The primary baritone is in a different world than the render view entity");
System.out.println("Not rendering the path");
return;
}
if (goal != null && settings.renderGoal.value) {
drawDankLitGoalBox(event.getModelViewStack(), renderView, goal, partialTicks, settings.colorGoalBox.value);
drawGoal(event.getModelViewStack(), ctx, goal, partialTicks, settings.colorGoalBox.value);
}
if (!settings.renderPath.value) {
@@ -106,9 +102,9 @@ public final class PathRenderer implements IRenderer, Helper {
PathExecutor current = behavior.getCurrent(); // this should prevent most race conditions?
PathExecutor next = behavior.getNext(); // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
if (current != null && settings.renderSelectionBoxes.value) {
drawManySelectionBoxes(event.getModelViewStack(), renderView, current.toBreak(), settings.colorBlocksToBreak.value);
drawManySelectionBoxes(event.getModelViewStack(), renderView, current.toPlace(), settings.colorBlocksToPlace.value);
drawManySelectionBoxes(event.getModelViewStack(), renderView, current.toWalkInto(), settings.colorBlocksToWalkInto.value);
drawManySelectionBoxes(event.getModelViewStack(), ctx.player(), current.toBreak(), settings.colorBlocksToBreak.value);
drawManySelectionBoxes(event.getModelViewStack(), ctx.player(), current.toPlace(), settings.colorBlocksToPlace.value);
drawManySelectionBoxes(event.getModelViewStack(), ctx.player(), current.toWalkInto(), settings.colorBlocksToWalkInto.value);
}
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
@@ -131,12 +127,12 @@ public final class PathRenderer implements IRenderer, Helper {
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
drawPath(event.getModelViewStack(), mr, 0, settings.colorMostRecentConsidered.value, settings.fadePath.value, 10, 20);
drawManySelectionBoxes(event.getModelViewStack(), renderView, Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
drawManySelectionBoxes(event.getModelViewStack(), ctx.player(), Collections.singletonList(mr.getDest()), settings.colorMostRecentConsidered.value);
});
});
}
public static void drawPath(MatrixStack stack, IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
private static void drawPath(MatrixStack stack, IPath path, int startIndex, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
IRenderer.startLines(color, settings.pathRenderLineWidthPixels.value, settings.renderPathIgnoreDepth.value);
int fadeStart = fadeStart0 + startIndex;
@@ -172,31 +168,31 @@ public final class PathRenderer implements IRenderer, Helper {
IRenderer.glColor(color, alpha);
}
drawLine(stack, start.x, start.y, start.z, end.x, end.y, end.z);
tessellator.draw();
emitLine(stack, start.x, start.y, start.z, end.x, end.y, end.z);
}
IRenderer.endLines(settings.renderPathIgnoreDepth.value);
}
public static void drawLine(MatrixStack stack, double x1, double y1, double z1, double x2, double y2, double z2) {
private static void emitLine(MatrixStack stack, double x1, double y1, double z1, double x2, double y2, double z2) {
Matrix4f matrix4f = stack.getLast().getMatrix();
double vpX = posX();
double vpY = posY();
double vpZ = posZ();
boolean renderPathAsFrickinThingy = !settings.renderPathAsLine.value;
buffer.begin(renderPathAsFrickinThingy ? GL_LINE_STRIP : GL_LINES, DefaultVertexFormats.POSITION);
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.5D - vpY), (float) (z1 + 0.5D - vpZ)).endVertex();
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.5D - vpY), (float) (z2 + 0.5D - vpZ)).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.5D - vpY), (float) (z1 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.5D - vpY), (float) (z2 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
if (renderPathAsFrickinThingy) {
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.53D - vpY), (float) (z2 + 0.5D - vpZ)).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.53D - vpY), (float) (z1 + 0.5D - vpZ)).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.5D - vpY), (float) (z1 + 0.5D - vpZ)).endVertex();
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.5D - vpY), (float) (z2 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.53D - vpY), (float) (z2 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x2 + 0.5D - vpX), (float) (y2 + 0.53D - vpY), (float) (z2 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.53D - vpY), (float) (z1 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.53D - vpY), (float) (z1 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) (x1 + 0.5D - vpX), (float) (y1 + 0.5D - vpY), (float) (z1 + 0.5D - vpZ)).color(color[0], color[1], color[2], color[3]).endVertex();
}
}
@@ -211,13 +207,17 @@ public final class PathRenderer implements IRenderer, Helper {
VoxelShape shape = state.getShape(player.world, pos);
AxisAlignedBB toDraw = shape.isEmpty() ? VoxelShapes.fullCube().getBoundingBox() : shape.getBoundingBox();
toDraw = toDraw.offset(pos);
IRenderer.drawAABB(stack, toDraw, .002D);
IRenderer.emitAABB(stack, toDraw, .002D);
});
IRenderer.endLines(settings.renderSelectionBoxesIgnoreDepth.value);
}
public static void drawDankLitGoalBox(MatrixStack stack, Entity player, Goal goal, float partialTicks, Color color) {
private static void drawGoal(MatrixStack stack, IPlayerContext ctx, Goal goal, float partialTicks, Color color) {
drawGoal(stack, ctx, goal, partialTicks, color, true);
}
private static void drawGoal(MatrixStack stack, IPlayerContext ctx, Goal goal, float partialTicks, Color color, boolean setupRender) {
double renderPosX = posX();
double renderPosY = posY();
double renderPosZ = posZ();
@@ -249,13 +249,14 @@ public final class PathRenderer implements IRenderer, Helper {
y2 -= 0.5;
maxY--;
}
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
} else if (goal instanceof GoalXZ) {
GoalXZ goalPos = (GoalXZ) goal;
if (settings.renderGoalXZBeacon.value) {
glPushAttrib(GL_LIGHTING_BIT);
Helper.mc.getTextureManager().bindTexture(TEXTURE_BEACON_BEAM);
textureManager.bindTexture(TEXTURE_BEACON_BEAM);
if (settings.renderGoalIgnoreDepth.value) {
RenderSystem.disableDepthTest();
}
@@ -265,11 +266,11 @@ public final class PathRenderer implements IRenderer, Helper {
BeaconTileEntityRenderer.renderBeamSegment(
stack,
mc.getRenderTypeBuffers().getBufferSource(),
ctx.minecraft().getRenderTypeBuffers().getBufferSource(),
TEXTURE_BEACON_BEAM,
settings.renderGoalAnimated.value ? partialTicks : 0,
1.0F,
settings.renderGoalAnimated.value ? player.world.getGameTime() : 0,
settings.renderGoalAnimated.value ? ctx.world().getGameTime() : 0,
0,
256,
color.getColorComponents(null),
@@ -298,57 +299,73 @@ public final class PathRenderer implements IRenderer, Helper {
y2 = 0;
minY = 0 - renderPosY;
maxY = 256 - renderPosY;
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
} else if (goal instanceof GoalComposite) {
for (Goal g : ((GoalComposite) goal).goals()) {
drawDankLitGoalBox(stack, player, g, partialTicks, color);
// Simple way to determine if goals can be batched, without having some sort of GoalRenderer
boolean batch = Arrays.stream(((GoalComposite) goal).goals()).allMatch(IGoalRenderPos.class::isInstance);
if (batch) {
IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
}
for (Goal g : ((GoalComposite) goal).goals()) {
drawGoal(stack, ctx, g, partialTicks, color, !batch);
}
if (batch) {
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
}
return;
} else if (goal instanceof GoalInverted) {
drawDankLitGoalBox(stack, player, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
return;
drawGoal(stack, ctx, ((GoalInverted) goal).origin, partialTicks, settings.colorInvertedGoalBox.value);
} else if (goal instanceof GoalYLevel) {
GoalYLevel goalpos = (GoalYLevel) goal;
minX = player.getPositionVec().x - settings.yLevelBoxSize.value - renderPosX;
minZ = player.getPositionVec().z - settings.yLevelBoxSize.value - renderPosZ;
maxX = player.getPositionVec().x + settings.yLevelBoxSize.value - renderPosX;
maxZ = player.getPositionVec().z + settings.yLevelBoxSize.value - renderPosZ;
minX = ctx.player().getPositionVec().x - settings.yLevelBoxSize.value - renderPosX;
minZ = ctx.player().getPositionVec().z - settings.yLevelBoxSize.value - renderPosZ;
maxX = ctx.player().getPositionVec().x + settings.yLevelBoxSize.value - renderPosX;
maxZ = ctx.player().getPositionVec().z + settings.yLevelBoxSize.value - renderPosZ;
minY = ((GoalYLevel) goal).level - renderPosY;
maxY = minY + 2;
y1 = 1 + y + goalpos.level - renderPosY;
y2 = 1 - y + goalpos.level - renderPosY;
} else {
return;
drawDankLitGoalBox(stack, color, minX, maxX, minZ, maxZ, minY, maxY, y1, y2, setupRender);
}
}
IRenderer.startLines(color, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
private static void drawDankLitGoalBox(MatrixStack stack, Color colorIn, double minX, double maxX, double minZ, double maxZ, double minY, double maxY, double y1, double y2, boolean setupRender) {
if (setupRender) {
IRenderer.startLines(colorIn, settings.goalRenderLineWidthPixels.value, settings.renderGoalIgnoreDepth.value);
}
renderHorizontalQuad(stack, minX, maxX, minZ, maxZ, y1);
renderHorizontalQuad(stack, minX, maxX, minZ, maxZ, y2);
Matrix4f matrix4f = stack.getLast().getMatrix();
buffer.begin(GL_LINES, DefaultVertexFormats.POSITION);
buffer.pos(matrix4f, (float) minX, (float) minY, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) minX, (float) maxY, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) minY, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) maxY, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) minY, (float) maxZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) maxY, (float) maxZ).endVertex();
buffer.pos(matrix4f, (float) minX, (float) minY, (float) maxZ).endVertex();
buffer.pos(matrix4f, (float) minX, (float) maxY, (float) maxZ).endVertex();
tessellator.draw();
buffer.pos(matrix4f, (float) minX, (float) minY, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) maxY, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) minY, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) maxY, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) minY, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) maxY, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) minY, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) maxY, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
if (setupRender) {
IRenderer.endLines(settings.renderGoalIgnoreDepth.value);
}
}
private static void renderHorizontalQuad(MatrixStack stack, double minX, double maxX, double minZ, double maxZ, double y) {
if (y != 0) {
Matrix4f matrix4f = stack.getLast().getMatrix();
buffer.begin(GL_LINE_LOOP, DefaultVertexFormats.POSITION);
buffer.pos(matrix4f, (float) minX, (float) y, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) minZ).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) maxZ).endVertex();
buffer.pos(matrix4f, (float) minX, (float) y, (float) maxZ).endVertex();
tessellator.draw();
buffer.pos(matrix4f, (float) minX, (float) y, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) maxX, (float) y, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) y, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) y, (float) maxZ).color(color[0], color[1], color[2], color[3]).endVertex();
buffer.pos(matrix4f, (float) minX, (float) y, (float) minZ).color(color[0], color[1], color[2], color[3]).endVertex();
}
}
}

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