Compare commits
57 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
82d09a536d | ||
|
|
6e49adea33 | ||
|
|
f85afdbc70 | ||
|
|
563028a5b3 | ||
|
|
d5c317b88b | ||
|
|
c59ec9da10 | ||
|
|
3a675836da | ||
|
|
7e0fc81246 | ||
|
|
f970f932c7 | ||
|
|
52d2741f52 | ||
|
|
7bc6765cac | ||
|
|
85b2aea6e9 | ||
|
|
c6ba5481d9 | ||
|
|
81f47d5632 | ||
|
|
9b1440ed2c | ||
|
|
2a8dcee028 | ||
|
|
277ba3643c | ||
|
|
e5fbaf60f3 | ||
|
|
0deb854e1b | ||
|
|
8268e3ec1b | ||
|
|
af91da6a28 | ||
|
|
9a15a65ad5 | ||
|
|
0cbe9f81c8 | ||
|
|
42afd2dd54 | ||
|
|
315929f31c | ||
|
|
358aa80280 | ||
|
|
1dd9e11994 | ||
|
|
5a8f02c944 | ||
|
|
f248a5b677 | ||
|
|
e4a49c5529 | ||
|
|
449b44ba50 | ||
|
|
a00eec402e | ||
|
|
717779f742 | ||
|
|
6f843bd24d | ||
|
|
d79fbea433 | ||
|
|
4d22c10ddb | ||
|
|
1ea92a6092 | ||
|
|
66eba84d06 | ||
|
|
92e39b5d1d | ||
|
|
0ddc47f473 | ||
|
|
ddfeca6947 | ||
|
|
6bd2e90cfd | ||
|
|
82505ddb01 | ||
|
|
2790d1d308 | ||
|
|
11e503a022 | ||
|
|
6fe49380ba | ||
|
|
1f2e267e3d | ||
|
|
4cf6783622 | ||
|
|
82d77a7bac | ||
|
|
841a927033 | ||
|
|
5a16561954 | ||
|
|
e2cc51908b | ||
|
|
1390e04435 | ||
|
|
84d961cbab | ||
|
|
87b9d3915c | ||
|
|
c38d17563d | ||
|
|
0c2af85ac0 |
1
.gitattributes
vendored
1
.gitattributes
vendored
@@ -1 +0,0 @@
|
||||
* text=auto
|
||||
1
.github/ISSUE_TEMPLATE.md
vendored
Normal file
1
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1 @@
|
||||
<!-- No UwU's or OwO's allowed -->
|
||||
25
.github/ISSUE_TEMPLATE/bug.md
vendored
25
.github/ISSUE_TEMPLATE/bug.md
vendored
@@ -1,25 +0,0 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Please file a separate report for each issue
|
||||
title: Please add a brief but descriptive title
|
||||
labels: bug
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Some information
|
||||
Operating system:
|
||||
Java version:
|
||||
Minecraft version:
|
||||
Baritone version:
|
||||
Forge mods (if used):
|
||||
|
||||
## Exception, error or logs
|
||||
You can find your logs in `%appdata%/.minecraft/logs/` (Windows) or `/Library/Application\ Support/minecraft/logs` (Mac).
|
||||
|
||||
## How to reproduce
|
||||
Add your steps to reproduce the issue/bug experienced here.
|
||||
|
||||
## Final checklist
|
||||
- [ ] I have included the version of Minecraft I'm running, baritone's version and forge mods (if used).
|
||||
- [ ] I have included logs, exceptions and / or steps to reproduce the issue.
|
||||
- [ ] I have not used any OwO's or UwU's in this issue.
|
||||
13
.github/ISSUE_TEMPLATE/question.md
vendored
13
.github/ISSUE_TEMPLATE/question.md
vendored
@@ -1,13 +0,0 @@
|
||||
---
|
||||
name: Question
|
||||
about: Please file a separate report for each question
|
||||
title: Please add a brief but descriptive title
|
||||
labels: question
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## What do you need help with?
|
||||
With as much detail as possible, describe your question and what you may need help with.
|
||||
|
||||
## Final checklist
|
||||
- [ ] I have not used any OwO's or UwU's in this issue.
|
||||
19
.github/ISSUE_TEMPLATE/suggestion.md
vendored
19
.github/ISSUE_TEMPLATE/suggestion.md
vendored
@@ -1,19 +0,0 @@
|
||||
---
|
||||
name: Suggestion
|
||||
about: Please file a separate report for each suggestion
|
||||
title: Please add a brief but descriptive title
|
||||
labels: enhancement
|
||||
assignees: ''
|
||||
---
|
||||
|
||||
## Describe your suggestion
|
||||
With as much detail as possible, describe what your suggestion would do for Baritone.
|
||||
|
||||
## Settings
|
||||
If applicable, what settings/customizability should be offered to tweak the functionality of your suggestion.
|
||||
|
||||
## Context
|
||||
Describe how your suggestion would improve Baritone, or the reason behind it being added.
|
||||
|
||||
## Final checklist
|
||||
- [ ] I have not used any OwO's or UwU's in this issue.
|
||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -11,6 +11,8 @@ build/
|
||||
classes/
|
||||
*.class
|
||||
|
||||
/out
|
||||
|
||||
# IntelliJ Files
|
||||
.idea/
|
||||
*.iml
|
||||
|
||||
@@ -10,7 +10,7 @@ install:
|
||||
|
||||
script:
|
||||
- docker run --rm cabaletta/baritone ./gradlew javadoc
|
||||
- docker run --name baritone cabaletta/baritone /bin/sh -c "set -e; /sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runClient"
|
||||
- docker run --name baritone cabaletta/baritone /bin/sh -c "/sbin/start-stop-daemon --start --quiet --pidfile /tmp/custom_xvfb_99.pid --make-pidfile --background --exec /usr/bin/Xvfb -- :99 -screen 0 128x128x24 -ac +extension GLX +render; DISPLAY=:99 BARITONE_AUTO_TEST=true ./gradlew runAutoTest; cat /code/autotest/success"
|
||||
- docker cp baritone:/code/dist dist
|
||||
- ls dist
|
||||
- cat dist/checksums.txt
|
||||
|
||||
39
README.md
39
README.md
@@ -1,44 +1,37 @@
|
||||
# Baritone
|
||||
[](https://travis-ci.com/cabaletta/baritone/)
|
||||
[](https://github.com/cabaletta/baritone/releases/)
|
||||
[](https://travis-ci.com/cabaletta/baritone)
|
||||
[](https://github.com/cabaletta/baritone/releases)
|
||||
[](LICENSE)
|
||||
[](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&utm_medium=referral&utm_content=cabaletta/baritone&utm_campaign=Badge_Grade)
|
||||
[](http://hits.dwyl.com/cabaletta/baritone/)
|
||||
[](https://github.com/cabaletta/baritone/releases/)
|
||||
[](https://github.com/cabaletta/baritone/tree/master/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.13.2/)
|
||||
[](https://github.com/cabaletta/baritone/tree/1.14.4/)
|
||||
[](http://hits.dwyl.com/cabaletta/baritone)
|
||||
[](https://github.com/cabaletta/baritone/blob/master/CODE_OF_CONDUCT.md)
|
||||
[](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle)
|
||||
[](https://github.com/cabaletta/baritone/issues/)
|
||||
[](https://github.com/cabaletta/baritone/issues)
|
||||
[](https://github.com/cabaletta/baritone/issues/)
|
||||
[](https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed)
|
||||
[](https://github.com/cabaletta/baritone/pulls/)
|
||||

|
||||

|
||||

|
||||

|
||||
[](https://minecraft.gamepedia.com/1.13.2)
|
||||
[](https://github.com/cabaletta/baritone/graphs/contributors/)
|
||||
[](https://github.com/cabaletta/baritone/commit/)
|
||||
[](https://impactdevelopment.github.io/)
|
||||
[](https://github.com/fr1kin/ForgeHax/)
|
||||
[](https://gitlab.com/emc-mods-indrit/baritone_api)
|
||||
[](https://impactdevelopment.github.io/)
|
||||
[](https://wweclient.com/)
|
||||
[](https://github.com/zeroeightysix/KAMI/)
|
||||
[](https://futureclient.net/)
|
||||
[](http://forthebadge.com/)
|
||||
[](http://forthebadge.com/)
|
||||
[](https://github.com/fr1kin/ForgeHax)
|
||||
[](http://forthebadge.com)
|
||||
[](http://forthebadge.com)
|
||||
|
||||
A Minecraft pathfinder bot.
|
||||
|
||||
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4. There's a [showcase video](https://www.youtube.com/watch?v=yI8hgW_m6dQ) made by @Adovin#3153 on Baritone's integration into Impact. [Here's](https://www.youtube.com/watch?v=StquF69-_wI) a video I made showing off what it can do.
|
||||
|
||||
The easiest way to install Baritone is to install [Impact](https://impactdevelopment.github.io/), which comes with Baritone. The second easiest way (for 1.12.2 only) is to install the v1.2.* forge api jar from [releases](https://github.com/cabaletta/baritone/releases). Otherwise, see [Installation & setup](SETUP.md). Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
|
||||
For 1.14.4, [click here](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1). Or [with optifine](https://github.com/cabaletta/baritone/issues/797).
|
||||
|
||||
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
|
||||
the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2 and 1.13.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
the original version of the bot for Minecraft 1.8.9, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
|
||||
|
||||
Have committed at least once a day from Aug 1 2018 to Aug 1 2019.
|
||||
Have committed at least once a day for the last 8 months =D 🦀
|
||||
|
||||
1Leijurv3DWTrGAfmmiTphjhXLvQiHg7K2
|
||||
|
||||
@@ -54,7 +47,7 @@ Here are some links to help to get started:
|
||||
|
||||
- [Settings](https://baritone.leijurv.com/baritone/api/Settings.html#field.detail)
|
||||
|
||||
- [Usage (chat control)](USAGE.md)
|
||||
- [Baritone chat control usage](USAGE.md)
|
||||
|
||||
# API
|
||||
|
||||
@@ -75,11 +68,11 @@ BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAnd
|
||||
|
||||
## Can I use Baritone as a library in my custom utility client?
|
||||
|
||||
That's what it's for, sure! (As long as usage is in compliance with the LGPL 3.0 License)
|
||||
That's what it's for, sure! (As long as usage is in compliance with the LGPL 3 License)
|
||||
|
||||
## How is it so fast?
|
||||
|
||||
Magic. (Hours of [leijurv](https://github.com/leijurv/) enduring excruciating pain)
|
||||
Magic. (Hours of [leijurv](https://github.com/leijurv) enduring excruciating pain)
|
||||
|
||||
## Why is it called Baritone?
|
||||
|
||||
|
||||
8
SETUP.md
8
SETUP.md
@@ -1,18 +1,10 @@
|
||||
# Installation
|
||||
|
||||
The easiest way to install Baritone is to install [Impact](https://impactdevelopment.github.io/), which comes with Baritone.
|
||||
|
||||
For 1.14.4, [click here](https://www.dropbox.com/s/rkml3hjokd3qv0m/1.14.4-Baritone.zip?dl=1).
|
||||
|
||||
Once Baritone is installed, look [here](USAGE.md) for instructions on how to use it.
|
||||
|
||||
## Prebuilt official releases
|
||||
These releases are not always completely up to date with latest features, and are only released from `master`. (so if you want `backfill-2` branch for example, you'll have to build it yourself)
|
||||
|
||||
Link to the releases page: [Releases](https://github.com/cabaletta/baritone/releases)
|
||||
|
||||
v1.2.* is for 1.12.2, v1.3.* is for 1.13.2
|
||||
|
||||
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
|
||||
|
||||
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone .` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
|
||||
|
||||
50
USAGE.md
50
USAGE.md
@@ -2,44 +2,49 @@
|
||||
|
||||
# Prefix
|
||||
|
||||
Baritone's chat control prefix is `#` by default. In Impact, you can also use `.b` as a prefix. (for example, `.b click` instead of `#click`)
|
||||
Baritone commands can by default be typed in the chatbox. However if you make a typo, like typing "gola 10000 10000" instead of goal it goes into public chat, which is bad.
|
||||
|
||||
Therefore you can use a prefix before your messages.
|
||||
|
||||
On Baritone v1.1.0 and newer: The prefix is `#` by default. Anything beginning with `#` isn't sent, and is only interpreted by Baritone.
|
||||
For older than v1.1.0, `#` must be enabled by toggling on the `prefix` setting.
|
||||
|
||||
**Only** in Impact is `.b` also a valid prefix. In 4.4, `#` does **not** work, neither does saying the commands directly in chat. `#` works by default in 4.5 (not 4.4).
|
||||
|
||||
Other clients like Kami and Asuna have their own custom things (like `-path`), and can disable direct chat control entirely.
|
||||
|
||||
Baritone commands can also by default be typed in the chatbox. However if you make a typo, like typing "gola 10000 10000" instead of "goal" it goes into public chat, which is bad, so using `#` is suggested.
|
||||
|
||||
To disable direct chat control (with no prefix), turn off the `chatControl` setting. To disable chat control with the `#` prefix, turn off the `prefixControl` setting. In Impact, `.b` cannot be disabled. Be careful that you don't leave yourself with all control methods disabled (if you do, reset your settings by deleting the file `minecraft/baritone/settings.txt` and relaunching).
|
||||
|
||||
# Commands
|
||||
|
||||
**All** of these commands may need a prefix before them, as above ^.
|
||||
|
||||
`help` for (rudimentary) help. You can see what it says [here](https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/utils/ExampleBaritoneControl.java#L47).
|
||||
`help` for (rudimentary) help. You can see what it says [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java#L53).
|
||||
|
||||
To toggle a boolean setting, just say its name in chat (for example saying `allowBreak` toggles whether Baritone will consider breaking blocks). For a numeric setting, say its name then the new value (like `primaryTimeoutMS 250`). It's case insensitive. To reset a setting to its default value, say `acceptableThrowawayItems reset`. To reset all settings, say `reset`. To see all settings that have been modified from their default values, say `modified`.
|
||||
|
||||
|
||||
|
||||
|
||||
Some common examples:
|
||||
- `thisway 1000` then `path` to go in the direction you're facing for a thousand blocks
|
||||
- `goal x y z` or `goal x z` or `goal y`, then `path` to set a goal to a certain coordinate then path to it
|
||||
- `goto x y z` or `goto x z` or `goto y` to go to a certain coordinate (in a single step, starts going immediately)
|
||||
- `goal x y z` or `goal x z` or `goal y`, then `path` to go to a certain coordinate
|
||||
- `goal` to set the goal to your player's feet
|
||||
- `goal clear` to clear the goal
|
||||
- `cancel` or `stop` to stop everything
|
||||
- `goto portal` or `goto ender_chest` or `goto block_type` to go to a block. (in Impact, `.goto` is an alias for `.b goto` for the most part)
|
||||
- `mine diamond_ore` to mine diamond ore (turn on the setting `legitMine` to only mine ores that it can actually see. It will explore randomly around y=11 until it finds them.) An amount of blocks can also be specified, for example, `mine diamond_ore 64`.
|
||||
- `click` to click your destination on the screen. Right click path to on top of the block, left click to path into it (either at foot level or eye level), and left click and drag to clear all blocks from an area.
|
||||
- `follow playerName` to follow a player. `followplayers` to follow any players in range (combine with Kill Aura for a fun time). `followentities` to follow any entities. `followentity pig` to follow entities of a specific type.
|
||||
- `mine diamond_ore` to mine diamond ore (turn on the setting `legitMine` to only mine ores that it can actually see. It will explore randomly around y=11 until it finds them.)
|
||||
- `click` to click your destination on the screen. left click to path into it, right click to path on top of it. left click and drag to clear an area.
|
||||
- `follow playerName` to follow a player. `follow` to follow the entity you're looking at (only works if it hitting range). `followplayers` to follow any players in range (combine with Kill Aura for a fun time).
|
||||
- `save waypointName` to save a waypoint. `goto waypointName` to go to it.
|
||||
- `build` to build a schematic. `build blah` will load `schematics/blah.schematic` and build it with the origin being your player feet. `build blah x y z` to set the origin. Any of those can be relative to your player (`~ 69 ~-420` would build at x=player x, y=69, z=player z-420).
|
||||
- `schematica` to build the schematic that is currently open in schematica
|
||||
- `tunnel` to dig just straight ahead and make a tunnel
|
||||
- `farm` to automatically harvest, replant, or bone meal crops
|
||||
- `axis` to go to an axis or diagonal axis at y=120 (`axisHeight` is a configurable setting, defaults to 120).
|
||||
- `explore x z` to explore the world from the origin of x,z. Leave out x and z to default to player feet. This will continually path towards the closest chunk to the origin that it's never seen before. `explorefilter filter.json` with optional invert can be used to load in a list of chunks to load.
|
||||
- `invert` to invert the current goal and path. This gets as far away from it as possible, instead of as close as possible. For example, do `goal` then `invert` to run as far as possible from where you're standing at the start.
|
||||
- `render` to rerender the world in case `renderCachedChunks` is being glitchy
|
||||
- `version` to get the version of Baritone you're running
|
||||
- `damn` daniel
|
||||
- `build` to build a schematic. `build blah` will load `schematics/blah.schematic` and build it with the origin being your player feet. `build blah x y z` to set the origin. Any of those can be relative to your player (`~ 69 ~-420` would build at x=player x, y=69, z=player z-420).
|
||||
|
||||
|
||||
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/utils/ExampleBaritoneControl.java).
|
||||
For the rest of the commands, you can take a look at the code [here](https://github.com/cabaletta/baritone/blob/master/src/main/java/baritone/utils/ExampleBaritoneControl.java).
|
||||
|
||||
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>. If you find HTML easier to read than Javadoc, you can look <a href="https://baritone.leijurv.com/baritone/api/Settings.html#field.detail">here</a>.
|
||||
|
||||
@@ -49,23 +54,18 @@ There are about a hundred settings, but here are some fun / interesting / import
|
||||
- `allowPlace`
|
||||
- `allowParkour`
|
||||
- `allowParkourPlace`
|
||||
- `blockPlacementPenalty`
|
||||
- `renderCachedChunks` (and `cachedChunksOpacity`) <-- very fun but you need a beefy computer
|
||||
- `avoidance` (avoidance of mobs / mob spawners)
|
||||
- `avoidance`
|
||||
- `legitMine`
|
||||
- `followRadius`
|
||||
- `backfill` (fill in tunnels behind you)
|
||||
- `buildInLayers`
|
||||
- `buildRepeatDistance` and `buildRepeatDirection`
|
||||
- `worldExploringChunkOffset`
|
||||
- `acceptableThrowawayItems`
|
||||
- `blocksToAvoidBreaking`
|
||||
|
||||
|
||||
|
||||
|
||||
# Troubleshooting / common issues
|
||||
|
||||
## Baritone highlights a block in green but gets completely stuck? Also I'm using Baritone with Future?
|
||||
Baritone is trying to right click to place a block there, but it can't since there's a conflicting mixin. Baritone can't force click right click when Future is also installed. Left click **does work** on recent Baritone even with Future, however. For now, turn off `allowPlace` and Baritone will only search for paths that don't require placing blocks to complete. `allowBreak` can remain on.
|
||||
|
||||
## Why doesn't Baritone respond to any of my chat commands?
|
||||
This could be one of many things.
|
||||
|
||||
|
||||
91
build.gradle
91
build.gradle
@@ -16,33 +16,33 @@
|
||||
*/
|
||||
|
||||
group 'baritone'
|
||||
version '1.2.9'
|
||||
version '1.3.1'
|
||||
|
||||
buildscript {
|
||||
repositories {
|
||||
jcenter()
|
||||
maven {
|
||||
name = 'forge'
|
||||
url = 'http://files.minecraftforge.net/maven'
|
||||
}
|
||||
maven {
|
||||
name = 'SpongePowered'
|
||||
url = 'http://repo.spongepowered.org/maven'
|
||||
name = 'impactdevelopment-repo'
|
||||
url = 'https://impactdevelopment.github.io/maven/'
|
||||
}
|
||||
jcenter()
|
||||
}
|
||||
|
||||
dependencies {
|
||||
classpath 'net.minecraftforge.gradle:ForgeGradle:2.3-SNAPSHOT'
|
||||
classpath 'org.spongepowered:mixingradle:0.6-SNAPSHOT'
|
||||
classpath group: 'com.github.ImpactDevelopment', name: 'ForgeGradle', version: '3.0.115'
|
||||
classpath group: 'com.github.ImpactDevelopment', name: 'MixinGradle', version: '0.6.2'
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
import baritone.gradle.task.CreateDistTask
|
||||
import baritone.gradle.task.ProguardTask
|
||||
import org.apache.tools.ant.taskdefs.condition.Os
|
||||
|
||||
apply plugin: 'java'
|
||||
apply plugin: 'net.minecraftforge.gradle.tweaker-client'
|
||||
apply plugin: 'net.minecraftforge.gradle'
|
||||
apply plugin: 'org.spongepowered.mixin'
|
||||
|
||||
sourceCompatibility = targetCompatibility = '1.8'
|
||||
@@ -52,27 +52,67 @@ compileJava {
|
||||
}
|
||||
|
||||
sourceSets {
|
||||
launch {
|
||||
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
}
|
||||
|
||||
schematica_api {
|
||||
api {
|
||||
compileClasspath += main.compileClasspath
|
||||
}
|
||||
|
||||
main {
|
||||
compileClasspath += schematica_api.output
|
||||
compileClasspath += api.output
|
||||
}
|
||||
test {
|
||||
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
}
|
||||
launch {
|
||||
compileClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
runtimeClasspath += main.compileClasspath + main.runtimeClasspath + main.output
|
||||
}
|
||||
}
|
||||
|
||||
minecraft {
|
||||
version = '1.12.2'
|
||||
mappings = 'stable_39'
|
||||
tweakClass = 'baritone.launch.BaritoneTweaker'
|
||||
runDir = 'run'
|
||||
task sourceJar(type: Jar, dependsOn: classes) {
|
||||
classifier = 'sources'
|
||||
from sourceSets.api.allSource
|
||||
}
|
||||
|
||||
// The sources jar should use SRG names not MCP to ensure compatibility with all mappings
|
||||
makeObfSourceJar = true
|
||||
minecraft {
|
||||
mappings channel: 'snapshot', version: '20190307-1.13.1'
|
||||
reobfMappings 'notch'
|
||||
|
||||
runs {
|
||||
client {
|
||||
workingDirectory project.file('run')
|
||||
source sourceSets.launch
|
||||
|
||||
main 'baritone.launch.LaunchTesting'
|
||||
|
||||
environment 'assetIndex', '{asset_index}'
|
||||
environment 'assetDirectory', downloadAssets.output
|
||||
environment 'nativesDirectory', extractNatives.output
|
||||
|
||||
environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
|
||||
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
jvmArgs "-XstartOnFirstThread"
|
||||
}
|
||||
}
|
||||
|
||||
autoTest {
|
||||
workingDirectory project.file('autotest')
|
||||
source sourceSets.launch
|
||||
|
||||
main 'baritone.launch.LaunchTesting'
|
||||
|
||||
environment 'assetIndex', '{asset_index}'
|
||||
environment 'assetDirectory', downloadAssets.output
|
||||
environment 'nativesDirectory', extractNatives.output
|
||||
|
||||
environment 'tweakClass', 'baritone.launch.BaritoneTweaker'
|
||||
environment 'BARITONE_AUTO_TEST', 'true'
|
||||
|
||||
if (Os.isFamily(Os.FAMILY_MAC)) {
|
||||
jvmArgs "-XstartOnFirstThread"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
repositories {
|
||||
@@ -90,6 +130,12 @@ repositories {
|
||||
}
|
||||
|
||||
dependencies {
|
||||
minecraft 'com.github.ImpactDevelopment:Vanilla:1.13.2'
|
||||
|
||||
runtime launchCompile('net.minecraft:launchwrapper:1.12') {
|
||||
exclude module: 'lwjgl'
|
||||
}
|
||||
runtime launchCompile('org.ow2.asm:asm-debug-all:5.2')
|
||||
runtime launchCompile('com.github.ImpactDevelopment:SimpleTweaker:1.2')
|
||||
runtime launchCompile('org.spongepowered:mixin:0.7.11-SNAPSHOT') {
|
||||
// Mixin includes a lot of dependencies that are too up-to-date
|
||||
@@ -99,6 +145,7 @@ dependencies {
|
||||
exclude module: 'commons-io'
|
||||
exclude module: 'log4j-core'
|
||||
}
|
||||
|
||||
testImplementation 'junit:junit:4.12'
|
||||
}
|
||||
|
||||
|
||||
@@ -40,17 +40,13 @@ class BaritoneGradleTask extends DefaultTask {
|
||||
PROGUARD_STANDALONE_CONFIG = "standalone.pro",
|
||||
PROGUARD_EXPORT_PATH = "proguard_out.jar",
|
||||
|
||||
TEMP_LIBRARY_DIR = "tempLibraries/",
|
||||
|
||||
ARTIFACT_STANDARD = "%s-%s.jar",
|
||||
ARTIFACT_UNOPTIMIZED = "%s-unoptimized-%s.jar",
|
||||
ARTIFACT_API = "%s-api-%s.jar",
|
||||
ARTIFACT_STANDALONE = "%s-standalone-%s.jar",
|
||||
ARTIFACT_FORGE_API = "%s-api-forge-%s.jar",
|
||||
ARTIFACT_FORGE_STANDALONE = "%s-standalone-forge-%s.jar";
|
||||
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
|
||||
|
||||
protected String artifactName, artifactVersion;
|
||||
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, artifactForgeApiPath, artifactForgeStandalonePath, proguardOut;
|
||||
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
|
||||
|
||||
protected void verifyArtifacts() throws IllegalStateException {
|
||||
this.artifactName = getProject().getName();
|
||||
@@ -60,8 +56,6 @@ class BaritoneGradleTask extends DefaultTask {
|
||||
this.artifactUnoptimizedPath = this.getBuildFile(formatVersion(ARTIFACT_UNOPTIMIZED));
|
||||
this.artifactApiPath = this.getBuildFile(formatVersion(ARTIFACT_API));
|
||||
this.artifactStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_STANDALONE));
|
||||
this.artifactForgeApiPath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_API));
|
||||
this.artifactForgeStandalonePath = this.getBuildFile(formatVersion(ARTIFACT_FORGE_STANDALONE));
|
||||
|
||||
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
|
||||
|
||||
|
||||
@@ -45,8 +45,6 @@ public class CreateDistTask extends BaritoneGradleTask {
|
||||
Path api = getRelativeFile("dist/" + formatVersion(ARTIFACT_API));
|
||||
Path standalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_STANDALONE));
|
||||
Path unoptimized = getRelativeFile("dist/" + formatVersion(ARTIFACT_UNOPTIMIZED));
|
||||
Path forgeApi = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_API));
|
||||
Path forgeStandalone = getRelativeFile("dist/" + formatVersion(ARTIFACT_FORGE_STANDALONE));
|
||||
|
||||
// NIO will not automatically create directories
|
||||
Path dir = getRelativeFile("dist/");
|
||||
@@ -58,11 +56,9 @@ public class CreateDistTask extends BaritoneGradleTask {
|
||||
Files.copy(this.artifactApiPath, api, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactStandalonePath, standalone, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactUnoptimizedPath, unoptimized, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactForgeApiPath, forgeApi, REPLACE_EXISTING);
|
||||
Files.copy(this.artifactForgeStandalonePath, forgeStandalone, REPLACE_EXISTING);
|
||||
|
||||
// Calculate all checksums and format them like "shasum"
|
||||
List<String> shasum = Stream.of(api, forgeApi, standalone, forgeStandalone, unoptimized)
|
||||
List<String> shasum = Stream.of(api, standalone, unoptimized)
|
||||
.map(path -> sha1(path) + " " + path.getFileName().toString())
|
||||
.collect(Collectors.toList());
|
||||
|
||||
|
||||
@@ -18,26 +18,18 @@
|
||||
package baritone.gradle.task;
|
||||
|
||||
import baritone.gradle.util.Determinizer;
|
||||
import baritone.gradle.util.MappingType;
|
||||
import baritone.gradle.util.ReobfWrapper;
|
||||
import org.apache.commons.io.IOUtils;
|
||||
import org.gradle.api.NamedDomainObjectContainer;
|
||||
import org.gradle.api.artifacts.Configuration;
|
||||
import org.gradle.api.artifacts.Dependency;
|
||||
import org.gradle.api.internal.plugins.DefaultConvention;
|
||||
import org.gradle.api.plugins.JavaPluginConvention;
|
||||
import org.gradle.api.tasks.Input;
|
||||
import org.gradle.api.tasks.TaskAction;
|
||||
import org.gradle.internal.Pair;
|
||||
|
||||
import java.io.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.URL;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.stream.Stream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
|
||||
@@ -49,18 +41,12 @@ import static java.nio.file.StandardCopyOption.REPLACE_EXISTING;
|
||||
*/
|
||||
public class ProguardTask extends BaritoneGradleTask {
|
||||
|
||||
private static final Pattern TEMP_LIBRARY_PATTERN = Pattern.compile("-libraryjars 'tempLibraries\\/([a-zA-Z0-9/_\\-\\.]+)\\.jar'");
|
||||
|
||||
@Input
|
||||
private String url;
|
||||
|
||||
@Input
|
||||
private String extract;
|
||||
|
||||
private List<String> requiredLibraries;
|
||||
|
||||
private File mixin;
|
||||
|
||||
@TaskAction
|
||||
protected void exec() throws Exception {
|
||||
super.verifyArtifacts();
|
||||
@@ -70,7 +56,6 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
downloadProguard();
|
||||
extractProguard();
|
||||
generateConfigs();
|
||||
acquireDependencies();
|
||||
proguardApi();
|
||||
proguardStandalone();
|
||||
cleanup();
|
||||
@@ -81,7 +66,7 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
Files.delete(this.artifactUnoptimizedPath);
|
||||
}
|
||||
|
||||
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString(), Optional.empty());
|
||||
Determinizer.determinize(this.artifactPath.toString(), this.artifactUnoptimizedPath.toString());
|
||||
}
|
||||
|
||||
private void downloadProguard() throws Exception {
|
||||
@@ -114,6 +99,19 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
String out = IOUtils.toString(p.getInputStream(), "UTF-8").split("\n")[0].split("Opened ")[1].replace("]", "");
|
||||
template.add(2, "-libraryjars '" + out + "'");
|
||||
|
||||
// Discover all of the libraries that we will need to acquire from gradle
|
||||
acquireDependencies().forEach(f -> {
|
||||
if (f.toString().endsWith("-recomp.jar")) {
|
||||
// remove MCP mapped jar
|
||||
return;
|
||||
}
|
||||
if (f.toString().endsWith("client-extra.jar")) {
|
||||
// go from the extra to the original downloaded client
|
||||
f = new File(f.getParentFile(), "client.jar");
|
||||
}
|
||||
template.add(2, "-libraryjars '" + f + "'");
|
||||
});
|
||||
|
||||
// API config doesn't require any changes from the changes that we made to the template
|
||||
Files.write(getTemporaryFile(PROGUARD_API_CONFIG), template);
|
||||
|
||||
@@ -121,165 +119,20 @@ public class ProguardTask extends BaritoneGradleTask {
|
||||
List<String> standalone = new ArrayList<>(template);
|
||||
standalone.removeIf(s -> s.contains("# this is the keep api"));
|
||||
Files.write(getTemporaryFile(PROGUARD_STANDALONE_CONFIG), standalone);
|
||||
|
||||
// Discover all of the libraries that we will need to acquire from gradle
|
||||
this.requiredLibraries = new ArrayList<>();
|
||||
template.forEach(line -> {
|
||||
if (!line.startsWith("#")) {
|
||||
Matcher m = TEMP_LIBRARY_PATTERN.matcher(line);
|
||||
if (m.find()) {
|
||||
this.requiredLibraries.add(m.group(1));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
private void acquireDependencies() throws Exception {
|
||||
|
||||
// Create a map of all of the dependencies that we are able to access in this project
|
||||
// Likely a better way to do this, I just pair the dependency with the first valid configuration
|
||||
Map<String, Pair<Configuration, Dependency>> dependencyLookupMap = new HashMap<>();
|
||||
getProject().getConfigurations().stream().filter(Configuration::isCanBeResolved).forEach(config ->
|
||||
config.getAllDependencies().forEach(dependency ->
|
||||
dependencyLookupMap.putIfAbsent(dependency.getName() + "-" + dependency.getVersion(), Pair.of(config, dependency))));
|
||||
|
||||
// Create the directory if it doesn't already exist
|
||||
Path tempLibraries = getTemporaryFile(TEMP_LIBRARY_DIR);
|
||||
if (!Files.exists(tempLibraries)) {
|
||||
Files.createDirectory(tempLibraries);
|
||||
}
|
||||
|
||||
// Iterate the required libraries to copy them to tempLibraries
|
||||
for (String lib : this.requiredLibraries) {
|
||||
// copy from the forgegradle cache
|
||||
if (lib.equals("minecraft")) {
|
||||
Path cachedJar = getMinecraftJar();
|
||||
Path inTempDir = getTemporaryFile("tempLibraries/minecraft.jar");
|
||||
// TODO: maybe try not to copy every time
|
||||
Files.copy(cachedJar, inTempDir, REPLACE_EXISTING);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
||||
// Find a configuration/dependency pair that matches the desired library
|
||||
Pair<Configuration, Dependency> pair = null;
|
||||
for (Map.Entry<String, Pair<Configuration, Dependency>> entry : dependencyLookupMap.entrySet()) {
|
||||
if (entry.getKey().startsWith(lib)) {
|
||||
pair = entry.getValue();
|
||||
}
|
||||
}
|
||||
|
||||
// The pair must be non-null
|
||||
Objects.requireNonNull(pair);
|
||||
|
||||
// Find the library jar file, and copy it to tempLibraries
|
||||
for (File file : pair.getLeft().files(pair.getRight())) {
|
||||
if (file.getName().startsWith(lib)) {
|
||||
if (lib.contains("mixin")) {
|
||||
mixin = file;
|
||||
}
|
||||
Files.copy(file.toPath(), getTemporaryFile("tempLibraries/" + lib + ".jar"), REPLACE_EXISTING);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (mixin == null) {
|
||||
throw new IllegalStateException("Unable to find mixin jar");
|
||||
}
|
||||
}
|
||||
|
||||
// a bunch of epic stuff to get the path to the cached jar
|
||||
private Path getMinecraftJar() throws Exception {
|
||||
MappingType mappingType;
|
||||
try {
|
||||
mappingType = getMappingType();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failed to get mapping type, assuming NOTCH.");
|
||||
mappingType = MappingType.NOTCH;
|
||||
}
|
||||
|
||||
String suffix;
|
||||
switch (mappingType) {
|
||||
case NOTCH:
|
||||
suffix = "";
|
||||
break;
|
||||
case SEARGE:
|
||||
suffix = "-srgBin";
|
||||
break;
|
||||
case CUSTOM:
|
||||
throw new IllegalStateException("Custom mappings not supported!");
|
||||
default:
|
||||
throw new IllegalStateException("Unknown mapping type: " + mappingType);
|
||||
}
|
||||
|
||||
DefaultConvention convention = (DefaultConvention) this.getProject().getConvention();
|
||||
Object extension = convention.getAsMap().get("minecraft");
|
||||
Objects.requireNonNull(extension);
|
||||
|
||||
// for some reason cant use Class.forName
|
||||
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed
|
||||
Field f_replacer = class_baseExtension.getDeclaredField("replacer");
|
||||
f_replacer.setAccessible(true);
|
||||
Object replacer = f_replacer.get(extension);
|
||||
Class<?> class_replacementProvider = replacer.getClass();
|
||||
Field replacement_replaceMap = class_replacementProvider.getDeclaredField("replaceMap");
|
||||
replacement_replaceMap.setAccessible(true);
|
||||
|
||||
Map<String, Object> replacements = (Map) replacement_replaceMap.get(replacer);
|
||||
String cacheDir = replacements.get("CACHE_DIR").toString() + "/net/minecraft";
|
||||
String mcVersion = replacements.get("MC_VERSION").toString();
|
||||
String mcpInsert = replacements.get("MAPPING_CHANNEL").toString() + "/" + replacements.get("MAPPING_VERSION").toString();
|
||||
String fullJarName = "minecraft-" + mcVersion + suffix + ".jar";
|
||||
|
||||
String baseDir = String.format("%s/minecraft/%s/", cacheDir, mcVersion);
|
||||
|
||||
String jarPath;
|
||||
if (mappingType == MappingType.SEARGE) {
|
||||
jarPath = String.format("%s/%s/%s", baseDir, mcpInsert, fullJarName);
|
||||
} else {
|
||||
jarPath = baseDir + fullJarName;
|
||||
}
|
||||
jarPath = jarPath
|
||||
.replace("/", File.separator)
|
||||
.replace("\\", File.separator); // hecking regex
|
||||
|
||||
return new File(jarPath).toPath();
|
||||
}
|
||||
|
||||
// throws IllegalStateException if mapping type is ambiguous or it fails to find it
|
||||
private MappingType getMappingType() {
|
||||
// if it fails to find this then its probably a forgegradle version problem
|
||||
Set<Object> reobf = (NamedDomainObjectContainer<Object>) this.getProject().getExtensions().getByName("reobf");
|
||||
|
||||
List<MappingType> mappingTypes = getUsedMappingTypes(reobf);
|
||||
long mappingTypesUsed = mappingTypes.size();
|
||||
if (mappingTypesUsed == 0) {
|
||||
throw new IllegalStateException("Failed to find mapping type (no jar task?)");
|
||||
}
|
||||
if (mappingTypesUsed > 1) {
|
||||
throw new IllegalStateException("Ambiguous mapping type (multiple jars with different mapping types?)");
|
||||
}
|
||||
|
||||
return mappingTypes.get(0);
|
||||
}
|
||||
|
||||
private List<MappingType> getUsedMappingTypes(Set<Object> reobf) {
|
||||
return reobf.stream()
|
||||
.map(ReobfWrapper::new)
|
||||
.map(ReobfWrapper::getMappingType)
|
||||
.distinct()
|
||||
.collect(Collectors.toList());
|
||||
private Stream<File> acquireDependencies() {
|
||||
return getProject().getConvention().getPlugin(JavaPluginConvention.class).getSourceSets().findByName("launch").getRuntimeClasspath().getFiles().stream().filter(File::isFile);
|
||||
}
|
||||
|
||||
private void proguardApi() throws Exception {
|
||||
runProguard(getTemporaryFile(PROGUARD_API_CONFIG));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString(), Optional.empty());
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeApiPath.toString(), Optional.of(mixin));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactApiPath.toString());
|
||||
}
|
||||
|
||||
private void proguardStandalone() throws Exception {
|
||||
runProguard(getTemporaryFile(PROGUARD_STANDALONE_CONFIG));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString(), Optional.empty());
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactForgeStandalonePath.toString(), Optional.of(mixin));
|
||||
Determinizer.determinize(this.proguardOut.toString(), this.artifactStandalonePath.toString());
|
||||
}
|
||||
|
||||
private void cleanup() {
|
||||
|
||||
@@ -22,7 +22,10 @@ import com.google.gson.stream.JsonReader;
|
||||
import com.google.gson.stream.JsonWriter;
|
||||
|
||||
import java.io.*;
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.jar.JarEntry;
|
||||
import java.util.jar.JarFile;
|
||||
import java.util.jar.JarOutputStream;
|
||||
@@ -36,7 +39,7 @@ import java.util.stream.Collectors;
|
||||
*/
|
||||
public class Determinizer {
|
||||
|
||||
public static void determinize(String inputPath, String outputPath, Optional<File> toInclude) throws IOException {
|
||||
public static void determinize(String inputPath, String outputPath) throws IOException {
|
||||
System.out.println("Running Determinizer");
|
||||
System.out.println(" Input path: " + inputPath);
|
||||
System.out.println(" Output path: " + outputPath);
|
||||
@@ -63,30 +66,10 @@ public class Determinizer {
|
||||
if (entry.getName().endsWith(".refmap.json")) {
|
||||
JsonObject object = new JsonParser().parse(new InputStreamReader(jarFile.getInputStream(entry))).getAsJsonObject();
|
||||
jos.write(writeSorted(object).getBytes());
|
||||
} else if (entry.getName().equals("META-INF/MANIFEST.MF") && toInclude.isPresent()) { // only replace for forge jar
|
||||
ByteArrayOutputStream cancer = new ByteArrayOutputStream();
|
||||
copy(jarFile.getInputStream(entry), cancer);
|
||||
String manifest = new String(cancer.toByteArray());
|
||||
if (!manifest.contains("baritone.launch.BaritoneTweaker")) {
|
||||
throw new IllegalStateException("unable to replace");
|
||||
}
|
||||
manifest = manifest.replace("baritone.launch.BaritoneTweaker", "org.spongepowered.asm.launch.MixinTweaker");
|
||||
jos.write(manifest.getBytes());
|
||||
} else {
|
||||
copy(jarFile.getInputStream(entry), jos);
|
||||
}
|
||||
}
|
||||
if (toInclude.isPresent()) {
|
||||
try (JarFile mixin = new JarFile(toInclude.get())) {
|
||||
for (JarEntry entry : mixin.stream().sorted(Comparator.comparing(JarEntry::getName)).collect(Collectors.toList())) {
|
||||
if (entry.getName().startsWith("META-INF") && !entry.getName().startsWith("META-INF/services")) {
|
||||
continue;
|
||||
}
|
||||
jos.putNextEntry(entry);
|
||||
copy(mixin.getInputStream(entry), jos);
|
||||
}
|
||||
}
|
||||
}
|
||||
jos.finish();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,29 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.gradle.util;
|
||||
|
||||
/**
|
||||
* All credits go to AsmLibGradle and its contributors.
|
||||
*
|
||||
* @see <a href="https://github.com/pozzed/AsmLibGradle/blob/8f917dbc3939eab7a3d9daf54d9d285fdf34f4b2/src/main/java/net/futureclient/asmlib/forgegradle/MappingType.java">Original Source</a>
|
||||
*/
|
||||
public enum MappingType {
|
||||
SEARGE,
|
||||
NOTCH,
|
||||
CUSTOM // forgegradle
|
||||
}
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.gradle.util;
|
||||
|
||||
import java.lang.reflect.Field;
|
||||
import java.util.Objects;
|
||||
|
||||
/**
|
||||
* All credits go to AsmLibGradle and its contributors.
|
||||
*
|
||||
* @see <a href="https://github.com/pozzed/AsmLibGradle/blob/8f917dbc3939eab7a3d9daf54d9d285fdf34f4b2/src/main/java/net/futureclient/asmlib/forgegradle/ReobfWrapper.java">Original Source</a>
|
||||
*/
|
||||
public class ReobfWrapper {
|
||||
|
||||
private final Object instance;
|
||||
private final Class<?> type;
|
||||
|
||||
public ReobfWrapper(Object instance) {
|
||||
this.instance = instance;
|
||||
Objects.requireNonNull(instance);
|
||||
this.type = instance.getClass();
|
||||
}
|
||||
|
||||
public String getName() {
|
||||
try {
|
||||
Field nameField = type.getDeclaredField("name");
|
||||
nameField.setAccessible(true);
|
||||
return (String) nameField.get(this.instance);
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
public MappingType getMappingType() {
|
||||
try {
|
||||
Field enumField = type.getDeclaredField("mappingType");
|
||||
enumField.setAccessible(true);
|
||||
Enum<?> aEnum = (Enum<?>) enumField.get(this.instance);
|
||||
MappingType mappingType = MappingType.values()[aEnum.ordinal()];
|
||||
if (!aEnum.name().equals(mappingType.name())) {
|
||||
throw new IllegalStateException("ForgeGradle ReobfMappingType is not equivalent to MappingType (version error?)");
|
||||
}
|
||||
return mappingType;
|
||||
} catch (ReflectiveOperationException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
}
|
||||
59
scripts/proguard.pro
vendored
59
scripts/proguard.pro
vendored
@@ -14,6 +14,8 @@
|
||||
|
||||
# lwjgl is weird
|
||||
-dontwarn org.lwjgl.**
|
||||
# also lwjgl lol
|
||||
-dontwarn module-info
|
||||
|
||||
-keep class baritone.api.** { *; } # this is the keep api
|
||||
|
||||
@@ -21,8 +23,6 @@
|
||||
-keep class baritone.BaritoneProvider
|
||||
-keep class baritone.api.IBaritoneProvider
|
||||
|
||||
-keep class baritone.api.utils.MyChunkPos { *; } # even in standalone we need to keep this for gson reflect
|
||||
|
||||
# setting names are reflected from field names, so keep field names
|
||||
-keepclassmembers class baritone.api.Settings {
|
||||
public <fields>;
|
||||
@@ -31,61 +31,6 @@
|
||||
# need to keep mixin names
|
||||
-keep class baritone.launch.** { *; }
|
||||
|
||||
#try to keep usage of schematica in separate classes
|
||||
-keep class baritone.utils.schematic.schematica.**
|
||||
#proguard doesnt like it when it cant find our fake schematica classes
|
||||
-dontwarn baritone.utils.schematic.schematica.**
|
||||
|
||||
# copy all necessary libraries into tempLibraries to build
|
||||
|
||||
# The correct jar will be copied from the forgegradle cache based on the mapping type being compiled with
|
||||
-libraryjars 'tempLibraries/minecraft.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/SimpleTweaker-1.2.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/authlib-1.5.25.jar'
|
||||
-libraryjars 'tempLibraries/codecjorbis-20101023.jar'
|
||||
-libraryjars 'tempLibraries/codecwav-20101023.jar'
|
||||
-libraryjars 'tempLibraries/commons-codec-1.10.jar'
|
||||
-libraryjars 'tempLibraries/commons-compress-1.8.1.jar'
|
||||
-libraryjars 'tempLibraries/commons-io-2.5.jar'
|
||||
-libraryjars 'tempLibraries/commons-lang3-3.5.jar'
|
||||
-libraryjars 'tempLibraries/commons-logging-1.1.3.jar'
|
||||
-libraryjars 'tempLibraries/fastutil-7.1.0.jar'
|
||||
-libraryjars 'tempLibraries/gson-2.8.0.jar'
|
||||
-libraryjars 'tempLibraries/guava-21.0.jar'
|
||||
-libraryjars 'tempLibraries/httpclient-4.3.3.jar'
|
||||
-libraryjars 'tempLibraries/httpcore-4.3.2.jar'
|
||||
-libraryjars 'tempLibraries/icu4j-core-mojang-51.2.jar'
|
||||
-libraryjars 'tempLibraries/jinput-2.0.5.jar'
|
||||
-libraryjars 'tempLibraries/jna-4.4.0.jar'
|
||||
-libraryjars 'tempLibraries/jopt-simple-5.0.3.jar'
|
||||
-libraryjars 'tempLibraries/jsr305-3.0.1.jar'
|
||||
-libraryjars 'tempLibraries/jutils-1.0.0.jar'
|
||||
-libraryjars 'tempLibraries/libraryjavasound-20101123.jar'
|
||||
-libraryjars 'tempLibraries/librarylwjglopenal-20100824.jar'
|
||||
-libraryjars 'tempLibraries/log4j-api-2.8.1.jar'
|
||||
-libraryjars 'tempLibraries/log4j-core-2.8.1.jar'
|
||||
|
||||
# startsWith is used to check the library, and mac/linux differ in which version they use
|
||||
# this is FINE
|
||||
-libraryjars 'tempLibraries/lwjgl-.jar'
|
||||
-libraryjars 'tempLibraries/lwjgl_util-.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/netty-all-4.1.9.Final.jar'
|
||||
-libraryjars 'tempLibraries/oshi-core-1.1.jar'
|
||||
-libraryjars 'tempLibraries/patchy-1.1.jar'
|
||||
-libraryjars 'tempLibraries/platform-3.4.0.jar'
|
||||
-libraryjars 'tempLibraries/realms-1.10.22.jar'
|
||||
-libraryjars 'tempLibraries/soundsystem-20120107.jar'
|
||||
-libraryjars 'tempLibraries/text2speech-1.10.3.jar'
|
||||
|
||||
-libraryjars 'tempLibraries/mixin-0.7.11-SNAPSHOT.jar'
|
||||
-libraryjars 'tempLibraries/launchwrapper-1.11.jar' # TODO why does only 1.11.jar exist?
|
||||
|
||||
|
||||
|
||||
|
||||
# Keep - Applications. Keep all application classes, along with their 'main'
|
||||
# methods.
|
||||
-keepclasseswithmembers public class * {
|
||||
|
||||
@@ -71,18 +71,6 @@ public interface IBaritone {
|
||||
*/
|
||||
IBuilderProcess getBuilderProcess();
|
||||
|
||||
/**
|
||||
* @return The {@link IExploreProcess} instance
|
||||
* @see IExploreProcess
|
||||
*/
|
||||
IExploreProcess getExploreProcess();
|
||||
|
||||
/**
|
||||
* @return The {@link IFarmProcess} instance
|
||||
* @see IFarmProcess
|
||||
*/
|
||||
IFarmProcess getFarmProcess();
|
||||
|
||||
/**
|
||||
* @return The {@link ICustomGoalProcess} instance
|
||||
* @see ICustomGoalProcess
|
||||
@@ -127,9 +115,4 @@ public interface IBaritone {
|
||||
* @see IEventBus
|
||||
*/
|
||||
IEventBus getGameEventHandler();
|
||||
|
||||
/**
|
||||
* Open click
|
||||
*/
|
||||
void openClick();
|
||||
}
|
||||
|
||||
@@ -18,18 +18,14 @@
|
||||
package baritone.api;
|
||||
|
||||
import baritone.api.utils.SettingsUtil;
|
||||
import baritone.api.utils.TypeUtils;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.text.ITextComponent;
|
||||
|
||||
import java.awt.*;
|
||||
import java.lang.reflect.Field;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.function.Consumer;
|
||||
@@ -84,7 +80,7 @@ public final class Settings {
|
||||
/**
|
||||
* Walking on water uses up hunger really quick, so penalize it
|
||||
*/
|
||||
public final Setting<Double> walkOnWaterOnePenalty = new Setting<>(3D);
|
||||
public final Setting<Double> walkOnWaterOnePenalty = new Setting<>(5D);
|
||||
|
||||
/**
|
||||
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
|
||||
@@ -124,13 +120,6 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> allowJumpAt256 = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* This should be monetized it's so good
|
||||
* <p>
|
||||
* Defaults to true, but only actually takes effect if allowParkour is also true
|
||||
*/
|
||||
public final Setting<Boolean> allowParkourAscend = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Allow descending diagonally
|
||||
* <p>
|
||||
@@ -151,44 +140,16 @@ public final class Settings {
|
||||
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
|
||||
*/
|
||||
public final Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
|
||||
Item.getItemFromBlock(Blocks.DIRT),
|
||||
Item.getItemFromBlock(Blocks.COBBLESTONE),
|
||||
Item.getItemFromBlock(Blocks.NETHERRACK),
|
||||
Item.getItemFromBlock(Blocks.STONE)
|
||||
Blocks.DIRT.asItem(),
|
||||
Blocks.COBBLESTONE.asItem(),
|
||||
Blocks.NETHERRACK.asItem()
|
||||
)));
|
||||
|
||||
/**
|
||||
* Blocks that Baritone will attempt to avoid (Used in avoidance)
|
||||
*/
|
||||
public final Setting<List<Block>> blocksToAvoid = new Setting<>(new ArrayList<>(
|
||||
// Leave Empty by Default
|
||||
));
|
||||
|
||||
/**
|
||||
* Blocks that Baritone is not allowed to break
|
||||
*/
|
||||
public final Setting<List<Block>> blocksToAvoidBreaking = new Setting<>(new ArrayList<>(Arrays.asList( // TODO can this be a HashSet or ImmutableSet?
|
||||
Blocks.CRAFTING_TABLE,
|
||||
Blocks.FURNACE,
|
||||
Blocks.LIT_FURNACE,
|
||||
Blocks.CHEST,
|
||||
Blocks.TRAPPED_CHEST,
|
||||
Blocks.STANDING_SIGN,
|
||||
Blocks.WALL_SIGN
|
||||
)));
|
||||
|
||||
/**
|
||||
* If this setting is true, Baritone will never break a block that is adjacent to an unsupported falling block.
|
||||
* <p>
|
||||
* I.E. it will never trigger cascading sand / gravel falls
|
||||
*/
|
||||
public final Setting<Boolean> avoidUpdatingFallingBlocks = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* 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.
|
||||
* <p>
|
||||
* Almost never turn this on lol
|
||||
* Never turn this on lol
|
||||
*/
|
||||
public final Setting<Boolean> allowVines = new Setting<>(false);
|
||||
|
||||
@@ -224,18 +185,6 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> sprintAscends = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If we overshoot a traverse and end up one block beyond the destination, mark it as successful anyway.
|
||||
* <p>
|
||||
* This helps with speed at >=20m/s
|
||||
*/
|
||||
public final Setting<Boolean> overshootTraverse = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* When breaking blocks for a movement, wait until all falling blocks have settled before continuing
|
||||
*/
|
||||
public final Setting<Boolean> pauseMiningForFallingBlocks = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* How many ticks between right clicks are allowed. Default in game is 4
|
||||
*/
|
||||
@@ -452,12 +401,10 @@ public final class Settings {
|
||||
* On save, delete from RAM any cached regions that are more than 1024 blocks away from the player
|
||||
* <p>
|
||||
* Temporarily disabled
|
||||
* <p>
|
||||
* Temporarily reenabled
|
||||
*
|
||||
* @see <a href="https://github.com/cabaletta/baritone/issues/248">Issue #248</a>
|
||||
*/
|
||||
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(true);
|
||||
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Remember the contents of containers (chests, echests, furnaces)
|
||||
@@ -466,11 +413,6 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> containerMemory = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Fill in blocks behind you
|
||||
*/
|
||||
public final Setting<Boolean> backfill = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Print all the debug messages to chat
|
||||
*/
|
||||
@@ -554,8 +496,6 @@ public final class Settings {
|
||||
|
||||
/**
|
||||
* Exclusively use cached chunks for pathing
|
||||
* <p>
|
||||
* Never turn this on
|
||||
*/
|
||||
public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
|
||||
|
||||
@@ -586,7 +526,7 @@ public final class Settings {
|
||||
public final Setting<Boolean> renderCachedChunks = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* 0.0f = not visible, fully transparent (instead of setting this to 0, turn off renderCachedChunks)
|
||||
* 0.0f = not visible, fully transparent
|
||||
* 1.0f = fully opaque
|
||||
*/
|
||||
public final Setting<Float> cachedChunksOpacity = new Setting<>(0.5f);
|
||||
@@ -601,16 +541,6 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> walkWhileBreaking = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* When a new segment is calculated that doesn't overlap with the current one, but simply begins where the current segment ends,
|
||||
* splice it on and make a longer combined path. If this setting is off, any planned segment will not be spliced and will instead
|
||||
* be the "next path" in PathingBehavior, and will only start after this one ends. Turning this off hurts planning ahead,
|
||||
* because the next segment will exist even if it's very short.
|
||||
*
|
||||
* @see #planningTickLookahead
|
||||
*/
|
||||
public final Setting<Boolean> splicePath = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* If we are more than 300 movements into the current path, discard the oldest segments, as they are no longer useful
|
||||
*/
|
||||
@@ -637,98 +567,26 @@ public final class Settings {
|
||||
*/
|
||||
public final Setting<Boolean> exploreForBlocks = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* While exploring the world, offset the closest unloaded chunk by this much in both axes.
|
||||
* <p>
|
||||
* This can result in more efficient loading, if you set this to the render distance.
|
||||
*/
|
||||
public final Setting<Integer> worldExploringChunkOffset = new Setting<>(0);
|
||||
|
||||
/**
|
||||
* Take the 10 closest chunks, even if they aren't strictly tied for distance metric from origin.
|
||||
*/
|
||||
public final Setting<Integer> exploreChunkSetMinimumSize = new Setting<>(10);
|
||||
|
||||
/**
|
||||
* Attempt to maintain Y coordinate while exploring
|
||||
* <p>
|
||||
* -1 to disable
|
||||
*/
|
||||
public final Setting<Integer> exploreMaintainY = new Setting<>(64);
|
||||
|
||||
/**
|
||||
* Replant nether wart while farming
|
||||
*/
|
||||
public final Setting<Boolean> replantNetherWart = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* When the cache scan gives less blocks than the maximum threshold (but still above zero), scan the main world too.
|
||||
* <p>
|
||||
* Only if you have a beefy CPU and automatically mine blocks that are in cache
|
||||
*/
|
||||
public final Setting<Boolean> extendCacheOnThreshold = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Don't consider the next layer in builder until the current one is done
|
||||
*/
|
||||
public final Setting<Boolean> buildInLayers = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* false = build from bottom to top
|
||||
* <p>
|
||||
* true = build from top to bottom
|
||||
* How far to move before repeating the build. -1 for the size of the build in that axis. 0 to disable
|
||||
*/
|
||||
public final Setting<Boolean> layerOrder = new Setting<>(false);
|
||||
public final Setting<Integer> buildRepeatDistance=new Setting<>(0);
|
||||
|
||||
/**
|
||||
* How far to move before repeating the build. 0 to disable repeating on a certain axis, 0,0,0 to disable entirely
|
||||
* What direction te repeat the build in
|
||||
*/
|
||||
public final Setting<Vec3i> buildRepeat = new Setting<>(new Vec3i(0, 0, 0));
|
||||
|
||||
/**
|
||||
* Allow standing above a block while mining it, in BuilderProcess
|
||||
* <p>
|
||||
* Experimental
|
||||
*/
|
||||
public final Setting<Boolean> breakFromAbove = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* As well as breaking from above, set a goal to up and to the side of all blocks to break.
|
||||
* <p>
|
||||
* Never turn this on without also turning on breakFromAbove.
|
||||
*/
|
||||
public final Setting<Boolean> goalBreakFromAbove = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Build in map art mode, which makes baritone only care about the top block in each column
|
||||
*/
|
||||
public final Setting<Boolean> mapArtMode = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Override builder's behavior to not attempt to correct blocks that are currently water
|
||||
*/
|
||||
public final Setting<Boolean> okIfWater = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* The set of incorrect blocks can never grow beyond this size
|
||||
*/
|
||||
public final Setting<Integer> incorrectSize = new Setting<>(100);
|
||||
|
||||
/**
|
||||
* Multiply the cost of breaking a block that's correct in the builder's schematic by this coefficient
|
||||
*/
|
||||
public final Setting<Double> breakCorrectBlockPenaltyMultiplier = new Setting<>(10d);
|
||||
public final Setting<EnumFacing> buildRepeatDirection = new Setting<>(EnumFacing.NORTH);
|
||||
|
||||
/**
|
||||
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
|
||||
*/
|
||||
public final Setting<Boolean> mineScanDroppedItems = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Trim incorrect positions too far away, helps performance but hurts reliability in very large schematics
|
||||
*/
|
||||
public final Setting<Boolean> distanceTrim = new Setting<>(true);
|
||||
|
||||
/**
|
||||
* Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore.
|
||||
* <p>
|
||||
@@ -810,10 +668,11 @@ public final class Settings {
|
||||
public final Setting<Integer> followRadius = new Setting<>(3);
|
||||
|
||||
/**
|
||||
* Turn this on if your exploration filter is enormous, you don't want it to check if it's done,
|
||||
* and you are just fine with it just hanging on completion
|
||||
* true = exploration uses pythagorean distance to choose closest uncached chunk
|
||||
* <p>
|
||||
* false = exploration uses manhattan / taxicab distance to choose
|
||||
*/
|
||||
public final Setting<Boolean> disableCompletionCheck = new Setting<>(false);
|
||||
public final Setting<Boolean> exploreUsePythagorean = new Setting<>(false);
|
||||
|
||||
/**
|
||||
* Cached chunks (regardless of if they're in RAM or saved to disk) expire and are deleted after this number of seconds
|
||||
@@ -842,12 +701,7 @@ public final class Settings {
|
||||
* via {@link Consumer#andThen(Consumer)} or it can completely be overriden via setting
|
||||
* {@link Setting#value};
|
||||
*/
|
||||
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage);
|
||||
|
||||
/**
|
||||
* The size of the box that is rendered when the current goal is a GoalYLevel
|
||||
*/
|
||||
public final Setting<Double> yLevelBoxSize = new Setting<>(15D);
|
||||
public final Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getInstance().ingameGUI.getChatGUI()::printChatMessage);
|
||||
|
||||
/**
|
||||
* The color of the current path
|
||||
@@ -900,12 +754,11 @@ public final class Settings {
|
||||
*/
|
||||
public final List<Setting<?>> allSettings;
|
||||
|
||||
public final Map<Setting<?>, Type> settingTypes;
|
||||
|
||||
public final class Setting<T> {
|
||||
public T value;
|
||||
public final T defaultValue;
|
||||
private String name;
|
||||
private final Class<T> klass;
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
private Setting(T value) {
|
||||
@@ -914,6 +767,7 @@ public final class Settings {
|
||||
}
|
||||
this.value = value;
|
||||
this.defaultValue = value;
|
||||
this.klass = (Class<T>) value.getClass();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -931,8 +785,7 @@ public final class Settings {
|
||||
}
|
||||
|
||||
public Class<T> getValueClass() {
|
||||
// noinspection unchecked
|
||||
return (Class<T>) TypeUtils.resolveBaseClass(getType());
|
||||
return klass;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -946,21 +799,14 @@ public final class Settings {
|
||||
public void reset() {
|
||||
value = defaultValue;
|
||||
}
|
||||
|
||||
public final Type getType() {
|
||||
return settingTypes.get(this);
|
||||
}
|
||||
}
|
||||
|
||||
// here be dragons
|
||||
|
||||
Settings() {
|
||||
Field[] temp = getClass().getFields();
|
||||
|
||||
Map<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
|
||||
List<Setting<?>> tmpAll = new ArrayList<>();
|
||||
Map<Setting<?>, Type> tmpSettingTypes = new HashMap<>();
|
||||
|
||||
try {
|
||||
for (Field field : temp) {
|
||||
if (field.getType().equals(Setting.class)) {
|
||||
@@ -973,7 +819,6 @@ public final class Settings {
|
||||
}
|
||||
tmpByName.put(name, setting);
|
||||
tmpAll.add(setting);
|
||||
tmpSettingTypes.put(setting, ((ParameterizedType) field.getGenericType()).getActualTypeArguments()[0]);
|
||||
}
|
||||
}
|
||||
} catch (IllegalAccessException e) {
|
||||
@@ -981,7 +826,6 @@ public final class Settings {
|
||||
}
|
||||
byLowerName = Collections.unmodifiableMap(tmpByName);
|
||||
allSettings = Collections.unmodifiableList(tmpAll);
|
||||
settingTypes = Collections.unmodifiableMap(tmpSettingTypes);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
|
||||
@@ -23,8 +23,9 @@ import baritone.api.event.listener.IGameEventListener;
|
||||
/**
|
||||
* A behavior is simply a type that is able to listen to events.
|
||||
*
|
||||
* @author Brady
|
||||
* @see IGameEventListener
|
||||
*
|
||||
* @author Brady
|
||||
* @since 9/23/2018
|
||||
*/
|
||||
public interface IBehavior extends AbstractGameEventListener {}
|
||||
|
||||
@@ -80,13 +80,6 @@ public interface IPathingBehavior extends IBehavior {
|
||||
*/
|
||||
boolean cancelEverything();
|
||||
|
||||
/**
|
||||
* PLEASE never call this
|
||||
* <p>
|
||||
* If cancelEverything was like "kill" this is "sudo kill -9". Or shutting off your computer.
|
||||
*/
|
||||
void forceCancel();
|
||||
|
||||
/**
|
||||
* Returns the current path, from the current path executor, if there is one.
|
||||
*
|
||||
|
||||
@@ -81,6 +81,4 @@ public interface ICachedWorld {
|
||||
* in a new thread by default.
|
||||
*/
|
||||
void save();
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -18,12 +18,11 @@
|
||||
package baritone.api.event.listener;
|
||||
|
||||
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.gui.GuiScreen;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.network.Packet;
|
||||
|
||||
@@ -45,7 +44,7 @@ public interface IGameEventListener {
|
||||
* Run once per game tick from before and after the player rotation is sent to the server.
|
||||
*
|
||||
* @param event The event
|
||||
* @see EntityPlayerSP#onUpdate()
|
||||
* @see EntityPlayerSP#tick()
|
||||
*/
|
||||
void onPlayerUpdate(PlayerUpdateEvent event);
|
||||
|
||||
@@ -61,14 +60,11 @@ public interface IGameEventListener {
|
||||
* Runs before and after whenever a chunk is either loaded, unloaded, or populated.
|
||||
*
|
||||
* @param event The event
|
||||
* @see WorldClient#doPreChunk(int, int, boolean)
|
||||
*/
|
||||
void onChunkEvent(ChunkEvent event);
|
||||
|
||||
/**
|
||||
* Runs once per world render pass. Two passes are made when {@link GameSettings#anaglyph} is on.
|
||||
* <p>
|
||||
* <b>Note:</b> {@link GameSettings#anaglyph} has been removed in Minecraft 1.13
|
||||
* Runs once per world render pass.
|
||||
*
|
||||
* @param event The event
|
||||
*/
|
||||
@@ -78,7 +74,7 @@ public interface IGameEventListener {
|
||||
* Runs before and after whenever a new world is loaded
|
||||
*
|
||||
* @param event The event
|
||||
* @see Minecraft#loadWorld(WorldClient, String)
|
||||
* @see Minecraft#loadWorld(WorldClient, GuiScreen)
|
||||
*/
|
||||
void onWorldEvent(WorldEvent event);
|
||||
|
||||
@@ -87,7 +83,6 @@ public interface IGameEventListener {
|
||||
*
|
||||
* @param event The event
|
||||
* @see Packet
|
||||
* @see GenericFutureListener
|
||||
*/
|
||||
void onSendPacket(PacketEvent event);
|
||||
|
||||
@@ -96,7 +91,6 @@ public interface IGameEventListener {
|
||||
*
|
||||
* @param event The event
|
||||
* @see Packet
|
||||
* @see GenericFutureListener
|
||||
*/
|
||||
void onReceivePacket(PacketEvent event);
|
||||
|
||||
@@ -110,10 +104,10 @@ public interface IGameEventListener {
|
||||
void onPlayerRotationMove(RotationMoveEvent event);
|
||||
|
||||
/**
|
||||
* Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#onLivingUpdate}
|
||||
* Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#livingTick}
|
||||
*
|
||||
* @param event The event
|
||||
* @see EntityPlayerSP#onLivingUpdate()
|
||||
* @see EntityPlayerSP#livingTick()
|
||||
*/
|
||||
void onPlayerSprintState(SprintStateEvent event);
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
|
||||
package baritone.api.pathing.goals;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
|
||||
@@ -31,17 +31,17 @@ public class GoalTwoBlocks implements Goal, IGoalRenderPos {
|
||||
/**
|
||||
* The X block position of this goal
|
||||
*/
|
||||
protected final int x;
|
||||
private final int x;
|
||||
|
||||
/**
|
||||
* The Y block position of this goal
|
||||
*/
|
||||
protected final int y;
|
||||
private final int y;
|
||||
|
||||
/**
|
||||
* The Z block position of this goal
|
||||
*/
|
||||
protected final int z;
|
||||
private final int z;
|
||||
|
||||
public GoalTwoBlocks(BlockPos pos) {
|
||||
this(pos.getX(), pos.getY(), pos.getZ());
|
||||
|
||||
@@ -29,7 +29,7 @@ public class GoalYLevel implements Goal, ActionCosts {
|
||||
/**
|
||||
* The target Y level
|
||||
*/
|
||||
public final int level;
|
||||
private final int level;
|
||||
|
||||
public GoalYLevel(int level) {
|
||||
this.level = level;
|
||||
|
||||
@@ -18,8 +18,6 @@
|
||||
package baritone.api.process;
|
||||
|
||||
import baritone.api.utils.ISchematic;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
import java.io.File;
|
||||
@@ -48,17 +46,4 @@ public interface IBuilderProcess extends IBaritoneProcess {
|
||||
* @return Whether or not the schematic was able to load from file
|
||||
*/
|
||||
boolean build(String name, File schematic, Vec3i origin);
|
||||
|
||||
default boolean build(String schematicFile, BlockPos origin) {
|
||||
File file = new File(new File(Minecraft.getMinecraft().gameDir, "schematics"), schematicFile);
|
||||
return build(schematicFile, file, origin);
|
||||
}
|
||||
|
||||
void buildOpenSchematic();
|
||||
|
||||
void pause();
|
||||
|
||||
void resume();
|
||||
|
||||
void clearArea(BlockPos corner1, BlockPos corner2);
|
||||
}
|
||||
|
||||
@@ -1,26 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
import java.nio.file.Path;
|
||||
|
||||
public interface IExploreProcess extends IBaritoneProcess {
|
||||
void explore(int centerX, int centerZ);
|
||||
|
||||
void applyJsonFilter(Path path, boolean invert) throws Exception;
|
||||
}
|
||||
@@ -1,22 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.process;
|
||||
|
||||
public interface IFarmProcess extends IBaritoneProcess {
|
||||
void farm();
|
||||
}
|
||||
@@ -25,6 +25,4 @@ import net.minecraft.block.Block;
|
||||
public interface IGetToBlockProcess extends IBaritoneProcess {
|
||||
|
||||
void getToBlock(Block block);
|
||||
|
||||
boolean blacklistClosest();
|
||||
}
|
||||
|
||||
@@ -51,10 +51,5 @@ public enum PathingCommandType {
|
||||
* <p>
|
||||
* Cancel the current path if the goals are not equal
|
||||
*/
|
||||
FORCE_REVALIDATE_GOAL_AND_PATH,
|
||||
|
||||
/**
|
||||
* Go and ask the next process what to do
|
||||
*/
|
||||
DEFER
|
||||
FORCE_REVALIDATE_GOAL_AND_PATH
|
||||
}
|
||||
|
||||
@@ -61,8 +61,6 @@ public final class BetterBlockPos extends BlockPos {
|
||||
}
|
||||
|
||||
public static long longHash(int x, int y, int z) {
|
||||
// TODO use the same thing as BlockPos.fromLong();
|
||||
// invertibility would be incredibly useful
|
||||
/*
|
||||
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
|
||||
*
|
||||
|
||||
@@ -1,63 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
|
||||
public class BlockUtils {
|
||||
private static transient Map<String, Block> resourceCache = new HashMap<>();
|
||||
|
||||
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 stringToBlockRequired(String name) {
|
||||
Block block = stringToBlockNullable(name);
|
||||
Objects.requireNonNull(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
public static Block stringToBlockNullable(String name) {
|
||||
// do NOT just replace this with a computeWithAbsent, it isn't thread safe
|
||||
Block block = resourceCache.get(name); // map is never mutated in place so this is safe
|
||||
if (block != null) {
|
||||
return block;
|
||||
}
|
||||
if (resourceCache.containsKey(name)) {
|
||||
return null; // cached as null
|
||||
}
|
||||
block = Block.getBlockFromName(name.contains(":") ? name : "minecraft:" + name);
|
||||
Map<String, Block> copy = new HashMap<>(resourceCache); // read only copy is safe, wont throw concurrentmodification
|
||||
copy.put(name, block);
|
||||
resourceCache = copy;
|
||||
return block;
|
||||
}
|
||||
|
||||
private BlockUtils() {}
|
||||
}
|
||||
@@ -71,26 +71,20 @@ public interface IPlayerContext {
|
||||
* @return The position of the highlighted block
|
||||
*/
|
||||
default Optional<BlockPos> getSelectedBlock() {
|
||||
RayTraceResult result = objectMouseOver();
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
return Optional.of(result.getBlockPos());
|
||||
if (objectMouseOver() != null && objectMouseOver().type == RayTraceResult.Type.BLOCK) {
|
||||
return Optional.of(objectMouseOver().getBlockPos());
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
default boolean isLookingAt(BlockPos pos) {
|
||||
return getSelectedBlock().equals(Optional.of(pos));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the entity that the crosshair is currently placed over. Updated once per tick.
|
||||
*
|
||||
* @return The entity
|
||||
*/
|
||||
default Optional<Entity> getSelectedEntity() {
|
||||
RayTraceResult result = objectMouseOver();
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(result.entityHit);
|
||||
if (objectMouseOver() != null && objectMouseOver().type == RayTraceResult.Type.ENTITY) {
|
||||
return Optional.of(objectMouseOver().entity);
|
||||
}
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
@@ -1,37 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import com.google.gson.annotations.SerializedName;
|
||||
|
||||
/**
|
||||
* Need a non obfed chunkpos that we can load using GSON
|
||||
*/
|
||||
public class MyChunkPos {
|
||||
|
||||
@SerializedName("x")
|
||||
public int x;
|
||||
|
||||
@SerializedName("z")
|
||||
public int z;
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return x + ", " + z;
|
||||
}
|
||||
}
|
||||
@@ -18,6 +18,7 @@
|
||||
package baritone.api.utils;
|
||||
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.RayTraceFluidMode;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
@@ -40,13 +41,13 @@ public final class RayTraceUtils {
|
||||
* @return The calculated raytrace result
|
||||
*/
|
||||
public static RayTraceResult rayTraceTowards(Entity entity, Rotation rotation, double blockReachDistance) {
|
||||
Vec3d start = entity.getPositionEyes(1.0F);
|
||||
Vec3d start = entity.getEyePosition(1.0F);
|
||||
Vec3d direction = RotationUtils.calcVec3dFromRotation(rotation);
|
||||
Vec3d end = start.add(
|
||||
direction.x * blockReachDistance,
|
||||
direction.y * blockReachDistance,
|
||||
direction.z * blockReachDistance
|
||||
);
|
||||
return entity.world.rayTraceBlocks(start, end, false, false, true);
|
||||
return entity.world.rayTraceBlocks(start, end, RayTraceFluidMode.NEVER, false, true);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,9 @@ public class Rotation {
|
||||
public Rotation(float yaw, float pitch) {
|
||||
this.yaw = yaw;
|
||||
this.pitch = pitch;
|
||||
if (Float.isInfinite(yaw) || Float.isNaN(yaw) || Float.isInfinite(pitch) || Float.isNaN(pitch)) {
|
||||
throw new IllegalStateException(yaw + " " + pitch);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -23,7 +23,13 @@ import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.MathHelper;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.util.math.shapes.VoxelShapes;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
@@ -154,7 +160,7 @@ public final class RotationUtils {
|
||||
*/
|
||||
public static Optional<Rotation> reachable(EntityPlayerSP entity, BlockPos pos, double blockReachDistance) {
|
||||
IBaritone baritone = BaritoneAPI.getProvider().getBaritoneForPlayer(entity);
|
||||
if (baritone.getPlayerContext().isLookingAt(pos)) {
|
||||
if (pos.equals(baritone.getPlayerContext().getSelectedBlock().orElse(null))) {
|
||||
/*
|
||||
* why add 0.0001?
|
||||
* to indicate that we actually have a desired pitch
|
||||
@@ -174,11 +180,14 @@ public final class RotationUtils {
|
||||
}
|
||||
|
||||
IBlockState state = entity.world.getBlockState(pos);
|
||||
AxisAlignedBB aabb = state.getBoundingBox(entity.world, pos);
|
||||
VoxelShape shape = state.getShape(entity.world, pos);
|
||||
if (shape.isEmpty()) {
|
||||
shape = VoxelShapes.fullCube();
|
||||
}
|
||||
for (Vec3d sideOffset : BLOCK_SIDE_MULTIPLIERS) {
|
||||
double xDiff = aabb.minX * sideOffset.x + aabb.maxX * (1 - sideOffset.x);
|
||||
double yDiff = aabb.minY * sideOffset.y + aabb.maxY * (1 - sideOffset.y);
|
||||
double zDiff = aabb.minZ * sideOffset.z + aabb.maxZ * (1 - sideOffset.z);
|
||||
double xDiff = shape.getStart(EnumFacing.Axis.X) * sideOffset.x + shape.getEnd(EnumFacing.Axis.X) * (1 - sideOffset.x);
|
||||
double yDiff = shape.getStart(EnumFacing.Axis.Y) * sideOffset.y + shape.getEnd(EnumFacing.Axis.Y) * (1 - sideOffset.y);
|
||||
double zDiff = shape.getStart(EnumFacing.Axis.Z) * sideOffset.z + shape.getEnd(EnumFacing.Axis.Z) * (1 - sideOffset.z);
|
||||
possibleRotation = reachableOffset(entity, pos, new Vec3d(pos).add(xDiff, yDiff, zDiff), blockReachDistance);
|
||||
if (possibleRotation.isPresent()) {
|
||||
return possibleRotation;
|
||||
@@ -199,10 +208,10 @@ public final class RotationUtils {
|
||||
* @return The optional rotation
|
||||
*/
|
||||
public static Optional<Rotation> reachableOffset(Entity entity, BlockPos pos, Vec3d offsetPos, double blockReachDistance) {
|
||||
Rotation rotation = calcRotationFromVec3d(entity.getPositionEyes(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
|
||||
Rotation rotation = calcRotationFromVec3d(entity.getEyePosition(1.0F), offsetPos, new Rotation(entity.rotationYaw, entity.rotationPitch));
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(entity, rotation, blockReachDistance);
|
||||
//System.out.println(result);
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK) {
|
||||
if (result != null && result.type == RayTraceResult.Type.BLOCK) {
|
||||
if (result.getBlockPos().equals(pos)) {
|
||||
return Optional.of(rotation);
|
||||
}
|
||||
|
||||
@@ -18,36 +18,33 @@
|
||||
package baritone.api.utils;
|
||||
|
||||
import baritone.api.Settings;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
import net.minecraft.util.ResourceLocation;
|
||||
import net.minecraft.util.registry.IRegistry;
|
||||
|
||||
import java.awt.*;
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.*;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.function.Consumer;
|
||||
import java.util.function.Function;
|
||||
import java.util.regex.Matcher;
|
||||
import java.util.regex.Pattern;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static net.minecraft.client.Minecraft.getMinecraft;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
public class SettingsUtil {
|
||||
|
||||
private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
|
||||
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>.+)"); // key and value split by the first space
|
||||
private static final Path SETTINGS_PATH = Minecraft.getInstance().gameDir.toPath().resolve("baritone").resolve("settings.txt");
|
||||
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces
|
||||
|
||||
private static final Map<Class<?>, SettingsIO> map;
|
||||
|
||||
private static boolean isComment(String line) {
|
||||
return line.startsWith("#") || line.startsWith("//");
|
||||
@@ -83,8 +80,6 @@ public class SettingsUtil {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
});
|
||||
} catch (NoSuchFileException ignored) {
|
||||
System.out.println("Baritone settings file not found, resetting.");
|
||||
} catch (Exception ex) {
|
||||
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
|
||||
ex.printStackTrace();
|
||||
@@ -124,11 +119,11 @@ public class SettingsUtil {
|
||||
if (setting.getName().equals("logger")) {
|
||||
return "logger";
|
||||
}
|
||||
Parser io = Parser.getParser(setting.getType());
|
||||
SettingsIO io = map.get(setting.getValueClass());
|
||||
if (io == null) {
|
||||
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting.getName());
|
||||
}
|
||||
return setting.getName() + " " + io.toString(new ParserContext(setting), setting.value);
|
||||
return setting.getName() + " " + io.toString.apply(setting.value);
|
||||
}
|
||||
|
||||
public static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
|
||||
@@ -137,132 +132,46 @@ public class SettingsUtil {
|
||||
throw new IllegalStateException("No setting by that name");
|
||||
}
|
||||
Class intendedType = setting.getValueClass();
|
||||
ISettingParser ioMethod = Parser.getParser(setting.getType());
|
||||
Object parsed = ioMethod.parse(new ParserContext(setting), settingValue);
|
||||
SettingsIO ioMethod = map.get(intendedType);
|
||||
Object parsed = ioMethod.parser.apply(settingValue);
|
||||
if (!intendedType.isInstance(parsed)) {
|
||||
throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass());
|
||||
}
|
||||
setting.value = parsed;
|
||||
}
|
||||
|
||||
private interface ISettingParser<T> {
|
||||
|
||||
T parse(ParserContext context, String raw);
|
||||
|
||||
String toString(ParserContext context, T value);
|
||||
|
||||
boolean accepts(Type type);
|
||||
}
|
||||
|
||||
private static class ParserContext {
|
||||
|
||||
private final Settings.Setting<?> setting;
|
||||
|
||||
private ParserContext(Settings.Setting<?> setting) {
|
||||
this.setting = setting;
|
||||
}
|
||||
|
||||
private Settings.Setting<?> getSetting() {
|
||||
return this.setting;
|
||||
}
|
||||
}
|
||||
|
||||
private enum Parser implements ISettingParser {
|
||||
|
||||
private enum SettingsIO {
|
||||
DOUBLE(Double.class, Double::parseDouble),
|
||||
BOOLEAN(Boolean.class, Boolean::parseBoolean),
|
||||
INTEGER(Integer.class, Integer::parseInt),
|
||||
FLOAT(Float.class, Float::parseFloat),
|
||||
LONG(Long.class, Long::parseLong),
|
||||
ENUMFACING(EnumFacing.class, EnumFacing::byName),
|
||||
COLOR(
|
||||
Color.class,
|
||||
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
|
||||
color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()
|
||||
),
|
||||
VEC3I(
|
||||
Vec3i.class,
|
||||
str -> new Vec3i(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
|
||||
vec -> vec.getX() + "," + vec.getY() + "," + vec.getZ()
|
||||
),
|
||||
BLOCK(
|
||||
Block.class,
|
||||
str -> BlockUtils.stringToBlockRequired(str.trim()),
|
||||
BlockUtils::blockToString
|
||||
),
|
||||
ITEM(
|
||||
Item.class,
|
||||
str -> Item.getByNameOrId(str.trim()),
|
||||
item -> Item.REGISTRY.getNameForObject(item).toString()
|
||||
),
|
||||
LIST() {
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(type);
|
||||
|
||||
return Arrays.stream(raw.split(","))
|
||||
.map(s -> parser.parse(context, s))
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(ResourceLocation::new).map(IRegistry.ITEM::get).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList<Item>) list).stream().map(IRegistry.ITEM::getKey).map(ResourceLocation::toString).collect(Collectors.joining(","))),
|
||||
COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()),
|
||||
ENUMFACING(EnumFacing.class, EnumFacing::byName);
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
Type type = ((ParameterizedType) context.getSetting().getType()).getActualTypeArguments()[0];
|
||||
Parser parser = Parser.getParser(type);
|
||||
|
||||
return ((List<?>) value).stream()
|
||||
.map(o -> parser.toString(context, o))
|
||||
.collect(Collectors.joining(","));
|
||||
}
|
||||
Class<?> klass;
|
||||
Function<String, Object> parser;
|
||||
Function<Object, String> toString;
|
||||
|
||||
@Override
|
||||
public boolean accepts(Type type) {
|
||||
return List.class.isAssignableFrom(TypeUtils.resolveBaseClass(type));
|
||||
}
|
||||
};
|
||||
|
||||
private final Class<?> klass;
|
||||
private final Function<String, Object> parser;
|
||||
private final Function<Object, String> toString;
|
||||
|
||||
Parser() {
|
||||
this.klass = null;
|
||||
this.parser = null;
|
||||
this.toString = null;
|
||||
}
|
||||
|
||||
<T> Parser(Class<T> klass, Function<String, T> parser) {
|
||||
<T> SettingsIO(Class<T> klass, Function<String, T> parser) {
|
||||
this(klass, parser, Object::toString);
|
||||
}
|
||||
|
||||
<T> Parser(Class<T> klass, Function<String, T> parser, Function<T, String> toString) {
|
||||
<T> SettingsIO(Class<T> klass, Function<String, T> parser, Function<T, String> toString) {
|
||||
this.klass = klass;
|
||||
this.parser = parser::apply;
|
||||
this.toString = x -> toString.apply((T) x);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Object parse(ParserContext context, String raw) {
|
||||
Object parsed = this.parser.apply(raw);
|
||||
Objects.requireNonNull(parsed);
|
||||
return parsed;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString(ParserContext context, Object value) {
|
||||
return this.toString.apply(value);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean accepts(Type type) {
|
||||
return type instanceof Class && this.klass.isAssignableFrom((Class) type);
|
||||
}
|
||||
|
||||
public static Parser getParser(Type type) {
|
||||
return Arrays.stream(values())
|
||||
.filter(parser -> parser.accepts(type))
|
||||
.findFirst().orElse(null);
|
||||
static {
|
||||
HashMap<Class<?>, SettingsIO> tempMap = new HashMap<>();
|
||||
for (SettingsIO type : SettingsIO.values()) {
|
||||
tempMap.put(type.klass, type);
|
||||
}
|
||||
map = Collections.unmodifiableMap(tempMap);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.utils;
|
||||
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
import java.lang.reflect.Type;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 4/20/2019
|
||||
*/
|
||||
public final class TypeUtils {
|
||||
|
||||
private TypeUtils() {}
|
||||
|
||||
/**
|
||||
* Resolves the "base type" for the specified type. For example, if the specified
|
||||
* type is {@code List<String>}, then {@code List.class} will be returned. If the
|
||||
* specified type is already a class, then it is directly returned.
|
||||
*
|
||||
* @param type The type to resolve
|
||||
* @return The base class
|
||||
*/
|
||||
public static Class<?> resolveBaseClass(Type type) {
|
||||
return type instanceof Class ? (Class<?>) type
|
||||
: type instanceof ParameterizedType ? (Class<?>) ((ParameterizedType) type).getRawType()
|
||||
: null;
|
||||
}
|
||||
}
|
||||
@@ -20,9 +20,10 @@ package baritone.api.utils;
|
||||
import net.minecraft.block.BlockFire;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
/**
|
||||
@@ -43,10 +44,16 @@ public final class VecUtils {
|
||||
*/
|
||||
public static Vec3d calculateBlockCenter(World world, BlockPos pos) {
|
||||
IBlockState b = world.getBlockState(pos);
|
||||
AxisAlignedBB bbox = b.getBoundingBox(world, pos);
|
||||
double xDiff = (bbox.minX + bbox.maxX) / 2;
|
||||
double yDiff = (bbox.minY + bbox.maxY) / 2;
|
||||
double zDiff = (bbox.minZ + bbox.maxZ) / 2;
|
||||
VoxelShape shape = b.getCollisionShape(world, pos);
|
||||
if (shape.isEmpty()) {
|
||||
return getBlockPosCenter(pos);
|
||||
}
|
||||
double xDiff = (shape.getStart(EnumFacing.Axis.X) + shape.getEnd(EnumFacing.Axis.X)) / 2;
|
||||
double yDiff = (shape.getStart(EnumFacing.Axis.Y) + shape.getEnd(EnumFacing.Axis.Y)) / 2;
|
||||
double zDiff = (shape.getStart(EnumFacing.Axis.Z) + shape.getEnd(EnumFacing.Axis.Z)) / 2;
|
||||
if (Double.isNaN(xDiff) || Double.isNaN(yDiff) || Double.isNaN(zDiff)) {
|
||||
throw new IllegalStateException(b + " " + pos + " " + shape);
|
||||
}
|
||||
if (b.getBlock() instanceof BlockFire) {//look at bottom of fire when putting it out
|
||||
yDiff = 0;
|
||||
}
|
||||
|
||||
105
src/launch/java/baritone/launch/LaunchTesting.java
Normal file
105
src/launch/java/baritone/launch/LaunchTesting.java
Normal file
@@ -0,0 +1,105 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch;
|
||||
|
||||
import com.google.common.base.Strings;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import com.mojang.authlib.Agent;
|
||||
import com.mojang.authlib.exceptions.AuthenticationException;
|
||||
import com.mojang.authlib.properties.PropertyMap;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilAuthenticationService;
|
||||
import com.mojang.authlib.yggdrasil.YggdrasilUserAuthentication;
|
||||
import net.minecraft.launchwrapper.Launch;
|
||||
|
||||
import java.io.File;
|
||||
import java.lang.reflect.Field;
|
||||
import java.net.Proxy;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Based on GradleStart from ForgeGradle 2.3
|
||||
*
|
||||
* @author Brady
|
||||
* @since 3/11/2019
|
||||
*/
|
||||
public class LaunchTesting {
|
||||
|
||||
public static void main(String[] args) {
|
||||
Map<String, String> arguments = new HashMap<>();
|
||||
|
||||
hackNatives();
|
||||
arguments.put("version", "BaritownedDeveloperEnvironment");
|
||||
arguments.put("assetIndex", System.getenv("assetIndex"));
|
||||
arguments.put("assetsDir", System.getenv().getOrDefault("assetDirectory", "assets"));
|
||||
arguments.put("accessToken", "FML");
|
||||
arguments.put("userProperties", "{}");
|
||||
arguments.put("tweakClass", System.getenv("tweakClass"));
|
||||
String password = System.getenv("password");
|
||||
if (password != null && !password.isEmpty()) {
|
||||
attemptLogin(arguments, System.getenv("username"), System.getenv("password"));
|
||||
}
|
||||
|
||||
List<String> argsArray = new ArrayList<>();
|
||||
arguments.forEach((k, v) -> {
|
||||
argsArray.add("--" + k);
|
||||
argsArray.add(v);
|
||||
});
|
||||
|
||||
Launch.main(argsArray.toArray(new String[0]));
|
||||
}
|
||||
|
||||
private static void hackNatives() {
|
||||
String paths = System.getProperty("java.library.path");
|
||||
String nativesDir = System.getenv().get("nativesDirectory");
|
||||
|
||||
if (Strings.isNullOrEmpty(paths))
|
||||
paths = nativesDir;
|
||||
else
|
||||
paths += File.pathSeparator + nativesDir;
|
||||
|
||||
System.setProperty("java.library.path", paths);
|
||||
|
||||
// hack the classloader now.
|
||||
try {
|
||||
final Field sysPathsField = ClassLoader.class.getDeclaredField("sys_paths");
|
||||
sysPathsField.setAccessible(true);
|
||||
sysPathsField.set(null, null);
|
||||
} catch (Throwable ignored) {}
|
||||
}
|
||||
|
||||
private static void attemptLogin(Map<String, String> argMap, String username, String password) {
|
||||
YggdrasilUserAuthentication auth = (YggdrasilUserAuthentication) (new YggdrasilAuthenticationService(Proxy.NO_PROXY, "1")).createUserAuthentication(Agent.MINECRAFT);
|
||||
auth.setUsername(username);
|
||||
auth.setPassword(password);
|
||||
|
||||
try {
|
||||
auth.logIn();
|
||||
} catch (AuthenticationException var4) {
|
||||
throw new RuntimeException(var4);
|
||||
}
|
||||
|
||||
argMap.put("accessToken", auth.getAuthenticatedToken());
|
||||
argMap.put("uuid", auth.getSelectedProfile().getId().toString().replace("-", ""));
|
||||
argMap.put("username", auth.getSelectedProfile().getName());
|
||||
argMap.put("userType", auth.getUserType().getName());
|
||||
argMap.put("userProperties", (new GsonBuilder()).registerTypeAdapter(PropertyMap.class, new PropertyMap.Serializer()).create().toJson(auth.getUserProperties()));
|
||||
}
|
||||
}
|
||||
@@ -29,6 +29,7 @@ import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
import static org.lwjgl.opengl.GL11.*;
|
||||
import static org.lwjgl.opengl.GL14.*;
|
||||
|
||||
@Mixin(ChunkRenderContainer.class)
|
||||
public class MixinChunkRenderContainer {
|
||||
@@ -41,11 +42,11 @@ public class MixinChunkRenderContainer {
|
||||
)
|
||||
)
|
||||
private BlockPos getPosition(RenderChunk renderChunkIn) {
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer() && Minecraft.getMinecraft().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
|
||||
GlStateManager.enableAlpha();
|
||||
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null && Minecraft.getInstance().world.getChunk(renderChunkIn.getPosition()).isEmpty()) {
|
||||
GlStateManager.enableAlphaTest();
|
||||
GlStateManager.enableBlend();
|
||||
GL14.glBlendColor(0, 0, 0, Baritone.settings().cachedChunksOpacity.value);
|
||||
GlStateManager.tryBlendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
|
||||
GlStateManager.blendFuncSeparate(GL_CONSTANT_ALPHA, GL_ONE_MINUS_CONSTANT_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
return renderChunkIn.getPosition();
|
||||
}
|
||||
|
||||
@@ -43,7 +43,7 @@ public abstract class MixinChunkRenderWorker {
|
||||
)
|
||||
)
|
||||
private boolean isChunkExisting(ChunkRenderWorker worker, BlockPos pos, World world) {
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
|
||||
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
|
||||
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
|
||||
IPlayerContext ctx = baritone.getPlayerContext();
|
||||
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
|
||||
|
||||
@@ -23,6 +23,7 @@ import baritone.api.event.events.RotationMoveEvent;
|
||||
import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.EntityLivingBase;
|
||||
import net.minecraft.entity.EntityType;
|
||||
import net.minecraft.world.World;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
@@ -44,9 +45,8 @@ public abstract class MixinEntityLivingBase extends Entity {
|
||||
*/
|
||||
private RotationMoveEvent jumpRotationEvent;
|
||||
|
||||
public MixinEntityLivingBase(World worldIn, RotationMoveEvent jumpRotationEvent) {
|
||||
super(worldIn);
|
||||
this.jumpRotationEvent = jumpRotationEvent;
|
||||
public MixinEntityLivingBase(EntityType<?> entityTypeIn, World worldIn) {
|
||||
super(entityTypeIn, worldIn);
|
||||
}
|
||||
|
||||
@Inject(
|
||||
|
||||
@@ -58,10 +58,10 @@ public class MixinEntityPlayerSP {
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onUpdate",
|
||||
method = "tick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.isRiding()Z",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.isPassenger()Z",
|
||||
shift = At.Shift.BY,
|
||||
by = -3
|
||||
)
|
||||
@@ -74,7 +74,7 @@ public class MixinEntityPlayerSP {
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "onUpdate",
|
||||
method = "tick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/entity/EntityPlayerSP.onUpdateWalkingPlayer()V",
|
||||
@@ -90,7 +90,7 @@ public class MixinEntityPlayerSP {
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "onLivingUpdate",
|
||||
method = "livingTick",
|
||||
at = @At(
|
||||
value = "FIELD",
|
||||
target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z"
|
||||
@@ -105,7 +105,7 @@ public class MixinEntityPlayerSP {
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "onLivingUpdate",
|
||||
method = "livingTick",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/client/settings/KeyBinding.isKeyDown()Z"
|
||||
|
||||
@@ -20,24 +20,24 @@ package baritone.launch.mixins;
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.event.events.RenderEvent;
|
||||
import net.minecraft.client.renderer.EntityRenderer;
|
||||
import net.minecraft.client.renderer.GameRenderer;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
@Mixin(EntityRenderer.class)
|
||||
public class MixinEntityRenderer {
|
||||
@Mixin(GameRenderer.class)
|
||||
public class MixinGameRenderer {
|
||||
|
||||
@Inject(
|
||||
method = "renderWorldPass",
|
||||
method = "updateCameraAndRender(FJ)V",
|
||||
at = @At(
|
||||
value = "INVOKE_STRING",
|
||||
target = "Lnet/minecraft/profiler/Profiler;endStartSection(Ljava/lang/String;)V",
|
||||
args = {"ldc=hand"}
|
||||
)
|
||||
)
|
||||
private void renderWorldPass(int pass, float partialTicks, long finishTimeNano, CallbackInfo ci) {
|
||||
private void renderWorldPass(float partialTicks, long finishTimeNano, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
ibaritone.getGameEventHandler().onRenderPass(new RenderEvent(partialTicks));
|
||||
}
|
||||
@@ -97,10 +97,10 @@ public class MixinMinecraft {
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Lnet/minecraft/client/gui/GuiScreen;)V",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
private void preLoadWorld(WorldClient world, GuiScreen loadingScreen, CallbackInfo ci) {
|
||||
// If we're unloading the world but one doesn't exist, ignore it
|
||||
if (this.world == null && world == null) {
|
||||
return;
|
||||
@@ -117,10 +117,10 @@ public class MixinMinecraft {
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
|
||||
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Lnet/minecraft/client/gui/GuiScreen;)V",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postLoadWorld(WorldClient world, String loadingMessage, CallbackInfo ci) {
|
||||
private void postLoadWorld(WorldClient world, GuiScreen loadingScreen, CallbackInfo ci) {
|
||||
// still fire event for both null, as that means we've just finished exiting a world
|
||||
|
||||
// mc.world changing is only the primary baritone
|
||||
|
||||
@@ -24,6 +24,7 @@ import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.network.NetHandlerPlayClient;
|
||||
import net.minecraft.network.play.server.SPacketChunkData;
|
||||
import net.minecraft.network.play.server.SPacketCombatEvent;
|
||||
import net.minecraft.network.play.server.SPacketUnloadChunk;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
@@ -40,7 +41,7 @@ public class MixinNetHandlerPlayClient {
|
||||
method = "handleChunkData",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/world/chunk/Chunk.read(Lnet/minecraft/network/PacketBuffer;IZ)V"
|
||||
target = "net/minecraft/client/multiplayer/ChunkProviderClient.func_212474_a(IILnet/minecraft/network/PacketBuffer;IZ)Lnet/minecraft/world/chunk/Chunk;"
|
||||
)
|
||||
)
|
||||
private void preRead(SPacketChunkData packetIn, CallbackInfo ci) {
|
||||
@@ -77,6 +78,34 @@ public class MixinNetHandlerPlayClient {
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processChunkUnload",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preChunkUnload(SPacketUnloadChunk packet, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
|
||||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(EventState.PRE, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "processChunkUnload",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postChunkUnload(SPacketUnloadChunk packet, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
if (ibaritone.getPlayerContext().player().connection == (NetHandlerPlayClient) (Object) this) {
|
||||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(EventState.POST, ChunkEvent.Type.UNLOAD, packet.getX(), packet.getZ())
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "handleCombatEvent",
|
||||
at = @At(
|
||||
|
||||
@@ -53,7 +53,7 @@ public class MixinNetworkManager {
|
||||
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) {
|
||||
if (this.direction != EnumPacketDirection.CLIENTBOUND) {
|
||||
return;
|
||||
}
|
||||
@@ -69,7 +69,7 @@ public 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) {
|
||||
if (this.direction != EnumPacketDirection.CLIENTBOUND) {
|
||||
return;
|
||||
}
|
||||
@@ -85,7 +85,7 @@ public class MixinNetworkManager {
|
||||
method = "channelRead0",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/network/Packet.processPacket(Lnet/minecraft/network/INetHandler;)V"
|
||||
target = "net/minecraft/network/NetworkManager.processPacket(Lnet/minecraft/network/Packet;Lnet/minecraft/network/INetHandler;)V"
|
||||
)
|
||||
)
|
||||
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
|
||||
|
||||
@@ -23,8 +23,8 @@ import baritone.api.utils.IPlayerContext;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunk;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunkCache;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.ChunkCache;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
@@ -40,43 +40,11 @@ public class MixinRenderChunk {
|
||||
method = "rebuildChunk",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/world/ChunkCache.isEmpty()Z"
|
||||
target = "net/minecraft/client/renderer/chunk/RenderChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
|
||||
)
|
||||
)
|
||||
private boolean isEmpty(ChunkCache chunkCache) {
|
||||
if (!chunkCache.isEmpty()) {
|
||||
return false;
|
||||
}
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
|
||||
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
|
||||
IPlayerContext ctx = baritone.getPlayerContext();
|
||||
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
|
||||
BlockPos position = ((RenderChunk) (Object) this).getPosition();
|
||||
// RenderChunk extends from -1,-1,-1 to +16,+16,+16
|
||||
// then the constructor of ChunkCache extends it one more (presumably to get things like the connected status of fences? idk)
|
||||
// so if ANY of the adjacent chunks are loaded, we are unempty
|
||||
for (int dx = -1; dx <= 1; dx++) {
|
||||
for (int dz = -1; dz <= 1; dz++) {
|
||||
if (baritone.bsi.isLoaded(16 * dx + position.getX(), 16 * dz + position.getZ())) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@Redirect(
|
||||
method = "rebuildChunk",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/world/ChunkCache.getBlockState(Lnet/minecraft/util/math/BlockPos;)Lnet/minecraft/block/state/IBlockState;"
|
||||
)
|
||||
)
|
||||
private IBlockState getBlockState(ChunkCache chunkCache, BlockPos pos) {
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
|
||||
private IBlockState getBlockState(RenderChunkCache chunkCache, BlockPos pos) {
|
||||
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
|
||||
Baritone baritone = (Baritone) BaritoneAPI.getProvider().getPrimaryBaritone();
|
||||
IPlayerContext ctx = baritone.getPlayerContext();
|
||||
if (ctx.player() != null && ctx.world() != null && baritone.bsi != null) {
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.Baritone;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.renderer.chunk.RenderChunkCache;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Redirect;
|
||||
|
||||
@Mixin(RenderChunkCache.class)
|
||||
public class MixinRenderChunkCache {
|
||||
|
||||
@Redirect(
|
||||
method = "generateCache",
|
||||
at = @At(
|
||||
value = "INVOKE",
|
||||
target = "net/minecraft/world/chunk/Chunk.isEmptyBetween(II)Z"
|
||||
)
|
||||
)
|
||||
private static boolean isEmpty(Chunk chunk, int yStart, int yEnd) {
|
||||
if (!chunk.isEmptyBetween(yStart, yEnd)) {
|
||||
return false;
|
||||
}
|
||||
if (chunk.isEmpty() && Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -38,9 +38,9 @@ public class MixinRenderList {
|
||||
)
|
||||
)
|
||||
private void popMatrix() {
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
|
||||
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
|
||||
// reset the blend func to normal (not dependent on constant alpha)
|
||||
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
GlStateManager.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@@ -38,9 +38,9 @@ public class MixinVboRenderList {
|
||||
)
|
||||
)
|
||||
private void popMatrix() {
|
||||
if (Baritone.settings().renderCachedChunks.value && !Minecraft.getMinecraft().isSingleplayer()) {
|
||||
if (Baritone.settings().renderCachedChunks.value && Minecraft.getInstance().getIntegratedServer() == null) {
|
||||
// reset the blend func to normal (not dependent on constant alpha)
|
||||
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
GlStateManager.blendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
|
||||
}
|
||||
GlStateManager.popMatrix();
|
||||
}
|
||||
|
||||
@@ -1,75 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.launch.mixins;
|
||||
|
||||
import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.event.events.ChunkEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import net.minecraft.client.multiplayer.WorldClient;
|
||||
import org.spongepowered.asm.mixin.Mixin;
|
||||
import org.spongepowered.asm.mixin.injection.At;
|
||||
import org.spongepowered.asm.mixin.injection.Inject;
|
||||
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
* @since 8/2/2018
|
||||
*/
|
||||
@Mixin(WorldClient.class)
|
||||
public class MixinWorldClient {
|
||||
|
||||
@Inject(
|
||||
method = "doPreChunk",
|
||||
at = @At("HEAD")
|
||||
)
|
||||
private void preDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
|
||||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(
|
||||
EventState.PRE,
|
||||
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
|
||||
chunkX,
|
||||
chunkZ
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Inject(
|
||||
method = "doPreChunk",
|
||||
at = @At("RETURN")
|
||||
)
|
||||
private void postDoPreChunk(int chunkX, int chunkZ, boolean loadChunk, CallbackInfo ci) {
|
||||
for (IBaritone ibaritone : BaritoneAPI.getProvider().getAllBaritones()) {
|
||||
if (ibaritone.getPlayerContext().world() == (WorldClient) (Object) this) {
|
||||
ibaritone.getGameEventHandler().onChunkEvent(
|
||||
new ChunkEvent(
|
||||
EventState.POST,
|
||||
loadChunk ? ChunkEvent.Type.LOAD : ChunkEvent.Type.UNLOAD,
|
||||
chunkX,
|
||||
chunkZ
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -16,13 +16,13 @@
|
||||
"MixinChunkRenderWorker",
|
||||
"MixinEntityLivingBase",
|
||||
"MixinEntityPlayerSP",
|
||||
"MixinEntityRenderer",
|
||||
"MixinGameRenderer",
|
||||
"MixinMinecraft",
|
||||
"MixinNetHandlerPlayClient",
|
||||
"MixinNetworkManager",
|
||||
"MixinRenderChunk",
|
||||
"MixinRenderChunkCache",
|
||||
"MixinRenderList",
|
||||
"MixinVboRenderList",
|
||||
"MixinWorldClient"
|
||||
"MixinVboRenderList"
|
||||
]
|
||||
}
|
||||
@@ -21,8 +21,6 @@ import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.Settings;
|
||||
import baritone.api.event.listener.IEventBus;
|
||||
import baritone.api.utils.ExampleBaritoneControl;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.behavior.*;
|
||||
import baritone.cache.WorldProvider;
|
||||
@@ -35,6 +33,8 @@ 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.concurrent.Executor;
|
||||
import java.util.concurrent.SynchronousQueue;
|
||||
import java.util.concurrent.ThreadPoolExecutor;
|
||||
@@ -52,7 +52,7 @@ public class Baritone implements IBaritone {
|
||||
static {
|
||||
threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
|
||||
|
||||
dir = new File(Minecraft.getMinecraft().gameDir, "baritone");
|
||||
dir = new File(Minecraft.getInstance().gameDir, "baritone");
|
||||
if (!Files.exists(dir.toPath())) {
|
||||
try {
|
||||
Files.createDirectories(dir.toPath());
|
||||
@@ -67,6 +67,7 @@ public class Baritone implements IBaritone {
|
||||
|
||||
private GameEventHandler gameEventHandler;
|
||||
|
||||
private List<Behavior> behaviors;
|
||||
private PathingBehavior pathingBehavior;
|
||||
private LookBehavior lookBehavior;
|
||||
private MemoryBehavior memoryBehavior;
|
||||
@@ -79,8 +80,6 @@ public class Baritone implements IBaritone {
|
||||
private CustomGoalProcess customGoalProcess;
|
||||
private BuilderProcess builderProcess;
|
||||
private ExploreProcess exploreProcess;
|
||||
private BackfillProcess backfillProcess;
|
||||
private FarmProcess farmProcess;
|
||||
|
||||
private PathingControlManager pathingControlManager;
|
||||
|
||||
@@ -102,6 +101,7 @@ public class Baritone implements IBaritone {
|
||||
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
|
||||
this.playerContext = PrimaryPlayerContext.INSTANCE;
|
||||
|
||||
this.behaviors = new ArrayList<>();
|
||||
{
|
||||
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
|
||||
pathingBehavior = new PathingBehavior(this);
|
||||
@@ -120,8 +120,6 @@ public class Baritone implements IBaritone {
|
||||
getToBlockProcess = new GetToBlockProcess(this);
|
||||
builderProcess = new BuilderProcess(this);
|
||||
exploreProcess = new ExploreProcess(this);
|
||||
backfillProcess = new BackfillProcess(this);
|
||||
farmProcess = new FarmProcess(this);
|
||||
}
|
||||
|
||||
this.worldProvider = new WorldProvider();
|
||||
@@ -138,7 +136,12 @@ public class Baritone implements IBaritone {
|
||||
return this.pathingControlManager;
|
||||
}
|
||||
|
||||
public List<Behavior> getBehaviors() {
|
||||
return this.behaviors;
|
||||
}
|
||||
|
||||
public void registerBehavior(Behavior behavior) {
|
||||
this.behaviors.add(behavior);
|
||||
this.gameEventHandler.registerEventListener(behavior);
|
||||
}
|
||||
|
||||
@@ -148,12 +151,12 @@ public class Baritone implements IBaritone {
|
||||
}
|
||||
|
||||
@Override
|
||||
public CustomGoalProcess getCustomGoalProcess() {
|
||||
public CustomGoalProcess getCustomGoalProcess() { // Iffy
|
||||
return this.customGoalProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public GetToBlockProcess getGetToBlockProcess() {
|
||||
public GetToBlockProcess getGetToBlockProcess() { // Iffy
|
||||
return this.getToBlockProcess;
|
||||
}
|
||||
|
||||
@@ -194,10 +197,6 @@ public class Baritone implements IBaritone {
|
||||
return this.mineProcess;
|
||||
}
|
||||
|
||||
public FarmProcess getFarmProcess() {
|
||||
return this.farmProcess;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingBehavior getPathingBehavior() {
|
||||
return this.pathingBehavior;
|
||||
@@ -213,16 +212,6 @@ public class Baritone implements IBaritone {
|
||||
return this.gameEventHandler;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void openClick() {
|
||||
new Thread(() -> {
|
||||
try {
|
||||
Thread.sleep(100);
|
||||
Helper.mc.addScheduledTask(() -> Helper.mc.displayGuiScreen(new GuiClick()));
|
||||
} catch (Exception ignored) {}
|
||||
}).start();
|
||||
}
|
||||
|
||||
public static Settings settings() {
|
||||
return BaritoneAPI.getSettings();
|
||||
}
|
||||
|
||||
@@ -32,7 +32,6 @@ import java.util.List;
|
||||
public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
private final Baritone primary = new Baritone();
|
||||
private final List<IBaritone> all = Collections.singletonList(primary);
|
||||
|
||||
@Override
|
||||
public IBaritone getPrimaryBaritone() {
|
||||
@@ -41,7 +40,8 @@ public final class BaritoneProvider implements IBaritoneProvider {
|
||||
|
||||
@Override
|
||||
public List<IBaritone> getAllBaritones() {
|
||||
return all;
|
||||
// TODO return a CopyOnWriteArrayList
|
||||
return Collections.singletonList(primary);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -26,7 +26,6 @@ import net.minecraft.client.entity.EntityPlayerSP;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.inventory.ClickType;
|
||||
import net.minecraft.item.*;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.NonNullList;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -34,7 +33,7 @@ import java.util.OptionalInt;
|
||||
import java.util.Random;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class InventoryBehavior extends Behavior {
|
||||
public class InventoryBehavior extends Behavior {
|
||||
public InventoryBehavior(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
@@ -124,30 +123,27 @@ public final class InventoryBehavior extends Behavior {
|
||||
|
||||
public boolean hasGenericThrowaway() {
|
||||
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
|
||||
if (throwaway(false, stack -> item.equals(stack.getItem()))) {
|
||||
if (throwaway(false, item::equals)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean selectThrowawayForLocation(boolean select, int x, int y, int z) {
|
||||
public boolean selectThrowawayForLocation(int x, int y, int z) {
|
||||
IBlockState maybe = baritone.getBuilderProcess().placeAt(x, y, z);
|
||||
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && maybe.equals(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player())))) {
|
||||
if (maybe != null && throwaway(true, item -> item instanceof ItemBlock && ((ItemBlock) item).getBlock().equals(maybe.getBlock()))) {
|
||||
return true; // gotem
|
||||
}
|
||||
if (maybe != null && throwaway(select, stack -> stack.getItem() instanceof ItemBlock && ((ItemBlock) stack.getItem()).getBlock().equals(maybe.getBlock()))) {
|
||||
return true;
|
||||
}
|
||||
for (Item item : Baritone.settings().acceptableThrowawayItems.value) {
|
||||
if (throwaway(select, stack -> item.equals(stack.getItem()))) {
|
||||
if (throwaway(true, item::equals)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public boolean throwaway(boolean select, Predicate<? super ItemStack> desired) {
|
||||
private boolean throwaway(boolean select, Predicate<? super Item> desired) {
|
||||
EntityPlayerSP p = ctx.player();
|
||||
NonNullList<ItemStack> inv = p.inventory.mainInventory;
|
||||
for (byte i = 0; i < 9; i++) {
|
||||
@@ -157,14 +153,14 @@ public final class InventoryBehavior extends Behavior {
|
||||
// and then it's called during execution
|
||||
// since this function is never called during cost calculation, we don't need to migrate
|
||||
// acceptableThrowawayItems to the CalculationContext
|
||||
if (desired.test(item)) {
|
||||
if (desired.test(item.getItem())) {
|
||||
if (select) {
|
||||
p.inventory.currentItem = i;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (desired.test(p.inventory.offHandInventory.get(0))) {
|
||||
if (desired.test(p.inventory.offHandInventory.get(0).getItem())) {
|
||||
// main hand takes precedence over off hand
|
||||
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
|
||||
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
|
||||
|
||||
@@ -28,9 +28,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
|
||||
|
||||
/**
|
||||
* Target's values are as follows:
|
||||
* <p>
|
||||
* getFirst() -> yaw
|
||||
* getSecond() -> pitch
|
||||
*/
|
||||
private Rotation target;
|
||||
|
||||
|
||||
@@ -18,13 +18,13 @@
|
||||
package baritone.behavior;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import baritone.api.event.events.BlockInteractEvent;
|
||||
import baritone.api.event.events.PacketEvent;
|
||||
import baritone.api.event.events.PlayerUpdateEvent;
|
||||
import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.cache.ContainerMemory;
|
||||
import baritone.cache.Waypoint;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockBed;
|
||||
|
||||
@@ -25,7 +25,6 @@ import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.api.utils.interfaces.IGoalRenderPos;
|
||||
import baritone.pathing.calc.AStarPathFinder;
|
||||
@@ -33,6 +32,7 @@ import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.PathRenderer;
|
||||
import baritone.utils.PathingCommandContext;
|
||||
import baritone.utils.pathing.Favoring;
|
||||
@@ -65,7 +65,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
|
||||
private boolean lastAutoJump;
|
||||
|
||||
private BetterBlockPos expectedSegmentStart;
|
||||
private BlockPos expectedSegmentStart;
|
||||
|
||||
private final LinkedBlockingQueue<PathEvent> toDispatch = new LinkedBlockingQueue<>();
|
||||
|
||||
@@ -135,6 +135,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
) {
|
||||
// when it was *just* started, currentBest will be empty so we need to also check calcFrom since that's always present
|
||||
inProgress.cancel(); // cancellation doesn't dispatch any events
|
||||
inProgress = null; // this is safe since we hold both locks
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -194,9 +195,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
current.onTick();
|
||||
return;
|
||||
}
|
||||
if (Baritone.settings().splicePath.value) {
|
||||
current = current.trySplice(next);
|
||||
}
|
||||
current = current.trySplice(next);
|
||||
if (next != null && current.getPath().getDest().equals(next.getPath().getDest())) {
|
||||
next = null;
|
||||
}
|
||||
@@ -338,7 +337,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
|
||||
// just cancel the current path
|
||||
private void secretInternalSegmentCancel() {
|
||||
public void secretInternalSegmentCancel() {
|
||||
queuePathEvent(PathEvent.CANCELED);
|
||||
synchronized (pathPlanLock) {
|
||||
getInProgress().ifPresent(AbstractNodeCostSearch::cancel);
|
||||
@@ -351,8 +350,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void forceCancel() { // exposed on public api because :sob:
|
||||
public void forceCancel() { // NOT exposed on public api
|
||||
cancelEverything();
|
||||
secretInternalSegmentCancel();
|
||||
synchronized (pathCalcLock) {
|
||||
@@ -360,6 +358,12 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
}
|
||||
|
||||
public void secretCursedFunctionDoNotCall(IPath path) {
|
||||
synchronized (pathPlanLock) {
|
||||
current = new PathExecutor(this, path);
|
||||
}
|
||||
}
|
||||
|
||||
public CalculationContext secretInternalGetCalculationContext() {
|
||||
return context;
|
||||
}
|
||||
@@ -488,7 +492,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
}
|
||||
}
|
||||
if (talkAboutIt && current != null && current.getPath() != null) {
|
||||
if (goal.isInGoal(current.getPath().getDest())) {
|
||||
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
|
||||
logDebug("Finished finding a path from " + start + " to " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
} else {
|
||||
logDebug("Found path segment from " + start + " towards " + goal + ". " + current.getPath().getNumNodesConsidered() + " nodes considered");
|
||||
@@ -501,7 +505,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
|
||||
});
|
||||
}
|
||||
|
||||
private static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
public static AbstractNodeCostSearch createPathfinder(BlockPos start, Goal goal, IPath previous, CalculationContext context) {
|
||||
Goal transformed = goal;
|
||||
if (Baritone.settings().simplifyUnloadedYCoord.value && goal instanceof IGoalRenderPos) {
|
||||
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
|
||||
|
||||
169
src/main/java/baritone/cache/CachedChunk.java
vendored
169
src/main/java/baritone/cache/CachedChunk.java
vendored
@@ -17,19 +17,14 @@
|
||||
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.api.utils.BlockUtils;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap;
|
||||
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.ArrayList;
|
||||
import java.util.BitSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.*;
|
||||
|
||||
/**
|
||||
* @author Brady
|
||||
@@ -37,60 +32,99 @@ import java.util.Map;
|
||||
*/
|
||||
public final class CachedChunk {
|
||||
|
||||
public static final ImmutableSet<Block> BLOCKS_TO_KEEP_TRACK_OF = ImmutableSet.of(
|
||||
Blocks.DIAMOND_BLOCK,
|
||||
//Blocks.COAL_ORE,
|
||||
Blocks.COAL_BLOCK,
|
||||
//Blocks.IRON_ORE,
|
||||
Blocks.IRON_BLOCK,
|
||||
//Blocks.GOLD_ORE,
|
||||
Blocks.GOLD_BLOCK,
|
||||
Blocks.EMERALD_ORE,
|
||||
Blocks.EMERALD_BLOCK,
|
||||
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF;
|
||||
|
||||
Blocks.ENDER_CHEST,
|
||||
Blocks.FURNACE,
|
||||
Blocks.CHEST,
|
||||
Blocks.TRAPPED_CHEST,
|
||||
Blocks.END_PORTAL,
|
||||
Blocks.END_PORTAL_FRAME,
|
||||
Blocks.MOB_SPAWNER,
|
||||
Blocks.BARRIER,
|
||||
Blocks.OBSERVER,
|
||||
Blocks.WHITE_SHULKER_BOX,
|
||||
Blocks.ORANGE_SHULKER_BOX,
|
||||
Blocks.MAGENTA_SHULKER_BOX,
|
||||
Blocks.LIGHT_BLUE_SHULKER_BOX,
|
||||
Blocks.YELLOW_SHULKER_BOX,
|
||||
Blocks.LIME_SHULKER_BOX,
|
||||
Blocks.PINK_SHULKER_BOX,
|
||||
Blocks.GRAY_SHULKER_BOX,
|
||||
Blocks.SILVER_SHULKER_BOX,
|
||||
Blocks.CYAN_SHULKER_BOX,
|
||||
Blocks.PURPLE_SHULKER_BOX,
|
||||
Blocks.BLUE_SHULKER_BOX,
|
||||
Blocks.BROWN_SHULKER_BOX,
|
||||
Blocks.GREEN_SHULKER_BOX,
|
||||
Blocks.RED_SHULKER_BOX,
|
||||
Blocks.BLACK_SHULKER_BOX,
|
||||
Blocks.PORTAL,
|
||||
Blocks.HOPPER,
|
||||
Blocks.BEACON,
|
||||
Blocks.BREWING_STAND,
|
||||
Blocks.SKULL,
|
||||
Blocks.ENCHANTING_TABLE,
|
||||
Blocks.ANVIL,
|
||||
Blocks.LIT_FURNACE,
|
||||
Blocks.BED,
|
||||
Blocks.DRAGON_EGG,
|
||||
Blocks.JUKEBOX,
|
||||
Blocks.END_GATEWAY,
|
||||
Blocks.WEB,
|
||||
Blocks.NETHER_WART,
|
||||
Blocks.LADDER,
|
||||
Blocks.VINE
|
||||
);
|
||||
static {
|
||||
HashSet<Block> temp = new HashSet<>();
|
||||
//temp.add(Blocks.DIAMOND_ORE);
|
||||
temp.add(Blocks.DIAMOND_BLOCK);
|
||||
//temp.add(Blocks.COAL_ORE);
|
||||
temp.add(Blocks.COAL_BLOCK);
|
||||
//temp.add(Blocks.IRON_ORE);
|
||||
temp.add(Blocks.IRON_BLOCK);
|
||||
//temp.add(Blocks.GOLD_ORE);
|
||||
temp.add(Blocks.GOLD_BLOCK);
|
||||
temp.add(Blocks.EMERALD_ORE);
|
||||
temp.add(Blocks.EMERALD_BLOCK);
|
||||
|
||||
temp.add(Blocks.ENDER_CHEST);
|
||||
temp.add(Blocks.FURNACE);
|
||||
temp.add(Blocks.CHEST);
|
||||
temp.add(Blocks.TRAPPED_CHEST);
|
||||
temp.add(Blocks.END_PORTAL);
|
||||
temp.add(Blocks.END_PORTAL_FRAME);
|
||||
temp.add(Blocks.SPAWNER);
|
||||
temp.add(Blocks.BARRIER);
|
||||
temp.add(Blocks.OBSERVER);
|
||||
|
||||
temp.add(Blocks.WHITE_SHULKER_BOX);
|
||||
temp.add(Blocks.ORANGE_SHULKER_BOX);
|
||||
temp.add(Blocks.MAGENTA_SHULKER_BOX);
|
||||
temp.add(Blocks.LIGHT_BLUE_SHULKER_BOX);
|
||||
temp.add(Blocks.YELLOW_SHULKER_BOX);
|
||||
temp.add(Blocks.LIME_SHULKER_BOX);
|
||||
temp.add(Blocks.PINK_SHULKER_BOX);
|
||||
temp.add(Blocks.GRAY_SHULKER_BOX);
|
||||
temp.add(Blocks.LIGHT_GRAY_SHULKER_BOX);
|
||||
temp.add(Blocks.CYAN_SHULKER_BOX);
|
||||
temp.add(Blocks.PURPLE_SHULKER_BOX);
|
||||
temp.add(Blocks.BLUE_SHULKER_BOX);
|
||||
temp.add(Blocks.BROWN_SHULKER_BOX);
|
||||
temp.add(Blocks.GREEN_SHULKER_BOX);
|
||||
temp.add(Blocks.RED_SHULKER_BOX);
|
||||
temp.add(Blocks.BLACK_SHULKER_BOX);
|
||||
|
||||
temp.add(Blocks.NETHER_PORTAL);
|
||||
temp.add(Blocks.HOPPER);
|
||||
temp.add(Blocks.BEACON);
|
||||
temp.add(Blocks.BREWING_STAND);
|
||||
|
||||
// TODO: Maybe add a predicate for blocks to keep track of?
|
||||
// This should really not need to happen
|
||||
temp.add(Blocks.CREEPER_HEAD);
|
||||
temp.add(Blocks.CREEPER_WALL_HEAD);
|
||||
temp.add(Blocks.DRAGON_HEAD);
|
||||
temp.add(Blocks.DRAGON_WALL_HEAD);
|
||||
temp.add(Blocks.PLAYER_HEAD);
|
||||
temp.add(Blocks.PLAYER_WALL_HEAD);
|
||||
temp.add(Blocks.ZOMBIE_HEAD);
|
||||
temp.add(Blocks.ZOMBIE_WALL_HEAD);
|
||||
temp.add(Blocks.SKELETON_SKULL);
|
||||
temp.add(Blocks.SKELETON_WALL_SKULL);
|
||||
temp.add(Blocks.WITHER_SKELETON_SKULL);
|
||||
temp.add(Blocks.WITHER_SKELETON_WALL_SKULL);
|
||||
|
||||
temp.add(Blocks.ENCHANTING_TABLE);
|
||||
temp.add(Blocks.ANVIL);
|
||||
|
||||
temp.add(Blocks.WHITE_BED);
|
||||
temp.add(Blocks.ORANGE_BED);
|
||||
temp.add(Blocks.MAGENTA_BED);
|
||||
temp.add(Blocks.LIGHT_BLUE_BED);
|
||||
temp.add(Blocks.YELLOW_BED);
|
||||
temp.add(Blocks.LIME_BED);
|
||||
temp.add(Blocks.PINK_BED);
|
||||
temp.add(Blocks.GRAY_BED);
|
||||
temp.add(Blocks.LIGHT_GRAY_BED);
|
||||
temp.add(Blocks.CYAN_BED);
|
||||
temp.add(Blocks.PURPLE_BED);
|
||||
temp.add(Blocks.BLUE_BED);
|
||||
temp.add(Blocks.BROWN_BED);
|
||||
temp.add(Blocks.GREEN_BED);
|
||||
temp.add(Blocks.RED_BED);
|
||||
temp.add(Blocks.BLACK_BED);
|
||||
|
||||
temp.add(Blocks.DRAGON_EGG);
|
||||
temp.add(Blocks.JUKEBOX);
|
||||
temp.add(Blocks.END_GATEWAY);
|
||||
temp.add(Blocks.COBWEB);
|
||||
temp.add(Blocks.NETHER_WART);
|
||||
temp.add(Blocks.LADDER);
|
||||
temp.add(Blocks.VINE);
|
||||
BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp);
|
||||
|
||||
// TODO: Lit Furnaces
|
||||
}
|
||||
|
||||
/**
|
||||
* The size of the chunk data in bits. Equal to 16 KiB.
|
||||
@@ -170,29 +204,20 @@ public final class CachedChunk {
|
||||
|
||||
// we have this exact block, it's a surface block
|
||||
/*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));
|
||||
if (!Minecraft.getInstance().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock().equals(state.getBlock())) {
|
||||
throw new IllegalStateException("failed " + Minecraft.getInstance().world.getBlockState(new BlockPos(x + this.x * 16, y, z + this.z * 16)).getBlock() + " " + state.getBlock() + " " + (x + this.x * 16) + " " + y + " " + (z + this.z * 16));
|
||||
}*/
|
||||
return overview[internalPos];
|
||||
}
|
||||
if (special != null) {
|
||||
String str = special.get(index);
|
||||
if (str != null) {
|
||||
return BlockUtils.stringToBlockRequired(str).getDefaultState();
|
||||
return ChunkPacker.stringToBlockRequired(str).getDefaultState();
|
||||
}
|
||||
}
|
||||
|
||||
if (type == PathingBlockType.SOLID) {
|
||||
if (y == 127 && dimension == -1) {
|
||||
// nether roof is always unbreakable
|
||||
return Blocks.BEDROCK.getDefaultState();
|
||||
}
|
||||
if (y < 5 && dimension == 0) {
|
||||
// solid blocks below 5 are commonly bedrock
|
||||
// however, returning bedrock always would be a little yikes
|
||||
// discourage paths that include breaking blocks below 5 a little more heavily just so that it takes paths breaking what's known to be stone (at 5 or above) instead of what could maybe be bedrock (below 5)
|
||||
return Blocks.OBSIDIAN.getDefaultState();
|
||||
}
|
||||
if (type == PathingBlockType.SOLID && y == 127 && dimension == -1) {
|
||||
return Blocks.BEDROCK.getDefaultState();
|
||||
}
|
||||
return ChunkPacker.pathingTypeToBlock(type, dimension);
|
||||
}
|
||||
|
||||
@@ -19,7 +19,6 @@ package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.ICachedRegion;
|
||||
import baritone.api.utils.BlockUtils;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
@@ -150,7 +149,7 @@ public final class CachedRegion implements ICachedRegion {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (chunks[x][z] != null) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
out.writeUTF(BlockUtils.blockToString(chunks[x][z].getOverview()[i].getBlock()));
|
||||
out.writeUTF(ChunkPacker.blockToString(chunks[x][z].getOverview()[i].getBlock()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -241,7 +240,7 @@ public final class CachedRegion implements ICachedRegion {
|
||||
for (int z = 0; z < 32; z++) {
|
||||
if (present[x][z]) {
|
||||
for (int i = 0; i < 256; i++) {
|
||||
overview[x][z][i] = BlockUtils.stringToBlockRequired(in.readUTF()).getDefaultState();
|
||||
overview[x][z][i] = ChunkPacker.stringToBlockRequired(in.readUTF()).getDefaultState();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -256,7 +255,7 @@ public final class CachedRegion implements ICachedRegion {
|
||||
int numSpecialBlockTypes = in.readShort() & 0xffff;
|
||||
for (int i = 0; i < numSpecialBlockTypes; i++) {
|
||||
String blockName = in.readUTF();
|
||||
BlockUtils.stringToBlockRequired(blockName);
|
||||
ChunkPacker.stringToBlockRequired(blockName);
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
location[x][z].put(blockName, locs);
|
||||
int numLocations = in.readShort() & 0xffff;
|
||||
|
||||
11
src/main/java/baritone/cache/CachedWorld.java
vendored
11
src/main/java/baritone/cache/CachedWorld.java
vendored
@@ -22,7 +22,7 @@ import baritone.api.BaritoneAPI;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.cache.ICachedWorld;
|
||||
import baritone.api.cache.IWorldData;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.utils.Helper;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectMap;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
@@ -180,8 +180,8 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
if (region == null) {
|
||||
continue;
|
||||
}
|
||||
int distX = ((region.getX() << 9) + 256) - pruneCenter.getX();
|
||||
int distZ = ((region.getZ() << 9) + 256) - pruneCenter.getZ();
|
||||
int distX = (region.getX() << 9 + 256) - pruneCenter.getX();
|
||||
int distZ = (region.getZ() << 9 + 256) - pruneCenter.getZ();
|
||||
double dist = Math.sqrt(distX * distX + distZ * distZ);
|
||||
if (dist > 1024) {
|
||||
logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
|
||||
@@ -216,7 +216,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
if (mostRecentlyModified == null) {
|
||||
return new BlockPos(0, 0, 0);
|
||||
}
|
||||
return new BlockPos((mostRecentlyModified.x << 4) + 8, 0, (mostRecentlyModified.z << 4) + 8);
|
||||
return new BlockPos(mostRecentlyModified.x << 4 + 8, 0, mostRecentlyModified.z << 4 + 8);
|
||||
}
|
||||
|
||||
private synchronized List<CachedRegion> allRegions() {
|
||||
@@ -303,9 +303,6 @@ public final class CachedWorld implements ICachedWorld, Helper {
|
||||
} catch (InterruptedException e) {
|
||||
e.printStackTrace();
|
||||
break;
|
||||
} catch (Throwable th) {
|
||||
// in the case of an exception, keep consuming from the queue so as not to leak memory
|
||||
th.printStackTrace();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
61
src/main/java/baritone/cache/ChunkPacker.java
vendored
61
src/main/java/baritone/cache/ChunkPacker.java
vendored
@@ -17,16 +17,18 @@
|
||||
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.api.utils.BlockUtils;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.pathing.PathingBlockType;
|
||||
import net.minecraft.block.*;
|
||||
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.util.math.Vec3d;
|
||||
import net.minecraft.util.registry.IRegistry;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
@@ -36,6 +38,8 @@ import java.util.*;
|
||||
*/
|
||||
public final class ChunkPacker {
|
||||
|
||||
private static final Map<String, Block> resourceCache = new HashMap<>();
|
||||
|
||||
private ChunkPacker() {}
|
||||
|
||||
public static CachedChunk pack(Chunk chunk) {
|
||||
@@ -44,9 +48,9 @@ public final class ChunkPacker {
|
||||
Map<String, List<BlockPos>> specialBlocks = new HashMap<>();
|
||||
BitSet bitSet = new BitSet(CachedChunk.SIZE);
|
||||
try {
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
ChunkSection[] chunkInternalStorageArray = chunk.getSections();
|
||||
for (int y0 = 0; y0 < 16; y0++) {
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
ChunkSection 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
|
||||
@@ -58,7 +62,7 @@ public final class ChunkPacker {
|
||||
// since a bitset is initialized to all zero, and air is saved as zeros
|
||||
continue;
|
||||
}
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
BlockStateContainer<IBlockState> 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
|
||||
@@ -73,7 +77,7 @@ public final class ChunkPacker {
|
||||
bitSet.set(index + 1, bits[1]);
|
||||
Block block = state.getBlock();
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(block)) {
|
||||
String name = BlockUtils.blockToString(block);
|
||||
String name = blockToString(block);
|
||||
specialBlocks.computeIfAbsent(name, b -> new ArrayList<>()).add(new BlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
@@ -88,7 +92,8 @@ public final class ChunkPacker {
|
||||
IBlockState[] blocks = new IBlockState[256];
|
||||
|
||||
for (int z = 0; z < 16; z++) {
|
||||
https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
|
||||
https:
|
||||
//www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
|
||||
for (int x = 0; x < 16; x++) {
|
||||
for (int y = 255; y >= 0; y--) {
|
||||
int index = CachedChunk.getPositionIndex(x, y, z);
|
||||
@@ -103,40 +108,58 @@ public final class ChunkPacker {
|
||||
return new CachedChunk(chunk.x, chunk.z, bitSet, blocks, specialBlocks, System.currentTimeMillis());
|
||||
}
|
||||
|
||||
public static String blockToString(Block block) {
|
||||
ResourceLocation loc = IRegistry.BLOCK.getKey(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 stringToBlockRequired(String name) {
|
||||
if (name.equals("lit_redstone_ore")) {
|
||||
return stringToBlockRequired("redstone_ore");
|
||||
}
|
||||
Block block = stringToBlockNullable(name);
|
||||
Objects.requireNonNull(block);
|
||||
return block;
|
||||
}
|
||||
|
||||
public static Block stringToBlockNullable(String name) {
|
||||
return resourceCache.computeIfAbsent(name, n -> IRegistry.BLOCK.get(new ResourceLocation(n.contains(":") ? n : "minecraft:" + n)));
|
||||
}
|
||||
|
||||
private static PathingBlockType getPathingBlockType(IBlockState state, Chunk chunk, int x, int y, int z) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.WATER || block == Blocks.FLOWING_WATER) {
|
||||
if (MovementHelper.isWater(state)) {
|
||||
// only water source blocks are plausibly usable, flowing water should be avoid
|
||||
// FLOWING_WATER is a waterfall, it doesn't really matter and caching it as AVOID just makes it look wrong
|
||||
if (MovementHelper.possiblyFlowing(state)) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
if (
|
||||
(x != 15 && MovementHelper.possiblyFlowing(chunk.getBlockState(x + 1, y, z)))
|
||||
|| (x != 0 && MovementHelper.possiblyFlowing(chunk.getBlockState(x - 1, y, z)))
|
||||
|| (z != 15 && MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z + 1)))
|
||||
|| (z != 0 && MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z - 1)))
|
||||
) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
if (x == 0 || x == 15 || z == 0 || z == 15) {
|
||||
if (BlockLiquid.getSlopeAngle(chunk.getWorld(), new BlockPos(x + chunk.x << 4, y, z + chunk.z << 4), state.getMaterial(), state) == -1000.0F) {
|
||||
Vec3d flow = state.getFluidState().getFlow(chunk.getWorld(), new BlockPos(x + chunk.x << 4, y, z + chunk.z << 4));
|
||||
if (flow.x != 0.0 || flow.z != 0.0) {
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
if (MovementHelper.possiblyFlowing(chunk.getBlockState(x + 1, y, z)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x - 1, y, z)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z + 1)) || MovementHelper.possiblyFlowing(chunk.getBlockState(x, y, z - 1))) {
|
||||
return PathingBlockType.AVOID;
|
||||
}
|
||||
return PathingBlockType.WATER;
|
||||
}
|
||||
|
||||
if (MovementHelper.avoidWalkingInto(block) || MovementHelper.isBottomSlab(state)) {
|
||||
if (MovementHelper.avoidWalkingInto(state) || 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) {
|
||||
if (block instanceof BlockAir || block instanceof BlockTallGrass || block instanceof BlockDoublePlant || block instanceof BlockFlower) {
|
||||
return PathingBlockType.AIR;
|
||||
}
|
||||
|
||||
|
||||
@@ -29,7 +29,6 @@ import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.NoSuchFileException;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
|
||||
@@ -46,8 +45,6 @@ public class ContainerMemory implements IContainerMemory {
|
||||
this.saveTo = saveTo;
|
||||
try {
|
||||
read(Files.readAllBytes(saveTo));
|
||||
} catch (NoSuchFileException ignored) {
|
||||
inventories.clear();
|
||||
} catch (Exception ex) {
|
||||
ex.printStackTrace();
|
||||
inventories.clear();
|
||||
|
||||
@@ -15,8 +15,9 @@
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.api.cache;
|
||||
package baritone.cache;
|
||||
|
||||
import baritone.api.cache.IWaypoint;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.Date;
|
||||
@@ -46,7 +47,7 @@ public class Waypoint implements IWaypoint {
|
||||
* @param location The waypoint location
|
||||
* @param creationTimestamp When the waypoint was created
|
||||
*/
|
||||
public Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) {
|
||||
Waypoint(String name, Tag tag, BlockPos location, long creationTimestamp) {
|
||||
this.name = name;
|
||||
this.tag = tag;
|
||||
this.location = location;
|
||||
@@ -19,7 +19,6 @@ package baritone.cache;
|
||||
|
||||
import baritone.api.cache.IWaypoint;
|
||||
import baritone.api.cache.IWaypointCollection;
|
||||
import baritone.api.cache.Waypoint;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
11
src/main/java/baritone/cache/WorldProvider.java
vendored
11
src/main/java/baritone/cache/WorldProvider.java
vendored
@@ -19,11 +19,12 @@ package baritone.cache;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.cache.IWorldProvider;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.accessor.IAnvilChunkLoader;
|
||||
import baritone.utils.accessor.IChunkProviderServer;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.world.WorldServer;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
import org.apache.commons.lang3.SystemUtils;
|
||||
|
||||
import java.io.File;
|
||||
@@ -55,14 +56,14 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
*
|
||||
* @param dimension The ID of the world's dimension
|
||||
*/
|
||||
public final void initWorld(int dimension) {
|
||||
public final void initWorld(DimensionType dimension) {
|
||||
File directory;
|
||||
File readme;
|
||||
|
||||
IntegratedServer integratedServer = mc.getIntegratedServer();
|
||||
|
||||
// If there is an integrated server running (Aka Singleplayer) then do magic to find the world save file
|
||||
if (mc.isSingleplayer()) {
|
||||
if (integratedServer != null) {
|
||||
WorldServer localServerWorld = integratedServer.getWorld(dimension);
|
||||
IChunkProviderServer provider = (IChunkProviderServer) localServerWorld.getChunkProvider();
|
||||
IAnvilChunkLoader loader = (IAnvilChunkLoader) provider.getChunkLoader();
|
||||
@@ -92,7 +93,7 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
} catch (IOException ignored) {}
|
||||
|
||||
// We will actually store the world data in a subfolder: "DIM<id>"
|
||||
Path dir = new File(directory, "DIM" + dimension).toPath();
|
||||
Path dir = new File(directory, "DIM" + dimension.getId()).toPath();
|
||||
if (!Files.exists(dir)) {
|
||||
try {
|
||||
Files.createDirectories(dir);
|
||||
@@ -101,7 +102,7 @@ public class WorldProvider implements IWorldProvider, Helper {
|
||||
|
||||
System.out.println("Baritone world data dir: " + dir);
|
||||
synchronized (worldCache) {
|
||||
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension));
|
||||
this.currentWorld = worldCache.computeIfAbsent(dir, d -> new WorldData(d, dimension.getId()));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
12
src/main/java/baritone/cache/WorldScanner.java
vendored
12
src/main/java/baritone/cache/WorldScanner.java
vendored
@@ -26,7 +26,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
import net.minecraft.world.chunk.BlockStateContainer;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||
import net.minecraft.world.chunk.ChunkSection;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.IntStream;
|
||||
@@ -70,7 +70,7 @@ public enum WorldScanner implements IWorldScanner {
|
||||
foundChunks = true;
|
||||
int chunkX = xoff + playerChunkX;
|
||||
int chunkZ = zoff + playerChunkZ;
|
||||
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
||||
Chunk chunk = chunkProvider.getChunk(chunkX, chunkZ, false, false);
|
||||
if (chunk == null) {
|
||||
continue;
|
||||
}
|
||||
@@ -97,7 +97,7 @@ public enum WorldScanner implements IWorldScanner {
|
||||
}
|
||||
|
||||
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
|
||||
Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z);
|
||||
Chunk chunk = chunkProvider.getChunk(pos.x, pos.z, false, false);
|
||||
int playerY = ctx.playerFeet().getY();
|
||||
|
||||
if (chunk == null || chunk.isEmpty()) {
|
||||
@@ -110,16 +110,16 @@ public enum WorldScanner implements IWorldScanner {
|
||||
}
|
||||
|
||||
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
|
||||
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||
ChunkSection[] chunkInternalStorageArray = chunk.getSections();
|
||||
boolean foundWithinY = false;
|
||||
for (int yIndex = 0; yIndex < 16; yIndex++) {
|
||||
int y0 = coordinateIterationOrder[yIndex];
|
||||
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
ChunkSection extendedblockstorage = chunkInternalStorageArray[y0];
|
||||
if (extendedblockstorage == null) {
|
||||
continue;
|
||||
}
|
||||
int yReal = y0 << 4;
|
||||
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||
BlockStateContainer<IBlockState> bsc = extendedblockstorage.getData();
|
||||
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
|
||||
// for better cache locality, iterate in that order
|
||||
for (int y = 0; y < 16; y++) {
|
||||
|
||||
@@ -22,9 +22,9 @@ import baritone.api.event.events.*;
|
||||
import baritone.api.event.events.type.EventState;
|
||||
import baritone.api.event.listener.IEventBus;
|
||||
import baritone.api.event.listener.IGameEventListener;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.cache.WorldProvider;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.world.World;
|
||||
import net.minecraft.world.chunk.Chunk;
|
||||
|
||||
@@ -84,7 +84,7 @@ public final class GameEventHandler implements IEventBus, Helper {
|
||||
// to make sure the chunk being unloaded is already loaded.
|
||||
boolean isPreUnload = state == EventState.PRE
|
||||
&& type == ChunkEvent.Type.UNLOAD
|
||||
&& world.getChunkProvider().isChunkGeneratedAt(event.getX(), event.getZ());
|
||||
&& world.getChunkProvider().getChunk(event.getX(), event.getZ(), false, false) != null;
|
||||
|
||||
if (isPostPopulate || isPreUnload) {
|
||||
baritone.getWorldProvider().ifWorldLoaded(worldData -> {
|
||||
@@ -109,7 +109,7 @@ public final class GameEventHandler implements IEventBus, Helper {
|
||||
if (event.getState() == EventState.POST) {
|
||||
cache.closeWorld();
|
||||
if (event.getWorld() != null) {
|
||||
cache.initWorld(event.getWorld().provider.getDimensionType().getId());
|
||||
cache.initWorld(event.getWorld().getDimension().getType());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -76,7 +76,6 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
int timeCheckInterval = 1 << 6;
|
||||
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.value; // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
|
||||
double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.value ? MIN_IMPROVEMENT : 0;
|
||||
Moves[] allMoves = Moves.values();
|
||||
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
|
||||
if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
|
||||
long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
|
||||
@@ -87,7 +86,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
if (slowPath) {
|
||||
try {
|
||||
Thread.sleep(Baritone.settings().slowPathTimeDelayMS.value);
|
||||
} catch (InterruptedException ignored) {}
|
||||
} catch (InterruptedException ex) {
|
||||
}
|
||||
}
|
||||
PathNode currentNode = openSet.removeLowest();
|
||||
mostRecentConsidered = currentNode;
|
||||
@@ -96,7 +96,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
|
||||
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
|
||||
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
|
||||
}
|
||||
for (Moves moves : allMoves) {
|
||||
for (Moves moves : Moves.values()) {
|
||||
int newX = currentNode.x + moves.xOffset;
|
||||
int newZ = currentNode.z + moves.zOffset;
|
||||
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) {
|
||||
|
||||
@@ -22,9 +22,9 @@ import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.calc.IPathFinder;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.PathCalculationResult;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.utils.Helper;
|
||||
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
|
||||
|
||||
import java.util.Optional;
|
||||
@@ -127,7 +127,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_SEGMENT, path);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
Helper.HELPER.logDirect("Pathing exception: " + e);
|
||||
Helper.HELPER.logDebug("Pathing exception: " + e);
|
||||
e.printStackTrace();
|
||||
return new PathCalculationResult(PathCalculationResult.Type.EXCEPTION);
|
||||
} finally {
|
||||
@@ -186,7 +186,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
|
||||
}
|
||||
|
||||
protected Optional<IPath> bestSoFar(boolean logInfo, int numNodes) {
|
||||
if (startNode == null) {
|
||||
if (startNode == null || bestSoFar == null) {
|
||||
return Optional.empty();
|
||||
}
|
||||
double bestDist = 0;
|
||||
|
||||
@@ -21,11 +21,11 @@ import baritone.api.pathing.calc.IPath;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.Moves;
|
||||
import baritone.pathing.path.CutoffPath;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.pathing.PathBase;
|
||||
|
||||
import java.util.ArrayList;
|
||||
@@ -72,12 +72,31 @@ class Path extends PathBase {
|
||||
this.start = new BetterBlockPos(start.x, start.y, start.z);
|
||||
this.end = new BetterBlockPos(end.x, end.y, end.z);
|
||||
this.numNodes = numNodes;
|
||||
this.path = new ArrayList<>();
|
||||
this.movements = new ArrayList<>();
|
||||
this.nodes = new ArrayList<>();
|
||||
this.goal = goal;
|
||||
this.context = context;
|
||||
assemblePath(end);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
}
|
||||
|
||||
/**
|
||||
* Assembles this path given the end node.
|
||||
*
|
||||
* @param end The end node
|
||||
*/
|
||||
private void assemblePath(PathNode end) {
|
||||
if (!path.isEmpty() || !movements.isEmpty()) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
PathNode current = end;
|
||||
LinkedList<BetterBlockPos> tempPath = new LinkedList<>();
|
||||
LinkedList<PathNode> tempNodes = new LinkedList<>();
|
||||
LinkedList<PathNode> tempNodes = new LinkedList();
|
||||
// Repeatedly inserting to the beginning of an arraylist is O(n^2)
|
||||
// Instead, do it into a linked list, then convert at the end
|
||||
while (current != null) {
|
||||
@@ -88,13 +107,8 @@ class Path extends PathBase {
|
||||
// Can't directly convert from the PathNode pseudo linked list to an array because we don't know how long it is
|
||||
// inserting into a LinkedList<E> keeps track of length, then when we addall (which calls .toArray) it's able
|
||||
// to performantly do that conversion since it knows the length.
|
||||
this.path = new ArrayList<>(tempPath);
|
||||
this.nodes = new ArrayList<>(tempNodes);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Goal getGoal() {
|
||||
return goal;
|
||||
path.addAll(tempPath);
|
||||
nodes.addAll(tempNodes);
|
||||
}
|
||||
|
||||
private boolean assembleMovements() {
|
||||
|
||||
@@ -58,7 +58,6 @@ public class CalculationContext {
|
||||
public final boolean allowParkour;
|
||||
public final boolean allowParkourPlace;
|
||||
public final boolean allowJumpAt256;
|
||||
public final boolean allowParkourAscend;
|
||||
public final boolean assumeWalkOnWater;
|
||||
public final boolean allowDiagonalDescend;
|
||||
public final boolean allowDownward;
|
||||
@@ -84,14 +83,13 @@ public class CalculationContext {
|
||||
this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread);
|
||||
this.toolSet = new ToolSet(player);
|
||||
this.hasThrowaway = Baritone.settings().allowPlace.value && ((Baritone) baritone).getInventoryBehavior().hasGenericThrowaway();
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
|
||||
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.value && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.getDimension().isNether();
|
||||
this.canSprint = Baritone.settings().allowSprint.value && player.getFoodStats().getFoodLevel() > 6;
|
||||
this.placeBlockCost = Baritone.settings().blockPlacementPenalty.value;
|
||||
this.allowBreak = Baritone.settings().allowBreak.value;
|
||||
this.allowParkour = Baritone.settings().allowParkour.value;
|
||||
this.allowParkourPlace = Baritone.settings().allowParkourPlace.value;
|
||||
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.value;
|
||||
this.allowParkourAscend = Baritone.settings().allowParkourAscend.value;
|
||||
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.value;
|
||||
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.value;
|
||||
this.allowDownward = Baritone.settings().allowDownward.value;
|
||||
|
||||
@@ -17,25 +17,23 @@
|
||||
|
||||
package baritone.pathing.movement;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.IBaritone;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.entity.item.EntityFallingBlock;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.AxisAlignedBB;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Objects;
|
||||
import java.util.Optional;
|
||||
|
||||
public abstract class Movement implements IMovement, MovementHelper {
|
||||
|
||||
public static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
|
||||
public static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
|
||||
|
||||
protected final IBaritone baritone;
|
||||
protected final IPlayerContext ctx;
|
||||
@@ -62,8 +60,6 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
public List<BlockPos> toPlaceCached = null;
|
||||
public List<BlockPos> toWalkIntoCached = null;
|
||||
|
||||
private Set<BetterBlockPos> validPositionsCached = null;
|
||||
|
||||
private Boolean calculatedWhileLoaded;
|
||||
|
||||
protected Movement(IBaritone baritone, BetterBlockPos src, BetterBlockPos dest, BetterBlockPos[] toBreak, BetterBlockPos toPlace) {
|
||||
@@ -101,20 +97,6 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
this.cost = cost;
|
||||
}
|
||||
|
||||
protected abstract Set<BetterBlockPos> calculateValidPositions();
|
||||
|
||||
public Set<BetterBlockPos> getValidPositions() {
|
||||
if (validPositionsCached == null) {
|
||||
validPositionsCached = calculateValidPositions();
|
||||
Objects.requireNonNull(validPositionsCached);
|
||||
}
|
||||
return validPositionsCached;
|
||||
}
|
||||
|
||||
protected boolean playerInValidPosition() {
|
||||
return getValidPositions().contains(ctx.playerFeet()) || getValidPositions().contains(((PathingBehavior) baritone.getPathingBehavior()).pathStart());
|
||||
}
|
||||
|
||||
/**
|
||||
* Handles the execution of the latest Movement
|
||||
* State, and offers a Status to the calling class.
|
||||
@@ -123,13 +105,12 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
*/
|
||||
@Override
|
||||
public MovementStatus update() {
|
||||
ctx.player().capabilities.isFlying = false;
|
||||
ctx.player().abilities.isFlying = false;
|
||||
currentState = updateState(currentState);
|
||||
if (MovementHelper.isLiquid(ctx, ctx.playerFeet())) {
|
||||
currentState.setInput(Input.JUMP, true);
|
||||
}
|
||||
if (ctx.player().isEntityInsideOpaqueBlock()) {
|
||||
ctx.getSelectedBlock().ifPresent(pos -> MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, pos)));
|
||||
currentState.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
|
||||
@@ -158,17 +139,14 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
}
|
||||
boolean somethingInTheWay = false;
|
||||
for (BetterBlockPos blockPos : positionsToBreak) {
|
||||
if (!ctx.world().getEntitiesWithinAABB(EntityFallingBlock.class, new AxisAlignedBB(0, 0, 0, 1, 1.1, 1).offset(blockPos)).isEmpty() && Baritone.settings().pauseMiningForFallingBlocks.value) {
|
||||
return false;
|
||||
}
|
||||
if (!MovementHelper.canWalkThrough(ctx, blockPos) && !(BlockStateInterface.getBlock(ctx, blockPos) instanceof BlockLiquid)) { // can't break liquid, so don't try
|
||||
if (!MovementHelper.canWalkThrough(ctx, blockPos)) { // can't break air, so don't try
|
||||
somethingInTheWay = true;
|
||||
MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, blockPos));
|
||||
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), blockPos, ctx.playerController().getBlockReachDistance());
|
||||
if (reachable.isPresent()) {
|
||||
Rotation rotTowardsBlock = reachable.get();
|
||||
MovementHelper.switchToBestToolFor(ctx, BlockStateInterface.get(ctx, blockPos));
|
||||
state.setTarget(new MovementState.MovementTarget(rotTowardsBlock, true));
|
||||
if (ctx.isLookingAt(blockPos) || ctx.playerRotations().isReallyCloseTo(rotTowardsBlock)) {
|
||||
if (Objects.equals(ctx.getSelectedBlock().orElse(null), blockPos) || ctx.playerRotations().isReallyCloseTo(rotTowardsBlock)) {
|
||||
state.setInput(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return false;
|
||||
@@ -177,7 +155,7 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
//i'm doing it anyway
|
||||
//i dont care if theres snow in the way!!!!!!!
|
||||
//you dont own me!!!!
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.player().getEyePosition(1.0F),
|
||||
VecUtils.getBlockPosCenter(blockPos), ctx.playerRotations()), true)
|
||||
);
|
||||
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
|
||||
@@ -291,8 +269,4 @@ public abstract class Movement implements IMovement, MovementHelper {
|
||||
}
|
||||
return toWalkIntoCached;
|
||||
}
|
||||
|
||||
public BlockPos[] toBreakAll() {
|
||||
return positionsToBreak;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,11 +25,19 @@ import baritone.api.utils.*;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.MovementState.MovementTarget;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.Helper;
|
||||
import baritone.utils.ToolSet;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.properties.PropertyBool;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.fluid.FlowingFluid;
|
||||
import net.minecraft.fluid.Fluid;
|
||||
import net.minecraft.fluid.IFluidState;
|
||||
import net.minecraft.fluid.WaterFluid;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Fluids;
|
||||
import net.minecraft.pathfinding.PathType;
|
||||
import net.minecraft.state.BooleanProperty;
|
||||
import net.minecraft.state.properties.SlabType;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
@@ -37,7 +45,7 @@ import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Optional;
|
||||
|
||||
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP;
|
||||
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP;
|
||||
|
||||
/**
|
||||
* Static helpers for cost calculation
|
||||
@@ -51,27 +59,11 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|
||||
|| b instanceof BlockSilverfish // obvious reasons
|
||||
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
|
||||
|| avoidAdjacentBreaking(bsi, x, y + 1, z, true)
|
||||
|| avoidAdjacentBreaking(bsi, x + 1, y, z, false)
|
||||
|| avoidAdjacentBreaking(bsi, x - 1, y, z, false)
|
||||
|| avoidAdjacentBreaking(bsi, x, y, z + 1, false)
|
||||
|| avoidAdjacentBreaking(bsi, x, y, z - 1, false);
|
||||
}
|
||||
|
||||
static boolean avoidAdjacentBreaking(BlockStateInterface bsi, int x, int y, int z, boolean directlyAbove) {
|
||||
// returns true if you should avoid breaking a block that's adjacent to this one (e.g. lava that will start flowing if you give it a path)
|
||||
// this is only called for north, south, east, west, and up. this is NOT called for down.
|
||||
// we assume that it's ALWAYS okay to break the block thats ABOVE liquid
|
||||
IBlockState state = bsi.get0(x, y, z);
|
||||
Block block = state.getBlock();
|
||||
if (!directlyAbove // it is fine to mine a block that has a falling block directly above, this (the cost of breaking the stacked fallings) is included in cost calculations
|
||||
// therefore if directlyAbove is true, we will actually ignore if this is falling
|
||||
&& block instanceof BlockFalling // obviously, this check is only valid for falling blocks
|
||||
&& Baritone.settings().avoidUpdatingFallingBlocks.value // and if the setting is enabled
|
||||
&& BlockFalling.canFallThrough(bsi.get0(x, y - 1, z))) { // and if it would fall (i.e. it's unsupported)
|
||||
return true; // dont break a block that is adjacent to unsupported gravel because it can cause really weird stuff
|
||||
}
|
||||
return block instanceof BlockLiquid;
|
||||
|| !bsi.get0(x, y + 1, z).getFluidState().isEmpty()//don't break anything touching liquid on any side
|
||||
|| !bsi.get0(x + 1, y, z).getFluidState().isEmpty()
|
||||
|| !bsi.get0(x - 1, y, z).getFluidState().isEmpty()
|
||||
|| !bsi.get0(x, y, z + 1).getFluidState().isEmpty()
|
||||
|| !bsi.get0(x, y, z - 1).getFluidState().isEmpty();
|
||||
}
|
||||
|
||||
static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) {
|
||||
@@ -84,13 +76,10 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean canWalkThrough(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) { // early return for most common case
|
||||
if (block instanceof BlockAir) { // early return for most common case
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block instanceof BlockTrapDoor) {
|
||||
return false;
|
||||
}
|
||||
if (Baritone.settings().blocksToAvoid.value.contains(block)) {
|
||||
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.COBWEB || block == Blocks.END_PORTAL || block == Blocks.COCOA || block instanceof BlockSkull || block == Blocks.BUBBLE_COLUMN || block instanceof BlockShulkerBox || block instanceof BlockSlab || block instanceof BlockTrapDoor) {
|
||||
return false;
|
||||
}
|
||||
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
|
||||
@@ -99,10 +88,10 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// be opened by just interacting.
|
||||
return block != Blocks.IRON_DOOR;
|
||||
}
|
||||
if (block == Blocks.CARPET) {
|
||||
if (block instanceof BlockCarpet) {
|
||||
return canWalkOn(bsi, x, y - 1, z);
|
||||
}
|
||||
if (block instanceof BlockSnow) {
|
||||
if (block instanceof BlockSnowLayer) {
|
||||
// we've already checked doors and fence gates
|
||||
// so the only remaining dynamic isPassables are snow and trapdoor
|
||||
// if they're cached as a top block, we don't know their metadata
|
||||
@@ -112,7 +101,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
}
|
||||
// the check in BlockSnow.isPassable is layers < 5
|
||||
// while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling
|
||||
if (state.getValue(BlockSnow.LAYERS) >= 3) {
|
||||
if (state.get(BlockSnowLayer.LAYERS) >= 3) {
|
||||
return false;
|
||||
}
|
||||
// ok, it's low enough we could walk through it, but is it supported?
|
||||
@@ -121,20 +110,21 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (isFlowing(x, y, z, state, bsi)) {
|
||||
return false; // Don't walk through flowing liquids
|
||||
}
|
||||
if (block instanceof BlockLiquid) {
|
||||
IFluidState fluidState = state.getFluidState();
|
||||
if (fluidState.getFluid() instanceof WaterFluid) {
|
||||
if (Baritone.settings().assumeWalkOnWater.value) {
|
||||
return false;
|
||||
}
|
||||
IBlockState up = bsi.get0(x, y + 1, z);
|
||||
if (up.getBlock() instanceof BlockLiquid || up.getBlock() instanceof BlockLilyPad) {
|
||||
if (!up.getFluidState().isEmpty() || up.getBlock() instanceof BlockLilyPad) {
|
||||
return false;
|
||||
}
|
||||
return block == Blocks.WATER || block == Blocks.FLOWING_WATER;
|
||||
return true;
|
||||
}
|
||||
// every block that overrides isPassable with anything more complicated than a "return true;" or "return false;"
|
||||
// has already been accounted for above
|
||||
// therefore it's safe to not construct a blockpos from our x, y, z ints and instead just pass null
|
||||
return block.isPassable(null, BlockPos.ORIGIN);
|
||||
return state.allowsMovement(null, null, PathType.LAND);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -153,27 +143,28 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean fullyPassable(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR) { // early return for most common case
|
||||
if (block instanceof BlockAir) { // early return for most common case
|
||||
return true;
|
||||
}
|
||||
// exceptions - blocks that are isPassable true, but we can't actually jump through
|
||||
if (block == Blocks.FIRE
|
||||
|| block == Blocks.TRIPWIRE
|
||||
|| block == Blocks.WEB
|
||||
|| block == Blocks.COBWEB
|
||||
|| block == Blocks.VINE
|
||||
|| block == Blocks.LADDER
|
||||
|| block == Blocks.COCOA
|
||||
|| block instanceof BlockDoor
|
||||
|| block instanceof BlockFenceGate
|
||||
|| block instanceof BlockSnow
|
||||
|| block instanceof BlockLiquid
|
||||
|| !state.getFluidState().isEmpty()
|
||||
|| block instanceof BlockTrapDoor
|
||||
|| block instanceof BlockEndPortal
|
||||
|| block instanceof BlockSkull) {
|
||||
|| block instanceof BlockSkull
|
||||
|| block instanceof BlockShulkerBox) {
|
||||
return false;
|
||||
}
|
||||
// door, fence gate, liquid, trapdoor have been accounted for, nothing else uses the world or pos parameters
|
||||
return block.isPassable(null, null);
|
||||
return state.allowsMovement(null, null, PathType.LAND);
|
||||
}
|
||||
|
||||
static boolean isReplacable(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
|
||||
@@ -188,20 +179,19 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* }
|
||||
*/
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR || isWater(block)) {
|
||||
if (block instanceof BlockAir) {
|
||||
// early return for common cases hehe
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSnow) {
|
||||
if (block instanceof BlockSnowLayer) {
|
||||
// as before, default to true (mostly because it would otherwise make long distance pathing through snowy biomes impossible)
|
||||
if (!bsi.worldContainsLoadedChunk(x, z)) {
|
||||
return true;
|
||||
}
|
||||
return state.getValue(BlockSnow.LAYERS) == 1;
|
||||
return state.get(BlockSnowLayer.LAYERS) == 1;
|
||||
}
|
||||
if (block instanceof BlockDoublePlant) {
|
||||
BlockDoublePlant.EnumPlantType kek = state.getValue(BlockDoublePlant.VARIANT);
|
||||
return kek == BlockDoublePlant.EnumPlantType.FERN || kek == BlockDoublePlant.EnumPlantType.GRASS;
|
||||
if (block == Blocks.LARGE_FERN || block == Blocks.TALL_GRASS) {
|
||||
return true;
|
||||
}
|
||||
return state.getMaterial().isReplaceable();
|
||||
}
|
||||
@@ -229,16 +219,16 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return true;
|
||||
}
|
||||
|
||||
return state.getValue(BlockFenceGate.OPEN);
|
||||
return state.get(BlockFenceGate.OPEN);
|
||||
}
|
||||
|
||||
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, PropertyBool propertyOpen) {
|
||||
static boolean isHorizontalBlockPassable(BlockPos blockPos, IBlockState blockState, BlockPos playerPos, BooleanProperty propertyOpen) {
|
||||
if (playerPos.equals(blockPos)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
EnumFacing.Axis facing = blockState.getValue(BlockHorizontal.FACING).getAxis();
|
||||
boolean open = blockState.getValue(propertyOpen);
|
||||
EnumFacing.Axis facing = blockState.get(BlockHorizontal.HORIZONTAL_FACING).getAxis();
|
||||
boolean open = blockState.get(propertyOpen);
|
||||
|
||||
EnumFacing.Axis playerFacing;
|
||||
if (playerPos.north().equals(blockPos) || playerPos.south().equals(blockPos)) {
|
||||
@@ -252,13 +242,15 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return (facing == playerFacing) == open;
|
||||
}
|
||||
|
||||
static boolean avoidWalkingInto(Block block) {
|
||||
return block instanceof BlockLiquid
|
||||
|| block == Blocks.MAGMA
|
||||
static boolean avoidWalkingInto(IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
return !state.getFluidState().isEmpty()
|
||||
|| block == Blocks.MAGMA_BLOCK
|
||||
|| block == Blocks.CACTUS
|
||||
|| block == Blocks.FIRE
|
||||
|| block == Blocks.END_PORTAL
|
||||
|| block == Blocks.WEB;
|
||||
|| block == Blocks.COBWEB
|
||||
|| block == Blocks.BUBBLE_COLUMN;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -275,7 +267,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
*/
|
||||
static boolean canWalkOn(BlockStateInterface bsi, int x, int y, int z, IBlockState state) {
|
||||
Block block = state.getBlock();
|
||||
if (block == Blocks.AIR || block == Blocks.MAGMA) {
|
||||
if (block instanceof BlockAir || block == Blocks.MAGMA_BLOCK || block == Blocks.BUBBLE_COLUMN) {
|
||||
// early return for most common case (air)
|
||||
// plus magma, which is a normal cube but it hurts you
|
||||
return false;
|
||||
@@ -292,33 +284,31 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
|
||||
return true;
|
||||
}
|
||||
if (isWater(block)) {
|
||||
if (isWater(state)) {
|
||||
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
|
||||
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
|
||||
Block up = bsi.get0(x, y + 1, z).getBlock();
|
||||
if (up == Blocks.WATERLILY || up == Blocks.CARPET) {
|
||||
IBlockState upState = bsi.get0(x, y + 1, z);
|
||||
Block up = upState.getBlock();
|
||||
if (up == Blocks.LILY_PAD || up instanceof BlockCarpet) {
|
||||
return true;
|
||||
}
|
||||
if (isFlowing(x, y, z, state, bsi) || block == Blocks.FLOWING_WATER) {
|
||||
if (isFlowing(x, y, z, state, bsi) || upState.getFluidState().getFluid() == Fluids.FLOWING_WATER) {
|
||||
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
|
||||
return isWater(up) && !Baritone.settings().assumeWalkOnWater.value;
|
||||
return isWater(upState) && !Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
|
||||
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
|
||||
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.value;
|
||||
return isWater(upState) ^ Baritone.settings().assumeWalkOnWater.value;
|
||||
}
|
||||
if (Baritone.settings().assumeWalkOnLava.value && isLava(block) && !isFlowing(x, y, z, state, bsi)) {
|
||||
if (Baritone.settings().assumeWalkOnLava.value && isLava(state) && !isFlowing(x, y, z, state, bsi)) {
|
||||
return true;
|
||||
}
|
||||
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
|
||||
if (block == Blocks.GLASS || block instanceof BlockStainedGlass) {
|
||||
return true;
|
||||
}
|
||||
if (block instanceof BlockSlab) {
|
||||
if (!Baritone.settings().allowWalkOnBottomSlab.value) {
|
||||
if (((BlockSlab) block).isDouble()) {
|
||||
return true;
|
||||
}
|
||||
return state.getValue(BlockSlab.HALF) != BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
return state.isTopSolid();
|
||||
}
|
||||
return true;
|
||||
}
|
||||
@@ -329,10 +319,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z, state);
|
||||
}
|
||||
|
||||
static boolean canWalkOn(IPlayerContext ctx, BlockPos pos) {
|
||||
return canWalkOn(new BlockStateInterface(ctx), pos.getX(), pos.getY(), pos.getZ());
|
||||
}
|
||||
|
||||
static boolean canWalkOn(IPlayerContext ctx, BetterBlockPos pos) {
|
||||
return canWalkOn(new BlockStateInterface(ctx), pos.x, pos.y, pos.z);
|
||||
}
|
||||
@@ -357,7 +343,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
// can we look at the center of a side face of this block and likely be able to place?
|
||||
// (thats how this check is used)
|
||||
// therefore dont include weird things that we technically could place against (like carpet) but practically can't
|
||||
return state.isBlockNormalCube() || state.isFullBlock() || state.getBlock() == Blocks.GLASS || state.getBlock() == Blocks.STAINED_GLASS;
|
||||
return state.isBlockNormalCube() || state.isFullCube() || state.getBlock() == Blocks.GLASS || state.getBlock() instanceof BlockStainedGlass;
|
||||
}
|
||||
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, boolean includeFalling) {
|
||||
@@ -367,9 +353,6 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
|
||||
Block block = state.getBlock();
|
||||
if (!canWalkThrough(context.bsi, x, y, z, state)) {
|
||||
if (block instanceof BlockLiquid) {
|
||||
return COST_INF;
|
||||
}
|
||||
double mult = context.breakCostMultiplierAt(x, y, z);
|
||||
if (mult >= COST_INF) {
|
||||
return COST_INF;
|
||||
@@ -377,11 +360,16 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
if (avoidBreaking(context.bsi, x, y, z, state)) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (!state.getFluidState().isEmpty()) {
|
||||
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.toolSet.getStrVsBlock(state);
|
||||
if (strVsBlock <= 0) {
|
||||
return COST_INF;
|
||||
}
|
||||
double result = 1 / strVsBlock;
|
||||
|
||||
double result = m / strVsBlock;
|
||||
result += context.breakBlockAdditionalCost;
|
||||
result *= mult;
|
||||
if (includeFalling) {
|
||||
@@ -397,8 +385,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
|
||||
static boolean isBottomSlab(IBlockState state) {
|
||||
return state.getBlock() instanceof BlockSlab
|
||||
&& !((BlockSlab) state.getBlock()).isDouble()
|
||||
&& state.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM;
|
||||
&& state.get(BlockSlab.TYPE) == SlabType.BOTTOM;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -435,11 +422,12 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* Returns whether or not the specified block is
|
||||
* water, regardless of whether or not it is flowing.
|
||||
*
|
||||
* @param b The block
|
||||
* @param state The block state
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(Block b) {
|
||||
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
|
||||
static boolean isWater(IBlockState state) {
|
||||
Fluid f = state.getFluidState().getFluid();
|
||||
return f == Fluids.WATER || f == Fluids.FLOWING_WATER;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -451,11 +439,12 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return Whether or not the block is water
|
||||
*/
|
||||
static boolean isWater(IPlayerContext ctx, BlockPos bp) {
|
||||
return isWater(BlockStateInterface.getBlock(ctx, bp));
|
||||
return isWater(BlockStateInterface.get(ctx, bp));
|
||||
}
|
||||
|
||||
static boolean isLava(Block b) {
|
||||
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
|
||||
static boolean isLava(IBlockState state) {
|
||||
Fluid f = state.getFluidState().getFluid();
|
||||
return f == Fluids.LAVA || f == Fluids.FLOWING_LAVA;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -466,20 +455,25 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
* @return Whether or not the block is a liquid
|
||||
*/
|
||||
static boolean isLiquid(IPlayerContext ctx, BlockPos p) {
|
||||
return BlockStateInterface.getBlock(ctx, p) instanceof BlockLiquid;
|
||||
return isLiquid(BlockStateInterface.get(ctx, p));
|
||||
}
|
||||
|
||||
static boolean isLiquid(IBlockState blockState) {
|
||||
return !blockState.getFluidState().isEmpty();
|
||||
}
|
||||
|
||||
static boolean possiblyFlowing(IBlockState state) {
|
||||
// Will be IFluidState in 1.13
|
||||
return state.getBlock() instanceof BlockLiquid
|
||||
&& state.getValue(BlockLiquid.LEVEL) != 0;
|
||||
IFluidState fluidState = state.getFluidState();
|
||||
return fluidState.getFluid() instanceof FlowingFluid
|
||||
&& fluidState.getFluid().getLevel(fluidState) != 8;
|
||||
}
|
||||
|
||||
static boolean isFlowing(int x, int y, int z, IBlockState state, BlockStateInterface bsi) {
|
||||
if (!(state.getBlock() instanceof BlockLiquid)) {
|
||||
IFluidState fluidState = state.getFluidState();
|
||||
if (!(fluidState.getFluid() instanceof FlowingFluid)) {
|
||||
return false;
|
||||
}
|
||||
if (state.getValue(BlockLiquid.LEVEL) != 0) {
|
||||
if (fluidState.getFluid().getLevel(fluidState) != 8) {
|
||||
return true;
|
||||
}
|
||||
return possiblyFlowing(bsi.get0(x + 1, y, z))
|
||||
@@ -498,19 +492,19 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
found = true;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
BlockPos against1 = placeAt.offset(HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
|
||||
BlockPos against1 = placeAt.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
|
||||
if (MovementHelper.canPlaceAgainst(ctx, against1)) {
|
||||
if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(false, placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block
|
||||
Helper.HELPER.logDebug("bb pls get me some blocks. dirt, netherrack, cobble");
|
||||
if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block
|
||||
Helper.HELPER.logDebug("bb pls get me some blocks. dirt or cobble");
|
||||
state.setStatus(MovementStatus.UNREACHABLE);
|
||||
return PlaceResult.NO_OPTION;
|
||||
}
|
||||
double faceX = (placeAt.getX() + against1.getX() + 1.0D) * 0.5D;
|
||||
double faceY = (placeAt.getY() + against1.getY() + 0.5D) * 0.5D;
|
||||
double faceY = (placeAt.getY() + against1.getY() + 1.0D) * 0.5D;
|
||||
double faceZ = (placeAt.getZ() + against1.getZ() + 1.0D) * 0.5D;
|
||||
Rotation place = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations());
|
||||
RayTraceResult res = RayTraceUtils.rayTraceTowards(ctx.player(), place, ctx.playerController().getBlockReachDistance());
|
||||
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) {
|
||||
if (res != null && res.type == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(placeAt)) {
|
||||
state.setTarget(new MovementState.MovementTarget(place, true));
|
||||
found = true;
|
||||
|
||||
@@ -527,15 +521,10 @@ public interface MovementHelper extends ActionCosts, Helper {
|
||||
EnumFacing side = ctx.objectMouseOver().sideHit;
|
||||
// only way for selectedBlock.equals(placeAt) to be true is if it's replacable
|
||||
if (selectedBlock.equals(placeAt) || (MovementHelper.canPlaceAgainst(ctx, selectedBlock) && selectedBlock.offset(side).equals(placeAt))) {
|
||||
((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ());
|
||||
return PlaceResult.READY_TO_PLACE;
|
||||
}
|
||||
}
|
||||
if (found) {
|
||||
((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, placeAt.getX(), placeAt.getY(), placeAt.getZ());
|
||||
return PlaceResult.ATTEMPTING;
|
||||
}
|
||||
return PlaceResult.NO_OPTION;
|
||||
return found ? PlaceResult.ATTEMPTING : PlaceResult.NO_OPTION;
|
||||
}
|
||||
|
||||
enum PlaceResult {
|
||||
|
||||
@@ -276,7 +276,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_NORTH(0, 0, -4, true, true) {
|
||||
PARKOUR_NORTH(0, 0, -4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.NORTH);
|
||||
@@ -288,7 +288,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_SOUTH(0, 0, +4, true, true) {
|
||||
PARKOUR_SOUTH(0, 0, +4, true, false) {
|
||||
@Override
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.SOUTH);
|
||||
@@ -300,7 +300,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_EAST(+4, 0, 0, true, true) {
|
||||
PARKOUR_EAST(+4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.EAST);
|
||||
@@ -312,7 +312,7 @@ public enum Moves {
|
||||
}
|
||||
},
|
||||
|
||||
PARKOUR_WEST(-4, 0, 0, true, true) {
|
||||
PARKOUR_WEST(-4, 0, 0, true, false) {
|
||||
@Override
|
||||
public Movement apply0(CalculationContext context, BetterBlockPos src) {
|
||||
return MovementParkour.cost(context, src, EnumFacing.WEST);
|
||||
|
||||
@@ -27,14 +27,11 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementAscend extends Movement {
|
||||
|
||||
private int ticksWithoutPlacement = 0;
|
||||
@@ -54,17 +51,6 @@ public class MovementAscend extends Movement {
|
||||
return cost(context, src.x, src.y, src.z, dest.x, dest.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
BetterBlockPos prior = new BetterBlockPos(src.subtract(getDirection()).up()); // sometimes we back up to place the block, also sprint ascends, also skip descend to straight ascend
|
||||
return ImmutableSet.of(src,
|
||||
src.up(),
|
||||
dest,
|
||||
prior,
|
||||
prior.up()
|
||||
);
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
IBlockState toPlace = context.get(destX, y, destZ);
|
||||
double additionalPlacementCost = 0;
|
||||
@@ -78,9 +64,9 @@ public class MovementAscend extends Movement {
|
||||
}
|
||||
boolean foundPlaceOption = false;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
if (againstX == x && againstZ == z) { // we might be able to backplace now, but it doesn't matter because it will have been broken by the time we'd need to use it
|
||||
continue;
|
||||
}
|
||||
@@ -157,10 +143,6 @@ public class MovementAscend extends Movement {
|
||||
|
||||
@Override
|
||||
public MovementState updateState(MovementState state) {
|
||||
if (ctx.playerFeet().y < src.y) {
|
||||
// this check should run even when in preparing state (breaking blocks)
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
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)
|
||||
@@ -168,10 +150,14 @@ public class MovementAscend extends Movement {
|
||||
return state;
|
||||
}
|
||||
|
||||
if (ctx.playerFeet().equals(dest) || ctx.playerFeet().equals(dest.add(getDirection().down()))) {
|
||||
if (ctx.playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
|
||||
if (ctx.playerFeet().y < src.y) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace);
|
||||
if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) {
|
||||
ticksWithoutPlacement++;
|
||||
@@ -211,7 +197,7 @@ public class MovementAscend extends Movement {
|
||||
if (headBonkClear()) {
|
||||
return state.setInput(Input.JUMP, true);
|
||||
}
|
||||
|
||||
|
||||
if (flatDistToNext > 1.2 || sideDist > 0.2) {
|
||||
return state;
|
||||
}
|
||||
|
||||
@@ -29,7 +29,6 @@ import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
@@ -38,8 +37,6 @@ import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementDescend extends Movement {
|
||||
|
||||
private int numTicks = 0;
|
||||
@@ -64,11 +61,6 @@ public class MovementDescend extends Movement {
|
||||
return result.cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
return ImmutableSet.of(src, dest.up(), dest);
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
double totalCost = 0;
|
||||
IBlockState destDown = context.get(destX, y - 1, destZ);
|
||||
@@ -145,7 +137,7 @@ public class MovementDescend extends Movement {
|
||||
IBlockState ontoBlock = context.get(destX, newY, destZ);
|
||||
int unprotectedFallHeight = fallHeight - (y - effectiveStartHeight); // equal to fallHeight - y + effectiveFallHeight, which is equal to -newY + effectiveFallHeight, which is equal to effectiveFallHeight - newY
|
||||
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[unprotectedFallHeight] + frontBreak + costSoFar;
|
||||
if (MovementHelper.isWater(ontoBlock.getBlock())) {
|
||||
if (MovementHelper.isWater(ontoBlock)) {
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
|
||||
return false;
|
||||
}
|
||||
@@ -224,7 +216,7 @@ public class MovementDescend extends Movement {
|
||||
double destZ = (src.getZ() + 0.5) * 0.17 + (dest.getZ() + 0.5) * 0.83;
|
||||
EntityPlayerSP player = ctx.player();
|
||||
state.setTarget(new MovementState.MovementTarget(
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(player.getPositionEyes(1.0F),
|
||||
new Rotation(RotationUtils.calcRotationFromVec3d(player.getEyePosition(1.0F),
|
||||
new Vec3d(destX, dest.getY(), destZ),
|
||||
new Rotation(player.rotationYaw, player.rotationPitch)).getYaw(), player.rotationPitch),
|
||||
false
|
||||
@@ -256,7 +248,7 @@ public class MovementDescend extends Movement {
|
||||
return true;
|
||||
}
|
||||
for (int y = 0; y <= 2; y++) { // we could hit any of the three blocks
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.getBlock(ctx, into.up(y)))) {
|
||||
if (MovementHelper.avoidWalkingInto(BlockStateInterface.get(ctx, into.up(y)))) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -37,7 +36,6 @@ import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementDiagonal extends Movement {
|
||||
|
||||
@@ -66,16 +64,6 @@ public class MovementDiagonal extends Movement {
|
||||
return result.cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
BetterBlockPos diagA = new BetterBlockPos(src.x, src.y, dest.z);
|
||||
BetterBlockPos diagB = new BetterBlockPos(dest.x, src.y, src.z);
|
||||
if (dest.y != src.y) { // only if allowDiagonalDescend
|
||||
return ImmutableSet.of(src, dest.up(), diagA, diagB, dest, diagA.down(), diagB.down());
|
||||
}
|
||||
return ImmutableSet.of(src, dest, diagA, diagB);
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
|
||||
IBlockState destInto = context.get(destX, y, destZ);
|
||||
if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) {
|
||||
@@ -103,12 +91,12 @@ public class MovementDiagonal extends Movement {
|
||||
if (fromDown == Blocks.SOUL_SAND) {
|
||||
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
|
||||
}
|
||||
Block cuttingOver1 = context.get(x, y - 1, destZ).getBlock();
|
||||
if (cuttingOver1 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver1)) {
|
||||
IBlockState cuttingOver1 = context.get(x, y - 1, destZ);
|
||||
if (cuttingOver1.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver1)) {
|
||||
return;
|
||||
}
|
||||
Block cuttingOver2 = context.get(destX, y - 1, z).getBlock();
|
||||
if (cuttingOver2 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver2)) {
|
||||
IBlockState cuttingOver2 = context.get(destX, y - 1, z);
|
||||
if (cuttingOver2.getBlock() == Blocks.MAGMA_BLOCK || MovementHelper.isLava(cuttingOver2)) {
|
||||
return;
|
||||
}
|
||||
IBlockState pb0 = context.get(x, y, destZ);
|
||||
@@ -127,7 +115,7 @@ public class MovementDiagonal extends Movement {
|
||||
return;
|
||||
}
|
||||
IBlockState pb3 = context.get(destX, y + 1, z);
|
||||
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3.getBlock()))) {
|
||||
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2) && pb2.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb3))) {
|
||||
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
|
||||
return;
|
||||
}
|
||||
@@ -136,13 +124,14 @@ public class MovementDiagonal extends Movement {
|
||||
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
|
||||
return;
|
||||
}
|
||||
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1.getBlock()))) {
|
||||
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0) && pb0.getBlock() != Blocks.WATER) || MovementHelper.avoidWalkingInto(pb1))) {
|
||||
// and now that option B is fully calculated, see if we can edge around that way
|
||||
return;
|
||||
}
|
||||
boolean water = false;
|
||||
Block startIn = context.getBlock(x, y, z);
|
||||
if (MovementHelper.isWater(startIn) || MovementHelper.isWater(destInto.getBlock())) {
|
||||
IBlockState startState = context.get(x, y, z);
|
||||
Block startIn = startState.getBlock();
|
||||
if (MovementHelper.isWater(startState) || MovementHelper.isWater(destInto)) {
|
||||
// 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
|
||||
@@ -183,9 +172,8 @@ public class MovementDiagonal extends Movement {
|
||||
}
|
||||
|
||||
if (ctx.playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
} else if (!playerInValidPosition() && !(MovementHelper.isLiquid(ctx, src) && getValidPositions().contains(ctx.playerFeet().up()))) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
return state;
|
||||
}
|
||||
if (sprint()) {
|
||||
state.setInput(Input.SPRINT, true);
|
||||
@@ -194,7 +182,7 @@ public class MovementDiagonal extends Movement {
|
||||
return state;
|
||||
}
|
||||
|
||||
private boolean sprint() {
|
||||
public boolean sprint() {
|
||||
if (MovementHelper.isLiquid(ctx, ctx.playerFeet()) && !Baritone.settings().sprintInWater.value) {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -24,13 +24,10 @@ import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementDownward extends Movement {
|
||||
|
||||
private int numTicks = 0;
|
||||
@@ -50,11 +47,6 @@ public class MovementDownward extends Movement {
|
||||
return cost(context, src.x, src.y, src.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
return ImmutableSet.of(src, dest);
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z) {
|
||||
if (!context.allowDownward) {
|
||||
return COST_INF;
|
||||
@@ -81,8 +73,6 @@ public class MovementDownward extends Movement {
|
||||
|
||||
if (ctx.playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
} else if (!playerInValidPosition()) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
double diffX = ctx.player().posX - (dest.getX() + 0.5);
|
||||
double diffZ = ctx.player().posZ - (dest.getZ() + 0.5);
|
||||
|
||||
@@ -34,17 +34,17 @@ import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLadder;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.player.InventoryPlayer;
|
||||
import net.minecraft.fluid.WaterFluid;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.util.math.Vec3i;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementFall extends Movement {
|
||||
|
||||
@@ -65,16 +65,6 @@ public class MovementFall extends Movement {
|
||||
return result.cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
Set<BetterBlockPos> set = new HashSet<>();
|
||||
set.add(src);
|
||||
for (int y = src.y - dest.y; y >= 0; y--) {
|
||||
set.add(dest.up(y));
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
private boolean willPlaceBucket() {
|
||||
CalculationContext context = new CalculationContext(baritone);
|
||||
MutableMoveResult result = new MutableMoveResult();
|
||||
@@ -91,10 +81,11 @@ public class MovementFall extends Movement {
|
||||
BlockPos playerFeet = ctx.playerFeet();
|
||||
Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations());
|
||||
Rotation targetRotation = null;
|
||||
Block destBlock = ctx.world().getBlockState(dest).getBlock();
|
||||
boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER;
|
||||
IBlockState destState = ctx.world().getBlockState(dest);
|
||||
Block destBlock = destState.getBlock();
|
||||
boolean isWater = destState.getFluidState().getFluid() instanceof WaterFluid;
|
||||
if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) {
|
||||
if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) {
|
||||
if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().getDimension().isNether()) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
@@ -103,7 +94,8 @@ public class MovementFall extends Movement {
|
||||
|
||||
targetRotation = new Rotation(toDest.getYaw(), 90.0F);
|
||||
|
||||
if (ctx.isLookingAt(dest) || ctx.isLookingAt(dest.down())) {
|
||||
RayTraceResult trace = ctx.objectMouseOver();
|
||||
if (trace != null && trace.type == RayTraceResult.Type.BLOCK && (trace.getBlockPos().equals(dest) || trace.getBlockPos().equals(dest.down()))) {
|
||||
state.setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
@@ -160,7 +152,7 @@ public class MovementFall extends Movement {
|
||||
for (int i = 0; i < 15; i++) {
|
||||
IBlockState state = ctx.world().getBlockState(ctx.playerFeet().down(i));
|
||||
if (state.getBlock() == Blocks.LADDER) {
|
||||
return state.getValue(BlockLadder.FACING);
|
||||
return state.get(BlockLadder.FACING);
|
||||
}
|
||||
}
|
||||
return null;
|
||||
|
||||
@@ -28,35 +28,31 @@ import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.pathing.MutableMoveResult;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.BlockStairs;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.fluid.WaterFluid;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Fluids;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
public class MovementParkour extends Movement {
|
||||
|
||||
private static final BetterBlockPos[] EMPTY = new BetterBlockPos[]{};
|
||||
|
||||
private final EnumFacing direction;
|
||||
private final int dist;
|
||||
private final boolean ascend;
|
||||
|
||||
private MovementParkour(IBaritone baritone, BetterBlockPos src, int dist, EnumFacing dir, boolean ascend) {
|
||||
super(baritone, src, src.offset(dir, dist).up(ascend ? 1 : 0), EMPTY, src.offset(dir, dist).down(ascend ? 0 : 1));
|
||||
private MovementParkour(IBaritone baritone, BetterBlockPos src, int dist, EnumFacing dir) {
|
||||
super(baritone, src, src.offset(dir, dist), EMPTY, src.offset(dir, dist).down());
|
||||
this.direction = dir;
|
||||
this.dist = dist;
|
||||
this.ascend = ascend;
|
||||
}
|
||||
|
||||
public static MovementParkour cost(CalculationContext context, BetterBlockPos src, EnumFacing direction) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
cost(context, src.x, src.y, src.z, direction, res);
|
||||
int dist = Math.abs(res.x - src.x) + Math.abs(res.z - src.z);
|
||||
return new MovementParkour(context.getBaritone(), src, dist, direction, res.y > src.y);
|
||||
return new MovementParkour(context.getBaritone(), src, dist, direction);
|
||||
}
|
||||
|
||||
public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
|
||||
@@ -78,7 +74,7 @@ public class MovementParkour extends Movement {
|
||||
// second most common case -- we could just traverse not parkour
|
||||
return;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(adj.getBlock()) && adj.getBlock() != Blocks.WATER && adj.getBlock() != Blocks.FLOWING_WATER) { // magma sucks
|
||||
if (MovementHelper.avoidWalkingInto(adj) && !(adj.getFluidState().getFluid() instanceof WaterFluid)) { // magma sucks
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(context, x + xDiff, y + 1, z + zDiff)) {
|
||||
@@ -91,7 +87,7 @@ public class MovementParkour extends Movement {
|
||||
return;
|
||||
}
|
||||
IBlockState standingOn = context.get(x, y - 1, z);
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn) || standingOn.getBlock() instanceof BlockLiquid) {
|
||||
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn) || standingOn.getFluidState().getFluid() != Fluids.EMPTY) {
|
||||
return;
|
||||
}
|
||||
int maxJump;
|
||||
@@ -105,36 +101,17 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
}
|
||||
for (int i = 2; i <= maxJump; i++) {
|
||||
int destX = x + xDiff * i;
|
||||
int destZ = z + zDiff * i;
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 1, destZ)) {
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 2, destZ)) {
|
||||
return;
|
||||
}
|
||||
IBlockState destInto = context.bsi.get0(destX, y, destZ);
|
||||
if (!MovementHelper.fullyPassable(destInto)) {
|
||||
if (i <= 3 && context.allowParkourAscend && context.canSprint && MovementHelper.canWalkOn(context.bsi, destX, y, destZ, destInto) && checkOvershootSafety(context.bsi, destX + xDiff, y + 1, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y + 1;
|
||||
res.z = destZ;
|
||||
res.cost = i * SPRINT_ONE_BLOCK_COST + context.jumpPenalty;
|
||||
// TODO perhaps dest.up(3) doesn't need to be fullyPassable, just canWalkThrough, possibly?
|
||||
for (int y2 = 0; y2 < 4; y2++) {
|
||||
if (!MovementHelper.fullyPassable(context, x + xDiff * i, y + y2, z + zDiff * i)) {
|
||||
return;
|
||||
}
|
||||
return;
|
||||
}
|
||||
IBlockState landingOn = context.bsi.get0(destX, y - 1, destZ);
|
||||
// farmland needs to be canwalkon otherwise farm can never work at all, but we want to specifically disallow ending a jumy on farmland haha
|
||||
if (landingOn.getBlock() != Blocks.FARMLAND && MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, landingOn)) {
|
||||
if (checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
res.x = destX;
|
||||
res.y = y;
|
||||
res.z = destZ;
|
||||
res.cost = costFromJumpDistance(i) + context.jumpPenalty;
|
||||
}
|
||||
return;
|
||||
}
|
||||
if (!MovementHelper.fullyPassable(context, destX, y + 3, destZ)) {
|
||||
if (MovementHelper.canWalkOn(context.bsi, x + xDiff * i, y - 1, z + zDiff * i)) {
|
||||
res.x = x + xDiff * i;
|
||||
res.y = y;
|
||||
res.z = z + zDiff * i;
|
||||
res.cost = costFromJumpDistance(i) + context.jumpPenalty;
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -155,13 +132,10 @@ public class MovementParkour extends Movement {
|
||||
if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi)) {
|
||||
return;
|
||||
}
|
||||
if (!checkOvershootSafety(context.bsi, destX + xDiff, y, destZ + zDiff)) {
|
||||
return;
|
||||
}
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
|
||||
continue;
|
||||
}
|
||||
@@ -175,11 +149,6 @@ public class MovementParkour extends Movement {
|
||||
}
|
||||
}
|
||||
|
||||
private static boolean checkOvershootSafety(BlockStateInterface bsi, int x, int y, int z) {
|
||||
// we're going to walk into these two blocks after the landing of the parkour anyway, so make sure they aren't avoidWalkingInto
|
||||
return !MovementHelper.avoidWalkingInto(bsi.get0(x, y, z).getBlock()) && !MovementHelper.avoidWalkingInto(bsi.get0(x, y + 1, z).getBlock());
|
||||
}
|
||||
|
||||
private static double costFromJumpDistance(int dist) {
|
||||
switch (dist) {
|
||||
case 2:
|
||||
@@ -198,23 +167,12 @@ public class MovementParkour extends Movement {
|
||||
public double calculateCost(CalculationContext context) {
|
||||
MutableMoveResult res = new MutableMoveResult();
|
||||
cost(context, src.x, src.y, src.z, direction, res);
|
||||
if (res.x != dest.x || res.y != dest.y || res.z != dest.z) {
|
||||
if (res.x != dest.x || res.z != dest.z) {
|
||||
return COST_INF;
|
||||
}
|
||||
return res.cost;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
Set<BetterBlockPos> set = new HashSet<>();
|
||||
for (int i = 0; i <= dist; i++) {
|
||||
for (int y = 0; y < 2; y++) {
|
||||
set.add(src.offset(direction, i).up(y));
|
||||
}
|
||||
}
|
||||
return set;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean safeToCancel(MovementState state) {
|
||||
// once this movement is instantiated, the state is default to PREPPING
|
||||
@@ -229,12 +187,16 @@ public class MovementParkour extends Movement {
|
||||
if (state.getStatus() != MovementStatus.RUNNING) {
|
||||
return state;
|
||||
}
|
||||
if (ctx.player().isHandActive()) {
|
||||
logDebug("Pausing parkour since hand is active");
|
||||
return state;
|
||||
}
|
||||
if (ctx.playerFeet().y < src.y) {
|
||||
// we have fallen
|
||||
logDebug("sorry");
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
if (dist >= 4 || ascend) {
|
||||
if (dist >= 4) {
|
||||
state.setInput(Input.SPRINT, true);
|
||||
}
|
||||
MovementHelper.moveTowards(ctx, state, dest);
|
||||
@@ -249,13 +211,12 @@ public class MovementParkour extends Movement {
|
||||
state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
} else if (!ctx.playerFeet().equals(src)) {
|
||||
if (ctx.playerFeet().equals(src.offset(direction)) || ctx.player().posY - src.y > 0.0001) {
|
||||
if (ctx.playerFeet().equals(src.offset(direction)) || ctx.player().posY - ctx.playerFeet().getY() > 0.0001) {
|
||||
if (!MovementHelper.canWalkOn(ctx, dest.down()) && !ctx.player().onGround && MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), true) == PlaceResult.READY_TO_PLACE) {
|
||||
// go in the opposite order to check DOWN before all horizontals -- down is preferable because you don't have to look to the side while in midair, which could mess up the trajectory
|
||||
state.setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
// prevent jumping too late by checking for ascend
|
||||
if (dist == 3 && !ascend) { // this is a 2 block gap, dest = src + direction * 3
|
||||
if (dist == 3) { // this is a 2 block gap, dest = src + direction * 3
|
||||
double xDiff = (src.x + 0.5) - ctx.player().posX;
|
||||
double zDiff = (src.z + 0.5) - ctx.player().posZ;
|
||||
double distFromStart = Math.max(Math.abs(xDiff), Math.abs(zDiff));
|
||||
|
||||
@@ -30,7 +30,6 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -38,7 +37,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.Optional;
|
||||
|
||||
public class MovementPillar extends Movement {
|
||||
|
||||
@@ -51,20 +50,16 @@ public class MovementPillar extends Movement {
|
||||
return cost(context, src.x, src.y, src.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
return ImmutableSet.of(src, dest);
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z) {
|
||||
Block from = context.get(x, y, z).getBlock();
|
||||
IBlockState fromState = context.get(x, y, z);
|
||||
Block from = fromState.getBlock();
|
||||
boolean ladder = from == Blocks.LADDER || from == Blocks.VINE;
|
||||
IBlockState fromDown = context.get(x, y - 1, z);
|
||||
if (!ladder) {
|
||||
if (fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE) {
|
||||
return COST_INF; // can't pillar from a ladder or vine onto something that isn't also climbable
|
||||
}
|
||||
if (fromDown.getBlock() instanceof BlockSlab && !((BlockSlab) fromDown.getBlock()).isDouble() && fromDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
|
||||
if (fromDown.getBlock() instanceof BlockSlab && !fromDown.isTopSolid()) {
|
||||
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
|
||||
}
|
||||
}
|
||||
@@ -76,9 +71,9 @@ public class MovementPillar extends Movement {
|
||||
if (toBreakBlock instanceof BlockFenceGate) { // see issue #172
|
||||
return COST_INF;
|
||||
}
|
||||
Block srcUp = null;
|
||||
if (MovementHelper.isWater(toBreakBlock) && MovementHelper.isWater(from)) { // TODO should this also be allowed if toBreakBlock is air?
|
||||
srcUp = context.get(x, y + 1, z).getBlock();
|
||||
IBlockState srcUp = null;
|
||||
if (MovementHelper.isWater(toBreak) && MovementHelper.isWater(fromState)) { // TODO should this also be allowed if toBreakBlock is air?
|
||||
srcUp = context.get(x, y + 1, z);
|
||||
if (MovementHelper.isWater(srcUp)) {
|
||||
return LADDER_UP_ONE_COST; // allow ascending pillars of water, but only if we're already in one
|
||||
}
|
||||
@@ -90,11 +85,11 @@ public class MovementPillar extends Movement {
|
||||
if (placeCost >= COST_INF) {
|
||||
return COST_INF;
|
||||
}
|
||||
if (fromDown.getBlock() == Blocks.AIR) {
|
||||
if (fromDown.getBlock() instanceof BlockAir) {
|
||||
placeCost += 0.1; // slightly (1/200th of a second) penalize pillaring on what's currently air
|
||||
}
|
||||
}
|
||||
if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && context.assumeWalkOnWater)) {
|
||||
if ((MovementHelper.isLiquid(fromState) && !MovementHelper.canPlaceAgainst(context.bsi, x, y - 1, z, fromDown)) || (MovementHelper.isLiquid(fromDown) && context.assumeWalkOnWater)) {
|
||||
// otherwise, if we're standing in water, we cannot pillar
|
||||
// if we're standing on water and assumeWalkOnWater is true, we cannot pillar
|
||||
// if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again
|
||||
@@ -112,9 +107,9 @@ public class MovementPillar extends Movement {
|
||||
if (check.getBlock() instanceof BlockFalling) {
|
||||
// see MovementAscend's identical check for breaking a falling block above our head
|
||||
if (srcUp == null) {
|
||||
srcUp = context.get(x, y + 1, z).getBlock();
|
||||
srcUp = context.get(x, y + 1, z);
|
||||
}
|
||||
if (!(toBreakBlock instanceof BlockFalling) || !(srcUp instanceof BlockFalling)) {
|
||||
if (!(toBreakBlock instanceof BlockFalling) || !(srcUp.getBlock() instanceof BlockFalling)) {
|
||||
return COST_INF;
|
||||
}
|
||||
}
|
||||
@@ -169,7 +164,7 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
|
||||
IBlockState fromDown = BlockStateInterface.get(ctx, src);
|
||||
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(ctx, dest)) {
|
||||
if (MovementHelper.isWater(fromDown) && MovementHelper.isWater(ctx, dest)) {
|
||||
// stay centered while swimming up a water column
|
||||
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()), false));
|
||||
Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
|
||||
@@ -183,7 +178,7 @@ public class MovementPillar extends Movement {
|
||||
}
|
||||
boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE;
|
||||
boolean vine = fromDown.getBlock() == Blocks.VINE;
|
||||
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
|
||||
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getEyePosition(1.0F),
|
||||
VecUtils.getBlockPosCenter(positionToPlace),
|
||||
new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
|
||||
if (!ladder) {
|
||||
@@ -192,7 +187,7 @@ public class MovementPillar extends Movement {
|
||||
|
||||
boolean blockIsThere = MovementHelper.canWalkOn(ctx, src) || ladder;
|
||||
if (ladder) {
|
||||
BlockPos against = vine ? getAgainst(new CalculationContext(baritone), src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
BlockPos against = vine ? getAgainst(new CalculationContext(baritone), src) : src.offset(fromDown.get(BlockLadder.FACING).getOpposite());
|
||||
if (against == null) {
|
||||
logDebug("Unable to climb vines");
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
@@ -214,7 +209,7 @@ public class MovementPillar extends Movement {
|
||||
return state;
|
||||
} else {
|
||||
// Get ready to place a throwaway block
|
||||
if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(true, src.x, src.y, src.z)) {
|
||||
if (!((Baritone) baritone).getInventoryBehavior().selectThrowawayForLocation(src.x, src.y, src.z)) {
|
||||
return state.setStatus(MovementStatus.UNREACHABLE);
|
||||
}
|
||||
|
||||
@@ -246,9 +241,10 @@ public class MovementPillar extends Movement {
|
||||
Block fr = frState.getBlock();
|
||||
// TODO: Evaluate usage of getMaterial().isReplaceable()
|
||||
if (!(fr instanceof BlockAir || frState.getMaterial().isReplaceable())) {
|
||||
RotationUtils.reachable(ctx.player(), src, ctx.playerController().getBlockReachDistance())
|
||||
.map(rot -> new MovementState.MovementTarget(rot, true))
|
||||
.ifPresent(state::setTarget);
|
||||
Optional<Rotation> reachable = RotationUtils.reachable(ctx.player(), src, ctx.playerController().getBlockReachDistance());
|
||||
if (reachable.isPresent()) {
|
||||
state.setTarget(new MovementState.MovementTarget(reachable.get(), true));
|
||||
}
|
||||
state.setInput(Input.JUMP, false); // breaking is like 5x slower when you're jumping
|
||||
state.setInput(Input.CLICK_LEFT, true);
|
||||
blockIsThere = false;
|
||||
|
||||
@@ -30,15 +30,15 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import com.google.common.collect.ImmutableSet;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.fluid.WaterFluid;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.state.properties.SlabType;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
|
||||
import java.util.Optional;
|
||||
import java.util.Set;
|
||||
import java.util.Objects;
|
||||
|
||||
public class MovementTraverse extends Movement {
|
||||
|
||||
@@ -62,20 +62,16 @@ public class MovementTraverse extends Movement {
|
||||
return cost(context, src.x, src.y, src.z, dest.x, dest.z);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Set<BetterBlockPos> calculateValidPositions() {
|
||||
return ImmutableSet.of(src, dest);
|
||||
}
|
||||
|
||||
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
|
||||
IBlockState pb0 = context.get(destX, y + 1, destZ);
|
||||
IBlockState pb1 = context.get(destX, y, destZ);
|
||||
IBlockState destOn = context.get(destX, y - 1, destZ);
|
||||
Block srcDown = context.getBlock(x, y - 1, z);
|
||||
IBlockState down = context.get(x, y - 1, z);
|
||||
Block srcDown = down.getBlock();
|
||||
if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
|
||||
double WC = WALK_ONE_BLOCK_COST;
|
||||
boolean water = false;
|
||||
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
|
||||
if (MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1)) {
|
||||
WC = context.waterWalkSpeed;
|
||||
water = true;
|
||||
} else {
|
||||
@@ -112,8 +108,8 @@ public class MovementTraverse extends Movement {
|
||||
return COST_INF;
|
||||
}
|
||||
if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) {
|
||||
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
|
||||
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
|
||||
boolean throughWater = MovementHelper.isWater(pb0) || MovementHelper.isWater(pb1);
|
||||
if (MovementHelper.isWater(destOn) && throughWater) {
|
||||
// this happens when assume walk on water is true and this is a traverse in water, which isn't allowed
|
||||
return COST_INF;
|
||||
}
|
||||
@@ -128,9 +124,9 @@ public class MovementTraverse extends Movement {
|
||||
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break
|
||||
double WC = throughWater ? context.waterWalkSpeed : WALK_ONE_BLOCK_COST;
|
||||
for (int i = 0; i < 5; i++) {
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
|
||||
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
|
||||
int againstZ = destZ + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getZOffset();
|
||||
if (againstX == x && againstZ == z) { // this would be a backplace
|
||||
continue;
|
||||
}
|
||||
@@ -139,10 +135,10 @@ public class MovementTraverse extends Movement {
|
||||
}
|
||||
}
|
||||
// now that we've checked all possible directions to side place, we actually need to backplace
|
||||
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && !((BlockSlab) srcDown).isDouble())) {
|
||||
if (srcDown == Blocks.SOUL_SAND || (srcDown instanceof BlockSlab && down.get(BlockSlab.TYPE) != SlabType.DOUBLE)) {
|
||||
return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/
|
||||
}
|
||||
if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) {
|
||||
if (down.getFluidState() instanceof WaterFluid) {
|
||||
return COST_INF; // this is obviously impossible
|
||||
}
|
||||
WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol
|
||||
@@ -167,10 +163,10 @@ public class MovementTraverse extends Movement {
|
||||
return state;
|
||||
}
|
||||
// and if it's fine to walk into the blocks in front
|
||||
if (MovementHelper.avoidWalkingInto(pb0.getBlock())) {
|
||||
if (MovementHelper.avoidWalkingInto(pb0)) {
|
||||
return state;
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(pb1.getBlock())) {
|
||||
if (MovementHelper.avoidWalkingInto(pb1)) {
|
||||
return state;
|
||||
}
|
||||
// and we aren't already pressed up against the block
|
||||
@@ -178,10 +174,6 @@ public class MovementTraverse extends Movement {
|
||||
if (dist < 0.83) {
|
||||
return state;
|
||||
}
|
||||
if (!state.getTarget().getRotation().isPresent()) {
|
||||
// this can happen rarely when the server lags and doesn't send the falling sand entity until you've already walked through the block and are now mining the next one
|
||||
return state;
|
||||
}
|
||||
|
||||
// combine the yaw to the center of the destination, and the pitch to the specific block we're trying to break
|
||||
// it's safe to do this since the two blocks we break (in a traverse) are right on top of each other and so will have the same yaw
|
||||
@@ -192,9 +184,8 @@ public class MovementTraverse extends Movement {
|
||||
pitchToBreak = 26;
|
||||
}
|
||||
|
||||
return state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true))
|
||||
.setInput(Input.MOVE_FORWARD, true)
|
||||
.setInput(Input.SPRINT, true);
|
||||
state.setTarget(new MovementState.MovementTarget(new Rotation(yawToDest, pitchToBreak), true));
|
||||
return state.setInput(Input.MOVE_FORWARD, true).setInput(Input.SPRINT, true);
|
||||
}
|
||||
|
||||
//sneak may have been set to true in the PREPPING state while mining an adjacent block
|
||||
@@ -203,44 +194,46 @@ public class MovementTraverse extends Movement {
|
||||
Block fd = BlockStateInterface.get(ctx, src.down()).getBlock();
|
||||
boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE;
|
||||
|
||||
if (pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor) {
|
||||
|
||||
boolean notPassable = pb0.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(ctx, src, dest) || pb1.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(ctx, dest, src);
|
||||
boolean canOpen = !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()));
|
||||
|
||||
if (notPassable && canOpen) {
|
||||
boolean door = pb0.getBlock() instanceof BlockDoor || pb1.getBlock() instanceof BlockDoor;
|
||||
if (door) {
|
||||
boolean isDoorActuallyBlockingUs = false;
|
||||
if (pb0.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(ctx, src, dest)) {
|
||||
isDoorActuallyBlockingUs = true;
|
||||
} else if (pb1.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(ctx, dest, src)) {
|
||||
isDoorActuallyBlockingUs = true;
|
||||
}
|
||||
if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
|
||||
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), positionsToBreak[0]), ctx.playerRotations()), true))
|
||||
.setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
|
||||
if (pb0.getBlock() instanceof BlockFenceGate || pb1.getBlock() instanceof BlockFenceGate) {
|
||||
BlockPos blocked = !MovementHelper.isGatePassable(ctx, positionsToBreak[0], src.up()) ? positionsToBreak[0]
|
||||
: !MovementHelper.isGatePassable(ctx, positionsToBreak[1], src) ? positionsToBreak[1]
|
||||
: null;
|
||||
BlockPos blocked = null;
|
||||
if (!MovementHelper.isGatePassable(ctx, positionsToBreak[0], src.up())) {
|
||||
blocked = positionsToBreak[0];
|
||||
} else if (!MovementHelper.isGatePassable(ctx, positionsToBreak[1], src)) {
|
||||
blocked = positionsToBreak[1];
|
||||
}
|
||||
|
||||
if (blocked != null) {
|
||||
Optional<Rotation> rotation = RotationUtils.reachable(ctx, blocked);
|
||||
if (rotation.isPresent()) {
|
||||
return state.setTarget(new MovementState.MovementTarget(rotation.get(), true)).setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.calculateBlockCenter(ctx.world(), blocked), ctx.playerRotations()), true))
|
||||
.setInput(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
}
|
||||
|
||||
boolean isTheBridgeBlockThere = MovementHelper.canWalkOn(ctx, positionToPlace) || ladder;
|
||||
BlockPos feet = ctx.playerFeet();
|
||||
if (feet.getY() != dest.getY() && !ladder) {
|
||||
BlockPos whereAmI = ctx.playerFeet();
|
||||
if (whereAmI.getY() != dest.getY() && !ladder) {
|
||||
logDebug("Wrong Y coordinate");
|
||||
if (feet.getY() < dest.getY()) {
|
||||
return state.setInput(Input.JUMP, true);
|
||||
if (whereAmI.getY() < dest.getY()) {
|
||||
state.setInput(Input.JUMP, true);
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
if (isTheBridgeBlockThere) {
|
||||
if (feet.equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
if (Baritone.settings().overshootTraverse.value && (feet.equals(dest.add(getDirection())) || feet.equals(dest.add(getDirection()).add(getDirection())))) {
|
||||
if (ctx.playerFeet().equals(dest)) {
|
||||
return state.setStatus(MovementStatus.SUCCESS);
|
||||
}
|
||||
Block low = BlockStateInterface.get(ctx, src).getBlock();
|
||||
@@ -251,22 +244,21 @@ public class MovementTraverse extends Movement {
|
||||
return state;
|
||||
}
|
||||
BlockPos into = dest.subtract(src).add(dest);
|
||||
Block intoBelow = BlockStateInterface.get(ctx, into).getBlock();
|
||||
Block intoAbove = BlockStateInterface.get(ctx, into.up()).getBlock();
|
||||
if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, feet) || Baritone.settings().sprintInWater.value) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) {
|
||||
IBlockState intoBelow = BlockStateInterface.get(ctx, into);
|
||||
IBlockState intoAbove = BlockStateInterface.get(ctx, into.up());
|
||||
if (wasTheBridgeBlockAlwaysThere && (!MovementHelper.isLiquid(ctx, ctx.playerFeet()) || Baritone.settings().sprintInWater.value) && (!MovementHelper.avoidWalkingInto(intoBelow) || MovementHelper.isWater(intoBelow)) && !MovementHelper.avoidWalkingInto(intoAbove)) {
|
||||
state.setInput(Input.SPRINT, true);
|
||||
}
|
||||
|
||||
IBlockState destDown = BlockStateInterface.get(ctx, dest.down());
|
||||
BlockPos against = positionsToBreak[0];
|
||||
if (feet.getY() != dest.getY() && ladder && (destDown.getBlock() == Blocks.VINE || destDown.getBlock() == Blocks.LADDER)) {
|
||||
against = destDown.getBlock() == Blocks.VINE ? MovementPillar.getAgainst(new CalculationContext(baritone), dest.down()) : dest.offset(destDown.getValue(BlockLadder.FACING).getOpposite());
|
||||
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();
|
||||
if (whereAmI.getY() != dest.getY() && ladder && (destDown == Blocks.VINE || destDown == Blocks.LADDER)) {
|
||||
new MovementPillar(baritone, dest.down(), dest).updateState(state); // i'm sorry
|
||||
return state;
|
||||
}
|
||||
MovementHelper.moveTowards(ctx, state, against);
|
||||
MovementHelper.moveTowards(ctx, state, positionsToBreak[0]);
|
||||
return state;
|
||||
} else {
|
||||
wasTheBridgeBlockAlwaysThere = false;
|
||||
Block standingOn = BlockStateInterface.get(ctx, feet.down()).getBlock();
|
||||
Block standingOn = BlockStateInterface.get(ctx, ctx.playerFeet().down()).getBlock();
|
||||
if (standingOn.equals(Blocks.SOUL_SAND) || standingOn instanceof BlockSlab) { // see issue #118
|
||||
double dist = Math.max(Math.abs(dest.getX() + 0.5 - ctx.player().posX), Math.abs(dest.getZ() + 0.5 - ctx.player().posZ));
|
||||
if (dist < 0.85) { // 0.5 + 0.3 + epsilon
|
||||
@@ -304,7 +296,7 @@ public class MovementTraverse extends Movement {
|
||||
default:
|
||||
break;
|
||||
}
|
||||
if (feet.equals(dest)) {
|
||||
if (whereAmI.equals(dest)) {
|
||||
// If we are in the block that we are trying to get to, we are sneaking over air and we need to place a block beneath us against the one we just walked off of
|
||||
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
|
||||
double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D;
|
||||
@@ -323,7 +315,7 @@ public class MovementTraverse extends Movement {
|
||||
} else {
|
||||
state.setTarget(new MovementState.MovementTarget(backToFace, true));
|
||||
}
|
||||
if (ctx.isLookingAt(goalLook)) {
|
||||
if (Objects.equals(ctx.getSelectedBlock().orElse(null), goalLook)) {
|
||||
return state.setInput(Input.CLICK_RIGHT, true); // wait to right click until we are able to place
|
||||
}
|
||||
// Out.log("Trying to look at " + goalLook + ", actually looking at" + Baritone.whatAreYouLookingAt());
|
||||
|
||||
@@ -23,7 +23,10 @@ import baritone.api.pathing.movement.ActionCosts;
|
||||
import baritone.api.pathing.movement.IMovement;
|
||||
import baritone.api.pathing.movement.MovementStatus;
|
||||
import baritone.api.pathing.path.IPathExecutor;
|
||||
import baritone.api.utils.*;
|
||||
import baritone.api.utils.BetterBlockPos;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.VecUtils;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.behavior.PathingBehavior;
|
||||
import baritone.pathing.calc.AbstractNodeCostSearch;
|
||||
@@ -32,7 +35,9 @@ import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.movements.*;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import baritone.utils.Helper;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Fluids;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
@@ -43,7 +48,8 @@ import java.util.*;
|
||||
import static baritone.api.pathing.movement.MovementStatus.*;
|
||||
|
||||
/**
|
||||
* Behavior to execute a precomputed path
|
||||
* Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching
|
||||
* or cutting (jumping onto the next path if it starts with a backtrack of this path's ending)
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
@@ -98,13 +104,14 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
if (pathPosition >= path.length()) {
|
||||
return true; // stop bugging me, I'm done
|
||||
}
|
||||
Movement movement = (Movement) path.movements().get(pathPosition);
|
||||
BetterBlockPos whereShouldIBe = path.positions().get(pathPosition);
|
||||
BetterBlockPos whereAmI = ctx.playerFeet();
|
||||
if (!movement.getValidPositions().contains(whereAmI)) {
|
||||
for (int i = 0; i < pathPosition && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
|
||||
if (((Movement) path.movements().get(i)).getValidPositions().contains(whereAmI)) {
|
||||
if (!whereShouldIBe.equals(whereAmI) && !Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
|
||||
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
|
||||
if (whereAmI.equals(path.positions().get(i))) {
|
||||
logDebug("Skipping back " + (pathPosition - i) + " steps, to " + i);
|
||||
int previousPos = pathPosition;
|
||||
pathPosition = i;
|
||||
pathPosition = Math.max(i - 1, 0); // previous step might not actually be done
|
||||
for (int j = pathPosition; j <= previousPos; j++) {
|
||||
path.movements().get(j).reset();
|
||||
}
|
||||
@@ -113,9 +120,9 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
for (int i = pathPosition + 3; i < path.length() - 1; i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
|
||||
for (int i = pathPosition + 3; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
|
||||
// also don't check pathPosition+2 because reasons
|
||||
if (((Movement) path.movements().get(i)).getValidPositions().contains(whereAmI)) {
|
||||
if (whereAmI.equals(path.positions().get(i))) {
|
||||
if (i - pathPosition > 2) {
|
||||
logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i);
|
||||
}
|
||||
@@ -130,7 +137,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
Tuple<Double, BlockPos> status = closestPathPos(path);
|
||||
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
|
||||
ticksAway++;
|
||||
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH);
|
||||
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getA() + ". Threshold: " + MAX_DIST_FROM_PATH);
|
||||
if (ticksAway > MAX_TICKS_AWAY) {
|
||||
logDebug("Too far away from path for too long, cancelling path");
|
||||
cancel();
|
||||
@@ -144,6 +151,38 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
cancel();
|
||||
return false;
|
||||
}
|
||||
//this commented block is literally cursed.
|
||||
/*Out.log(actions.get(pathPosition));
|
||||
if (pathPosition < actions.size() - 1) {//if there are two ActionBridges in a row and they are at right angles, walk diagonally. This makes it so you walk at 45 degrees along a zigzag path instead of doing inefficient zigging and zagging
|
||||
if ((actions.get(pathPosition) instanceof ActionBridge) && (actions.get(pathPosition + 1) instanceof ActionBridge)) {
|
||||
ActionBridge curr = (ActionBridge) actions.get(pathPosition);
|
||||
ActionBridge next = (ActionBridge) actions.get(pathPosition + 1);
|
||||
if (curr.dx() != next.dx() || curr.dz() != next.dz()) {//two movement are not parallel, so this is a right angle
|
||||
if (curr.amIGood() && next.amIGood()) {//nothing in the way
|
||||
BlockPos cornerToCut1 = new BlockPos(next.to.getX() - next.from.getX() + curr.from.getX(), next.to.getY(), next.to.getZ() - next.from.getZ() + curr.from.getZ());
|
||||
BlockPos cornerToCut2 = cornerToCut1.up();
|
||||
//Block corner1 = Baritone.get(cornerToCut1).getBlock();
|
||||
//Block corner2 = Baritone.get(cornerToCut2).getBlock();
|
||||
//Out.gui("Cutting conner " + cornerToCut1 + " " + corner1, Out.Mode.Debug);
|
||||
if (!Action.avoidWalkingInto(cornerToCut1) && !Action.avoidWalkingInto(cornerToCut2)) {
|
||||
double x = (next.from.getX() + next.to.getX() + 1.0D) * 0.5D;
|
||||
double z = (next.from.getZ() + next.to.getZ() + 1.0D) * 0.5D;
|
||||
MovementManager.clearMovement();
|
||||
if (!MovementManager.forward && curr.oneInTen != null && curr.oneInTen) {
|
||||
MovementManager.clearMovement();
|
||||
MovementManager.forward = LookManager.lookAtCoords(x, 0, z, false);
|
||||
} else {
|
||||
MovementManager.moveTowardsCoords(x, 0, z);
|
||||
}
|
||||
if (MovementManager.forward && !MovementManager.backward) {
|
||||
thePlayer.setSprinting(true);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}*/
|
||||
//long start = System.nanoTime() / 1000000L;
|
||||
BlockStateInterface bsi = new BlockStateInterface(ctx);
|
||||
for (int i = pathPosition - 10; i < pathPosition + 10; i++) {
|
||||
@@ -170,10 +209,10 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
HashSet<BlockPos> newPlace = new HashSet<>();
|
||||
HashSet<BlockPos> newWalkInto = new HashSet<>();
|
||||
for (int i = pathPosition; i < path.movements().size(); i++) {
|
||||
Movement m = (Movement) path.movements().get(i);
|
||||
newBreak.addAll(m.toBreak(bsi));
|
||||
newPlace.addAll(m.toPlace(bsi));
|
||||
newWalkInto.addAll(m.toWalkInto(bsi));
|
||||
Movement movement = (Movement) path.movements().get(i);
|
||||
newBreak.addAll(movement.toBreak(bsi));
|
||||
newPlace.addAll(movement.toPlace(bsi));
|
||||
newWalkInto.addAll(movement.toWalkInto(bsi));
|
||||
}
|
||||
toBreak = newBreak;
|
||||
toPlace = newPlace;
|
||||
@@ -184,14 +223,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
if (end - start > 0) {
|
||||
System.out.println("Recalculating break and place took " + (end - start) + "ms");
|
||||
}*/
|
||||
if (pathPosition < path.movements().size() - 1) {
|
||||
IMovement next = path.movements().get(pathPosition + 1);
|
||||
if (!behavior.baritone.bsi.worldContainsLoadedChunk(next.getDest().x, next.getDest().z)) {
|
||||
logDebug("Pausing since destination is at edge of loaded chunks");
|
||||
clearKeys();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
IMovement movement = path.movements().get(pathPosition);
|
||||
boolean canCancel = movement.safeToCancel();
|
||||
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
|
||||
costEstimateIndex = pathPosition;
|
||||
@@ -205,7 +237,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
double currentCost = movement.recalculateCost(behavior.secretInternalGetCalculationContext());
|
||||
double currentCost = ((Movement) movement).recalculateCost(behavior.secretInternalGetCalculationContext());
|
||||
if (currentCost >= ActionCosts.COST_INF && canCancel) {
|
||||
logDebug("Something has changed in the world and this movement has become impossible. Cancelling.");
|
||||
cancel();
|
||||
@@ -257,13 +289,11 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
private Tuple<Double, BlockPos> closestPathPos(IPath path) {
|
||||
double best = -1;
|
||||
BlockPos bestPos = null;
|
||||
for (IMovement movement : path.movements()) {
|
||||
for (BlockPos pos : ((Movement) movement).getValidPositions()) {
|
||||
double dist = VecUtils.entityDistanceToCenter(ctx.player(), pos);
|
||||
if (dist < best || best == -1) {
|
||||
best = dist;
|
||||
bestPos = pos;
|
||||
}
|
||||
for (BlockPos pos : path.positions()) {
|
||||
double dist = VecUtils.entityDistanceToCenter(ctx.player(), pos);
|
||||
if (dist < best || best == -1) {
|
||||
best = dist;
|
||||
bestPos = pos;
|
||||
}
|
||||
}
|
||||
return new Tuple<>(best, bestPos);
|
||||
@@ -303,7 +333,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
}
|
||||
|
||||
private boolean possiblyOffPath(Tuple<Double, BlockPos> status, double leniency) {
|
||||
double distanceFromPath = status.getFirst();
|
||||
double distanceFromPath = status.getA();
|
||||
if (distanceFromPath > leniency) {
|
||||
// when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path
|
||||
if (path.movements().get(pathPosition) instanceof MovementFall) {
|
||||
@@ -323,7 +353,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
* @return Whether or not it was possible to snap to the current player feet
|
||||
*/
|
||||
public boolean snipsnapifpossible() {
|
||||
if (!ctx.player().onGround && !(ctx.world().getBlockState(ctx.playerFeet()).getBlock() instanceof BlockLiquid)) {
|
||||
if (!ctx.player().onGround && ctx.world().getFluidState(ctx.playerFeet()).isEmpty()) {
|
||||
// if we're falling in the air, and not in water, don't splice
|
||||
return false;
|
||||
} else {
|
||||
@@ -411,10 +441,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
IMovement prev = path.movements().get(pathPosition - 1);
|
||||
if (prev instanceof MovementDescend && prev.getDirection().up().equals(current.getDirection().down())) {
|
||||
BlockPos center = current.getSrc().up();
|
||||
// playerFeet adds 0.1251 to account for soul sand
|
||||
// farmland is 0.9375
|
||||
// 0.07 is to account for farmland
|
||||
if (ctx.player().posY >= center.getY() - 0.07) {
|
||||
if (ctx.player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, false);
|
||||
return true;
|
||||
}
|
||||
@@ -426,7 +453,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
if (current instanceof MovementFall) {
|
||||
Tuple<Vec3d, BlockPos> data = overrideFall((MovementFall) current);
|
||||
if (data != null) {
|
||||
BetterBlockPos fallDest = new BetterBlockPos(data.getSecond());
|
||||
BlockPos fallDest = data.getB();
|
||||
if (!path.positions().contains(fallDest)) {
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
@@ -437,7 +464,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
return true;
|
||||
}
|
||||
clearKeys();
|
||||
behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getFirst(), ctx.playerRotations()), false);
|
||||
behavior.baritone.getLookBehavior().updateTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), data.getA(), ctx.playerRotations()), false);
|
||||
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.MOVE_FORWARD, true);
|
||||
return true;
|
||||
}
|
||||
@@ -529,20 +556,17 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
}
|
||||
}
|
||||
}
|
||||
if (MovementHelper.avoidWalkingInto(ctx.world().getBlockState(current.getSrc().up(3)).getBlock())) {
|
||||
if (MovementHelper.avoidWalkingInto(ctx.world().getBlockState(current.getSrc().up(3)))) {
|
||||
return false;
|
||||
}
|
||||
return !MovementHelper.avoidWalkingInto(ctx.world().getBlockState(next.getDest().up(2)).getBlock()); // codacy smh my head
|
||||
return !MovementHelper.avoidWalkingInto(ctx.world().getBlockState(next.getDest().up(2))); // codacy smh my head
|
||||
}
|
||||
|
||||
private static boolean canSprintFromDescendInto(IPlayerContext ctx, IMovement current, IMovement next) {
|
||||
if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) {
|
||||
return true;
|
||||
}
|
||||
if (!MovementHelper.canWalkOn(ctx, current.getDest().add(current.getDirection()))) {
|
||||
return false;
|
||||
}
|
||||
if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection())) {
|
||||
if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(ctx, next.getDest().down())) {
|
||||
return true;
|
||||
}
|
||||
return next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.value;
|
||||
@@ -584,7 +608,7 @@ public class PathExecutor implements IPathExecutor, Helper {
|
||||
ret.costEstimateIndex = costEstimateIndex;
|
||||
ret.ticksOnCurrent = ticksOnCurrent;
|
||||
return ret;
|
||||
}).orElseGet(this::cutIfTooLong); // dont actually call cutIfTooLong every tick if we won't actually use it, use a method reference
|
||||
}).orElse(cutIfTooLong());
|
||||
}
|
||||
|
||||
private PathExecutor cutIfTooLong() {
|
||||
|
||||
@@ -1,143 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.pathing.movement.Movement;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.pathing.movement.MovementState;
|
||||
import baritone.pathing.path.PathExecutor;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public final class BackfillProcess extends BaritoneProcessHelper {
|
||||
|
||||
public HashMap<BlockPos, IBlockState> blocksToReplace = new HashMap<>();
|
||||
|
||||
public BackfillProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
if (ctx.player() == null || ctx.world() == null) {
|
||||
return false;
|
||||
}
|
||||
if (!Baritone.settings().backfill.value) {
|
||||
return false;
|
||||
}
|
||||
if (Baritone.settings().allowParkour.value) {
|
||||
logDirect("Backfill cannot be used with allowParkour true");
|
||||
Baritone.settings().backfill.value = false;
|
||||
return false;
|
||||
}
|
||||
amIBreakingABlockHMMMMMMM();
|
||||
for (BlockPos pos : new ArrayList<>(blocksToReplace.keySet())) {
|
||||
if (ctx.world().getChunk(pos) instanceof EmptyChunk) {
|
||||
blocksToReplace.remove(pos);
|
||||
}
|
||||
}
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
|
||||
return !toFillIn().isEmpty();
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (!isSafeToCancel) {
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
for (BlockPos toPlace : toFillIn()) {
|
||||
MovementState fake = new MovementState();
|
||||
switch (MovementHelper.attemptToPlaceABlock(fake, baritone, toPlace, false)) {
|
||||
case NO_OPTION:
|
||||
continue;
|
||||
case READY_TO_PLACE:
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
case ATTEMPTING:
|
||||
// patience
|
||||
baritone.getLookBehavior().updateTarget(fake.getTarget().getRotation().get(), true);
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
default:
|
||||
throw new IllegalStateException();
|
||||
}
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.DEFER); // cede to other process
|
||||
}
|
||||
|
||||
private void amIBreakingABlockHMMMMMMM() {
|
||||
if (!ctx.getSelectedBlock().isPresent()) {
|
||||
return;
|
||||
}
|
||||
blocksToReplace.put(ctx.getSelectedBlock().get(), ctx.world().getBlockState(ctx.getSelectedBlock().get()));
|
||||
}
|
||||
|
||||
public List<BlockPos> toFillIn() {
|
||||
return blocksToReplace
|
||||
.keySet()
|
||||
.stream()
|
||||
.filter(pos -> ctx.world().getBlockState(pos).getBlock() == Blocks.AIR)
|
||||
.filter(pos -> ctx.world().mayPlace(Blocks.DIRT, pos, false, EnumFacing.UP, null))
|
||||
.filter(pos -> !partOfCurrentMovement(pos))
|
||||
.sorted(Comparator.<BlockPos>comparingDouble(ctx.player()::getDistanceSq).reversed())
|
||||
.collect(Collectors.toList());
|
||||
}
|
||||
|
||||
private boolean partOfCurrentMovement(BlockPos pos) {
|
||||
PathExecutor exec = baritone.getPathingBehavior().getCurrent();
|
||||
if (exec == null || exec.finished() || exec.failed()) {
|
||||
return false;
|
||||
}
|
||||
Movement movement = (Movement) exec.getPath().movements().get(exec.getPosition());
|
||||
return Arrays.asList(movement.toBreakAll()).contains(pos);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
if (blocksToReplace != null && !blocksToReplace.isEmpty()) {
|
||||
blocksToReplace.clear();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName0() {
|
||||
return "Backfill";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isTemporary() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double priority() {
|
||||
return 5;
|
||||
}
|
||||
}
|
||||
@@ -34,33 +34,33 @@ import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import baritone.utils.PathingCommandContext;
|
||||
import baritone.utils.schematic.AirSchematic;
|
||||
import baritone.utils.schematic.MapArtSchematic;
|
||||
import baritone.utils.schematic.Schematic;
|
||||
import baritone.utils.schematic.schematica.SchematicaHelper;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.BlockLiquid;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.item.BlockItemUseContext;
|
||||
import net.minecraft.item.ItemBlock;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.item.ItemUseContext;
|
||||
import net.minecraft.nbt.CompressedStreamTools;
|
||||
import net.minecraft.nbt.NBTTagCompound;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.Tuple;
|
||||
import net.minecraft.util.math.*;
|
||||
import net.minecraft.util.math.shapes.VoxelShape;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
|
||||
public final class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
|
||||
public class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
|
||||
|
||||
private HashSet<BetterBlockPos> incorrectPositions;
|
||||
private LongOpenHashSet observedCompleted; // positions that are completed even if they're out of render distance and we can't make sure right now
|
||||
private String name;
|
||||
private ISchematic realSchematic;
|
||||
private ISchematic schematic;
|
||||
@@ -73,6 +73,12 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
public boolean build(String schematicFile, BlockPos origin) {
|
||||
File file = new File(new File(Minecraft.getInstance().gameDir, "schematics"), schematicFile);
|
||||
System.out.println(file + " " + file.exists());
|
||||
return build(schematicFile, file, origin);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void build(String name, ISchematic schematic, Vec3i origin) {
|
||||
this.name = name;
|
||||
@@ -81,17 +87,12 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
this.origin = origin;
|
||||
this.paused = false;
|
||||
this.layer = 0;
|
||||
this.observedCompleted = new LongOpenHashSet();
|
||||
}
|
||||
|
||||
public void resume() {
|
||||
paused = false;
|
||||
}
|
||||
|
||||
public void pause() {
|
||||
paused = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean build(String name, File schematic, Vec3i origin) {
|
||||
NBTTagCompound tag;
|
||||
@@ -108,20 +109,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void buildOpenSchematic() {
|
||||
if (SchematicaHelper.isSchematicaPresent()) {
|
||||
Optional<Tuple<ISchematic, BlockPos>> schematic = SchematicaHelper.getOpenSchematic();
|
||||
if (schematic.isPresent()) {
|
||||
this.build(schematic.get().getFirst().toString(), schematic.get().getFirst(), schematic.get().getSecond());
|
||||
} else {
|
||||
logDirect("No schematic currently open");
|
||||
}
|
||||
} else {
|
||||
logDirect("Schematica is not present");
|
||||
}
|
||||
}
|
||||
|
||||
public void clearArea(BlockPos corner1, BlockPos corner2) {
|
||||
BlockPos origin = new BlockPos(Math.min(corner1.getX(), corner2.getX()), Math.min(corner1.getY(), corner2.getY()), Math.min(corner1.getZ(), corner2.getZ()));
|
||||
int widthX = Math.abs(corner1.getX() - corner2.getX()) + 1;
|
||||
@@ -131,7 +118,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
|
||||
private static ISchematic parse(NBTTagCompound schematic) {
|
||||
return Baritone.settings().mapArtMode.value ? new MapArtSchematic(schematic) : new Schematic(schematic);
|
||||
return new Schematic(schematic);
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -147,30 +134,27 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return null;
|
||||
}
|
||||
IBlockState state = schematic.desiredState(x - origin.getX(), y - origin.getY(), z - origin.getZ());
|
||||
if (state.getBlock() == Blocks.AIR) {
|
||||
if (state.getBlock() instanceof BlockAir) {
|
||||
return null;
|
||||
}
|
||||
return state;
|
||||
}
|
||||
|
||||
private Optional<Tuple<BetterBlockPos, Rotation>> toBreakNearPlayer(BuilderCalculationContext bcc) {
|
||||
|
||||
public Optional<Tuple<BetterBlockPos, Rotation>> toBreakNearPlayer(BuilderCalculationContext bcc) {
|
||||
BetterBlockPos center = ctx.playerFeet();
|
||||
BetterBlockPos pathStart = baritone.getPathingBehavior().pathStart();
|
||||
for (int dx = -5; dx <= 5; dx++) {
|
||||
for (int dy = Baritone.settings().breakFromAbove.value ? -1 : 0; dy <= 5; dy++) {
|
||||
for (int dy = 0; dy <= 5; dy++) {
|
||||
for (int dz = -5; dz <= 5; dz++) {
|
||||
int x = center.x + dx;
|
||||
int y = center.y + dy;
|
||||
int z = center.z + dz;
|
||||
if (dy == -1 && x == pathStart.x && z == pathStart.z) {
|
||||
continue; // dont mine what we're supported by, but not directly standing on
|
||||
}
|
||||
IBlockState desired = bcc.getSchematic(x, y, z);
|
||||
if (desired == null) {
|
||||
continue; // irrelevant
|
||||
}
|
||||
IBlockState curr = bcc.bsi.get0(x, y, z);
|
||||
if (curr.getBlock() != Blocks.AIR && !(curr.getBlock() instanceof BlockLiquid) && !valid(curr, desired)) {
|
||||
if (!(curr.getBlock() instanceof BlockAir) && !valid(curr, desired)) {
|
||||
BetterBlockPos pos = new BetterBlockPos(x, y, z);
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
|
||||
if (rot.isPresent()) {
|
||||
@@ -197,7 +181,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
private Optional<Placement> searchForPlacables(BuilderCalculationContext bcc, List<IBlockState> desirableOnHotbar) {
|
||||
public Optional<Placement> searchForPlacables(BuilderCalculationContext bcc, List<IBlockState> desirableOnHotbar) {
|
||||
BetterBlockPos center = ctx.playerFeet();
|
||||
for (int dx = -5; dx <= 5; dx++) {
|
||||
for (int dy = -5; dy <= 1; dy++) {
|
||||
@@ -211,7 +195,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
IBlockState curr = bcc.bsi.get0(x, y, z);
|
||||
if (MovementHelper.isReplacable(x, y, z, curr, bcc.bsi) && !valid(curr, desired)) {
|
||||
if (dy == 1 && bcc.bsi.get0(x, y + 1, z).getBlock() == Blocks.AIR) {
|
||||
if (dy == 1 && bcc.bsi.get0(x, y + 1, z).getBlock() instanceof BlockAir) {
|
||||
continue;
|
||||
}
|
||||
desirableOnHotbar.add(desired);
|
||||
@@ -226,24 +210,32 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private Optional<Placement> possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
|
||||
public boolean placementPlausible(BlockPos pos, IBlockState state) {
|
||||
VoxelShape voxelshape = state.getCollisionShape(ctx.world(), pos);
|
||||
return voxelshape.isEmpty() || ctx.world().checkNoEntityCollision(null, voxelshape.withOffset(pos.getX(), pos.getY(), pos.getZ()));
|
||||
}
|
||||
|
||||
public Optional<Placement> possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
|
||||
for (EnumFacing against : EnumFacing.values()) {
|
||||
BetterBlockPos placeAgainstPos = new BetterBlockPos(x, y, z).offset(against);
|
||||
IBlockState placeAgainstState = bsi.get0(placeAgainstPos);
|
||||
if (MovementHelper.isReplacable(placeAgainstPos.x, placeAgainstPos.y, placeAgainstPos.z, placeAgainstState, bsi)) {
|
||||
continue;
|
||||
}
|
||||
if (!ctx.world().mayPlace(toPlace.getBlock(), new BetterBlockPos(x, y, z), false, against, null)) {
|
||||
if (!toPlace.isValidPosition(ctx.world(), new BetterBlockPos(x, y, z))) {
|
||||
continue;
|
||||
}
|
||||
AxisAlignedBB aabb = placeAgainstState.getBoundingBox(ctx.world(), placeAgainstPos);
|
||||
if (!placementPlausible(new BetterBlockPos(x, y, z), toPlace)) {
|
||||
continue;
|
||||
}
|
||||
AxisAlignedBB aabb = placeAgainstState.getShape(ctx.world(), placeAgainstPos).getBoundingBox();
|
||||
for (Vec3d placementMultiplier : aabbSideMultipliers(against)) {
|
||||
double placeX = placeAgainstPos.x + aabb.minX * placementMultiplier.x + aabb.maxX * (1 - placementMultiplier.x);
|
||||
double placeY = placeAgainstPos.y + aabb.minY * placementMultiplier.y + aabb.maxY * (1 - placementMultiplier.y);
|
||||
double placeZ = placeAgainstPos.z + aabb.minZ * placementMultiplier.z + aabb.maxZ * (1 - placementMultiplier.z);
|
||||
Rotation rot = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(placeX, placeY, placeZ), ctx.playerRotations());
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot, ctx.playerController().getBlockReachDistance());
|
||||
if (result != null && result.typeOfHit == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
|
||||
if (result != null && result.type == RayTraceResult.Type.BLOCK && result.getBlockPos().equals(placeAgainstPos) && result.sideHit == against.getOpposite()) {
|
||||
OptionalInt hotbar = hasAnyItemThatWouldPlace(toPlace, result, rot);
|
||||
if (hotbar.isPresent()) {
|
||||
return Optional.of(new Placement(hotbar.getAsInt(), placeAgainstPos, against.getOpposite(), rot));
|
||||
@@ -254,7 +246,8 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return Optional.empty();
|
||||
}
|
||||
|
||||
private OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
|
||||
|
||||
public OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
|
||||
for (int i = 0; i < 9; i++) {
|
||||
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
|
||||
if (stack.isEmpty() || !(stack.getItem() instanceof ItemBlock)) {
|
||||
@@ -265,18 +258,24 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
// the state depends on the facing of the player sometimes
|
||||
ctx.player().rotationYaw = rot.getYaw();
|
||||
ctx.player().rotationPitch = rot.getPitch();
|
||||
IBlockState wouldBePlaced = ((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(
|
||||
ctx.world(),
|
||||
BlockItemUseContext meme = new BlockItemUseContext(new ItemUseContext(
|
||||
ctx.player(),
|
||||
stack,
|
||||
result.getBlockPos().offset(result.sideHit),
|
||||
result.sideHit,
|
||||
(float) result.hitVec.x - result.getBlockPos().getX(), // as in PlayerControllerMP
|
||||
(float) result.hitVec.x - result.getBlockPos().getX(),
|
||||
(float) result.hitVec.y - result.getBlockPos().getY(),
|
||||
(float) result.hitVec.z - result.getBlockPos().getZ(),
|
||||
stack.getItem().getMetadata(stack.getMetadata()),
|
||||
ctx.player()
|
||||
);
|
||||
(float) result.hitVec.z - result.getBlockPos().getZ()
|
||||
));
|
||||
IBlockState wouldBePlaced = ((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(meme);
|
||||
ctx.player().rotationYaw = originalYaw;
|
||||
ctx.player().rotationPitch = originalPitch;
|
||||
if (wouldBePlaced == null) {
|
||||
continue;
|
||||
}
|
||||
if (!meme.canPlace()) {
|
||||
continue;
|
||||
}
|
||||
if (valid(wouldBePlaced, desired)) {
|
||||
return OptionalInt.of(i);
|
||||
}
|
||||
@@ -311,35 +310,18 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
if (paused) {
|
||||
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
if (Baritone.settings().buildInLayers.value) {
|
||||
if (realSchematic == null) {
|
||||
realSchematic = schematic;
|
||||
}
|
||||
ISchematic realSchematic = this.realSchematic; // wrap this properly, dont just have the inner class refer to the builderprocess.this
|
||||
int minYInclusive;
|
||||
int maxYInclusive;
|
||||
// layer = 0 should be nothing
|
||||
// layer = realSchematic.heightY() should be everything
|
||||
if (Baritone.settings().layerOrder.value) { // top to bottom
|
||||
maxYInclusive = realSchematic.heightY() - 1;
|
||||
minYInclusive = realSchematic.heightY() - layer;
|
||||
} else {
|
||||
maxYInclusive = layer - 1;
|
||||
minYInclusive = 0;
|
||||
}
|
||||
schematic = new ISchematic() {
|
||||
@Override
|
||||
public IBlockState desiredState(int x, int y, int z) {
|
||||
return realSchematic.desiredState(x, y, z);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean inSchematic(int x, int y, int z) {
|
||||
return ISchematic.super.inSchematic(x, y, z) && y >= minYInclusive && y <= maxYInclusive;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int widthX() {
|
||||
return realSchematic.widthX();
|
||||
@@ -347,7 +329,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
|
||||
@Override
|
||||
public int heightY() {
|
||||
return realSchematic.heightY();
|
||||
return layer;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -363,28 +345,29 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
layer++;
|
||||
return onTick(calcFailed, isSafeToCancel);
|
||||
}
|
||||
Vec3i repeat = Baritone.settings().buildRepeat.value;
|
||||
if (repeat.equals(new Vec3i(0, 0, 0))) {
|
||||
int distance = Baritone.settings().buildRepeatDistance.value;
|
||||
EnumFacing direction = Baritone.settings().buildRepeatDirection.value;
|
||||
if (distance == 0) {
|
||||
logDirect("Done building");
|
||||
onLostControl();
|
||||
return null;
|
||||
}
|
||||
// build repeat time
|
||||
if (distance == -1) {
|
||||
distance = schematic.size(direction.getAxis());
|
||||
}
|
||||
layer = 0;
|
||||
origin = new BlockPos(origin).add(repeat);
|
||||
logDirect("Repeating build in vector " + repeat + ", new origin is " + origin);
|
||||
return onTick(calcFailed, isSafeToCancel);
|
||||
}
|
||||
if (Baritone.settings().distanceTrim.value) {
|
||||
trim();
|
||||
origin = new BlockPos(origin).offset(direction, distance);
|
||||
logDirect("Repeating build " + distance + " blocks to the " + direction + ", new origin is " + origin);
|
||||
}
|
||||
trim(bcc);
|
||||
|
||||
Optional<Tuple<BetterBlockPos, Rotation>> toBreak = toBreakNearPlayer(bcc);
|
||||
if (toBreak.isPresent() && isSafeToCancel && ctx.player().onGround) {
|
||||
// we'd like to pause to break this block
|
||||
// only change look direction if it's safe (don't want to fuck up an in progress parkour for example
|
||||
Rotation rot = toBreak.get().getSecond();
|
||||
BetterBlockPos pos = toBreak.get().getFirst();
|
||||
Rotation rot = toBreak.get().getB();
|
||||
BetterBlockPos pos = toBreak.get().getA();
|
||||
baritone.getLookBehavior().updateTarget(rot, true);
|
||||
MovementHelper.switchToBestToolFor(ctx, bcc.get(pos));
|
||||
if (ctx.player().isSneaking()) {
|
||||
@@ -393,10 +376,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
// and is unable since it's unsneaked in the intermediary tick
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true);
|
||||
}
|
||||
if (ctx.isLookingAt(pos) || ctx.playerRotations().isReallyCloseTo(rot)) {
|
||||
if (Objects.equals(ctx.objectMouseOver().getBlockPos(), pos) || ctx.playerRotations().isReallyCloseTo(rot)) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
List<IBlockState> desirableOnHotbar = new ArrayList<>();
|
||||
Optional<Placement> toPlace = searchForPlacables(bcc, desirableOnHotbar);
|
||||
@@ -405,10 +388,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
baritone.getLookBehavior().updateTarget(rot, true);
|
||||
ctx.player().inventory.currentItem = toPlace.get().hotbarSelection;
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.SNEAK, true);
|
||||
if ((ctx.isLookingAt(toPlace.get().placeAgainst) && ctx.objectMouseOver().sideHit.equals(toPlace.get().side)) || ctx.playerRotations().isReallyCloseTo(rot)) {
|
||||
if ((Objects.equals(ctx.objectMouseOver().getBlockPos(), toPlace.get().placeAgainst) && ctx.objectMouseOver().sideHit.equals(toPlace.get().side)) || ctx.playerRotations().isReallyCloseTo(rot)) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.CANCEL_AND_SET_GOAL);
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
|
||||
List<IBlockState> approxPlacable = placable(36);
|
||||
@@ -437,6 +420,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Goal goal = assemble(bcc, approxPlacable.subList(0, 9));
|
||||
if (goal == null) {
|
||||
goal = assemble(bcc, approxPlacable); // we're far away, so assume that we have our whole inventory to recalculate placable properly
|
||||
@@ -449,7 +433,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return new PathingCommandContext(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH, bcc);
|
||||
}
|
||||
|
||||
private boolean recalc(BuilderCalculationContext bcc) {
|
||||
public boolean recalc(BuilderCalculationContext bcc) {
|
||||
if (incorrectPositions == null) {
|
||||
incorrectPositions = new HashSet<>();
|
||||
fullRecalc(bcc);
|
||||
@@ -464,7 +448,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return !incorrectPositions.isEmpty();
|
||||
}
|
||||
|
||||
private void trim() {
|
||||
public void trim(BuilderCalculationContext bcc) {
|
||||
HashSet<BetterBlockPos> copy = new HashSet<>(incorrectPositions);
|
||||
copy.removeIf(pos -> pos.distanceSq(ctx.player().posX, ctx.player().posY, ctx.player().posZ) > 200);
|
||||
if (!copy.isEmpty()) {
|
||||
@@ -472,7 +456,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
private void recalcNearby(BuilderCalculationContext bcc) {
|
||||
public void recalcNearby(BuilderCalculationContext bcc) {
|
||||
BetterBlockPos center = ctx.playerFeet();
|
||||
for (int dx = -5; dx <= 5; dx++) {
|
||||
for (int dy = -5; dy <= 5; dy++) {
|
||||
@@ -483,13 +467,10 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
IBlockState desired = bcc.getSchematic(x, y, z);
|
||||
if (desired != null) {
|
||||
// we care about this position
|
||||
BetterBlockPos pos = new BetterBlockPos(x, y, z);
|
||||
if (valid(bcc.bsi.get0(x, y, z), desired)) {
|
||||
incorrectPositions.remove(pos);
|
||||
observedCompleted.add(BetterBlockPos.longHash(pos));
|
||||
incorrectPositions.remove(new BetterBlockPos(x, y, z));
|
||||
} else {
|
||||
incorrectPositions.add(pos);
|
||||
observedCompleted.remove(BetterBlockPos.longHash(pos));
|
||||
incorrectPositions.add(new BetterBlockPos(x, y, z));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -497,38 +478,13 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
private void fullRecalc(BuilderCalculationContext bcc) {
|
||||
public void fullRecalc(BuilderCalculationContext bcc) {
|
||||
incorrectPositions = new HashSet<>();
|
||||
for (int y = 0; y < schematic.heightY(); y++) {
|
||||
for (int z = 0; z < schematic.lengthZ(); z++) {
|
||||
for (int x = 0; x < schematic.widthX(); x++) {
|
||||
if (!schematic.inSchematic(x, y, z)) {
|
||||
continue;
|
||||
}
|
||||
int blockX = x + origin.getX();
|
||||
int blockY = y + origin.getY();
|
||||
int blockZ = z + origin.getZ();
|
||||
if (bcc.bsi.worldContainsLoadedChunk(blockX, blockZ)) { // check if its in render distance, not if its in cache
|
||||
// we can directly observe this block, it is in render distance
|
||||
if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z))) {
|
||||
observedCompleted.add(BetterBlockPos.longHash(blockX, blockY, blockZ));
|
||||
} else {
|
||||
incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
|
||||
observedCompleted.remove(BetterBlockPos.longHash(blockX, blockY, blockZ));
|
||||
if (incorrectPositions.size() > Baritone.settings().incorrectSize.value) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
// this is not in render distance
|
||||
if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))) {
|
||||
// and we've never seen this position be correct
|
||||
// therefore mark as incorrect
|
||||
incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
|
||||
if (incorrectPositions.size() > Baritone.settings().incorrectSize.value) {
|
||||
return;
|
||||
}
|
||||
if (schematic.inSchematic(x, y, z) && !valid(bcc.bsi.get0(x + origin.getX(), y + origin.getY(), z + origin.getZ()), schematic.desiredState(x, y, z))) {
|
||||
incorrectPositions.add(new BetterBlockPos(x + origin.getX(), y + origin.getY(), z + origin.getZ()));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -536,45 +492,17 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
|
||||
private Goal assemble(BuilderCalculationContext bcc, List<IBlockState> approxPlacable) {
|
||||
List<BetterBlockPos> placable = new ArrayList<>();
|
||||
List<BetterBlockPos> breakable = new ArrayList<>();
|
||||
List<BetterBlockPos> sourceLiquids = new ArrayList<>();
|
||||
incorrectPositions.forEach(pos -> {
|
||||
IBlockState state = bcc.bsi.get0(pos);
|
||||
if (state.getBlock() instanceof BlockAir) {
|
||||
if (approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))) {
|
||||
placable.add(pos);
|
||||
}
|
||||
} else {
|
||||
if (state.getBlock() instanceof BlockLiquid) {
|
||||
// if the block itself is JUST a liquid (i.e. not just a waterlogged block), we CANNOT break it
|
||||
// TODO for 1.13 make sure that this only matches pure water, not waterlogged blocks
|
||||
if (!MovementHelper.possiblyFlowing(state)) {
|
||||
// if it's a source block then we want to replace it with a throwaway
|
||||
sourceLiquids.add(pos);
|
||||
}
|
||||
} else {
|
||||
breakable.add(pos);
|
||||
}
|
||||
}
|
||||
});
|
||||
List<Goal> toBreak = new ArrayList<>();
|
||||
breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
|
||||
List<Goal> toPlace = new ArrayList<>();
|
||||
placable.forEach(pos -> {
|
||||
if (!placable.contains(pos.down()) && !placable.contains(pos.down(2))) {
|
||||
toPlace.add(placementGoal(pos, bcc));
|
||||
}
|
||||
});
|
||||
sourceLiquids.forEach(pos -> toPlace.add(new GoalBlock(pos.up())));
|
||||
List<BetterBlockPos> placable = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() instanceof BlockAir && approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))).collect(Collectors.toList());
|
||||
Goal[] toBreak = incorrectPositions.stream().filter(pos -> !(bcc.bsi.get0(pos).getBlock() instanceof BlockAir)).map(GoalBreak::new).toArray(Goal[]::new);
|
||||
Goal[] toPlace = placable.stream().filter(pos -> !placable.contains(pos.down()) && !placable.contains(pos.down(2))).map(pos -> placementgoal(pos, bcc)).toArray(Goal[]::new);
|
||||
|
||||
if (!toPlace.isEmpty()) {
|
||||
return new JankyGoalComposite(new GoalComposite(toPlace.toArray(new Goal[0])), new GoalComposite(toBreak.toArray(new Goal[0])));
|
||||
if (toPlace.length != 0) {
|
||||
return new JankyGoalComposite(new GoalComposite(toPlace), new GoalComposite(toBreak));
|
||||
}
|
||||
if (toBreak.isEmpty()) {
|
||||
if (toBreak.length == 0) {
|
||||
return null;
|
||||
}
|
||||
return new GoalComposite(toBreak.toArray(new Goal[0]));
|
||||
return new GoalComposite(toBreak);
|
||||
}
|
||||
|
||||
public static class JankyGoalComposite implements Goal {
|
||||
@@ -620,41 +548,24 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
}
|
||||
|
||||
private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
|
||||
if (ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) { // TODO can this even happen?
|
||||
public Goal placementgoal(BlockPos pos, BuilderCalculationContext bcc) {
|
||||
if (!(ctx.world().getBlockState(pos).getBlock() instanceof BlockAir)) {
|
||||
return new GoalPlace(pos);
|
||||
}
|
||||
boolean allowSameLevel = ctx.world().getBlockState(pos.up()).getBlock() != Blocks.AIR;
|
||||
for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN_____SO_EVERY_DIRECTION_EXCEPT_UP) {
|
||||
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && ctx.world().mayPlace(bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ()).getBlock(), pos, false, facing, null)) {
|
||||
return new GoalAdjacent(pos, pos.offset(facing), allowSameLevel);
|
||||
boolean allowSameLevel = !(ctx.world().getBlockState(pos.up()).getBlock() instanceof BlockAir);
|
||||
for (EnumFacing facing : Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP) {
|
||||
if (MovementHelper.canPlaceAgainst(ctx, pos.offset(facing)) && placementPlausible(pos, bcc.getSchematic(pos.getX(), pos.getY(), pos.getZ()))) {
|
||||
return new GoalAdjacent(pos, allowSameLevel);
|
||||
}
|
||||
}
|
||||
return new GoalPlace(pos);
|
||||
}
|
||||
|
||||
private Goal breakGoal(BlockPos pos, BuilderCalculationContext bcc) {
|
||||
if (Baritone.settings().goalBreakFromAbove.value && bcc.bsi.get0(pos.up()).getBlock() instanceof BlockAir && bcc.bsi.get0(pos.up(2)).getBlock() instanceof BlockAir) { // TODO maybe possible without the up(2) check?
|
||||
return new JankyGoalComposite(new GoalBreak(pos), new GoalGetToBlock(pos.up()) {
|
||||
@Override
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
if (y > this.y || (x == this.x && y == this.y && z == this.z)) {
|
||||
return false;
|
||||
}
|
||||
return super.isInGoal(x, y, z);
|
||||
}
|
||||
});
|
||||
}
|
||||
return new GoalBreak(pos);
|
||||
}
|
||||
|
||||
public static class GoalAdjacent extends GoalGetToBlock {
|
||||
private boolean allowSameLevel;
|
||||
private BlockPos no;
|
||||
|
||||
public GoalAdjacent(BlockPos pos, BlockPos no, boolean allowSameLevel) {
|
||||
public GoalAdjacent(BlockPos pos, boolean allowSameLevel) {
|
||||
super(pos);
|
||||
this.no = no;
|
||||
this.allowSameLevel = allowSameLevel;
|
||||
}
|
||||
|
||||
@@ -662,9 +573,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
if (x == this.x && y == this.y && z == this.z) {
|
||||
return false;
|
||||
}
|
||||
if (x == no.getX() && y == no.getY() && z == no.getZ()) {
|
||||
return false;
|
||||
}
|
||||
if (!allowSameLevel && y == this.y - 1) {
|
||||
return false;
|
||||
}
|
||||
@@ -699,7 +607,6 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
realSchematic = null;
|
||||
layer = 0;
|
||||
paused = false;
|
||||
observedCompleted = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -707,7 +614,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
return paused ? "Builder Paused" : "Building " + name;
|
||||
}
|
||||
|
||||
private List<IBlockState> placable(int size) {
|
||||
public List<IBlockState> placable(int size) {
|
||||
List<IBlockState> result = new ArrayList<>();
|
||||
for (int i = 0; i < size; i++) {
|
||||
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
|
||||
@@ -716,18 +623,21 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
continue;
|
||||
}
|
||||
// <toxic cloud>
|
||||
result.add(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(ctx.world(), ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ, stack.getItem().getMetadata(stack.getMetadata()), ctx.player()));
|
||||
result.add(((ItemBlock) stack.getItem()).getBlock().getStateForPlacement(new BlockItemUseContext(new ItemUseContext(ctx.player(), stack, ctx.playerFeet(), EnumFacing.UP, (float) ctx.player().posX, (float) ctx.player().posY, (float) ctx.player().posZ))));
|
||||
// </toxic cloud>
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean valid(IBlockState current, IBlockState desired) {
|
||||
// TODO more complicated comparison logic I guess
|
||||
if (current.getBlock() instanceof BlockLiquid && Baritone.settings().okIfWater.value) {
|
||||
public boolean valid(IBlockState current, IBlockState desired) {
|
||||
if (desired == null) {
|
||||
return true;
|
||||
}
|
||||
return desired == null || current.equals(desired);
|
||||
if (current.getBlock() instanceof BlockAir && desired.getBlock() instanceof BlockAir) {
|
||||
return true;
|
||||
}
|
||||
// TODO more complicated comparison logic I guess
|
||||
return current.equals(desired);
|
||||
}
|
||||
|
||||
public class BuilderCalculationContext extends CalculationContext {
|
||||
@@ -765,7 +675,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
IBlockState sch = getSchematic(x, y, z);
|
||||
if (sch != null) {
|
||||
// TODO this can return true even when allowPlace is off.... is that an issue?
|
||||
if (sch.getBlock() == Blocks.AIR) {
|
||||
if (sch.getBlock() instanceof BlockAir) {
|
||||
// we want this to be air, but they're asking if they can place here
|
||||
// this won't be a schematic block, this will be a throwaway
|
||||
return placeBlockCost * 2; // we're going to have to break it eventually
|
||||
@@ -798,7 +708,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
}
|
||||
IBlockState sch = getSchematic(x, y, z);
|
||||
if (sch != null) {
|
||||
if (sch.getBlock() == Blocks.AIR) {
|
||||
if (sch.getBlock() instanceof BlockAir) {
|
||||
// it should be air
|
||||
// regardless of current contents, we can break it
|
||||
return 1;
|
||||
@@ -806,7 +716,7 @@ public final class BuilderProcess extends BaritoneProcessHelper implements IBuil
|
||||
// it should be a real block
|
||||
// is it already that block?
|
||||
if (valid(bsi.get0(x, y, z), sch)) {
|
||||
return Baritone.settings().breakCorrectBlockPenaltyMultiplier.value;
|
||||
return 3;
|
||||
} else {
|
||||
// can break if it's wrong
|
||||
// would be great to return less than 1 here, but that would actually make the cost calculation messed up
|
||||
|
||||
@@ -29,7 +29,7 @@ import baritone.utils.BaritoneProcessHelper;
|
||||
*
|
||||
* @author leijurv
|
||||
*/
|
||||
public final class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess {
|
||||
public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess {
|
||||
|
||||
/**
|
||||
* The current goal
|
||||
|
||||
@@ -22,33 +22,19 @@ import baritone.api.cache.ICachedWorld;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.pathing.goals.GoalXZ;
|
||||
import baritone.api.pathing.goals.GoalYLevel;
|
||||
import baritone.api.process.IExploreProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.MyChunkPos;
|
||||
import baritone.cache.CachedWorld;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import com.google.gson.Gson;
|
||||
import com.google.gson.GsonBuilder;
|
||||
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.ChunkPos;
|
||||
|
||||
import java.io.InputStreamReader;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
public final class ExploreProcess extends BaritoneProcessHelper implements IExploreProcess {
|
||||
public class ExploreProcess extends BaritoneProcessHelper {
|
||||
|
||||
private BlockPos explorationOrigin;
|
||||
|
||||
private IChunkFilter filter;
|
||||
|
||||
private int distanceCompleted;
|
||||
|
||||
public ExploreProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
@@ -58,25 +44,8 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
return explorationOrigin != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void explore(int centerX, int centerZ) {
|
||||
explorationOrigin = new BlockPos(centerX, 0, centerZ);
|
||||
distanceCompleted = 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void applyJsonFilter(Path path, boolean invert) throws Exception {
|
||||
filter = new JsonChunkFilter(path, invert);
|
||||
}
|
||||
|
||||
public IChunkFilter calcFilter() {
|
||||
IChunkFilter filter;
|
||||
if (this.filter != null) {
|
||||
filter = new EitherChunk(this.filter, new BaritoneChunkCache());
|
||||
} else {
|
||||
filter = new BaritoneChunkCache();
|
||||
}
|
||||
return filter;
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -86,196 +55,45 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
onLostControl();
|
||||
return null;
|
||||
}
|
||||
IChunkFilter filter = calcFilter();
|
||||
if (!Baritone.settings().disableCompletionCheck.value && filter.countRemain() == 0) {
|
||||
logDirect("Explored all chunks");
|
||||
onLostControl();
|
||||
return null;
|
||||
}
|
||||
Goal[] closestUncached = closestUncachedChunks(explorationOrigin, filter);
|
||||
Goal[] closestUncached = closestUncachedChunks(explorationOrigin);
|
||||
if (closestUncached == null) {
|
||||
logDebug("awaiting region load from disk");
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
System.out.println("Closest uncached: " + closestUncached);
|
||||
return new PathingCommand(new GoalComposite(closestUncached), PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
private Goal[] closestUncachedChunks(BlockPos center, IChunkFilter filter) {
|
||||
private Goal[] closestUncachedChunks(BlockPos center) {
|
||||
int chunkX = center.getX() >> 4;
|
||||
int chunkZ = center.getZ() >> 4;
|
||||
int count = Math.min(filter.countRemain(), Baritone.settings().exploreChunkSetMinimumSize.value);
|
||||
List<BlockPos> centers = new ArrayList<>();
|
||||
int renderDistance = Baritone.settings().worldExploringChunkOffset.value;
|
||||
for (int dist = distanceCompleted; ; dist++) {
|
||||
ICachedWorld cache = baritone.getWorldProvider().getCurrentWorld().getCachedWorld();
|
||||
for (int dist = 0; ; dist++) {
|
||||
List<BlockPos> centers = new ArrayList<>();
|
||||
for (int dx = -dist; dx <= dist; dx++) {
|
||||
int zval = dist - Math.abs(dx);
|
||||
for (int mult = 0; mult < 2; mult++) {
|
||||
int dz = (mult * 2 - 1) * zval; // dz can be either -zval or zval
|
||||
int trueDist = Math.abs(dx) + Math.abs(dz);
|
||||
for (int dz = -dist; dz <= dist; dz++) {
|
||||
int trueDist = Baritone.settings().exploreUsePythagorean.value ? dx * dx + dz * dz : Math.abs(dx) + Math.abs(dz);
|
||||
if (trueDist != dist) {
|
||||
throw new IllegalStateException();
|
||||
continue; // not considering this one just yet in our expanding search
|
||||
}
|
||||
switch (filter.isAlreadyExplored(chunkX + dx, chunkZ + dz)) {
|
||||
case UNKNOWN:
|
||||
return null; // awaiting load
|
||||
case NOT_EXPLORED:
|
||||
break; // note: this breaks the switch not the for
|
||||
case EXPLORED:
|
||||
continue; // note: this continues the for
|
||||
default:
|
||||
int centerX = (chunkX + dx) * 16 + 8;
|
||||
int centerZ = (chunkZ + dz) * 18 + 8;
|
||||
|
||||
if (cache.isCached(centerX, centerZ)) {
|
||||
continue;
|
||||
}
|
||||
int centerX = ((chunkX + dx) << 4) + 8;
|
||||
int centerZ = ((chunkZ + dz) << 4) + 8;
|
||||
int offset = renderDistance << 4;
|
||||
if (dx < 0) {
|
||||
centerX -= offset;
|
||||
} else {
|
||||
centerX += offset;
|
||||
}
|
||||
if (dz < 0) {
|
||||
centerZ -= offset;
|
||||
} else {
|
||||
centerZ += offset;
|
||||
if (!((CachedWorld) cache).regionLoaded(centerX, centerZ)) {
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
((CachedWorld) cache).tryLoadFromDisk(centerX >> 9, centerZ >> 9);
|
||||
});
|
||||
return null; // we still need to load regions from disk in order to decide properly
|
||||
}
|
||||
centers.add(new BlockPos(centerX, 0, centerZ));
|
||||
}
|
||||
}
|
||||
if (dist % 10 == 0) {
|
||||
count = Math.min(filter.countRemain(), Baritone.settings().exploreChunkSetMinimumSize.value);
|
||||
if (!centers.isEmpty()) {
|
||||
return centers.stream().map(pos -> new GoalXZ(pos.getX(), pos.getZ())).toArray(Goal[]::new);
|
||||
}
|
||||
if (centers.size() >= count) {
|
||||
return centers.stream().map(pos -> createGoal(pos.getX(), pos.getZ())).toArray(Goal[]::new);
|
||||
}
|
||||
if (centers.isEmpty()) {
|
||||
// we have explored everything from 0 to dist inclusive
|
||||
// next time we should start our check at dist+1
|
||||
distanceCompleted = dist + 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Goal createGoal(int x, int z) {
|
||||
if (Baritone.settings().exploreMaintainY.value == -1) {
|
||||
return new GoalXZ(x, z);
|
||||
}
|
||||
// don't use a goalblock because we still want isInGoal to return true if X and Z are correct
|
||||
// we just want to try and maintain Y on the way there, not necessarily end at that specific Y
|
||||
return new GoalXZ(x, z) {
|
||||
@Override
|
||||
public double heuristic(int x, int y, int z) {
|
||||
return super.heuristic(x, y, z) + GoalYLevel.calculate(Baritone.settings().exploreMaintainY.value, y);
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
private enum Status {
|
||||
EXPLORED, NOT_EXPLORED, UNKNOWN;
|
||||
}
|
||||
|
||||
private interface IChunkFilter {
|
||||
Status isAlreadyExplored(int chunkX, int chunkZ);
|
||||
|
||||
int countRemain();
|
||||
}
|
||||
|
||||
private class BaritoneChunkCache implements IChunkFilter {
|
||||
|
||||
private final ICachedWorld cache = baritone.getWorldProvider().getCurrentWorld().getCachedWorld();
|
||||
|
||||
@Override
|
||||
public Status isAlreadyExplored(int chunkX, int chunkZ) {
|
||||
int centerX = chunkX << 4;
|
||||
int centerZ = chunkZ << 4;
|
||||
if (cache.isCached(centerX, centerZ)) {
|
||||
return Status.EXPLORED;
|
||||
}
|
||||
if (!((CachedWorld) cache).regionLoaded(centerX, centerZ)) {
|
||||
Baritone.getExecutor().execute(() -> {
|
||||
((CachedWorld) cache).tryLoadFromDisk(centerX >> 9, centerZ >> 9);
|
||||
});
|
||||
return Status.UNKNOWN; // we still need to load regions from disk in order to decide properly
|
||||
}
|
||||
return Status.NOT_EXPLORED;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countRemain() {
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
}
|
||||
|
||||
private class JsonChunkFilter implements IChunkFilter {
|
||||
private final boolean invert; // if true, the list is interpreted as a list of chunks that are NOT explored, if false, the list is interpreted as a list of chunks that ARE explored
|
||||
private final LongOpenHashSet inFilter;
|
||||
private final MyChunkPos[] positions;
|
||||
|
||||
private JsonChunkFilter(Path path, boolean invert) throws Exception { // ioexception, json exception, etc
|
||||
this.invert = invert;
|
||||
Gson gson = new GsonBuilder().create();
|
||||
positions = gson.fromJson(new InputStreamReader(Files.newInputStream(path)), MyChunkPos[].class);
|
||||
logDirect("Loaded " + positions.length + " positions");
|
||||
inFilter = new LongOpenHashSet();
|
||||
for (MyChunkPos mcp : positions) {
|
||||
inFilter.add(ChunkPos.asLong(mcp.x, mcp.z));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status isAlreadyExplored(int chunkX, int chunkZ) {
|
||||
if (inFilter.contains(ChunkPos.asLong(chunkX, chunkZ)) ^ invert) {
|
||||
// either it's on the list of explored chunks, or it's not on the list of unexplored chunks
|
||||
// either way, we have it
|
||||
return Status.EXPLORED;
|
||||
} else {
|
||||
// either it's not on the list of explored chunks, or it's on the list of unexplored chunks
|
||||
// either way, it depends on if baritone has cached it so defer to that
|
||||
return Status.UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countRemain() {
|
||||
if (!invert) {
|
||||
// if invert is false, anything not on the list is uncached
|
||||
return Integer.MAX_VALUE;
|
||||
}
|
||||
// but if invert is true, anything not on the list IS assumed cached
|
||||
// so we are done if everything on our list is cached!
|
||||
int countRemain = 0;
|
||||
BaritoneChunkCache bcc = new BaritoneChunkCache();
|
||||
for (MyChunkPos pos : positions) {
|
||||
if (bcc.isAlreadyExplored(pos.x, pos.z) != Status.EXPLORED) {
|
||||
// either waiting for it or dont have it at all
|
||||
countRemain++;
|
||||
if (countRemain >= Baritone.settings().exploreChunkSetMinimumSize.value) {
|
||||
return countRemain;
|
||||
}
|
||||
}
|
||||
}
|
||||
return countRemain;
|
||||
}
|
||||
}
|
||||
|
||||
private class EitherChunk implements IChunkFilter {
|
||||
private final IChunkFilter a;
|
||||
private final IChunkFilter b;
|
||||
|
||||
private EitherChunk(IChunkFilter a, IChunkFilter b) {
|
||||
this.a = a;
|
||||
this.b = b;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Status isAlreadyExplored(int chunkX, int chunkZ) {
|
||||
if (a.isAlreadyExplored(chunkX, chunkZ) == Status.EXPLORED) {
|
||||
return Status.EXPLORED;
|
||||
}
|
||||
return b.isAlreadyExplored(chunkX, chunkZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
public int countRemain() {
|
||||
return Math.min(a.countRemain(), b.countRemain());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -286,6 +104,6 @@ public final class ExploreProcess extends BaritoneProcessHelper implements IExpl
|
||||
|
||||
@Override
|
||||
public String displayName0() {
|
||||
return "Exploring around " + explorationOrigin + ", distance completed " + distanceCompleted + ", currently going to " + new GoalComposite(closestUncachedChunks(explorationOrigin, calcFilter()));
|
||||
return "Exploring around " + explorationOrigin + ", currently going to " + new GoalComposite(closestUncachedChunks(explorationOrigin));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,295 +0,0 @@
|
||||
/*
|
||||
* This file is part of Baritone.
|
||||
*
|
||||
* Baritone is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU Lesser General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* Baritone is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU Lesser General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU Lesser General Public License
|
||||
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
package baritone.process;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.api.pathing.goals.GoalComposite;
|
||||
import baritone.api.process.IFarmProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.RayTraceUtils;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
import baritone.utils.BaritoneProcessHelper;
|
||||
import net.minecraft.block.*;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.init.Blocks;
|
||||
import net.minecraft.init.Items;
|
||||
import net.minecraft.item.EnumDyeColor;
|
||||
import net.minecraft.item.Item;
|
||||
import net.minecraft.item.ItemDye;
|
||||
import net.minecraft.item.ItemStack;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.util.math.RayTraceResult;
|
||||
import net.minecraft.util.math.Vec3d;
|
||||
import net.minecraft.world.World;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
import java.util.function.Predicate;
|
||||
|
||||
public final class FarmProcess extends BaritoneProcessHelper implements IFarmProcess {
|
||||
|
||||
private boolean active;
|
||||
|
||||
private List<BlockPos> locations;
|
||||
private int tickCount;
|
||||
|
||||
private static final List<Item> FARMLAND_PLANTABLE = Arrays.asList(
|
||||
Items.BEETROOT_SEEDS,
|
||||
Items.MELON_SEEDS,
|
||||
Items.WHEAT_SEEDS,
|
||||
Items.PUMPKIN_SEEDS,
|
||||
Items.POTATO,
|
||||
Items.CARROT
|
||||
);
|
||||
|
||||
private static final List<Item> PICKUP_DROPPED = Arrays.asList(
|
||||
Items.BEETROOT_SEEDS,
|
||||
Items.BEETROOT,
|
||||
Items.MELON_SEEDS,
|
||||
Items.MELON,
|
||||
Item.getItemFromBlock(Blocks.MELON_BLOCK),
|
||||
Items.WHEAT_SEEDS,
|
||||
Items.WHEAT,
|
||||
Items.PUMPKIN_SEEDS,
|
||||
Item.getItemFromBlock(Blocks.PUMPKIN),
|
||||
Items.POTATO,
|
||||
Items.CARROT,
|
||||
Items.NETHER_WART,
|
||||
Items.REEDS,
|
||||
Item.getItemFromBlock(Blocks.CACTUS)
|
||||
);
|
||||
|
||||
public FarmProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isActive() {
|
||||
return active;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void farm() {
|
||||
active = true;
|
||||
locations = null;
|
||||
}
|
||||
|
||||
private enum Harvest {
|
||||
WHEAT((BlockCrops) Blocks.WHEAT),
|
||||
CARROTS((BlockCrops) Blocks.CARROTS),
|
||||
POTATOES((BlockCrops) Blocks.POTATOES),
|
||||
BEETROOT((BlockCrops) Blocks.BEETROOTS),
|
||||
PUMPKIN(Blocks.PUMPKIN, state -> true),
|
||||
MELON(Blocks.MELON_BLOCK, state -> true),
|
||||
NETHERWART(Blocks.NETHER_WART, state -> state.getValue(BlockNetherWart.AGE) >= 3),
|
||||
SUGARCANE(Blocks.REEDS, null) {
|
||||
@Override
|
||||
public boolean readyToHarvest(World world, BlockPos pos, IBlockState state) {
|
||||
return world.getBlockState(pos.down()).getBlock() instanceof BlockReed;
|
||||
}
|
||||
},
|
||||
CACTUS(Blocks.CACTUS, null) {
|
||||
@Override
|
||||
public boolean readyToHarvest(World world, BlockPos pos, IBlockState state) {
|
||||
return world.getBlockState(pos.down()).getBlock() instanceof BlockCactus;
|
||||
}
|
||||
};
|
||||
public final Block block;
|
||||
public final Predicate<IBlockState> readyToHarvest;
|
||||
|
||||
Harvest(BlockCrops blockCrops) {
|
||||
this(blockCrops, blockCrops::isMaxAge);
|
||||
// max age is 7 for wheat, carrots, and potatoes, but 3 for beetroot
|
||||
}
|
||||
|
||||
Harvest(Block block, Predicate<IBlockState> readyToHarvest) {
|
||||
this.block = block;
|
||||
this.readyToHarvest = readyToHarvest;
|
||||
}
|
||||
|
||||
public boolean readyToHarvest(World world, BlockPos pos, IBlockState state) {
|
||||
return readyToHarvest.test(state);
|
||||
}
|
||||
}
|
||||
|
||||
private boolean readyForHarvest(World world, BlockPos pos, IBlockState state) {
|
||||
for (Harvest harvest : Harvest.values()) {
|
||||
if (harvest.block == state.getBlock()) {
|
||||
return harvest.readyToHarvest(world, pos, state);
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
private boolean isPlantable(ItemStack stack) {
|
||||
return FARMLAND_PLANTABLE.contains(stack.getItem());
|
||||
}
|
||||
|
||||
private boolean isBoneMeal(ItemStack stack) {
|
||||
return !stack.isEmpty() && stack.getItem() instanceof ItemDye && EnumDyeColor.byDyeDamage(stack.getMetadata()) == EnumDyeColor.WHITE;
|
||||
}
|
||||
|
||||
private boolean isNetherWart(ItemStack stack) {
|
||||
return !stack.isEmpty() && stack.getItem().equals(Items.NETHER_WART);
|
||||
}
|
||||
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
ArrayList<Block> scan = new ArrayList<>();
|
||||
for (Harvest harvest : Harvest.values()) {
|
||||
scan.add(harvest.block);
|
||||
}
|
||||
scan.add(Blocks.FARMLAND);
|
||||
if (Baritone.settings().replantNetherWart.value) {
|
||||
scan.add(Blocks.SOUL_SAND);
|
||||
}
|
||||
if (Baritone.settings().mineGoalUpdateInterval.value != 0 && tickCount++ % Baritone.settings().mineGoalUpdateInterval.value == 0) {
|
||||
Baritone.getExecutor().execute(() -> locations = WorldScanner.INSTANCE.scanChunkRadius(ctx, scan, 256, 10, 10));
|
||||
}
|
||||
if (locations == null) {
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
List<BlockPos> toBreak = new ArrayList<>();
|
||||
List<BlockPos> openFarmland = new ArrayList<>();
|
||||
List<BlockPos> bonemealable = new ArrayList<>();
|
||||
List<BlockPos> openSoulsand = new ArrayList<>();
|
||||
for (BlockPos pos : locations) {
|
||||
IBlockState state = ctx.world().getBlockState(pos);
|
||||
boolean airAbove = ctx.world().getBlockState(pos.up()).getBlock() instanceof BlockAir;
|
||||
if (state.getBlock() == Blocks.FARMLAND) {
|
||||
if (airAbove) {
|
||||
openFarmland.add(pos);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (state.getBlock() == Blocks.SOUL_SAND) {
|
||||
if (airAbove) {
|
||||
openSoulsand.add(pos);
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (readyForHarvest(ctx.world(), pos, state)) {
|
||||
toBreak.add(pos);
|
||||
continue;
|
||||
}
|
||||
if (state.getBlock() instanceof IGrowable) {
|
||||
IGrowable ig = (IGrowable) state.getBlock();
|
||||
if (ig.canGrow(ctx.world(), pos, state, true) && ig.canUseBonemeal(ctx.world(), ctx.world().rand, pos, state)) {
|
||||
bonemealable.add(pos);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
for (BlockPos pos : toBreak) {
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
|
||||
if (rot.isPresent() && isSafeToCancel) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
MovementHelper.switchToBestToolFor(ctx, ctx.world().getBlockState(pos));
|
||||
if (ctx.isLookingAt(pos)) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
}
|
||||
ArrayList<BlockPos> both = new ArrayList<>(openFarmland);
|
||||
both.addAll(openSoulsand);
|
||||
for (BlockPos pos : both) {
|
||||
boolean soulsand = openSoulsand.contains(pos);
|
||||
Optional<Rotation> rot = RotationUtils.reachableOffset(ctx.player(), pos, new Vec3d(pos.getX() + 0.5, pos.getY() + 1, pos.getZ() + 0.5), ctx.playerController().getBlockReachDistance());
|
||||
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, soulsand ? this::isNetherWart : this::isPlantable)) {
|
||||
RayTraceResult result = RayTraceUtils.rayTraceTowards(ctx.player(), rot.get(), ctx.playerController().getBlockReachDistance());
|
||||
if (result.typeOfHit == RayTraceResult.Type.BLOCK && result.sideHit == EnumFacing.UP) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
if (ctx.isLookingAt(pos)) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
for (BlockPos pos : bonemealable) {
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
|
||||
if (rot.isPresent() && isSafeToCancel && baritone.getInventoryBehavior().throwaway(true, this::isBoneMeal)) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
if (ctx.isLookingAt(pos)) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_RIGHT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
}
|
||||
|
||||
if (calcFailed) {
|
||||
logDirect("Farm failed");
|
||||
onLostControl();
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
|
||||
List<Goal> goalz = new ArrayList<>();
|
||||
for (BlockPos pos : toBreak) {
|
||||
goalz.add(new BuilderProcess.GoalBreak(pos));
|
||||
}
|
||||
if (baritone.getInventoryBehavior().throwaway(false, this::isPlantable)) {
|
||||
for (BlockPos pos : openFarmland) {
|
||||
goalz.add(new GoalBlock(pos.up()));
|
||||
}
|
||||
}
|
||||
if (baritone.getInventoryBehavior().throwaway(false, this::isNetherWart)) {
|
||||
for (BlockPos pos : openSoulsand) {
|
||||
goalz.add(new GoalBlock(pos.up()));
|
||||
}
|
||||
}
|
||||
if (baritone.getInventoryBehavior().throwaway(false, this::isBoneMeal)) {
|
||||
for (BlockPos pos : bonemealable) {
|
||||
goalz.add(new GoalBlock(pos));
|
||||
}
|
||||
}
|
||||
for (Entity entity : ctx.world().loadedEntityList) {
|
||||
if (entity instanceof EntityItem && entity.onGround) {
|
||||
EntityItem ei = (EntityItem) entity;
|
||||
if (PICKUP_DROPPED.contains(ei.getItem().getItem())) {
|
||||
// +0.1 because of farmland's 0.9375 dummy height lol
|
||||
goalz.add(new GoalBlock(new BlockPos(entity.posX, entity.posY + 0.1, entity.posZ)));
|
||||
}
|
||||
}
|
||||
}
|
||||
return new PathingCommand(new GoalComposite(goalz.toArray(new Goal[0])), PathingCommandType.SET_GOAL_AND_PATH);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onLostControl() {
|
||||
active = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String displayName0() {
|
||||
return "Farming";
|
||||
}
|
||||
}
|
||||
@@ -72,7 +72,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
if (entity == null) {
|
||||
return false;
|
||||
}
|
||||
if (entity.isDead) {
|
||||
if (!entity.isAlive()) {
|
||||
return false;
|
||||
}
|
||||
if (entity.equals(ctx.player())) {
|
||||
@@ -82,12 +82,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
|
||||
}
|
||||
|
||||
private void scanWorld() {
|
||||
cache = Stream.of(ctx.world().loadedEntityList, ctx.world().playerEntities)
|
||||
.flatMap(List::stream)
|
||||
.filter(this::followable)
|
||||
.filter(this.filter)
|
||||
.distinct()
|
||||
.collect(Collectors.toCollection(ArrayList::new));
|
||||
cache = Stream.of(ctx.world().loadedEntityList, ctx.world().playerEntities).flatMap(List::stream).filter(this::followable).filter(this.filter).distinct().collect(Collectors.toCollection(ArrayList::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -34,7 +34,7 @@ import net.minecraft.util.math.BlockPos;
|
||||
|
||||
import java.util.*;
|
||||
|
||||
public final class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
|
||||
public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
|
||||
|
||||
private Block gettingTo;
|
||||
private List<BlockPos> knownLocations;
|
||||
@@ -42,7 +42,6 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
private BlockPos start;
|
||||
|
||||
private int tickCount = 0;
|
||||
private int arrivalTickCount = 0;
|
||||
|
||||
public GetToBlockProcess(Baritone baritone) {
|
||||
super(baritone);
|
||||
@@ -54,7 +53,6 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
gettingTo = block;
|
||||
start = ctx.playerFeet();
|
||||
blacklist = new ArrayList<>();
|
||||
arrivalTickCount = 0;
|
||||
rescan(new ArrayList<>(), new CalculationContext(baritone));
|
||||
}
|
||||
|
||||
@@ -119,7 +117,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
}
|
||||
|
||||
// blacklist the closest block and its adjacent blocks
|
||||
public synchronized boolean blacklistClosest() {
|
||||
public synchronized void blacklistClosest() {
|
||||
List<BlockPos> newBlacklist = new ArrayList<>();
|
||||
knownLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(newBlacklist::add);
|
||||
outer:
|
||||
@@ -142,7 +140,6 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
}
|
||||
logDebug("Blacklisting unreachable locations " + newBlacklist);
|
||||
blacklist.addAll(newBlacklist);
|
||||
return !newBlacklist.isEmpty();
|
||||
}
|
||||
|
||||
// safer than direct double comparison from distanceSq
|
||||
@@ -198,10 +195,6 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
return true;
|
||||
}
|
||||
}
|
||||
if (arrivalTickCount++ > 20) {
|
||||
logDirect("Right click timed out");
|
||||
return true;
|
||||
}
|
||||
return false; // trying to right click, will do it next tick or so
|
||||
}
|
||||
}
|
||||
@@ -213,7 +206,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
|
||||
if (!Baritone.settings().enterPortal.value) {
|
||||
return false;
|
||||
}
|
||||
return block == Blocks.PORTAL;
|
||||
return block == Blocks.NETHER_PORTAL;
|
||||
}
|
||||
|
||||
private boolean rightClickOnArrival(Block block) {
|
||||
|
||||
@@ -22,12 +22,10 @@ import baritone.api.pathing.goals.*;
|
||||
import baritone.api.process.IMineProcess;
|
||||
import baritone.api.process.PathingCommand;
|
||||
import baritone.api.process.PathingCommandType;
|
||||
import baritone.api.utils.BlockUtils;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import baritone.api.utils.Rotation;
|
||||
import baritone.api.utils.RotationUtils;
|
||||
import baritone.api.utils.input.Input;
|
||||
import baritone.cache.CachedChunk;
|
||||
import baritone.cache.ChunkPacker;
|
||||
import baritone.cache.WorldScanner;
|
||||
import baritone.pathing.movement.CalculationContext;
|
||||
import baritone.pathing.movement.MovementHelper;
|
||||
@@ -35,8 +33,6 @@ import baritone.utils.BaritoneProcessHelper;
|
||||
import baritone.utils.BlockStateInterface;
|
||||
import net.minecraft.block.Block;
|
||||
import net.minecraft.block.BlockAir;
|
||||
import net.minecraft.block.BlockFalling;
|
||||
import net.minecraft.block.state.IBlockState;
|
||||
import net.minecraft.entity.Entity;
|
||||
import net.minecraft.entity.item.EntityItem;
|
||||
import net.minecraft.init.Blocks;
|
||||
@@ -48,8 +44,6 @@ import net.minecraft.world.World;
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
|
||||
|
||||
/**
|
||||
* Mine blocks of a certain type
|
||||
*
|
||||
@@ -79,61 +73,36 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
@Override
|
||||
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
|
||||
if (desiredQuantity > 0) {
|
||||
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0);
|
||||
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), ctx.world(), null, 0).asItem();
|
||||
int curr = ctx.player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum();
|
||||
System.out.println("Currently have " + curr + " " + item);
|
||||
if (curr >= desiredQuantity) {
|
||||
logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1)));
|
||||
logDirect("Have " + curr + " " + item.getDisplayName(new ItemStack(item, 1)));
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
if (calcFailed) {
|
||||
if (!knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
|
||||
logDirect("Unable to find any path to " + mining + ", blacklisting presumably unreachable closest instance...");
|
||||
knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(blacklist::add);
|
||||
knownOreLocations.removeIf(blacklist::contains);
|
||||
} else {
|
||||
logDirect("Unable to find any path to " + mining + ", canceling Mine");
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
boolean shouldCancel = calcFailed;
|
||||
if (calcFailed && !knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
|
||||
logDirect("Unable to find any path to " + mining + ", blacklisting presumably unreachable closest instance...");
|
||||
knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(blacklist::add);
|
||||
knownOreLocations.removeIf(blacklist::contains);
|
||||
shouldCancel = false; // 😎
|
||||
}
|
||||
if (!Baritone.settings().allowBreak.value) {
|
||||
logDirect("Unable to mine when allowBreak is false!");
|
||||
if (shouldCancel) {
|
||||
logDirect("Unable to find any path to " + mining + ", canceling Mine");
|
||||
cancel();
|
||||
return null;
|
||||
}
|
||||
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value;
|
||||
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||
if (mineGoalUpdateInterval != 0 && tickCount++ % mineGoalUpdateInterval == 0) { // big brain
|
||||
List<BlockPos> curr = new ArrayList<>(knownOreLocations);
|
||||
CalculationContext context = new CalculationContext(baritone, true);
|
||||
Baritone.getExecutor().execute(() -> rescan(curr, context));
|
||||
}
|
||||
if (Baritone.settings().legitMine.value) {
|
||||
addNearby();
|
||||
}
|
||||
Optional<BlockPos> shaft = curr.stream()
|
||||
.filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ())
|
||||
.filter(pos -> pos.getY() >= ctx.playerFeet().getY())
|
||||
.filter(pos -> !(BlockStateInterface.get(ctx, pos).getBlock() instanceof BlockAir)) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =(
|
||||
.min(Comparator.comparingDouble(ctx.player()::getDistanceSq));
|
||||
baritone.getInputOverrideHandler().clearAllKeys();
|
||||
if (shaft.isPresent() && ctx.player().onGround) {
|
||||
BlockPos pos = shaft.get();
|
||||
IBlockState state = baritone.bsi.get0(pos);
|
||||
if (!MovementHelper.avoidBreaking(baritone.bsi, pos.getX(), pos.getY(), pos.getZ(), state)) {
|
||||
Optional<Rotation> rot = RotationUtils.reachable(ctx, pos);
|
||||
if (rot.isPresent() && isSafeToCancel) {
|
||||
baritone.getLookBehavior().updateTarget(rot.get(), true);
|
||||
MovementHelper.switchToBestToolFor(ctx, ctx.world().getBlockState(pos));
|
||||
if (ctx.isLookingAt(pos) || ctx.playerRotations().isReallyCloseTo(rot.get())) {
|
||||
baritone.getInputOverrideHandler().setInputForceState(Input.CLICK_LEFT, true);
|
||||
}
|
||||
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);
|
||||
}
|
||||
}
|
||||
}
|
||||
PathingCommand command = updateGoal();
|
||||
if (command == null) {
|
||||
// none in range
|
||||
@@ -160,7 +129,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
if (!locs.isEmpty()) {
|
||||
List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, blacklist);
|
||||
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
|
||||
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new));
|
||||
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new));
|
||||
knownOreLocations = locs2;
|
||||
return new PathingCommand(goal, legit ? PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType.REVALIDATE_GOAL_AND_PATH);
|
||||
}
|
||||
@@ -210,88 +179,25 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
knownOreLocations = locs;
|
||||
}
|
||||
|
||||
private boolean internalMiningGoal(BlockPos pos, IPlayerContext ctx, List<BlockPos> locs) {
|
||||
// Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of)
|
||||
if (locs.contains(pos)) {
|
||||
return true;
|
||||
}
|
||||
Block block = BlockStateInterface.getBlock(ctx, pos);
|
||||
if (Baritone.settings().internalMiningAirException.value && block instanceof BlockAir) {
|
||||
return true;
|
||||
}
|
||||
return mining.contains(block);
|
||||
}
|
||||
|
||||
private Goal coalesce(BlockPos loc, List<BlockPos> locs) {
|
||||
boolean assumeVerticalShaftMine = !(baritone.bsi.get0(loc.up()).getBlock() instanceof BlockFalling);
|
||||
private static Goal coalesce(IPlayerContext ctx, BlockPos loc, List<BlockPos> locs) {
|
||||
if (!Baritone.settings().forceInternalMining.value) {
|
||||
if (assumeVerticalShaftMine) {
|
||||
// we can get directly below the block
|
||||
return new GoalThreeBlocks(loc);
|
||||
} else {
|
||||
// we need to get feet or head into the block
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
}
|
||||
boolean upwardGoal = internalMiningGoal(loc.up(), ctx, locs);
|
||||
boolean downwardGoal = internalMiningGoal(loc.down(), ctx, locs);
|
||||
boolean doubleDownwardGoal = internalMiningGoal(loc.down(2), ctx, locs);
|
||||
if (upwardGoal == downwardGoal) { // symmetric
|
||||
if (doubleDownwardGoal && assumeVerticalShaftMine) {
|
||||
// we have a checkerboard like pattern
|
||||
// this one, and the one two below it
|
||||
// therefore it's fine to path to immediately below this one, since your feet will be in the doubleDownwardGoal
|
||||
// but only if assumeVerticalShaftMine
|
||||
return new GoalThreeBlocks(loc);
|
||||
} else {
|
||||
// this block has nothing interesting two below, but is symmetric vertically so we can get either feet or head into it
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
}
|
||||
if (upwardGoal) {
|
||||
// downwardGoal known to be false
|
||||
// ignore the gap then potential doubleDownward, because we want to path feet into this one and head into upwardGoal
|
||||
return new GoalBlock(loc);
|
||||
}
|
||||
// upwardGoal known to be false, downwardGoal known to be true
|
||||
if (doubleDownwardGoal && assumeVerticalShaftMine) {
|
||||
// this block and two below it are goals
|
||||
// path into the center of the one below, because that includes directly below this one
|
||||
return new GoalTwoBlocks(loc.down());
|
||||
}
|
||||
// upwardGoal false, downwardGoal true, doubleDownwardGoal false
|
||||
// just this block and the one immediately below, no others
|
||||
return new GoalBlock(loc.down());
|
||||
}
|
||||
|
||||
private static class GoalThreeBlocks extends GoalTwoBlocks {
|
||||
|
||||
public GoalThreeBlocks(BlockPos pos) {
|
||||
super(pos);
|
||||
return new GoalTwoBlocks(loc);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isInGoal(int x, int y, int z) {
|
||||
return x == this.x && (y == this.y || y == this.y - 1 || y == this.y - 2) && z == this.z;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double heuristic(int x, int y, int z) {
|
||||
int xDiff = x - this.x;
|
||||
int yDiff = y - this.y;
|
||||
int zDiff = z - this.z;
|
||||
return GoalBlock.calculate(xDiff, yDiff < -1 ? yDiff + 2 : yDiff == -1 ? 0 : yDiff, zDiff);
|
||||
}
|
||||
// Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of)
|
||||
boolean upwardGoal = locs.contains(loc.up()) || (Baritone.settings().internalMiningAirException.value && BlockStateInterface.getBlock(ctx, loc.up()) instanceof BlockAir);
|
||||
boolean downwardGoal = locs.contains(loc.down()) || (Baritone.settings().internalMiningAirException.value && BlockStateInterface.getBlock(ctx, loc.down()) instanceof BlockAir);
|
||||
return upwardGoal == downwardGoal ? new GoalTwoBlocks(loc) : upwardGoal ? new GoalBlock(loc) : new GoalBlock(loc.down());
|
||||
}
|
||||
|
||||
public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) {
|
||||
if (!Baritone.settings().mineScanDroppedItems.value) {
|
||||
return Collections.emptyList();
|
||||
return new ArrayList<>();
|
||||
}
|
||||
Set<Item> searchingFor = new HashSet<>();
|
||||
for (Block block : mining) {
|
||||
Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0);
|
||||
Item ore = Item.getItemFromBlock(block);
|
||||
Item drop = block.getItemDropped(block.getDefaultState(), world, null, 0).asItem();
|
||||
Item ore = block.asItem();
|
||||
searchingFor.add(drop);
|
||||
searchingFor.add(ore);
|
||||
}
|
||||
@@ -310,20 +216,24 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
public static List<BlockPos> searchWorld(CalculationContext ctx, List<Block> mining, int max, List<BlockPos> alreadyKnown, List<BlockPos> blacklist) {
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
List<Block> uninteresting = new ArrayList<>();
|
||||
//long b = System.currentTimeMillis();
|
||||
for (Block m : mining) {
|
||||
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
|
||||
// maxRegionDistanceSq 2 means adjacent directly or adjacent diagonally; nothing further than that
|
||||
locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(BlockUtils.blockToString(m), Baritone.settings().maxCachedWorldScanCount.value, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
|
||||
locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), Baritone.settings().maxCachedWorldScanCount.value, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
|
||||
} else {
|
||||
uninteresting.add(m);
|
||||
}
|
||||
}
|
||||
locs = prune(ctx, locs, mining, max, blacklist);
|
||||
if (locs.isEmpty() || (Baritone.settings().extendCacheOnThreshold.value && locs.size() < max)) {
|
||||
//System.out.println("Scan of cached chunks took " + (System.currentTimeMillis() - b) + "ms");
|
||||
if (locs.isEmpty()) {
|
||||
uninteresting = mining;
|
||||
}
|
||||
if (!uninteresting.isEmpty()) {
|
||||
//long before = System.currentTimeMillis();
|
||||
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx.getBaritone().getPlayerContext(), uninteresting, max, 10, 32)); // maxSearchRadius is NOT sq
|
||||
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
|
||||
}
|
||||
locs.addAll(alreadyKnown);
|
||||
return prune(ctx, locs, mining, max, blacklist);
|
||||
@@ -356,7 +266,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world);
|
||||
dropped.removeIf(drop -> {
|
||||
for (BlockPos pos : locs2) {
|
||||
if (pos.distanceSq(drop) <= 9 && mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx, pos)) { // TODO maybe drop also has to be supported? no lava below?
|
||||
if (pos.distanceSq(drop) <= 9 && mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx.bsi, pos)) { // TODO maybe drop also has to be supported? no lava below?
|
||||
return true;
|
||||
}
|
||||
}
|
||||
@@ -370,11 +280,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
|
||||
|
||||
// remove any that are implausible to mine (encased in bedrock, or touching lava)
|
||||
.filter(pos -> MineProcess.plausibleToBreak(ctx, pos))
|
||||
.filter(pos -> MineProcess.plausibleToBreak(ctx.bsi, pos))
|
||||
|
||||
.filter(pos -> !blacklist.contains(pos))
|
||||
|
||||
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().player()::getDistanceSq))
|
||||
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
if (locs.size() > max) {
|
||||
@@ -383,27 +293,23 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
|
||||
return locs;
|
||||
}
|
||||
|
||||
public static boolean plausibleToBreak(CalculationContext ctx, BlockPos pos) {
|
||||
if (MovementHelper.getMiningDurationTicks(ctx, pos.getX(), pos.getY(), pos.getZ(), ctx.bsi.get0(pos), true) >= COST_INF) {
|
||||
public static boolean plausibleToBreak(BlockStateInterface bsi, BlockPos pos) {
|
||||
if (MovementHelper.avoidBreaking(bsi, pos.getX(), pos.getY(), pos.getZ(), bsi.get0(pos))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
// bedrock above and below makes it implausible, otherwise we're good
|
||||
return !(ctx.bsi.get0(pos.up()).getBlock() == Blocks.BEDROCK && ctx.bsi.get0(pos.down()).getBlock() == Blocks.BEDROCK);
|
||||
return !(bsi.get0(pos.up()).getBlock() == Blocks.BEDROCK && bsi.get0(pos.down()).getBlock() == Blocks.BEDROCK);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mineByName(int quantity, String... blocks) {
|
||||
mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(BlockUtils::stringToBlockRequired).toArray(Block[]::new));
|
||||
mine(quantity, blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlockRequired).toArray(Block[]::new));
|
||||
}
|
||||
|
||||
@Override
|
||||
public void mine(int quantity, Block... blocks) {
|
||||
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks);
|
||||
if (mining != null && !Baritone.settings().allowBreak.value) {
|
||||
logDirect("Unable to mine when allowBreak is false!");
|
||||
mining = null;
|
||||
}
|
||||
this.desiredQuantity = quantity;
|
||||
this.knownOreLocations = new ArrayList<>();
|
||||
this.blacklist = new ArrayList<>();
|
||||
|
||||
@@ -22,16 +22,22 @@ import baritone.api.event.events.TickEvent;
|
||||
import baritone.api.event.listener.AbstractGameEventListener;
|
||||
import baritone.api.pathing.goals.Goal;
|
||||
import baritone.api.pathing.goals.GoalBlock;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import net.minecraft.client.GameSettings;
|
||||
import net.minecraft.client.Minecraft;
|
||||
import net.minecraft.client.gui.GuiMainMenu;
|
||||
import net.minecraft.client.settings.GameSettings;
|
||||
import net.minecraft.client.tutorial.TutorialSteps;
|
||||
import net.minecraft.server.integrated.IntegratedServer;
|
||||
import net.minecraft.util.HttpUtil;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.GameType;
|
||||
import net.minecraft.world.WorldSettings;
|
||||
import net.minecraft.world.WorldType;
|
||||
import net.minecraft.world.dimension.DimensionType;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
|
||||
/**
|
||||
* Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific
|
||||
@@ -89,11 +95,13 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
mc.launchIntegratedServer("BaritoneAutoTest", "BaritoneAutoTest", worldsettings);
|
||||
}
|
||||
|
||||
IntegratedServer server = mc.getIntegratedServer();
|
||||
|
||||
// If the integrated server is launched and the world has initialized, set the spawn point
|
||||
// to our defined starting position
|
||||
if (mc.getIntegratedServer() != null && mc.getIntegratedServer().worlds[0] != null) {
|
||||
mc.getIntegratedServer().worlds[0].setSpawnPoint(STARTING_POSITION);
|
||||
mc.getIntegratedServer().worlds[0].getGameRules().setOrCreateGameRule("spawnRadius", "0");
|
||||
if (server != null && server.getWorld(DimensionType.OVERWORLD) != null) {
|
||||
server.getWorld(DimensionType.OVERWORLD).setSpawnPoint(STARTING_POSITION);
|
||||
server.getWorld(DimensionType.OVERWORLD).getGameRules().setOrCreateGameRule("spawnRadius", "0", server);
|
||||
}
|
||||
|
||||
if (event.getType() == TickEvent.Type.IN) { // If we're in-game
|
||||
@@ -101,7 +109,7 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
// Force the integrated server to share the world to LAN so that
|
||||
// the ingame pause menu gui doesn't actually pause our game
|
||||
if (mc.isSingleplayer() && !mc.getIntegratedServer().getPublic()) {
|
||||
mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false);
|
||||
mc.getIntegratedServer().shareToLAN(GameType.getByName("survival"), false, HttpUtil.getSuitableLanPort());
|
||||
}
|
||||
|
||||
// For the first 200 ticks, wait for the world to generate
|
||||
@@ -123,7 +131,16 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
|
||||
// If we have reached our goal, print a message and safely close the game
|
||||
if (GOAL.isInGoal(ctx.playerFeet())) {
|
||||
System.out.println("Successfully pathed to " + ctx.playerFeet() + " in " + event.getCount() + " ticks");
|
||||
try {
|
||||
File file = new File("success");
|
||||
System.out.println("Writing success to " + file.getAbsolutePath());
|
||||
Files.write(file.getAbsoluteFile().toPath(), "Success!".getBytes());
|
||||
} catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
mc.shutdown();
|
||||
mc.shutdownMinecraftApplet();
|
||||
System.exit(0);
|
||||
}
|
||||
|
||||
// If we have exceeded the expected number of ticks to complete the pathing
|
||||
|
||||
@@ -19,7 +19,6 @@ package baritone.utils;
|
||||
|
||||
import baritone.Baritone;
|
||||
import baritone.api.process.IBaritoneProcess;
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
|
||||
public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper {
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
|
||||
package baritone.utils;
|
||||
|
||||
import baritone.api.utils.Helper;
|
||||
import baritone.api.utils.IPlayerContext;
|
||||
import net.minecraft.util.EnumFacing;
|
||||
import net.minecraft.util.EnumHand;
|
||||
@@ -38,7 +37,7 @@ public final class BlockBreakHelper implements Helper {
|
||||
this.playerContext = playerContext;
|
||||
}
|
||||
|
||||
private void tryBreakBlock(BlockPos pos, EnumFacing side) {
|
||||
public void tryBreakBlock(BlockPos pos, EnumFacing side) {
|
||||
if (playerContext.playerController().onPlayerDamageBlock(pos, side)) {
|
||||
playerContext.player().swingArm(EnumHand.MAIN_HAND);
|
||||
}
|
||||
@@ -54,7 +53,7 @@ public final class BlockBreakHelper implements Helper {
|
||||
|
||||
public void tick(boolean isLeftClick) {
|
||||
RayTraceResult trace = playerContext.objectMouseOver();
|
||||
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
|
||||
boolean isBlockTrace = trace != null && trace.type == RayTraceResult.Type.BLOCK;
|
||||
|
||||
if (isLeftClick && isBlockTrace) {
|
||||
tryBreakBlock(trace.getBlockPos(), trace.sideHit);
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user