Compare commits
363 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 125c8a6742 | |||
| d8ca6cad4e | |||
| d29a37664c | |||
| 4221c07d1f | |||
| 6801d00d7e | |||
| 7b712fe677 | |||
| 4a13b54e50 | |||
| ef4de2b159 | |||
| 44ece7c510 | |||
| 07b0e2cdbf | |||
| 760f68cb05 | |||
| dce51d856b | |||
| a8ef421757 | |||
| b69acadca6 | |||
| 387e27e8de | |||
| 2533cbc2c1 | |||
| 02ebc1947b | |||
| b31930ebd2 | |||
| 83693525af | |||
| 489b9dea98 | |||
| b143dcff5f | |||
| dfd2ef055e | |||
| b45a2c94ea | |||
| fadb17f364 | |||
| 9577967da1 | |||
| 132e277388 | |||
| 5ffd21dddc | |||
| 9052781889 | |||
| 3261687ee0 | |||
| 6ad9451798 | |||
| 85babda97e | |||
| 2d969b55ef | |||
| 392395446d | |||
| d17cc96e90 | |||
| e5f8b5de5b | |||
| 99323463e3 | |||
| ead6edc574 | |||
| dcad5fb79e | |||
| 439ff92727 | |||
| 0d515b336f | |||
| e51c729acb | |||
| 9757422626 | |||
| b746e56631 | |||
| 915b03a44e | |||
| 5e063f56a2 | |||
| 63b04df95d | |||
| 8a7013d8d3 | |||
| 008422680d | |||
| db3aa5a714 | |||
| de84a49391 | |||
| 2cf9a3a74b | |||
| bba2458f8e | |||
| a45f291d67 | |||
| 1e6599cc42 | |||
| 40e86df080 | |||
| d40418d344 | |||
| 81ffbddc94 | |||
| 0c4fd39845 | |||
| 2bb01fdd20 | |||
| 69d8bd56fa | |||
| e7d41ba4fc | |||
| 8c9bb85d4b | |||
| 4f07d655d6 | |||
| 7cc23bc89b | |||
| 0bd3f9f680 | |||
| 9f156e8e27 | |||
| 288e57d275 | |||
| b8ee7f5b96 | |||
| 3fd1063e3c | |||
| ebd4930fe4 | |||
| 424113f052 | |||
| 438392840b | |||
| f51bcc8b89 | |||
| 2452a69089 | |||
| 5cfb270a32 | |||
| c367297136 | |||
| a2f0a1839a | |||
| bfafca541f | |||
| 07a9829865 | |||
| dd1a20a047 | |||
| 25c21df9fc | |||
| 53f2ab5901 | |||
| fc0d4c67f2 | |||
| 574fd05376 | |||
| 21342d6ea5 | |||
| 4690bcb5ac | |||
| 6eb293c97a | |||
| bfd41f9473 | |||
| 53d9d3da5e | |||
| ba7dc46442 | |||
| da67c4aca9 | |||
| dcfc7a1bd6 | |||
| b3b9bb8aa5 | |||
| c2fc241d89 | |||
| 4b2f98ccfd | |||
| 5151c77703 | |||
| 7473e34602 | |||
| d328438cf2 | |||
| 16f88aa858 | |||
| bac07ce100 | |||
| 31a87a8938 | |||
| 5dbf1014b3 | |||
| 12ec7ea990 | |||
| 7fd0d5799d | |||
| a1aaaef67f | |||
| 41c03cbf36 | |||
| 8c58dcb41f | |||
| f75188b24d | |||
| c63ccc3dcb | |||
| da5460413c | |||
| 9e272824c5 | |||
| 7ed13bf358 | |||
| 639ec38981 | |||
| 0e6d61e907 | |||
| 115b8553b2 | |||
| e8b108fde8 | |||
| 8d62f754a7 | |||
| 5caa0542ba | |||
| 6389917898 | |||
| 1cb25e29c7 | |||
| 5ed40ff50d | |||
| 1f73fe8c79 | |||
| 262b33f322 | |||
| 17b27af09f | |||
| f3bd50dc36 | |||
| e58c43305c | |||
| 462ccad885 | |||
| 3afd836822 | |||
| 1f97daf391 | |||
| 2e22f1cf54 | |||
| e705f9808b | |||
| 8d46c36269 | |||
| 76cdad2223 | |||
| c0bc7b5ecd | |||
| aca487f97e | |||
| e354227635 | |||
| 0b892e05cb | |||
| 3c25e2b685 | |||
| 791eb886c0 | |||
| 24c5c5d238 | |||
| c08f0f1e4d | |||
| 3f688bc45e | |||
| f10e010e20 | |||
| a93af3404b | |||
| 7cd0b186a9 | |||
| aa3a8338e6 | |||
| 606581b044 | |||
| 1734caeed8 | |||
| 51593a95e4 | |||
| 532024248f | |||
| 336b323697 | |||
| 4b41c6b1d7 | |||
| b073d591fb | |||
| be303f2e57 | |||
| 95cda79ef1 | |||
| cebdd76ca7 | |||
| 5c5507cc9e | |||
| 0342136edc | |||
| 81b0e14c9a | |||
| fb04ec6ff4 | |||
| 8d1570a11b | |||
| e553ee93b8 | |||
| 23cbef102d | |||
| 340b1558e4 | |||
| f99abd6170 | |||
| a3e5714e91 | |||
| d433cbb90b | |||
| a33b515871 | |||
| 324c3a2705 | |||
| 801f942c30 | |||
| 4e531ec578 | |||
| 804cad2776 | |||
| ff83b42132 | |||
| 557f2e48c3 | |||
| 53d477d99a | |||
| 4836f044ba | |||
| 1dc0f5c3ad | |||
| d4d2fb392a | |||
| 890e5be0ed | |||
| bf05de1de7 | |||
| 169eb1d0a3 | |||
| 01dbf75eca | |||
| c761a9b127 | |||
| c0fb57825c | |||
| df73e07923 | |||
| 09a146e0ce | |||
| 46fefa9298 | |||
| 850beb6c08 | |||
| c404258b00 | |||
| 27a3adeceb | |||
| 65bfe466bb | |||
| af3bc18079 | |||
| 43b7aece74 | |||
| 423087cc12 | |||
| 8f8bedb1b0 | |||
| 9762fe73cf | |||
| fe8e9202e2 | |||
| aca6503ac6 | |||
| 3da6b160db | |||
| 71e04ad104 | |||
| 92e0b842be | |||
| 3bf4b997b0 | |||
| 3bb1c1a972 | |||
| 5abadc6fe5 | |||
| 74916dd24e | |||
| f052c91cda | |||
| 68c2537d20 | |||
| 6408e678ff | |||
| 45631fa12a | |||
| 9a24e6a1a3 | |||
| f95e35de0a | |||
| 5f6a5ea403 | |||
| e8c644fc63 | |||
| 6dd501a46b | |||
| 50fd63647b | |||
| 91c4d8292d | |||
| 5c7ffe6ed1 | |||
| 8de7963c74 | |||
| f1fcacf241 | |||
| 5ec99977fa | |||
| 1801551d3b | |||
| 7d863ebfed | |||
| d655745d1a | |||
| f834bcec08 | |||
| 72c2a58ef2 | |||
| 32a0f4eaac | |||
| 85cf5322f9 | |||
| 879d72d715 | |||
| c6ca584847 | |||
| 199d69d79c | |||
| fdf11f9d76 | |||
| 871dc98acc | |||
| 342bb8616c | |||
| db6453fae0 | |||
| 21c1fc09e7 | |||
| 8ff89e7400 | |||
| d14d0e131b | |||
| c51a65488a | |||
| cbec60472b | |||
| 5b60d01c11 | |||
| 37d4e7b178 | |||
| 6631f9c80f | |||
| bf37d50d6f | |||
| a18ff092d8 | |||
| 830c90dd97 | |||
| 71ce9cd901 | |||
| 93de55318f | |||
| c8de4a4e00 | |||
| 6ce0f40451 | |||
| c3009b46a8 | |||
| e778a79a7b | |||
| 05ba817052 | |||
| 00b0266c43 | |||
| 18a9206058 | |||
| 42b7597cd6 | |||
| 4de52cfec2 | |||
| 85c88e669c | |||
| 8ef71da481 | |||
| 54151b9a30 | |||
| 40545c0c5d | |||
| e85f439c0f | |||
| 9accdf097f | |||
| 28be7121e3 | |||
| 90316b3359 | |||
| c14f0dac8f | |||
| d17122a777 | |||
| 559bc46702 | |||
| b3189721a6 | |||
| 9a065f55cc | |||
| c4cc0c6cdf | |||
| cacd2096ec | |||
| 14df84ef0e | |||
| b56dde8f7e | |||
| cf05e75e9a | |||
| 709822ef47 | |||
| 1889e37493 | |||
| e9308d7e70 | |||
| d0fc77ede4 | |||
| 8dd064838b | |||
| 36cbffb593 | |||
| a7abfef329 | |||
| 3ce764a472 | |||
| bde507cac6 | |||
| f9189d7ec3 | |||
| 5baa56bb29 | |||
| 2d7b465844 | |||
| dbb5d56b74 | |||
| 6a5bdf9023 | |||
| 9dcadc979e | |||
| 5760d0fb8d | |||
| 060eeb9737 | |||
| fcb947bedc | |||
| 4bf1c79830 | |||
| dab70926e2 | |||
| 7996cfe0a5 | |||
| 1251b515fa | |||
| d9a00ce164 | |||
| cd9ad69d28 | |||
| 6e7f7bfa7f | |||
| a2f539353b | |||
| c7387662f5 | |||
| e730f3a84d | |||
| 38aad9d92c | |||
| 56975c0e0f | |||
| e4e0fdd6d0 | |||
| 45f69a0f33 | |||
| a407fa66a2 | |||
| 9f12a0ab6f | |||
| 4c0d581d7f | |||
| d4a6618b55 | |||
| 71abf0c27e | |||
| c0eb94b318 | |||
| 86f45202d0 | |||
| c96b9cb6af | |||
| 843bc17777 | |||
| c5c26b73d8 | |||
| 5271b7d5c1 | |||
| eb34c1fc24 | |||
| 14dddfb1de | |||
| 194dd7abe7 | |||
| a9cac7718e | |||
| 40dd2e33f6 | |||
| 530f87ad14 | |||
| 7d6d34c5aa | |||
| 05cc63f4ff | |||
| 7623b8b386 | |||
| 5bc8adc777 | |||
| 800078a75c | |||
| a64e07685b | |||
| 8ee65f1212 | |||
| 25d3fa7676 | |||
| 177e15fc09 | |||
| 4cf5ba0fcc | |||
| 7f578bc3bf | |||
| 6f10a007d5 | |||
| d925dddb78 | |||
| 77e97b4285 | |||
| 1024a1df2d | |||
| a16301b989 | |||
| 92ec2a35c6 | |||
| e5128635fc | |||
| 0e900f2c05 | |||
| 519773493e | |||
| e3f122c371 | |||
| 1b957dc336 | |||
| 8db6438d16 | |||
| 922671c77d | |||
| d3bd6ae843 | |||
| ff108a55e6 | |||
| 494a4a8d18 | |||
| d60e0ced67 | |||
| 237ac85b6b | |||
| ee8e44d314 | |||
| d94e825a79 | |||
| 0f56af65b1 | |||
| f23683fbaa | |||
| 85dcedc26a | |||
| 47787fc128 | |||
| 1dcad9ac59 | |||
| 88b276f7c9 | |||
| bd40c9709d | |||
| fb61b47fb2 | |||
| b742704fd0 |
@@ -1,43 +0,0 @@
|
||||
# Java Gradle CircleCI 2.0 configuration file
|
||||
#
|
||||
# Check https://circleci.com/docs/2.0/language-java/ for more details
|
||||
#
|
||||
version: 2
|
||||
jobs:
|
||||
build:
|
||||
docker:
|
||||
# specify the version you desire here
|
||||
- image: circleci/openjdk:8-jdk
|
||||
|
||||
# Specify service dependencies here if necessary
|
||||
# CircleCI maintains a library of pre-built images
|
||||
# documented at https://circleci.com/docs/2.0/circleci-images/
|
||||
# - image: circleci/postgres:9.4
|
||||
|
||||
working_directory: ~/repo
|
||||
|
||||
environment:
|
||||
# Customize the JVM maximum heap limit
|
||||
JVM_OPTS: -Xmx3200m
|
||||
TERM: dumb
|
||||
|
||||
steps:
|
||||
- checkout
|
||||
|
||||
# Download and cache dependencies
|
||||
- restore_cache:
|
||||
keys:
|
||||
- v1-dependencies-{{ checksum "build.gradle" }}
|
||||
# fallback to using the latest cache if no exact match is found
|
||||
- v1-dependencies-
|
||||
|
||||
- run: gradle dependencies
|
||||
|
||||
- save_cache:
|
||||
paths:
|
||||
- ~/.gradle
|
||||
key: v1-dependencies-{{ checksum "build.gradle" }}
|
||||
|
||||
# run tests!
|
||||
- run: gradle test
|
||||
|
||||
@@ -0,0 +1 @@
|
||||
language: java
|
||||
+49
@@ -0,0 +1,49 @@
|
||||
# Pathing features
|
||||
- **Long distance pathing and splicing** Baritone calculates paths in segments, and precalculates the next segment when the current one is about to end, so that it's moving towards the goal at all times.
|
||||
- **Chunk caching** Baritone simplifies chunks to a compacted internal 2-bit representation (AIR, SOLID, WATER, AVOID) and stores them in RAM for better very-long-distance pathing. There is also an option to save these cached chunks to disk. <a href="https://www.youtube.com/watch?v=dyfYKSubhdc">Example</a>
|
||||
- **Block breaking** Baritone considers breaking blocks as part of its path. It also takes into account your current tool set and hot bar. For example, if you have a Eff V diamond pick, it may choose to mine through a stone barrier, while if you only had a wood pick it might be faster to climb over it.
|
||||
- **Block placing** Baritone considers placing blocks as part of its path. This includes sneak-back-placing, pillaring, etc. It has a configurable penalty of placing a block (set to 1 second by default), to conserve its resources. The list of acceptable throwaway blocks is also configurable, and is cobble, dirt, or netherrack by default. <a href="https://www.youtube.com/watch?v=F6FbI1L9UmU">Example</a>
|
||||
- **Falling** Baritone will fall up to 3 blocks onto solid ground (configurable, if you have Feather Falling and/or don't mind taking a little damage). If you have a water bucket on your hotbar, it will fall up to 23 blocks and place the bucket beneath it. It will fall an unlimited distance into existing still water.
|
||||
- **Vines and ladders** Baritone understands how to climb and descend vines and ladders. There is experimental support for more advanced maneuvers, like strafing to a different ladder / vine column in midair (off by default, setting named `allowVines`).
|
||||
- **Opening fence gates and doors**
|
||||
- **Slabs and stairs**
|
||||
- **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore).
|
||||
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
|
||||
- **Parkour** Sprint jumping over 1, 2, or 3 block gaps
|
||||
|
||||
# Pathing method
|
||||
Baritone uses a modified version of A*.
|
||||
|
||||
- **Incremental cost backoff** Since most of the time Baritone only knows the terrain up to the render distance, it can't calculate a full path to the goal. Therefore it needs to select a segment to execute first (assuming it will calculate the next segment at the end of this one). It uses incremental cost backoff to select the best node by varying metrics, then paths to that node. This is unchanged from MineBot and I made a <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">write-up</a> that still applies. In essence, it keeps track of the best node by various increasing coefficients, then picks the node with the least coefficient that goes at least 5 blocks from the starting position.
|
||||
- **Minimum improvement repropagation** The pathfinder ignores alternate routes that provide minimal improvements (less than 0.01 ticks of improvement), because the calculation cost of repropagating this to all connected nodes is much higher than the half-millisecond path time improvement it would get.
|
||||
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment slightly, as a tiebreaker. This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a>
|
||||
|
||||
# Configuring Baritone
|
||||
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/Settings.java">here</a>.
|
||||
To change a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `pathTimeoutMS 250`). It's case insensitive.
|
||||
|
||||
# Goals
|
||||
The pathing goal can be set to any of these options:
|
||||
- **GoalBlock** one specific block that the player should stand inside at foot level
|
||||
- **GoalXZ** an X and a Z coordinate, used for long distance pathing
|
||||
- **GoalYLevel** a Y coordinate
|
||||
- **GoalTwoBlocks** a block position that the player should stand in, either at foot or eye level
|
||||
- **GoalGetToBlock** a block position that the player should stand adjacent to, below, or on top of
|
||||
- **GoalNear** a block position that the player should get within a certain radius of, used for following entities
|
||||
|
||||
And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one of which satisfies the goal. For example, `mine diamond_ore` creates a `GoalComposite` of `GoalTwoBlocks`s for every diamond ore location it knows of.
|
||||
|
||||
|
||||
# Future features
|
||||
Things it doesn't have yet
|
||||
- Trapdoors
|
||||
- Sprint jumping in a 1x2 corridor
|
||||
- Parkour (jumping over gaps of any length) [IN PROGRESS]
|
||||
|
||||
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.
|
||||
|
||||
Things it may not ever have, from most likely to least likely =(
|
||||
- Pigs
|
||||
- Boats
|
||||
- Horses (2x3 path instead of 1x2)
|
||||
- Elytra
|
||||
@@ -0,0 +1,16 @@
|
||||
# Integration between Baritone and Impact
|
||||
|
||||
Baritone will be in Impact 4.4 with nice integrations with its utility modules, but if you're impatient you can run Baritone on top of Impact 4.3 right now.
|
||||
|
||||
You can either build Baritone yourself, or download the jar from September 4 from <a href="https://www.dropbox.com/s/imc6xwwpwsh3i0y/baritone-1.0.0.jar?dl=0">here</a>
|
||||
|
||||
To build it yourself, clone and setup Baritone (instructions in main README.md). Then, build the jar. From the command line, it's `./gradlew build` (or `gradlew build` on Windows). In IntelliJ, you can just start the `build` task in the Gradle menu.
|
||||
|
||||
Copy the jar into place. It should be `build/libs/baritone-1.0.0.jar` in baritone. Copy it to your libraries in your Minecraft install. For example, on Mac I do `cp Documents/baritone/build/libs/baritone-1.0.0.jar Library/Application\ Support/minecraft/libraries/cabaletta/baritone/1.0.0/baritone-1.0.0.jar`. The first time you'll need to make the directory `cabaletta/baritone/1.0.0` in libraries first.
|
||||
|
||||
Then, we'll need to modify the Impact launch json. Open `minecraft/versions/1.12.2-Impact_4.3/1.12.2-Impact_4.3.json` or copy your existing installation and rename the version folder, json, and id in the json.
|
||||
|
||||
- Add the Baritone tweak class to line 7 "minecraftArguments" like so: `"minecraftArguments": " ... --tweakClass clientapi.load.ClientTweaker --tweakClass baritone.launch.BaritoneTweakerOptifine",`. You need the Optifine tweaker even though there is no Optifine involved, for reasons I don't quite understand.
|
||||
- Add the Baritone library. Insert `{ "name": "cabaletta:baritone:1.0.0" },` between Impact and ClientAPI, which should be between lines 15 and 16.
|
||||
|
||||
Restart the Minecraft launcher, then load Impact 4.3 as normal, and it should now include Baritone.
|
||||
@@ -1,3 +1,57 @@
|
||||
# Baritone
|
||||
[](https://travis-ci.com/cabaletta/baritone)
|
||||
|
||||
A Minecraft bot. This project is an updated version of [Minebot](https://github.com/leijurv/MineBot/),
|
||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2.
|
||||
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2.
|
||||
|
||||
<a href="https://github.com/cabaletta/baritone/blob/master/FEATURES.md">Features</a>
|
||||
|
||||
<a href="https://github.com/cabaletta/baritone/blob/master/IMPACT.md">Baritone + Impact</a>
|
||||
|
||||
# Setup
|
||||
- Open the project in IntelliJ as a Gradle project
|
||||
- Run the Gradle task `setupDecompWorkspace`
|
||||
- Run the Gradle task `genIntellijRuns`
|
||||
- Refresh the Gradle project (or just restart IntelliJ)
|
||||
- Select the "Minecraft Client" launch config and run
|
||||
|
||||
## Command Line
|
||||
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
|
||||
|
||||
Running Baritone:
|
||||
|
||||
```
|
||||
$ gradlew run
|
||||
```
|
||||
|
||||
Setting up for IntelliJ:
|
||||
```
|
||||
$ gradlew setupDecompWorkspace
|
||||
$ gradlew --refresh-dependencies
|
||||
$ gradlew genIntellijRuns
|
||||
```
|
||||
|
||||
# Chat control
|
||||
<a href="https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java">Defined here</a>
|
||||
|
||||
Quick start example: `thisway 1000` or `goal 70` to set the goal, `path` to actually start pathing. Also try `mine diamond_ore`. `cancel` to cancel.
|
||||
|
||||
# API example
|
||||
|
||||
```
|
||||
Baritone.settings().allowSprint.value = true;
|
||||
Baritone.settings().pathTimeoutMS.value = 2000L;
|
||||
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalXZ(10000, 20000));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
```
|
||||
|
||||
# FAQ
|
||||
|
||||
## Can I use Baritone as a library in my hacked client?
|
||||
|
||||
Sure! (As long as usage is in compliance with the GPL 3 License)
|
||||
|
||||
## How is it so fast?
|
||||
|
||||
Magic
|
||||
|
||||
+18
-4
@@ -16,7 +16,7 @@
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '1.0'
|
||||
version '1.0.0'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
@@ -38,14 +38,19 @@ buildscript {
|
||||
}
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
|
||||
sourceCompatibility = targetCompatibility = '1.8'
|
||||
compileJava {
|
||||
sourceCompatibility = targetCompatibility = '1.8'
|
||||
}
|
||||
|
||||
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
sourceSets {
|
||||
launch {
|
||||
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = '1.12.2'
|
||||
@@ -65,7 +70,7 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
implementation ('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
|
||||
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
exclude module: 'launchwrapper'
|
||||
exclude module: 'guava'
|
||||
@@ -75,3 +80,12 @@ dependencies {
|
||||
}
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
mixin {
|
||||
defaultObfuscationEnv notch
|
||||
add sourceSets.launch, 'mixins.baritone.refmap.json'
|
||||
}
|
||||
|
||||
jar {
|
||||
from sourceSets.launch.output
|
||||
}
|
||||
|
||||
Vendored
+369
@@ -0,0 +1,369 @@
|
||||
-injars baritone-1.0.0.jar
|
||||
-outjars Obfuscated
|
||||
|
||||
|
||||
-keepattributes Signature
|
||||
-keepattributes *Annotation*
|
||||
|
||||
-optimizationpasses 20
|
||||
-verbose
|
||||
|
||||
-allowaccessmodification # anything not kept can be changed from public to private and inlined etc
|
||||
-mergeinterfacesaggressively
|
||||
-overloadaggressively
|
||||
-dontusemixedcaseclassnames
|
||||
|
||||
# instead of obfing to a, b, c, obf to baritone.a, baritone.b, baritone.c so as to not conflict with mcp
|
||||
-flattenpackagehierarchy
|
||||
-repackageclasses 'baritone'
|
||||
|
||||
#-keep class baritone.behavior.** { *; }
|
||||
#-keep class baritone.api.** { *; }
|
||||
#-keep class baritone.* { *; }
|
||||
#-keep class baritone.pathing.goals.** { *; }
|
||||
|
||||
# setting names are reflected from field names, so keep field names
|
||||
-keepclassmembers class baritone.Settings {
|
||||
public <fields>;
|
||||
}
|
||||
|
||||
# need to keep mixin names
|
||||
-keep class baritone.launch.** { *; }
|
||||
|
||||
# copy all necessary libraries into tempLibraries to build
|
||||
-libraryjars '/Library/Internet Plug-Ins/JavaAppletPlugin.plugin/Contents/Home/lib/rt.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/1.12.2.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/authlib-1.5.25.jar'
|
||||
-libraryjars 'tempLibraries/codecjorbis-20101023.jar'
|
||||
-libraryjars 'tempLibraries/codecwav-20101023.jar'
|
||||
-libraryjars 'tempLibraries/commons-codec-1.10.jar'
|
||||
-libraryjars 'tempLibraries/commons-compress-1.8.1.jar'
|
||||
-libraryjars 'tempLibraries/commons-io-2.5.jar'
|
||||
-libraryjars 'tempLibraries/commons-lang3-3.5.jar'
|
||||
-libraryjars 'tempLibraries/commons-logging-1.1.3.jar'
|
||||
-libraryjars 'tempLibraries/fastutil-7.1.0.jar'
|
||||
-libraryjars 'tempLibraries/gson-2.8.0.jar'
|
||||
-libraryjars 'tempLibraries/guava-21.0.jar'
|
||||
-libraryjars 'tempLibraries/httpclient-4.3.3.jar'
|
||||
-libraryjars 'tempLibraries/httpcore-4.3.2.jar'
|
||||
-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar'
|
||||
-libraryjars 'tempLibraries/java-objc-bridge-1.0.0-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/java-objc-bridge-1.0.0.jar'
|
||||
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
|
||||
-libraryjars 'tempLibraries/jinput-platform-2.0.5-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/jna-4.4.0.jar'
|
||||
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
|
||||
-libraryjars 'tempLibraries/jsr305-3.0.1-sources.jar'
|
||||
-libraryjars 'tempLibraries/jsr305-3.0.1.jar'
|
||||
-libraryjars 'tempLibraries/jutils-1.0.0.jar'
|
||||
-libraryjars 'tempLibraries/libraryjavasound-20101123.jar'
|
||||
-libraryjars 'tempLibraries/librarylwjglopenal-20100824.jar'
|
||||
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/log4j-core-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl-2.9.2-nightly-20140822.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl-platform-2.9.2-nightly-20140822-natives-osx.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl_util-2.9.2-nightly-20140822.jar'
|
||||
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
|
||||
-libraryjars 'tempLibraries/oshi-core-1.1.jar'
|
||||
-libraryjars 'tempLibraries/patchy-1.1.jar'
|
||||
-libraryjars 'tempLibraries/platform-3.4.0.jar'
|
||||
-libraryjars 'tempLibraries/realms-1.10.22.jar'
|
||||
-libraryjars 'tempLibraries/soundsystem-20120107.jar'
|
||||
-libraryjars 'tempLibraries/text2speech-1.10.3.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/mixin-0.7.8-SNAPSHOT.jar'
|
||||
-libraryjars 'tempLibraries/launchwrapper-1.12.jar'
|
||||
|
||||
|
||||
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main'
|
||||
# methods.
|
||||
-keepclasseswithmembers public class * {
|
||||
public static void main(java.lang.String[]);
|
||||
}
|
||||
|
||||
# Also keep - Enumerations. Keep the special static methods that are required in
|
||||
# enumeration classes.
|
||||
-keepclassmembers enum * {
|
||||
public static **[] values();
|
||||
public static ** valueOf(java.lang.String);
|
||||
}
|
||||
|
||||
# Also keep - Database drivers. Keep all implementations of java.sql.Driver.
|
||||
-keep class * extends java.sql.Driver
|
||||
|
||||
# Also keep - Swing UI L&F. Keep all extensions of javax.swing.plaf.ComponentUI,
|
||||
# along with the special 'createUI' method.
|
||||
-keep class * extends javax.swing.plaf.ComponentUI {
|
||||
public static javax.swing.plaf.ComponentUI createUI(javax.swing.JComponent);
|
||||
}
|
||||
|
||||
# Keep names - Native method names. Keep all native class/method names.
|
||||
-keepclasseswithmembers,includedescriptorclasses,allowshrinking class * {
|
||||
native <methods>;
|
||||
}
|
||||
|
||||
# Remove - System method calls. Remove all invocations of System
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.System {
|
||||
public static long currentTimeMillis();
|
||||
static java.lang.Class getCallerClass();
|
||||
public static int identityHashCode(java.lang.Object);
|
||||
public static java.lang.SecurityManager getSecurityManager();
|
||||
public static java.util.Properties getProperties();
|
||||
public static java.lang.String getProperty(java.lang.String);
|
||||
public static java.lang.String getenv(java.lang.String);
|
||||
public static java.lang.String mapLibraryName(java.lang.String);
|
||||
public static java.lang.String getProperty(java.lang.String,java.lang.String);
|
||||
}
|
||||
|
||||
# Remove - Math method calls. Remove all invocations of Math
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.Math {
|
||||
public static double sin(double);
|
||||
public static double cos(double);
|
||||
public static double tan(double);
|
||||
public static double asin(double);
|
||||
public static double acos(double);
|
||||
public static double atan(double);
|
||||
public static double toRadians(double);
|
||||
public static double toDegrees(double);
|
||||
public static double exp(double);
|
||||
public static double log(double);
|
||||
public static double log10(double);
|
||||
public static double sqrt(double);
|
||||
public static double cbrt(double);
|
||||
public static double IEEEremainder(double,double);
|
||||
public static double ceil(double);
|
||||
public static double floor(double);
|
||||
public static double rint(double);
|
||||
public static double atan2(double,double);
|
||||
public static double pow(double,double);
|
||||
public static int round(float);
|
||||
public static long round(double);
|
||||
public static double random();
|
||||
public static int abs(int);
|
||||
public static long abs(long);
|
||||
public static float abs(float);
|
||||
public static double abs(double);
|
||||
public static int max(int,int);
|
||||
public static long max(long,long);
|
||||
public static float max(float,float);
|
||||
public static double max(double,double);
|
||||
public static int min(int,int);
|
||||
public static long min(long,long);
|
||||
public static float min(float,float);
|
||||
public static double min(double,double);
|
||||
public static double ulp(double);
|
||||
public static float ulp(float);
|
||||
public static double signum(double);
|
||||
public static float signum(float);
|
||||
public static double sinh(double);
|
||||
public static double cosh(double);
|
||||
public static double tanh(double);
|
||||
public static double hypot(double,double);
|
||||
public static double expm1(double);
|
||||
public static double log1p(double);
|
||||
}
|
||||
|
||||
# Remove - Number method calls. Remove all invocations of Number
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.* extends java.lang.Number {
|
||||
public static java.lang.String toString(byte);
|
||||
public static java.lang.Byte valueOf(byte);
|
||||
public static byte parseByte(java.lang.String);
|
||||
public static byte parseByte(java.lang.String,int);
|
||||
public static java.lang.Byte valueOf(java.lang.String,int);
|
||||
public static java.lang.Byte valueOf(java.lang.String);
|
||||
public static java.lang.Byte decode(java.lang.String);
|
||||
public int compareTo(java.lang.Byte);
|
||||
public static java.lang.String toString(short);
|
||||
public static short parseShort(java.lang.String);
|
||||
public static short parseShort(java.lang.String,int);
|
||||
public static java.lang.Short valueOf(java.lang.String,int);
|
||||
public static java.lang.Short valueOf(java.lang.String);
|
||||
public static java.lang.Short valueOf(short);
|
||||
public static java.lang.Short decode(java.lang.String);
|
||||
public static short reverseBytes(short);
|
||||
public int compareTo(java.lang.Short);
|
||||
public static java.lang.String toString(int,int);
|
||||
public static java.lang.String toHexString(int);
|
||||
public static java.lang.String toOctalString(int);
|
||||
public static java.lang.String toBinaryString(int);
|
||||
public static java.lang.String toString(int);
|
||||
public static int parseInt(java.lang.String,int);
|
||||
public static int parseInt(java.lang.String);
|
||||
public static java.lang.Integer valueOf(java.lang.String,int);
|
||||
public static java.lang.Integer valueOf(java.lang.String);
|
||||
public static java.lang.Integer valueOf(int);
|
||||
public static java.lang.Integer getInteger(java.lang.String);
|
||||
public static java.lang.Integer getInteger(java.lang.String,int);
|
||||
public static java.lang.Integer getInteger(java.lang.String,java.lang.Integer);
|
||||
public static java.lang.Integer decode(java.lang.String);
|
||||
public static int highestOneBit(int);
|
||||
public static int lowestOneBit(int);
|
||||
public static int numberOfLeadingZeros(int);
|
||||
public static int numberOfTrailingZeros(int);
|
||||
public static int bitCount(int);
|
||||
public static int rotateLeft(int,int);
|
||||
public static int rotateRight(int,int);
|
||||
public static int reverse(int);
|
||||
public static int signum(int);
|
||||
public static int reverseBytes(int);
|
||||
public int compareTo(java.lang.Integer);
|
||||
public static java.lang.String toString(long,int);
|
||||
public static java.lang.String toHexString(long);
|
||||
public static java.lang.String toOctalString(long);
|
||||
public static java.lang.String toBinaryString(long);
|
||||
public static java.lang.String toString(long);
|
||||
public static long parseLong(java.lang.String,int);
|
||||
public static long parseLong(java.lang.String);
|
||||
public static java.lang.Long valueOf(java.lang.String,int);
|
||||
public static java.lang.Long valueOf(java.lang.String);
|
||||
public static java.lang.Long valueOf(long);
|
||||
public static java.lang.Long decode(java.lang.String);
|
||||
public static java.lang.Long getLong(java.lang.String);
|
||||
public static java.lang.Long getLong(java.lang.String,long);
|
||||
public static java.lang.Long getLong(java.lang.String,java.lang.Long);
|
||||
public static long highestOneBit(long);
|
||||
public static long lowestOneBit(long);
|
||||
public static int numberOfLeadingZeros(long);
|
||||
public static int numberOfTrailingZeros(long);
|
||||
public static int bitCount(long);
|
||||
public static long rotateLeft(long,int);
|
||||
public static long rotateRight(long,int);
|
||||
public static long reverse(long);
|
||||
public static int signum(long);
|
||||
public static long reverseBytes(long);
|
||||
public int compareTo(java.lang.Long);
|
||||
public static java.lang.String toString(float);
|
||||
public static java.lang.String toHexString(float);
|
||||
public static java.lang.Float valueOf(java.lang.String);
|
||||
public static java.lang.Float valueOf(float);
|
||||
public static float parseFloat(java.lang.String);
|
||||
public static boolean isNaN(float);
|
||||
public static boolean isInfinite(float);
|
||||
public static int floatToIntBits(float);
|
||||
public static int floatToRawIntBits(float);
|
||||
public static float intBitsToFloat(int);
|
||||
public static int compare(float,float);
|
||||
public boolean isNaN();
|
||||
public boolean isInfinite();
|
||||
public int compareTo(java.lang.Float);
|
||||
public static java.lang.String toString(double);
|
||||
public static java.lang.String toHexString(double);
|
||||
public static java.lang.Double valueOf(java.lang.String);
|
||||
public static java.lang.Double valueOf(double);
|
||||
public static double parseDouble(java.lang.String);
|
||||
public static boolean isNaN(double);
|
||||
public static boolean isInfinite(double);
|
||||
public static long doubleToLongBits(double);
|
||||
public static long doubleToRawLongBits(double);
|
||||
public static double longBitsToDouble(long);
|
||||
public static int compare(double,double);
|
||||
public boolean isNaN();
|
||||
public boolean isInfinite();
|
||||
public int compareTo(java.lang.Double);
|
||||
public byte byteValue();
|
||||
public short shortValue();
|
||||
public int intValue();
|
||||
public long longValue();
|
||||
public float floatValue();
|
||||
public double doubleValue();
|
||||
public int compareTo(java.lang.Object);
|
||||
public boolean equals(java.lang.Object);
|
||||
public int hashCode();
|
||||
public java.lang.String toString();
|
||||
}
|
||||
|
||||
# Remove - String method calls. Remove all invocations of String
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.String {
|
||||
public static java.lang.String copyValueOf(char[]);
|
||||
public static java.lang.String copyValueOf(char[],int,int);
|
||||
public static java.lang.String valueOf(boolean);
|
||||
public static java.lang.String valueOf(char);
|
||||
public static java.lang.String valueOf(char[]);
|
||||
public static java.lang.String valueOf(char[],int,int);
|
||||
public static java.lang.String valueOf(double);
|
||||
public static java.lang.String valueOf(float);
|
||||
public static java.lang.String valueOf(int);
|
||||
public static java.lang.String valueOf(java.lang.Object);
|
||||
public static java.lang.String valueOf(long);
|
||||
public boolean contentEquals(java.lang.StringBuffer);
|
||||
public boolean endsWith(java.lang.String);
|
||||
public boolean equalsIgnoreCase(java.lang.String);
|
||||
public boolean equals(java.lang.Object);
|
||||
public boolean matches(java.lang.String);
|
||||
public boolean regionMatches(boolean,int,java.lang.String,int,int);
|
||||
public boolean regionMatches(int,java.lang.String,int,int);
|
||||
public boolean startsWith(java.lang.String);
|
||||
public boolean startsWith(java.lang.String,int);
|
||||
public byte[] getBytes();
|
||||
public byte[] getBytes(java.lang.String);
|
||||
public char charAt(int);
|
||||
public char[] toCharArray();
|
||||
public int compareToIgnoreCase(java.lang.String);
|
||||
public int compareTo(java.lang.Object);
|
||||
public int compareTo(java.lang.String);
|
||||
public int hashCode();
|
||||
public int indexOf(int);
|
||||
public int indexOf(int,int);
|
||||
public int indexOf(java.lang.String);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(int);
|
||||
public int lastIndexOf(int,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.CharSequence subSequence(int,int);
|
||||
public java.lang.String concat(java.lang.String);
|
||||
public java.lang.String replaceAll(java.lang.String,java.lang.String);
|
||||
public java.lang.String replace(char,char);
|
||||
public java.lang.String replaceFirst(java.lang.String,java.lang.String);
|
||||
public java.lang.String[] split(java.lang.String);
|
||||
public java.lang.String[] split(java.lang.String,int);
|
||||
public java.lang.String substring(int);
|
||||
public java.lang.String substring(int,int);
|
||||
public java.lang.String toLowerCase();
|
||||
public java.lang.String toLowerCase(java.util.Locale);
|
||||
public java.lang.String toString();
|
||||
public java.lang.String toUpperCase();
|
||||
public java.lang.String toUpperCase(java.util.Locale);
|
||||
public java.lang.String trim();
|
||||
}
|
||||
|
||||
# Remove - StringBuffer method calls. Remove all invocations of StringBuffer
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.StringBuffer {
|
||||
public java.lang.String toString();
|
||||
public char charAt(int);
|
||||
public int capacity();
|
||||
public int codePointAt(int);
|
||||
public int codePointBefore(int);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.String substring(int);
|
||||
public java.lang.String substring(int,int);
|
||||
}
|
||||
|
||||
# Remove - StringBuilder method calls. Remove all invocations of StringBuilder
|
||||
# methods without side effects whose return values are not used.
|
||||
-assumenosideeffects public class java.lang.StringBuilder {
|
||||
public java.lang.String toString();
|
||||
public char charAt(int);
|
||||
public int capacity();
|
||||
public int codePointAt(int);
|
||||
public int codePointBefore(int);
|
||||
public int indexOf(java.lang.String,int);
|
||||
public int lastIndexOf(java.lang.String);
|
||||
public int lastIndexOf(java.lang.String,int);
|
||||
public int length();
|
||||
public java.lang.String substring(int);
|
||||
public java.lang.String substring(int,int);
|
||||
}
|
||||
Executable → Regular
+77
-71
@@ -1,71 +1,77 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 9:59 PM
|
||||
*/
|
||||
public class BaritoneTweaker implements ITweaker {
|
||||
|
||||
List<String> args;
|
||||
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>(args);
|
||||
if (gameDir != null) addArg("gameDir", gameDir.getAbsolutePath());
|
||||
if (assetsDir != null) addArg("assetsDir", assetsDir.getAbsolutePath());
|
||||
if (profile != null) addArg("version", profile);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
MixinBootstrap.init();
|
||||
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
|
||||
Mixins.addConfiguration("mixins.baritone.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLaunchTarget() {
|
||||
return "net.minecraft.client.main.Main";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getLaunchArguments() {
|
||||
return this.args.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void addArg(String label, String value) {
|
||||
if (!args.contains("--" + label) && value != null) {
|
||||
this.args.add("--" + label);
|
||||
this.args.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.ITweaker;
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.launch.MixinBootstrap;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.asm.mixin.Mixins;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 9:59 PM
|
||||
*/
|
||||
public class BaritoneTweaker implements ITweaker {
|
||||
|
||||
List<String> args;
|
||||
|
||||
@Override
|
||||
public void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>(args);
|
||||
if (gameDir != null) {
|
||||
addArg("gameDir", gameDir.getAbsolutePath());
|
||||
}
|
||||
if (assetsDir != null) {
|
||||
addArg("assetsDir", assetsDir.getAbsolutePath());
|
||||
}
|
||||
if (profile != null) {
|
||||
addArg("version", profile);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
MixinBootstrap.init();
|
||||
MixinEnvironment.getDefaultEnvironment().setSide(MixinEnvironment.Side.CLIENT);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.NOTCH);
|
||||
Mixins.addConfiguration("mixins.baritone.json");
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String getLaunchTarget() {
|
||||
return "net.minecraft.client.main.Main";
|
||||
}
|
||||
|
||||
@Override
|
||||
public final String[] getLaunchArguments() {
|
||||
return this.args.toArray(new String[0]);
|
||||
}
|
||||
|
||||
private void addArg(String label, String value) {
|
||||
if (!args.contains("--" + label) && value != null) {
|
||||
this.args.add("--" + label);
|
||||
this.args.add(value);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
+44
-44
@@ -1,44 +1,44 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:09 PM
|
||||
*/
|
||||
public class BaritoneTweakerForge extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import net.minecraft.launchwrapper.LaunchClassLoader;
|
||||
import org.spongepowered.asm.mixin.MixinEnvironment;
|
||||
import org.spongepowered.tools.obfuscation.mcp.ObfuscationServiceMCP;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:09 PM
|
||||
*/
|
||||
public class BaritoneTweakerForge extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void injectIntoClassLoader(LaunchClassLoader classLoader) {
|
||||
super.injectIntoClassLoader(classLoader);
|
||||
MixinEnvironment.getDefaultEnvironment().setObfuscationContext(ObfuscationServiceMCP.SEARGE);
|
||||
}
|
||||
}
|
||||
Executable → Regular
+34
-34
@@ -1,34 +1,34 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:10 PM
|
||||
*/
|
||||
public class BaritoneTweakerOptifine extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:10 PM
|
||||
*/
|
||||
public class BaritoneTweakerOptifine extends BaritoneTweaker {
|
||||
|
||||
@Override
|
||||
public final void acceptOptions(List<String> args, File gameDir, File assetsDir, String profile) {
|
||||
this.args = new ArrayList<>();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,58 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import net.minecraft.world.chunk.storage.AnvilChunkLoader;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/4/2018
|
||||
*/
|
||||
@Mixin(AnvilChunkLoader.class)
|
||||
public class MixinAnvilChunkLoader implements IAnvilChunkLoader {
|
||||
|
||||
@Shadow @Final private File chunkSaveLocation;
|
||||
|
||||
@Override
|
||||
public File getChunkSaveLocation() {
|
||||
return this.chunkSaveLocation;
|
||||
}
|
||||
}
|
||||
Executable → Regular
+43
-40
@@ -1,40 +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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import net.minecraft.client.main.Main;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:18 PM
|
||||
*/
|
||||
@Mixin(Main.class)
|
||||
public class MixinMain {
|
||||
|
||||
@Inject(
|
||||
method = "main",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private static void main(String[] args, CallbackInfo ci) {
|
||||
System.setProperty("java.net.preferIPv4Stack", "true");
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import com.google.common.base.MoreObjects;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/25/2018
|
||||
*/
|
||||
@Mixin(BlockPos.class)
|
||||
public class MixinBlockPos extends Vec3i {
|
||||
|
||||
public MixinBlockPos(int xIn, int yIn, int zIn) {
|
||||
super(xIn, yIn, zIn);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Nonnull
|
||||
public String toString() {
|
||||
return MoreObjects.toStringHelper("BlockPos").add("x", this.getX()).add("y", this.getY()).add("z", this.getZ()).toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import net.minecraft.world.chunk.storage.IChunkLoader;
|
||||
import net.minecraft.world.gen.ChunkProviderServer;
|
||||
import org.spongepowered.asm.mixin.Final;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 9/4/2018
|
||||
*/
|
||||
@Mixin(ChunkProviderServer.class)
|
||||
public class MixinChunkProviderServer implements IChunkProviderServer {
|
||||
|
||||
@Shadow @Final private IChunkLoader chunkLoader;
|
||||
|
||||
@Override
|
||||
public IChunkLoader getChunkLoader() {
|
||||
return this.chunkLoader;
|
||||
}
|
||||
}
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RelativeMoveEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.entity.Entity;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
@Mixin(Entity.class)
|
||||
public class MixinEntity {
|
||||
|
||||
@Inject(
|
||||
method = "moveRelative",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.PRE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "moveRelative",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
|
||||
Entity _this = (Entity) (Object) this;
|
||||
if (_this == Minecraft.getMinecraft().player)
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerRelativeMove(new RelativeMoveEvent(EventState.POST));
|
||||
}
|
||||
}
|
||||
+21
-5
@@ -17,8 +17,10 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChatEvent;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.ChatEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -40,8 +42,9 @@ public class MixinEntityPlayerSP {
|
||||
private void sendChatMessage(String msg, CallbackInfo ci) {
|
||||
ChatEvent event = new ChatEvent(msg);
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendChatMessage(event);
|
||||
if (event.isCancelled())
|
||||
if (event.isCancelled()) {
|
||||
ci.cancel();
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
@@ -53,7 +56,20 @@ public class MixinEntityPlayerSP {
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void onUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate();
|
||||
private void onPreUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onUpdate",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
|
||||
shift = At.Shift.BY,
|
||||
by = 2
|
||||
)
|
||||
)
|
||||
private void onPostUpdate(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -17,8 +17,8 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.RenderEvent;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
Executable → Regular
+44
-43
@@ -1,43 +1,44 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 12:28 AM
|
||||
*/
|
||||
@Mixin(GameSettings.class)
|
||||
public class MixinGameSettings {
|
||||
|
||||
@Redirect(
|
||||
method = "isKeyDown",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/1/2018 12:28 AM
|
||||
*/
|
||||
@Mixin(GameSettings.class)
|
||||
public class MixinGameSettings {
|
||||
|
||||
@Redirect(
|
||||
method = "isKeyDown",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
Executable → Regular
+47
-46
@@ -1,46 +1,47 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:47 PM
|
||||
*/
|
||||
@Mixin(GuiContainer.class)
|
||||
public class MixinGuiContainer {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"mouseClicked",
|
||||
"mouseReleased"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.inventory.GuiContainer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:47 PM
|
||||
*/
|
||||
@Mixin(GuiContainer.class)
|
||||
public class MixinGuiContainer {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"mouseClicked",
|
||||
"mouseReleased"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
Executable → Regular
+48
-47
@@ -1,47 +1,48 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:38 PM
|
||||
*/
|
||||
@Mixin(GuiScreen.class)
|
||||
public class MixinGuiScreen {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"isCtrlKeyDown",
|
||||
"isShiftKeyDown",
|
||||
"isAltKeyDown"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:38 PM
|
||||
*/
|
||||
@Mixin(GuiScreen.class)
|
||||
public class MixinGuiScreen {
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"isCtrlKeyDown",
|
||||
"isShiftKeyDown",
|
||||
"isAltKeyDown"
|
||||
},
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private static boolean isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
}
|
||||
Executable → Regular
+44
-43
@@ -1,43 +1,44 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:44 PM
|
||||
*/
|
||||
@Mixin(KeyBinding.class)
|
||||
public abstract class MixinKeyBinding {
|
||||
|
||||
@Inject(
|
||||
method = "isKeyDown",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this))
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:44 PM
|
||||
*/
|
||||
@Mixin(KeyBinding.class)
|
||||
public class MixinKeyBinding {
|
||||
|
||||
@Inject(
|
||||
method = "isKeyDown",
|
||||
at = @At("HEAD"),
|
||||
cancellable = true
|
||||
)
|
||||
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
|
||||
if (Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) {
|
||||
cir.setReturnValue(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
Executable → Regular
+176
-144
@@ -1,144 +1,176 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.TickEvent;
|
||||
import baritone.bot.event.events.WorldEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.bot.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:51 PM
|
||||
*/
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow private int leftClickCounter;
|
||||
@Shadow public WorldClient world;
|
||||
|
||||
@Inject(
|
||||
method = "init",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void init(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
|
||||
ordinal = 5,
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void runTick(CallbackInfo ci) {
|
||||
Minecraft mc = (Minecraft) (Object) this;
|
||||
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
|
||||
EventState.PRE,
|
||||
(mc.player != null && mc.world != null)
|
||||
? TickEvent.Type.IN
|
||||
: TickEvent.Type.OUT
|
||||
));
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTickKeyboard",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z"
|
||||
)
|
||||
)
|
||||
private boolean Keyboard$isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processKeyBinds",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void runTickKeyboard(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = {
|
||||
"setIngameFocus",
|
||||
"runTick"
|
||||
},
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.PUTFIELD,
|
||||
target = "net/minecraft/client/Minecraft.leftClickCounter:I",
|
||||
ordinal = 0
|
||||
)
|
||||
)
|
||||
private void setLeftClickCounter(Minecraft mc, int value) {
|
||||
if (!Baritone.INSTANCE.isInitialized() || !Baritone.INSTANCE.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindAttack))
|
||||
this.leftClickCounter = value;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null)
|
||||
return;
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.PRE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null)
|
||||
return;
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.POST
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.WorldEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.utils.ExampleBaritoneControl;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumActionResult;
|
||||
import net.minecraft.util.EnumHand;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.spongepowered.asm.lib.Opcodes;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.Shadow;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 10:51 PM
|
||||
*/
|
||||
@Mixin(Minecraft.class)
|
||||
public class MixinMinecraft {
|
||||
|
||||
@Shadow
|
||||
private int leftClickCounter;
|
||||
@Shadow
|
||||
public EntityPlayerSP player;
|
||||
@Shadow
|
||||
public WorldClient world;
|
||||
|
||||
@Inject(
|
||||
method = "init",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void init(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.init();
|
||||
ExampleBaritoneControl.INSTANCE.initAndRegister();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/Minecraft.currentScreen:Lnet/minecraft/client/gui/GuiScreen;",
|
||||
ordinal = 5,
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
)
|
||||
private void runTick(CallbackInfo ci) {
|
||||
Minecraft mc = (Minecraft) (Object) this;
|
||||
Baritone.INSTANCE.getGameEventHandler().onTick(new TickEvent(
|
||||
EventState.PRE,
|
||||
(mc.player != null && mc.world != null)
|
||||
? TickEvent.Type.IN
|
||||
: TickEvent.Type.OUT
|
||||
));
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTickKeyboard",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "org/lwjgl/input/Keyboard.isKeyDown(I)Z",
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private boolean Keyboard$isKeyDown(int keyCode) {
|
||||
return Baritone.INSTANCE.getInputOverrideHandler().isKeyDown(keyCode);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processKeyBinds",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void runTickKeyboard(CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onProcessKeyBinds();
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.PRE
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
// still fire event for both null, as that means we've just finished exiting a world
|
||||
|
||||
Baritone.INSTANCE.getGameEventHandler().onWorldEvent(
|
||||
new WorldEvent(
|
||||
world,
|
||||
EventState.POST
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "runTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
opcode = Opcodes.GETFIELD,
|
||||
target = "net/minecraft/client/gui/GuiScreen.allowUserInput:Z"
|
||||
)
|
||||
)
|
||||
private boolean isAllowUserInput(GuiScreen screen) {
|
||||
return (PathingBehavior.INSTANCE.getCurrent() != null && player != null) || screen.allowUserInput;
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "clickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/multiplayer/PlayerControllerMP.clickBlock(Lnet/minecraft/util/math/BlockPos;Lnet/minecraft/util/EnumFacing;)Z"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockBreak(CallbackInfo ci, BlockPos pos) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(pos, BlockInteractEvent.Type.BREAK));
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "rightClickMouse",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.swingArm(Lnet/minecraft/util/EnumHand;)V"
|
||||
),
|
||||
locals = LocalCapture.CAPTURE_FAILHARD
|
||||
)
|
||||
private void onBlockUse(CallbackInfo ci, EnumHand var1[], int var2, int var3, EnumHand enumhand, ItemStack itemstack, BlockPos blockpos, int i, EnumActionResult enumactionresult) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onBlockInteract(new BlockInteractEvent(blockpos, BlockInteractEvent.Type.USE));
|
||||
}
|
||||
}
|
||||
+15
-3
@@ -17,11 +17,12 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChunkEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.ChunkEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketCombatEvent;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -66,4 +67,15 @@ public class MixinNetHandlerPlayClient {
|
||||
)
|
||||
);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "handleCombatEvent",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/Minecraft.displayGuiScreen(Lnet/minecraft/client/gui/GuiScreen;)V"
|
||||
)
|
||||
)
|
||||
private void onPlayerDeath(SPacketCombatEvent packetIn, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onPlayerDeath();
|
||||
}
|
||||
}
|
||||
+12
-14
@@ -17,9 +17,9 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.PacketEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import io.netty.channel.Channel;
|
||||
import io.netty.channel.ChannelHandlerContext;
|
||||
import io.netty.util.concurrent.Future;
|
||||
@@ -37,17 +37,16 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
* @since 8/6/2018 9:30 PM
|
||||
*/
|
||||
@Mixin(NetworkManager.class)
|
||||
public abstract class MixinNetworkManager {
|
||||
public class MixinNetworkManager {
|
||||
|
||||
@Shadow private Channel channel;
|
||||
|
||||
@Shadow protected abstract void channelRead0(ChannelHandlerContext p_channelRead0_1_, Packet<?> p_channelRead0_2_) throws Exception;
|
||||
@Shadow
|
||||
private Channel channel;
|
||||
|
||||
@Inject(
|
||||
method = "dispatchPacket",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void >>[] futureListeners, CallbackInfo ci) {
|
||||
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket));
|
||||
}
|
||||
|
||||
@@ -55,7 +54,7 @@ public abstract class MixinNetworkManager {
|
||||
method = "dispatchPacket",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void >>[] futureListeners, CallbackInfo ci) {
|
||||
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket));
|
||||
}
|
||||
|
||||
@@ -64,8 +63,7 @@ public abstract class MixinNetworkManager {
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/network/Packet.processPacket(Lnet/minecraft/network/INetHandler;)V"
|
||||
),
|
||||
remap = false
|
||||
)
|
||||
)
|
||||
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet));
|
||||
@@ -73,11 +71,11 @@ public abstract class MixinNetworkManager {
|
||||
|
||||
@Inject(
|
||||
method = "channelRead0",
|
||||
at = @At("RETURN"),
|
||||
remap = false
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
if (this.channel.isOpen())
|
||||
if (this.channel.isOpen()) {
|
||||
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.POST, packet));
|
||||
}
|
||||
}
|
||||
}
|
||||
+3
-3
@@ -17,9 +17,9 @@
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.event.events.ChunkEvent;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.ChunkEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
Executable → Regular
+25
-22
@@ -1,23 +1,26 @@
|
||||
{
|
||||
"required": true,
|
||||
"package": "baritone.launch.mixins",
|
||||
"refmap": "mixins.client.refmap.json",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"verbose": false,
|
||||
"client": [
|
||||
"MixinEntityPlayerSP",
|
||||
"MixinEntityRenderer",
|
||||
"MixinGameSettings",
|
||||
"MixinGuiContainer",
|
||||
"MixinGuiScreen",
|
||||
"MixinKeyBinding",
|
||||
"MixinMain",
|
||||
"MixinMinecraft",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinWorldClient",
|
||||
|
||||
"accessor.IAnvilChunkLoader",
|
||||
"accessor.IChunkProviderServer"
|
||||
]
|
||||
{
|
||||
"required": true,
|
||||
"package": "baritone.launch.mixins",
|
||||
"refmap": "mixins.baritone.refmap.json",
|
||||
"compatibilityLevel": "JAVA_8",
|
||||
"verbose": false,
|
||||
"injectors": {
|
||||
"maxShiftBy": 2
|
||||
},
|
||||
"client": [
|
||||
"MixinAnvilChunkLoader",
|
||||
"MixinBlockPos",
|
||||
"MixinChunkProviderServer",
|
||||
"MixinEntity",
|
||||
"MixinEntityPlayerSP",
|
||||
"MixinEntityRenderer",
|
||||
"MixinGameSettings",
|
||||
"MixinGuiContainer",
|
||||
"MixinGuiScreen",
|
||||
"MixinKeyBinding",
|
||||
"MixinMinecraft",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinWorldClient"
|
||||
]
|
||||
}
|
||||
@@ -15,17 +15,20 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot;
|
||||
package baritone;
|
||||
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.behavior.impl.LookBehavior;
|
||||
import baritone.bot.behavior.impl.MemoryBehavior;
|
||||
import baritone.bot.behavior.impl.PathingBehavior;
|
||||
import baritone.bot.event.GameEventHandler;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.api.event.GameEventHandler;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.behavior.impl.*;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.Minecraft;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -47,12 +50,22 @@ public enum Baritone {
|
||||
private InputOverrideHandler inputOverrideHandler;
|
||||
private Settings settings;
|
||||
private List<Behavior> behaviors;
|
||||
private File dir;
|
||||
|
||||
/**
|
||||
* List of consumers to be called after Baritone has initialized
|
||||
*/
|
||||
private List<Consumer<Baritone>> onInitConsumers;
|
||||
|
||||
/**
|
||||
* Whether or not Baritone is active
|
||||
*/
|
||||
private boolean active;
|
||||
|
||||
Baritone() {
|
||||
this.onInitConsumers = new ArrayList<>();
|
||||
}
|
||||
|
||||
public synchronized void init() {
|
||||
if (initialized) {
|
||||
return;
|
||||
@@ -61,12 +74,25 @@ public enum Baritone {
|
||||
this.inputOverrideHandler = new InputOverrideHandler();
|
||||
this.settings = new Settings();
|
||||
this.behaviors = new ArrayList<>();
|
||||
behaviors.add(PathingBehavior.INSTANCE);
|
||||
behaviors.add(LookBehavior.INSTANCE);
|
||||
behaviors.add(MemoryBehavior.INSTANCE);
|
||||
{
|
||||
registerBehavior(PathingBehavior.INSTANCE);
|
||||
registerBehavior(LookBehavior.INSTANCE);
|
||||
registerBehavior(MemoryBehavior.INSTANCE);
|
||||
registerBehavior(LocationTrackingBehavior.INSTANCE);
|
||||
registerBehavior(FollowBehavior.INSTANCE);
|
||||
registerBehavior(MineBehavior.INSTANCE);
|
||||
}
|
||||
this.dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
this.active = true;
|
||||
this.initialized = true;
|
||||
|
||||
this.onInitConsumers.forEach(consumer -> consumer.accept(this));
|
||||
}
|
||||
|
||||
public final boolean isInitialized() {
|
||||
@@ -87,6 +113,7 @@ public enum Baritone {
|
||||
|
||||
public void registerBehavior(Behavior behavior) {
|
||||
this.behaviors.add(behavior);
|
||||
this.gameEventHandler.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
public final boolean isActive() {
|
||||
@@ -100,4 +127,12 @@ public enum Baritone {
|
||||
public static Settings settings() {
|
||||
return Baritone.INSTANCE.settings; // yolo
|
||||
}
|
||||
|
||||
public final File getDir() {
|
||||
return this.dir;
|
||||
}
|
||||
|
||||
public final void registerInitListener(Consumer<Baritone> runnable) {
|
||||
this.onInitConsumers.add(runnable);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,372 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Baritone's settings
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Settings {
|
||||
/**
|
||||
* Allow Baritone to break blocks
|
||||
*/
|
||||
public Setting<Boolean> allowBreak = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to sprint
|
||||
*/
|
||||
public Setting<Boolean> allowSprint = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to place blocks
|
||||
*/
|
||||
public Setting<Boolean> allowPlace = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* It doesn't actually take twenty ticks to place a block, this cost is so high
|
||||
* because we want to generally conserve blocks which might be limited
|
||||
*/
|
||||
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
|
||||
|
||||
/**
|
||||
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
|
||||
* Reliability: questionable.
|
||||
*/
|
||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow Baritone to assume it can walk on still water just like any other block.
|
||||
* This functionality is assumed to be provided by a separate library that might have imported Baritone.
|
||||
*/
|
||||
public Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
|
||||
*/
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||
)));
|
||||
|
||||
/**
|
||||
* Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real
|
||||
* pathing scenarios. And they can cause Baritone to get trapped indefinitely in a strange scenario.
|
||||
*/
|
||||
public Setting<Boolean> allowVines = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Slab behavior is complicated, disable this for higher path reliability. Leave enabled if you have bottom slabs
|
||||
* everywhere in your base.
|
||||
*/
|
||||
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* You know what it is
|
||||
* <p>
|
||||
* But it's very unreliable and falls off when cornering like all the time so.
|
||||
*/
|
||||
public Setting<Boolean> allowParkour = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
|
||||
*/
|
||||
public Setting<Boolean> considerPotionEffects = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* This is the big A* setting.
|
||||
* As long as your cost heuristic is an *underestimate*, it's guaranteed to find you the best path.
|
||||
* 3.5 is always an underestimate, even if you are sprinting.
|
||||
* If you're walking only (with allowSprint off) 4.6 is safe.
|
||||
* Any value below 3.5 is never worth it. It's just more computation to find the same path, guaranteed.
|
||||
* (specifically, it needs to be strictly slightly less than ActionCosts.WALK_ONE_BLOCK_COST, which is about 3.56)
|
||||
* <p>
|
||||
* Setting it at 3.57 or above with sprinting, or to 4.64 or above without sprinting, will result in
|
||||
* faster computation, at the cost of a suboptimal path. Any value above the walk / sprint cost will result
|
||||
* in it going straight at its goal, and not investigating alternatives, because the combined cost / heuristic
|
||||
* metric gets better and better with each block, instead of slightly worse.
|
||||
* <p>
|
||||
* Finding the optimal path is worth it, so it's the default.
|
||||
*/
|
||||
public Setting<Double> costHeuristic = this.new <Double>Setting<Double>(3.5D);
|
||||
|
||||
// a bunch of obscure internal A* settings that you probably don't want to change
|
||||
/**
|
||||
* The maximum number of times it will fetch outside loaded or cached chunks before assuming that
|
||||
* pathing has reached the end of the known area, and should therefore stop.
|
||||
*/
|
||||
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
|
||||
|
||||
/**
|
||||
* See issue #18
|
||||
* Set to 1.0 to effectively disable this feature
|
||||
*/
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9);
|
||||
|
||||
/**
|
||||
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
|
||||
* and there's no point.
|
||||
*/
|
||||
public Setting<Boolean> minimumImprovementRepropagation = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Use a pythagorean metric (as opposed to the more accurate hybrid diagonal / traverse).
|
||||
* You probably don't want this. It roughly triples nodes considered for no real advantage.
|
||||
*/
|
||||
public Setting<Boolean> pythagoreanMetric = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is
|
||||
* entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified.
|
||||
* See issue #114 for why this is disabled.
|
||||
*/
|
||||
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Stop 5 movements before anything that made the path COST_INF.
|
||||
* For example, if lava has spread across the path, don't walk right up to it then recalculate, it might
|
||||
* still be spreading lol
|
||||
*/
|
||||
public Setting<Integer> costVerificationLookahead = new Setting<>(5);
|
||||
|
||||
/**
|
||||
* Static cutoff factor. 0.9 means cut off the last 10% of all paths, regardless of chunk load state
|
||||
*/
|
||||
public Setting<Double> pathCutoffFactor = new Setting<>(0.9);
|
||||
|
||||
/**
|
||||
* Only apply static cutoff for paths of at least this length (in terms of number of movements)
|
||||
*/
|
||||
public Setting<Integer> pathCutoffMinimumLength = new Setting<>(30);
|
||||
|
||||
/**
|
||||
* Start planning the next path once the remaining movements tick estimates sum up to less than this value
|
||||
*/
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* How far are you allowed to fall onto solid ground (without a water bucket)?
|
||||
* 3 won't deal any damage. But if you just want to get down the mountain quickly and you have
|
||||
* Feather Falling IV, you might set it a bit higher, like 4 or 5.
|
||||
*/
|
||||
public Setting<Integer> maxFallHeightNoWater = new Setting<>(3);
|
||||
|
||||
/**
|
||||
* How far are you allowed to fall onto solid ground (with a water bucket)?
|
||||
* It's not that reliable, so I've set it below what would kill an unarmored player (23)
|
||||
*/
|
||||
public Setting<Integer> maxFallHeightBucket = new Setting<>(20);
|
||||
|
||||
/**
|
||||
* Is it okay to sprint through a descend followed by a diagonal?
|
||||
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
|
||||
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
|
||||
*/
|
||||
public Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If your goal is a GoalBlock in an unloaded chunk, assume it's far enough away that the Y coord
|
||||
* doesn't matter yet, and replace it with a GoalXZ to the same place before calculating a path.
|
||||
* Once a segment ends within chunk load range of the GoalBlock, it will go back to normal behavior
|
||||
* of considering the Y coord. The reasoning is that if your X and Z are 10,000 blocks away,
|
||||
* your Y coordinate's accuracy doesn't matter at all until you get much much closer.
|
||||
*/
|
||||
public Setting<Boolean> simplifyUnloadedYCoord = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If a movement takes this many ticks more than its initial cost estimate, cancel it
|
||||
*/
|
||||
public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* Pathing can never take longer than this
|
||||
*/
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(2000L);
|
||||
|
||||
/**
|
||||
* Planning ahead while executing a segment can never take longer than this
|
||||
*/
|
||||
public Setting<Number> planAheadTimeoutMS = new Setting<>(4000L);
|
||||
|
||||
/**
|
||||
* For debugging, consider nodes much much slower
|
||||
*/
|
||||
public Setting<Boolean> slowPath = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Milliseconds between each node
|
||||
*/
|
||||
public Setting<Number> slowPathTimeDelayMS = new Setting<>(100L);
|
||||
|
||||
/**
|
||||
* The alternative timeout number when slowPath is on
|
||||
*/
|
||||
public Setting<Number> slowPathTimeoutMS = new Setting<>(40000L);
|
||||
|
||||
/**
|
||||
* The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing.
|
||||
*/
|
||||
public Setting<Boolean> chunkCaching = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Print all the debug messages to chat
|
||||
*/
|
||||
public Setting<Boolean> chatDebug = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
|
||||
* something else
|
||||
*/
|
||||
public Setting<Boolean> chatControl = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* A second override over chatControl to force it on
|
||||
*/
|
||||
public Setting<Boolean> removePrefix = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Render the path
|
||||
*/
|
||||
public Setting<Boolean> renderPath = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Render the goal
|
||||
*/
|
||||
public Setting<Boolean> renderGoal = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Line width of the path when rendered, in pixels
|
||||
*/
|
||||
public Setting<Float> pathRenderLineWidthPixels = new Setting<>(5F);
|
||||
|
||||
/**
|
||||
* Line width of the goal when rendered, in pixels
|
||||
*/
|
||||
public Setting<Float> goalRenderLineWidthPixels = new Setting<>(3F);
|
||||
|
||||
/**
|
||||
* Start fading out the path at 20 movements ahead, and stop rendering it entirely 30 movements ahead.
|
||||
* Improves FPS.
|
||||
*/
|
||||
public Setting<Boolean> fadePath = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Move without having to force the client-sided rotations
|
||||
*/
|
||||
public Setting<Boolean> freeLook = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
|
||||
* <p>
|
||||
* At the moment this will silently set the player's rotations when using freeLook so you're not sprinting in
|
||||
* directions other than forward, which is picken up by more "advanced" anticheats like AAC, but not NCP.
|
||||
*/
|
||||
public Setting<Boolean> antiCheatCompatibility = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Exclusively use cached chunks for pathing
|
||||
*/
|
||||
public Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Whether or not to use the "#" command prefix
|
||||
*/
|
||||
public Setting<Boolean> prefix = new Setting<>(false);
|
||||
|
||||
public final Map<String, Setting<?>> byLowerName;
|
||||
public final List<Setting<?>> allSettings;
|
||||
|
||||
public class Setting<T> {
|
||||
public T value;
|
||||
private String name;
|
||||
private final Class<T> klass;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Setting(T value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Cannot determine value type class from null");
|
||||
}
|
||||
this.value = value;
|
||||
this.klass = (Class<T>) value.getClass();
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <K extends T> K get() {
|
||||
return (K) value;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> getValueClass() {
|
||||
return klass;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// here be dragons
|
||||
|
||||
{
|
||||
Field[] temp = getClass().getFields();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Setting.class)) {
|
||||
Setting<?> setting = (Setting<?>) field.get(this);
|
||||
String name = field.getName();
|
||||
setting.name = name;
|
||||
name = name.toLowerCase();
|
||||
if (tmpByName.containsKey(name)) {
|
||||
throw new IllegalStateException("Duplicate setting name");
|
||||
}
|
||||
tmpByName.put(name, setting);
|
||||
tmpAll.add(setting);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byLowerName = Collections.unmodifiableMap(tmpByName);
|
||||
allSettings = Collections.unmodifiableList(tmpAll);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public <T> List<Setting<T>> getAllValuesByType(Class<T> klass) {
|
||||
List<Setting<T>> result = new ArrayList<>();
|
||||
for (Setting<?> setting : allSettings) {
|
||||
if (setting.getValueClass().equals(klass)) {
|
||||
result.add((Setting<T>) setting);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Settings() { }
|
||||
}
|
||||
@@ -0,0 +1,235 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.event;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.*;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.ArrayList;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:04 PM
|
||||
*/
|
||||
public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
|
||||
private final ArrayList<IGameEventListener> listeners = new ArrayList<>();
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onTick(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerUpdate(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onProcessKeyBinds() {
|
||||
InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler();
|
||||
|
||||
// Simulate the key being held down this tick
|
||||
for (InputOverrideHandler.Input input : InputOverrideHandler.Input.values()) {
|
||||
KeyBinding keyBinding = input.getKeyBinding();
|
||||
|
||||
if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
|
||||
int keyCode = keyBinding.getKeyCode();
|
||||
|
||||
if (keyCode < Keyboard.KEYBOARD_SIZE) {
|
||||
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onProcessKeyBinds();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendChatMessage(ChatEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onSendChatMessage(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onChunkEvent(ChunkEvent event) {
|
||||
EventState state = event.getState();
|
||||
ChunkEvent.Type type = event.getType();
|
||||
|
||||
boolean isPostPopulate = state == EventState.POST
|
||||
&& type == ChunkEvent.Type.POPULATE;
|
||||
|
||||
// Whenever the server sends us to another dimension, chunks are unloaded
|
||||
// technically after the new world has been loaded, so we perform a check
|
||||
// to make sure the chunk being unloaded is already loaded.
|
||||
boolean isPreUnload = state == EventState.PRE
|
||||
&& type == ChunkEvent.Type.UNLOAD
|
||||
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
WorldProvider.INSTANCE.ifWorldLoaded(world -> {
|
||||
Chunk chunk = mc.world.getChunk(event.getX(), event.getZ());
|
||||
world.cache.queueForPacking(chunk);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onChunkEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onRenderPass(RenderEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onRenderPass(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onWorldEvent(WorldEvent event) {
|
||||
WorldProvider cache = WorldProvider.INSTANCE;
|
||||
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
break;
|
||||
case POST:
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null) {
|
||||
cache.initWorld(event.getWorld());
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onWorldEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onSendPacket(PacketEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onSendPacket(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void onReceivePacket(PacketEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onReceivePacket(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerRelativeMove(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onBlockInteract(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPlayerDeath();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
listeners.forEach(l -> {
|
||||
if (canDispatch(l)) {
|
||||
l.onPathEvent(event);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public final void registerEventListener(IGameEventListener listener) {
|
||||
this.listeners.add(listener);
|
||||
}
|
||||
|
||||
private boolean canDispatch(IGameEventListener listener) {
|
||||
return !(listener instanceof Toggleable) || ((Toggleable) listener).isEnabled();
|
||||
}
|
||||
}
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
public final class BlockInteractEvent {
|
||||
|
||||
/**
|
||||
* The position of the block interacted with
|
||||
*/
|
||||
private final BlockPos pos;
|
||||
|
||||
/**
|
||||
* The type of interaction that occurred
|
||||
*/
|
||||
private final Type type;
|
||||
|
||||
public BlockInteractEvent(BlockPos pos, Type type) {
|
||||
this.pos = pos;
|
||||
this.type = type;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The position of the block interacted with
|
||||
*/
|
||||
public final BlockPos getPos() {
|
||||
return this.pos;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The type of interaction with the target block
|
||||
*/
|
||||
public final Type getType() {
|
||||
return this.type;
|
||||
}
|
||||
|
||||
public enum Type {
|
||||
|
||||
/**
|
||||
* We're breaking the target block.
|
||||
*/
|
||||
BREAK,
|
||||
|
||||
/**
|
||||
* We're right clicking on the target block. Either placing or interacting with.
|
||||
*/
|
||||
USE
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.bot.event.events.type.Cancellable;
|
||||
import baritone.api.event.events.type.Cancellable;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
|
||||
/**
|
||||
* Called in some cases where a player's inventory has it's current slot queried.
|
||||
* <p>
|
||||
* @see IGameEventListener#onQueryItemSlotForBlocks()
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/20/2018
|
||||
*/
|
||||
public final class ItemSlotEvent {
|
||||
|
||||
/**
|
||||
* The current slot index
|
||||
*/
|
||||
private int slot;
|
||||
|
||||
public ItemSlotEvent(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the new slot index that will be used
|
||||
*
|
||||
* @param slot The slot index
|
||||
*/
|
||||
public final void setSlot(int slot) {
|
||||
this.slot = slot;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The current slot index
|
||||
*/
|
||||
public final int getSlot() {
|
||||
return this.slot;
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
/**
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
public enum PathEvent {
|
||||
CALC_STARTED,
|
||||
CALC_FINISHED_NOW_EXECUTING,
|
||||
CALC_FAILED,
|
||||
NEXT_SEGMENT_CALC_STARTED,
|
||||
NEXT_SEGMENT_CALC_FINISHED,
|
||||
CONTINUING_ONTO_PLANNED_NEXT,
|
||||
SPLICING_ONTO_NEXT_EARLY,
|
||||
AT_GOAL,
|
||||
PATH_FINISHED_NEXT_STILL_CALCULATING,
|
||||
NEXT_CALC_FAILED,
|
||||
DISCARD_NEXT
|
||||
}
|
||||
+17
-15
@@ -15,27 +15,29 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* Don't get into the block, but get directly adjacent to it. Useful for chests.
|
||||
*
|
||||
* @author avecowa
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public class GoalGetToBlock extends GoalComposite {
|
||||
public final class PlayerUpdateEvent {
|
||||
|
||||
public GoalGetToBlock(BlockPos pos) {
|
||||
super(adjacentBlocks(pos));
|
||||
/**
|
||||
* The state of the event
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public PlayerUpdateEvent(EventState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
private static BlockPos[] adjacentBlocks(BlockPos pos) {
|
||||
BlockPos[] sides = new BlockPos[6];
|
||||
for (int i = 0; i < 6; i++) {
|
||||
sides[i] = pos.offset(EnumFacing.values()[i]);
|
||||
}
|
||||
return sides;
|
||||
/**
|
||||
* @return The state of the event
|
||||
*/
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/21/2018
|
||||
*/
|
||||
public final class RelativeMoveEvent {
|
||||
|
||||
/**
|
||||
* The state of the event
|
||||
*/
|
||||
private final EventState state;
|
||||
|
||||
public RelativeMoveEvent(EventState state) {
|
||||
this.state = state;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The state of the event
|
||||
*/
|
||||
public final EventState getState() {
|
||||
return this.state;
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
|
||||
public final class TickEvent {
|
||||
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events;
|
||||
package baritone.api.event.events;
|
||||
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
|
||||
/**
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events.type;
|
||||
package baritone.api.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.events.type;
|
||||
package baritone.api.event.events.type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
+16
-5
@@ -32,18 +32,17 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.listener;
|
||||
package baritone.api.event.listener;
|
||||
|
||||
import baritone.bot.event.events.*;
|
||||
import baritone.api.event.events.*;
|
||||
|
||||
/**
|
||||
* An implementation of {@link IGameEventListener} that has all methods
|
||||
* overridden with empty bodies, allowing inheritors of this class to choose
|
||||
* which events they would like to listen in on.
|
||||
*
|
||||
* @see IGameEventListener
|
||||
*
|
||||
* @author Brady
|
||||
* @see IGameEventListener
|
||||
* @since 8/1/2018 6:29 PM
|
||||
*/
|
||||
public interface AbstractGameEventListener extends IGameEventListener {
|
||||
@@ -52,7 +51,7 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
||||
default void onTick(TickEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerUpdate() {}
|
||||
default void onPlayerUpdate(PlayerUpdateEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onProcessKeyBinds() {}
|
||||
@@ -74,4 +73,16 @@ public interface AbstractGameEventListener extends IGameEventListener {
|
||||
|
||||
@Override
|
||||
default void onReceivePacket(PacketEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerRelativeMove(RelativeMoveEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onBlockInteract(BlockInteractEvent event) {}
|
||||
|
||||
@Override
|
||||
default void onPlayerDeath() {}
|
||||
|
||||
@Override
|
||||
default void onPathEvent(PathEvent event) {}
|
||||
}
|
||||
+35
-4
@@ -32,17 +32,20 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event.listener;
|
||||
package baritone.api.event.listener;
|
||||
|
||||
import baritone.bot.event.events.*;
|
||||
import baritone.api.event.events.*;
|
||||
import io.netty.util.concurrent.GenericFutureListener;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.client.gui.GuiGameOver;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.NetworkManager;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -58,10 +61,11 @@ public interface IGameEventListener {
|
||||
void onTick(TickEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before the player rotation is sent to the server.
|
||||
* Run once per game tick from before and after the player rotation is sent to the server.
|
||||
*
|
||||
* @see EntityPlayerSP#onUpdate()
|
||||
*/
|
||||
void onPlayerUpdate();
|
||||
void onPlayerUpdate(PlayerUpdateEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before keybinds are processed.
|
||||
@@ -114,5 +118,32 @@ public interface IGameEventListener {
|
||||
*/
|
||||
void onReceivePacket(PacketEvent event);
|
||||
|
||||
/**
|
||||
* Run once per game tick from before and after the player's moveRelative method is called
|
||||
*
|
||||
* @see Entity#moveRelative(float, float, float, float)
|
||||
*/
|
||||
void onPlayerRelativeMove(RelativeMoveEvent event);
|
||||
|
||||
/**
|
||||
* Called when the local player interacts with a block, whether it is breaking or opening/placing.
|
||||
*
|
||||
* @see Minecraft#clickMouse()
|
||||
* @see Minecraft#rightClickMouse()
|
||||
*/
|
||||
void onBlockInteract(BlockInteractEvent event);
|
||||
|
||||
/**
|
||||
* Called when the local player dies, as indicated by the creation of the {@link GuiGameOver} screen.
|
||||
*
|
||||
* @see GuiGameOver(ITextComponent)
|
||||
*/
|
||||
void onPlayerDeath();
|
||||
|
||||
/**
|
||||
* When the pathfinder's state changes
|
||||
*
|
||||
* @param event
|
||||
*/
|
||||
void onPathEvent(PathEvent event);
|
||||
}
|
||||
+10
-5
@@ -15,10 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.behavior;
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.bot.event.listener.AbstractGameEventListener;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.interfaces.Toggleable;
|
||||
|
||||
/**
|
||||
* A generic bot behavior.
|
||||
@@ -26,7 +27,7 @@ import baritone.bot.utils.Helper;
|
||||
* @author Brady
|
||||
* @since 8/1/2018 6:29 PM
|
||||
*/
|
||||
public class Behavior implements AbstractGameEventListener, Helper {
|
||||
public class Behavior implements AbstractGameEventListener, Toggleable, Helper {
|
||||
|
||||
/**
|
||||
* Whether or not this behavior is enabled
|
||||
@@ -38,6 +39,7 @@ public class Behavior implements AbstractGameEventListener, Helper {
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean toggle() {
|
||||
return this.setEnabled(!this.enabled);
|
||||
}
|
||||
@@ -47,10 +49,12 @@ public class Behavior implements AbstractGameEventListener, Helper {
|
||||
*
|
||||
* @return The new state.
|
||||
*/
|
||||
@Override
|
||||
public final boolean setEnabled(boolean enabled) {
|
||||
boolean newState = getNewState(this.enabled, enabled);
|
||||
if (newState == this.enabled)
|
||||
if (newState == this.enabled) {
|
||||
return this.enabled;
|
||||
}
|
||||
|
||||
if (this.enabled = newState) {
|
||||
onStart();
|
||||
@@ -79,6 +83,7 @@ public class Behavior implements AbstractGameEventListener, Helper {
|
||||
/**
|
||||
* @return Whether or not this {@link Behavior} is active.
|
||||
*/
|
||||
@Override
|
||||
public final boolean isEnabled() {
|
||||
return this.enabled;
|
||||
}
|
||||
@@ -0,0 +1,60 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.pathing.goals.GoalNear;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* Follow an entity
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class FollowBehavior extends Behavior {
|
||||
public static final FollowBehavior INSTANCE = new FollowBehavior();
|
||||
|
||||
private FollowBehavior() {
|
||||
}
|
||||
|
||||
Entity following;
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
return;
|
||||
}
|
||||
if (following == null) {
|
||||
return;
|
||||
}
|
||||
// lol this is trashy but it works
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalNear(new BlockPos(following), 3));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
}
|
||||
|
||||
public void follow(Entity follow) {
|
||||
this.following = follow;
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
follow(null);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,53 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.Waypoint;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockBed;
|
||||
|
||||
/**
|
||||
* A collection of event methods that are used to interact with Baritone's
|
||||
* waypoint system. This class probably needs a better name.
|
||||
*
|
||||
* @see Waypoint
|
||||
*
|
||||
* @author Brady
|
||||
* @since 8/22/2018
|
||||
*/
|
||||
public final class LocationTrackingBehavior extends Behavior {
|
||||
|
||||
public static final LocationTrackingBehavior INSTANCE = new LocationTrackingBehavior();
|
||||
|
||||
private LocationTrackingBehavior() {}
|
||||
|
||||
@Override
|
||||
public void onBlockInteract(BlockInteractEvent event) {
|
||||
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerDeath() {
|
||||
WorldProvider.INSTANCE.getCurrentWorld().waypoints.addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,121 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.Settings;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RelativeMoveEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.utils.Rotation;
|
||||
|
||||
public class LookBehavior extends Behavior {
|
||||
|
||||
public static final LookBehavior INSTANCE = new LookBehavior();
|
||||
|
||||
private LookBehavior() {}
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
*/
|
||||
private Rotation target;
|
||||
|
||||
/**
|
||||
* Whether or not rotations are currently being forced
|
||||
*/
|
||||
private boolean force;
|
||||
|
||||
/**
|
||||
* The last player yaw angle. Used when free looking
|
||||
*
|
||||
* @see Settings#freeLook
|
||||
*/
|
||||
private float lastYaw;
|
||||
|
||||
public void updateTarget(Rotation target, boolean force) {
|
||||
this.target = target;
|
||||
this.force = force || !Baritone.settings().freeLook.get();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (this.target == null) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Whether or not we're going to silently set our angles
|
||||
boolean silent = Baritone.settings().antiCheatCompatibility.get();
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE: {
|
||||
if (this.force) {
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
float oldPitch = player().rotationPitch;
|
||||
float desiredPitch = this.target.getSecond();
|
||||
player().rotationPitch = desiredPitch;
|
||||
if (desiredPitch == oldPitch) {
|
||||
nudgeToLevel();
|
||||
}
|
||||
this.target = null;
|
||||
} else if (silent) {
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
}
|
||||
break;
|
||||
}
|
||||
case POST: {
|
||||
if (!this.force && silent) {
|
||||
player().rotationYaw = this.lastYaw;
|
||||
this.target = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerRelativeMove(RelativeMoveEvent event) {
|
||||
if (this.target != null && !this.force) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
this.lastYaw = player().rotationYaw;
|
||||
player().rotationYaw = this.target.getFirst();
|
||||
break;
|
||||
case POST:
|
||||
player().rotationYaw = this.lastYaw;
|
||||
|
||||
// If we have antiCheatCompatibility on, we're going to use the target value later in onPlayerUpdate()
|
||||
if (!Baritone.settings().antiCheatCompatibility.get()) {
|
||||
this.target = null;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void nudgeToLevel() {
|
||||
if (player().rotationPitch < -20) {
|
||||
player().rotationPitch++;
|
||||
} else if (player().rotationPitch > 10) {
|
||||
player().rotationPitch--;
|
||||
}
|
||||
}
|
||||
}
|
||||
+9
-22
@@ -15,19 +15,16 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.behavior.impl;
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.Utils;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.*;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.bot.utils.Utils.DEG_TO_RAD;
|
||||
import static baritone.utils.Utils.DEG_TO_RAD;
|
||||
|
||||
public final class LookBehaviorUtils implements Helper {
|
||||
|
||||
@@ -70,9 +67,10 @@ public final class LookBehaviorUtils implements Helper {
|
||||
return Optional.of(new Rotation(mc.player.rotationYaw, mc.player.rotationPitch + 0.0001f));
|
||||
}
|
||||
Optional<Rotation> possibleRotation = reachableCenter(pos);
|
||||
System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent())
|
||||
//System.out.println("center: " + possibleRotation);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(mc.world, pos);
|
||||
@@ -81,24 +79,13 @@ public final class LookBehaviorUtils implements Helper {
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(pos, new Vec3d(pos).add(xDiff, yDiff, zDiff));
|
||||
if (possibleRotation.isPresent())
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
}
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private static RayTraceResult rayTraceTowards(Rotation rotation) {
|
||||
double blockReachDistance = mc.playerController.getBlockReachDistance();
|
||||
Vec3d start = mc.player.getPositionEyes(1.0F);
|
||||
Vec3d direction = calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
direction.y * blockReachDistance,
|
||||
direction.z * blockReachDistance
|
||||
);
|
||||
return mc.world.rayTraceBlocks(start, end, false, false, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if coordinate is reachable with the given block-face rotation offset
|
||||
*
|
||||
@@ -108,7 +95,7 @@ public final class LookBehaviorUtils implements Helper {
|
||||
*/
|
||||
protected static Optional<Rotation> reachableOffset(BlockPos pos, Vec3d offsetPos) {
|
||||
Rotation rotation = Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F), offsetPos);
|
||||
RayTraceResult result = rayTraceTowards(rotation);
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(rotation);
|
||||
System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
+17
-13
@@ -1,7 +1,9 @@
|
||||
package baritone.bot.behavior.impl;
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.behavior.Behavior;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.network.Packet;
|
||||
import net.minecraft.network.play.client.CPacketCloseWindow;
|
||||
@@ -35,8 +37,10 @@ public class MemoryBehavior extends Behavior {
|
||||
private final Map<BlockPos, RememberedInventory> rememberedInventories = new HashMap<>();
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate() {
|
||||
updateInventory();
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (event.getState() == EventState.PRE) {
|
||||
updateInventory();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -56,7 +60,7 @@ public class MemoryBehavior extends Behavior {
|
||||
TileEntityLockable lockable = (TileEntityLockable) tileEntity;
|
||||
int size = lockable.getSizeInventory();
|
||||
|
||||
this.futureInventories.add(new FutureInventory(System.currentTimeMillis(), size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
this.futureInventories.add(new FutureInventory(System.nanoTime() / 1000000L, size, lockable.getGuiID(), tileEntity.getPos()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,18 +82,18 @@ public class MemoryBehavior extends Behavior {
|
||||
SPacketOpenWindow packet = event.cast();
|
||||
|
||||
// Remove any entries that were created over a second ago, this should make up for INSANE latency
|
||||
this.futureInventories.removeIf(i -> System.currentTimeMillis() - i.time > 1000);
|
||||
this.futureInventories.removeIf(i -> System.nanoTime() / 1000000L - i.time > 1000);
|
||||
|
||||
this.futureInventories.stream()
|
||||
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
|
||||
.findFirst().ifPresent(matched -> {
|
||||
// Remove the future inventory
|
||||
this.futureInventories.remove(matched);
|
||||
// Remove the future inventory
|
||||
this.futureInventories.remove(matched);
|
||||
|
||||
// Setup the remembered inventory
|
||||
RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
|
||||
inventory.windowId = packet.getWindowId();
|
||||
inventory.size = packet.getSlotCount();
|
||||
// Setup the remembered inventory
|
||||
RememberedInventory inventory = this.rememberedInventories.computeIfAbsent(matched.pos, pos -> new RememberedInventory());
|
||||
inventory.windowId = packet.getWindowId();
|
||||
inventory.size = packet.getSlotCount();
|
||||
});
|
||||
}
|
||||
|
||||
@@ -0,0 +1,111 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.api.event.events.PathEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.chunk.CachedChunk;
|
||||
import baritone.chunk.ChunkPacker;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.chunk.WorldScanner;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalComposite;
|
||||
import baritone.pathing.goals.GoalTwoBlocks;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* Mine blocks of a certain type
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class MineBehavior extends Behavior {
|
||||
public static final MineBehavior INSTANCE = new MineBehavior();
|
||||
|
||||
private MineBehavior() {
|
||||
}
|
||||
|
||||
List<String> mining;
|
||||
|
||||
@Override
|
||||
public void onPathEvent(PathEvent event) {
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
public void updateGoal() {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = scanFor(mining, 64);
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
cancel();
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalTwoBlocks::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
}
|
||||
|
||||
public static List<BlockPos> scanFor(List<String> mining, int max) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<String> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
for (String m : mining) {
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(ChunkPacker.stringToBlock(m))) {
|
||||
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(m, 1, 1));
|
||||
} else {
|
||||
uninteresting.add(m);
|
||||
}
|
||||
}
|
||||
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
|
||||
if (!uninteresting.isEmpty()) {
|
||||
//long before = System.currentTimeMillis();
|
||||
locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max));
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
|
||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
||||
|
||||
// remove any that are within loaded chunks that aren't actually what we want
|
||||
locs.removeAll(locs.stream()
|
||||
.filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk))
|
||||
.filter(pos -> !mining.contains(ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).toLowerCase()))
|
||||
.collect(Collectors.toList()));
|
||||
if (locs.size() > max) {
|
||||
locs = locs.subList(0, max);
|
||||
}
|
||||
return locs;
|
||||
}
|
||||
|
||||
public void mine(String... mining) {
|
||||
this.mining = mining == null || mining.length == 0 ? null : new ArrayList<>(Arrays.asList(mining));
|
||||
updateGoal();
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
mine();
|
||||
}
|
||||
}
|
||||
+135
-33
@@ -15,20 +15,26 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.behavior.impl;
|
||||
package baritone.behavior.impl;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.event.events.RenderEvent;
|
||||
import baritone.bot.event.events.TickEvent;
|
||||
import baritone.bot.pathing.calc.AStarPathFinder;
|
||||
import baritone.bot.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.bot.pathing.calc.IPathFinder;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.pathing.path.PathExecutor;
|
||||
import baritone.bot.utils.PathRenderer;
|
||||
import baritone.Baritone;
|
||||
import baritone.api.event.events.PathEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.behavior.Behavior;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.calc.IPathFinder;
|
||||
import baritone.pathing.goals.*;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.PathRenderer;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.awt.*;
|
||||
import java.util.Collections;
|
||||
@@ -51,11 +57,16 @@ public class PathingBehavior extends Behavior {
|
||||
|
||||
private final Object pathPlanLock = new Object();
|
||||
|
||||
private boolean lastAutoJump;
|
||||
|
||||
private void dispatchPathEvent(PathEvent event) {
|
||||
new Thread(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event)).start();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onTick(TickEvent event) {
|
||||
if (event.getType() == TickEvent.Type.OUT) {
|
||||
current = null;
|
||||
next = null;
|
||||
this.cancel();
|
||||
return;
|
||||
}
|
||||
if (current == null) {
|
||||
@@ -67,6 +78,7 @@ public class PathingBehavior extends Behavior {
|
||||
current = null;
|
||||
if (goal == null || goal.isInGoal(playerFeet())) {
|
||||
displayChatMessageRaw("All done. At " + goal);
|
||||
dispatchPathEvent(PathEvent.AT_GOAL);
|
||||
next = null;
|
||||
return;
|
||||
}
|
||||
@@ -78,10 +90,12 @@ public class PathingBehavior extends Behavior {
|
||||
// but if we fail in the middle of current
|
||||
// we're nowhere close to our planned ahead path
|
||||
// so need to discard it sadly.
|
||||
dispatchPathEvent(PathEvent.DISCARD_NEXT);
|
||||
next = null;
|
||||
}
|
||||
if (next != null) {
|
||||
displayChatMessageRaw("Continuing on to planned next path");
|
||||
dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
|
||||
current = next;
|
||||
next = null;
|
||||
return;
|
||||
@@ -89,10 +103,12 @@ public class PathingBehavior extends Behavior {
|
||||
// at this point, current just ended, but we aren't in the goal and have no plan for the future
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
dispatchPathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
|
||||
// if we aren't calculating right now
|
||||
return;
|
||||
}
|
||||
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
}
|
||||
return;
|
||||
}
|
||||
@@ -103,6 +119,7 @@ public class PathingBehavior extends Behavior {
|
||||
if (next.getPath().positions().contains(playerFeet())) {
|
||||
// jump directly onto the next path
|
||||
displayChatMessageRaw("Splicing into planned next path early...");
|
||||
dispatchPathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
|
||||
current = next;
|
||||
next = null;
|
||||
return;
|
||||
@@ -125,12 +142,28 @@ public class PathingBehavior extends Behavior {
|
||||
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
|
||||
// and this path has 5 seconds or less left
|
||||
displayChatMessageRaw("Path almost over. Planning ahead...");
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
|
||||
findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate(PlayerUpdateEvent event) {
|
||||
if (current != null) {
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
lastAutoJump = mc.gameSettings.autoJump;
|
||||
mc.gameSettings.autoJump = false;
|
||||
break;
|
||||
case POST:
|
||||
mc.gameSettings.autoJump = lastAutoJump;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public Optional<Double> ticksRemainingInSegment() {
|
||||
if (current == null) {
|
||||
return Optional.empty();
|
||||
@@ -142,11 +175,17 @@ public class PathingBehavior extends Behavior {
|
||||
this.goal = goal;
|
||||
}
|
||||
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
public PathExecutor getCurrent() {
|
||||
return current;
|
||||
}
|
||||
|
||||
public PathExecutor getNext() {return next;}
|
||||
public PathExecutor getNext() {
|
||||
return next;
|
||||
}
|
||||
|
||||
public Optional<IPath> getPath() {
|
||||
return Optional.ofNullable(current).map(PathExecutor::getPath);
|
||||
@@ -156,23 +195,44 @@ public class PathingBehavior extends Behavior {
|
||||
current = null;
|
||||
next = null;
|
||||
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
|
||||
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(AbstractNodeCostSearch::cancel);
|
||||
}
|
||||
|
||||
public void path() {
|
||||
/**
|
||||
* Start calculating a path if we aren't already
|
||||
*
|
||||
* @return true if this call started path calculation, false if it was already calculating or executing a path
|
||||
*/
|
||||
public boolean path() {
|
||||
if (goal == null) {
|
||||
return false;
|
||||
}
|
||||
if (goal.isInGoal(playerFeet())) {
|
||||
return false;
|
||||
}
|
||||
synchronized (pathPlanLock) {
|
||||
if (current != null) {
|
||||
displayChatMessageRaw("Currently executing a path. Please cancel it first.");
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
synchronized (pathCalcLock) {
|
||||
if (isPathCalcInProgress) {
|
||||
return;
|
||||
return false;
|
||||
}
|
||||
findPathInNewThread(playerFeet(), true, Optional.empty());
|
||||
dispatchPathEvent(PathEvent.CALC_STARTED);
|
||||
findPathInNewThread(pathStart(), true, Optional.empty());
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public BlockPos pathStart() {
|
||||
BlockPos feet = playerFeet();
|
||||
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) {
|
||||
return feet.down();
|
||||
}
|
||||
return feet;
|
||||
}
|
||||
|
||||
/**
|
||||
* In a new thread, pathfind to target blockpos
|
||||
*
|
||||
@@ -191,19 +251,33 @@ public class PathingBehavior extends Behavior {
|
||||
displayChatMessageRaw("Starting to search for path from " + start + " to " + goal);
|
||||
}
|
||||
|
||||
findPath(start, previous).map(IPath::cutoffAtLoadedChunks).map(PathExecutor::new).ifPresent(path -> {
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null) {
|
||||
current = path;
|
||||
Optional<IPath> path = findPath(start, previous);
|
||||
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
|
||||
path = path.map(IPath::cutoffAtLoadedChunks);
|
||||
}
|
||||
Optional<PathExecutor> executor = path.map(p -> p.staticCutoff(goal)).map(PathExecutor::new);
|
||||
synchronized (pathPlanLock) {
|
||||
if (current == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
|
||||
current = executor.get();
|
||||
} else {
|
||||
if (next == null) {
|
||||
next = path;
|
||||
dispatchPathEvent(PathEvent.CALC_FAILED);
|
||||
}
|
||||
} else {
|
||||
if (next == null) {
|
||||
if (executor.isPresent()) {
|
||||
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
|
||||
next = executor.get();
|
||||
} else {
|
||||
throw new IllegalStateException("I have no idea what to do with this path");
|
||||
dispatchPathEvent(PathEvent.NEXT_CALC_FAILED);
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("I have no idea what to do with this path");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
if (talkAboutIt && current != null && current.getPath() != null) {
|
||||
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
||||
displayChatMessageRaw("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
@@ -225,15 +299,42 @@ public class PathingBehavior extends Behavior {
|
||||
* @return
|
||||
*/
|
||||
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
|
||||
Goal goal = this.goal;
|
||||
if (goal == null) {
|
||||
displayChatMessageRaw("no goal");
|
||||
return Optional.empty();
|
||||
}
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
|
||||
BlockPos pos = null;
|
||||
if (goal instanceof GoalBlock) {
|
||||
pos = ((GoalBlock) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalTwoBlocks) {
|
||||
pos = ((GoalTwoBlocks) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalNear) {
|
||||
pos = ((GoalNear) goal).getGoalPos();
|
||||
}
|
||||
if (goal instanceof GoalGetToBlock) {
|
||||
pos = ((GoalGetToBlock) goal).getGoalPos();
|
||||
}
|
||||
// TODO simplify each individual goal in a GoalComposite
|
||||
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
|
||||
displayChatMessageRaw("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
|
||||
goal = new GoalXZ(pos.getX(), pos.getZ());
|
||||
}
|
||||
}
|
||||
long timeout;
|
||||
if (current == null) {
|
||||
timeout = Baritone.settings().pathTimeoutMS.<Long>get();
|
||||
} else {
|
||||
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
|
||||
}
|
||||
try {
|
||||
IPathFinder pf = new AStarPathFinder(start, goal, previous.map(IPath::positions));
|
||||
return pf.calculate();
|
||||
return pf.calculate(timeout);
|
||||
} catch (Exception e) {
|
||||
displayChatMessageRaw("Exception: " + e);
|
||||
displayChatMessageRaw("Pathing exception: " + e);
|
||||
e.printStackTrace();
|
||||
return Optional.empty();
|
||||
}
|
||||
@@ -265,7 +366,7 @@ public class PathingBehavior extends Behavior {
|
||||
PathRenderer.drawPath(current.getPath(), renderBegin, player(), partialTicks, Color.RED, Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
if (next != null && next.getPath() != null) {
|
||||
PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Color.GREEN, Baritone.settings().fadePath.get(), 10, 20);
|
||||
PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Color.MAGENTA, Baritone.settings().fadePath.get(), 10, 20);
|
||||
}
|
||||
|
||||
long split = System.nanoTime();
|
||||
@@ -288,8 +389,9 @@ public class PathingBehavior extends Behavior {
|
||||
});
|
||||
long end = System.nanoTime();
|
||||
//System.out.println((end - split) + " " + (split - start));
|
||||
// if (end - start > 0)
|
||||
// if (end - start > 0) {
|
||||
// System.out.println("Frame took " + (split - start) + " " + (end - split));
|
||||
//}
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,133 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot;
|
||||
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Baritone's settings
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Settings {
|
||||
public Setting<Boolean> allowBreak = new Setting<>(true);
|
||||
public Setting<Boolean> allowPlaceThrowaway = new Setting<>(true);
|
||||
/**
|
||||
* It doesn't actually take twenty ticks to place a block, this cost is so high
|
||||
* because we want to generally conserve blocks which might be limited
|
||||
*/
|
||||
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
|
||||
public Setting<Boolean> allowSprint = new Setting<>(true);
|
||||
public Setting<Double> costHeuristic = new <Double>Setting<Double>(4D);
|
||||
public Setting<Boolean> chuckCaching = new Setting<>(false);
|
||||
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
|
||||
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
|
||||
public Setting<Boolean> chatDebug = new Setting<>(true);
|
||||
public Setting<Boolean> chatControl = new Setting<>(true); // probably false in impact
|
||||
public Setting<Boolean> renderPath = new Setting<>(true);
|
||||
public Setting<Boolean> fadePath = new Setting<>(false); // give this a better name in the UI, like "better path fps" idk
|
||||
public Setting<Number> pathTimeoutMS = new Setting<>(4000L);
|
||||
public Setting<Boolean> slowPath = new Setting<>(false);
|
||||
public Setting<Number> slowPathTimeDelayMS = new Setting<>(100L);
|
||||
public Setting<Number> slowPathTimeoutMS = new Setting<>(40000L);
|
||||
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK)
|
||||
));
|
||||
public Setting<Boolean> renderGoal = new Setting<>(true);
|
||||
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
|
||||
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.9); // see issue #18
|
||||
public Setting<Float> pathRenderLineWidth = new Setting<>(5F);
|
||||
public Setting<Float> goalRenderLineWidth = new Setting<>(3F);
|
||||
|
||||
public final Map<String, Setting<?>> byName;
|
||||
public final List<Setting<?>> allSettings;
|
||||
|
||||
public class Setting<T> {
|
||||
public T value;
|
||||
private String name;
|
||||
private final Class<T> klass;
|
||||
|
||||
private Setting(T value) {
|
||||
if (value == null) {
|
||||
throw new IllegalArgumentException("Cannot determine value type class from null");
|
||||
}
|
||||
this.value = value;
|
||||
this.klass = (Class<T>) value.getClass();
|
||||
}
|
||||
|
||||
public final <K extends T> K get() {
|
||||
return (K) value;
|
||||
}
|
||||
|
||||
public final String getName() {
|
||||
return name;
|
||||
}
|
||||
|
||||
public Class<T> getValueClass() {
|
||||
return klass;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + ": " + value;
|
||||
}
|
||||
}
|
||||
|
||||
// here be dragons
|
||||
|
||||
{
|
||||
Field[] temp = getClass().getFields();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Setting.class)) {
|
||||
Setting<?> setting = (Setting<? extends Object>) field.get(this);
|
||||
String name = field.getName();
|
||||
setting.name = name;
|
||||
if (tmpByName.containsKey(name)) {
|
||||
throw new IllegalStateException("Duplicate setting name");
|
||||
}
|
||||
tmpByName.put(name, setting);
|
||||
tmpAll.add(setting);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
byName = Collections.unmodifiableMap(tmpByName);
|
||||
allSettings = Collections.unmodifiableList(tmpAll);
|
||||
}
|
||||
|
||||
public <T> List<Setting<T>> getByValueType(Class<T> klass) {
|
||||
ArrayList<Setting<T>> result = new ArrayList<>();
|
||||
for (Setting<?> setting : allSettings) {
|
||||
if (setting.klass.equals(klass)) {
|
||||
result.add((Setting<T>) setting);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
Settings() { }
|
||||
}
|
||||
@@ -1,62 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.behavior.impl;
|
||||
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.utils.Rotation;
|
||||
|
||||
public class LookBehavior extends Behavior {
|
||||
|
||||
public static final LookBehavior INSTANCE = new LookBehavior();
|
||||
|
||||
private LookBehavior() {}
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
*/
|
||||
private Rotation target;
|
||||
|
||||
public void updateTarget(Rotation target) {
|
||||
this.target = target;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate() {
|
||||
if (target != null) {
|
||||
player().rotationYaw = target.getFirst();
|
||||
float oldPitch = player().rotationPitch;
|
||||
float desiredPitch = target.getSecond();
|
||||
player().rotationPitch = desiredPitch;
|
||||
if (desiredPitch == oldPitch) {
|
||||
nudgeToLevel();
|
||||
}
|
||||
target = null;
|
||||
}
|
||||
}
|
||||
|
||||
private void nudgeToLevel() {
|
||||
if (player().rotationPitch < -20) {
|
||||
player().rotationPitch++;
|
||||
} else if (player().rotationPitch > 10) {
|
||||
player().rotationPitch--;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,131 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.IBlockTypeAccess;
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:04 AM
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess {
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
* <p>
|
||||
* Chunks are 16x16x256, each block requires 2 bits.
|
||||
*/
|
||||
public static final int SIZE = 2 * 16 * 16 * 256;
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bytes. Equal to 16 KiB.
|
||||
*/
|
||||
public static final int SIZE_IN_BYTES = SIZE / 8;
|
||||
|
||||
/**
|
||||
* An array of just 0s with the length of {@link CachedChunk#SIZE_IN_BYTES}
|
||||
*/
|
||||
public static final byte[] EMPTY_CHUNK = new byte[SIZE_IN_BYTES];
|
||||
|
||||
/**
|
||||
* The chunk x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The chunk z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
/**
|
||||
* The actual raw data of this packed chunk.
|
||||
* <p>
|
||||
* Each block is expressed as 2 bits giving a total of 16 KiB
|
||||
*/
|
||||
private final BitSet data;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data) {
|
||||
validateSize(data);
|
||||
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
int index = getPositionIndex(x, y, z);
|
||||
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
||||
}
|
||||
|
||||
void updateContents(BitSet data) {
|
||||
validateSize(data);
|
||||
|
||||
for (int i = 0; i < data.length(); i++)
|
||||
this.data.set(i, data.get(i));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Thee chunk x coordinat
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The chunk z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the raw packed chunk data as a byte array
|
||||
*/
|
||||
public final byte[] toByteArray() {
|
||||
return this.data.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw bit index of the specified position
|
||||
*
|
||||
* @param x The x position
|
||||
* @param y The y position
|
||||
* @param z The z position
|
||||
* @return The bit index
|
||||
*/
|
||||
public static int getPositionIndex(int x, int y, int z) {
|
||||
return (x + (z << 4) + (y << 8)) * 2;
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the size of an input {@link BitSet} containing the raw
|
||||
* packed chunk data. Sizes that exceed {@link CachedChunk#SIZE} are
|
||||
* considered invalid, and thus, an exception will be thrown.
|
||||
*
|
||||
* @param data The raw data
|
||||
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
|
||||
*/
|
||||
private static void validateSize(BitSet data) {
|
||||
if (data.size() > SIZE)
|
||||
throw new IllegalArgumentException("BitSet of invalid length provided");
|
||||
}
|
||||
}
|
||||
@@ -1,180 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import baritone.bot.utils.GZIPUtils;
|
||||
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 9:35 PM
|
||||
*/
|
||||
public final class CachedRegion implements ICachedChunkAccess {
|
||||
|
||||
/**
|
||||
* All of the chunks in this region: A 32x32 array of them.
|
||||
*/
|
||||
private final CachedChunk[][] chunks = new CachedChunk[32][32];
|
||||
|
||||
/**
|
||||
* The region x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The region z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
CachedRegion(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
CachedChunk chunk = this.getChunk(x >> 4, z >> 4);
|
||||
if (chunk != null) {
|
||||
return chunk.getBlockType(x & 15, y, z & 15);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
|
||||
CachedChunk chunk = this.getChunk(chunkX, chunkZ);
|
||||
if (chunk == null) {
|
||||
this.chunks[chunkX][chunkZ] = new CachedChunk(chunkX, chunkZ, data);
|
||||
} else {
|
||||
chunk.updateContents(data);
|
||||
}
|
||||
}
|
||||
|
||||
private CachedChunk getChunk(int chunkX, int chunkZ) {
|
||||
return this.chunks[chunkX][chunkZ];
|
||||
}
|
||||
|
||||
public void forEachChunk(Consumer<CachedChunk> consumer) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
CachedChunk chunk = getChunk(x, z);
|
||||
if (chunk != null) {
|
||||
consumer.accept(chunk);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final void save(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
Files.createFile(regionFile);
|
||||
try (FileOutputStream fileOut = new FileOutputStream(regionFile.toFile()); GZIPOutputStream out = new GZIPOutputStream(fileOut)) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
CachedChunk chunk = this.chunks[x][z];
|
||||
if (chunk == null) {
|
||||
out.write(CachedChunk.EMPTY_CHUNK);
|
||||
} else {
|
||||
byte[] chunkBytes = chunk.toByteArray();
|
||||
out.write(chunkBytes);
|
||||
// Messy, but fills the empty 0s that should be trailing to fill up the space.
|
||||
out.write(new byte[CachedChunk.SIZE_IN_BYTES - chunkBytes.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
public void load(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path))
|
||||
Files.createDirectories(path);
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile))
|
||||
return;
|
||||
|
||||
byte[] decompressed;
|
||||
try (FileInputStream in = new FileInputStream(regionFile.toFile())) {
|
||||
decompressed = GZIPUtils.decompress(in);
|
||||
}
|
||||
|
||||
if (decompressed == null)
|
||||
return;
|
||||
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
int index = (x + (z << 5)) * CachedChunk.SIZE_IN_BYTES;
|
||||
byte[] bytes = Arrays.copyOfRange(decompressed, index, index + CachedChunk.SIZE_IN_BYTES);
|
||||
if (isAllZeros(bytes)) {
|
||||
this.chunks[x][z] = null;
|
||||
} else {
|
||||
BitSet bits = BitSet.valueOf(bytes);
|
||||
updateCachedChunk(x, z, bits);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
private static boolean isAllZeros(final byte[] array) {
|
||||
for (byte b : array) {
|
||||
if (b != 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
private static Path getRegionFile(Path cacheDir, int regionX, int regionZ) {
|
||||
return Paths.get(cacheDir.toString(), "r." + regionX + "." + regionZ + ".bcr");
|
||||
}
|
||||
}
|
||||
@@ -1,144 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.BitSet;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 12:02 AM
|
||||
*/
|
||||
public final class CachedWorld implements ICachedChunkAccess {
|
||||
|
||||
/**
|
||||
* The maximum number of regions in any direction from (0,0)
|
||||
*/
|
||||
private static final int REGION_MAX = 117188;
|
||||
|
||||
/**
|
||||
* A map of all of the cached regions.
|
||||
*/
|
||||
private Long2ObjectMap<CachedRegion> cachedRegions = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* The directory that the cached region files are saved to
|
||||
*/
|
||||
private final String directory;
|
||||
|
||||
public CachedWorld(String directory) {
|
||||
this.directory = directory;
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
}
|
||||
|
||||
@Override
|
||||
public final PathingBlockType getBlockType(int x, int y, int z) {
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region != null) {
|
||||
return region.getBlockType(x & 511, y, z & 511);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final void updateCachedChunk(int chunkX, int chunkZ, BitSet data) {
|
||||
CachedRegion region = getOrCreateRegion(chunkX >> 5, chunkZ >> 5);
|
||||
if (region != null) {
|
||||
region.updateCachedChunk(chunkX & 31, chunkZ & 31, data);
|
||||
}
|
||||
}
|
||||
|
||||
public final void save() {
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.save(this.directory);
|
||||
});
|
||||
}
|
||||
|
||||
public final void load() {
|
||||
this.cachedRegions.values().forEach(region -> {
|
||||
if (region != null)
|
||||
region.load(this.directory);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
public final CachedRegion getRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.get(getRegionID(regionX, regionZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates. If a
|
||||
* region is not found, then a new one is created.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
CachedRegion getOrCreateRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||
newRegion.load(this.directory);
|
||||
return newRegion;
|
||||
});
|
||||
}
|
||||
|
||||
public void forEachRegion(Consumer<CachedRegion> consumer) {
|
||||
this.cachedRegions.forEach((id, r) -> {
|
||||
if (r != null)
|
||||
consumer.accept(r);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region ID based on the region coordinates. 0 will be
|
||||
* returned if the specified region coordinates are out of bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region ID
|
||||
*/
|
||||
private long getRegionID(int regionX, int regionZ) {
|
||||
if (!isRegionInWorld(regionX, regionZ))
|
||||
return 0;
|
||||
|
||||
return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified region coordinates is within the world bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return Whether or not the region is in world bounds
|
||||
*/
|
||||
private boolean isRegionInWorld(int regionX, int regionZ) {
|
||||
return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX;
|
||||
}
|
||||
}
|
||||
@@ -1,98 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.launch.mixins.accessor.IAnvilChunkLoader;
|
||||
import baritone.launch.mixins.accessor.IChunkProviderServer;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
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.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:06 AM
|
||||
*/
|
||||
public enum CachedWorldProvider implements Helper {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private static final Pattern REGION_REGEX = Pattern.compile("r\\.(-?[0-9]+)\\.(-?[0-9]+)\\.bcr");
|
||||
|
||||
private final Map<String, CachedWorld> singlePlayerWorldCache = new HashMap<>();
|
||||
|
||||
private CachedWorld currentWorld;
|
||||
|
||||
public final CachedWorld getCurrentWorld() {
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
public final void initWorld(WorldClient world) {
|
||||
IntegratedServer integratedServer;
|
||||
if ((integratedServer = mc.getIntegratedServer()) != null) {
|
||||
|
||||
WorldServer localServerWorld = integratedServer.getWorld(world.provider.getDimensionType().getId());
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
|
||||
Path dir = new File(new File(loader.getChunkSaveLocation(), "region"), "cache").toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
this.currentWorld = this.singlePlayerWorldCache.computeIfAbsent(dir.toString(), CachedWorld::new);
|
||||
|
||||
try {
|
||||
Files.list(dir).forEach(path -> {
|
||||
String file = path.getFileName().toString();
|
||||
Matcher matcher = REGION_REGEX.matcher(file);
|
||||
if (matcher.matches()) {
|
||||
int rx = Integer.parseInt(matcher.group(1));
|
||||
int ry = Integer.parseInt(matcher.group(2));
|
||||
// Recognize the region for when we load from file
|
||||
this.currentWorld.getOrCreateRegion(rx, ry);
|
||||
}
|
||||
});
|
||||
} catch (Exception ignored) {}
|
||||
|
||||
this.currentWorld.load();
|
||||
}
|
||||
// TODO: Store server worlds
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
this.currentWorld = null;
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<CachedWorld> currentWorldConsumer) {
|
||||
if (this.currentWorld != null)
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
}
|
||||
}
|
||||
@@ -1,78 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.chunk;
|
||||
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.utils.pathing.PathingBlockType;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.util.BitSet;
|
||||
|
||||
import static net.minecraft.block.Block.NULL_AABB;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:09 AM
|
||||
*/
|
||||
public final class ChunkPacker implements Helper {
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
public static BitSet createPackedChunk(Chunk chunk) {
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
boolean[] bits = getPathingBlockType(new BlockPos(x, y, z), chunk.getBlockState(x, y, z)).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
|
||||
if (block instanceof BlockAir || state.getCollisionBoundingBox(mc.world, pos) == NULL_AABB) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
return PathingBlockType.SOLID;
|
||||
}
|
||||
}
|
||||
@@ -1,189 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.event;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.chunk.CachedWorld;
|
||||
import baritone.bot.chunk.CachedWorldProvider;
|
||||
import baritone.bot.chunk.ChunkPacker;
|
||||
import baritone.bot.event.events.*;
|
||||
import baritone.bot.event.events.type.EventState;
|
||||
import baritone.bot.event.listener.IGameEventListener;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import net.minecraft.client.renderer.BufferBuilder;
|
||||
import net.minecraft.client.renderer.GlStateManager;
|
||||
import net.minecraft.client.renderer.Tessellator;
|
||||
import net.minecraft.client.renderer.vertex.DefaultVertexFormats;
|
||||
import net.minecraft.client.settings.KeyBinding;
|
||||
import org.lwjgl.input.Keyboard;
|
||||
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 7/31/2018 11:04 PM
|
||||
*/
|
||||
public final class GameEventHandler implements IGameEventListener, Helper {
|
||||
|
||||
@Override
|
||||
public final void onTick(TickEvent event) {
|
||||
dispatch(behavior -> behavior.onTick(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onPlayerUpdate() {
|
||||
dispatch(Behavior::onPlayerUpdate);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onProcessKeyBinds() {
|
||||
InputOverrideHandler inputHandler = Baritone.INSTANCE.getInputOverrideHandler();
|
||||
|
||||
// Simulate the key being held down this tick
|
||||
for (InputOverrideHandler.Input input : InputOverrideHandler.Input.values()) {
|
||||
KeyBinding keyBinding = input.getKeyBinding();
|
||||
|
||||
if (inputHandler.isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
|
||||
int keyCode = keyBinding.getKeyCode();
|
||||
|
||||
if (keyCode < Keyboard.KEYBOARD_SIZE)
|
||||
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(Behavior::onProcessKeyBinds);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
dispatch(behavior -> behavior.onSendChatMessage(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onChunkEvent(ChunkEvent event) {
|
||||
EventState state = event.getState();
|
||||
ChunkEvent.Type type = event.getType();
|
||||
|
||||
boolean isPostPopulate = state == EventState.POST
|
||||
&& type == ChunkEvent.Type.POPULATE;
|
||||
|
||||
// Whenever the server sends us to another dimension, chunks are unloaded
|
||||
// technically after the new world has been loaded, so we perform a check
|
||||
// to make sure the chunk being unloaded is already loaded.
|
||||
boolean isPreUnload = state == EventState.PRE
|
||||
&& type == ChunkEvent.Type.UNLOAD
|
||||
&& mc.world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
|
||||
if (Baritone.settings().chuckCaching.get()) {
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
CachedWorldProvider.INSTANCE.ifWorldLoaded(world ->
|
||||
world.updateCachedChunk(event.getX(), event.getZ(),
|
||||
ChunkPacker.createPackedChunk(mc.world.getChunk(event.getX(), event.getZ()))));
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(behavior -> behavior.onChunkEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onRenderPass(RenderEvent event) {
|
||||
/*
|
||||
CachedWorldProvider.INSTANCE.ifWorldLoaded(world -> world.forEachRegion(region -> region.forEachChunk(chunk -> {
|
||||
drawChunkLine(region.getX() * 512 + chunk.getX() * 16, region.getZ() * 512 + chunk.getZ() * 16, event.getPartialTicks());
|
||||
})));
|
||||
*/
|
||||
|
||||
dispatch(behavior -> behavior.onRenderPass(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onWorldEvent(WorldEvent event) {
|
||||
if (Baritone.settings().chuckCaching.get()) {
|
||||
CachedWorldProvider cache = CachedWorldProvider.INSTANCE;
|
||||
|
||||
switch (event.getState()) {
|
||||
case PRE:
|
||||
cache.ifWorldLoaded(CachedWorld::save);
|
||||
break;
|
||||
case POST:
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null)
|
||||
cache.initWorld(event.getWorld());
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
dispatch(behavior -> behavior.onWorldEvent(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendPacket(PacketEvent event) {
|
||||
dispatch(behavior -> behavior.onSendPacket(event));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onReceivePacket(PacketEvent event) {
|
||||
dispatch(behavior -> behavior.onReceivePacket(event));
|
||||
}
|
||||
|
||||
private void dispatch(Consumer<Behavior> dispatchFunction) {
|
||||
Baritone.INSTANCE.getBehaviors().stream().filter(Behavior::isEnabled).forEach(dispatchFunction);
|
||||
}
|
||||
|
||||
private void drawChunkLine(int posX, int posZ, float partialTicks) {
|
||||
GlStateManager.enableBlend();
|
||||
GlStateManager.tryBlendFuncSeparate(770, 771, 1, 0);
|
||||
GlStateManager.color(1.0F, 1.0F, 0.0F, 0.4F);
|
||||
GlStateManager.glLineWidth(2.0F);
|
||||
GlStateManager.disableTexture2D();
|
||||
|
||||
Tessellator tessellator = Tessellator.getInstance();
|
||||
BufferBuilder buffer = tessellator.getBuffer();
|
||||
double d0 = mc.getRenderManager().viewerPosX;
|
||||
double d1 = mc.getRenderManager().viewerPosY;
|
||||
double d2 = mc.getRenderManager().viewerPosZ;
|
||||
buffer.begin(3, DefaultVertexFormats.POSITION);
|
||||
buffer.pos(posX - d0, 0 - d1, posZ - d2).endVertex();
|
||||
buffer.pos(posX - d0, 256 - d1, posZ - d2).endVertex();
|
||||
tessellator.draw();
|
||||
|
||||
GlStateManager.enableDepth();
|
||||
GlStateManager.depthMask(true);
|
||||
GlStateManager.enableTexture2D();
|
||||
GlStateManager.disableBlend();
|
||||
}
|
||||
}
|
||||
@@ -1,302 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.bot.pathing.movement.movements.MovementDescend;
|
||||
import baritone.bot.pathing.movement.movements.MovementFall;
|
||||
import baritone.bot.utils.*;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(BlockPos pos, IBlockState state) {
|
||||
Block b = state.getBlock();
|
||||
BlockPos below = new BlockPos(pos.getX(), pos.getY() - 1, pos.getZ());
|
||||
return Blocks.ICE.equals(b) // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY() + 1, pos.getZ()))//don't break anything touching liquid on any side
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() + 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX() - 1, pos.getY(), pos.getZ()))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() + 1))
|
||||
|| BlockStateInterface.isLiquid(new BlockPos(pos.getX(), pos.getY(), pos.getZ() - 1))
|
||||
|| (!(b instanceof BlockLilyPad && BlockStateInterface.isWater(below)) && BlockStateInterface.isLiquid(below));//if it's a lilypad above water, it's ok to break, otherwise don't break if its liquid
|
||||
}
|
||||
|
||||
/**
|
||||
* Can I walk through this block? e.g. air, saplings, torches, etc
|
||||
*
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkThrough(BlockPos pos) {
|
||||
return canWalkThrough(pos, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof BlockLilyPad
|
||||
|| block instanceof BlockFire
|
||||
|| block instanceof BlockTripWire
|
||||
|| block instanceof BlockWeb
|
||||
|| block instanceof BlockEndPortal) {//you can't actually walk through a lilypad from the side, and you shouldn't walk through fire
|
||||
return false;
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state) || BlockStateInterface.isLiquid(pos.up())) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockDoor) {
|
||||
return true; // we can just open the door
|
||||
}
|
||||
return block.isPassable(mc.world, pos);
|
||||
}
|
||||
|
||||
static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) {
|
||||
IBlockState door = BlockStateInterface.get(doorPos);
|
||||
if (!(door.getBlock() instanceof BlockDoor)) {
|
||||
return true;
|
||||
}
|
||||
String facing = door.getValue(BlockDoor.FACING).getName();
|
||||
boolean open = door.getValue(BlockDoor.OPEN).booleanValue();
|
||||
/**
|
||||
* yes this is dumb
|
||||
* change it if you want
|
||||
*/
|
||||
String playerFacing = "";
|
||||
if (playerPos.equals(doorPos)) {
|
||||
return false;
|
||||
}
|
||||
if (playerPos.north().equals(doorPos) || playerPos.south().equals(doorPos)) {
|
||||
playerFacing = "northsouth";
|
||||
} else if (playerPos.east().equals(doorPos) || playerPos.west().equals(doorPos)) {
|
||||
playerFacing = "eastwest";
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (facing == "north" || facing == "south") {
|
||||
if (open) {
|
||||
return playerFacing == "northsouth";
|
||||
} else {
|
||||
return playerFacing == "eastwest";
|
||||
}
|
||||
} else {
|
||||
if (open) {
|
||||
return playerFacing == "eastwest";
|
||||
} else {
|
||||
return playerFacing == "northsouth";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
return BlockStateInterface.isLava(block)
|
||||
|| block instanceof BlockCactus
|
||||
|| block instanceof BlockFire
|
||||
|| block instanceof BlockEndPortal
|
||||
|| block instanceof BlockWeb;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can I walk on this block without anything weird happening like me falling
|
||||
* through? Includes water because we know that we automatically jump on
|
||||
* water
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkOn(BlockPos pos, IBlockState state) {
|
||||
|
||||
Block block = state.getBlock();
|
||||
if (block instanceof BlockLadder || block instanceof BlockVine) { // TODO reconsider this
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockAir) {
|
||||
return false;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
return BlockStateInterface.isWater(pos.up()); // You can only walk on water if there is water above it
|
||||
}
|
||||
if (Blocks.MAGMA.equals(block)) {
|
||||
return false;
|
||||
}
|
||||
return state.isBlockNormalCube() && !BlockStateInterface.isLava(block);
|
||||
}
|
||||
|
||||
static boolean canWalkOn(BlockPos pos) {
|
||||
return canWalkOn(pos, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canFall(BlockPos pos) {
|
||||
return BlockStateInterface.get(pos).getBlock() instanceof BlockFalling;
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position, state);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (!block.equals(Blocks.AIR) && !canWalkThrough(position, state)) { // TODO is the air check really necessary? Isn't air canWalkThrough?
|
||||
if (!context.allowBreak()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (avoidBreaking(position, state)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
|
||||
return m / context.getToolSet().getStrVsBlock(state, position);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* The entity the player is currently looking at
|
||||
*
|
||||
* @return the entity object
|
||||
*/
|
||||
static Optional<Entity> whatEntityAmILookingAt() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(mc.objectMouseOver.entityHit);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool
|
||||
*/
|
||||
static void switchToBestTool() {
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(pos -> {
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
if (state.getBlock().equals(Blocks.AIR)) {
|
||||
return;
|
||||
}
|
||||
switchToBestToolFor(state);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool for a specific block
|
||||
*
|
||||
* @param b the blockstate to mine
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b) {
|
||||
switchToBestToolFor(b, new ToolSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool for a specific block with precomputed ToolSet data
|
||||
*
|
||||
* @param b the blockstate to mine
|
||||
* @param ts previously calculated ToolSet
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
||||
mc.player.inventory.currentItem = ts.getBestSlot(b);
|
||||
}
|
||||
|
||||
static boolean throwaway(boolean select) {
|
||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
// this usage of settings() is okay because it's only called once during pathing
|
||||
// (while creating the CalculationContext at the very beginning)
|
||||
// and then it's called during execution
|
||||
// since this function is never called during cost calculation, we don't need to migrate
|
||||
// acceptableThrowawayItems to the CalculationContext
|
||||
if (Baritone.settings().acceptableThrowawayItems.get().contains(item.getItem())) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void moveTowards(MovementState state, BlockPos pos) {
|
||||
state.setTarget(new MovementTarget(new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch))
|
||||
).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
|
||||
static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
|
||||
// A
|
||||
//SA
|
||||
// B
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
//if S is where you start, both of B need to be air for a movementfall
|
||||
//A is plausibly breakable by either descend or fall
|
||||
//C, D, etc determine the length of the fall
|
||||
for (int i = 1; i < 3; i++) {
|
||||
if (!canWalkThrough(dest.down(i))) {
|
||||
//if any of these two (B in the diagram) aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
}
|
||||
}
|
||||
// we're clear for a fall 2
|
||||
// let's see how far we can fall
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
BlockPos onto = dest.down(fallHeight);
|
||||
if (onto.getY() < 0) {
|
||||
break;
|
||||
}
|
||||
IBlockState ontoBlock = BlockStateInterface.get(onto);
|
||||
if (BlockStateInterface.isWater(ontoBlock.getBlock())) {
|
||||
return new MovementFall(pos, onto);
|
||||
}
|
||||
if (canWalkThrough(onto, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (canWalkOn(onto, ontoBlock)) {
|
||||
if (calcContext.hasWaterBucket() || fallHeight <= 4) {
|
||||
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
|
||||
return new MovementFall(pos, onto.up());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -1,173 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.bot.utils.Utils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MovementAscend extends Movement {
|
||||
|
||||
private BlockPos[] against = new BlockPos[3];
|
||||
private int ticksWithoutPlacement = 0;
|
||||
|
||||
public MovementAscend(BlockPos src, BlockPos dest) {
|
||||
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, new BlockPos[]{dest.down()});
|
||||
|
||||
BlockPos placementLocation = positionsToPlace[0]; // dest.down()
|
||||
int i = 0;
|
||||
if (!placementLocation.north().equals(src))
|
||||
against[i++] = placementLocation.north();
|
||||
|
||||
if (!placementLocation.south().equals(src))
|
||||
against[i++] = placementLocation.south();
|
||||
|
||||
if (!placementLocation.east().equals(src))
|
||||
against[i++] = placementLocation.east();
|
||||
|
||||
if (!placementLocation.west().equals(src))
|
||||
against[i] = placementLocation.west();
|
||||
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
// useful for when you are starting a staircase without anything to place against
|
||||
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState toPlace = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0], toPlace)) {
|
||||
if (!BlockStateInterface.isAir(toPlace) && !BlockStateInterface.isWater(toPlace.getBlock())) {
|
||||
// TODO replace this check with isReplacable or similar
|
||||
return COST_INF;
|
||||
}
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
for (BlockPos against1 : against) {
|
||||
if (BlockStateInterface.get(against1).isBlockNormalCube()) {
|
||||
return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
}
|
||||
return COST_INF;
|
||||
}
|
||||
if (BlockStateInterface.get(src.up(3)).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
Block srcUp = BlockStateInterface.get(src.up(1)).getBlock();
|
||||
Block srcUp2 = BlockStateInterface.get(src.up(2)).getBlock();
|
||||
if (!(srcUp instanceof BlockFalling) || !(srcUp2 instanceof BlockFalling)) {
|
||||
// if both of those are BlockFalling, that means that by standing on src
|
||||
// (the presupposition of this Movement)
|
||||
// we have necessarily already cleared the entire BlockFalling stack
|
||||
// on top of our head
|
||||
|
||||
// but if either of them aren't BlockFalling, that means we're still in suffocation danger
|
||||
// so don't do it
|
||||
return COST_INF;
|
||||
}
|
||||
// you may think we only need to check srcUp2, not srcUp
|
||||
// however, in the scenario where glitchy world gen where unsupported sand / gravel generates
|
||||
// it's possible srcUp is AIR from the start, and srcUp2 is falling
|
||||
// and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us
|
||||
}
|
||||
// TODO maybe change behavior if src.down() is soul sand?
|
||||
double walk = WALK_ONE_BLOCK_COST;
|
||||
if (toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
|
||||
}
|
||||
// we hit space immediately on entering this action
|
||||
return Math.max(JUMP_ONE_BLOCK_COST, walk) + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
// TODO incorporate some behavior from ActionClimb (specifically how it waited until it was at most 1.2 blocks away before starting to jump
|
||||
// for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly)
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
for (BlockPos anAgainst : against) {
|
||||
if (BlockStateInterface.get(anAgainst).isBlockNormalCube()) {
|
||||
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations())));
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
if (Objects.equals(LookBehaviorUtils.getSelectedBlock().orElse(null), anAgainst) && LookBehaviorUtils.getSelectedBlock().get().offset(side).equals(positionsToPlace[0])) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (player().isSneaking()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
if (ticksWithoutPlacement > 20) {
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);//we might be standing in the way, move back
|
||||
}
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + LookBehaviorUtils.getSelectedBlock());
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
|
||||
// TODO check if the below actually helps or hurts, it's weird
|
||||
//double flatDistToNext = Math.abs(to.getX() - from.getX()) * Math.abs((to.getX() + 0.5D) - thePlayer.posX) + Math.abs(to.getZ() - from.getZ()) * Math.abs((to.getZ() + 0.5D) - thePlayer.posZ);
|
||||
//boolean pointingInCorrectDirection = MovementManager.moveTowardsBlock(to);
|
||||
//MovementManager.jumping = flatDistToNext < 1.2 && pointingInCorrectDirection;
|
||||
//once we are pointing the right way and moving, start jumping
|
||||
//this is slightly more efficient because otherwise we might start jumping before moving, and fall down without moving onto the block we want to jump onto
|
||||
//also wait until we are close enough, because we might jump and hit our head on an adjacent block
|
||||
//return Baritone.playerFeet.equals(to);
|
||||
|
||||
return state;
|
||||
}
|
||||
}
|
||||
@@ -1,115 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.Settings;
|
||||
import baritone.bot.behavior.Behavior;
|
||||
import baritone.bot.behavior.impl.PathingBehavior;
|
||||
import baritone.bot.event.events.ChatEvent;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.goals.GoalBlock;
|
||||
import baritone.bot.pathing.goals.GoalXZ;
|
||||
import baritone.bot.pathing.goals.GoalYLevel;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior {
|
||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||
|
||||
private ExampleBaritoneControl() {
|
||||
|
||||
}
|
||||
|
||||
public void initAndRegister() {
|
||||
Baritone.INSTANCE.registerBehavior(this);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onSendChatMessage(ChatEvent event) {
|
||||
if (!Baritone.settings().chatControl.get()) {
|
||||
return;
|
||||
}
|
||||
String msg = event.getMessage();
|
||||
if (msg.toLowerCase().startsWith("goal")) {
|
||||
event.cancel();
|
||||
String[] params = msg.toLowerCase().substring(4).trim().split(" ");
|
||||
if (params[0].equals("")) {
|
||||
params = new String[]{};
|
||||
}
|
||||
Goal goal;
|
||||
try {
|
||||
switch (params.length) {
|
||||
case 0:
|
||||
goal = new GoalBlock(playerFeet());
|
||||
break;
|
||||
case 1:
|
||||
if (params[0].equals("clear") || params[0].equals("none")) {
|
||||
goal = null;
|
||||
} else {
|
||||
goal = new GoalYLevel(Integer.parseInt(params[0]));
|
||||
}
|
||||
break;
|
||||
case 2:
|
||||
goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
|
||||
break;
|
||||
case 3:
|
||||
goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
|
||||
break;
|
||||
default:
|
||||
displayChatMessageRaw("unable to understand lol");
|
||||
return;
|
||||
}
|
||||
} catch (NumberFormatException ex) {
|
||||
displayChatMessageRaw("unable to parse integer " + ex);
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
displayChatMessageRaw("Goal: " + goal);
|
||||
return;
|
||||
}
|
||||
if (msg.equals("path")) {
|
||||
PathingBehavior.INSTANCE.path();
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().equals("cancel")) {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
event.cancel();
|
||||
displayChatMessageRaw("ok canceled");
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().startsWith("thisway")) {
|
||||
Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
|
||||
PathingBehavior.INSTANCE.setGoal(goal);
|
||||
displayChatMessageRaw("Goal: " + goal);
|
||||
event.cancel();
|
||||
return;
|
||||
}
|
||||
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getByValueType(Boolean.class);
|
||||
for (Settings.Setting<Boolean> setting : toggleable) {
|
||||
if (msg.toLowerCase().equals(setting.getName().toLowerCase())) {
|
||||
setting.value ^= true;
|
||||
event.cancel();
|
||||
displayChatMessageRaw("Toggled " + setting.getName() + " to " + setting.value);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 10:18 PM
|
||||
*/
|
||||
public final class GZIPUtils {
|
||||
|
||||
private GZIPUtils() {
|
||||
}
|
||||
|
||||
public static byte[] compress(byte[] in) throws IOException {
|
||||
ByteArrayOutputStream byteStream = new ByteArrayOutputStream(in.length);
|
||||
|
||||
try (GZIPOutputStream gzipStream = new GZIPOutputStream(byteStream)) {
|
||||
gzipStream.write(in);
|
||||
}
|
||||
return byteStream.toByteArray();
|
||||
}
|
||||
|
||||
public static byte[] decompress(InputStream in) throws IOException {
|
||||
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
|
||||
|
||||
try (GZIPInputStream gzipStream = new GZIPInputStream(in)) {
|
||||
byte[] buffer = new byte[1024];
|
||||
int len;
|
||||
while ((len = gzipStream.read(buffer)) > 0) {
|
||||
outStream.write(buffer, 0, len);
|
||||
}
|
||||
}
|
||||
return outStream.toByteArray();
|
||||
}
|
||||
}
|
||||
@@ -1,148 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemAir;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemTool;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* A cached list of the best tools on the hotbar for any block
|
||||
*
|
||||
* @author avecowa
|
||||
*/
|
||||
public class ToolSet implements Helper {
|
||||
|
||||
/**
|
||||
* A list of tools on the hotbar that should be considered.
|
||||
* Note that if there are no tools on the hotbar this list will still have one (null) entry.
|
||||
*/
|
||||
private List<ItemTool> tools;
|
||||
|
||||
/**
|
||||
* A mapping from the tools array to what hotbar slots the tool is actually in.
|
||||
* tools.get(i) will be on your hotbar in slot slots.get(i)
|
||||
*/
|
||||
private List<Byte> slots;
|
||||
|
||||
/**
|
||||
* A mapping from a block to which tool index is best for it.
|
||||
* The values in this map are *not* hotbar slots indexes, they need to be looked up in slots
|
||||
* in order to be converted into hotbar slots.
|
||||
*/
|
||||
private Map<Block, Byte> cache = new HashMap<>();
|
||||
|
||||
/**
|
||||
* Create a toolset from the current player's inventory (but don't calculate any hardness values just yet)
|
||||
*/
|
||||
public ToolSet() {
|
||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
tools = new ArrayList<>();
|
||||
slots = new ArrayList<>();
|
||||
boolean fnull = false;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
if (!fnull || ((!(inv.get(i).getItem() instanceof ItemAir)) && inv.get(i).getItem() instanceof ItemTool)) {
|
||||
tools.add(inv.get(i).getItem() instanceof ItemTool ? (ItemTool) inv.get(i).getItem() : null);
|
||||
slots.add(i);
|
||||
fnull |= (inv.get(i).getItem() instanceof ItemAir) || (!inv.get(i).getItem().isDamageable());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A caching wrapper around getBestToolIndex
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @return get which tool on the hotbar is best for mining it
|
||||
*/
|
||||
public Item getBestTool(IBlockState state) {
|
||||
return tools.get(cache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Calculate which tool on the hotbar is best for mining
|
||||
*
|
||||
* @param b the blockstate to be mined
|
||||
* @return a byte indicating the index in the tools array that worked best
|
||||
*/
|
||||
private byte getBestToolIndex(IBlockState b) {
|
||||
byte best = 0;
|
||||
float value = -1;
|
||||
for (byte i = 0; i < tools.size(); i++) {
|
||||
Item item = tools.get(i);
|
||||
if (item == null)
|
||||
continue;
|
||||
|
||||
float v = item.getDestroySpeed(new ItemStack(item), b);
|
||||
if (v > value || value == -1) {
|
||||
value = v;
|
||||
best = i;
|
||||
}
|
||||
}
|
||||
return best;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get which hotbar slot should be selected for fastest mining
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @return a byte indicating which hotbar slot worked best
|
||||
*/
|
||||
public byte getBestSlot(IBlockState state) {
|
||||
return slots.get(cache.computeIfAbsent(state.getBlock(), block -> getBestToolIndex(state)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Using the best tool on the hotbar, how long would it take to mine this block
|
||||
*
|
||||
* @param state the blockstate to be mined
|
||||
* @param pos the blockpos to be mined
|
||||
* @return how long it would take in ticks
|
||||
*/
|
||||
public double getStrVsBlock(IBlockState state, BlockPos pos) {
|
||||
// Calculate the slot with the best item
|
||||
byte slot = this.getBestSlot(state);
|
||||
|
||||
// Save the old current slot
|
||||
int oldSlot = player().inventory.currentItem;
|
||||
|
||||
// Set the best slot
|
||||
player().inventory.currentItem = slot;
|
||||
|
||||
// Calculate the relative hardness of the block to the player
|
||||
float hardness = state.getPlayerRelativeBlockHardness(player(), world(), pos);
|
||||
|
||||
// Restore the old slot
|
||||
player().inventory.currentItem = oldSlot;
|
||||
|
||||
return hardness;
|
||||
}
|
||||
}
|
||||
@@ -1,118 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.utils.pathing;
|
||||
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
/**
|
||||
* A better BlockPos that has fewer hash collisions (and slightly more performant offsets)
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class BetterBlockPos extends BlockPos {
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
private final int hashCode;
|
||||
|
||||
public BetterBlockPos(int x, int y, int z) {
|
||||
super(x, y, z);
|
||||
this.x = x;
|
||||
this.y = y;
|
||||
this.z = z;
|
||||
/*
|
||||
* This is the hashcode implementation of Vec3i, the superclass of BlockPos
|
||||
*
|
||||
* public int hashCode() {
|
||||
* return (this.getY() + this.getZ() * 31) * 31 + this.getX();
|
||||
* }
|
||||
*
|
||||
* That is terrible and has tons of collisions and makes the HashMap terribly inefficient.
|
||||
*
|
||||
* That's why we grab out the X, Y, Z and calculate our own hashcode
|
||||
*/
|
||||
int hash = 3241;
|
||||
hash = 3457689 * hash + x;
|
||||
hash = 8734625 * hash + y;
|
||||
hash = 2873465 * hash + z;
|
||||
this.hashCode = hash;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return hashCode;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (o instanceof BetterBlockPos) {
|
||||
BetterBlockPos oth = (BetterBlockPos) o;
|
||||
if (oth.hashCode != hashCode) {
|
||||
return false;
|
||||
}
|
||||
return oth.x == x && oth.y == y && oth.z == z;
|
||||
}
|
||||
// during path execution, like "if (whereShouldIBe.equals(whereAmI)) {"
|
||||
// sometimes we compare a BlockPos to a BetterBlockPos
|
||||
BlockPos oth = (BlockPos) o;
|
||||
return oth.getX() == x && oth.getY() == y && oth.getZ() == z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos up() {
|
||||
// this is unimaginably faster than blockpos.up
|
||||
// that literally calls
|
||||
// this.up(1)
|
||||
// which calls this.offset(EnumFacing.UP, 1)
|
||||
// which does return n == 0 ? this : new BlockPos(this.getX() + facing.getXOffset() * n, this.getY() + facing.getYOffset() * n, this.getZ() + facing.getZOffset() * n);
|
||||
|
||||
// how many function calls is that? up(), up(int), offset(EnumFacing, int), new BlockPos, getX, getXOffset, getY, getYOffset, getZ, getZOffset
|
||||
// that's ten.
|
||||
// this is one function call.
|
||||
return new BetterBlockPos(x, y + 1, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos up(int amt) {
|
||||
// see comment in up()
|
||||
return amt == 0 ? this : new BetterBlockPos(x, y + amt, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos down() {
|
||||
// see comment in up()
|
||||
return new BetterBlockPos(x, y - 1, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos down(int amt) {
|
||||
// see comment in up()
|
||||
return new BetterBlockPos(x, y - amt, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public BlockPos offset(EnumFacing dir) {
|
||||
Vec3i vec = dir.getDirectionVec();
|
||||
return new BetterBlockPos(x + vec.getX(), y + vec.getY(), z + vec.getZ());
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,206 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:04 AM
|
||||
*/
|
||||
public final class CachedChunk implements IBlockTypeAccess {
|
||||
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(new HashSet<Block>() {{
|
||||
add(Blocks.DIAMOND_ORE);
|
||||
add(Blocks.DIAMOND_BLOCK);
|
||||
//add(Blocks.COAL_ORE);
|
||||
add(Blocks.COAL_BLOCK);
|
||||
//add(Blocks.IRON_ORE);
|
||||
add(Blocks.IRON_BLOCK);
|
||||
//add(Blocks.GOLD_ORE);
|
||||
add(Blocks.GOLD_BLOCK);
|
||||
add(Blocks.EMERALD_ORE);
|
||||
add(Blocks.EMERALD_BLOCK);
|
||||
|
||||
add(Blocks.ENDER_CHEST);
|
||||
add(Blocks.FURNACE);
|
||||
add(Blocks.CHEST);
|
||||
add(Blocks.END_PORTAL);
|
||||
add(Blocks.END_PORTAL_FRAME);
|
||||
add(Blocks.MOB_SPAWNER);
|
||||
// TODO add all shulker colors
|
||||
add(Blocks.PORTAL);
|
||||
add(Blocks.HOPPER);
|
||||
add(Blocks.BEACON);
|
||||
add(Blocks.BREWING_STAND);
|
||||
add(Blocks.SKULL);
|
||||
add(Blocks.ENCHANTING_TABLE);
|
||||
add(Blocks.ANVIL);
|
||||
add(Blocks.LIT_FURNACE);
|
||||
add(Blocks.BED);
|
||||
add(Blocks.DRAGON_EGG);
|
||||
add(Blocks.JUKEBOX);
|
||||
add(Blocks.END_GATEWAY);
|
||||
}});
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
* <p>
|
||||
* Chunks are 16x16x256, each block requires 2 bits.
|
||||
*/
|
||||
public static final int SIZE = 2 * 16 * 16 * 256;
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bytes. Equal to 16 KiB.
|
||||
*/
|
||||
public static final int SIZE_IN_BYTES = SIZE / 8;
|
||||
|
||||
/**
|
||||
* The chunk x coordinate
|
||||
*/
|
||||
public final int x;
|
||||
|
||||
/**
|
||||
* The chunk z coordinate
|
||||
*/
|
||||
public final int z;
|
||||
|
||||
/**
|
||||
* The actual raw data of this packed chunk.
|
||||
* <p>
|
||||
* Each block is expressed as 2 bits giving a total of 16 KiB
|
||||
*/
|
||||
private final BitSet data;
|
||||
|
||||
/**
|
||||
* The block names of each surface level block for generating an overview
|
||||
*/
|
||||
private final String[] overview;
|
||||
|
||||
private final int[] heightMap;
|
||||
|
||||
private final Map<String, List<BlockPos>> specialBlockLocations;
|
||||
|
||||
CachedChunk(int x, int z, BitSet data, String[] overview, Map<String, List<BlockPos>> specialBlockLocations) {
|
||||
validateSize(data);
|
||||
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.data = data;
|
||||
this.overview = overview;
|
||||
this.heightMap = new int[256];
|
||||
this.specialBlockLocations = specialBlockLocations;
|
||||
calculateHeightMap();
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
int internalPos = z << 4 | x;
|
||||
if (heightMap[internalPos] == y) {
|
||||
// we have this exact block, it's a surface block
|
||||
IBlockState state = ChunkPacker.stringToBlock(overview[internalPos]).getDefaultState();
|
||||
/*System.out.println("Saying that " + x + "," + y + "," + z + " is " + state);
|
||||
if (!Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) {
|
||||
throw new IllegalStateException("failed " + Minecraft.getMinecraft().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16));
|
||||
}*/
|
||||
return state;
|
||||
}
|
||||
PathingBlockType type = getType(x, y, z);
|
||||
return ChunkPacker.pathingTypeToBlock(type);
|
||||
}
|
||||
|
||||
private PathingBlockType getType(int x, int y, int z) {
|
||||
int index = getPositionIndex(x, y, z);
|
||||
return PathingBlockType.fromBits(data.get(index), data.get(index + 1));
|
||||
}
|
||||
|
||||
private void calculateHeightMap() {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = z << 4 | x;
|
||||
heightMap[index] = 0;
|
||||
for (int y = 256; y >= 0; y--) {
|
||||
int i = getPositionIndex(x, y, z);
|
||||
if (data.get(i) || data.get(i + 1)) {
|
||||
heightMap[index] = y;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public final String[] getOverview() {
|
||||
return overview;
|
||||
}
|
||||
|
||||
public final Map<String, List<BlockPos>> getRelativeBlocks() {
|
||||
return specialBlockLocations;
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getAbsoluteBlocks(String blockType) {
|
||||
if (specialBlockLocations.get(blockType) == null) {
|
||||
return null;
|
||||
}
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
for (BlockPos pos : specialBlockLocations.get(blockType)) {
|
||||
res.add(new BlockPos(pos.getX() + x * 16, pos.getY(), pos.getZ() + z * 16));
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return Returns the raw packed chunk data as a byte array
|
||||
*/
|
||||
public final byte[] toByteArray() {
|
||||
return this.data.toByteArray();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the raw bit index of the specified position
|
||||
*
|
||||
* @param x The x position
|
||||
* @param y The y position
|
||||
* @param z The z position
|
||||
* @return The bit index
|
||||
*/
|
||||
public static int getPositionIndex(int x, int y, int z) {
|
||||
return (x << 1) | (z << 5) | (y << 9);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates the size of an input {@link BitSet} containing the raw
|
||||
* packed chunk data. Sizes that exceed {@link CachedChunk#SIZE} are
|
||||
* considered invalid, and thus, an exception will be thrown.
|
||||
*
|
||||
* @param data The raw data
|
||||
* @throws IllegalArgumentException if the bitset size exceeds the maximum size
|
||||
*/
|
||||
private static void validateSize(BitSet data) {
|
||||
if (data.size() > SIZE) {
|
||||
throw new IllegalArgumentException("BitSet of invalid length provided");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,297 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.*;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.GZIPOutputStream;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 9:35 PM
|
||||
*/
|
||||
public final class CachedRegion implements IBlockTypeAccess {
|
||||
private static final byte CHUNK_NOT_PRESENT = 0;
|
||||
private static final byte CHUNK_PRESENT = 1;
|
||||
|
||||
/**
|
||||
* Magic value to detect invalid cache files, or incompatible cache files saved in an old version of Baritone
|
||||
*/
|
||||
private static final int CACHED_REGION_MAGIC = 456022910;
|
||||
|
||||
/**
|
||||
* All of the chunks in this region: A 32x32 array of them.
|
||||
*/
|
||||
private final CachedChunk[][] chunks = new CachedChunk[32][32];
|
||||
|
||||
/**
|
||||
* The region x coordinate
|
||||
*/
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The region z coordinate
|
||||
*/
|
||||
private final int z;
|
||||
|
||||
/**
|
||||
* Has this region been modified since its most recent load or save
|
||||
*/
|
||||
private boolean hasUnsavedChanges;
|
||||
|
||||
CachedRegion(int x, int z) {
|
||||
this.x = x;
|
||||
this.z = z;
|
||||
this.hasUnsavedChanges = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
CachedChunk chunk = chunks[x >> 4][z >> 4];
|
||||
if (chunk != null) {
|
||||
return chunk.getBlock(x & 15, y, z & 15);
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
public final boolean isCached(int x, int z) {
|
||||
return chunks[x >> 4][z >> 4] != null;
|
||||
}
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
for (int chunkX = 0; chunkX < 32; chunkX++) {
|
||||
for (int chunkZ = 0; chunkZ < 32; chunkZ++) {
|
||||
if (chunks[chunkX][chunkZ] == null) {
|
||||
continue;
|
||||
}
|
||||
List<BlockPos> locs = chunks[chunkX][chunkZ].getAbsoluteBlocks(block);
|
||||
if (locs == null) {
|
||||
continue;
|
||||
}
|
||||
for (BlockPos pos : locs) {
|
||||
res.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
final synchronized void updateCachedChunk(int chunkX, int chunkZ, CachedChunk chunk) {
|
||||
this.chunks[chunkX][chunkZ] = chunk;
|
||||
hasUnsavedChanges = true;
|
||||
}
|
||||
|
||||
|
||||
public synchronized final void save(String directory) {
|
||||
if (!hasUnsavedChanges) {
|
||||
return;
|
||||
}
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path)) {
|
||||
Files.createDirectories(path);
|
||||
|
||||
}
|
||||
System.out.println("Saving region " + x + "," + z + " to disk " + path);
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile)) {
|
||||
Files.createFile(regionFile);
|
||||
}
|
||||
try (
|
||||
FileOutputStream fileOut = new FileOutputStream(regionFile.toFile());
|
||||
GZIPOutputStream gzipOut = new GZIPOutputStream(fileOut, 16384);
|
||||
DataOutputStream out = new DataOutputStream(gzipOut)
|
||||
) {
|
||||
out.writeInt(CACHED_REGION_MAGIC);
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
CachedChunk chunk = this.chunks[x][z];
|
||||
if (chunk == null) {
|
||||
out.write(CHUNK_NOT_PRESENT);
|
||||
} else {
|
||||
out.write(CHUNK_PRESENT);
|
||||
byte[] chunkBytes = chunk.toByteArray();
|
||||
out.write(chunkBytes);
|
||||
// Messy, but fills the empty 0s that should be trailing to fill up the space.
|
||||
out.write(new byte[CachedChunk.SIZE_IN_BYTES - chunkBytes.length]);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (chunks[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
out.writeUTF(chunks[x][z].getOverview()[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (chunks[x][z] != null) {
|
||||
Map<String, List<BlockPos>> locs = chunks[x][z].getRelativeBlocks();
|
||||
out.writeShort(locs.entrySet().size());
|
||||
for (Map.Entry<String, List<BlockPos>> entry : locs.entrySet()) {
|
||||
out.writeUTF(entry.getKey());
|
||||
out.writeShort(entry.getValue().size());
|
||||
for (BlockPos pos : entry.getValue()) {
|
||||
out.writeByte((byte) (pos.getZ() << 4 | pos.getX()));
|
||||
out.writeByte((byte) (pos.getY()));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
System.out.println("Saved region successfully");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void load(String directory) {
|
||||
try {
|
||||
Path path = Paths.get(directory);
|
||||
if (!Files.exists(path)) {
|
||||
Files.createDirectories(path);
|
||||
}
|
||||
|
||||
Path regionFile = getRegionFile(path, this.x, this.z);
|
||||
if (!Files.exists(regionFile)) {
|
||||
return;
|
||||
}
|
||||
|
||||
System.out.println("Loading region " + x + "," + z + " from disk " + path);
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
|
||||
try (
|
||||
FileInputStream fileIn = new FileInputStream(regionFile.toFile());
|
||||
GZIPInputStream gzipIn = new GZIPInputStream(fileIn, 32768);
|
||||
DataInputStream in = new DataInputStream(gzipIn)
|
||||
) {
|
||||
int magic = in.readInt();
|
||||
if (magic != CACHED_REGION_MAGIC) {
|
||||
// in the future, if we change the format on disk
|
||||
// we can keep converters for the old format
|
||||
// by switching on the magic value, and either loading it normally, or loading through a converter.
|
||||
throw new IOException("Bad magic value " + magic);
|
||||
}
|
||||
CachedChunk[][] tmpCached = new CachedChunk[32][32];
|
||||
Map<String, List<BlockPos>>[][] location = new Map[32][32];
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
int isChunkPresent = in.read();
|
||||
switch (isChunkPresent) {
|
||||
case CHUNK_PRESENT:
|
||||
byte[] bytes = new byte[CachedChunk.SIZE_IN_BYTES];
|
||||
in.readFully(bytes);
|
||||
location[x][z] = new HashMap<>();
|
||||
int regionX = this.x;
|
||||
int regionZ = this.z;
|
||||
int chunkX = x + 32 * regionX;
|
||||
int chunkZ = z + 32 * regionZ;
|
||||
tmpCached[x][z] = new CachedChunk(chunkX, chunkZ, BitSet.valueOf(bytes), new String[256], location[x][z]);
|
||||
break;
|
||||
case CHUNK_NOT_PRESENT:
|
||||
tmpCached[x][z] = null;
|
||||
break;
|
||||
default:
|
||||
throw new IOException("Malformed stream");
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
tmpCached[x][z].getOverview()[i] = in.readUTF();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (int z = 0; z < 32; z++) {
|
||||
for (int x = 0; x < 32; x++) {
|
||||
if (tmpCached[x][z] != null) {
|
||||
// 16 * 16 * 256 = 65536 so a short is enough
|
||||
// ^ haha jokes on leijurv, java doesn't have unsigned types so that isn't correct
|
||||
// also why would you have more than 32767 special blocks in a chunk
|
||||
// haha double jokes on you now it works for 65535 not just 32767
|
||||
int numSpecialBlockTypes = in.readShort() & 0xffff;
|
||||
for (int i = 0; i < numSpecialBlockTypes; i++) {
|
||||
String blockName = in.readUTF();
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
location[x][z].put(blockName, locs);
|
||||
int numLocations = in.readShort() & 0xffff;
|
||||
if (numLocations == 0) {
|
||||
// an entire chunk full of air can happen in the end
|
||||
numLocations = 65536;
|
||||
}
|
||||
for (int j = 0; j < numLocations; j++) {
|
||||
byte xz = in.readByte();
|
||||
int X = xz & 0x0f;
|
||||
int Z = (xz >>> 4) & 0x0f;
|
||||
int Y = in.readByte() & 0xff;
|
||||
locs.add(new BlockPos(X, Y, Z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
// only if the entire file was uncorrupted do we actually set the chunks
|
||||
for (int x = 0; x < 32; x++) {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
this.chunks[x][z] = tmpCached[x][z];
|
||||
}
|
||||
}
|
||||
}
|
||||
hasUnsavedChanges = false;
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
System.out.println("Loaded region successfully in " + (end - start) + "ms");
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region x coordinate
|
||||
*/
|
||||
public final int getX() {
|
||||
return this.x;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return The region z coordinate
|
||||
*/
|
||||
public final int getZ() {
|
||||
return this.z;
|
||||
}
|
||||
|
||||
private static Path getRegionFile(Path cacheDir, int regionX, int regionZ) {
|
||||
return Paths.get(cacheDir.toString(), "r." + regionX + "." + regionZ + ".bcr");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,255 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.pathing.IBlockTypeAccess;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.LinkedBlockingQueue;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 12:02 AM
|
||||
*/
|
||||
public final class CachedWorld implements IBlockTypeAccess {
|
||||
|
||||
/**
|
||||
* The maximum number of regions in any direction from (0,0)
|
||||
*/
|
||||
private static final int REGION_MAX = 58594;
|
||||
|
||||
/**
|
||||
* A map of all of the cached regions.
|
||||
*/
|
||||
private Long2ObjectMap<CachedRegion> cachedRegions = new Long2ObjectOpenHashMap<>();
|
||||
|
||||
/**
|
||||
* The directory that the cached region files are saved to
|
||||
*/
|
||||
private final String directory;
|
||||
|
||||
private final LinkedBlockingQueue<Chunk> toPack = new LinkedBlockingQueue<>();
|
||||
|
||||
CachedWorld(Path directory) {
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
} catch (IOException ignored) {
|
||||
}
|
||||
}
|
||||
this.directory = directory.toString();
|
||||
System.out.println("Cached world directory: " + directory);
|
||||
// Insert an invalid region element
|
||||
cachedRegions.put(0, null);
|
||||
new PackerThread().start();
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(30000);
|
||||
while (true) {
|
||||
// since a region only saves if it's been modified since its last save
|
||||
// saving every 10 minutes means that once it's time to exit
|
||||
// we'll only have a couple regions to save
|
||||
save();
|
||||
Thread.sleep(600000);
|
||||
}
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public final void queueForPacking(Chunk chunk) {
|
||||
try {
|
||||
toPack.put(chunk);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final IBlockState getBlock(int x, int y, int z) {
|
||||
// no point in doing getOrCreate region, if we don't have it we don't have it
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region == null) {
|
||||
return null;
|
||||
}
|
||||
return region.getBlock(x & 511, y, z & 511);
|
||||
}
|
||||
|
||||
public final boolean isCached(BlockPos pos) {
|
||||
int x = pos.getX();
|
||||
int z = pos.getZ();
|
||||
CachedRegion region = getRegion(x >> 9, z >> 9);
|
||||
if (region == null) {
|
||||
return false;
|
||||
}
|
||||
return region.isCached(x & 511, z & 511);
|
||||
}
|
||||
|
||||
|
||||
public final LinkedList<BlockPos> getLocationsOf(String block, int minimum, int maxRegionDistanceSq) {
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
int playerRegionX = playerFeet().getX() >> 9;
|
||||
int playerRegionZ = playerFeet().getZ() >> 9;
|
||||
|
||||
int searchRadius = 0;
|
||||
while (searchRadius <= maxRegionDistanceSq) {
|
||||
for (int xoff = -searchRadius; xoff <= searchRadius; xoff++) {
|
||||
for (int zoff = -searchRadius; zoff <= searchRadius; zoff++) {
|
||||
int distance = xoff * xoff + zoff * zoff;
|
||||
if (distance != searchRadius) {
|
||||
continue;
|
||||
}
|
||||
int regionX = xoff + playerRegionX;
|
||||
int regionZ = zoff + playerRegionZ;
|
||||
CachedRegion region = getOrCreateRegion(regionX, regionZ);
|
||||
if (region != null) {
|
||||
for (BlockPos pos : region.getLocationsOf(block)) {
|
||||
res.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (res.size() >= minimum) {
|
||||
return res;
|
||||
}
|
||||
searchRadius++;
|
||||
}
|
||||
return res;
|
||||
}
|
||||
|
||||
private void updateCachedChunk(CachedChunk chunk) {
|
||||
CachedRegion region = getOrCreateRegion(chunk.x >> 5, chunk.z >> 5);
|
||||
region.updateCachedChunk(chunk.x & 31, chunk.z & 31, chunk);
|
||||
}
|
||||
|
||||
public final void save() {
|
||||
if (!Baritone.settings().chunkCaching.get()) {
|
||||
System.out.println("Not saving to disk; chunk caching is disabled.");
|
||||
return;
|
||||
}
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
allRegions().parallelStream().forEach(region -> {
|
||||
if (region != null) {
|
||||
region.save(this.directory);
|
||||
}
|
||||
});
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
System.out.println("World save took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
private synchronized List<CachedRegion> allRegions() {
|
||||
return new ArrayList<>(this.cachedRegions.values());
|
||||
}
|
||||
|
||||
public final void reloadAllFromDisk() {
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
allRegions().forEach(region -> {
|
||||
if (region != null) {
|
||||
region.load(this.directory);
|
||||
}
|
||||
});
|
||||
long now = System.nanoTime() / 1000000L;
|
||||
System.out.println("World load took " + (now - start) + "ms");
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
public final synchronized CachedRegion getRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.get(getRegionID(regionX, regionZ));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region at the specified region coordinates. If a
|
||||
* region is not found, then a new one is created.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region located at the specified coordinates
|
||||
*/
|
||||
private synchronized CachedRegion getOrCreateRegion(int regionX, int regionZ) {
|
||||
return cachedRegions.computeIfAbsent(getRegionID(regionX, regionZ), id -> {
|
||||
CachedRegion newRegion = new CachedRegion(regionX, regionZ);
|
||||
newRegion.load(this.directory);
|
||||
return newRegion;
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the region ID based on the region coordinates. 0 will be
|
||||
* returned if the specified region coordinates are out of bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return The region ID
|
||||
*/
|
||||
private long getRegionID(int regionX, int regionZ) {
|
||||
if (!isRegionInWorld(regionX, regionZ)) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (long) regionX & 0xFFFFFFFFL | ((long) regionZ & 0xFFFFFFFFL) << 32;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns whether or not the specified region coordinates is within the world bounds.
|
||||
*
|
||||
* @param regionX The region X coordinate
|
||||
* @param regionZ The region Z coordinate
|
||||
* @return Whether or not the region is in world bounds
|
||||
*/
|
||||
private boolean isRegionInWorld(int regionX, int regionZ) {
|
||||
return regionX <= REGION_MAX && regionX >= -REGION_MAX && regionZ <= REGION_MAX && regionZ >= -REGION_MAX;
|
||||
}
|
||||
|
||||
private class PackerThread extends Thread {
|
||||
public void run() {
|
||||
while (true) {
|
||||
LinkedBlockingQueue<Chunk> queue = toPack;
|
||||
if (queue == null) {
|
||||
break;
|
||||
}
|
||||
try {
|
||||
Chunk chunk = queue.take();
|
||||
CachedChunk cached = ChunkPacker.pack(chunk);
|
||||
CachedWorld.this.updateCachedChunk(cached);
|
||||
//System.out.println("Processed chunk at " + chunk.x + "," + chunk.z);
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,195 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockDoublePlant;
|
||||
import net.minecraft.block.BlockFlower;
|
||||
import net.minecraft.block.BlockTallGrass;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/3/2018 1:09 AM
|
||||
*/
|
||||
public final class ChunkPacker implements Helper {
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
private static BitSet originalPacker(Chunk chunk) {
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
for (int y = 0; y < 256; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
IBlockState state = chunk.getBlockState(x, y, z);
|
||||
boolean[] bits = getPathingBlockType(state).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
return bitSet;
|
||||
}
|
||||
|
||||
public static CachedChunk pack(Chunk chunk) {
|
||||
long start = System.nanoTime() / 1000000L;
|
||||
|
||||
Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
for (int y0 = 0; y0 < 16; y0++) {
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
if (extendedblockstorage == null) {
|
||||
// any 16x16x16 area that's all air will have null storage
|
||||
// for example, in an ocean biome, with air from y=64 to y=256
|
||||
// the first 4 extended blocks storages will be full
|
||||
// and the remaining 12 will be null
|
||||
|
||||
// since the index into the bitset is calculated from the x y and z
|
||||
// and doesn't function as an append, we can entirely skip the scanning
|
||||
// since a bitset is initialized to all zero, and air is saved as zeros
|
||||
continue;
|
||||
}
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
int yReal = y0 << 4;
|
||||
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
|
||||
// for better cache locality, iterate in that order
|
||||
for (int y1 = 0; y1 < 16; y1++) {
|
||||
int y = y1 | yReal;
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
IBlockState state = bsc.get(x, y1, z);
|
||||
boolean[] bits = getPathingBlockType(state).getBits();
|
||||
bitSet.set(index, bits[0]);
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
Block block = state.getBlock();
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
|
||||
String name = blockToString(block);
|
||||
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
/*if (!bitSet.equals(originalPacker(chunk))) {
|
||||
throw new IllegalStateException();
|
||||
}*/
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
//System.out.println("Packed special blocks: " + specialBlocks);
|
||||
long end = System.nanoTime() / 1000000L;
|
||||
//System.out.println("Chunk packing took " + (end - start) + "ms for " + chunk.x + "," + chunk.z);
|
||||
String[] blockNames = new String[256];
|
||||
for (int z = 0; z < 16; z++) {
|
||||
outerLoop:
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 255; y >= 0; y--) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
if (bitSet.get(index) || bitSet.get(index + 1)) {
|
||||
String name = blockToString(chunk.getBlockState(x, y, z).getBlock());
|
||||
blockNames[z << 4 | x] = name;
|
||||
continue outerLoop;
|
||||
}
|
||||
}
|
||||
blockNames[z << 4 | x] = "air";
|
||||
}
|
||||
}
|
||||
CachedChunk cached = new CachedChunk(chunk.x, chunk.z, bitSet, blockNames, specialBlocks);
|
||||
return cached;
|
||||
}
|
||||
|
||||
public static String blockToString(Block block) {
|
||||
ResourceLocation loc = Block.REGISTRY.getNameForObject(block);
|
||||
String name = loc.getPath(); // normally, only write the part after the minecraft:
|
||||
if (!loc.getNamespace().equals("minecraft")) {
|
||||
// Baritone is running on top of forge with mods installed, perhaps?
|
||||
name = loc.toString(); // include the namespace with the colon
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
public static Block stringToBlock(String name) {
|
||||
if (!name.contains(":")) {
|
||||
name = "minecraft:" + name;
|
||||
}
|
||||
return Block.getBlockFromName(name);
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block.equals(Blocks.WATER)) {
|
||||
// only water source blocks are plausibly usable, flowing water should be avoid
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block) || block.equals(Blocks.FLOWING_WATER) || MovementHelper.isBottomSlab(state)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
// We used to do an AABB check here
|
||||
// however, this failed in the nether when you were near a nether fortress
|
||||
// because fences check their adjacent blocks in the world for their fence connection status to determine AABB shape
|
||||
// this caused a nullpointerexception when we saved chunks on unload, because they were unable to check their neighbors
|
||||
if (block == Blocks.AIR || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
return PathingBlockType.SOLID;
|
||||
}
|
||||
|
||||
static IBlockState pathingTypeToBlock(PathingBlockType type) {
|
||||
if (type != null) {
|
||||
switch (type) {
|
||||
case AIR:
|
||||
return Blocks.AIR.getDefaultState();
|
||||
case WATER:
|
||||
return Blocks.WATER.getDefaultState();
|
||||
case AVOID:
|
||||
return Blocks.LAVA.getDefaultState();
|
||||
case SOLID:
|
||||
// Dimension solid types
|
||||
switch (mc.player.dimension) {
|
||||
case -1:
|
||||
return Blocks.NETHERRACK.getDefaultState();
|
||||
case 0:
|
||||
return Blocks.STONE.getDefaultState();
|
||||
case 1:
|
||||
return Blocks.END_STONE.getDefaultState();
|
||||
}
|
||||
|
||||
// The fallback solid type
|
||||
return Blocks.STONE.getDefaultState();
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,92 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import com.google.common.collect.ImmutableList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import org.apache.commons.lang3.ArrayUtils;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* A single waypoint
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Waypoint {
|
||||
|
||||
public final String name;
|
||||
public final Tag tag;
|
||||
private final long creationTimestamp;
|
||||
public final BlockPos location;
|
||||
|
||||
public Waypoint(String name, Tag tag, BlockPos location) {
|
||||
this(name, tag, location, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) { // read from disk
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.location = location;
|
||||
this.creationTimestamp = creationTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object o) {
|
||||
if (o == null) {
|
||||
return false;
|
||||
}
|
||||
if (!(o instanceof Waypoint)) {
|
||||
return false;
|
||||
}
|
||||
Waypoint w = (Waypoint) o;
|
||||
return name.equals(w.name) && tag == w.tag && location.equals(w.location);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
return name.hashCode() + tag.hashCode() + location.hashCode(); //lol
|
||||
}
|
||||
|
||||
public long creationTimestamp() {
|
||||
return creationTimestamp;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return name + " " + location.toString() + " " + new Date(creationTimestamp).toString();
|
||||
}
|
||||
|
||||
public enum Tag {
|
||||
HOME("home", "base"),
|
||||
DEATH("death"),
|
||||
BED("bed", "spawn"),
|
||||
USER();
|
||||
|
||||
private static final List<Tag> TAG_LIST = ImmutableList.<Tag>builder().add(Tag.values()).build();
|
||||
|
||||
private final String[] names;
|
||||
|
||||
Tag(String... names) {
|
||||
this.names = names;
|
||||
}
|
||||
|
||||
public static Tag fromString(String name) {
|
||||
return TAG_LIST.stream().filter(tag -> ArrayUtils.contains(tag.names, name.toLowerCase())).findFirst().orElse(null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,125 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.*;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* Waypoints for a world
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class Waypoints {
|
||||
|
||||
/**
|
||||
* Magic value to detect invalid waypoint files
|
||||
*/
|
||||
private static final long WAYPOINT_MAGIC_VALUE = 121977993584L; // good value
|
||||
|
||||
private final Path directory;
|
||||
private final Map<Waypoint.Tag, Set<Waypoint>> waypoints;
|
||||
|
||||
Waypoints(Path directory) {
|
||||
this.directory = directory;
|
||||
if (!Files.exists(directory)) {
|
||||
try {
|
||||
Files.createDirectories(directory);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
System.out.println("Would save waypoints to " + directory);
|
||||
this.waypoints = new HashMap<>();
|
||||
load();
|
||||
}
|
||||
|
||||
private void load() {
|
||||
for (Waypoint.Tag tag : Waypoint.Tag.values()) {
|
||||
load(tag);
|
||||
}
|
||||
}
|
||||
|
||||
private synchronized void load(Waypoint.Tag tag) {
|
||||
waypoints.put(tag, new HashSet<>());
|
||||
|
||||
Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4");
|
||||
if (!Files.exists(fileName)) {
|
||||
return;
|
||||
}
|
||||
|
||||
try (
|
||||
FileInputStream fileIn = new FileInputStream(fileName.toFile());
|
||||
BufferedInputStream bufIn = new BufferedInputStream(fileIn);
|
||||
DataInputStream in = new DataInputStream(bufIn)
|
||||
) {
|
||||
long magic = in.readLong();
|
||||
if (magic != WAYPOINT_MAGIC_VALUE) {
|
||||
throw new IOException("Bad magic value " + magic);
|
||||
}
|
||||
|
||||
long length = in.readLong(); // Yes I want 9,223,372,036,854,775,807 waypoints, do you not?
|
||||
while (length-- > 0) {
|
||||
String name = in.readUTF();
|
||||
long creationTimestamp = in.readLong();
|
||||
int x = in.readInt();
|
||||
int y = in.readInt();
|
||||
int z = in.readInt();
|
||||
waypoints.get(tag).add(new Waypoint(name, tag, new BlockPos(x, y, z), creationTimestamp));
|
||||
}
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
|
||||
private synchronized void save(Waypoint.Tag tag) {
|
||||
Path fileName = directory.resolve(tag.name().toLowerCase() + ".mp4");
|
||||
try (
|
||||
FileOutputStream fileOut = new FileOutputStream(fileName.toFile());
|
||||
BufferedOutputStream bufOut = new BufferedOutputStream(fileOut);
|
||||
DataOutputStream out = new DataOutputStream(bufOut)
|
||||
) {
|
||||
out.writeLong(WAYPOINT_MAGIC_VALUE);
|
||||
out.writeLong(waypoints.get(tag).size());
|
||||
for (Waypoint waypoint : waypoints.get(tag)) {
|
||||
out.writeUTF(waypoint.name);
|
||||
out.writeLong(waypoint.creationTimestamp());
|
||||
out.writeInt(waypoint.location.getX());
|
||||
out.writeInt(waypoint.location.getY());
|
||||
out.writeInt(waypoint.location.getZ());
|
||||
}
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
public Set<Waypoint> getByTag(Waypoint.Tag tag) {
|
||||
return Collections.unmodifiableSet(waypoints.get(tag));
|
||||
}
|
||||
|
||||
public Waypoint getMostRecentByTag(Waypoint.Tag tag) {
|
||||
// Find a waypoint of the given tag which has the greatest timestamp value, indicating the most recent
|
||||
return this.waypoints.get(tag).stream().min(Comparator.comparingLong(w -> -w.creationTimestamp())).orElse(null);
|
||||
}
|
||||
|
||||
public void addWaypoint(Waypoint waypoint) {
|
||||
// no need to check for duplicate, because it's a Set not a List
|
||||
waypoints.get(waypoint.tag).add(waypoint);
|
||||
save(waypoint.tag);
|
||||
}
|
||||
}
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
/**
|
||||
* Data about a world, from baritone's point of view. Includes cached chunks, waypoints, and map data.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class WorldData {
|
||||
public final CachedWorld cache;
|
||||
public final Waypoints waypoints;
|
||||
//public final MapData map;
|
||||
public final Path directory;
|
||||
|
||||
WorldData(Path directory) {
|
||||
this.directory = directory;
|
||||
this.cache = new CachedWorld(directory.resolve("cache"));
|
||||
this.waypoints = new Waypoints(directory.resolve("waypoints"));
|
||||
}
|
||||
|
||||
void onClose() {
|
||||
new Thread() {
|
||||
public void run() {
|
||||
System.out.println("Started saving the world in a new thread");
|
||||
cache.save();
|
||||
}
|
||||
}.start();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,109 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/4/2018 11:06 AM
|
||||
*/
|
||||
public enum WorldProvider implements Helper {
|
||||
|
||||
INSTANCE;
|
||||
|
||||
private final Map<Path, WorldData> worldCache = new HashMap<>();
|
||||
|
||||
private WorldData currentWorld;
|
||||
|
||||
public final WorldData getCurrentWorld() {
|
||||
return this.currentWorld;
|
||||
}
|
||||
|
||||
public final void initWorld(WorldClient world) {
|
||||
int dimensionID = world.provider.getDimensionType().getId();
|
||||
File directory;
|
||||
File readme;
|
||||
IntegratedServer integratedServer = mc.getIntegratedServer();
|
||||
if (integratedServer != null) {
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimensionID);
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
directory = loader.getChunkSaveLocation();
|
||||
|
||||
// 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 {
|
||||
//remote
|
||||
directory = new File(Baritone.INSTANCE.getDir(), mc.getCurrentServerData().serverIP);
|
||||
readme = Baritone.INSTANCE.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) {}
|
||||
|
||||
directory = new File(directory, "DIM" + dimensionID);
|
||||
Path dir = directory.toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
} catch (IOException ignored) {}
|
||||
}
|
||||
System.out.println("Baritone world data dir: " + dir);
|
||||
this.currentWorld = this.worldCache.computeIfAbsent(dir, WorldData::new);
|
||||
}
|
||||
|
||||
public final void closeWorld() {
|
||||
WorldData world = this.currentWorld;
|
||||
this.currentWorld = null;
|
||||
if (world == null) {
|
||||
return;
|
||||
}
|
||||
world.onClose();
|
||||
}
|
||||
|
||||
public final void ifWorldLoaded(Consumer<WorldData> currentWorldConsumer) {
|
||||
if (this.currentWorld != null) {
|
||||
currentWorldConsumer.accept(this.currentWorld);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,100 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.chunk;
|
||||
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
|
||||
import java.util.LinkedList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public enum WorldScanner implements Helper {
|
||||
INSTANCE;
|
||||
|
||||
public List<BlockPos> scanLoadedChunks(List<String> blockTypes, int max) {
|
||||
List<Block> asBlocks = blockTypes.stream().map(ChunkPacker::stringToBlock).collect(Collectors.toList());
|
||||
if (asBlocks.contains(null)) {
|
||||
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blockTypes.toString());
|
||||
}
|
||||
LinkedList<BlockPos> res = new LinkedList<>();
|
||||
if (asBlocks.isEmpty()) {
|
||||
return res;
|
||||
}
|
||||
ChunkProviderClient chunkProvider = world().getChunkProvider();
|
||||
|
||||
int playerChunkX = playerFeet().getX() >> 4;
|
||||
int playerChunkZ = playerFeet().getZ() >> 4;
|
||||
|
||||
int searchRadiusSq = 0;
|
||||
while (true) {
|
||||
boolean allUnloaded = true;
|
||||
for (int xoff = -searchRadiusSq; xoff <= searchRadiusSq; xoff++) {
|
||||
for (int zoff = -searchRadiusSq; zoff <= searchRadiusSq; zoff++) {
|
||||
int distance = xoff * xoff + zoff * zoff;
|
||||
if (distance != searchRadiusSq) {
|
||||
continue;
|
||||
}
|
||||
int chunkX = xoff + playerChunkX;
|
||||
int chunkZ = zoff + playerChunkZ;
|
||||
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
||||
if (chunk == null) {
|
||||
continue;
|
||||
}
|
||||
allUnloaded = false;
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
chunkX = chunkX << 4;
|
||||
chunkZ = chunkZ << 4;
|
||||
for (int y0 = 0; y0 < 16; y0++) {
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
if (extendedblockstorage == null) {
|
||||
continue;
|
||||
}
|
||||
int yReal = y0 << 4;
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
|
||||
// for better cache locality, iterate in that order
|
||||
for (int y = 0; y < 16; y++) {
|
||||
for (int z = 0; z < 16; z++) {
|
||||
for (int x = 0; x < 16; x++) {
|
||||
IBlockState state = bsc.get(x, y, z);
|
||||
if (asBlocks.contains(state.getBlock())) {
|
||||
res.add(new BlockPos(chunkX | x, yReal | y, chunkZ | z));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (allUnloaded) {
|
||||
return res;
|
||||
}
|
||||
if (res.size() >= max && searchRadiusSq > 26) {
|
||||
return res;
|
||||
}
|
||||
searchRadiusSq++;
|
||||
}
|
||||
}
|
||||
}
|
||||
+83
-79
@@ -15,42 +15,25 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
package baritone.pathing.calc;
|
||||
|
||||
package baritone.bot.pathing.calc;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.chunk.CachedWorldProvider;
|
||||
import baritone.bot.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.bot.pathing.calc.openset.IOpenSet;
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.movement.ActionCosts;
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.movements.*;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import baritone.Baritone;
|
||||
import baritone.chunk.CachedWorld;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.pathing.path.IPath;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.HashSet;
|
||||
@@ -64,19 +47,19 @@ import java.util.Random;
|
||||
*/
|
||||
public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
|
||||
private final Optional<HashSet<BetterBlockPos>> favoredPositions;
|
||||
private final Optional<HashSet<BlockPos>> favoredPositions;
|
||||
|
||||
public AStarPathFinder(BlockPos start, Goal goal, Optional<Collection<BetterBlockPos>> favoredPositions) {
|
||||
public AStarPathFinder(BlockPos start, Goal goal, Optional<Collection<BlockPos>> favoredPositions) {
|
||||
super(start, goal);
|
||||
this.favoredPositions = favoredPositions.map(HashSet::new); // <-- okay this is epic
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Optional<IPath> calculate0() {
|
||||
protected Optional<IPath> calculate0(long timeout) {
|
||||
startNode = getNodeAtPosition(start);
|
||||
startNode.cost = 0;
|
||||
startNode.combinedCost = startNode.estimatedCostToGoal;
|
||||
IOpenSet openSet = new BinaryHeapOpenSet();
|
||||
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
|
||||
openSet.insert(startNode);
|
||||
startNode.isOpen = true;
|
||||
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
|
||||
@@ -85,19 +68,26 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
bestHeuristicSoFar[i] = Double.MAX_VALUE;
|
||||
}
|
||||
CalculationContext calcContext = new CalculationContext();
|
||||
HashSet<BetterBlockPos> favored = favoredPositions.orElse(null);
|
||||
HashSet<BlockPos> favored = favoredPositions.orElse(null);
|
||||
currentlyRunning = this;
|
||||
long startTime = System.currentTimeMillis();
|
||||
CachedWorld cachedWorld = Optional.ofNullable(WorldProvider.INSTANCE.getCurrentWorld()).map(w -> w.cache).orElse(null);
|
||||
ChunkProviderClient chunkProvider = Minecraft.getMinecraft().world.getChunkProvider();
|
||||
BlockStateInterface.clearCachedChunk();
|
||||
long startTime = System.nanoTime() / 1000000L;
|
||||
boolean slowPath = Baritone.settings().slowPath.get();
|
||||
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS : Baritone.settings().pathTimeoutMS).<Long>get();
|
||||
long lastPrintout = 0;
|
||||
if (slowPath) {
|
||||
displayChatMessageRaw("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + timeout + "ms");
|
||||
}
|
||||
long timeoutTime = startTime + (slowPath ? Baritone.settings().slowPathTimeoutMS.<Long>get() : timeout);
|
||||
//long lastPrintout = 0;
|
||||
int numNodes = 0;
|
||||
int numMovementsConsidered = 0;
|
||||
int numEmptyChunk = 0;
|
||||
boolean favoring = favoredPositions.isPresent(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
boolean cache = Baritone.settings().chuckCaching.get();
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get();
|
||||
boolean favoring = favoredPositions.isPresent();
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
double favorCoeff = Baritone.settings().backtrackCostFavoringCoefficient.get();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.currentTimeMillis() < timeoutTime) {
|
||||
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && System.nanoTime() / 1000000L - timeoutTime < 0 && !cancelRequested) {
|
||||
if (slowPath) {
|
||||
try {
|
||||
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.<Long>get());
|
||||
@@ -107,43 +97,35 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
PathNode currentNode = openSet.removeLowest();
|
||||
currentNode.isOpen = false;
|
||||
mostRecentConsidered = currentNode;
|
||||
BetterBlockPos currentNodePos = currentNode.pos;
|
||||
BlockPos currentNodePos = currentNode.pos;
|
||||
numNodes++;
|
||||
if (System.currentTimeMillis() > lastPrintout + 1000) {//print once a second
|
||||
System.out.println("searching... at " + currentNodePos + ", considered " + numNodes + " nodes so far");
|
||||
lastPrintout = System.currentTimeMillis();
|
||||
}
|
||||
if (goal.isInGoal(currentNodePos)) {
|
||||
currentlyRunning = null;
|
||||
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes));
|
||||
}
|
||||
//long constructStart = System.nanoTime();
|
||||
Movement[] possibleMovements = getConnectedPositions(currentNodePos, calcContext);//movement that we could take that start at currentNodePos, in random order
|
||||
shuffle(possibleMovements);
|
||||
//long constructEnd = System.nanoTime();
|
||||
//System.out.println(constructEnd - constructStart);
|
||||
for (Movement movementToGetToNeighbor : possibleMovements) {
|
||||
if (movementToGetToNeighbor == null) {
|
||||
continue;
|
||||
}
|
||||
BetterBlockPos dest = (BetterBlockPos) movementToGetToNeighbor.getDest();
|
||||
boolean isPositionCached = false;
|
||||
if (cache) {
|
||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld() != null) {
|
||||
if (CachedWorldProvider.INSTANCE.getCurrentWorld().getBlockType(dest) != null) {
|
||||
isPositionCached = true;
|
||||
BlockPos dest = movementToGetToNeighbor.getDest();
|
||||
int chunkX = currentNodePos.getX() >> 4;
|
||||
int chunkZ = currentNodePos.getZ() >> 4;
|
||||
if (dest.getX() >> 4 != chunkX || dest.getZ() >> 4 != chunkZ) {
|
||||
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
|
||||
if (chunkProvider.getLoadedChunk(chunkX, chunkZ) == null) {
|
||||
// see issue #106
|
||||
if (cachedWorld == null || !cachedWorld.isCached(dest)) {
|
||||
numEmptyChunk++;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!isPositionCached && Minecraft.getMinecraft().world.getChunk(dest) instanceof EmptyChunk) {
|
||||
numEmptyChunk++;
|
||||
continue;
|
||||
}
|
||||
//long costStart = System.nanoTime();
|
||||
// TODO cache cost
|
||||
double actionCost = movementToGetToNeighbor.getCost(calcContext);
|
||||
//long costEnd = System.nanoTime();
|
||||
//System.out.println(movementToGetToNeighbor.getClass() + "" + (costEnd - costStart));
|
||||
numMovementsConsidered++;
|
||||
if (actionCost >= ActionCosts.COST_INF) {
|
||||
continue;
|
||||
}
|
||||
@@ -160,6 +142,14 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
if (tentativeCost < 0) {
|
||||
throw new IllegalStateException(movementToGetToNeighbor.getClass() + " " + movementToGetToNeighbor + " overflowed into negative " + actionCost + " " + neighbor.cost + " " + tentativeCost);
|
||||
}
|
||||
double improvementBy = neighbor.cost - tentativeCost;
|
||||
// there are floating point errors caused by random combinations of traverse and diagonal over a flat area
|
||||
// that means that sometimes there's a cost improvement of like 10 ^ -16
|
||||
// it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
|
||||
if (improvementBy < 0.01 && minimumImprovementRepropagation) {
|
||||
// who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
|
||||
continue;
|
||||
}
|
||||
neighbor.previous = currentNode;
|
||||
neighbor.previousMovement = movementToGetToNeighbor;
|
||||
neighbor.cost = tentativeCost;
|
||||
@@ -173,6 +163,9 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
|
||||
if (heuristic < bestHeuristicSoFar[i]) {
|
||||
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
|
||||
continue;
|
||||
}
|
||||
bestHeuristicSoFar[i] = heuristic;
|
||||
bestSoFar[i] = neighbor;
|
||||
}
|
||||
@@ -180,6 +173,13 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (cancelRequested) {
|
||||
currentlyRunning = null;
|
||||
return Optional.empty();
|
||||
}
|
||||
System.out.println(numMovementsConsidered + " movements considered");
|
||||
System.out.println("Open set size: " + openSet.size());
|
||||
System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second");
|
||||
double bestDist = 0;
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
if (bestSoFar[i] == null) {
|
||||
@@ -190,51 +190,55 @@ public class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
|
||||
bestDist = dist;
|
||||
}
|
||||
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
displayChatMessageRaw("A* cost coefficient " + COEFFICIENTS[i]);
|
||||
displayChatMessageRaw("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
|
||||
if (COEFFICIENTS[i] >= 3) {
|
||||
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
|
||||
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
|
||||
System.out.println("But I'm going to do it anyway, because yolo");
|
||||
}
|
||||
System.out.println("Path goes for " + dist + " blocks");
|
||||
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
|
||||
currentlyRunning = null;
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], numNodes));
|
||||
}
|
||||
}
|
||||
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + bestDist + " blocks =(");
|
||||
displayChatMessageRaw("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
|
||||
displayChatMessageRaw("No path found =(");
|
||||
currentlyRunning = null;
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
|
||||
private static Movement[] getConnectedPositions(BetterBlockPos pos, CalculationContext calcContext) {
|
||||
public static Movement[] getConnectedPositions(BlockPos pos, CalculationContext calcContext) {
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
BetterBlockPos east = new BetterBlockPos(x + 1, y, z);
|
||||
BetterBlockPos west = new BetterBlockPos(x - 1, y, z);
|
||||
BetterBlockPos south = new BetterBlockPos(x, y, z + 1);
|
||||
BetterBlockPos north = new BetterBlockPos(x, y, z - 1);
|
||||
BlockPos east = new BlockPos(x + 1, y, z);
|
||||
BlockPos west = new BlockPos(x - 1, y, z);
|
||||
BlockPos south = new BlockPos(x, y, z + 1);
|
||||
BlockPos north = new BlockPos(x, y, z - 1);
|
||||
return new Movement[]{
|
||||
new MovementTraverse(pos, east),
|
||||
new MovementTraverse(pos, west),
|
||||
new MovementTraverse(pos, north),
|
||||
new MovementTraverse(pos, south),
|
||||
new MovementAscend(pos, new BetterBlockPos(x + 1, y + 1, z)),
|
||||
new MovementAscend(pos, new BetterBlockPos(x - 1, y + 1, z)),
|
||||
new MovementAscend(pos, new BetterBlockPos(x, y + 1, z + 1)),
|
||||
new MovementAscend(pos, new BetterBlockPos(x, y + 1, z - 1)),
|
||||
new MovementAscend(pos, new BlockPos(x + 1, y + 1, z)),
|
||||
new MovementAscend(pos, new BlockPos(x - 1, y + 1, z)),
|
||||
new MovementAscend(pos, new BlockPos(x, y + 1, z + 1)),
|
||||
new MovementAscend(pos, new BlockPos(x, y + 1, z - 1)),
|
||||
MovementHelper.generateMovementFallOrDescend(pos, east, calcContext),
|
||||
MovementHelper.generateMovementFallOrDescend(pos, west, calcContext),
|
||||
MovementHelper.generateMovementFallOrDescend(pos, north, calcContext),
|
||||
MovementHelper.generateMovementFallOrDescend(pos, south, calcContext),
|
||||
new MovementDownward(pos, new BetterBlockPos(x, y - 1, z)),
|
||||
new MovementDownward(pos, new BlockPos(x, y - 1, z)),
|
||||
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.WEST),
|
||||
new MovementDiagonal(pos, EnumFacing.NORTH, EnumFacing.EAST),
|
||||
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.WEST),
|
||||
new MovementDiagonal(pos, EnumFacing.SOUTH, EnumFacing.EAST),
|
||||
new MovementPillar(pos, new BetterBlockPos(x, y + 1, z))
|
||||
new MovementPillar(pos, new BlockPos(x, y + 1, z)),
|
||||
MovementParkour.calculate(pos, EnumFacing.NORTH),
|
||||
MovementParkour.calculate(pos, EnumFacing.SOUTH),
|
||||
MovementParkour.calculate(pos, EnumFacing.EAST),
|
||||
MovementParkour.calculate(pos, EnumFacing.WEST),
|
||||
};
|
||||
}
|
||||
|
||||
+56
-19
@@ -15,15 +15,14 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc;
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import baritone.behavior.impl.PathingBehavior;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
@@ -38,11 +37,11 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
*/
|
||||
protected static AbstractNodeCostSearch currentlyRunning = null;
|
||||
|
||||
protected final BetterBlockPos start;
|
||||
protected final BlockPos start;
|
||||
|
||||
protected final Goal goal;
|
||||
|
||||
protected final Map<BetterBlockPos, PathNode> map;
|
||||
private final HashMap<BlockPos, PathNode> map; // see issue #107
|
||||
|
||||
protected PathNode startNode;
|
||||
|
||||
@@ -52,34 +51,51 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
private volatile boolean isFinished;
|
||||
|
||||
protected boolean cancelRequested;
|
||||
|
||||
/**
|
||||
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
|
||||
* long it was easier as a Google Doc (because I could insert charts).
|
||||
*
|
||||
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a>
|
||||
*/
|
||||
protected static final double[] COEFFICIENTS = {1.25, 1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
|
||||
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
|
||||
/**
|
||||
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
|
||||
*/
|
||||
protected final static double MIN_DIST_PATH = 5;
|
||||
|
||||
AbstractNodeCostSearch(BlockPos start, Goal goal) {
|
||||
this.start = new BetterBlockPos(start.getX(), start.getY(), start.getZ());
|
||||
this.start = new BlockPos(start.getX(), start.getY(), start.getZ());
|
||||
this.goal = goal;
|
||||
this.map = new HashMap<>();
|
||||
}
|
||||
|
||||
public synchronized Optional<IPath> calculate() {
|
||||
public void cancel() {
|
||||
cancelRequested = true;
|
||||
}
|
||||
|
||||
public synchronized Optional<IPath> calculate(long timeout) {
|
||||
if (isFinished) {
|
||||
throw new IllegalStateException("Path Finder is currently in use, and cannot be reused!");
|
||||
}
|
||||
Optional<IPath> path = calculate0();
|
||||
isFinished = true;
|
||||
return path;
|
||||
this.cancelRequested = false;
|
||||
try {
|
||||
Optional<IPath> path = calculate0(timeout);
|
||||
isFinished = true;
|
||||
return path;
|
||||
} catch (Exception e) {
|
||||
currentlyRunning = null;
|
||||
isFinished = true;
|
||||
if (e instanceof RuntimeException) {
|
||||
throw (RuntimeException) e;
|
||||
} else {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
protected abstract Optional<IPath> calculate0();
|
||||
protected abstract Optional<IPath> calculate0(long timeout);
|
||||
|
||||
/**
|
||||
* Determines the distance squared from the specified node to the start
|
||||
@@ -104,8 +120,19 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
* @param pos The pos to lookup
|
||||
* @return The associated node
|
||||
*/
|
||||
protected PathNode getNodeAtPosition(BetterBlockPos pos) {
|
||||
return map.computeIfAbsent(pos, p -> new PathNode(p, goal));
|
||||
protected PathNode getNodeAtPosition(BlockPos pos) {
|
||||
// see issue #107
|
||||
PathNode node = map.get(pos);
|
||||
if (node == null) {
|
||||
node = new PathNode(pos, goal);
|
||||
map.put(pos, node);
|
||||
}
|
||||
return node;
|
||||
}
|
||||
|
||||
public static void forceCancel() {
|
||||
PathingBehavior.INSTANCE.cancel();
|
||||
currentlyRunning = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -115,10 +142,20 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
|
||||
|
||||
@Override
|
||||
public Optional<IPath> bestPathSoFar() {
|
||||
if (startNode == null || bestSoFar[0] == null)
|
||||
if (startNode == null || bestSoFar[0] == null) {
|
||||
return Optional.empty();
|
||||
|
||||
return Optional.of(new Path(startNode, bestSoFar[0], 0));
|
||||
}
|
||||
for (int i = 0; i < bestSoFar.length; i++) {
|
||||
if (bestSoFar[i] == null) {
|
||||
continue;
|
||||
}
|
||||
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
|
||||
return Optional.of(new Path(startNode, bestSoFar[i], 0));
|
||||
}
|
||||
}
|
||||
// instead of returning bestSoFar[0], be less misleading
|
||||
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@Override
|
||||
+4
-4
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc;
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.path.IPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -39,7 +39,7 @@ public interface IPathFinder {
|
||||
*
|
||||
* @return The final path
|
||||
*/
|
||||
Optional<IPath> calculate();
|
||||
Optional<IPath> calculate(long timeout);
|
||||
|
||||
/**
|
||||
* Intended to be called concurrently with calculatePath from a different thread to tell if it's finished yet
|
||||
+11
-11
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc;
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.path.IPath;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.path.IPath;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -37,18 +37,18 @@ class Path implements IPath {
|
||||
/**
|
||||
* The start position of this path
|
||||
*/
|
||||
final BetterBlockPos start;
|
||||
final BlockPos start;
|
||||
|
||||
/**
|
||||
* The end position of this path
|
||||
*/
|
||||
final BetterBlockPos end;
|
||||
final BlockPos end;
|
||||
|
||||
/**
|
||||
* The blocks on the path. Guaranteed that path.get(0) equals start and
|
||||
* path.get(path.size()-1) equals end
|
||||
*/
|
||||
final List<BetterBlockPos> path;
|
||||
final List<BlockPos> path;
|
||||
|
||||
final List<Movement> movements;
|
||||
|
||||
@@ -75,7 +75,7 @@ class Path implements IPath {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
LinkedList<BlockPos> tempPath = new LinkedList<>(); // Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
LinkedList<Movement> tempMovements = new LinkedList<>(); // Instead, do it into a linked list, then convert at the end
|
||||
while (!current.equals(start)) {
|
||||
tempPath.addFirst(current.pos);
|
||||
@@ -122,7 +122,7 @@ class Path implements IPath {
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<BetterBlockPos> positions() {
|
||||
public List<BlockPos> positions() {
|
||||
return Collections.unmodifiableList(path);
|
||||
}
|
||||
|
||||
@@ -132,12 +132,12 @@ class Path implements IPath {
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetterBlockPos getSrc() {
|
||||
public BlockPos getSrc() {
|
||||
return start;
|
||||
}
|
||||
|
||||
@Override
|
||||
public BetterBlockPos getDest() {
|
||||
public BlockPos getDest() {
|
||||
return end;
|
||||
}
|
||||
}
|
||||
+10
-9
@@ -15,23 +15,23 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc;
|
||||
package baritone.pathing.calc;
|
||||
|
||||
import baritone.bot.pathing.goals.Goal;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.utils.pathing.BetterBlockPos;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
* A node in the path, containing the cost and steps to get to it.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class PathNode {
|
||||
public final class PathNode {
|
||||
|
||||
/**
|
||||
* The position of this node
|
||||
*/
|
||||
final BetterBlockPos pos;
|
||||
final BlockPos pos;
|
||||
|
||||
/**
|
||||
* The goal it's going towards
|
||||
@@ -78,7 +78,7 @@ public class PathNode {
|
||||
*/
|
||||
public int heapPosition;
|
||||
|
||||
public PathNode(BetterBlockPos pos, Goal goal) {
|
||||
public PathNode(BlockPos pos, Goal goal) {
|
||||
this.pos = pos;
|
||||
this.previous = null;
|
||||
this.cost = Short.MAX_VALUE;
|
||||
@@ -95,7 +95,7 @@ public class PathNode {
|
||||
*/
|
||||
@Override
|
||||
public int hashCode() {
|
||||
throw new IllegalStateException();
|
||||
return pos.hashCode() * 7 + 3;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -103,8 +103,9 @@ public class PathNode {
|
||||
// GOTTA GO FAST
|
||||
// ALL THESE CHECKS ARE FOR PEOPLE WHO WANT SLOW CODE
|
||||
// SKRT SKRT
|
||||
//if (obj == null || !(obj instanceof PathNode))
|
||||
//if (obj == null || !(obj instanceof PathNode)) {
|
||||
// return false;
|
||||
//}
|
||||
|
||||
//final PathNode other = (PathNode) obj;
|
||||
//return Objects.equals(this.pos, other.pos) && Objects.equals(this.goal, other.goal);
|
||||
+32
-33
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
package baritone.pathing.calc.openset;
|
||||
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
import baritone.pathing.calc.PathNode;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
@@ -26,7 +26,7 @@ import java.util.Arrays;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class BinaryHeapOpenSet implements IOpenSet {
|
||||
public final class BinaryHeapOpenSet implements IOpenSet {
|
||||
|
||||
/**
|
||||
* The initial capacity of the heap (2^10)
|
||||
@@ -52,28 +52,45 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
this.array = new PathNode[size];
|
||||
}
|
||||
|
||||
public int size() {
|
||||
return size;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void insert(PathNode value) {
|
||||
public final void insert(PathNode value) {
|
||||
if (size >= array.length - 1) {
|
||||
array = Arrays.copyOf(array, array.length * 2);
|
||||
}
|
||||
size++;
|
||||
value.heapPosition = size;
|
||||
array[size] = value;
|
||||
upHeap(size);
|
||||
}
|
||||
|
||||
public void update(PathNode node) {
|
||||
upHeap(node.heapPosition);
|
||||
update(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEmpty() {
|
||||
public final void update(PathNode val) {
|
||||
int index = val.heapPosition;
|
||||
int parentInd = index >>> 1;
|
||||
double cost = val.combinedCost;
|
||||
PathNode parentNode = array[parentInd];
|
||||
while (index > 1 && parentNode.combinedCost > cost) {
|
||||
array[index] = parentNode;
|
||||
array[parentInd] = val;
|
||||
val.heapPosition = parentInd;
|
||||
parentNode.heapPosition = index;
|
||||
index = parentInd;
|
||||
parentInd = index >>> 1;
|
||||
parentNode = array[parentInd];
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public final boolean isEmpty() {
|
||||
return size == 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathNode removeLowest() {
|
||||
public final PathNode removeLowest() {
|
||||
if (size == 0) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -91,14 +108,13 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
int smallerChild = 2;
|
||||
double cost = val.combinedCost;
|
||||
do {
|
||||
int right = smallerChild + 1;
|
||||
PathNode smallerChildNode = array[smallerChild];
|
||||
double smallerChildCost = smallerChildNode.combinedCost;
|
||||
if (right <= size) {
|
||||
PathNode rightChildNode = array[right];
|
||||
if (smallerChild < size) {
|
||||
PathNode rightChildNode = array[smallerChild + 1];
|
||||
double rightChildCost = rightChildNode.combinedCost;
|
||||
if (smallerChildCost > rightChildCost) {
|
||||
smallerChild = right;
|
||||
smallerChild++;
|
||||
smallerChildCost = rightChildCost;
|
||||
smallerChildNode = rightChildNode;
|
||||
}
|
||||
@@ -111,24 +127,7 @@ public class BinaryHeapOpenSet implements IOpenSet {
|
||||
val.heapPosition = smallerChild;
|
||||
smallerChildNode.heapPosition = index;
|
||||
index = smallerChild;
|
||||
smallerChild = index << 1;
|
||||
} while (smallerChild <= size);
|
||||
} while ((smallerChild <<= 1) <= size);
|
||||
return result;
|
||||
}
|
||||
|
||||
private void upHeap(int index) {
|
||||
int parentInd = index >>> 1;
|
||||
PathNode val = array[index];
|
||||
double cost = val.combinedCost;
|
||||
PathNode parentNode = array[parentInd];
|
||||
while (index > 1 && parentNode.combinedCost > cost) {
|
||||
array[index] = parentNode;
|
||||
array[parentInd] = val;
|
||||
val.heapPosition = parentInd;
|
||||
parentNode.heapPosition = index;
|
||||
index = parentInd;
|
||||
parentInd = index >>> 1;
|
||||
parentNode = array[parentInd];
|
||||
}
|
||||
}
|
||||
}
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
package baritone.pathing.calc.openset;
|
||||
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
import baritone.pathing.calc.PathNode;
|
||||
|
||||
/**
|
||||
* An open set for A* or similar graph search algorithm
|
||||
+4
-3
@@ -15,17 +15,18 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.calc.openset;
|
||||
package baritone.pathing.calc.openset;
|
||||
|
||||
import baritone.bot.pathing.calc.PathNode;
|
||||
import baritone.pathing.calc.PathNode;
|
||||
|
||||
/**
|
||||
* A linked list implementation of an open set. This is the original implementation from MineBot.
|
||||
* It has incredibly fast insert performance, at the cost of O(n) removeLowest.
|
||||
* It sucks. BinaryHeapOpenSet results in more than 10x more nodes considered in 4 seconds.
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class LinkedListOpenSet implements IOpenSet {
|
||||
class LinkedListOpenSet implements IOpenSet {
|
||||
private Node first = null;
|
||||
|
||||
@Override
|
||||
+2
-2
@@ -15,9 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.bot.pathing.movement.ActionCosts;
|
||||
import baritone.pathing.movement.ActionCosts;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
+6
-16
@@ -15,8 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -24,7 +25,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class GoalBlock implements Goal {
|
||||
public class GoalBlock implements Goal, IGoalRenderPos {
|
||||
|
||||
/**
|
||||
* The X block position of this goal
|
||||
@@ -87,23 +88,12 @@ public class GoalBlock implements Goal {
|
||||
}
|
||||
|
||||
public static double calculate(double xDiff, int yDiff, double zDiff) {
|
||||
double pythaDist = Math.sqrt(xDiff * xDiff + zDiff * zDiff);
|
||||
double heuristic = 0;
|
||||
if (pythaDist < MAX) {//if we are more than MAX away, ignore the Y coordinate. It really doesn't matter how far away your Y coordinate is if you X coordinate is 1000 blocks away.
|
||||
//as we get closer, slowly reintroduce the Y coordinate as a heuristic cost
|
||||
double multiplier;
|
||||
if (pythaDist < MIN) {
|
||||
multiplier = 1;
|
||||
} else {
|
||||
multiplier = 1 - (pythaDist - MIN) / (MAX - MIN);
|
||||
}
|
||||
|
||||
// if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be
|
||||
// therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate
|
||||
heuristic += new GoalYLevel(yDiff).heuristic(new BlockPos(0, 0, 0));
|
||||
// if yDiff is 1 that means that pos.getY()-this.y==1 which means that we're 1 block below where we should be
|
||||
// therefore going from 0,0,0 to a GoalYLevel of pos.getY()-this.y is accurate
|
||||
heuristic += new GoalYLevel(yDiff).heuristic(new BlockPos(0, 0, 0));
|
||||
|
||||
heuristic *= multiplier;
|
||||
}
|
||||
//use the pythagorean and manhattan mixture from GoalXZ
|
||||
heuristic += GoalXZ.calculate(xDiff, zDiff);
|
||||
return heuristic;
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Collection;
|
||||
@@ -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 General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
|
||||
/**
|
||||
* Don't get into the block, but get directly adjacent to it. Useful for chests.
|
||||
*
|
||||
* @author avecowa
|
||||
*/
|
||||
public class GoalGetToBlock implements Goal, IGoalRenderPos {
|
||||
|
||||
private final int x;
|
||||
private final int y;
|
||||
private final int z;
|
||||
|
||||
public GoalGetToBlock(BlockPos pos) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
}
|
||||
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
int xDiff = pos.getX() - this.x;
|
||||
int yDiff = pos.getY() - this.y;
|
||||
int zDiff = pos.getZ() - this.z;
|
||||
if (yDiff < 0) {
|
||||
yDiff++;
|
||||
}
|
||||
return Math.abs(xDiff) + Math.abs(yDiff) + Math.abs(zDiff) <= 1;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(BlockPos pos) {
|
||||
int xDiff = pos.getX() - this.x;
|
||||
int yDiff = pos.getY() - this.y;
|
||||
int zDiff = pos.getZ() - this.z;
|
||||
return GoalBlock.calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,65 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class GoalNear implements Goal, IGoalRenderPos {
|
||||
final int x;
|
||||
final int y;
|
||||
final int z;
|
||||
final int rangeSq;
|
||||
|
||||
public GoalNear(BlockPos pos, int range) {
|
||||
this.x = pos.getX();
|
||||
this.y = pos.getY();
|
||||
this.z = pos.getZ();
|
||||
this.rangeSq = range * range;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(BlockPos pos) {
|
||||
int diffX = x - pos.getX();
|
||||
int diffY = y - pos.getY();
|
||||
int diffZ = z - pos.getZ();
|
||||
return diffX * diffX + diffY * diffY + diffZ * diffZ <= rangeSq;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(BlockPos pos) {
|
||||
int diffX = x - pos.getX();
|
||||
int diffY = y - pos.getY();
|
||||
int diffZ = z - pos.getZ();
|
||||
return GoalBlock.calculate(diffX, diffY, diffZ);
|
||||
}
|
||||
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalNear{" +
|
||||
"x=" + x +
|
||||
", y=" + y +
|
||||
", z=" + z +
|
||||
", rangeSq=" + rangeSq +
|
||||
'}';
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import java.util.Arrays;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
+7
-2
@@ -15,8 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.utils.interfaces.IGoalRenderPos;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
/**
|
||||
@@ -25,7 +26,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public class GoalTwoBlocks implements Goal {
|
||||
public class GoalTwoBlocks implements Goal, IGoalRenderPos {
|
||||
|
||||
/**
|
||||
* The X block position of this goal
|
||||
@@ -68,6 +69,10 @@ public class GoalTwoBlocks implements Goal {
|
||||
return GoalBlock.calculate(xDiff, yDiff, zDiff);
|
||||
}
|
||||
|
||||
public BlockPos getGoalPos() {
|
||||
return new BlockPos(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "GoalTwoBlocks{x=" + x + ",y=" + y + ",z=" + z + "}";
|
||||
+10
-6
@@ -15,11 +15,12 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.utils.Utils;
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Utils;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
/**
|
||||
@@ -64,6 +65,9 @@ public class GoalXZ implements Goal {
|
||||
}
|
||||
|
||||
public static double calculate(double xDiff, double zDiff) {
|
||||
if (Baritone.settings().pythagoreanMetric.get()) {
|
||||
return Math.sqrt(xDiff * xDiff + zDiff * zDiff) * Baritone.settings().costHeuristic.get();
|
||||
}
|
||||
//This is a combination of pythagorean and manhattan distance
|
||||
//It takes into account the fact that pathing can either walk diagonally or forwards
|
||||
|
||||
@@ -85,9 +89,9 @@ public class GoalXZ implements Goal {
|
||||
}
|
||||
|
||||
public static GoalXZ fromDirection(Vec3d origin, float yaw, double distance) {
|
||||
double theta = Utils.degToRad(yaw);
|
||||
double x = origin.x - Math.sin(theta) * distance;
|
||||
double z = origin.z + Math.cos(theta) * distance;
|
||||
float theta = (float) Utils.degToRad(yaw);
|
||||
double x = origin.x - MathHelper.sin(theta) * distance;
|
||||
double z = origin.z + MathHelper.cos(theta) * distance;
|
||||
return new GoalXZ((int) x, (int) z);
|
||||
}
|
||||
|
||||
+2
-2
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.goals;
|
||||
package baritone.pathing.goals;
|
||||
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -44,7 +44,7 @@ public class GoalYLevel implements Goal {
|
||||
public double heuristic(BlockPos pos) {
|
||||
if (pos.getY() > level) {
|
||||
// need to descend
|
||||
return FALL_N_BLOCKS_COST[pos.getY() - level];
|
||||
return FALL_N_BLOCKS_COST[2] / 2 * (pos.getY() - level);
|
||||
}
|
||||
if (pos.getY() < level) {
|
||||
// need to ascend
|
||||
+3
-2
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
package baritone.pathing.movement;
|
||||
|
||||
public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieInside {
|
||||
|
||||
@@ -24,7 +24,8 @@ public interface ActionCosts extends ActionCostsButOnlyTheOnesThatMakeMickeyDieI
|
||||
*/
|
||||
double WALK_ONE_BLOCK_COST = 20 / 4.317; // 4.633
|
||||
double WALK_ONE_IN_WATER_COST = 20 / 2.2;
|
||||
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_IN_WATER_COST; // TODO issue #7
|
||||
double WALK_ONE_OVER_SOUL_SAND_COST = WALK_ONE_BLOCK_COST * 0.5; // 0.4 in BlockSoulSand but effectively about half
|
||||
double SPRINT_ONE_OVER_SOUL_SAND_COST = WALK_ONE_OVER_SOUL_SAND_COST / 0.75;
|
||||
double LADDER_UP_ONE_COST = 20 / 2.35;
|
||||
double LADDER_DOWN_ONE_COST = 20 / 3.0;
|
||||
double SNEAK_ONE_BLOCK_COST = 20 / 1.3;
|
||||
+1
-1
@@ -15,7 +15,7 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
package baritone.pathing.movement;
|
||||
|
||||
public interface ActionCostsButOnlyTheOnesThatMakeMickeyDieInside {
|
||||
double[] FALL_N_BLOCKS_COST = generateFallNBlocksCost();
|
||||
+18
-6
@@ -15,11 +15,11 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.ToolSet;
|
||||
import baritone.Baritone;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
@@ -38,19 +38,22 @@ public class CalculationContext implements Helper {
|
||||
private final boolean canSprint;
|
||||
private final double placeBlockCost;
|
||||
private final boolean allowBreak;
|
||||
private final int maxFallHeightNoWater;
|
||||
private final int maxFallHeightBucket;
|
||||
|
||||
public CalculationContext() {
|
||||
this(new ToolSet());
|
||||
}
|
||||
|
||||
public CalculationContext(ToolSet toolSet) {
|
||||
player().setSprinting(true);
|
||||
this.toolSet = toolSet;
|
||||
this.hasThrowaway = Baritone.settings().allowPlaceThrowaway.get() && MovementHelper.throwaway(false);
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();
|
||||
this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6;
|
||||
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.get();
|
||||
this.allowBreak = Baritone.settings().allowBreak.get();
|
||||
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
|
||||
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
|
||||
// why cache these things here, why not let the movements just get directly from settings?
|
||||
// because if some movements are calculated one way and others are calculated another way,
|
||||
// then you get a wildly inconsistent path that isn't optimal for either scenario.
|
||||
@@ -79,4 +82,13 @@ public class CalculationContext implements Helper {
|
||||
public boolean allowBreak() {
|
||||
return allowBreak;
|
||||
}
|
||||
|
||||
public int maxFallHeightNoWater() {
|
||||
return maxFallHeightNoWater;
|
||||
}
|
||||
|
||||
public int maxFallHeightBucket() {
|
||||
return maxFallHeightBucket;
|
||||
}
|
||||
|
||||
}
|
||||
+139
-84
@@ -15,32 +15,29 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.bot.Baritone;
|
||||
import baritone.bot.behavior.impl.LookBehavior;
|
||||
import baritone.bot.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.pathing.movement.movements.MovementDownward;
|
||||
import baritone.bot.pathing.movement.movements.MovementPillar;
|
||||
import baritone.bot.pathing.movement.movements.MovementTraverse;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.Helper;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.bot.utils.ToolSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehavior;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.bot.utils.InputOverrideHandler.Input;
|
||||
import static baritone.utils.InputOverrideHandler.Input;
|
||||
|
||||
public abstract class Movement implements Helper, MovementHelper {
|
||||
|
||||
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
|
||||
|
||||
private MovementState currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
|
||||
protected final BlockPos src;
|
||||
@@ -53,42 +50,35 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
protected final BlockPos[] positionsToBreak;
|
||||
|
||||
/**
|
||||
* The positions where we need to place a block before this movement can ensue
|
||||
* The position where we need to place a block before this movement can ensue
|
||||
*/
|
||||
protected final BlockPos[] positionsToPlace;
|
||||
protected final BlockPos positionToPlace;
|
||||
|
||||
private boolean didBreakLastTick;
|
||||
|
||||
private Double cost;
|
||||
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace) {
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos toPlace) {
|
||||
this.src = src;
|
||||
this.dest = dest;
|
||||
this.positionsToBreak = toBreak;
|
||||
this.positionsToPlace = toPlace;
|
||||
this.positionToPlace = toPlace;
|
||||
}
|
||||
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak, BlockPos[] toPlace, Vec3d rotationTarget) {
|
||||
this(src, dest, toBreak, toPlace);
|
||||
protected Movement(BlockPos src, BlockPos dest, BlockPos[] toBreak) {
|
||||
this(src, dest, toBreak, null);
|
||||
}
|
||||
|
||||
public double getCost(CalculationContext context) {
|
||||
if (cost == null) {
|
||||
if (context == null)
|
||||
if (context == null) {
|
||||
context = new CalculationContext();
|
||||
cost = calculateCost0(context);
|
||||
}
|
||||
cost = calculateCost(context);
|
||||
}
|
||||
return cost;
|
||||
}
|
||||
|
||||
private double calculateCost0(CalculationContext context) {
|
||||
if (!(this instanceof MovementPillar) && !(this instanceof MovementTraverse) && !(this instanceof MovementDownward)) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown instanceof BlockLadder || fromDown instanceof BlockVine) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
return calculateCost(context);
|
||||
}
|
||||
|
||||
protected abstract double calculateCost(CalculationContext context);
|
||||
|
||||
public double recalculateCost() {
|
||||
@@ -96,6 +86,14 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return getCost(null);
|
||||
}
|
||||
|
||||
protected void override(double cost) {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
public double calculateCostWithoutCaching() {
|
||||
return calculateCost(new CalculationContext());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the execution of the latest Movement
|
||||
* State, and offers a Status to the calling class.
|
||||
@@ -103,40 +101,74 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
* @return Status
|
||||
*/
|
||||
public MovementStatus update() {
|
||||
player().setSprinting(false);
|
||||
MovementState latestState = updateState(currentState);
|
||||
if (BlockStateInterface.isLiquid(playerFeet())) {
|
||||
latestState.setInput(Input.JUMP, true);
|
||||
}
|
||||
latestState.getTarget().getRotation().ifPresent(LookBehavior.INSTANCE::updateTarget);
|
||||
|
||||
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
|
||||
latestState.getTarget().getRotation().ifPresent(rotation ->
|
||||
LookBehavior.INSTANCE.updateTarget(
|
||||
rotation,
|
||||
latestState.getTarget().hasToForceRotations()));
|
||||
|
||||
// TODO: calculate movement inputs from latestState.getGoal().position
|
||||
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
|
||||
|
||||
this.didBreakLastTick = false;
|
||||
|
||||
latestState.getInputStates().forEach((input, forced) -> {
|
||||
RayTraceResult trace = mc.objectMouseOver;
|
||||
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
|
||||
boolean isLeftClick = forced && input == Input.CLICK_LEFT;
|
||||
|
||||
// If we're forcing left click, we're in a gui screen, and we're looking
|
||||
// at a block, break the block without a direct game input manipulation.
|
||||
if (mc.currentScreen != null && isLeftClick && isBlockTrace) {
|
||||
BlockBreakHelper.tryBreakBlock(trace.getBlockPos(), trace.sideHit);
|
||||
this.didBreakLastTick = true;
|
||||
return;
|
||||
}
|
||||
|
||||
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced);
|
||||
});
|
||||
latestState.getInputStates().replaceAll((input, forced) -> false);
|
||||
|
||||
if (!this.didBreakLastTick) {
|
||||
BlockBreakHelper.stopBreakingBlock();
|
||||
}
|
||||
|
||||
currentState = latestState;
|
||||
|
||||
if (isFinished())
|
||||
if (isFinished()) {
|
||||
onFinish(latestState);
|
||||
}
|
||||
|
||||
return currentState.getStatus();
|
||||
}
|
||||
|
||||
protected boolean prepared(MovementState state) {
|
||||
if (state.getStatus() == MovementStatus.WAITING)
|
||||
if (state.getStatus() == MovementStatus.WAITING) {
|
||||
return true;
|
||||
|
||||
}
|
||||
boolean somethingInTheWay = false;
|
||||
for (BlockPos blockPos : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(blockPos)) {
|
||||
somethingInTheWay = true;
|
||||
Optional<Rotation> reachable = LookBehaviorUtils.reachable(blockPos);
|
||||
if (reachable.isPresent()) {
|
||||
player().inventory.currentItem = new ToolSet().getBestSlot(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get())).setInput(Input.CLICK_LEFT, true);
|
||||
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
//get rekt minecraft
|
||||
//i'm doing it anyway
|
||||
//i dont care if theres snow in the way!!!!!!!
|
||||
//you dont own me!!!!
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(blockPos)), true)
|
||||
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
if (somethingInTheWay) {
|
||||
@@ -168,7 +200,6 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
public void onFinish(MovementState state) {
|
||||
state.getInputStates().replaceAll((input, forced) -> false);
|
||||
state.getInputStates().forEach((input, forced) -> Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(input, forced));
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
public void cancel() {
|
||||
@@ -177,41 +208,58 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
currentState.setStatus(MovementStatus.CANCELED);
|
||||
}
|
||||
|
||||
public void reset() {
|
||||
currentState = new MovementState().setStatus(MovementStatus.PREPPING);
|
||||
}
|
||||
|
||||
public double getTotalHardnessOfBlocksToBreak(CalculationContext ctx) {
|
||||
/*
|
||||
double sum = 0;
|
||||
HashSet<BlockPos> toBreak = new HashSet();
|
||||
for (BlockPos positionsToBreak1 : positionsToBreak) {
|
||||
toBreak.add(positionsToBreak1);
|
||||
if (this instanceof ActionFall) {//if we are digging straight down, assume we have already broken the sand above us
|
||||
continue;
|
||||
}
|
||||
BlockPos tmp = positionsToBreak1.up();
|
||||
while (canFall(tmp)) {
|
||||
toBreak.add(tmp);
|
||||
tmp = tmp.up();
|
||||
}
|
||||
if (positionsToBreak.length == 0) {
|
||||
return 0;
|
||||
}
|
||||
for (BlockPos pos : toBreak) {
|
||||
sum += getHardness(ts, Baritone.get(pos), pos);
|
||||
if (sum >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (positionsToBreak.length == 1) {
|
||||
return MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[0], true);
|
||||
}
|
||||
if (!Baritone.allowBreakOrPlace || !Baritone.hasThrowaway) {
|
||||
for (int i = 0; i < blocksToPlace.length; i++) {
|
||||
if (!canWalkOn(positionsToPlace[i])) {
|
||||
return COST_INF;
|
||||
int firstColumnX = positionsToBreak[0].getX();
|
||||
int firstColumnZ = positionsToBreak[0].getZ();
|
||||
int firstColumnMaxY = positionsToBreak[0].getY();
|
||||
int firstColumnMaximalIndex = 0;
|
||||
boolean hasSecondColumn = false;
|
||||
int secondColumnX = -1;
|
||||
int secondColumnZ = -1;
|
||||
int secondColumnMaxY = -1;
|
||||
int secondColumnMaximalIndex = -1;
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
BlockPos pos = positionsToBreak[i];
|
||||
if (pos.getX() == firstColumnX && pos.getZ() == firstColumnZ) {
|
||||
if (pos.getY() > firstColumnMaxY) {
|
||||
firstColumnMaxY = pos.getY();
|
||||
firstColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
if (!hasSecondColumn || (pos.getX() == secondColumnX && pos.getZ() == secondColumnZ)) {
|
||||
if (hasSecondColumn) {
|
||||
if (pos.getY() > secondColumnMaxY) {
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
hasSecondColumn = true;
|
||||
secondColumnX = pos.getX();
|
||||
secondColumnZ = pos.getZ();
|
||||
secondColumnMaxY = pos.getY();
|
||||
secondColumnMaximalIndex = i;
|
||||
}
|
||||
} else {
|
||||
throw new IllegalStateException("I literally have no idea " + Arrays.asList(positionsToBreak));
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//^ the above implementation properly deals with falling blocks, TODO integrate
|
||||
}
|
||||
|
||||
double sum = 0;
|
||||
for (BlockPos pos : positionsToBreak) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, pos);
|
||||
for (int i = 0; i < positionsToBreak.length; i++) {
|
||||
sum += MovementHelper.getMiningDurationTicks(ctx, positionsToBreak[i], firstColumnMaximalIndex == i || secondColumnMaximalIndex == i);
|
||||
if (sum >= COST_INF) {
|
||||
return COST_INF;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return sum;
|
||||
@@ -225,23 +273,32 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
* @return
|
||||
*/
|
||||
public MovementState updateState(MovementState state) {
|
||||
if (!prepared(state))
|
||||
if (!prepared(state)) {
|
||||
return state.setStatus(MovementStatus.PREPPING);
|
||||
else if (state.getStatus() == MovementStatus.PREPPING) {
|
||||
} else if (state.getStatus() == MovementStatus.PREPPING) {
|
||||
state.setStatus(MovementStatus.WAITING);
|
||||
}
|
||||
|
||||
if (state.getStatus() == MovementStatus.WAITING) {
|
||||
state.setStatus(MovementStatus.RUNNING);
|
||||
}
|
||||
|
||||
return state;
|
||||
}
|
||||
|
||||
public ArrayList<BlockPos> toBreakCached = null;
|
||||
public ArrayList<BlockPos> toPlaceCached = null;
|
||||
public ArrayList<BlockPos> toWalkIntoCached = null;
|
||||
public BlockPos getDirection() {
|
||||
return getDest().subtract(getSrc());
|
||||
}
|
||||
|
||||
public ArrayList<BlockPos> toBreak() {
|
||||
public List<BlockPos> toBreakCached = null;
|
||||
public List<BlockPos> toPlaceCached = null;
|
||||
public List<BlockPos> toWalkIntoCached = null;
|
||||
|
||||
public List<BlockPos> toBreak() {
|
||||
if (toBreakCached != null) {
|
||||
return toBreakCached;
|
||||
}
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
for (BlockPos positionToBreak : positionsToBreak) {
|
||||
if (!MovementHelper.canWalkThrough(positionToBreak)) {
|
||||
result.add(positionToBreak);
|
||||
@@ -251,21 +308,19 @@ public abstract class Movement implements Helper, MovementHelper {
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArrayList<BlockPos> toPlace() {
|
||||
public List<BlockPos> toPlace() {
|
||||
if (toPlaceCached != null) {
|
||||
return toPlaceCached;
|
||||
}
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
for (BlockPos positionToBreak : positionsToPlace) {
|
||||
if (!MovementHelper.canWalkOn(positionToBreak)) {
|
||||
result.add(positionToBreak);
|
||||
}
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
if (positionToPlace != null && !MovementHelper.canWalkOn(positionToPlace)) {
|
||||
result.add(positionToPlace);
|
||||
}
|
||||
toPlaceCached = result;
|
||||
return result;
|
||||
}
|
||||
|
||||
public ArrayList<BlockPos> toWalkInto() { // overridden by movementdiagonal
|
||||
public List<BlockPos> toWalkInto() { // overridden by movementdiagonal
|
||||
if (toWalkIntoCached == null) {
|
||||
toWalkIntoCached = new ArrayList<>();
|
||||
}
|
||||
@@ -0,0 +1,452 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.pathing.movement.movements.MovementDescend;
|
||||
import baritone.pathing.movement.movements.MovementFall;
|
||||
import baritone.utils.*;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean avoidBreaking(BlockPos pos, IBlockState state) {
|
||||
Block b = state.getBlock();
|
||||
int x = pos.getX();
|
||||
int y = pos.getY();
|
||||
int z = pos.getZ();
|
||||
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish // obvious reasons
|
||||
// call BlockStateInterface.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|
||||
|| BlockStateInterface.get(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side
|
||||
|| BlockStateInterface.get(x + 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x - 1, y, z).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x, y, z + 1).getBlock() instanceof BlockLiquid
|
||||
|| BlockStateInterface.get(x, y, z - 1).getBlock() instanceof BlockLiquid;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can I walk through this block? e.g. air, saplings, torches, etc
|
||||
*
|
||||
* @param pos
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkThrough(BlockPos pos) {
|
||||
return canWalkThrough(pos, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) {
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL) {
|
||||
return false;
|
||||
}
|
||||
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
|
||||
if (block == Blocks.IRON_DOOR) {
|
||||
return false;
|
||||
}
|
||||
return true; // we can just open the door
|
||||
}
|
||||
if (block instanceof BlockSnow || block instanceof BlockTrapDoor) {
|
||||
// we've already checked doors
|
||||
// so the only remaining dynamic isPassables are snow, fence gate, and trapdoor
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
// default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (mc.world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
if (Baritone.settings().assumeWalkOnWater.get()) {
|
||||
return false;
|
||||
}
|
||||
IBlockState up = BlockStateInterface.get(pos.up());
|
||||
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return block.isPassable(mc.world, pos);
|
||||
}
|
||||
|
||||
/**
|
||||
* canWalkThrough but also won't impede movement at all. so not including doors or fence gates (we'd have to right click),
|
||||
* not including water, and not including ladders or vines or cobwebs (they slow us down)
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean fullyPassable(BlockPos pos) {
|
||||
return fullyPassable(pos, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean fullyPassable(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) {
|
||||
return true;
|
||||
}
|
||||
// exceptions - blocks that are isPassasble true, but we can't actually jump through
|
||||
if (block == Blocks.FIRE
|
||||
|| block == Blocks.TRIPWIRE
|
||||
|| block == Blocks.WEB
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.LADDER
|
||||
|| block instanceof BlockDoor
|
||||
|| block instanceof BlockFenceGate
|
||||
|| block instanceof BlockSnow
|
||||
|| block instanceof BlockLiquid
|
||||
|| block instanceof BlockTrapDoor
|
||||
|| block instanceof BlockEndPortal) {
|
||||
return false;
|
||||
}
|
||||
return block.isPassable(mc.world, pos);
|
||||
}
|
||||
|
||||
static boolean isReplacable(BlockPos pos, IBlockState state) {
|
||||
// for MovementTraverse and MovementAscend
|
||||
// block double plant defaults to true when the block doesn't match, so don't need to check that case
|
||||
// all other overrides just return true or false
|
||||
// the only case to deal with is snow
|
||||
/*
|
||||
* public boolean isReplaceable(IBlockAccess worldIn, BlockPos pos)
|
||||
* {
|
||||
* return ((Integer)worldIn.getBlockState(pos).getValue(LAYERS)).intValue() == 1;
|
||||
* }
|
||||
*/
|
||||
if (state.getBlock() instanceof BlockSnow) {
|
||||
// as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (mc.world.getChunk(pos) instanceof EmptyChunk) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return state.getBlock().isReplaceable(mc.world, pos);
|
||||
}
|
||||
|
||||
static boolean isDoorPassable(BlockPos doorPos, BlockPos playerPos) {
|
||||
if (playerPos.equals(doorPos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IBlockState state = BlockStateInterface.get(doorPos);
|
||||
if (!(state.getBlock() instanceof BlockDoor)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isHorizontalBlockPassable(doorPos, state, playerPos, BlockDoor.OPEN);
|
||||
}
|
||||
|
||||
static boolean isGatePassable(BlockPos gatePos, BlockPos playerPos) {
|
||||
if (playerPos.equals(gatePos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
IBlockState state = BlockStateInterface.get(gatePos);
|
||||
if (!(state.getBlock() instanceof BlockFenceGate)) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return isHorizontalBlockPassable(gatePos, state, playerPos, BlockFenceGate.OPEN);
|
||||
}
|
||||
|
||||
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) {
|
||||
if (playerPos.equals(blockPos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis();
|
||||
boolean open = blockState.getValue(propertyOpen);
|
||||
|
||||
EnumFacing.Axis playerFacing;
|
||||
if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) {
|
||||
playerFacing = EnumFacing.Axis.Z;
|
||||
} else if (playerPos.east().equals(blockPos) || playerPos.west().equals(blockPos)) {
|
||||
playerFacing = EnumFacing.Axis.X;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
|
||||
return facing == playerFacing == open;
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
return BlockStateInterface.isLava(block)
|
||||
|| block == Blocks.MAGMA
|
||||
|| block == Blocks.CACTUS
|
||||
|| block == Blocks.FIRE
|
||||
|| block == Blocks.END_PORTAL
|
||||
|| block == Blocks.WEB;
|
||||
}
|
||||
|
||||
/**
|
||||
* Can I walk on this block without anything weird happening like me falling
|
||||
* through? Includes water because we know that we automatically jump on
|
||||
* water
|
||||
*
|
||||
* @return
|
||||
*/
|
||||
static boolean canWalkOn(BlockPos pos, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR || block == Blocks.MAGMA) {
|
||||
return false;
|
||||
}
|
||||
if (state.isBlockNormalCube()) {
|
||||
if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.FARMLAND || block == Blocks.GRASS_PATH) {
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isWater(block)) {
|
||||
Block up = BlockStateInterface.get(pos.up()).getBlock();
|
||||
if (up instanceof BlockLilyPad) {
|
||||
return true;
|
||||
}
|
||||
if (BlockStateInterface.isFlowing(state)) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
|
||||
}
|
||||
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.get()) {
|
||||
if (((BlockSlab) block).isDouble()) {
|
||||
return true;
|
||||
}
|
||||
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockStairs) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static boolean canWalkOn(BlockPos pos) {
|
||||
return canWalkOn(pos, BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
static boolean canPlaceAgainst(BlockPos pos) {
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
// TODO isBlockNormalCube isn't the best check for whether or not we can place a block against it. e.g. glass isn't normalCube but we can place against it
|
||||
return state.isBlockNormalCube();
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, boolean includeFalling) {
|
||||
IBlockState state = BlockStateInterface.get(position);
|
||||
return getMiningDurationTicks(context, position, state, includeFalling);
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, BlockPos position, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(position, state)) {
|
||||
if (!context.allowBreak()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (avoidBreaking(position, state)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
|
||||
double strVsBlock = context.getToolSet().getStrVsBlock(state);
|
||||
if (strVsBlock < 0) {
|
||||
return COST_INF;
|
||||
}
|
||||
|
||||
double result = m / strVsBlock;
|
||||
if (includeFalling) {
|
||||
BlockPos up = position.up();
|
||||
IBlockState above = BlockStateInterface.get(up);
|
||||
if (above.getBlock() instanceof BlockFalling) {
|
||||
result += getMiningDurationTicks(context, up, above, true);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
return 0; // we won't actually mine it, so don't check fallings above
|
||||
}
|
||||
|
||||
static boolean isBottomSlab(IBlockState state) {
|
||||
return state.getBlock() instanceof BlockSlab
|
||||
&& !((BlockSlab) state.getBlock()).isDouble()
|
||||
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
}
|
||||
|
||||
static boolean isBottomSlab(BlockPos pos) {
|
||||
return isBottomSlab(BlockStateInterface.get(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* The entity the player is currently looking at
|
||||
*
|
||||
* @return the entity object
|
||||
*/
|
||||
static Optional<Entity> whatEntityAmILookingAt() {
|
||||
if (mc.objectMouseOver != null && mc.objectMouseOver.typeOfHit == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(mc.objectMouseOver.entityHit);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool
|
||||
*/
|
||||
static void switchToBestTool() {
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(pos -> {
|
||||
IBlockState state = BlockStateInterface.get(pos);
|
||||
if (state.getBlock().equals(Blocks.AIR)) {
|
||||
return;
|
||||
}
|
||||
switchToBestToolFor(state);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool for a specific block
|
||||
*
|
||||
* @param b the blockstate to mine
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b) {
|
||||
switchToBestToolFor(b, new ToolSet());
|
||||
}
|
||||
|
||||
/**
|
||||
* AutoTool for a specific block with precomputed ToolSet data
|
||||
*
|
||||
* @param b the blockstate to mine
|
||||
* @param ts previously calculated ToolSet
|
||||
*/
|
||||
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
|
||||
mc.player.inventory.currentItem = ts.getBestSlot(b);
|
||||
}
|
||||
|
||||
static boolean throwaway(boolean select) {
|
||||
EntityPlayerSP p = Minecraft.getMinecraft().player;
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
ItemStack item = inv.get(i);
|
||||
// this usage of settings() is okay because it's only called once during pathing
|
||||
// (while creating the CalculationContext at the very beginning)
|
||||
// and then it's called during execution
|
||||
// since this function is never called during cost calculation, we don't need to migrate
|
||||
// acceptableThrowawayItems to the CalculationContext
|
||||
if (Baritone.settings().acceptableThrowawayItems.get().contains(item.getItem())) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void moveTowards(MovementState state, BlockPos pos) {
|
||||
state.setTarget(new MovementTarget(
|
||||
new Rotation(Utils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
|
||||
Utils.getBlockPosCenter(pos),
|
||||
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)).getFirst(), mc.player.rotationPitch),
|
||||
false
|
||||
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
|
||||
}
|
||||
|
||||
static Movement generateMovementFallOrDescend(BlockPos pos, BlockPos dest, CalculationContext calcContext) {
|
||||
// A
|
||||
//SA
|
||||
// A
|
||||
// B
|
||||
// C
|
||||
// D
|
||||
//if S is where you start, B needs to be air for a movementfall
|
||||
//A is plausibly breakable by either descend or fall
|
||||
//C, D, etc determine the length of the fall
|
||||
|
||||
if (!canWalkThrough(dest.down(2))) {
|
||||
//if B in the diagram aren't air
|
||||
//have to do a descend, because fall is impossible
|
||||
|
||||
//this doesn't guarantee descend is possible, it just guarantees fall is impossible
|
||||
return new MovementDescend(pos, dest.down()); // standard move out by 1 and descend by 1
|
||||
// we can't cost shortcut descend because !canWalkThrough doesn't mean canWalkOn
|
||||
}
|
||||
|
||||
// we're clear for a fall 2
|
||||
// let's see how far we can fall
|
||||
for (int fallHeight = 3; true; fallHeight++) {
|
||||
BlockPos onto = dest.down(fallHeight);
|
||||
if (onto.getY() < 0) {
|
||||
// when pathing in the end, where you could plausibly fall into the void
|
||||
// this check prevents it from getting the block at y=-1 and crashing
|
||||
break;
|
||||
}
|
||||
IBlockState ontoBlock = BlockStateInterface.get(onto);
|
||||
if (BlockStateInterface.isWater(ontoBlock.getBlock())) {
|
||||
return new MovementFall(pos, onto);
|
||||
}
|
||||
if (canWalkThrough(onto, ontoBlock)) {
|
||||
continue;
|
||||
}
|
||||
if (canWalkOn(onto, ontoBlock)) {
|
||||
if ((calcContext.hasWaterBucket() && fallHeight <= calcContext.maxFallHeightBucket() + 1) || fallHeight <= calcContext.maxFallHeightNoWater() + 1) {
|
||||
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
|
||||
return new MovementFall(pos, onto.up());
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
+20
-8
@@ -15,10 +15,10 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement;
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.bot.utils.InputOverrideHandler.Input;
|
||||
import baritone.bot.utils.Rotation;
|
||||
import baritone.utils.InputOverrideHandler.Input;
|
||||
import baritone.utils.Rotation;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.HashMap;
|
||||
@@ -93,21 +93,29 @@ public class MovementState {
|
||||
*/
|
||||
public Rotation rotation;
|
||||
|
||||
/**
|
||||
* Whether or not this target must force rotations.
|
||||
* <p>
|
||||
* {@code true} if we're trying to place or break blocks, {@code false} if we're trying to look at the movement location
|
||||
*/
|
||||
private boolean forceRotations;
|
||||
|
||||
public MovementTarget() {
|
||||
this(null, null);
|
||||
this(null, null, false);
|
||||
}
|
||||
|
||||
public MovementTarget(Vec3d position) {
|
||||
this(position, null);
|
||||
this(position, null, false);
|
||||
}
|
||||
|
||||
public MovementTarget(Rotation rotation) {
|
||||
this(null, rotation);
|
||||
public MovementTarget(Rotation rotation, boolean forceRotations) {
|
||||
this(null, rotation, forceRotations);
|
||||
}
|
||||
|
||||
public MovementTarget(Vec3d position, Rotation rotation) {
|
||||
public MovementTarget(Vec3d position, Rotation rotation, boolean forceRotations) {
|
||||
this.position = position;
|
||||
this.rotation = rotation;
|
||||
this.forceRotations = forceRotations;
|
||||
}
|
||||
|
||||
public final Optional<Vec3d> getPosition() {
|
||||
@@ -117,5 +125,9 @@ public class MovementState {
|
||||
public final Optional<Rotation> getRotation() {
|
||||
return Optional.ofNullable(this.rotation);
|
||||
}
|
||||
|
||||
public boolean hasToForceRotations() {
|
||||
return this.forceRotations;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,210 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.behavior.impl.LookBehaviorUtils;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import baritone.utils.Utils;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Objects;
|
||||
|
||||
public class MovementAscend extends Movement {
|
||||
|
||||
private int ticksWithoutPlacement = 0;
|
||||
|
||||
public MovementAscend(BlockPos src, BlockPos dest) {
|
||||
super(src, dest, new BlockPos[]{dest, src.up(2), dest.up()}, dest.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
ticksWithoutPlacement = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
IBlockState srcDown = BlockStateInterface.get(src.down());
|
||||
if (srcDown.getBlock() == Blocks.LADDER || srcDown.getBlock() == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
// we can jump from soul sand, but not from a bottom slab
|
||||
boolean jumpingFromBottomSlab = MovementHelper.isBottomSlab(srcDown);
|
||||
IBlockState toPlace = BlockStateInterface.get(positionToPlace);
|
||||
boolean jumpingToBottomSlab = MovementHelper.isBottomSlab(toPlace);
|
||||
|
||||
if (jumpingFromBottomSlab && !jumpingToBottomSlab) {
|
||||
return COST_INF;// the only thing we can ascend onto from a bottom slab is another bottom slab
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(positionToPlace, toPlace)) {
|
||||
if (!context.hasThrowaway()) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(positionToPlace, toPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
// TODO: add ability to place against .down() as well as the cardinal directions
|
||||
// useful for when you are starting a staircase without anything to place against
|
||||
// Counterpoint to the above TODO ^ you should move then pillar instead of ascend
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos against1 = positionToPlace.offset(HORIZONTALS[i]);
|
||||
if (against1.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(against1)) {
|
||||
return JUMP_ONE_BLOCK_COST + WALK_ONE_BLOCK_COST + context.placeBlockCost() + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
}
|
||||
return COST_INF;
|
||||
}
|
||||
if (BlockStateInterface.get(src.up(3)).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us
|
||||
// HOWEVER, we assume that we're standing in the start position
|
||||
// that means that src and src.up(1) are both air
|
||||
// maybe they aren't now, but they will be by the time this starts
|
||||
Block srcUp = BlockStateInterface.get(src.up(1)).getBlock();
|
||||
Block srcUp2 = BlockStateInterface.get(src.up(2)).getBlock();
|
||||
if (!(srcUp instanceof BlockFalling) || !(srcUp2 instanceof BlockFalling)) {
|
||||
// if both of those are BlockFalling, that means that by standing on src
|
||||
// (the presupposition of this Movement)
|
||||
// we have necessarily already cleared the entire BlockFalling stack
|
||||
// on top of our head
|
||||
|
||||
// but if either of them aren't BlockFalling, that means we're still in suffocation danger
|
||||
// so don't do it
|
||||
return COST_INF;
|
||||
}
|
||||
// you may think we only need to check srcUp2, not srcUp
|
||||
// however, in the scenario where glitchy world gen where unsupported sand / gravel generates
|
||||
// it's possible srcUp is AIR from the start, and srcUp2 is falling
|
||||
// and in that scenario, when we arrive and break srcUp2, that lets srcUp3 fall on us and suffocate us
|
||||
}
|
||||
double walk = WALK_ONE_BLOCK_COST;
|
||||
if (jumpingToBottomSlab && !jumpingFromBottomSlab) {
|
||||
return walk + getTotalHardnessOfBlocksToBreak(context); // we don't hit space we just walk into the slab
|
||||
}
|
||||
if (!jumpingToBottomSlab && toPlace.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
|
||||
}
|
||||
// we hit space immediately on entering this action
|
||||
return Math.max(JUMP_ONE_BLOCK_COST, walk) + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
// TODO incorporate some behavior from ActionClimb (specifically how it waited until it was at most 1.2 blocks away before starting to jump
|
||||
// for efficiency in ascending minimal height staircases, which is just repeated MovementAscend, so that it doesn't bonk its head on the ceiling repeatedly)
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
IBlockState jumpingOnto = BlockStateInterface.get(positionToPlace);
|
||||
if (!MovementHelper.canWalkOn(positionToPlace, jumpingOnto)) {
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos anAgainst = positionToPlace.offset(HORIZONTALS[i]);
|
||||
if (anAgainst.equals(src)) {
|
||||
continue;
|
||||
}
|
||||
if (MovementHelper.canPlaceAgainst(anAgainst)) {
|
||||
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
|
||||
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
|
||||
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
|
||||
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
|
||||
|
||||
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
|
||||
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionToPlace)) {
|
||||
ticksWithoutPlacement++;
|
||||
state.setInput(InputOverrideHandler.Input.SNEAK, true);
|
||||
if (player().isSneaking()) {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
|
||||
}
|
||||
if (ticksWithoutPlacement > 10) {
|
||||
// After 10 ticks without placement, we might be standing in the way, move back
|
||||
state.setInput(InputOverrideHandler.Input.MOVE_BACK, true);
|
||||
}
|
||||
} else {
|
||||
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true); // break whatever replaceable block is in the way
|
||||
}
|
||||
System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
|
||||
});
|
||||
return state;
|
||||
}
|
||||
}
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
if (MovementHelper.isBottomSlab(jumpingOnto)) {
|
||||
if (!MovementHelper.isBottomSlab(src.down())) {
|
||||
return state; // don't jump while walking from a non double slab into a bottom slab
|
||||
}
|
||||
}
|
||||
|
||||
if (headBonkClear()) {
|
||||
return state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
|
||||
int xAxis = Math.abs(src.getX() - dest.getX()); // either 0 or 1
|
||||
int zAxis = Math.abs(src.getZ() - dest.getZ()); // either 0 or 1
|
||||
double flatDistToNext = xAxis * Math.abs((dest.getX() + 0.5D) - player().posX) + zAxis * Math.abs((dest.getZ() + 0.5D) - player().posZ);
|
||||
double sideDist = zAxis * Math.abs((dest.getX() + 0.5D) - player().posX) + xAxis * Math.abs((dest.getZ() + 0.5D) - player().posZ);
|
||||
// System.out.println(flatDistToNext + " " + sideDist);
|
||||
if (flatDistToNext > 1.2 || sideDist > 0.2) {
|
||||
return state;
|
||||
}
|
||||
|
||||
// Once we are pointing the right way and moving, start jumping
|
||||
// This is slightly more efficient because otherwise we might start jumping before moving, and fall down without moving onto the block we want to jump onto
|
||||
// Also wait until we are close enough, because we might jump and hit our head on an adjacent block
|
||||
return state.setInput(InputOverrideHandler.Input.JUMP, true);
|
||||
}
|
||||
|
||||
private boolean headBonkClear() {
|
||||
BlockPos startUp = src.up(2);
|
||||
for (int i = 0; i < 4; i++) {
|
||||
BlockPos check = startUp.offset(EnumFacing.byHorizontalIndex(i));
|
||||
if (!MovementHelper.canWalkThrough(check)) {
|
||||
// We might bonk our head
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
+28
-26
@@ -15,41 +15,50 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.bot.utils.InputOverrideHandler;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.movement.MovementState.MovementStatus;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.BlockVine;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
public MovementDescend(BlockPos start, BlockPos end) {
|
||||
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, new BlockPos[]{end.down()});
|
||||
super(start, end, new BlockPos[]{end.up(2), end.up(), end}, end.down());
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset() {
|
||||
super.reset();
|
||||
numTicks = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0])) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(positionToPlace)) {
|
||||
return COST_INF;
|
||||
}
|
||||
Block tmp1 = BlockStateInterface.get(dest).getBlock();
|
||||
if (tmp1 instanceof BlockLadder || tmp1 instanceof BlockVine) {
|
||||
if (tmp1 == Blocks.LADDER || tmp1 == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
// we walk half the block plus 0.3 to get to the edge, then we walk the other 0.2 while simultaneously falling (math.max because of how it's in parallel)
|
||||
double walk = WALK_OFF_BLOCK_COST;
|
||||
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
// use this ratio to apply the soul sand speed penalty to our 0.8 block distance
|
||||
walk *= WALK_ONE_OVER_SOUL_SAND_COST / WALK_ONE_BLOCK_COST;
|
||||
walk = WALK_ONE_OVER_SOUL_SAND_COST;
|
||||
}
|
||||
return walk + Math.max(FALL_N_BLOCKS_COST[1], CENTER_AFTER_FALL_COST) + getTotalHardnessOfBlocksToBreak(context);
|
||||
}
|
||||
@@ -59,17 +68,13 @@ public class MovementDescend extends Movement {
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
state.setStatus(MovementStatus.RUNNING);
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
BlockPos playerFeet = playerFeet();
|
||||
if (playerFeet.equals(dest)) {
|
||||
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.01) {
|
||||
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads
|
||||
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
@@ -85,9 +90,6 @@ public class MovementDescend extends Movement {
|
||||
double fromStart = Math.sqrt(x * x + z * z);
|
||||
if (!playerFeet.equals(dest) || ab > 0.25) {
|
||||
BlockPos fakeDest = new BlockPos(dest.getX() * 2 - src.getX(), dest.getY(), dest.getZ() * 2 - src.getZ());
|
||||
double diffX2 = player().posX - (fakeDest.getX() + 0.5);
|
||||
double diffZ2 = player().posZ - (fakeDest.getZ() + 0.5);
|
||||
double d = Math.sqrt(diffX2 * diffX2 + diffZ2 * diffZ2);
|
||||
if (numTicks++ < 20) {
|
||||
MovementHelper.moveTowards(state, fakeDest);
|
||||
if (fromStart > 1.25) {
|
||||
+61
-57
@@ -15,13 +15,16 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.bot.pathing.movement.movements;
|
||||
package baritone.pathing.movement.movements;
|
||||
|
||||
import baritone.bot.pathing.movement.CalculationContext;
|
||||
import baritone.bot.pathing.movement.Movement;
|
||||
import baritone.bot.pathing.movement.MovementHelper;
|
||||
import baritone.bot.pathing.movement.MovementState;
|
||||
import baritone.bot.utils.BlockStateInterface;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.InputOverrideHandler;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockMagma;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -29,6 +32,7 @@ import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public class MovementDiagonal extends Movement {
|
||||
|
||||
@@ -39,109 +43,109 @@ public class MovementDiagonal extends Movement {
|
||||
// super(start, start.offset(dir1).offset(dir2), new BlockPos[]{start.offset(dir1), start.offset(dir1).up(), start.offset(dir2), start.offset(dir2).up(), start.offset(dir1).offset(dir2), start.offset(dir1).offset(dir2).up()}, new BlockPos[]{start.offset(dir1).offset(dir2).down()});
|
||||
}
|
||||
|
||||
public MovementDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) {
|
||||
private MovementDiagonal(BlockPos start, BlockPos dir1, BlockPos dir2, EnumFacing drr2) {
|
||||
this(start, dir1.offset(drr2), dir1, dir2);
|
||||
}
|
||||
|
||||
public MovementDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) {
|
||||
super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()}, new BlockPos[]{end.down()});
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
switch (state.getStatus()) {
|
||||
case WAITING:
|
||||
case RUNNING:
|
||||
break;
|
||||
default:
|
||||
return state;
|
||||
}
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
player().setSprinting(true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
return state;
|
||||
private MovementDiagonal(BlockPos start, BlockPos end, BlockPos dir1, BlockPos dir2) {
|
||||
super(start, end, new BlockPos[]{dir1, dir1.up(), dir2, dir2.up(), end, end.up()});
|
||||
}
|
||||
|
||||
@Override
|
||||
protected double calculateCost(CalculationContext context) {
|
||||
Block fromDown = BlockStateInterface.get(src.down()).getBlock();
|
||||
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[4]) || !MovementHelper.canWalkThrough(positionsToBreak[5])) {
|
||||
return COST_INF;
|
||||
}
|
||||
IBlockState destWalkOn = BlockStateInterface.get(positionsToPlace[0]);
|
||||
if (!MovementHelper.canWalkOn(positionsToPlace[0], destWalkOn)) {
|
||||
BlockPos destDown = dest.down();
|
||||
IBlockState destWalkOn = BlockStateInterface.get(destDown);
|
||||
if (!MovementHelper.canWalkOn(destDown, destWalkOn)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double multiplier = WALK_ONE_BLOCK_COST;
|
||||
|
||||
// for either possible soul sand, that affects half of our walking
|
||||
// For either possible soul sand, that affects half of our walking
|
||||
if (destWalkOn.getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
if (BlockStateInterface.get(src.down()).getBlock().equals(Blocks.SOUL_SAND)) {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
|
||||
if (BlockStateInterface.get(positionsToBreak[2].down()).getBlock() instanceof BlockMagma) {
|
||||
Block cuttingOver1 = BlockStateInterface.get(positionsToBreak[2].down()).getBlock();
|
||||
if (cuttingOver1 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver1)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (BlockStateInterface.get(positionsToBreak[4].down()).getBlock() instanceof BlockMagma) {
|
||||
Block cuttingOver2 = BlockStateInterface.get(positionsToBreak[4].down()).getBlock();
|
||||
if (cuttingOver2 instanceof BlockMagma || BlockStateInterface.isLava(cuttingOver2)) {
|
||||
return COST_INF;
|
||||
}
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1]);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2]) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3]);
|
||||
IBlockState pb0 = BlockStateInterface.get(positionsToBreak[0]);
|
||||
IBlockState pb1 = BlockStateInterface.get(positionsToBreak[1]);
|
||||
IBlockState pb2 = BlockStateInterface.get(positionsToBreak[2]);
|
||||
IBlockState pb3 = BlockStateInterface.get(positionsToBreak[3]);
|
||||
double optionA = MovementHelper.getMiningDurationTicks(context, positionsToBreak[0], pb0, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[1], pb1, true);
|
||||
double optionB = MovementHelper.getMiningDurationTicks(context, positionsToBreak[2], pb2, false) + MovementHelper.getMiningDurationTicks(context, positionsToBreak[3], pb3, true);
|
||||
if (optionA != 0 && optionB != 0) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (optionA == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[2]))) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[3]))) {
|
||||
if (MovementHelper.avoidWalkingInto(pb2.getBlock()) || MovementHelper.avoidWalkingInto(pb3.getBlock())) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (optionB == 0) {
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[0]))) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(positionsToBreak[1]))) {
|
||||
if (MovementHelper.avoidWalkingInto(pb0.getBlock()) || MovementHelper.avoidWalkingInto(pb1.getBlock())) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
if (BlockStateInterface.isWater(src) || BlockStateInterface.isWater(dest)) {
|
||||
// ignore previous multiplier
|
||||
// whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
|
||||
// not even touching the blocks below
|
||||
// Ignore previous multiplier
|
||||
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
|
||||
// Not even touching the blocks below
|
||||
multiplier = WALK_ONE_IN_WATER_COST;
|
||||
}
|
||||
if (optionA != 0 || optionB != 0) {
|
||||
multiplier *= SQRT_2 - 0.001; // TODO tune
|
||||
}
|
||||
if (multiplier == WALK_ONE_BLOCK_COST && context.canSprint()) {
|
||||
// if we aren't edging around anything, and we aren't in water or soul sand
|
||||
// we can sprint =D
|
||||
// If we aren't edging around anything, and we aren't in water or soul sand
|
||||
// We can sprint =D
|
||||
multiplier = SPRINT_ONE_BLOCK_COST;
|
||||
}
|
||||
return multiplier * SQRT_2;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
super.updateState(state);
|
||||
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (playerFeet().equals(dest)) {
|
||||
state.setStatus(MovementState.MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (!BlockStateInterface.isLiquid(playerFeet())) {
|
||||
state.setInput(InputOverrideHandler.Input.SPRINT, true);
|
||||
}
|
||||
MovementHelper.moveTowards(state, dest);
|
||||
return state;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected boolean prepared(MovementState state) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlockPos> toBreak() {
|
||||
public List<BlockPos> toBreak() {
|
||||
if (toBreakCached != null) {
|
||||
return toBreakCached;
|
||||
}
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
for (int i = 4; i < 6; i++) {
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[i])) {
|
||||
result.add(positionsToBreak[i]);
|
||||
@@ -152,11 +156,11 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
@Override
|
||||
public ArrayList<BlockPos> toWalkInto() {
|
||||
public List<BlockPos> toWalkInto() {
|
||||
if (toWalkIntoCached == null) {
|
||||
toWalkIntoCached = new ArrayList<>();
|
||||
}
|
||||
ArrayList<BlockPos> result = new ArrayList<>();
|
||||
List<BlockPos> result = new ArrayList<>();
|
||||
for (int i = 0; i < 4; i++) {
|
||||
if (!MovementHelper.canWalkThrough(positionsToBreak[i])) {
|
||||
result.add(positionsToBreak[i]);
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user