Compare commits

..

3 Commits

Author SHA1 Message Date
Brady 35cb592d09 Clean up BaritoneResourcePack 2018-12-15 18:11:18 -06:00
Leijurv 863db53b24 improved fitmc 2018-12-15 15:59:36 -08:00
Brady fa3dab0adb Startup FitMC intro sound 2018-12-15 17:50:01 -06:00
90 changed files with 1153 additions and 1242 deletions
-1
View File
@@ -9,7 +9,6 @@ install:
- travis_retry docker build -t cabaletta/baritone .
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 cp baritone:/code/dist dist
- ls dist
+1 -1
View File
@@ -11,7 +11,6 @@
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
- **Parkour** Sprint jumping over 1, 2, or 3 block gaps
- **Parkour place** Sprint jumping over a 3 block gap and placing the block to land on while executing the jump. It's really cool.
- **Pigs** It can sort of control pigs. I wouldn't rely on it though.
# Pathing method
Baritone uses A*, with some modifications:
@@ -47,6 +46,7 @@ Things it doesn't have yet
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.
Things it may not ever have, from most likely to least likely =(
- Pigs
- Boats
- Horses (2x3 path instead of 1x2)
- Elytra
+1
View File
@@ -0,0 +1 @@
Impact 4.4 is out. See <a href="INSTALL.md">INSTALL.md</a>
+10 -2
View File
@@ -1,10 +1,11 @@
# Integration between Baritone and Impact
Impact 4.4 has Baritone included.
These instructions apply to Impact 4.3 (and potentially other "hacked clients").
These instructions apply to Impact 4.3 (and potentially other hacked clients).
To run Baritone on Vanilla, just follow the instructions in the README (it's `./gradlew runClient`).
## An Introduction
There are some basic steps to getting Baritone setup with Impact.
- Acquiring a build of Baritone
@@ -25,7 +26,14 @@ Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMe
The build is fully deterministic and reproducible, and you can verify Travis did it properly by running `docker build --no-cache -t cabaletta/baritone . && docker run --rm cabaletta/baritone cat /code/dist/checksums.txt` yourself and comparing the shasum. This works identically on Travis, Mac, and Linux (if you have docker on Windows, I'd be grateful if you could let me know if it works there too).
### Building Baritone yourself
You can either build Baritone through a command line or through IntelliJ's UI, information on that can be found [here](SETUP.md#building).
There are a few steps to this
- Clone this repository
- Setup the project as instructed in the README
- Run the ``build`` gradle task. You can either do this using IntelliJ's gradle UI or through a
command line
- Windows: ``gradlew build``
- Mac/Linux: ``./gradlew build``
- The build should be exported into ``/build/libs/baritone-X.Y.Z.jar``
## Placing Baritone in the libraries directory
``/libraries`` is a neat directory in your <a href="https://minecraft.gamepedia.com/.minecraft">Minecraft Installation Directory</a>
+31 -17
View File
@@ -6,37 +6,51 @@
[![HitCount](http://hits.dwyl.com/cabaletta/baritone.svg)](http://hits.dwyl.com/cabaletta/baritone)
[![Known Vulnerabilities](https://snyk.io/test/github/cabaletta/baritone/badge.svg?targetFile=build.gradle)](https://snyk.io/test/github/cabaletta/baritone?targetFile=build.gradle)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cabaletta/baritone/issues)
[![Issues](https://img.shields.io/github/issues/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues/)
[![GitHub issues-closed](https://img.shields.io/github/issues-closed/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/issues?q=is%3Aissue+is%3Aclosed)
[![Pull Requests](https://img.shields.io/github/issues-pr/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/pulls/)
![Code size](https://img.shields.io/github/languages/code-size/cabaletta/baritone.svg)
![GitHub repo size](https://img.shields.io/github/repo-size/cabaletta/baritone.svg)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2)
[![GitHub contributors](https://img.shields.io/github/contributors/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/graphs/contributors/)
[![GitHub commits](https://img.shields.io/github/commits-since/cabaletta/baritone/v1.0.0.svg)](https://github.com/cabaletta/baritone/commit/)
[![Asuna integration](https://img.shields.io/badge/Asuna%20integration-builder%20branch-brightgreen.svg)](https://github.com/EmotionalLove/Asuna/)
[![Impact integration](https://img.shields.io/badge/Impact%20integration-v1.0.0--hotfix--4-green.svg)](https://impactdevelopment.github.io/)
[![Impact integration](https://img.shields.io/badge/Impact%20integration-v1.0.0--hotfix--4-brightgreen.svg)](https://impactdevelopment.github.io/)
[![KAMI integration](https://img.shields.io/badge/KAMI%20integration-v1.0.0-orange.svg)](https://github.com/zeroeightysix/KAMI/)
[![WWE integration](https://img.shields.io/badge/WWE%20%22integration%22-v1.0.0%3F%3F%20smh%20license%20violations-orange.svg)](https://wweclient.com/)
[![Future integration](https://img.shields.io/badge/Future%20integration-Soon™%3F%3F%3F-red.svg)](https://futureclient.net/)
[![ForgeHax integration](https://img.shields.io/badge/ForgeHax%20integration-Soon™-red.svg)](https://github.com/fr1kin/ForgeHax)
[![Asuna integration](https://img.shields.io/badge/Asuna%20integration-v1.0.0-orange.svg)](https://github.com/EmotionalLove/Asuna/)
[![Future integration](https://img.shields.io/badge/Future%20integration-%3F%3F%3F-red.svg)](https://futureclient.net/)
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.
This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [30x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. Baritone focuses on reliability and particularly performance (it's over [29x faster](https://github.com/cabaletta/baritone/pull/180#issuecomment-423822928) than MineBot at calculating paths).
Here are some links to help to get started:
- [Features](FEATURES.md)
- [Setup](SETUP.md)
- [Installation](INSTALL.md)
- [Javadocs](https://baritone.leijurv.com/)
There's also some useful information down below
# Setup
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
Running Baritone:
```
$ gradlew runClient
```
Building Baritone:
```
$ gradlew build
```
To replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
## IntelliJ's Gradle UI
- Open the project in IntelliJ as a Gradle project
- Run the Gradle tasks `setupDecompWorkspace` then `genIntellijRuns`
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
- Select the "Minecraft Client" launch config
- In `Edit Configurations...` you may need to select `baritone_launch` for `Use classpath of module:`.
# Chat control
[Defined Here](src/main/java/baritone/utils/ExampleBaritoneControl.java)
@@ -47,7 +61,7 @@ Quick start example: `thisway 1000` or `goal 70` to set the goal, `path` to actu
```
BaritoneAPI.getSettings().allowSprint.value = true;
BaritoneAPI.getSettings().primaryTimeoutMS.value = 2000L;
BaritoneAPI.getSettings().pathTimeoutMS.value = 2000L;
BaritoneAPI.getProvider().getPrimaryBaritone().getCustomGoalProcess().setGoalAndPath(new GoalXZ(10000, 20000));
```
-79
View File
@@ -1,79 +0,0 @@
# Setup
- Clone or download Baritone
![Image](https://i.imgur.com/kbqBtoN.png)
- If you choose to download, make sure you extract the ZIP archive.
- Follow one of the instruction sets below, based on your preference
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
Setting up the Environment:
```
$ gradlew setupDecompWorkspace
$ gradlew --refresh-dependencies
```
Running Baritone:
```
$ gradlew runClient
```
For information on how to build baritone, see [Building Baritone](#building-baritone)
## IntelliJ
- Open the project in IntelliJ as a Gradle project
![Image](https://i.imgur.com/jw7Q6vY.png)
- Run the Gradle tasks `setupDecompWorkspace` then `genIntellijRuns`
![Image](https://i.imgur.com/QEfVvWP.png)
- Refresh the Gradle project (or, to be safe, just restart IntelliJ)
![Image](https://i.imgur.com/3V7EdWr.png)
- Select the "Minecraft Client" launch config
![Image](https://i.imgur.com/1qz2QGV.png)
- Click on ``Edit Configurations...`` from the same dropdown and select the "Minecraft Client" config
![Image](https://i.imgur.com/s4ly0ZF.png)
- In `Edit Configurations...` you need to select `baritone_launch` for `Use classpath of module:`.
![Image](https://i.imgur.com/hrLhG9u.png)
# Building
Make sure that you have properly [setup](#setup) the environment before trying to build it.
## Command Line
```
$ gradlew build
```
## IntelliJ
- Navigate to the gradle tasks on the right tab as follows
![Image](https://i.imgur.com/PE6r9iN.png)
- Right click on **build** and press **Run**
## Artifacts
Building Baritone will result in 3 artifacts created in the ``dist`` directory.
- **API**: Only the non-api packages are obfuscated. This should be used in environments where other mods would like to use Baritone's features.
- **Standalone**: Everything is obfuscated. This should be used in environments where there are no other mods present that would like to use Baritone's features.
- **Unoptimized**: Nothing is obfuscated. This shouldn't be used ever in production.
## More Info
To replace out Impact 4.4's Baritone build with a customized one, switch to the `impact4.4-compat` branch, build Baritone as above then copy `dist/baritone-api-$VERSION$.jar` into `minecraft/libraries/cabaletta/baritone-api/1.0.0/baritone-api-1.0.0.jar`, replacing the jar that was previously there. You also need to edit `minecraft/versions/1.12.2-Impact_4.4/1.12.2-Impact_4.4.json`, find the line `"name": "cabaletta:baritone-api:1.0.0"`, remove the comma from the end, and entirely remove the line that's immediately after (starts with `"url"`).
+2 -6
View File
@@ -48,7 +48,6 @@ apply plugin: 'org.spongepowered.mixin'
sourceCompatibility = targetCompatibility = '1.8'
compileJava {
sourceCompatibility = targetCompatibility = '1.8'
options.encoding = "UTF-8" // allow emoji in comments :^)
}
sourceSets {
@@ -100,11 +99,8 @@ mixin {
}
javadoc {
options.addStringOption('Xwerror', '-quiet') // makes the build fail on travis when there is a javadoc error
options.linkSource true
options.encoding "UTF-8" // allow emoji in comments :^)
source += sourceSets.api.allJava
classpath += sourceSets.api.compileClasspath
source = sourceSets.api.allJava
classpath = sourceSets.api.compileClasspath
}
jar {
@@ -208,7 +208,7 @@ public class ProguardTask extends BaritoneGradleTask {
Objects.requireNonNull(extension);
// for some reason cant use Class.forName
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass();
Field f_replacer = class_baseExtension.getDeclaredField("replacer");
f_replacer.setAccessible(true);
Object replacer = f_replacer.get(extension);
@@ -26,4 +26,4 @@ public enum MappingType {
SEARGE,
NOTCH,
CUSTOM // forgegradle
}
}
@@ -60,4 +60,4 @@ public class ReobfWrapper {
throw new IllegalStateException(ex);
}
}
}
}
-3
View File
@@ -21,7 +21,6 @@ import baritone.api.behavior.ILookBehavior;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.cache.IWorldProvider;
import baritone.api.event.listener.IEventBus;
import baritone.api.pathing.calc.IPathingControlManager;
import baritone.api.process.ICustomGoalProcess;
import baritone.api.process.IFollowProcess;
import baritone.api.process.IGetToBlockProcess;
@@ -65,8 +64,6 @@ public interface IBaritone {
*/
IWorldProvider getWorldProvider();
IPathingControlManager getPathingControlManager();
IInputOverrideHandler getInputOverrideHandler();
ICustomGoalProcess getCustomGoalProcess();
+111 -134
View File
@@ -33,67 +33,57 @@ import java.util.function.Consumer;
*
* @author leijurv
*/
public final class Settings {
public class Settings {
/**
* Allow Baritone to break blocks
*/
public final Setting<Boolean> allowBreak = new Setting<>(true);
public Setting<Boolean> allowBreak = new Setting<>(true);
/**
* Allow Baritone to sprint
*/
public final Setting<Boolean> allowSprint = new Setting<>(true);
public Setting<Boolean> allowSprint = new Setting<>(true);
/**
* Allow Baritone to place blocks
*/
public final Setting<Boolean> allowPlace = new Setting<>(true);
public Setting<Boolean> allowPlace = new Setting<>(true);
/**
* Allow Baritone to move items in your inventory to your hotbar
*/
public final Setting<Boolean> allowInventory = new Setting<>(false);
public Setting<Boolean> allowInventory = new Setting<>(false);
/**
* It doesn't actually take twenty ticks to place a block, this cost is so high
* because we want to generally conserve blocks which might be limited
*/
public final Setting<Double> blockPlacementPenalty = new Setting<>(20D);
public Setting<Double> blockPlacementPenalty = new Setting<>(20D);
/**
* This is just a tiebreaker to make it less likely to break blocks if it can avoid it.
* For example, fire has a break cost of 0, this makes it nonzero, so all else being equal
* it will take an otherwise equivalent route that doesn't require it to put out fire.
*/
public final Setting<Double> blockBreakAdditionalPenalty = new Setting<>(2D);
/**
* Additional penalty for hitting the space bar (ascend, pillar, or parkour) because it uses hunger
*/
public final Setting<Double> jumpPenalty = new Setting<>(2D);
/**
* Walking on water uses up hunger really quick, so penalize it
*/
public final Setting<Double> walkOnWaterOnePenalty = new Setting<>(5D);
public Setting<Double> blockBreakAdditionalPenalty = new Setting<>(2D);
/**
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
* Reliability: questionable.
*/
public final Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
public Setting<Boolean> allowWaterBucketFall = new Setting<>(true);
/**
* Allow Baritone to assume it can walk on still water just like any other block.
* This functionality is assumed to be provided by a separate library that might have imported Baritone.
*/
public final Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
public Setting<Boolean> assumeWalkOnWater = new Setting<>(false);
/**
* Assume step functionality; don't jump on an Ascend.
*/
public final Setting<Boolean> assumeStep = new Setting<>(false);
public Setting<Boolean> assumeStep = new Setting<>(false);
/**
* Assume safe walk functionality; don't sneak on a backplace traverse.
@@ -102,28 +92,19 @@ public final class Settings {
* it won't sneak right click, it'll just right click, which means it'll open the chest instead of placing
* against it. That's why this defaults to off.
*/
public final Setting<Boolean> assumeSafeWalk = new Setting<>(false);
public Setting<Boolean> assumeSafeWalk = new Setting<>(false);
/**
* If true, parkour is allowed to make jumps when standing on blocks at the maximum height, so player feet is y=256
* <p>
* Defaults to false because this fails on constantiam
* Defaults to false because this fails on NCP
*/
public final Setting<Boolean> allowJumpAt256 = new Setting<>(false);
/**
* Allow descending diagonally
* <p>
* Safer than allowParkour yet still slightly unsafe, can make contact with unchecked adjacent blocks, so it's unsafe in the nether.
* <p>
* For a generic "take some risks" mode I'd turn on this one, parkour, and parkour place.
*/
public final Setting<Boolean> allowDiagonalDescend = new Setting<>(false);
public Setting<Boolean> allowJumpAt256 = new Setting<>(false);
/**
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
*/
public final Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
public Setting<List<Item>> acceptableThrowawayItems = new Setting<>(new ArrayList<>(Arrays.asList(
Item.getItemFromBlock(Blocks.DIRT),
Item.getItemFromBlock(Blocks.COBBLESTONE),
Item.getItemFromBlock(Blocks.NETHERRACK)
@@ -132,37 +113,31 @@ public final class Settings {
/**
* 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>
* Never turn this on lol
*/
public final Setting<Boolean> allowVines = new Setting<>(false);
public Setting<Boolean> allowVines = new Setting<>(false);
/**
* Slab behavior is complicated, disable this for higher path reliability. Leave enabled if you have bottom slabs
* everywhere in your base.
*/
public final Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
public Setting<Boolean> allowWalkOnBottomSlab = new Setting<>(true);
/**
* You know what it is
* <p>
* But it's very unreliable and falls off when cornering like all the time so.
* <p>
* It also overshoots the landing pretty much always (making contact with the next block over), so be careful
*/
public final Setting<Boolean> allowParkour = new Setting<>(false);
public Setting<Boolean> allowParkour = new Setting<>(false);
/**
* Actually pretty reliable.
* <p>
* Doesn't make it any more dangerous compared to just normal allowParkour th
* Like parkour, but even more unreliable!
*/
public final Setting<Boolean> allowParkourPlace = new Setting<>(false);
public Setting<Boolean> allowParkourPlace = new Setting<>(false);
/**
* For example, if you have Mining Fatigue or Haste, adjust the costs of breaking blocks accordingly.
*/
public final Setting<Boolean> considerPotionEffects = new Setting<>(true);
public Setting<Boolean> considerPotionEffects = new Setting<>(true);
/**
* This is the big A* setting.
@@ -178,138 +153,134 @@ public final class Settings {
* metric gets better and better with each block, instead of slightly worse.
* <p>
* Finding the optimal path is worth it, so it's the default.
* <p>
* This value is an expression instead of a literal so that it's exactly equal to SPRINT_ONE_BLOCK_COST defined in ActionCosts.java
*/
public final Setting<Double> costHeuristic = new Setting<>(3.563);
public Setting<Double> costHeuristic = new Setting<>(20 / 5.612);
// a bunch of obscure internal A* settings that you probably don't want to change
/**
* The maximum number of times it will fetch outside loaded or cached chunks before assuming that
* pathing has reached the end of the known area, and should therefore stop.
*/
public final Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
public Setting<Integer> pathingMaxChunkBorderFetch = new Setting<>(50);
/**
* Set to 1.0 to effectively disable this feature
*
* @see <a href="https://github.com/cabaletta/baritone/issues/18">Issue #18</a>
*/
public final Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.5);
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.5);
/**
* Toggle the following 4 settings
* <p>
* They have a noticeable performance impact, so they default off
* <p>
* Specifically, building up the avoidance map on the main thread before pathing starts actually takes a noticeable
* amount of time, especially when there are a lot of mobs around, and your game jitters for like 200ms while doing so
* They have a noticable performance impact, so they default off
*/
public final Setting<Boolean> avoidance = new Setting<>(false);
public Setting<Boolean> avoidance = new Setting<>(false);
/**
* Set to 1.0 to effectively disable this feature
* <p>
* Set below 1.0 to go out of your way to walk near mob spawners
*/
public final Setting<Double> mobSpawnerAvoidanceCoefficient = new Setting<>(2.0);
public Setting<Double> mobSpawnerAvoidanceCoefficient = new Setting<>(2.0);
public final Setting<Integer> mobSpawnerAvoidanceRadius = new Setting<>(16);
public Setting<Integer> mobSpawnerAvoidanceRadius = new Setting<>(16);
/**
* Set to 1.0 to effectively disable this feature
* <p>
* Set below 1.0 to go out of your way to walk near mobs
*/
public final Setting<Double> mobAvoidanceCoefficient = new Setting<>(1.5);
public Setting<Double> mobAvoidanceCoefficient = new Setting<>(1.5);
public final Setting<Integer> mobAvoidanceRadius = new Setting<>(8);
public Setting<Integer> mobAvoidanceRadius = new Setting<>(8);
/**
* When running a goto towards a container block (chest, ender chest, furnace, etc),
* right click and open it once you arrive.
*/
public final Setting<Boolean> rightClickContainerOnArrival = new Setting<>(true);
public Setting<Boolean> rightClickContainerOnArrival = new Setting<>(true);
/**
* When running a goto towards a nether portal block, walk all the way into the portal
* instead of stopping one block before.
*/
public final Setting<Boolean> enterPortal = new Setting<>(true);
public Setting<Boolean> enterPortal = new Setting<>(true);
/**
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
* and there's no point.
*/
public final Setting<Boolean> minimumImprovementRepropagation = new Setting<>(true);
public Setting<Boolean> minimumImprovementRepropagation = new Setting<>(true);
/**
* After calculating a path (potentially through cached chunks), artificially cut it off to just the part that is
* entirely within currently loaded chunks. Improves path safety because cached chunks are heavily simplified.
* <p>
* This is much safer to leave off now, and makes pathing more efficient. More explanation in the issue.
*
* @see <a href="https://github.com/cabaletta/baritone/issues/114">Issue #114</a>
* @see <a href="https://github.com/cabaletta/baritone/issues/144">Issue #144</a>
*/
public final Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(false);
public Setting<Boolean> cutoffAtLoadBoundary = new Setting<>(false);
/**
* If a movement's cost increases by more than this amount between calculation and execution (due to changes
* in the environment / world), cancel and recalculate
*/
public final Setting<Double> maxCostIncrease = new Setting<>(10D);
public Setting<Double> maxCostIncrease = new Setting<>(10D);
/**
* Stop 5 movements before anything that made the path COST_INF.
* For example, if lava has spread across the path, don't walk right up to it then recalculate, it might
* still be spreading lol
*/
public final Setting<Integer> costVerificationLookahead = new Setting<>(5);
public Setting<Integer> costVerificationLookahead = new Setting<>(5);
/**
* Static cutoff factor. 0.9 means cut off the last 10% of all paths, regardless of chunk load state
*/
public final Setting<Double> pathCutoffFactor = new Setting<>(0.9);
public Setting<Double> pathCutoffFactor = new Setting<>(0.9);
/**
* Only apply static cutoff for paths of at least this length (in terms of number of movements)
*/
public final Setting<Integer> pathCutoffMinimumLength = new Setting<>(30);
public Setting<Integer> pathCutoffMinimumLength = new Setting<>(30);
/**
* Start planning the next path once the remaining movements tick estimates sum up to less than this value
*/
public final Setting<Integer> planningTickLookAhead = new Setting<>(150);
public Setting<Integer> planningTickLookAhead = new Setting<>(150);
/**
* Default size of the Long2ObjectOpenHashMap used in pathing
*/
public final Setting<Integer> pathingMapDefaultSize = new Setting<>(1024);
public Setting<Integer> pathingMapDefaultSize = new Setting<>(1024);
/**
* Load factor coefficient for the Long2ObjectOpenHashMap used in pathing
* <p>
* Decrease for faster map operations, but higher memory usage
*/
public final Setting<Float> pathingMapLoadFactor = new Setting<>(0.75f);
public Setting<Float> pathingMapLoadFactor = new Setting<>(0.75f);
/**
* How far are you allowed to fall onto solid ground (without a water bucket)?
* 3 won't deal any damage. But if you just want to get down the mountain quickly and you have
* Feather Falling IV, you might set it a bit higher, like 4 or 5.
*/
public final Setting<Integer> maxFallHeightNoWater = new Setting<>(3);
public Setting<Integer> maxFallHeightNoWater = new Setting<>(3);
/**
* How far are you allowed to fall onto solid ground (with a water bucket)?
* It's not that reliable, so I've set it below what would kill an unarmored player (23)
*/
public final Setting<Integer> maxFallHeightBucket = new Setting<>(20);
public Setting<Integer> maxFallHeightBucket = new Setting<>(20);
/**
* Is it okay to sprint through a descend followed by a diagonal?
* The player overshoots the landing, but not enough to fall off. And the diagonal ensures that there isn't
* lava or anything that's !canWalkInto in that space, so it's technically safe, just a little sketchy.
*/
public final Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
public Setting<Boolean> allowOvershootDiagonalDescend = new Setting<>(true);
/**
* If your goal is a GoalBlock in an unloaded chunk, assume it's far enough away that the Y coord
@@ -318,133 +289,131 @@ public final class Settings {
* of considering the Y coord. The reasoning is that if your X and Z are 10,000 blocks away,
* your Y coordinate's accuracy doesn't matter at all until you get much much closer.
*/
public final Setting<Boolean> simplifyUnloadedYCoord = new Setting<>(true);
public Setting<Boolean> simplifyUnloadedYCoord = new Setting<>(true);
/**
* If a movement takes this many ticks more than its initial cost estimate, cancel it
*/
public final Setting<Integer> movementTimeoutTicks = new Setting<>(100);
public Setting<Integer> movementTimeoutTicks = new Setting<>(100);
/**
* Pathing ends after this amount of time, but only if a path has been found
* <p>
* If no valid path (length above the minimum) has been found, pathing continues up until the failure timeout
*/
public final Setting<Long> primaryTimeoutMS = new Setting<>(500L);
public Setting<Long> primaryTimeoutMS = new Setting<>(500L);
/**
* Pathing can never take longer than this, even if that means failing to find any path at all
*/
public final Setting<Long> failureTimeoutMS = new Setting<>(2000L);
public Setting<Long> failureTimeoutMS = new Setting<>(2000L);
/**
* Planning ahead while executing a segment ends after this amount of time, but only if a path has been found
* <p>
* If no valid path (length above the minimum) has been found, pathing continues up until the failure timeout
*/
public final Setting<Long> planAheadPrimaryTimeoutMS = new Setting<>(4000L);
public Setting<Long> planAheadPrimaryTimeoutMS = new Setting<>(4000L);
/**
* Planning ahead while executing a segment can never take longer than this, even if that means failing to find any path at all
*/
public final Setting<Long> planAheadFailureTimeoutMS = new Setting<>(5000L);
public Setting<Long> planAheadFailureTimeoutMS = new Setting<>(5000L);
/**
* For debugging, consider nodes much much slower
*/
public final Setting<Boolean> slowPath = new Setting<>(false);
public Setting<Boolean> slowPath = new Setting<>(false);
/**
* Milliseconds between each node
*/
public final Setting<Long> slowPathTimeDelayMS = new Setting<>(100L);
public Setting<Long> slowPathTimeDelayMS = new Setting<>(100L);
/**
* The alternative timeout number when slowPath is on
*/
public final Setting<Long> slowPathTimeoutMS = new Setting<>(40000L);
public Setting<Long> slowPathTimeoutMS = new Setting<>(40000L);
/**
* The big one. Download all chunks in simplified 2-bit format and save them for better very-long-distance pathing.
*/
public final Setting<Boolean> chunkCaching = new Setting<>(true);
public Setting<Boolean> chunkCaching = new Setting<>(true);
/**
* On save, delete from RAM any cached regions that are more than 1024 blocks away from the player
* <p>
* Temporarily disabled
*
* @see <a href="https://github.com/cabaletta/baritone/issues/248">Issue #248</a>
* Temporarily disabled, see issue #248
*/
public final Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
public Setting<Boolean> pruneRegionsFromRAM = new Setting<>(false);
/**
* Print all the debug messages to chat
*/
public final Setting<Boolean> chatDebug = new Setting<>(true);
public Setting<Boolean> chatDebug = new Setting<>(true);
/**
* Allow chat based control of Baritone. Most likely should be disabled when Baritone is imported for use in
* something else
*/
public final Setting<Boolean> chatControl = new Setting<>(true);
public Setting<Boolean> chatControl = new Setting<>(true);
/**
* A second override over chatControl to force it on
*/
public final Setting<Boolean> removePrefix = new Setting<>(false);
public Setting<Boolean> removePrefix = new Setting<>(false);
/**
* Render the path
*/
public final Setting<Boolean> renderPath = new Setting<>(true);
public Setting<Boolean> renderPath = new Setting<>(true);
/**
* Render the goal
*/
public final Setting<Boolean> renderGoal = new Setting<>(true);
public Setting<Boolean> renderGoal = new Setting<>(true);
/**
* Ignore depth when rendering the goal
*/
public final Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(true);
public Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(true);
/**
* Renders X/Z type Goals with the vanilla beacon beam effect. Combining this with
* {@link #renderGoalIgnoreDepth} will cause strange render clipping.
*/
public final Setting<Boolean> renderGoalXZBeacon = new Setting<>(false);
public Setting<Boolean> renderGoalXZBeacon = new Setting<>(false);
/**
* Ignore depth when rendering the selection boxes (to break, to place, to walk into)
*/
public final Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(true);
public Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(true);
/**
* Ignore depth when rendering the path
*/
public final Setting<Boolean> renderPathIgnoreDepth = new Setting<>(true);
public Setting<Boolean> renderPathIgnoreDepth = new Setting<>(true);
/**
* Line width of the path when rendered, in pixels
*/
public final Setting<Float> pathRenderLineWidthPixels = new Setting<>(5F);
public Setting<Float> pathRenderLineWidthPixels = new Setting<>(5F);
/**
* Line width of the goal when rendered, in pixels
*/
public final Setting<Float> goalRenderLineWidthPixels = new Setting<>(3F);
public Setting<Float> goalRenderLineWidthPixels = new Setting<>(3F);
/**
* Start fading out the path at 20 movements ahead, and stop rendering it entirely 30 movements ahead.
* Improves FPS.
*/
public final Setting<Boolean> fadePath = new Setting<>(false);
public Setting<Boolean> fadePath = new Setting<>(false);
/**
* Move without having to force the client-sided rotations
*/
public final Setting<Boolean> freeLook = new Setting<>(true);
public Setting<Boolean> freeLook = new Setting<>(true);
/**
* Will cause some minor behavioral differences to ensure that Baritone works on anticheats.
@@ -452,43 +421,52 @@ public final class Settings {
* At the moment this will silently set the player's rotations when using freeLook so you're not sprinting in
* directions other than forward, which is picken up by more "advanced" anticheats like AAC, but not NCP.
*/
public final Setting<Boolean> antiCheatCompatibility = new Setting<>(true);
public Setting<Boolean> antiCheatCompatibility = new Setting<>(true);
/**
* Exclusively use cached chunks for pathing
*/
public final Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
public Setting<Boolean> pathThroughCachedOnly = new Setting<>(false);
/**
* Whether or not to use the "#" command prefix
*/
public final Setting<Boolean> prefix = new Setting<>(false);
public Setting<Boolean> prefix = new Setting<>(false);
/**
* {@code true}: can mine blocks when in inventory, chat, or tabbed away in ESC menu
* <p>
* {@code false}: works on cosmic prisons
* <p>
* LOL
*/
public Setting<Boolean> leftClickWorkaround = new Setting<>(true);
/**
* Don't stop walking forward when you need to break blocks in your way
*/
public final Setting<Boolean> walkWhileBreaking = new Setting<>(true);
public Setting<Boolean> walkWhileBreaking = new Setting<>(true);
/**
* If we are more than 300 movements into the current path, discard the oldest segments, as they are no longer useful
* If we are more than 500 movements into the current path, discard the oldest segments, as they are no longer useful
*/
public final Setting<Integer> maxPathHistoryLength = new Setting<>(300);
public Setting<Integer> maxPathHistoryLength = new Setting<>(300);
/**
* If the current path is too long, cut off this many movements from the beginning.
*/
public final Setting<Integer> pathHistoryCutoffAmount = new Setting<>(50);
public Setting<Integer> pathHistoryCutoffAmount = new Setting<>(50);
/**
* Rescan for the goal once every 5 ticks.
* Set to 0 to disable.
*/
public final Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
public Setting<Integer> mineGoalUpdateInterval = new Setting<>(5);
/**
* 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);
public Setting<Boolean> mineScanDroppedItems = new Setting<>(true);
/**
* Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore.
@@ -503,54 +481,54 @@ public final class Settings {
* <p>
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
*/
public final Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
/**
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
*/
public final Setting<Integer> axisHeight = new Setting<>(120);
public Setting<Integer> axisHeight = new Setting<>(120);
/**
* Disallow MineBehavior from using X-Ray to see where the ores are. Turn this option on to force it to mine "legit"
* Allow MineBehavior to use X-Ray to see where the ores are. Turn this option off to force it to mine "legit"
* where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player
* couldn't. If you don't want it to look like you're X-Raying, turn this on
* couldn't. If you don't want it to look like you're X-Raying, turn this off
*/
public final Setting<Boolean> legitMine = new Setting<>(false);
public Setting<Boolean> legitMine = new Setting<>(false);
/**
* What Y level to go to for legit strip mining
*/
public final Setting<Integer> legitMineYLevel = new Setting<>(11);
public Setting<Integer> legitMineYLevel = new Setting<>(11);
/**
* When mining block of a certain type, try to mine two at once instead of one.
* If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks
* If the block below is also a goal block, set GoalBlock to the position one down instead of GoalTwoBlocks
*/
public final Setting<Boolean> forceInternalMining = new Setting<>(true);
public Setting<Boolean> forceInternalMining = new Setting<>(true);
/**
* Modification to the previous setting, only has effect if forceInternalMining is true
* If true, only apply the previous setting if the block adjacent to the goal isn't air.
*/
public final Setting<Boolean> internalMiningAirException = new Setting<>(true);
public Setting<Boolean> internalMiningAirException = new Setting<>(true);
/**
* The actual GoalNear is set this distance away from the entity you're following
* <p>
* For example, set followOffsetDistance to 5 and followRadius to 0 to always stay precisely 5 blocks north of your follow target.
*/
public final Setting<Double> followOffsetDistance = new Setting<>(0D);
public Setting<Double> followOffsetDistance = new Setting<>(0D);
/**
* The actual GoalNear is set in this direction from the entity you're following. This value is in degrees.
* The actual GoalNear is set in this direction from the entity you're following
*/
public final Setting<Float> followOffsetDirection = new Setting<>(0F);
public Setting<Float> followOffsetDirection = new Setting<>(0F);
/**
* The radius (for the GoalNear) of how close to your target position you actually have to be
*/
public final Setting<Integer> followRadius = new Setting<>(3);
public Setting<Integer> followRadius = new Setting<>(3);
/**
* Cached chunks (regardless of if they're in RAM or saved to disk) expire and are deleted after this number of seconds
@@ -572,55 +550,54 @@ public final class Settings {
* has to build up that cache from scratch. But after it's gone through an area just once, the next time will have zero
* backtracking, since the entire area is now known and cached.
*/
public final Setting<Long> cachedChunksExpirySeconds = new Setting<>(-1L);
public Setting<Long> cachedChunksExpirySeconds = new Setting<>(-1L);
/**
* The function that is called when Baritone will log to chat. This function can be added to
* 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);
public Setting<Consumer<ITextComponent>> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage);
/**
* The color of the current path
*/
public final Setting<Color> colorCurrentPath = new Setting<>(Color.RED);
public Setting<Color> colorCurrentPath = new Setting<>(Color.RED);
/**
* The color of the next path
*/
public final Setting<Color> colorNextPath = new Setting<>(Color.MAGENTA);
public Setting<Color> colorNextPath = new Setting<>(Color.MAGENTA);
/**
* The color of the blocks to break
*/
public final Setting<Color> colorBlocksToBreak = new Setting<>(Color.RED);
public Setting<Color> colorBlocksToBreak = new Setting<>(Color.RED);
/**
* The color of the blocks to place
*/
public final Setting<Color> colorBlocksToPlace = new Setting<>(Color.GREEN);
public Setting<Color> colorBlocksToPlace = new Setting<>(Color.GREEN);
/**
* The color of the blocks to walk into
*/
public final Setting<Color> colorBlocksToWalkInto = new Setting<>(Color.MAGENTA);
public Setting<Color> colorBlocksToWalkInto = new Setting<>(Color.MAGENTA);
/**
* The color of the best path so far
*/
public final Setting<Color> colorBestPathSoFar = new Setting<>(Color.BLUE);
public Setting<Color> colorBestPathSoFar = new Setting<>(Color.BLUE);
/**
* The color of the path to the most recent considered node
*/
public final Setting<Color> colorMostRecentConsidered = new Setting<>(Color.CYAN);
public Setting<Color> colorMostRecentConsidered = new Setting<>(Color.CYAN);
/**
* The color of the goal box
*/
public final Setting<Color> colorGoalBox = new Setting<>(Color.GREEN);
public Setting<Color> colorGoalBox = new Setting<>(Color.GREEN);
/**
* A map of lowercase setting field names to their respective setting
@@ -37,13 +37,7 @@ public interface IPathingBehavior extends IBehavior {
*
* @return The estimated remaining ticks in the current segment.
*/
default Optional<Double> ticksRemainingInSegment() {
IPathExecutor current = getCurrent();
if (current == null) {
return Optional.empty();
}
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
}
Optional<Double> ticksRemainingInSegment();
/**
* @return The current pathing goal
@@ -53,9 +47,7 @@ public interface IPathingBehavior extends IBehavior {
/**
* @return Whether or not a path is currently being executed.
*/
default boolean isPathing() {
return getCurrent() != null;
}
boolean isPathing();
/**
* Cancels the pathing behavior or the current path calculation, and all processes that could be controlling path.
@@ -17,20 +17,22 @@
package baritone.api.event.events;
import baritone.api.event.events.type.Cancellable;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* @author Brady
* @since 8/1/2018
*/
public final class ChatEvent extends Cancellable {
public final class ChatEvent extends ManagedPlayerEvent.Cancellable {
/**
* The message being sent
*/
private final String message;
public ChatEvent(String message) {
public ChatEvent(EntityPlayerSP player, String message) {
super(player);
this.message = message;
}
@@ -18,19 +18,22 @@
package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* @author Brady
* @since 8/21/2018
*/
public final class PlayerUpdateEvent {
public final class PlayerUpdateEvent extends ManagedPlayerEvent {
/**
* The state of the event
*/
private final EventState state;
public PlayerUpdateEvent(EventState state) {
public PlayerUpdateEvent(EntityPlayerSP player, EventState state) {
super(player);
this.state = state;
}
@@ -17,6 +17,8 @@
package baritone.api.event.events;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -24,7 +26,7 @@ import net.minecraft.entity.EntityLivingBase;
* @author Brady
* @since 8/21/2018
*/
public final class RotationMoveEvent {
public final class RotationMoveEvent extends ManagedPlayerEvent {
/**
* The type of event
@@ -36,7 +38,8 @@ public final class RotationMoveEvent {
*/
private float yaw;
public RotationMoveEvent(Type type, float yaw) {
public RotationMoveEvent(EntityPlayerSP player, Type type, float yaw) {
super(player);
this.type = type;
this.yaw = yaw;
}
@@ -0,0 +1,61 @@
/*
* 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.event.events.type;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* An event that has a reference to a locally managed player.
*
* @author Brady
* @since 10/11/2018
*/
public class ManagedPlayerEvent {
protected final EntityPlayerSP player;
public ManagedPlayerEvent(EntityPlayerSP player) {
this.player = player;
}
public final EntityPlayerSP getPlayer() {
return this.player;
}
public static class Cancellable extends ManagedPlayerEvent implements ICancellable {
/**
* Whether or not this event has been cancelled
*/
private boolean cancelled;
public Cancellable(EntityPlayerSP player) {
super(player);
}
@Override
public final void cancel() {
this.cancelled = true;
}
@Override
public final boolean isCancelled() {
return this.cancelled;
}
}
}
@@ -36,6 +36,9 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override
default void onPlayerUpdate(PlayerUpdateEvent event) {}
@Override
default void onProcessKeyBinds() {}
@Override
default void onSendChatMessage(ChatEvent event) {}
@@ -57,9 +60,6 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override
default void onPlayerRotationMove(RotationMoveEvent event) {}
@Override
default void onPlayerSprintState(SprintStateEvent event) {}
@Override
default void onBlockInteract(BlockInteractEvent event) {}
@@ -49,6 +49,11 @@ public interface IGameEventListener {
*/
void onPlayerUpdate(PlayerUpdateEvent event);
/**
* Run once per game tick from before keybinds are processed.
*/
void onProcessKeyBinds();
/**
* Runs whenever the client player sends a message to the server.
*
@@ -109,14 +114,6 @@ public interface IGameEventListener {
*/
void onPlayerRotationMove(RotationMoveEvent event);
/**
* Called whenever the sprint keybind state is checked in {@link EntityPlayerSP#onLivingUpdate}
*
* @param event The event
* @see EntityPlayerSP#onLivingUpdate()
*/
void onPlayerSprintState(SprintStateEvent event);
/**
* Called when the local player interacts with a block, whether it is breaking or opening/placing.
*
@@ -36,6 +36,7 @@ public interface IPathFinder {
*
* @param primaryTimeout If a path is found, the path finder will stop after this amount of time
* @param failureTimeout If a path isn't found, the path finder will continue for this amount of time
*
* @return The final path
*/
PathCalculationResult calculate(long primaryTimeout, long failureTimeout);
@@ -22,26 +22,10 @@ import baritone.api.process.PathingCommand;
import java.util.Optional;
/**
* @author leijurv
*/
public interface IPathingControlManager {
/**
* Registers a process with this pathing control manager. See {@link IBaritoneProcess} for more details.
*
* @param process The process
* @see IBaritoneProcess
*/
void registerProcess(IBaritoneProcess process);
/**
* @return The most recent {@link IBaritoneProcess} that had control
*/
Optional<IBaritoneProcess> mostRecentInControl();
/**
* @return The most recent pathing command executed
*/
Optional<PathingCommand> mostRecentCommand();
}
@@ -33,6 +33,7 @@ public interface Goal {
* @param x The goal X position
* @param y The goal Y position
* @param z The goal Z position
*
* @return Whether or not it satisfies this goal
*/
boolean isInGoal(int x, int y, int z);
@@ -43,6 +44,7 @@ public interface Goal {
* @param x The goal X position
* @param y The goal Y position
* @param z The goal Z position
*
* @return The estimate number of ticks to satisfy the goal
*/
double heuristic(int x, int y, int z);
@@ -26,6 +26,4 @@ import baritone.api.pathing.calc.IPath;
public interface IPathExecutor {
IPath getPath();
int getPosition();
}
@@ -17,6 +17,7 @@
package baritone.api.process;
import baritone.api.IBaritone;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.PathEvent;
@@ -24,10 +25,8 @@ import baritone.api.event.events.PathEvent;
* A process that can control the PathingBehavior.
* <p>
* Differences between a baritone process and a behavior:
* <ul>
* <li>Only one baritone process can be active at a time</li>
* <li>PathingBehavior can only be controlled by a process</li>
* </ul>
* Only one baritone process can be active at a time
* PathingBehavior can only be controlled by a process
* <p>
* That's it actually
*
@@ -84,6 +83,13 @@ public interface IBaritoneProcess {
*/
double priority();
/**
* Returns which bot this process is associated with. (5000000iq forward thinking)
*
* @return The Bot associated with this process
*/
IBaritone associatedWith();
/**
* Returns a user-friendly name for this process. Suitable for a HUD.
*
@@ -27,7 +27,9 @@ import net.minecraft.client.settings.KeyBinding;
*/
public interface IInputOverrideHandler extends IBehavior {
Boolean isInputForcedDown(KeyBinding key);
default boolean isInputForcedDown(KeyBinding key) {
return isInputForcedDown(Input.getInputForBind(key));
}
boolean isInputForcedDown(Input input);
@@ -20,6 +20,7 @@ package baritone.api.utils;
import baritone.api.cache.IWorldData;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
@@ -36,7 +37,7 @@ public interface IPlayerContext {
EntityPlayerSP player();
IPlayerController playerController();
PlayerControllerMP playerController();
World world();
@@ -1,46 +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.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType;
/**
* @author Brady
* @since 12/14/2018
*/
public interface IPlayerController {
boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side);
void resetBlockRemoving();
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player);
void setGameType(GameType type);
GameType getGameType();
default double getBlockReachDistance() {
return this.getGameType().isCreative() ? 5.0F : 4.5F;
}
}
@@ -15,21 +15,13 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.event.events;
package baritone.api.utils;
/**
* @author Brady
* @since 1/18/2019
* @since 9/23/2018
*/
public final class SprintStateEvent {
public class Logger {
private Boolean state;
public final void setState(boolean state) {
this.state = state;
}
public final Boolean getState() {
return this.state;
}
}
@@ -19,7 +19,6 @@ package baritone.api.utils;
import baritone.api.pathing.calc.IPath;
import java.util.Objects;
import java.util.Optional;
public class PathCalculationResult {
@@ -32,9 +31,11 @@ public class PathCalculationResult {
}
public PathCalculationResult(Type type, IPath path) {
Objects.requireNonNull(type);
this.path = path;
this.type = type;
if (type == null) {
throw new IllegalArgumentException("come on");
}
}
public final Optional<IPath> getPath() {
@@ -127,16 +127,6 @@ public final class RotationUtils {
return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2));
}
/**
* @param ctx Context for the viewing entity
* @param pos The target block position
* @return The optional rotation
* @see #reachable(EntityPlayerSP, BlockPos, double)
*/
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos) {
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
}
/**
* Determines if the specified entity is able to reach the center of any of the sides
* of the specified block. It first checks if the block center is reachable, and if so,
@@ -18,77 +18,56 @@
package baritone.api.utils;
import baritone.api.Settings;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import java.awt.*;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import java.util.stream.Stream;
import static net.minecraft.client.Minecraft.getMinecraft;
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>[^ ]+)"); // 2 words separated by spaces
private static final File settingsFile = new File(new File(Minecraft.getMinecraft().gameDir, "baritone"), "settings.txt");
private static final Map<Class<?>, SettingsIO> map;
private static boolean isComment(String line) {
return line.startsWith("#") || line.startsWith("//");
}
private static void forEachLine(Path file, Consumer<String> consumer) throws IOException {
try (BufferedReader scan = Files.newBufferedReader(file)) {
String line;
while ((line = scan.readLine()) != null) {
if (line.isEmpty() || isComment(line)) {
public static void readAndApply(Settings settings) {
try (Scanner scan = new Scanner(settingsFile)) {
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.isEmpty()) {
continue;
}
consumer.accept(line);
}
}
}
public static void readAndApply(Settings settings) {
try {
forEachLine(SETTINGS_PATH, line -> {
Matcher matcher = SETTING_PATTERN.matcher(line);
if (!matcher.matches()) {
System.out.println("Invalid syntax in setting file: " + line);
return;
if (line.startsWith("#") || line.startsWith("//")) {
continue;
}
String settingName = matcher.group("setting").toLowerCase();
String settingValue = matcher.group("value");
int space = line.indexOf(" ");
if (space == -1) {
System.out.println("Skipping invalid line with no space: " + line);
continue;
}
String settingName = line.substring(0, space).trim().toLowerCase();
String settingValue = line.substring(space).trim();
try {
parseAndApply(settings, settingName, settingValue);
} catch (Exception ex) {
System.out.println("Unable to parse line " + line);
ex.printStackTrace();
System.out.println("Unable to parse line " + line);
}
});
}
} catch (Exception ex) {
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
ex.printStackTrace();
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
}
}
public static synchronized void save(Settings settings) {
try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) {
try (FileOutputStream out = new FileOutputStream(settingsFile)) {
for (Settings.Setting setting : settings.allSettings) {
if (setting.get() == null) {
System.out.println("NULL SETTING?" + setting.getName());
@@ -104,11 +83,11 @@ public class SettingsUtil {
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting + " " + setting.getName());
}
out.write(setting.getName() + " " + io.toString.apply(setting.get()) + "\n");
out.write((setting.getName() + " " + io.toString.apply(setting.get()) + "\n").getBytes());
}
} catch (Exception ex) {
System.out.println("Exception thrown while saving Baritone settings!");
ex.printStackTrace();
System.out.println("Exception while saving Baritone settings!");
}
}
@@ -52,7 +52,7 @@ public class MixinEntity {
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
// noinspection ConstantConditions
if (EntityPlayerSP.class.isInstance(this)) {
this.motionUpdateRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
this.motionUpdateRotationEvent = new RotationMoveEvent((EntityPlayerSP) (Object) this, RotationMoveEvent.Type.MOTION_UPDATE, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.motionUpdateRotationEvent);
}
}
@@ -55,7 +55,7 @@ public abstract class MixinEntityLivingBase extends Entity {
private void preMoveRelative(CallbackInfo ci) {
// noinspection ConstantConditions
if (EntityPlayerSP.class.isInstance(this)) {
this.jumpRotationEvent = new RotationMoveEvent(RotationMoveEvent.Type.JUMP, this.rotationYaw);
this.jumpRotationEvent = new RotationMoveEvent((EntityPlayerSP) (Object) this, RotationMoveEvent.Type.JUMP, this.rotationYaw);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerRotationMove(this.jumpRotationEvent);
}
}
@@ -21,11 +21,8 @@ import baritone.api.BaritoneAPI;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.SprintStateEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.LookBehavior;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.entity.player.PlayerCapabilities;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -46,7 +43,7 @@ public class MixinEntityPlayerSP {
cancellable = true
)
private void sendChatMessage(String msg, CallbackInfo ci) {
ChatEvent event = new ChatEvent(msg);
ChatEvent event = new ChatEvent((EntityPlayerSP) (Object) this, msg);
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onSendChatMessage(event);
if (event.isCancelled()) {
ci.cancel();
@@ -63,7 +60,7 @@ public class MixinEntityPlayerSP {
)
)
private void onPreUpdate(CallbackInfo ci) {
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.PRE));
}
@Inject(
@@ -76,7 +73,7 @@ public class MixinEntityPlayerSP {
)
)
private void onPostUpdate(CallbackInfo ci) {
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.POST));
}
@Redirect(
@@ -90,27 +87,4 @@ public class MixinEntityPlayerSP {
IPathingBehavior pathingBehavior = BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getPathingBehavior();
return !pathingBehavior.isPathing() && capabilities.allowFlying;
}
@Redirect(
method = "onLivingUpdate",
at = @At(
value = "INVOKE",
target = "net/minecraft/client/settings/KeyBinding.isKeyDown()Z"
)
)
private boolean isKeyDown(KeyBinding keyBinding) {
SprintStateEvent event = new SprintStateEvent();
BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getGameEventHandler().onPlayerSprintState(event);
return event.getState() == null ? keyBinding.isKeyDown() : event.getState();
}
@Inject(
method = "updateRidden",
at = @At(
value = "HEAD"
)
)
private void updateRidden(CallbackInfo cb) {
((LookBehavior) BaritoneAPI.getProvider().getBaritoneForPlayer((EntityPlayerSP) (Object) this).getLookBehavior()).pig();
}
}
@@ -18,10 +18,8 @@
package baritone.launch.mixins;
import baritone.api.BaritoneAPI;
import baritone.utils.Helper;
import net.minecraft.client.settings.KeyBinding;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -33,9 +31,6 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(KeyBinding.class)
public class MixinKeyBinding {
@Shadow
private int pressTime;
@Inject(
method = "isKeyDown",
at = @At("HEAD"),
@@ -43,26 +38,8 @@ public class MixinKeyBinding {
)
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null) {
cir.setReturnValue(force); // :sunglasses:
}
}
@Inject(
method = "isPressed",
at = @At("HEAD"),
cancellable = true
)
private void isPressed(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null && !force) { // <-- cursed
if (pressTime > 0) {
Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you");
pressTime--;
}
cir.setReturnValue(force); // :sunglasses:
if (BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) {
cir.setReturnValue(true);
}
}
}
@@ -25,15 +25,18 @@ import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import baritone.utils.BaritoneAutoTest;
import baritone.utils.resource.BaritoneResourcePack;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
import net.minecraft.client.multiplayer.WorldClient;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumActionResult;
import net.minecraft.util.EnumHand;
import net.minecraft.util.math.BlockPos;
import org.spongepowered.asm.lib.Opcodes;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At;
@@ -42,6 +45,8 @@ import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
import java.util.List;
/**
* @author Brady
* @since 7/31/2018
@@ -49,10 +54,9 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow
public EntityPlayerSP player;
@Shadow
public WorldClient world;
@Shadow public EntityPlayerSP player;
@Shadow public WorldClient world;
@Shadow @Final private List<IResourcePack> defaultResourcePacks;
@Inject(
method = "init",
@@ -71,6 +75,7 @@ public class MixinMinecraft {
)
private void preInit(CallbackInfo ci) {
BaritoneAutoTest.INSTANCE.onPreInit();
this.defaultResourcePacks.add(new BaritoneResourcePack());
}
@Inject(
@@ -96,6 +101,15 @@ public class MixinMinecraft {
}
@Inject(
method = "processKeyBinds",
at = @At("HEAD")
)
private void runTickKeyboard(CallbackInfo ci) {
// keyboard input is only the primary baritone
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onProcessKeyBinds();
}
@Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("HEAD")
+10 -1
View File
@@ -35,6 +35,9 @@ import baritone.utils.InputOverrideHandler;
import baritone.utils.PathingControlManager;
import baritone.utils.player.PrimaryPlayerContext;
import net.minecraft.client.Minecraft;
import net.minecraft.client.audio.PositionedSoundRecord;
import net.minecraft.util.ResourceLocation;
import net.minecraft.util.SoundEvent;
import java.io.File;
import java.io.IOException;
@@ -93,11 +96,18 @@ public class Baritone implements IBaritone {
this.gameEventHandler = new GameEventHandler(this);
}
public void fitmc() {
SoundEvent event = new SoundEvent(new ResourceLocation("baritone", "fitmc_intro"));
Minecraft.getMinecraft().getSoundHandler().playSound(PositionedSoundRecord.getMasterRecord(event, 0.8F + (float) Math.random() * 0.4F));
}
public synchronized void init() {
if (initialized) {
return;
}
fitmc();
// Define this before behaviors try and get it, or else it will be null and the builds will fail!
this.playerContext = PrimaryPlayerContext.INSTANCE;
@@ -129,7 +139,6 @@ public class Baritone implements IBaritone {
this.initialized = true;
}
@Override
public PathingControlManager getPathingControlManager() {
return this.pathingControlManager;
}
@@ -55,7 +55,10 @@ public class InventoryBehavior extends Behavior {
}
private void swapWithHotBar(int inInventory, int inHotbar) {
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
if (inInventory < 9) {
inInventory += 36;
}
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory, inHotbar, ClickType.SWAP, ctx.player());
}
private int firstValidThrowaway() { // TODO offhand idk
@@ -78,7 +81,7 @@ public class InventoryBehavior extends Behavior {
continue;
}
if (klass.isInstance(stack.getItem())) {
double speed = ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState()); // takes into account enchants
double speed = ToolSet.calculateStrVsBlock(stack, against.getDefaultState()); // takes into account enchants
if (speed > bestSpeed) {
bestSpeed = speed;
bestInd = i;
@@ -95,12 +95,6 @@ public final class LookBehavior extends Behavior implements ILookBehavior {
}
}
public void pig() {
if (this.target != null) {
ctx.player().rotationYaw = this.target.getYaw();
}
}
@Override
public void onPlayerRotationMove(RotationMoveEvent event) {
if (this.target != null && !this.force) {
@@ -21,7 +21,6 @@ import baritone.Baritone;
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;
@@ -48,8 +47,6 @@ import java.nio.file.Path;
import java.util.*;
/**
* doesn't work for horse inventories :^)
*
* @author Brady
* @since 8/6/2018
*/
@@ -63,14 +60,6 @@ public final class MemoryBehavior extends Behavior {
super(baritone);
}
@Override
public synchronized void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
enderChestWindowId = null;
futureInventories.clear();
}
}
@Override
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE) {
@@ -109,6 +98,7 @@ public final class MemoryBehavior extends Behavior {
}
if (p instanceof CPacketCloseWindow) {
updateInventory();
getCurrent().save();
}
}
@@ -126,10 +116,12 @@ public final class MemoryBehavior extends Behavior {
System.out.println("Received packet " + packet.getGuiId() + " " + packet.getEntityId() + " " + packet.getSlotCount() + " " + packet.getWindowId());
System.out.println(packet.getWindowTitle());
if (packet.getWindowTitle() instanceof TextComponentTranslation && ((TextComponentTranslation) packet.getWindowTitle()).getKey().equals("container.enderchest")) {
if (packet.getWindowTitle() instanceof TextComponentTranslation) {
// title is not customized (i.e. this isn't just a renamed shulker)
enderChestWindowId = packet.getWindowId();
return;
if (((TextComponentTranslation) packet.getWindowTitle()).getKey().equals("container.enderchest")) {
enderChestWindowId = packet.getWindowId();
return;
}
}
futureInventories.stream()
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
@@ -143,6 +135,7 @@ public final class MemoryBehavior extends Behavior {
}
if (p instanceof SPacketCloseWindow) {
updateInventory();
getCurrent().save();
}
}
@@ -184,7 +177,7 @@ public final class MemoryBehavior extends Behavior {
}
private BlockPos neighboringConnectedBlock(BlockPos in) {
BlockStateInterface bsi = new CalculationContext(baritone).bsi;
BlockStateInterface bsi = new CalculationContext(baritone).bsi();
Block block = bsi.get0(in).getBlock();
if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) {
return null; // other things that have contents, but can be placed adjacent without combining
@@ -19,7 +19,10 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IPathingBehavior;
import baritone.api.event.events.*;
import baritone.api.event.events.PathEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ;
@@ -30,11 +33,13 @@ import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.CutoffPath;
import baritone.pathing.path.PathExecutor;
import baritone.utils.Helper;
import baritone.utils.PathRenderer;
import baritone.utils.pathing.Favoring;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList;
import java.util.Comparator;
@@ -93,13 +98,6 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
dispatchEvents();
}
@Override
public void onPlayerSprintState(SprintStateEvent event) {
if (current != null) {
event.setState(current.isSprinting());
}
}
private void tickPath() {
if (pauseRequestedLastTick && safeToCancel) {
pauseRequestedLastTick = false;
@@ -124,7 +122,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
next = null;
return;
}
if (next != null && !next.getPath().positions().contains(ctx.playerFeet()) && !next.getPath().positions().contains(pathStart())) { // can contain either one
if (next != null && !next.getPath().positions().contains(ctx.playerFeet())) {
// if the current path failed, we may not actually be on the next one, so make sure
logDebug("Discarding next path as it does not contain current position");
// for example if we had a nicely planned ahead path that starts where current ends
@@ -140,27 +138,16 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
current = next;
next = null;
current.onTick(); // don't waste a tick doing nothing, get started right away
current.onTick();
return;
}
// at this point, current just ended, but we aren't in the goal and have no plan for the future
synchronized (pathCalcLock) {
if (inProgress != null) {
// we are calculating
// are we calculating the right thing though? 🤔
BetterBlockPos calcFrom = inProgress.getStart();
// if current just succeeded, we should be standing in calcFrom, so that's cool and good
// but if current just failed, we should discard this calculation since it doesn't start from where we're standing
if (calcFrom.equals(ctx.playerFeet()) || calcFrom.equals(pathStart())) {
// cool and good
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
return;
}
// oh noes
inProgress.cancel(); // cancellation doesn't dispatch any events
inProgress = null; // this is safe since we hold both locks
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
// if we aren't calculating right now
return;
}
// we aren't calculating
queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true);
}
@@ -190,11 +177,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return;
}
if (goal == null || goal.isInGoal(current.getPath().getDest())) {
// and this path doesn't get us all the way there
// and this path dosen't get us all the way there
return;
}
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 7.5 seconds or less left
// and this path has 5 seconds or less left
logDebug("Path almost over. Planning ahead...");
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false);
@@ -220,6 +207,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
}
@Override
public Optional<Double> ticksRemainingInSegment() {
if (current == null) {
return Optional.empty();
}
return Optional.of(current.getPath().ticksRemainingFrom(current.getPosition()));
}
public void secretInternalSetGoal(Goal goal) {
this.goal = goal;
}
@@ -249,6 +244,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return Optional.ofNullable(inProgress);
}
@Override
public boolean isPathing() {
return this.current != null;
}
public boolean isSafeToCancel() {
return current == null || safeToCancel;
}
@@ -271,7 +271,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (doIt) {
secretInternalSegmentCancel();
}
baritone.getPathingControlManager().cancelEverything(); // regardless of if we can stop the current segment, we can still stop the processes
baritone.getPathingControlManager().cancelEverything();
return doIt;
}
@@ -307,9 +307,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
public void forceCancel() { // NOT exposed on public api
cancelEverything();
secretInternalSegmentCancel();
synchronized (pathCalcLock) {
inProgress = null;
}
inProgress = null;
}
/**
@@ -432,8 +430,33 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
PathCalculationResult calcResult = pathfinder.calculate(primaryTimeout, failureTimeout);
Optional<IPath> path = calcResult.getPath();
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks(context.bsi());
if (result instanceof CutoffPath) {
logDebug("Cutting off path at edge of loaded chunks");
logDebug("Length decreased by " + (p.length() - result.length()));
} else {
logDebug("Path ends within loaded chunks");
}
return result;
});
}
Optional<PathExecutor> executor = path.map(p -> {
IPath result = p.staticCutoff(goal);
if (result instanceof CutoffPath) {
logDebug("Static cutoff " + p.length() + " to " + result.length());
}
return result;
}).map(p -> new PathExecutor(this, p));
synchronized (pathPlanLock) {
Optional<PathExecutor> executor = calcResult.getPath().map(p -> new PathExecutor(PathingBehavior.this, p));
if (current == null) {
if (executor.isPresent()) {
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
@@ -476,7 +499,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Goal transformed = goal;
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
if (!context.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ())) {
if (context.world().getChunk(pos) instanceof EmptyChunk) {
transformed = new GoalXZ(pos.getX(), pos.getZ());
}
}
+3 -3
View File
@@ -179,8 +179,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() * 512 + 256) - pruneCenter.getX();
int distZ = (region.getZ() * 512 + 256) - pruneCenter.getZ();
double dist = Math.sqrt(distX * distX + distZ * distZ);
if (dist > 1024) {
logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
@@ -215,7 +215,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 * 16 + 8, 0, mostRecentlyModified.z * 16 + 8);
}
private synchronized List<CachedRegion> allRegions() {
+1 -2
View File
@@ -123,8 +123,7 @@ public class ContainerMemory implements IContainerMemory {
return out.array();
}
public static PacketBuffer writeItemStacks(List<ItemStack> write, PacketBuffer out2) {
PacketBuffer out = out2; // avoid reassigning an argument LOL
public static PacketBuffer writeItemStacks(List<ItemStack> write, PacketBuffer out) {
out = new PacketBuffer(out.writeInt(write.size()));
for (ItemStack stack : write) {
out = out.writeItemStack(stack);
+1 -6
View File
@@ -24,7 +24,6 @@ import baritone.utils.accessor.IAnvilChunkLoader;
import baritone.utils.accessor.IChunkProviderServer;
import net.minecraft.server.integrated.IntegratedServer;
import net.minecraft.world.WorldServer;
import org.apache.commons.lang3.SystemUtils;
import java.io.File;
import java.io.FileOutputStream;
@@ -77,11 +76,7 @@ public class WorldProvider implements IWorldProvider, Helper {
directory = new File(directory, "baritone");
readme = directory;
} else { // Otherwise, the server must be remote...
String folderName = mc.getCurrentServerData().serverIP;
if (SystemUtils.IS_OS_WINDOWS) {
folderName = folderName.replace(":", "_");
}
directory = new File(Baritone.getDir(), folderName);
directory = new File(Baritone.getDir(), mc.getCurrentServerData().serverIP);
readme = Baritone.getDir();
}
+35 -16
View File
@@ -28,9 +28,8 @@ import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.LinkedList;
import java.util.List;
public enum WorldScanner implements IWorldScanner {
@@ -42,7 +41,7 @@ public enum WorldScanner implements IWorldScanner {
if (blocks.contains(null)) {
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString());
}
ArrayList<BlockPos> res = new ArrayList<>();
LinkedList<BlockPos> res = new LinkedList<>();
if (blocks.isEmpty()) {
return res;
}
@@ -72,7 +71,33 @@ public enum WorldScanner implements IWorldScanner {
continue;
}
allUnloaded = false;
scanChunkInto(chunkX << 4, chunkZ << 4, chunk, blocks, res, max, yLevelThreshold, playerY);
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
chunkX = chunkX << 4;
chunkZ = chunkZ << 4;
for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) {
continue;
}
int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (blocks.contains(state.getBlock())) {
int yy = yReal | y;
res.add(new BlockPos(chunkX | x, yy, chunkZ | z));
if (Math.abs(yy - playerY) < yLevelThreshold) {
foundWithinY = true;
}
}
}
}
}
}
}
}
if ((allUnloaded && foundChunks)
@@ -99,12 +124,7 @@ public enum WorldScanner implements IWorldScanner {
return Collections.emptyList();
}
ArrayList<BlockPos> res = new ArrayList<>();
scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY);
return res;
}
public void scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY) {
LinkedList<BlockPos> res = new LinkedList<>();
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
@@ -113,22 +133,21 @@ public enum WorldScanner implements IWorldScanner {
}
int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (search.contains(state.getBlock())) {
if (blocks.contains(state.getBlock())) {
int yy = yReal | y;
result.add(new BlockPos(chunkX | x, yy, chunkZ | z));
if (result.size() >= max && Math.abs(yy - playerY) < yLevelThreshold) {
return;
res.add(new BlockPos((pos.x << 4) | x, yy, (pos.z << 4) | z));
if (res.size() >= max || Math.abs(yy - playerY) < yLevelThreshold) {
return res;
}
}
}
}
}
}
return res;
}
}
@@ -54,6 +54,11 @@ public final class GameEventHandler implements IEventBus, Helper {
listeners.forEach(l -> l.onPlayerUpdate(event));
}
@Override
public final void onProcessKeyBinds() {
listeners.forEach(IGameEventListener::onProcessKeyBinds);
}
@Override
public final void onSendChatMessage(ChatEvent event) {
listeners.forEach(l -> l.onSendChatMessage(event));
@@ -121,11 +126,6 @@ public final class GameEventHandler implements IEventBus, Helper {
listeners.forEach(l -> l.onPlayerRotationMove(event));
}
@Override
public void onPlayerSprintState(SprintStateEvent event) {
listeners.forEach(l -> l.onPlayerSprintState(event));
}
@Override
public void onBlockInteract(BlockInteractEvent event) {
listeners.forEach(l -> l.onBlockInteract(event));
@@ -25,6 +25,7 @@ import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves;
import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult;
@@ -36,7 +37,7 @@ import java.util.Optional;
*
* @author leijurv
*/
public final class AStarPathFinder extends AbstractNodeCostSearch {
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
private final Favoring favoring;
private final CalculationContext calcContext;
@@ -54,14 +55,17 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode);
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
startNode.isOpen = true;
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];
for (int i = 0; i < bestHeuristicSoFar.length; i++) {
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode;
}
MutableMoveResult res = new MutableMoveResult();
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.currentTimeMillis();
Favoring favored = favoring;
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world().getWorldBorder());
long startTime = System.nanoTime() / 1000000L;
boolean slowPath = Baritone.settings().slowPath.get();
if (slowPath) {
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms");
@@ -72,16 +76,13 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
int numNodes = 0;
int numMovementsConsidered = 0;
int numEmptyChunk = 0;
boolean isFavoring = !favoring.isEmpty();
int timeCheckInterval = 1 << 6;
boolean favoring = !favored.isEmpty();
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
double minimumImprovement = Baritone.settings().minimumImprovementRepropagation.get() ? MIN_IMPROVEMENT : 0;
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
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)
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
break;
}
long now = System.nanoTime() / 1000000L;
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
break;
}
if (slowPath) {
try {
@@ -90,10 +91,11 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
}
}
PathNode currentNode = openSet.removeLowest();
currentNode.isOpen = false;
mostRecentConsidered = currentNode;
numNodes++;
if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) {
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered");
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
}
for (Moves moves : Moves.values()) {
@@ -122,10 +124,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
if (actionCost <= 0 || Double.isNaN(actionCost)) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
}
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
continue;
}
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
}
@@ -133,24 +135,36 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
}
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (isFavoring) {
if (favoring) {
// see issue #18
actionCost *= favoring.calculate(hashCode);
actionCost *= favored.calculate(hashCode);
}
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
double tentativeCost = currentNode.cost + actionCost;
if (neighbor.cost - tentativeCost > minimumImprovement) {
if (tentativeCost < neighbor.cost) {
double improvementBy = neighbor.cost - tentativeCost;
// there are floating point errors caused by random combinations of traverse and diagonal over a flat area
// that means that sometimes there's a cost improvement of like 10 ^ -16
// it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
if (improvementBy < 0.01 && minimumImprovementRepropagation) {
// who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
continue;
}
neighbor.previous = currentNode;
neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
if (neighbor.isOpen()) {
if (neighbor.isOpen) {
openSet.update(neighbor);
} else {
neighbor.isOpen = true;
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
}
for (int i = 0; i < COEFFICIENTS.length; i++) {
for (int i = 0; i < bestSoFar.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
if (bestHeuristicSoFar[i] - heuristic > minimumImprovement) {
if (heuristic < bestHeuristicSoFar[i]) {
if (bestHeuristicSoFar[i] - heuristic < 0.01 && minimumImprovementRepropagation) {
continue;
}
bestHeuristicSoFar[i] = heuristic;
bestSoFar[i] = neighbor;
if (getDistFromStartSq(neighbor) > MIN_DIST_PATH * MIN_DIST_PATH) {
@@ -167,11 +181,29 @@ public final class AStarPathFinder extends AbstractNodeCostSearch {
System.out.println(numMovementsConsidered + " movements considered");
System.out.println("Open set size: " + openSet.size());
System.out.println("PathNode map size: " + mapSize());
System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
Optional<IPath> result = bestSoFar(true, numNodes);
if (result.isPresent()) {
logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second");
double bestDist = 0;
for (int i = 0; i < bestSoFar.length; i++) {
if (bestSoFar[i] == null) {
continue;
}
double dist = getDistFromStartSq(bestSoFar[i]);
if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, calcContext));
}
}
return result;
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
logDebug("No path found =(");
return Optional.empty();
}
}
@@ -34,7 +34,7 @@ import java.util.Optional;
*
* @author leijurv
*/
public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
public abstract class AbstractNodeCostSearch implements IPathFinder {
protected final int startX;
protected final int startY;
@@ -53,7 +53,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
protected PathNode mostRecentConsidered;
protected final PathNode[] bestSoFar = new PathNode[COEFFICIENTS.length];
protected PathNode[] bestSoFar;
private volatile boolean isFinished;
@@ -63,23 +63,13 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
* This is really complicated and hard to explain. I wrote a comment in the old version of MineBot but it was so
* long it was easier as a Google Doc (because I could insert charts).
*
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">here</a>
* @see <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit"></a>
*/
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10};
protected static final double[] COEFFICIENTS = {1.5, 2, 2.5, 3, 4, 5, 10}; // big TODO tune
/**
* If a path goes less than 5 blocks and doesn't make it to its goal, it's not worth considering.
*/
protected static final double MIN_DIST_PATH = 5;
/**
* there are floating point errors caused by random combinations of traverse and diagonal over a flat area
* that means that sometimes there's a cost improvement of like 10 ^ -16
* it's not worth the time to update the costs, decrease-key the heap, potentially repropagate, etc
* <p>
* who cares about a hundredth of a tick? that's half a millisecond for crying out loud!
*/
protected static final double MIN_IMPROVEMENT = 0.01;
protected final static double MIN_DIST_PATH = 5;
AbstractNodeCostSearch(int startX, int startY, int startZ, Goal goal, CalculationContext context) {
this.startX = startX;
@@ -102,25 +92,13 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
cancelRequested = false;
try {
IPath path = calculate0(primaryTimeout, failureTimeout).map(IPath::postProcess).orElse(null);
isFinished = true;
if (cancelRequested) {
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION);
return new PathCalculationResult(PathCalculationResult.Type.CANCELLATION, path);
}
if (path == null) {
return new PathCalculationResult(PathCalculationResult.Type.FAILURE);
}
int previousLength = path.length();
path = path.cutoffAtLoadedChunks(context.bsi);
if (path.length() < previousLength) {
Helper.HELPER.logDebug("Cutting off path at edge of loaded chunks");
Helper.HELPER.logDebug("Length decreased by " + (previousLength - path.length()));
} else {
Helper.HELPER.logDebug("Path ends within loaded chunks");
}
previousLength = path.length();
path = path.staticCutoff(goal);
if (path.length() < previousLength) {
Helper.HELPER.logDebug("Static cutoff " + previousLength + " to " + path.length());
}
if (goal.isInGoal(path.getDest())) {
return new PathCalculationResult(PathCalculationResult.Type.SUCCESS_TO_GOAL, path);
} else {
@@ -158,10 +136,11 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
* for the node mapped to the specified pos. If no node is found,
* a new node is created.
*
* @param x The x position of the node
* @param y The y position of the node
* @param z The z position of the node
* @param x The x position of the node
* @param y The y position of the node
* @param z The z position of the node
* @param hashCode The hash code of the node, provided by {@link BetterBlockPos#longHash(int, int, int)}
*
* @return The associated node
* @see <a href="https://github.com/cabaletta/baritone/issues/107">Issue #107</a>
*/
@@ -180,43 +159,25 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
return Optional.ofNullable(mostRecentConsidered).map(node -> new Path(startNode, node, 0, goal, context));
}
@Override
public Optional<IPath> bestPathSoFar() {
return bestSoFar(false, 0);
protected int mapSize() {
return map.size();
}
protected Optional<IPath> bestSoFar(boolean logInfo, int numNodes) {
@Override
public Optional<IPath> bestPathSoFar() {
if (startNode == null || bestSoFar == null) {
return Optional.empty();
}
double bestDist = 0;
for (int i = 0; i < COEFFICIENTS.length; i++) {
for (int i = 0; i < bestSoFar.length; i++) {
if (bestSoFar[i] == null) {
continue;
}
double dist = getDistFromStartSq(bestSoFar[i]);
if (dist > bestDist) {
bestDist = dist;
}
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
if (logInfo) {
if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
System.out.println("But I'm going to do it anyway, because yolo");
}
System.out.println("Path goes for " + Math.sqrt(dist) + " blocks");
logDebug("A* cost coefficient " + COEFFICIENTS[i]);
}
return Optional.of(new Path(startNode, bestSoFar[i], numNodes, goal, context));
if (getDistFromStartSq(bestSoFar[i]) > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
return Optional.of(new Path(startNode, bestSoFar[i], 0, goal, context));
}
}
// instead of returning bestSoFar[0], be less misleading
// if it actually won't find any path, don't make them think it will by rendering a dark blue that will never actually happen
if (logInfo) {
logDebug("Even with a cost coefficient of " + COEFFICIENTS[COEFFICIENTS.length - 1] + ", I couldn't get more than " + Math.sqrt(bestDist) + " blocks");
logDebug("No path found =(");
}
return Optional.empty();
}
@@ -229,12 +190,4 @@ public abstract class AbstractNodeCostSearch implements IPathFinder, Helper {
public final Goal getGoal() {
return goal;
}
public BetterBlockPos getStart() {
return new BetterBlockPos(startX, startY, startZ);
}
protected int mapSize() {
return map.size();
}
}
@@ -132,9 +132,7 @@ class Path extends PathBase {
Movement move = moves.apply0(context, src);
if (move.getDest().equals(dest)) {
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
// however, taking into account possible favoring that could skew the node cost, we really want the stricter limit of the two
// so we take the minimum of the path node cost difference, and the calculated cost
move.override(Math.min(move.calculateCost(context), cost));
move.override(cost);
return move;
}
}
@@ -58,6 +58,12 @@ public final class PathNode {
*/
public PathNode previous;
/**
* Is this a member of the open set in A*? (only used during pathfinding)
* Instead of doing a costly member check in the open set, cache membership in each node individually too.
*/
public boolean isOpen;
/**
* Where is this node in the array flattenization of the binary heap? Needed for decrease-key operations.
*/
@@ -70,16 +76,12 @@ public final class PathNode {
if (Double.isNaN(estimatedCostToGoal)) {
throw new IllegalStateException(goal + " calculated implausible heuristic");
}
this.heapPosition = -1;
this.isOpen = false;
this.x = x;
this.y = y;
this.z = z;
}
public boolean isOpen() {
return heapPosition != -1;
}
/**
* TODO: Possibly reimplement hashCode and equals. They are necessary for this class to function but they could be done better
*
@@ -59,7 +59,7 @@ public final class BinaryHeapOpenSet implements IOpenSet {
@Override
public final void insert(PathNode value) {
if (size >= array.length - 1) {
array = Arrays.copyOf(array, array.length << 1);
array = Arrays.copyOf(array, array.length * 2);
}
size++;
value.heapPosition = size;
@@ -72,7 +72,6 @@ public final class BinaryHeapOpenSet implements IOpenSet {
int index = val.heapPosition;
int parentInd = index >>> 1;
double cost = val.combinedCost;
PathNode[] array = this.array;
PathNode parentNode = array[parentInd];
while (index > 1 && parentNode.combinedCost > cost) {
array[index] = parentNode;
@@ -95,50 +94,40 @@ public final class BinaryHeapOpenSet implements IOpenSet {
if (size == 0) {
throw new IllegalStateException();
}
PathNode[] array = this.array;
PathNode result = array[1];
PathNode val = array[size];
array[1] = val;
val.heapPosition = 1;
array[size] = null;
int size = --this.size;
size--;
result.heapPosition = -1;
if (size < 2) {
return result;
}
int index = 1;
int smallerChild = 1;
int smallerChild = 2;
double cost = val.combinedCost;
while ((smallerChild <<= 1) < size) {
do {
PathNode smallerChildNode = array[smallerChild];
PathNode otherChildNode = array[smallerChild + 1];
double smallerChildCost = smallerChildNode.combinedCost;
double rightChildCost = otherChildNode.combinedCost;
if (smallerChildCost > rightChildCost) {
smallerChild++;
smallerChildCost = rightChildCost;
smallerChildNode = otherChildNode;
if (smallerChild < size) {
PathNode rightChildNode = array[smallerChild + 1];
double rightChildCost = rightChildNode.combinedCost;
if (smallerChildCost > rightChildCost) {
smallerChild++;
smallerChildCost = rightChildCost;
smallerChildNode = rightChildNode;
}
}
if (cost <= smallerChildCost) {
return result;
break;
}
array[index] = smallerChildNode;
array[smallerChild] = val;
val.heapPosition = smallerChild;
smallerChildNode.heapPosition = index;
index = smallerChild;
}
// if we get here, then smallerChild >= size
// one last swap to check
if (smallerChild == size) {
PathNode onlyChildNode = array[smallerChild];
if (cost > onlyChildNode.combinedCost) {
array[index] = onlyChildNode;
array[smallerChild] = val;
val.heapPosition = smallerChild;
onlyChildNode.heapPosition = index;
}
}
} while ((smallerChild <<= 1) <= size);
return result;
}
}
@@ -42,28 +42,26 @@ public class CalculationContext {
private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET);
public final IBaritone baritone;
public final World world;
public final WorldData worldData;
public final BlockStateInterface bsi;
public final ToolSet toolSet;
public final boolean hasWaterBucket;
public final boolean hasThrowaway;
public final boolean canSprint;
public final double placeBlockCost;
public final boolean allowBreak;
public final boolean allowParkour;
public final boolean allowParkourPlace;
public final boolean allowJumpAt256;
public final boolean assumeWalkOnWater;
public final boolean allowDiagonalDescend;
public final int maxFallHeightNoWater;
public final int maxFallHeightBucket;
public final double waterWalkSpeed;
public final double breakBlockAdditionalCost;
public final double jumpPenalty;
public final double walkOnWaterOnePenalty;
public final BetterWorldBorder worldBorder;
private final IBaritone baritone;
private final EntityPlayerSP player;
private final World world;
private final WorldData worldData;
private final BlockStateInterface bsi;
private final ToolSet toolSet;
private final boolean hasWaterBucket;
private final boolean hasThrowaway;
private final boolean canSprint;
private final double placeBlockCost;
private final boolean allowBreak;
private final boolean allowParkour;
private final boolean allowParkourPlace;
private final boolean allowJumpAt256;
private final boolean assumeWalkOnWater;
private final int maxFallHeightNoWater;
private final int maxFallHeightBucket;
private final double waterWalkSpeed;
private final double breakBlockAdditionalCost;
private final BetterWorldBorder worldBorder;
public CalculationContext(IBaritone baritone) {
this(baritone, false);
@@ -71,10 +69,11 @@ public class CalculationContext {
public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) {
this.baritone = baritone;
EntityPlayerSP player = baritone.getPlayerContext().player();
this.player = baritone.getPlayerContext().player();
this.world = baritone.getPlayerContext().world();
this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld();
this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread); // TODO TODO TODO
// new CalculationContext() needs to happen, can't add an argument (i'll beat you), can we get the world provider from currentlyTicking?
this.toolSet = new ToolSet(player);
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(baritone.getPlayerContext(), false);
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
@@ -85,7 +84,6 @@ public class CalculationContext {
this.allowParkourPlace = Baritone.settings().allowParkourPlace.get();
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.get();
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.get();
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.get();
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
int depth = EnchantmentHelper.getDepthStriderModifier(player);
@@ -95,8 +93,6 @@ public class CalculationContext {
float mult = depth / 3.0F;
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult;
this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.get();
this.jumpPenalty = Baritone.settings().jumpPenalty.get();
this.walkOnWaterOnePenalty = Baritone.settings().walkOnWaterOnePenalty.get();
// why cache these things here, why not let the movements just get directly from settings?
// because if some movements are calculated one way and others are calculated another way,
// then you get a wildly inconsistent path that isn't optimal for either scenario.
@@ -124,7 +120,7 @@ public class CalculationContext {
}
public boolean canPlaceThrowawayAt(int x, int y, int z) {
if (!hasThrowaway) { // only true if allowPlace is true, see constructor
if (!hasThrowaway()) { // only true if allowPlace is true, see constructor
return false;
}
if (isPossiblyProtected(x, y, z)) {
@@ -134,7 +130,7 @@ public class CalculationContext {
}
public boolean canBreakAt(int x, int y, int z) {
if (!allowBreak) {
if (!allowBreak()) {
return false;
}
return !isPossiblyProtected(x, y, z);
@@ -144,4 +140,76 @@ public class CalculationContext {
// TODO more protection logic here; see #220
return false;
}
public World world() {
return world;
}
public EntityPlayerSP player() {
return player;
}
public BlockStateInterface bsi() {
return bsi;
}
public WorldData worldData() {
return worldData;
}
public ToolSet getToolSet() {
return toolSet;
}
public boolean hasWaterBucket() {
return hasWaterBucket;
}
public boolean hasThrowaway() {
return hasThrowaway;
}
public boolean canSprint() {
return canSprint;
}
public double placeBlockCost() {
return placeBlockCost;
}
public boolean allowBreak() {
return allowBreak;
}
public boolean allowParkour() {
return allowParkour;
}
public boolean allowParkourPlace() {
return allowParkourPlace;
}
public boolean allowJumpAt256() {
return allowJumpAt256;
}
public boolean assumeWalkOnWater() {
return assumeWalkOnWater;
}
public int maxFallHeightNoWater() {
return maxFallHeightNoWater;
}
public int maxFallHeightBucket() {
return maxFallHeightBucket;
}
public double waterWalkSpeed() {
return waterWalkSpeed;
}
public double breakBlockAdditionalCost() {
return breakBlockAdditionalCost;
}
}
@@ -26,6 +26,7 @@ import baritone.utils.BlockStateInterface;
import net.minecraft.block.BlockLiquid;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList;
import java.util.List;
@@ -34,6 +35,7 @@ import java.util.Optional;
public abstract class Movement implements IMovement, MovementHelper {
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
protected 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;
@@ -84,7 +86,7 @@ public abstract class Movement implements IMovement, MovementHelper {
return cost;
}
public abstract double calculateCost(CalculationContext context);
protected abstract double calculateCost(CalculationContext context);
@Override
public double recalculateCost() {
@@ -123,11 +125,14 @@ public abstract class Movement implements IMovement, MovementHelper {
baritone.getLookBehavior().updateTarget(
rotation,
currentState.getTarget().hasToForceRotations()));
baritone.getInputOverrideHandler().clearAllKeys();
// TODO: calculate movement inputs from latestState.getGoal().position
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
currentState.getInputStates().forEach((input, forced) -> {
baritone.getInputOverrideHandler().setInputForceState(input, forced);
});
currentState.getInputStates().clear();
currentState.getInputStates().replaceAll((input, forced) -> false);
// If the current status indicates a completed movement
if (currentState.getStatus().isComplete()) {
@@ -226,7 +231,7 @@ public abstract class Movement implements IMovement, MovementHelper {
}
public void checkLoadedChunk(CalculationContext context) {
calculatedWhileLoaded = context.bsi.worldContainsLoadedChunk(dest.x, dest.z);
calculatedWhileLoaded = !(context.world().getChunk(getDest()) instanceof EmptyChunk);
}
@Override
@@ -18,9 +18,7 @@
package baritone.pathing.movement;
import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.*;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.MovementState.MovementTarget;
@@ -37,10 +35,6 @@ import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import static baritone.pathing.movement.Movement.HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP;
/**
* Static helpers for cost calculation
@@ -346,24 +340,24 @@ 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 (!canWalkThrough(context.bsi(), x, y, z, state)) {
if (!context.canBreakAt(x, y, z)) {
return COST_INF;
}
if (avoidBreaking(context.bsi, x, y, z, state)) {
if (avoidBreaking(context.bsi(), x, y, z, state)) {
return COST_INF;
}
if (block instanceof BlockLiquid) {
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);
double strVsBlock = context.getToolSet().getStrVsBlock(state);
if (strVsBlock <= 0) {
return COST_INF;
}
double result = m / strVsBlock;
result += context.breakBlockAdditionalCost;
result += context.breakBlockAdditionalCost();
if (includeFalling) {
IBlockState above = context.get(x, y + 1, z);
if (above.getBlock() instanceof BlockFalling) {
@@ -491,48 +485,4 @@ public interface MovementHelper extends ActionCosts, Helper {
return state.getBlock() instanceof BlockLiquid
&& state.getValue(BlockLiquid.LEVEL) != 0;
}
static PlaceResult attemptToPlaceABlock(MovementState state, IBaritone baritone, BlockPos placeAt, boolean preferDown) {
IPlayerContext ctx = baritone.getPlayerContext();
boolean found = false;
for (int i = 0; i < 5; 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(placeAt.getX(), placeAt.getY(), placeAt.getZ())) { // get ready to place a throwaway block
if (!throwaway(ctx, true)) {
Helper.HELPER.logDebug("bb pls get me some blocks. dirt or cobble");
state.setStatus(MovementStatus.UNREACHABLE);
return PlaceResult.NO_OPTION;
}
double faceX = (placeAt.getX() + against1.getX() + 1.0D) * 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)) {
state.setTarget(new MovementState.MovementTarget(place, true));
found = true;
if (!preferDown) {
// if preferDown is true, we want the last option
// if preferDown is false, we want the first
break;
}
}
}
}
if (ctx.getSelectedBlock().isPresent()) {
BlockPos selectedBlock = ctx.getSelectedBlock().get();
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))) {
return PlaceResult.READY_TO_PLACE;
}
}
return found ? PlaceResult.ATTEMPTING : PlaceResult.NO_OPTION;
}
enum PlaceResult {
READY_TO_PLACE, ATTEMPTING, NO_OPTION;
}
}
@@ -20,6 +20,7 @@ package baritone.pathing.movement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.Rotation;
import baritone.api.utils.input.Input;
import net.minecraft.util.math.Vec3d;
import java.util.HashMap;
import java.util.Map;
@@ -28,6 +29,7 @@ import java.util.Optional;
public class MovementState {
private MovementStatus status;
private MovementTarget goal = new MovementTarget();
private MovementTarget target = new MovementTarget();
private final Map<Input, Boolean> inputState = new HashMap<>();
@@ -40,6 +42,15 @@ public class MovementState {
return status;
}
public MovementTarget getGoal() {
return this.goal;
}
public MovementState setGoal(MovementTarget goal) {
this.goal = goal;
return this;
}
public MovementTarget getTarget() {
return this.target;
}
@@ -54,12 +65,23 @@ public class MovementState {
return this;
}
public boolean getInput(Input input) {
return this.inputState.getOrDefault(input, false);
}
public Map<Input, Boolean> getInputStates() {
return this.inputState;
}
public static class MovementTarget {
/**
* Necessary movement to achieve
* <p>
* TODO: Decide desiredMovement type
*/
public Vec3d position;
/**
* Yaw and pitch angles that must be matched
*/
@@ -73,14 +95,27 @@ public class MovementState {
private boolean forceRotations;
public MovementTarget() {
this(null, false);
this(null, null, false);
}
public MovementTarget(Vec3d position) {
this(position, null, false);
}
public MovementTarget(Rotation rotation, boolean forceRotations) {
this(null, rotation, forceRotations);
}
public MovementTarget(Vec3d position, Rotation rotation, boolean forceRotations) {
this.position = position;
this.rotation = rotation;
this.forceRotations = forceRotations;
}
public final Optional<Vec3d> getPosition() {
return Optional.ofNullable(this.position);
}
public final Optional<Rotation> getRotation() {
return Optional.ofNullable(this.rotation);
}
@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
@@ -31,6 +32,10 @@ import net.minecraft.block.BlockFalling;
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.util.math.Vec3d;
import java.util.Objects;
public class MovementAscend extends Movement {
@@ -47,18 +52,18 @@ public class MovementAscend extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z, dest.x, dest.z);
}
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
IBlockState toPlace = context.get(destX, y, destZ);
boolean hasToPlace = false;
if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, y, destZ, toPlace)) {
if (!context.canPlaceThrowawayAt(destX, y, destZ)) {
return COST_INF;
}
if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi)) {
if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi())) {
return COST_INF;
}
for (int i = 0; i < 5; i++) {
@@ -68,7 +73,7 @@ public class MovementAscend extends Movement {
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;
}
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) {
hasToPlace = true;
break;
}
@@ -78,7 +83,7 @@ public class MovementAscend extends Movement {
}
}
IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi(), x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
// HOWEVER, we assume that we're standing in the start position
// that means that src and src.up(1) are both air
// maybe they aren't now, but they will be by the time this starts
@@ -110,23 +115,23 @@ public class MovementAscend extends Movement {
if (jumpingToBottomSlab) {
if (jumpingFromBottomSlab) {
walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); // we hit space immediately on entering this action
walk += context.jumpPenalty;
} else {
walk = WALK_ONE_BLOCK_COST; // we don't hit space we just walk into the slab
}
} else {
// jumpingFromBottomSlab must be false
if (toPlace.getBlock() == Blocks.SOUL_SAND) {
walk = WALK_ONE_OVER_SOUL_SAND_COST;
} else {
walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST);
walk = WALK_ONE_BLOCK_COST;
}
walk += context.jumpPenalty;
}
double totalCost = walk;
// cracks knuckles
double totalCost = 0;
totalCost += walk;
if (hasToPlace) {
totalCost += context.placeBlockCost;
totalCost += context.placeBlockCost();
}
// start with srcUp2 since we already have its state
// includeFalling isn't needed because of the falling check above -- if srcUp3 is falling we will have already exited with COST_INF if we'd actually have to break it
@@ -157,30 +162,55 @@ public class MovementAscend extends Movement {
IBlockState jumpingOnto = BlockStateInterface.get(ctx, positionToPlace);
if (!MovementHelper.canWalkOn(ctx, positionToPlace, jumpingOnto)) {
ticksWithoutPlacement++;
if (MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false) == PlaceResult.READY_TO_PLACE) {
state.setInput(Input.SNEAK, true);
if (ctx.player().isSneaking()) {
state.setInput(Input.CLICK_RIGHT, true);
for (int i = 0; i < 5; i++) {
BlockPos anAgainst = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (anAgainst.equals(src)) {
continue;
}
if (MovementHelper.canPlaceAgainst(ctx, anAgainst)) {
if (!MovementHelper.throwaway(ctx, true)) {//get ready to place a throwaway block
return state.setStatus(MovementStatus.UNREACHABLE);
}
double faceX = (dest.getX() + anAgainst.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + anAgainst.getY()) * 0.5D;
double faceZ = (dest.getZ() + anAgainst.getZ() + 1.0D) * 0.5D;
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations()), true));
EnumFacing side = ctx.objectMouseOver().sideHit;
ctx.getSelectedBlock().ifPresent(selectedBlock -> {
if (Objects.equals(selectedBlock, anAgainst) && selectedBlock.offset(side).equals(positionToPlace)) {
ticksWithoutPlacement++;
state.setInput(Input.SNEAK, true);
if (ctx.player().isSneaking()) {
state.setInput(Input.CLICK_RIGHT, true);
}
if (ticksWithoutPlacement > 10) {
// After 10 ticks without placement, we might be standing in the way, move back
state.setInput(Input.MOVE_BACK, true);
}
} else {
state.setInput(Input.CLICK_LEFT, true); // break whatever replaceable block is in the way
}
//System.out.println("Trying to look at " + anAgainst + ", actually looking at" + selectedBlock);
});
return state;
}
}
if (ticksWithoutPlacement > 10) {
// After 10 ticks without placement, we might be standing in the way, move back
state.setInput(Input.MOVE_BACK, true);
}
return state;
return state.setStatus(MovementStatus.UNREACHABLE);
}
MovementHelper.moveTowards(ctx, state, dest);
if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(BlockStateInterface.get(ctx, src.down()))) {
return state; // don't jump while walking from a non double slab into a bottom slab
}
if (Baritone.settings().assumeStep.get() || ctx.playerFeet().equals(src.up())) {
// no need to hit space if we're already jumping
if (Baritone.settings().assumeStep.get()) {
return state;
}
if (ctx.playerFeet().equals(src.up())) {
return state; // no need to hit space if we're already jumping
}
if (headBonkClear()) {
return state.setInput(Input.JUMP, true);
}
@@ -52,7 +52,7 @@ public class MovementDescend extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult();
cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) {
@@ -93,7 +93,7 @@ public class MovementDescend extends Movement {
//C, D, etc determine the length of the fall
IBlockState below = context.get(destX, y - 2, destZ);
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ, below)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 2, destZ, below)) {
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
return;
}
@@ -122,7 +122,7 @@ public class MovementDescend extends Movement {
// and potentially replace the water we're going to fall into
return false;
}
if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
if (!MovementHelper.canWalkThrough(context.bsi(), destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
return false;
}
double costSoFar = 0;
@@ -137,16 +137,16 @@ 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 ((ontoBlock.getBlock() == Blocks.WATER || ontoBlock.getBlock() == Blocks.FLOWING_WATER) && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) {
if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) {
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
if (context.assumeWalkOnWater) {
if (context.assumeWalkOnWater()) {
return false; // TODO fix
}
if (MovementHelper.isFlowing(ontoBlock)) {
return false; // TODO flowing check required here?
}
if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, newY - 1, destZ)) {
// we could punch right through the water into something else
return false;
}
@@ -157,6 +157,9 @@ public class MovementDescend extends Movement {
res.cost = tentativeCost;// TODO incorporate water swim up cost?
return false;
}
if (ontoBlock.getBlock() == Blocks.FLOWING_WATER) {
return false;
}
if (unprotectedFallHeight <= 11 && (ontoBlock.getBlock() == Blocks.VINE || ontoBlock.getBlock() == Blocks.LADDER)) {
// if fall height is greater than or equal to 11, we don't actually grab on to vines or ladders. the more you know
// this effectively "resets" our falling speed
@@ -165,29 +168,29 @@ public class MovementDescend extends Movement {
effectiveStartHeight = newY;
continue;
}
if (MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
if (MovementHelper.canWalkThrough(context.bsi(), destX, newY, destZ, ontoBlock)) {
continue;
}
if (!MovementHelper.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, newY, destZ, ontoBlock)) {
return false;
}
if (MovementHelper.isBottomSlab(ontoBlock)) {
return false; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
}
if (unprotectedFallHeight <= context.maxFallHeightNoWater + 1) {
if (context.hasWaterBucket() && unprotectedFallHeight <= context.maxFallHeightBucket() + 1) {
res.x = destX;
res.y = newY + 1;// this is the block we're falling onto, so dest is +1
res.z = destZ;
res.cost = tentativeCost + context.placeBlockCost();
return true;
}
if (unprotectedFallHeight <= context.maxFallHeightNoWater() + 1) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max
res.x = destX;
res.y = newY + 1;
res.z = destZ;
res.cost = tentativeCost;
return false;
}
if (context.hasWaterBucket && unprotectedFallHeight <= context.maxFallHeightBucket + 1) {
res.x = destX;
res.y = newY + 1;// this is the block we're falling onto, so dest is +1
res.z = destZ;
res.cost = tentativeCost + context.placeBlockCost;
return true;
} else {
return false;
}
@@ -232,7 +235,8 @@ public class MovementDescend extends Movement {
if (numTicks++ < 20) {
MovementHelper.moveTowards(ctx, state, fakeDest);
if (fromStart > 1.25) {
state.getTarget().rotation = new Rotation(state.getTarget().rotation.getYaw() + 180F, state.getTarget().rotation.getPitch());
state.setInput(Input.MOVE_FORWARD, false);
state.setInput(Input.MOVE_BACK, true);
}
} else {
MovementHelper.moveTowards(ctx, state, dest);
@@ -54,7 +54,7 @@ public class MovementDiagonal extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult();
cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) {
@@ -65,14 +65,14 @@ public class MovementDiagonal extends Movement {
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)) {
if (!MovementHelper.canWalkThrough(context.bsi(), destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi(), destX, y + 1, destZ)) {
return;
}
IBlockState destWalkOn = context.get(destX, y - 1, destZ);
boolean descend = false;
if (!MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 1, destZ, destWalkOn)) {
descend = true;
if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) {
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi(), destX, y - 1, destZ, destWalkOn)) {
return;
}
}
@@ -80,8 +80,6 @@ public class MovementDiagonal extends Movement {
// For either possible soul sand, that affects half of our walking
if (destWalkOn.getBlock() == Blocks.SOUL_SAND) {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
} else if (destWalkOn.getBlock() == Blocks.WATER) {
multiplier += context.walkOnWaterOnePenalty * SQRT_2;
}
Block fromDown = context.get(x, y - 1, z).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
@@ -133,7 +131,7 @@ public class MovementDiagonal extends Movement {
// Ignore previous multiplier
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
// Not even touching the blocks below
multiplier = context.waterWalkSpeed;
multiplier = context.waterWalkSpeed();
water = true;
}
if (optionA != 0 || optionB != 0) {
@@ -144,7 +142,7 @@ public class MovementDiagonal extends Movement {
}
} else {
// only can sprint if not edging around
if (context.canSprint && !water) {
if (context.canSprint() && !water) {
// If we aren't edging around anything, and we aren't in water
// We can sprint =D
// Don't check for soul sand, since we can sprint on that too
@@ -43,12 +43,12 @@ public class MovementDownward extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z);
}
public static double cost(CalculationContext context, int x, int y, int z) {
if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) {
if (!MovementHelper.canWalkOn(context.bsi(), x, y - 2, z)) {
return COST_INF;
}
IBlockState down = context.get(x, y - 1, z);
@@ -30,7 +30,6 @@ import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLadder;
import net.minecraft.block.state.IBlockState;
import net.minecraft.entity.player.InventoryPlayer;
@@ -55,7 +54,7 @@ public class MovementFall extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult();
MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) {
@@ -80,9 +79,7 @@ public class MovementFall extends Movement {
BlockPos playerFeet = ctx.playerFeet();
Rotation toDest = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest));
Rotation targetRotation = null;
Block destBlock = ctx.world().getBlockState(dest).getBlock();
boolean isWater = destBlock == Blocks.WATER || destBlock == Blocks.FLOWING_WATER;
if (!isWater && willPlaceBucket() && !playerFeet.equals(dest)) {
if (!MovementHelper.isWater(ctx, dest) && willPlaceBucket() && !playerFeet.equals(dest)) {
if (!InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_WATER)) || ctx.world().provider.isNether()) {
return state.setStatus(MovementStatus.UNREACHABLE);
}
@@ -103,8 +100,8 @@ public class MovementFall extends Movement {
} else {
state.setTarget(new MovementTarget(toDest, false));
}
if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || isWater)) { // 0.094 because lilypads
if (isWater) { // only match water, not flowing water (which we cannot pick up with a bucket)
if (playerFeet.equals(dest) && (ctx.player().posY - playerFeet.getY() < 0.094 || MovementHelper.isWater(ctx, dest))) { // 0.094 because lilypads
if (MovementHelper.isWater(ctx, dest)) {
if (InventoryPlayer.isHotbar(ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
ctx.player().inventory.currentItem = ctx.player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
if (ctx.player().motionY >= 0) {
@@ -135,7 +132,7 @@ public class MovementFall extends Movement {
double dist = Math.abs(avoid.getX() * (destCenter.x - avoid.getX() / 2.0 - ctx.player().posX)) + Math.abs(avoid.getZ() * (destCenter.z - avoid.getZ() / 2.0 - ctx.player().posZ));
if (dist < 0.6) {
state.setInput(Input.MOVE_FORWARD, true);
} else if (!ctx.player().onGround) {
} else {
state.setInput(Input.SNEAK, false);
}
}
@@ -20,6 +20,9 @@ package baritone.pathing.movement.movements;
import baritone.api.IBaritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
@@ -32,6 +35,9 @@ import net.minecraft.block.BlockStairs;
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.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
public class MovementParkour extends Movement {
@@ -54,10 +60,10 @@ public class MovementParkour extends Movement {
}
public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
if (!context.allowParkour) {
if (!context.allowParkour()) {
return;
}
if (y == 256 && !context.allowJumpAt256) {
if (y == 256 && !context.allowJumpAt256()) {
return;
}
@@ -68,7 +74,7 @@ public class MovementParkour extends Movement {
return;
}
IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff);
if (MovementHelper.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
if (MovementHelper.canWalkOn(context.bsi(), x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
// second most common case -- we could just traverse not parkour
return;
}
@@ -92,7 +98,7 @@ public class MovementParkour extends Movement {
if (standingOn.getBlock() == Blocks.SOUL_SAND) {
maxJump = 2; // 1 block gap
} else {
if (context.canSprint) {
if (context.canSprint()) {
maxJump = 4;
} else {
maxJump = 3;
@@ -105,18 +111,18 @@ public class MovementParkour extends Movement {
return;
}
}
if (MovementHelper.canWalkOn(context.bsi, x + xDiff * i, y - 1, z + zDiff * i)) {
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;
res.cost = costFromJumpDistance(i);
return;
}
}
if (maxJump != 4) {
return;
}
if (!context.allowParkourPlace) {
if (!context.allowParkourPlace()) {
return;
}
int destX = x + 4 * xDiff;
@@ -125,7 +131,7 @@ public class MovementParkour extends Movement {
return;
}
IBlockState toReplace = context.get(destX, y - 1, destZ);
if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi)) {
if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi())) {
return;
}
for (int i = 0; i < 5; i++) {
@@ -135,11 +141,11 @@ public class MovementParkour extends Movement {
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
continue;
}
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) {
res.x = destX;
res.y = y;
res.z = destZ;
res.cost = costFromJumpDistance(4) + context.placeBlockCost + context.jumpPenalty;
res.cost = costFromJumpDistance(4) + context.placeBlockCost();
return;
}
}
@@ -160,7 +166,7 @@ public class MovementParkour extends Movement {
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
MutableMoveResult res = new MutableMoveResult();
cost(context, src.x, src.y, src.z, direction, res);
if (res.x != dest.x || res.z != dest.z) {
@@ -203,9 +209,35 @@ public class MovementParkour extends Movement {
}
} else if (!ctx.playerFeet().equals(src)) {
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);
if (!MovementHelper.canWalkOn(ctx, dest.down()) && !ctx.player().onGround) {
BlockPos positionToPlace = dest.down();
for (int i = 4; i >= 0; i--) { // 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
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (against1.up().equals(src.offset(direction, 3))) { // we can't turn around that fast
continue;
}
if (MovementHelper.canPlaceAgainst(ctx, against1)) {
if (!MovementHelper.throwaway(ctx, true)) {//get ready to place a throwaway block
return state.setStatus(MovementStatus.UNREACHABLE);
}
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D;
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
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(dest.down())) {
state.setTarget(new MovementState.MovementTarget(place, true));
break;
}
}
}
ctx.getSelectedBlock().ifPresent(selectedBlock -> {
EnumFacing side = ctx.objectMouseOver().sideHit;
if (MovementHelper.canPlaceAgainst(ctx, selectedBlock) && selectedBlock.offset(side).equals(dest.down())) {
state.setInput(Input.CLICK_RIGHT, true);
}
});
}
if (dist == 3) { // this is a 2 block gap, dest = src + direction * 3
double xDiff = (src.x + 0.5) - ctx.player().posX;
@@ -35,8 +35,6 @@ import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
import java.util.Objects;
public class MovementPillar extends Movement {
public MovementPillar(IBaritone baritone, BetterBlockPos start, BetterBlockPos end) {
@@ -44,7 +42,7 @@ public class MovementPillar extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z);
}
@@ -60,7 +58,7 @@ public class MovementPillar extends Movement {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
}
}
if (from == Blocks.VINE && !hasAgainst(context, x, y, z)) { // TODO this vine can't be climbed, but we could place a pillar still since vines are replacable, no? perhaps the pillar jump would be impossible because of the slowdown actually.
if (from instanceof BlockVine && !hasAgainst(context, x, y, z)) { // TODO this vine can't be climbed, but we could place a pillar still since vines are replacable, no? perhaps the pillar jump would be impossible because of the slowdown actually.
return COST_INF;
}
IBlockState toBreak = context.get(x, y + 2, z);
@@ -78,7 +76,7 @@ public class MovementPillar extends Movement {
if (!ladder && !context.canPlaceThrowawayAt(x, y, z)) { // we need to place a block where we started to jump on it
return COST_INF;
}
if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && context.assumeWalkOnWater)) {
if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && 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
@@ -114,7 +112,7 @@ public class MovementPillar extends Movement {
if (ladder) {
return LADDER_UP_ONE_COST + hardness * 5;
} else {
return JUMP_ONE_BLOCK_COST + context.placeBlockCost + context.jumpPenalty + hardness;
return JUMP_ONE_BLOCK_COST + context.placeBlockCost() + hardness;
}
}
@@ -161,8 +159,8 @@ public class MovementPillar extends Movement {
}
return state;
}
boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE;
boolean vine = fromDown.getBlock() == Blocks.VINE;
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine;
boolean vine = fromDown.getBlock() instanceof BlockVine;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
@@ -226,7 +224,7 @@ public class MovementPillar extends Movement {
if (!(fr instanceof BlockAir || fr.isReplaceable(ctx.world(), src))) {
state.setInput(Input.CLICK_LEFT, true);
blockIsThere = false;
} else if (ctx.player().isSneaking() && (Objects.equals(src.down(), ctx.objectMouseOver().getBlockPos()) || Objects.equals(src, ctx.objectMouseOver().getBlockPos()))) {
} else if (ctx.player().isSneaking()) { // 1 tick after we're able to place
state.setInput(Input.CLICK_RIGHT, true);
}
}
@@ -30,12 +30,10 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import net.minecraft.block.Block;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockFenceGate;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.*;
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.util.math.Vec3d;
@@ -59,7 +57,7 @@ public class MovementTraverse extends Movement {
}
@Override
public double calculateCost(CalculationContext context) {
protected double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z, dest.x, dest.z);
}
@@ -68,17 +66,15 @@ public class MovementTraverse extends Movement {
IBlockState pb1 = context.get(destX, y, destZ);
IBlockState destOn = context.get(destX, y - 1, destZ);
Block srcDown = context.getBlock(x, y - 1, z);
if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
if (MovementHelper.canWalkOn(context.bsi(), destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
double WC = WALK_ONE_BLOCK_COST;
boolean water = false;
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
WC = context.waterWalkSpeed;
WC = context.waterWalkSpeed();
water = true;
} else {
if (destOn.getBlock() == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
} else if (destOn.getBlock() == Blocks.WATER) {
WC += context.walkOnWaterOnePenalty;
}
if (srcDown == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
@@ -90,7 +86,7 @@ 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
if (hardness1 == 0 && hardness2 == 0) {
if (!water && context.canSprint) {
if (!water && context.canSprint()) {
// If there's nothing in the way, and this isn't water, and we aren't sneak placing
// We can sprint =D
// Don't check for soul sand, since we can sprint on that too
@@ -107,7 +103,7 @@ public class MovementTraverse extends Movement {
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
return COST_INF;
}
if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) {
if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi())) {
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
// this happens when assume walk on water is true and this is a traverse in water, which isn't allowed
@@ -121,7 +117,7 @@ public class MovementTraverse extends Movement {
return COST_INF;
}
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;
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();
@@ -129,19 +125,19 @@ public class MovementTraverse extends Movement {
if (againstX == x && againstZ == z) { // this would be a backplace
continue;
}
if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option
return WC + context.placeBlockCost + hardness1 + hardness2;
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) { // found a side place option
return WC + context.placeBlockCost() + hardness1 + hardness2;
}
}
// 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())) {
return COST_INF; // can't sneak and backplace against soul sand or half slabs (regardless of whether it's top half or bottom half) =/
return COST_INF; // can't sneak and backplace against soul sand or half slabs =/
}
if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) {
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
return WC + context.placeBlockCost + hardness1 + hardness2;
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are sneak backplacing, we are sneaking lol
return WC + context.placeBlockCost() + hardness1 + hardness2;
}
return COST_INF;
}
@@ -185,7 +181,7 @@ public class MovementTraverse extends Movement {
state.setInput(Input.SNEAK, false);
Block fd = BlockStateInterface.get(ctx, src.down()).getBlock();
boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE;
boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine;
IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]);
@@ -238,7 +234,7 @@ public class MovementTraverse extends Movement {
state.setInput(Input.SPRINT, true);
}
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();
if (whereAmI.getY() != dest.getY() && ladder && (destDown == Blocks.VINE || destDown == Blocks.LADDER)) {
if (whereAmI.getY() != dest.getY() && ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) {
new MovementPillar(baritone, dest.down(), dest).updateState(state); // i'm sorry
return state;
}
@@ -246,45 +242,53 @@ public class MovementTraverse extends Movement {
return state;
} else {
wasTheBridgeBlockAlwaysThere = false;
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
MovementHelper.moveTowards(ctx, state, dest);
return state.setInput(Input.MOVE_FORWARD, false)
.setInput(Input.MOVE_BACK, true);
for (int i = 0; i < 5; i++) {
BlockPos against1 = dest.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
if (against1.equals(src)) {
continue;
}
}
double dist1 = Math.max(Math.abs(ctx.player().posX - (dest.getX() + 0.5D)), Math.abs(ctx.player().posZ - (dest.getZ() + 0.5D)));
PlaceResult p = MovementHelper.attemptToPlaceABlock(state, baritone, dest.down(), false);
if ((p == PlaceResult.READY_TO_PLACE || dist1 < 0.6) && !Baritone.settings().assumeSafeWalk.get()) {
state.setInput(Input.SNEAK, true);
}
switch (p) {
case READY_TO_PLACE: {
if (ctx.player().isSneaking() || Baritone.settings().assumeSafeWalk.get()) {
state.setInput(Input.CLICK_RIGHT, true);
against1 = against1.down();
if (MovementHelper.canPlaceAgainst(ctx, against1)) {
if (!MovementHelper.throwaway(ctx, true)) { // get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementStatus.UNREACHABLE);
}
return state;
}
case ATTEMPTING: {
if (dist1 > 0.83) {
// might need to go forward a bit
float yaw = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), VecUtils.getBlockPosCenter(dest), ctx.playerRotations()).getYaw();
if (Math.abs(state.getTarget().rotation.getYaw() - yaw) < 0.1) {
// but only if our attempted place is straight ahead
return state.setInput(Input.MOVE_FORWARD, true);
if (!Baritone.settings().assumeSafeWalk.get()) {
state.setInput(Input.SNEAK, true);
}
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
MovementHelper.moveTowards(ctx, state, dest);
return state.setInput(Input.MOVE_FORWARD, false)
.setInput(Input.MOVE_BACK, true);
}
} else if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) {
// well i guess theres something in the way
return state.setInput(Input.CLICK_LEFT, true);
}
return state;
state.setInput(Input.MOVE_BACK, false);
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D;
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations()), true));
EnumFacing side = ctx.objectMouseOver().sideHit;
if (Objects.equals(ctx.getSelectedBlock().orElse(null), against1) && (ctx.player().isSneaking() || Baritone.settings().assumeSafeWalk.get()) && ctx.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
return state.setInput(Input.CLICK_RIGHT, true);
}
//System.out.println("Trying to look at " + against1 + ", actually looking at" + RayTraceUtils.getSelectedBlock());
return state.setInput(Input.CLICK_LEFT, true);
}
}
if (!Baritone.settings().assumeSafeWalk.get()) {
state.setInput(Input.SNEAK, true);
}
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);
if (!MovementHelper.throwaway(ctx, true)) {// get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementStatus.UNREACHABLE);
}
double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D;
double faceZ = (dest.getZ() + src.getZ() + 1.0D) * 0.5D;
@@ -293,26 +297,25 @@ public class MovementTraverse extends Movement {
Rotation backToFace = RotationUtils.calcRotationFromVec3d(ctx.playerHead(), new Vec3d(faceX, faceY, faceZ), ctx.playerRotations());
float pitch = backToFace.getPitch();
double dist2 = Math.max(Math.abs(ctx.player().posX - faceX), Math.abs(ctx.player().posZ - faceZ));
if (dist2 < 0.29) { // see issue #208
double dist = Math.max(Math.abs(ctx.player().posX - faceX), Math.abs(ctx.player().posZ - faceZ));
if (dist < 0.29) {
float yaw = RotationUtils.calcRotationFromVec3d(VecUtils.getBlockPosCenter(dest), ctx.playerHead(), ctx.playerRotations()).getYaw();
state.setTarget(new MovementState.MovementTarget(new Rotation(yaw, pitch), true));
state.setInput(Input.MOVE_BACK, true);
} else {
state.setTarget(new MovementState.MovementTarget(backToFace, true));
}
state.setInput(Input.SNEAK, true);
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());
if (ctx.playerRotations().isReallyCloseTo(state.getTarget().rotation)) {
state.setInput(Input.CLICK_LEFT, true);
}
return state.setInput(Input.CLICK_LEFT, true);
} else {
MovementHelper.moveTowards(ctx, state, positionsToBreak[0]);
return state;
// TODO MovementManager.moveTowardsBlock(to); // move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block
}
MovementHelper.moveTowards(ctx, state, positionsToBreak[0]);
return state;
// TODO MovementManager.moveTowardsBlock(to); // move towards not look at because if we are bridging for a couple blocks in a row, it is faster if we dont spin around and walk forwards then spin around and place backwards for every block
}
}
@@ -334,4 +337,4 @@ public class MovementTraverse extends Movement {
}
return super.prepared(state);
}
}
}
@@ -79,8 +79,6 @@ public class PathExecutor implements IPathExecutor, Helper {
private PathingBehavior behavior;
private IPlayerContext ctx;
private boolean sprintNextTick;
public PathExecutor(PathingBehavior behavior, IPath path) {
this.behavior = behavior;
this.ctx = behavior.ctx;
@@ -112,6 +110,7 @@ public class PathExecutor implements IPathExecutor, Helper {
return false;
}
//System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
if (whereAmI.equals(path.positions().get(i))) {
@@ -271,10 +270,7 @@ public class PathExecutor implements IPathExecutor, Helper {
onTick();
return true;
} else {
sprintNextTick = shouldSprintNextTick();
if (!sprintNextTick) {
ctx.player().setSprinting(false); // letting go of control doesn't make you stop sprinting actually
}
sprintIfRequested();
ticksOnCurrent++;
if (ticksOnCurrent > currentMovementOriginalCostEstimate + Baritone.settings().movementTimeoutTicks.get()) {
// only cancel if the total time has exceeded the initial estimate
@@ -376,17 +372,20 @@ public class PathExecutor implements IPathExecutor, Helper {
return true;
}
private boolean shouldSprintNextTick() {
private void sprintIfRequested() {
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint) {
if (!new CalculationContext(behavior.baritone).canSprint()) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return false;
ctx.player().setSprinting(false);
return;
}
// if the movement requested sprinting, then we're done
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
return true;
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindSprint)) {
if (!ctx.player().isSprinting()) {
ctx.player().setSprinting(true);
}
return;
}
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
@@ -394,32 +393,36 @@ public class PathExecutor implements IPathExecutor, Helper {
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend) {
if (current instanceof MovementDescend && pathPosition < path.length() - 2) {
if (((MovementDescend) current).safeMode()) {
logDebug("Sprinting would be unsafe");
return false;
ctx.player().setSprinting(false);
return;
}
if (pathPosition < path.length() - 2) {
IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction
pathPosition++;
// okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric
logDebug("Skipping descend to straight ascend");
return true;
IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction
if (!ctx.player().isSprinting()) {
ctx.player().setSprinting(true);
}
if (canSprintInto(ctx, current, next)) {
if (ctx.playerFeet().equals(current.getDest())) {
pathPosition++;
onChangeInPathPosition();
onTick();
}
return true;
}
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
pathPosition++;
// okay to skip clearKeys and / or onChangeInPathPosition here since this isn't possible to repeat, since it's asymmetric
logDebug("Skipping descend to straight ascend");
return;
}
if (canSprintInto(ctx, current, next)) {
if (ctx.playerFeet().equals(current.getDest())) {
pathPosition++;
onChangeInPathPosition();
}
if (!ctx.player().isSprinting()) {
ctx.player().setSprinting(true);
}
return;
}
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
}
if (current instanceof MovementAscend && pathPosition != 0) {
IMovement prev = path.movements().get(pathPosition - 1);
@@ -427,11 +430,14 @@ public class PathExecutor implements IPathExecutor, Helper {
BlockPos center = current.getSrc().up();
if (ctx.player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.JUMP, false);
return true;
if (!ctx.player().isSprinting()) {
ctx.player().setSprinting(true);
}
return;
}
}
}
return false;
ctx.player().setSprinting(false);
}
private static boolean canSprintInto(IPlayerContext ctx, IMovement current, IMovement next) {
@@ -461,7 +467,6 @@ public class PathExecutor implements IPathExecutor, Helper {
failed = true;
}
@Override
public int getPosition() {
return pathPosition;
}
@@ -527,8 +532,4 @@ public class PathExecutor implements IPathExecutor, Helper {
public Set<BlockPos> toWalkInto() {
return Collections.unmodifiableSet(toWalkInto);
}
public boolean isSprinting() {
return sprintNextTick;
}
}
@@ -57,6 +57,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
}
private Goal towards(Entity following) {
// lol this is trashy but it works
BlockPos pos;
if (Baritone.settings().followOffsetDistance.get() == 0) {
pos = new BlockPos(following);
@@ -78,7 +79,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
if (entity.equals(ctx.player())) {
return false;
}
return ctx.world().loadedEntityList.contains(entity);
return ctx.world().loadedEntityList.contains(entity) || ctx.world().playerEntities.contains(entity);
}
private void scanWorld() {
@@ -154,4 +154,4 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
}
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
}
}
}
+12 -13
View File
@@ -39,6 +39,7 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.*;
import java.util.stream.Collectors;
@@ -94,14 +95,14 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
if (Baritone.settings().legitMine.get()) {
addNearby();
}
PathingCommand command = updateGoal();
if (command == null) {
Goal goal = updateGoal();
if (goal == null) {
// none in range
// maybe say something in chat? (ahem impact)
cancel();
return null;
}
return command;
return new PathingCommand(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH);
}
@Override
@@ -114,18 +115,17 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return "Mine " + mining;
}
private PathingCommand updateGoal() {
boolean legit = Baritone.settings().legitMine.get();
private Goal updateGoal() {
List<BlockPos> locs = knownOreLocations;
if (!locs.isEmpty()) {
List<BlockPos> locs2 = prune(new CalculationContext(baritone), new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT);
// can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final
Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(ctx, loc, locs2)).toArray(Goal[]::new));
knownOreLocations = locs2;
return new PathingCommand(goal, legit ? PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH : PathingCommandType.REVALIDATE_GOAL_AND_PATH);
return goal;
}
// we don't know any ore locations at the moment
if (!legit) {
if (!Baritone.settings().legitMine.get()) {
return null;
}
// only in non-Xray mode (aka legit mode) do we do this
@@ -150,7 +150,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
}
};
}
return new PathingCommand(branchPointRunaway, PathingCommandType.REVALIDATE_GOAL_AND_PATH);
return branchPointRunaway;
}
private void rescan(List<BlockPos> already, CalculationContext context) {
@@ -210,7 +210,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
//long b = System.currentTimeMillis();
for (Block m : mining) {
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
locs.addAll(ctx.worldData().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
} else {
uninteresting.add(m);
}
@@ -249,17 +249,16 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
}
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world);
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world());
List<BlockPos> locs = locs2
.stream()
.distinct()
// remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
.filter(pos -> ctx.world().getChunk(pos) instanceof EmptyChunk || 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.bsi, pos))
.filter(pos -> MineProcess.plausibleToBreak(ctx.bsi(), pos))
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
.collect(Collectors.toList());
@@ -32,15 +32,6 @@ import net.minecraft.world.GameType;
import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType;
/**
* Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific
* seed, setting a specified goal, and only allowing a certain amount of ticks to pass before the pathing test is
* considered a failure. In order to test locally, docker may be used, or through an IDE: Create a run config which runs
* in a separate directory from the primary one (./run), and set the enrivonmental variable {@code BARITONE_AUTO_TEST}
* to {@code true}.
*
* @author leijurv, Brady
*/
public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
public static final BaritoneAutoTest INSTANCE = new BaritoneAutoTest();
@@ -23,10 +23,16 @@ import baritone.api.utils.IPlayerContext;
public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper {
public static final double DEFAULT_PRIORITY = 0;
protected final Baritone baritone;
protected final IPlayerContext ctx;
private final double priority;
public BaritoneProcessHelper(Baritone baritone) {
this(baritone, DEFAULT_PRIORITY);
}
public BaritoneProcessHelper(Baritone baritone, double priority) {
this.baritone = baritone;
this.ctx = baritone.getPlayerContext();
@@ -34,6 +40,11 @@ public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper
baritone.getPathingControlManager().registerProcess(this);
}
@Override
public Baritone associatedWith() {
return baritone;
}
@Override
public boolean isTemporary() {
return false;
@@ -17,6 +17,8 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand;
@@ -29,6 +31,11 @@ import net.minecraft.util.math.RayTraceResult;
*/
public final class BlockBreakHelper implements Helper {
/**
* The last block that we tried to break, if this value changes
* between attempts, then we re-initialize the breaking process.
*/
private BlockPos lastBlock;
private boolean didBreakLastTick;
private IPlayerContext playerContext;
@@ -38,20 +45,42 @@ public final class BlockBreakHelper implements Helper {
}
public void tryBreakBlock(BlockPos pos, EnumFacing side) {
if (!pos.equals(lastBlock)) {
playerContext.playerController().clickBlock(pos, side);
}
if (playerContext.playerController().onPlayerDamageBlock(pos, side)) {
playerContext.player().swingArm(EnumHand.MAIN_HAND);
}
lastBlock = pos;
}
public void stopBreakingBlock() {
// The player controller will never be null, but the player can be
if (playerContext.player() != null) {
if (playerContext.playerController() != null) {
playerContext.playerController().resetBlockRemoving();
}
lastBlock = null;
}
private boolean fakeBreak() {
if (playerContext != BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()) {
// for a non primary player, we need to fake break always, CLICK_LEFT has no effect
return true;
}
if (!Baritone.settings().leftClickWorkaround.get()) {
// if this setting is false, we CLICK_LEFT regardless of gui status
return false;
}
return mc.currentScreen != null;
}
public boolean tick(boolean isLeftClick) {
if (!fakeBreak()) {
if (didBreakLastTick) {
stopBreakingBlock();
}
return isLeftClick;
}
public void tick(boolean isLeftClick) {
RayTraceResult trace = playerContext.objectMouseOver();
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
@@ -62,5 +91,6 @@ public final class BlockBreakHelper implements Helper {
stopBreakingBlock();
didBreakLastTick = false;
}
return false; // fakeBreak is true so no matter what we aren't forcing CLICK_LEFT
}
}
@@ -46,8 +46,6 @@ public class BlockStateInterface {
private Chunk prev = null;
private CachedRegion prevCached = null;
private final boolean useTheRealWorld;
private static final IBlockState AIR = Blocks.AIR.getDefaultState();
public BlockStateInterface(IPlayerContext ctx) {
@@ -66,7 +64,6 @@ public class BlockStateInterface {
} else {
this.loadedChunks = worldLoaded; // this will only be used on the main thread
}
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.get();
if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) {
throw new IllegalStateException();
}
@@ -97,7 +94,7 @@ public class BlockStateInterface {
return AIR;
}
if (useTheRealWorld) {
if (!Baritone.settings().pathThroughCachedOnly.get()) {
Chunk cached = prev;
// there's great cache locality in block state lookups
// generally it's within each movement
@@ -77,8 +77,6 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
"costs - (debug) all movement costs from current location\n" +
"damn - Daniel ";
private static final String COMMAND_PREFIX = "#";
public ExampleBaritoneControl(Baritone baritone) {
super(baritone);
}
@@ -90,20 +88,17 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
}
String msg = event.getMessage();
if (Baritone.settings().prefix.get()) {
if (msg.startsWith(COMMAND_PREFIX)) {
if (!runCommand(msg.substring(COMMAND_PREFIX.length()))) {
logDirect("Invalid command");
}
event.cancel(); // always cancel if using prefix
}
} else {
if (runCommand(msg)) {
event.cancel();
if (!msg.startsWith("#")) {
return;
}
msg = msg.substring(1);
}
if (runCommand(msg)) {
event.cancel();
}
}
public boolean runCommand(String msg0) { // you may think this can be private, but impcat calls it from .b =)
public boolean runCommand(String msg0) {
String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL
PathingBehavior pathingBehavior = baritone.getPathingBehavior();
CustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess();
@@ -126,7 +121,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
for (String line : HELP_MSG.split("\n")) {
logDirect(line);
}
return true;
return false;
}
if (msg.contains(" ")) {
String[] data = msg.split(" ");
@@ -206,6 +201,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} else if (pathingBehavior.isPathing()) {
logDirect("Currently executing a path. Please cancel it first.");
} else {
baritone.fitmc();
customGoalProcess.setGoalAndPath(pathingBehavior.getGoal());
}
return true;
@@ -18,15 +18,12 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.TickEvent;
import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input;
import baritone.behavior.Behavior;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding;
import net.minecraft.util.MovementInput;
import net.minecraft.util.MovementInputFromOptions;
import org.lwjgl.input.Keyboard;
import java.util.HashMap;
import java.util.Map;
@@ -60,18 +57,8 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
* @return Whether or not it is being forced down
*/
@Override
public final Boolean isInputForcedDown(KeyBinding key) {
Input input = Input.getInputForBind(key);
if (input == null || !inControl()) {
return null;
}
if (input == Input.CLICK_LEFT) {
return false;
}
if (input == Input.CLICK_RIGHT) {
return isInputForcedDown(Input.CLICK_RIGHT);
}
return null;
public final boolean isInputForcedDown(KeyBinding key) {
return isInputForcedDown(Input.getInputForBind(key));
}
/**
@@ -104,25 +91,29 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
this.inputForceStateMap.clear();
}
@Override
public final void onProcessKeyBinds() {
// Simulate the key being held down this tick
for (Input input : Input.values()) {
KeyBinding keyBinding = input.getKeyBinding();
if (isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
int keyCode = keyBinding.getKeyCode();
if (keyCode < Keyboard.KEYBOARD_SIZE) {
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
}
}
}
}
@Override
public final void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
return;
}
blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT));
MovementInput desired = inControl()
? new PlayerMovementInput(this)
: new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
if (ctx.player().movementInput.getClass() != desired.getClass()) {
ctx.player().movementInput = desired; // only set it if it was previously incorrect
// gotta do it this way, or else it constantly thinks you're beginning a double tap W sprint lol
}
}
private boolean inControl() {
return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone();
boolean stillClick = blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT));
setInputForceState(Input.CLICK_LEFT, stillClick);
}
public BlockBreakHelper getBlockBreakHelper() {
@@ -216,9 +216,8 @@ public final class PathRenderer implements Helper {
double renderPosX = player.lastTickPosX + (player.posX - player.lastTickPosX) * (double) partialTicks;
double renderPosY = player.lastTickPosY + (player.posY - player.lastTickPosY) * (double) partialTicks;
double renderPosZ = player.lastTickPosZ + (player.posZ - player.lastTickPosZ) * (double) partialTicks;
BlockStateInterface bsi = new BlockStateInterface(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()); // TODO this assumes same dimension between primary baritone and render view? is this safe?
positions.forEach(pos -> {
IBlockState state = bsi.get0(pos);
IBlockState state = BlockStateInterface.get(BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext(), pos);
AxisAlignedBB toDraw;
if (state.getBlock().equals(Blocks.AIR)) {
toDraw = Blocks.DIRT.getDefaultState().getSelectedBoundingBox(player.world, pos);
@@ -29,7 +29,7 @@ import baritone.pathing.path.PathExecutor;
import net.minecraft.util.math.BlockPos;
import java.util.*;
import java.util.stream.Stream;
import java.util.stream.Collectors;
public class PathingControlManager implements IPathingControlManager {
private final Baritone baritone;
@@ -64,7 +64,8 @@ public class PathingControlManager implements IPathingControlManager {
command = null;
for (IBaritoneProcess proc : processes) {
proc.onLostControl();
if (proc.isActive() && !proc.isTemporary()) { // it's okay only for a temporary thing (like combat pause) to maintain control even if you say to cancel
if (proc.isActive() && !proc.isTemporary()) { // it's okay for a temporary thing (like combat pause) to maintain control even if you say to cancel
// but not for a non temporary thing
throw new IllegalStateException(proc.displayName());
}
}
@@ -82,12 +83,11 @@ public class PathingControlManager implements IPathingControlManager {
public void preTick() {
inControlLastTick = inControlThisTick;
PathingBehavior p = baritone.getPathingBehavior();
command = executeProcesses();
command = doTheStuff();
if (command == null) {
p.cancelSegmentIfSafe();
return;
}
PathingBehavior p = baritone.getPathingBehavior();
switch (command.commandType) {
case REQUEST_PAUSE:
p.requestPause();
@@ -170,30 +170,32 @@ public class PathingControlManager implements IPathingControlManager {
}
public PathingCommand executeProcesses() {
Stream<IBaritoneProcess> inContention = processes.stream()
.filter(IBaritoneProcess::isActive)
.sorted(Comparator.comparingDouble(IBaritoneProcess::priority).reversed());
Iterator<IBaritoneProcess> iterator = inContention.iterator();
while (iterator.hasNext()) {
IBaritoneProcess proc = iterator.next();
PathingCommand exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel());
if (exec == null) {
if (proc.isActive()) {
throw new IllegalStateException(proc.displayName() + " returned null PathingCommand");
public PathingCommand doTheStuff() {
List<IBaritoneProcess> inContention = processes.stream().filter(IBaritoneProcess::isActive).sorted(Comparator.comparingDouble(IBaritoneProcess::priority)).collect(Collectors.toList());
boolean found = false;
boolean cancelOthers = false;
PathingCommand exec = null;
for (int i = inContention.size() - 1; i >= 0; i--) { // truly a gamer moment
IBaritoneProcess proc = inContention.get(i);
if (found) {
if (cancelOthers) {
proc.onLostControl();
}
proc.onLostControl();
} else {
inControlThisTick = proc;
if (!proc.isTemporary()) {
iterator.forEachRemaining(IBaritoneProcess::onLostControl);
exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel());
if (exec == null) {
if (proc.isActive()) {
throw new IllegalStateException(proc.displayName());
}
proc.onLostControl();
continue;
}
return exec;
//System.out.println("Executing command " + exec.commandType + " " + exec.goal + " from " + proc.displayName());
inControlThisTick = proc;
found = true;
cancelOthers = !proc.isTemporary();
}
}
return null;
return exec;
}
}
@@ -1,57 +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.utils;
import baritone.api.utils.input.Input;
import net.minecraft.util.MovementInput;
public class PlayerMovementInput extends MovementInput {
private final InputOverrideHandler handler;
public PlayerMovementInput(InputOverrideHandler handler) {
this.handler = handler;
}
public void updatePlayerMoveState() {
this.moveStrafe = 0.0F;
this.moveForward = 0.0F;
jump = handler.isInputForcedDown(Input.JUMP); // oppa
if (this.forwardKeyDown = handler.isInputForcedDown(Input.MOVE_FORWARD)) {
this.moveForward++;
}
if (this.backKeyDown = handler.isInputForcedDown(Input.MOVE_BACK)) {
this.moveForward--;
}
if (this.leftKeyDown = handler.isInputForcedDown(Input.MOVE_LEFT)) {
this.moveStrafe++;
}
if (this.rightKeyDown = handler.isInputForcedDown(Input.MOVE_RIGHT)) {
this.moveStrafe--;
}
if (this.sneak = handler.isInputForcedDown(Input.SNEAK)) {
this.moveStrafe *= 0.3D;
this.moveForward *= 0.3D;
}
}
}
+7 -7
View File
@@ -103,7 +103,7 @@ public class ToolSet {
IBlockState blockState = b.getDefaultState();
for (byte i = 0; i < 9; i++) {
ItemStack itemStack = player.inventory.getStackInSlot(i);
double v = calculateSpeedVsBlock(itemStack, blockState);
double v = calculateStrVsBlock(itemStack, blockState);
if (v > value) {
value = v;
best = i;
@@ -128,18 +128,17 @@ public class ToolSet {
*/
private double getBestDestructionTime(Block b) {
ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b));
return calculateSpeedVsBlock(stack, b.getDefaultState());
return calculateStrVsBlock(stack, b.getDefaultState());
}
/**
* Calculates how long would it take to mine the specified block given the best tool
* in this toolset is used. A negative value is returned if the specified block is unbreakable.
*
* @param item the item to mine it with
* @param state the blockstate to be mined
* @return how long it would take in ticks
*/
public static double calculateSpeedVsBlock(ItemStack item, IBlockState state) {
public static double calculateStrVsBlock(ItemStack item, IBlockState state) {
float hardness = state.getBlockHardness(null, null);
if (hardness < 0) {
return -1;
@@ -155,10 +154,11 @@ public class ToolSet {
speed /= hardness;
if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) {
return speed / 30;
speed /= 30;
} else {
return speed / 100;
speed /= 100;
}
return speed;
}
/**
@@ -180,7 +180,7 @@ public class ToolSet {
speed *= 0.09;
break;
case 2:
speed *= 0.0027; // you might think that 0.09*0.3 = 0.027 so that should be next, that would make too much sense. it's 0.0027.
speed *= 0.0027;
break;
default:
speed *= 0.00081;
@@ -23,12 +23,16 @@ import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.IPlayerContext;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import java.util.List;
public final class Favoring {
private List<Avoidance> avoidances;
private final Long2DoubleOpenHashMap favorings;
public Favoring(IPlayerContext ctx, IPath previous) {
this(previous);
for (Avoidance avoid : Avoidance.create(ctx)) {
avoidances = Avoidance.create(ctx);
for (Avoidance avoid : avoidances) {
avoid.applySpherical(favorings);
}
System.out.println("Favoring size: " + favorings.size());
@@ -17,7 +17,6 @@
package baritone.utils.pathing;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
@@ -27,10 +26,7 @@ import net.minecraft.util.math.BlockPos;
public abstract class PathBase implements IPath {
@Override
public PathBase cutoffAtLoadedChunks(Object bsi0) { // <-- cursed cursed cursed
if (!Baritone.settings().cutoffAtLoadBoundary.get()) {
return this;
}
public PathBase cutoffAtLoadedChunks(Object bsi0) {
BlockStateInterface bsi = (BlockStateInterface) bsi0;
for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i);
@@ -20,14 +20,14 @@ package baritone.utils.player;
import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldData;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.IPlayerController;
import baritone.utils.Helper;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World;
/**
* Implementation of {@link IPlayerContext} that provides information about the primary player.
* Implementation of {@link IPlayerContext} that provides information about the local player.
*
* @author Brady
* @since 11/12/2018
@@ -42,8 +42,8 @@ public enum PrimaryPlayerContext implements IPlayerContext, Helper {
}
@Override
public IPlayerController playerController() {
return PrimaryPlayerController.INSTANCE;
public PlayerControllerMP playerController() {
return mc.playerController;
}
@Override
@@ -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.utils.player;
import baritone.api.utils.IPlayerController;
import baritone.utils.Helper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType;
/**
* Implementation of {@link IPlayerController} that chains to the primary player controller's methods
*
* @author Brady
* @since 12/14/2018
*/
public enum PrimaryPlayerController implements IPlayerController, Helper {
INSTANCE;
@Override
public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) {
return mc.playerController.onPlayerDamageBlock(pos, side);
}
@Override
public void resetBlockRemoving() {
mc.playerController.resetBlockRemoving();
}
@Override
public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) {
return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player);
}
@Override
public void setGameType(GameType type) {
mc.playerController.setGameType(type);
}
@Override
public GameType getGameType() {
return mc.playerController.getCurrentGameType();
}
}
@@ -0,0 +1,70 @@
/*
* 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.utils.resource;
import net.minecraft.client.resources.IResourcePack;
import net.minecraft.client.resources.data.IMetadataSection;
import net.minecraft.client.resources.data.MetadataSerializer;
import net.minecraft.util.ResourceLocation;
import java.awt.image.BufferedImage;
import java.io.InputStream;
import java.util.Collections;
import java.util.Set;
/**
* @author Brady
* @since 12/15/2018
*/
@SuppressWarnings("NullableProblems")
public class BaritoneResourcePack implements IResourcePack {
@Override
public InputStream getInputStream(ResourceLocation location) {
return getResourceStream(location);
}
@Override
public boolean resourceExists(ResourceLocation location) {
return getResourceStream(location) != null;
}
@Override
public Set<String> getResourceDomains() {
return Collections.singleton("baritone");
}
@Override
public <T extends IMetadataSection> T getPackMetadata(MetadataSerializer metadataSerializer, String metadataSectionName) {
return null;
}
@Override
public BufferedImage getPackImage() {
return null;
}
@Override
public String getPackName() {
return "baritone";
}
private InputStream getResourceStream(ResourceLocation location) {
return BaritoneResourcePack.class.getResourceAsStream("/assets/" + location.getNamespace() + "/" + location.getPath());
}
}
@@ -0,0 +1,10 @@
{
"fitmc_intro": {
"category": "master",
"sounds": [
{
"name": "baritone:fitmc/intro"
}
]
}
}
+1 -1
View File
@@ -44,4 +44,4 @@ public class CachedRegionTest {
}
}
}
}
}
@@ -36,39 +36,24 @@ public class OpenSetsTest {
this.size = size;
}
private static final ArrayList<Long> insertions = new ArrayList<>();
private static final ArrayList<Long> removal1 = new ArrayList<>();
private static final ArrayList<Long> removal2 = new ArrayList<>();
@Parameterized.Parameters
public static Collection<Object[]> data() {
ArrayList<Object[]> testSizes = new ArrayList<>();
/*for (int size = 1; size < 20; size++) {
for (int size = 1; size < 20; size++) {
testSizes.add(new Object[]{size});
}
for (int size = 100; size <= 1000; size += 100) {
testSizes.add(new Object[]{size});
}
testSizes.add(new Object[]{5000});
testSizes.add(new Object[]{10000});*/
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{100000});
testSizes.add(new Object[]{10000});
return testSizes;
}
private static void removeAndTest(int amount, IOpenSet[] test, Optional<Collection<PathNode>> mustContain) {
double[][] results = new double[test.length][amount];
for (int i = 0; i < test.length; i++) {
long before = System.nanoTime();
long before = System.nanoTime() / 1000000L;
for (int j = 0; j < amount; j++) {
PathNode pn = test[i].removeLowest();
if (mustContain.isPresent() && !mustContain.get().contains(pn)) {
@@ -76,13 +61,7 @@ public class OpenSetsTest {
}
results[i][j] = pn.combinedCost;
}
long time = System.nanoTime() - before;
System.out.println(test[i].getClass() + " " + (time));
if (mustContain.isPresent()) {
removal1.add(time);
} else {
removal2.add(time);
}
System.out.println(test[i].getClass() + " " + (System.nanoTime() / 1000000L - before));
}
for (int j = 0; j < amount; j++) {
for (int i = 1; i < test.length; i++) {
@@ -96,16 +75,10 @@ public class OpenSetsTest {
@Test
public void testSize() {
try {
System.gc();
Thread.sleep(1000L);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Testing size " + size);
// Include LinkedListOpenSet even though it's not performant because I absolutely trust that it behaves properly
// I'm really testing the heap implementations against it as the ground truth
IOpenSet[] test = new IOpenSet[]{new BinaryHeapOpenSet()/*, new LinkedListOpenSet()*/};
IOpenSet[] test = new IOpenSet[]{new BinaryHeapOpenSet(), new LinkedListOpenSet()};
for (IOpenSet set : test) {
assertTrue(set.isEmpty());
}
@@ -143,12 +116,10 @@ public class OpenSetsTest {
System.out.println("Insertion");
for (IOpenSet set : test) {
long before = System.nanoTime();
long before = System.nanoTime() / 1000000L;
for (int i = 0; i < size; i++)
set.insert(toInsert[i]);
long time = System.nanoTime() - before;
System.out.println(set.getClass() + " " + (time));
insertions.add(time);
System.out.println(set.getClass() + " " + (System.nanoTime() / 1000000L - before));
//all three take either 0 or 1ms to insert up to 10,000 nodes
//linkedlist takes 0ms most often (because there's no array resizing or allocation there, just pointer shuffling)
}
@@ -195,18 +166,5 @@ public class OpenSetsTest {
for (IOpenSet set : test) {
assertTrue(set.isEmpty());
}
printo(insertions);
printo(removal1);
printo(removal2);
}
private static void printo(ArrayList<Long> data) {
if (data.size() < 3) {
return;
}
System.out.println(data.subList(2, data.size()).stream().mapToLong(x -> x).average().getAsDouble() / 1000000D);
}
}
}
@@ -47,4 +47,4 @@ public class GoalGetToBlockTest {
}
assertTrue(acceptableOffsets.toString(), acceptableOffsets.isEmpty());
}
}
}
@@ -48,4 +48,4 @@ public class ActionCostsTest {
return fallDistance;
}
}
}
@@ -136,4 +136,4 @@ public class BetterBlockPosTest {
long after2 = System.nanoTime() / 1000000L;
System.out.println((after1 - before1) + " " + (after2 - before2));
}
}
}
@@ -29,4 +29,4 @@ public class PathingBlockTypeTest {
assertTrue(type == PathingBlockType.fromBits(bits[0], bits[1]));
}
}
}
}