Compare commits

...

75 Commits

Author SHA1 Message Date
Leijurv e661330fb6 v1.0.0-hotfix-4 2018-12-04 14:19:20 -08:00
Leijurv 9b13380b29 fixed switched block states in traverse 2018-12-04 14:18:32 -08:00
Leijurv b48444da8c don't splice if not on ground 2018-12-01 10:48:43 -08:00
Leijurv 11a4225eaf fix inability to break fire 2018-11-29 20:10:04 -08:00
Leijurv 0611e3088e cherry pick flowing cache fix 2018-11-28 16:04:13 -08:00
Leijurv 73628f09c1 don't crash when Auto mine does weird things 2018-11-27 10:23:26 -08:00
Leijurv a907746f53 only walk through supported snow, fixes #276 2018-11-26 15:33:33 -08:00
Leijurv 8189e90569 unable to start a parkour jump from stairs 2018-11-26 15:19:03 -08:00
Leijurv 9f83677df9 favored lookup performance 2018-11-26 15:11:36 -08:00
Leijurv 5265c46f60 over 10k less objects per second 2018-11-26 15:08:37 -08:00
Leijurv 6d37e14b0e thousands here too, on long paths 2018-11-26 15:07:38 -08:00
Leijurv fbecff52af believe it or not, this saves thousands of object allocations per second 2018-11-26 15:07:29 -08:00
Leijurv 4af14cf0a6 unneeded, and was allocating thousands of sets a second 2018-11-26 15:07:12 -08:00
Leijurv 16a201255e fix behavior around cocoa pods and vines, fixes #277 2018-11-26 15:03:59 -08:00
Leijurv 22bb9f0ec8 v1.0.0-hotfix-3 2018-11-12 09:07:48 -08:00
Leijurv 654ac1075a wait a tick until objectMouseOver matches, fixes #254 2018-11-10 09:26:32 -08:00
Leijurv ffc050668b fix cherry pick merge errors 2018-11-07 10:01:58 -08:00
Leijurv 80f65452e1 make sure to pick up dropped items while mining, fixes #170 2018-11-07 09:56:47 -08:00
Leijurv c614d7ec6a fix stupid minebehavior bug 2018-11-03 20:25:09 -07:00
Leijurv c37a5ba956 revamp readme 2018-11-02 16:23:57 -07:00
Leijurv da5969c2fd shouldnt have taken this long to figure that out 2018-11-01 20:58:48 -07:00
Leijurv 990107a1fa simplify 2018-11-01 20:27:34 -07:00
Leijurv 42eb86b624 useless check? 2018-11-01 15:41:53 -07:00
Leijurv b65a199e54 move all checks from BlockStateInterface to MovementHelper 2018-11-01 15:36:32 -07:00
Leijurv 88e3bcdf63 what 2018-11-01 15:32:58 -07:00
Leijurv 0fbfa32e6b fix exception in pathfinder 2018-11-01 15:30:33 -07:00
Leijurv 20405716bc fix impact 4.4 compatibility and add help message 2018-11-01 14:07:08 -07:00
Leijurv 8da7406e8f green 2018-10-31 20:37:18 -07:00
Leijurv 97fd3df8f7 minecraft version badge 2018-10-30 19:06:42 -07:00
Leijurv b9b33b5351 move calculation context construction to main thread 2018-10-29 18:58:59 -07:00
Brady 19ecb1bbb3 Merge LocationTrackingBehavior into MemoryBehavior
Fixes #242
2018-10-29 16:43:03 -05:00
Leijurv f6043f4ac6 changed wording 2018-10-28 16:44:56 -07:00
Brady ed1941abdb Fix desynchronized allowFlying state 2018-10-28 18:38:23 -05:00
Leijurv 24d24728dc intellij be like 2018-10-28 16:05:08 -07:00
Leijurv 77db4cd19f codacy 2018-10-28 15:24:52 -07:00
Leijurv adbb03e5cb unused lol 2018-10-28 15:24:23 -07:00
Leijurv f0226f1ea7 brady doesn't know how to do imports 2018-10-28 15:23:34 -07:00
Leijurv be5df2677b finally add shulkers lol 2018-10-28 13:55:03 -07:00
Brady 3d4a856bb2 Remove unnecessary casts 2018-10-27 23:21:30 -05:00
Leijurv 1b1233d26a only one singleton 2018-10-27 18:45:17 -07:00
Leijurv c4b0e0a810 codady submission complete 2018-10-27 16:18:03 -07:00
Leijurv 1dee8ef355 completely submitting to codacy 2018-10-27 14:41:25 -07:00
Leijurv 8cee173f92 appease codacy some more 2018-10-27 14:16:34 -07:00
Brady 19e0e6d962 Feed codacy 2018-10-27 14:38:10 -05:00
Leijurv ef8fd70475 add some more badges for no reason lol 2018-10-27 09:25:53 -07:00
Leijurv 6df05f4b7f add link to my vid 2018-10-27 08:37:30 -07:00
Brady 4e1491a0cc Rename xrayFor to searchWorld 2018-10-26 13:30:16 -05:00
leijurv 55091154c4 start on legitMine 2018-10-25 21:22:00 -07:00
leijurv a0b1cb2993 preliminary refactoring 2018-10-25 20:09:06 -07:00
Leijurv 7617081637 no longer needed 2018-10-24 23:22:19 -07:00
Leijurv 96e7f37799 add link to adovin's video 2018-10-23 20:41:35 -07:00
Leijurv a0bf22de86 Merge pull request #233 from ave4224/toolkit
Toolkit fixes
2018-10-22 21:43:42 -07:00
ave4224 9a1aecc002 tool set, fixes #227 2018-10-23 00:41:59 -04:00
Brady ad941fcbb2 Clarify anti nudge 2018-10-22 18:02:18 -05:00
Leijurv e5ca30dc26 forgot that one 2018-10-22 14:04:19 -07:00
Leijurv a23eadf5cf Merge pull request #235 from 0-x-2-2/patch-1
Fixed serious issue.
2018-10-22 12:46:17 -07:00
Leijurv 82417f4f85 comment to explain weird thing 2018-10-22 12:42:08 -07:00
0x22 af788133c2 Fixed serious issue.
Determinizer description was incorrect.
2018-10-22 15:42:05 -04:00
Leijurv a6dc156a79 bump version to match build gradle 2018-10-21 14:24:23 -07:00
Leijurv 25bebdc172 leftClickCounter shadow appears to be unneeded 2018-10-20 20:33:49 -07:00
Leijurv b55d96169f update some documentation 2018-10-19 21:15:37 -07:00
Leijurv 1a809fa7a3 dispatch path events from main thread instead of calculation thread 2018-10-18 15:04:40 -07:00
Leijurv 313a5fddbe add release badge 2018-10-18 14:36:14 -07:00
Leijurv 732d806820 allow cutting onto next path one movement earlier 2018-10-17 12:16:03 -07:00
Leijurv 11ed8a2f21 rearrange fields and constructors 2018-10-16 20:05:18 -07:00
Leijurv 3aa8f51015 print shasums on build 2018-10-16 17:00:37 -07:00
Leijurv 85b038dada v1.0.0-hotfix-2 2018-10-16 16:03:51 -07:00
Leijurv dd25527a62 pillar fixes for ncp 2018-10-16 14:21:27 -07:00
Leijurv ac372bc6fc v1.0.0-hotfix-1 2018-10-16 11:32:44 -07:00
Leijurv 63ce4fe0bd don't crash on empty region 2018-10-16 11:32:27 -07:00
Leijurv 398169f68e special case for damn daniel 2018-10-16 11:13:35 -07:00
Leijurv 46a24af373 cancel chat event 2018-10-16 11:13:08 -07:00
Leijurv 0cd9bb658f keep ExampleBaritoneControl 2018-10-16 11:04:49 -07:00
Leijurv b0678fd259 better control 2018-10-16 10:47:44 -07:00
Leijurv 9cb4a1779e fix placement rotation during parkour 2018-10-15 20:37:10 -07:00
45 changed files with 870 additions and 669 deletions
+4 -4
View File
@@ -15,10 +15,10 @@ RUN apt install -qq --force-yes mesa-utils libgl1-mesa-glx libxcursor1 libxrandr
COPY . /code
# this .deb is specially patched to support lwjgl
# source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173
RUN dpkg -i /code/scripts/xvfb_1.16.4-1_amd64.deb
WORKDIR /code
# this .deb is specially patched to support lwjgl
# source: https://github.com/tectonicus/tectonicus/issues/60#issuecomment-154239173
RUN dpkg -i scripts/xvfb_1.16.4-1_amd64.deb
RUN ./gradlew build
+4 -6
View File
@@ -3,6 +3,8 @@ Impact 4.4 has Baritone included.
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.
@@ -12,7 +14,7 @@ There are some basic steps to getting Baritone setup with Impact.
- How to use Baritone
## Acquiring a build of Baritone
There are 3 methods of acquiring a build of Baritone (While it is still in development)
There are two methods of acquiring a build of Baritone
### Official Release (Not always up to date)
https://github.com/cabaletta/baritone/releases
@@ -33,10 +35,6 @@ command line
- Mac/Linux: ``./gradlew build``
- The build should be exported into ``/build/libs/baritone-X.Y.Z.jar``
### Cutting Edge Release
If you want to trust @Plutie#9079, you can download an automatically generated build of the latest commit
from his Jenkins server, found <a href="https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/">here</a>.
## Placing Baritone in the libraries directory
``/libraries`` is a neat directory in your <a href="https://minecraft.gamepedia.com/.minecraft">Minecraft Installation Directory</a>
that contains all of the dependencies that are required from the game and some mods. This is where we will be
@@ -83,7 +81,7 @@ The final step is "registering" the Baritone library with Impact, so that it loa
"name": "cabaletta:baritone:X.Y.Z"
},
{
"name": "com.github.ImpactDevelopment:SimpleTweaker:1.1",
"name": "com.github.ImpactDevelopment:SimpleTweaker:1.2",
"url": "https://impactdevelopment.github.io/maven/"
},
```
+18 -15
View File
@@ -1,14 +1,16 @@
# Baritone
[![Build Status](https://travis-ci.com/cabaletta/baritone.svg?branch=master)](https://travis-ci.com/cabaletta/baritone)
[![Release](https://img.shields.io/github/release/cabaletta/baritone.svg)](https://github.com/cabaletta/baritone/releases)
[![License](https://img.shields.io/github/license/cabaletta/baritone.svg)](LICENSE)
[![Codacy Badge](https://api.codacy.com/project/badge/Grade/a73d037823b64a5faf597a18d71e3400)](https://www.codacy.com/app/leijurv/baritone?utm_source=github.com&amp;utm_medium=referral&amp;utm_content=cabaletta/baritone&amp;utm_campaign=Badge_Grade)
<!-- Unofficial Jenkins: [![Build Status](https://plutiejenkins.leijurv.com/job/baritone/badge/icon)](https://plutiejenkins.leijurv.com/job/baritone/lastSuccessfulBuild/) -->
[![HitCount](http://hits.dwyl.com/cabaletta/baritone.svg)](http://hits.dwyl.com/cabaletta/baritone)
[![contributions welcome](https://img.shields.io/badge/contributions-welcome-brightgreen.svg?style=flat)](https://github.com/cabaletta/baritone/issues)
[![Minecraft](https://img.shields.io/badge/MC-1.12.2-green.svg)](https://minecraft.gamepedia.com/1.12.2)
A Minecraft pathfinder bot. This project is an updated version of [MineBot](https://github.com/leijurv/MineBot/),
the original version of the bot for Minecraft 1.8, rebuilt for 1.12.2. 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).
Baritone is the pathfinding system used in [Impact](https://impactdevelopment.github.io/) since 4.4.
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.
Here are some links to help to get started:
@@ -20,29 +22,30 @@ There's also some useful information down below
# Setup
## IntelliJ's Gradle UI
- Open the project in IntelliJ as a Gradle project
- Run the Gradle task `setupDecompWorkspace`
- Run the Gradle task `genIntellijRuns`
- Refresh the Gradle project (or just restart IntelliJ)
- Select the "Minecraft Client" launch config and run
## Command Line
On Mac OSX and Linux, use `./gradlew` instead of `gradlew`.
Running Baritone:
```
$ gradlew run
$ gradlew runClient
```
Setting up for IntelliJ:
Building Baritone:
```
$ gradlew setupDecompWorkspace
$ gradlew --refresh-dependencies
$ gradlew genIntellijRuns
$ gradlew build
```
For example, to replace out Impact 4.4's Baritone build with a customized one, 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 task `setupDecompWorkspace`
- Run the Gradle task `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)
+1 -1
View File
@@ -16,7 +16,7 @@
*/
group 'baritone'
version '1.0.0'
version '1.0.0-hotfix-4'
buildscript {
repositories {
@@ -34,9 +34,9 @@ import java.util.List;
*/
class BaritoneGradleTask extends DefaultTask {
static final JsonParser PARSER = new JsonParser();
protected static final JsonParser PARSER = new JsonParser();
static final String
protected static final String
PROGUARD_ZIP = "proguard.zip",
PROGUARD_JAR = "proguard.jar",
PROGUARD_CONFIG_TEMPLATE = "scripts/proguard.pro",
@@ -54,10 +54,10 @@ class BaritoneGradleTask extends DefaultTask {
ARTIFACT_API = "%s-api-%s.jar",
ARTIFACT_STANDALONE = "%s-standalone-%s.jar";
String artifactName, artifactVersion;
Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
protected String artifactName, artifactVersion;
protected Path artifactPath, artifactUnoptimizedPath, artifactApiPath, artifactStandalonePath, proguardOut;
void verifyArtifacts() throws Exception {
protected void verifyArtifacts() throws IllegalStateException {
this.artifactName = getProject().getName();
this.artifactVersion = getProject().getVersion().toString();
@@ -69,34 +69,34 @@ class BaritoneGradleTask extends DefaultTask {
this.proguardOut = this.getTemporaryFile(PROGUARD_EXPORT_PATH);
if (!Files.exists(this.artifactPath)) {
throw new Exception("Artifact not found! Run build first!");
throw new IllegalStateException("Artifact not found! Run build first!");
}
}
void write(InputStream stream, Path file) throws Exception {
protected void write(InputStream stream, Path file) throws Exception {
if (Files.exists(file)) {
Files.delete(file);
}
Files.copy(stream, file);
}
String formatVersion(String string) {
protected String formatVersion(String string) {
return String.format(string, this.artifactName, this.artifactVersion);
}
Path getRelativeFile(String file) {
protected Path getRelativeFile(String file) {
return Paths.get(new File(file).getAbsolutePath());
}
Path getTemporaryFile(String file) {
protected Path getTemporaryFile(String file) {
return Paths.get(new File(getTemporaryDir(), file).getAbsolutePath());
}
Path getBuildFile(String file) {
protected Path getBuildFile(String file) {
return getRelativeFile("build/libs/" + file);
}
JsonElement readJson(List<String> lines) {
protected JsonElement readJson(List<String> lines) {
return PARSER.parse(String.join("\n", lines));
}
}
@@ -62,6 +62,8 @@ public class CreateDistTask extends BaritoneGradleTask {
.map(path -> sha1(path) + " " + path.getFileName().toString())
.collect(Collectors.toList());
shasum.forEach(System.out::println);
// Write the checksums to a file
Files.write(getRelativeFile("dist/checksums.txt"), shasum);
}
@@ -74,7 +76,7 @@ public class CreateDistTask extends BaritoneGradleTask {
return DatatypeConverter.printHexBinary(SHA1_DIGEST.digest(Files.readAllBytes(path))).toLowerCase();
} catch (Exception e) {
// haha no thanks
throw new RuntimeException(e);
throw new IllegalStateException(e);
}
}
}
@@ -241,7 +241,7 @@ public class ProguardTask extends BaritoneGradleTask {
// Halt the current thread until the process is complete, if the exit code isn't 0, throw an exception
int exitCode = p.waitFor();
if (exitCode != 0) {
throw new Exception("Proguard exited with code " + exitCode);
throw new IllegalStateException("Proguard exited with code " + exitCode);
}
}
@@ -32,7 +32,7 @@ import java.util.jar.JarOutputStream;
import java.util.stream.Collectors;
/**
* Make a .jar file deterministic by sorting all entries by name, and setting all the last modified times to 0.
* Make a .jar file deterministic by sorting all entries by name, and setting all the last modified times to 42069.
* This makes the build 100% reproducible since the timestamp when you built it no longer affects the final file.
*
* @author leijurv
+5
View File
@@ -13,9 +13,14 @@
-repackageclasses 'baritone'
-keep class baritone.api.** { *; } # this is the keep api
# service provider needs these class names
-keep class baritone.BaritoneProvider
-keep class baritone.api.IBaritoneProvider
# hack
-keep class baritone.utils.ExampleBaritoneControl { *; }
# setting names are reflected from field names, so keep field names
-keepclassmembers class baritone.api.Settings {
public <fields>;
+17
View File
@@ -376,6 +376,11 @@ public class Settings {
*/
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 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.
* <p>
@@ -396,6 +401,18 @@ public class Settings {
*/
public Setting<Integer> axisHeight = new Setting<>(120);
/**
* 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 off
*/
public Setting<Boolean> legitMine = new Setting<>(false);
/**
* What Y level to go to for legit strip mining
*/
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
@@ -105,8 +105,9 @@ public interface IPath {
default double ticksRemainingFrom(int pathPosition) {
double sum = 0;
//this is fast because we aren't requesting recalculation, it's just cached
for (int i = pathPosition; i < movements().size(); i++) {
sum += movements().get(i).getCost();
List<IMovement> movements = movements();
for (int i = pathPosition; i < movements.size(); i++) {
sum += movements.get(i).getCost();
}
return sum;
}
@@ -30,14 +30,13 @@ import java.util.Optional;
* @since 8/25/2018
*/
public final class RayTraceUtils {
private RayTraceUtils() {}
/**
* The {@link Minecraft} instance
*/
private static final Minecraft mc = Minecraft.getMinecraft();
private RayTraceUtils() {}
/**
* Simulates a "vanilla" raytrace. A RayTraceResult returned by this method
* will be that of the next render pass given that the local player's yaw and
@@ -46,7 +45,7 @@ public final class RayTraceUtils {
* thing to achieve the desired outcome (whether it is hitting and entity or placing
* a block) can be done just by modifying user input.
*
* @param yaw The yaw to raytrace with
* @param yaw The yaw to raytrace with
* @param pitch The pitch to raytrace with
* @return The calculated raytrace result
*/
@@ -31,8 +31,6 @@ import java.util.Optional;
*/
public final class RotationUtils {
private RotationUtils() {}
/**
* The {@link Minecraft} instance
*/
@@ -60,6 +58,8 @@ public final class RotationUtils {
new Vec3d(1, 0.5, 0.5) // East
};
private RotationUtils() {}
/**
* Clamps the specified pitch value between -90 and 90.
*
@@ -177,6 +177,8 @@ public final class RotationUtils {
* is by setting the desired pitch to the current pitch
* setting the desired pitch to the current pitch + 0.0001 means that we do have a desired pitch, it's
* just what it currently is
*
* or if you're a normal person literally all this does it ensure that we don't nudge the pitch to a normal level
*/
return Optional.of(new Rotation(entity.rotationYaw, entity.rotationPitch + 0.0001F));
}
@@ -218,10 +220,8 @@ public final class RotationUtils {
if (result.getBlockPos().equals(pos)) {
return Optional.of(rotation);
}
if (entity.world.getBlockState(pos).getBlock() instanceof BlockFire) {
if (result.getBlockPos().equals(pos.down())) {
return Optional.of(rotation);
}
if (entity.world.getBlockState(pos).getBlock() instanceof BlockFire && result.getBlockPos().equals(pos.down())) {
return Optional.of(rotation);
}
}
return Optional.empty();
+15 -22
View File
@@ -30,21 +30,19 @@ import net.minecraft.util.math.Vec3d;
* @since 10/13/2018
*/
public final class VecUtils {
private VecUtils() {}
/**
* The {@link Minecraft} instance
*/
private static final Minecraft mc = Minecraft.getMinecraft();
private VecUtils() {}
/**
* Calculates the center of the block at the specified position's bounding box
*
* @see #getBlockPosCenter(BlockPos)
*
* @param pos The block position
* @return The center of the block's bounding box
* @see #getBlockPosCenter(BlockPos)
*/
public static Vec3d calculateBlockCenter(BlockPos pos) {
IBlockState b = mc.world.getBlockState(pos);
@@ -68,10 +66,9 @@ public final class VecUtils {
* <p>
* TODO: We may want to consider replacing many usages of this method with #calculateBlockCenter(BlockPos)
*
* @see #calculateBlockCenter(BlockPos)
*
* @param pos The block position
* @return The assumed center of the position
* @see #calculateBlockCenter(BlockPos)
*/
public static Vec3d getBlockPosCenter(BlockPos pos) {
return new Vec3d(pos.getX() + 0.5, pos.getY() + 0.5, pos.getZ() + 0.5);
@@ -80,19 +77,17 @@ public final class VecUtils {
/**
* Gets the distance from the specified position to the assumed center of the specified block position.
*
* @see #getBlockPosCenter(BlockPos)
*
* @param pos The block position
* @param x The x pos
* @param y The y pos
* @param z The z pos
* @param x The x pos
* @param y The y pos
* @param z The z pos
* @return The distance from the assumed block center to the position
* @see #getBlockPosCenter(BlockPos)
*/
public static double distanceToCenter(BlockPos pos, double x, double y, double z) {
Vec3d center = getBlockPosCenter(pos);
double xdiff = x - center.x;
double ydiff = y - center.y;
double zdiff = z - center.z;
double xdiff = pos.getX() + 0.5 - x;
double ydiff = pos.getY() + 0.5 - y;
double zdiff = pos.getZ() + 0.5 - z;
return Math.sqrt(xdiff * xdiff + ydiff * ydiff + zdiff * zdiff);
}
@@ -100,11 +95,10 @@ public final class VecUtils {
* Gets the distance from the specified entity's position to the assumed
* center of the specified block position.
*
* @see #getBlockPosCenter(BlockPos)
*
* @param entity The entity
* @param pos The block position
* @param pos The block position
* @return The distance from the entity to the block's assumed center
* @see #getBlockPosCenter(BlockPos)
*/
public static double entityDistanceToCenter(Entity entity, BlockPos pos) {
return distanceToCenter(pos, entity.posX, entity.posY, entity.posZ);
@@ -114,11 +108,10 @@ public final class VecUtils {
* Gets the distance from the specified entity's position to the assumed
* center of the specified block position, ignoring the Y axis.
*
* @see #getBlockPosCenter(BlockPos)
*
* @param entity The entity
* @param pos The block position
* @param pos The block position
* @return The horizontal distance from the entity to the block's assumed center
* @see #getBlockPosCenter(BlockPos)
*/
public static double entityFlatDistanceToCenter(Entity entity, BlockPos pos) {
return distanceToCenter(pos, entity.posX, pos.getY() + 0.5, entity.posZ);
@@ -40,6 +40,8 @@ public class MixinEntityLivingBase {
)
private void preJump(CallbackInfo ci) {
EntityLivingBase _this = (EntityLivingBase) (Object) this;
// This uses Class.isInstance instead of instanceof since proguard optimizes out the instanceof (since MixinEntityLivingBase could never be instanceof EntityLivingBase in normal java)
// but proguard isn't smart enough to optimize out this Class.isInstance =)
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.JUMP));
}
@@ -50,6 +52,7 @@ public class MixinEntityLivingBase {
)
private void postJump(CallbackInfo ci) {
EntityLivingBase _this = (EntityLivingBase) (Object) this;
// See above
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.JUMP));
}
@@ -21,10 +21,13 @@ import baritone.Baritone;
import baritone.api.event.events.ChatEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.PathingBehavior;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.player.PlayerCapabilities;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
/**
@@ -72,4 +75,16 @@ public class MixinEntityPlayerSP {
private void onPostUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.POST));
}
@Redirect(
method = "onLivingUpdate",
at = @At(
value = "FIELD",
target = "net/minecraft/entity/player/PlayerCapabilities.allowFlying:Z"
)
)
private boolean isAllowFlying(PlayerCapabilities capabilities) {
PathingBehavior pathingBehavior = Baritone.INSTANCE.getPathingBehavior();
return (!pathingBehavior.isEnabled() || !pathingBehavior.isPathing()) && capabilities.allowFlying;
}
}
@@ -22,9 +22,7 @@ import baritone.api.event.events.BlockInteractEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.WorldEvent;
import baritone.api.event.events.type.EventState;
import baritone.behavior.PathingBehavior;
import baritone.utils.BaritoneAutoTest;
import baritone.utils.ExampleBaritoneControl;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.gui.GuiScreen;
@@ -49,8 +47,6 @@ import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
@Mixin(Minecraft.class)
public class MixinMinecraft {
@Shadow
private int leftClickCounter;
@Shadow
public EntityPlayerSP player;
@Shadow
@@ -62,7 +58,6 @@ public class MixinMinecraft {
)
private void postInit(CallbackInfo ci) {
Baritone.INSTANCE.init();
ExampleBaritoneControl.INSTANCE.initAndRegister();
}
@Inject(
@@ -147,7 +142,7 @@ public class MixinMinecraft {
)
)
private boolean isAllowUserInput(GuiScreen screen) {
return (PathingBehavior.INSTANCE.getCurrent() != null && PathingBehavior.INSTANCE.isEnabled() && player != null) || screen.allowUserInput;
return (Baritone.INSTANCE.getPathingBehavior().getCurrent() != null && Baritone.INSTANCE.getPathingBehavior().isEnabled() && player != null) || screen.allowUserInput;
}
@Inject(
+55 -8
View File
@@ -18,11 +18,15 @@
package baritone;
import baritone.api.BaritoneAPI;
import baritone.api.IBaritoneProvider;
import baritone.api.Settings;
import baritone.api.event.listener.IGameEventListener;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.cache.WorldScanner;
import baritone.event.GameEventHandler;
import baritone.utils.BaritoneAutoTest;
import baritone.utils.ExampleBaritoneControl;
import baritone.utils.InputOverrideHandler;
import net.minecraft.client.Minecraft;
@@ -40,7 +44,7 @@ import java.util.concurrent.TimeUnit;
* @author Brady
* @since 7/31/2018 10:50 PM
*/
public enum Baritone {
public enum Baritone implements IBaritoneProvider {
/**
* Singleton instance of this class
@@ -55,10 +59,16 @@ public enum Baritone {
private GameEventHandler gameEventHandler;
private InputOverrideHandler inputOverrideHandler;
private Settings settings;
private List<Behavior> behaviors;
private File dir;
private ThreadPoolExecutor threadPool;
private List<Behavior> behaviors;
private PathingBehavior pathingBehavior;
private LookBehavior lookBehavior;
private MemoryBehavior memoryBehavior;
private FollowBehavior followBehavior;
private MineBehavior mineBehavior;
/**
* Whether or not Baritone is active
*/
@@ -81,12 +91,13 @@ public enum Baritone {
this.behaviors = new ArrayList<>();
{
registerBehavior(PathingBehavior.INSTANCE);
registerBehavior(LookBehavior.INSTANCE);
registerBehavior(MemoryBehavior.INSTANCE);
registerBehavior(LocationTrackingBehavior.INSTANCE);
registerBehavior(FollowBehavior.INSTANCE);
registerBehavior(MineBehavior.INSTANCE);
// the Behavior constructor calls baritone.registerBehavior(this) so this populates the behaviors arraylist
pathingBehavior = new PathingBehavior(this);
lookBehavior = new LookBehavior(this);
memoryBehavior = new MemoryBehavior(this);
followBehavior = new FollowBehavior(this);
mineBehavior = new MineBehavior(this);
new ExampleBaritoneControl(this);
}
if (BaritoneAutoTest.ENABLE_AUTO_TEST) {
registerEventListener(BaritoneAutoTest.INSTANCE);
@@ -127,6 +138,42 @@ public enum Baritone {
this.registerEventListener(behavior);
}
@Override
public FollowBehavior getFollowBehavior() {
return followBehavior;
}
@Override
public LookBehavior getLookBehavior() {
return lookBehavior;
}
@Override
public MemoryBehavior getMemoryBehavior() {
return memoryBehavior;
}
@Override
public MineBehavior getMineBehavior() {
return mineBehavior;
}
@Override
public PathingBehavior getPathingBehavior() {
return pathingBehavior;
}
@Override
public WorldProvider getWorldProvider() {
return WorldProvider.INSTANCE;
}
@Override
public WorldScanner getWorldScanner() {
return WorldScanner.INSTANCE;
}
@Override
public void registerEventListener(IGameEventListener listener) {
this.gameEventHandler.registerEventListener(listener);
}
+7 -6
View File
@@ -22,11 +22,12 @@ import baritone.api.behavior.*;
import baritone.api.cache.IWorldProvider;
import baritone.api.cache.IWorldScanner;
import baritone.api.event.listener.IGameEventListener;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.cache.WorldScanner;
/**
* todo fix this cancer
*
* @author Brady
* @since 9/29/2018
*/
@@ -34,27 +35,27 @@ public final class BaritoneProvider implements IBaritoneProvider {
@Override
public IFollowBehavior getFollowBehavior() {
return FollowBehavior.INSTANCE;
return Baritone.INSTANCE.getFollowBehavior();
}
@Override
public ILookBehavior getLookBehavior() {
return LookBehavior.INSTANCE;
return Baritone.INSTANCE.getLookBehavior();
}
@Override
public IMemoryBehavior getMemoryBehavior() {
return MemoryBehavior.INSTANCE;
return Baritone.INSTANCE.getMemoryBehavior();
}
@Override
public IMineBehavior getMineBehavior() {
return MineBehavior.INSTANCE;
return Baritone.INSTANCE.getMineBehavior();
}
@Override
public IPathingBehavior getPathingBehavior() {
return PathingBehavior.INSTANCE;
return Baritone.INSTANCE.getPathingBehavior();
}
@Override
@@ -17,6 +17,7 @@
package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IBehavior;
/**
@@ -27,11 +28,18 @@ import baritone.api.behavior.IBehavior;
*/
public class Behavior implements IBehavior {
public final Baritone baritone;
/**
* Whether or not this behavior is enabled
*/
private boolean enabled = true;
protected Behavior(Baritone baritone) {
this.baritone = baritone;
baritone.registerBehavior(this);
}
/**
* Toggles the enabled state of this {@link Behavior}.
*
@@ -33,11 +33,11 @@ import net.minecraft.util.math.BlockPos;
*/
public final class FollowBehavior extends Behavior implements IFollowBehavior, Helper {
public static final FollowBehavior INSTANCE = new FollowBehavior();
private Entity following;
private FollowBehavior() {}
public FollowBehavior(Baritone baritone) {
super(baritone);
}
@Override
public void onTick(TickEvent event) {
@@ -56,9 +56,9 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H
GoalXZ g = GoalXZ.fromDirection(following.getPositionVector(), Baritone.settings().followOffsetDirection.get(), Baritone.settings().followOffsetDistance.get());
pos = new BlockPos(g.getX(), following.posY, g.getZ());
}
PathingBehavior.INSTANCE.setGoal(new GoalNear(pos, Baritone.settings().followRadius.get()));
PathingBehavior.INSTANCE.revalidateGoal();
PathingBehavior.INSTANCE.path();
baritone.getPathingBehavior().setGoal(new GoalNear(pos, Baritone.settings().followRadius.get()));
((PathingBehavior) baritone.getPathingBehavior()).revalidateGoal();
baritone.getPathingBehavior().path();
}
@Override
@@ -73,7 +73,7 @@ public final class FollowBehavior extends Behavior implements IFollowBehavior, H
@Override
public void cancel() {
PathingBehavior.INSTANCE.cancel();
baritone.getPathingBehavior().cancel();
follow(null);
}
}
@@ -1,53 +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.behavior;
import baritone.api.event.events.BlockInteractEvent;
import baritone.cache.Waypoint;
import baritone.cache.WorldProvider;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import net.minecraft.block.BlockBed;
/**
* A collection of event methods that are used to interact with Baritone's
* waypoint system. This class probably needs a better name.
*
* @see Waypoint
*
* @author Brady
* @since 8/22/2018
*/
public final class LocationTrackingBehavior extends Behavior implements Helper {
public static final LocationTrackingBehavior INSTANCE = new LocationTrackingBehavior();
private LocationTrackingBehavior() {}
@Override
public void onBlockInteract(BlockInteractEvent event) {
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
}
}
@Override
public void onPlayerDeath() {
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
}
}
@@ -26,9 +26,6 @@ import baritone.api.utils.Rotation;
import baritone.utils.Helper;
public final class LookBehavior extends Behavior implements ILookBehavior, Helper {
public static final LookBehavior INSTANCE = new LookBehavior();
/**
* Target's values are as follows:
* <p>
@@ -49,7 +46,9 @@ public final class LookBehavior extends Behavior implements ILookBehavior, Helpe
*/
private float lastYaw;
private LookBehavior() {}
public LookBehavior(Baritone baritone) {
super(baritone);
}
@Override
public void updateTarget(Rotation target, boolean force) {
@@ -17,14 +17,19 @@
package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IMemoryBehavior;
import baritone.api.behavior.memory.IRememberedInventory;
import baritone.api.cache.IWorldData;
import baritone.api.event.events.BlockInteractEvent;
import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.type.EventState;
import baritone.cache.Waypoint;
import baritone.cache.WorldProvider;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import net.minecraft.block.BlockBed;
import net.minecraft.item.ItemStack;
import net.minecraft.network.Packet;
import net.minecraft.network.play.client.CPacketCloseWindow;
@@ -43,11 +48,11 @@ import java.util.*;
*/
public final class MemoryBehavior extends Behavior implements IMemoryBehavior, Helper {
public static MemoryBehavior INSTANCE = new MemoryBehavior();
private final Map<IWorldData, WorldDataContainer> worldDataContainers = new HashMap<>();
private MemoryBehavior() {}
public MemoryBehavior(Baritone baritone) {
super(baritone);
}
@Override
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
@@ -114,6 +119,18 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
}
}
@Override
public void onBlockInteract(BlockInteractEvent event) {
if (event.getType() == BlockInteractEvent.Type.USE && BlockStateInterface.getBlock(event.getPos()) instanceof BlockBed) {
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("bed", Waypoint.Tag.BED, event.getPos()));
}
}
@Override
public void onPlayerDeath() {
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("death", Waypoint.Tag.DEATH, playerFeet()));
}
private Optional<RememberedInventory> getInventoryFromWindow(int windowId) {
return this.getCurrentContainer().rememberedInventories.values().stream().filter(i -> i.windowId == windowId).findFirst();
}
+124 -44
View File
@@ -20,21 +20,23 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IMineBehavior;
import baritone.api.event.events.TickEvent;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.pathing.goals.*;
import baritone.api.utils.RotationUtils;
import baritone.cache.CachedChunk;
import baritone.cache.ChunkPacker;
import baritone.cache.WorldProvider;
import baritone.cache.WorldScanner;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import net.minecraft.block.Block;
import net.minecraft.entity.Entity;
import net.minecraft.entity.item.EntityItem;
import net.minecraft.init.Blocks;
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.*;
@@ -46,14 +48,15 @@ import java.util.stream.Collectors;
* @author leijurv
*/
public final class MineBehavior extends Behavior implements IMineBehavior, Helper {
public static final MineBehavior INSTANCE = new MineBehavior();
public static final int ORE_LOCATIONS_COUNT = 64;
private List<Block> mining;
private List<BlockPos> locationsCache;
private int quantity;
private List<BlockPos> knownOreLocations;
private BlockPos branchPoint;
private int desiredQuantity;
private MineBehavior() {}
public MineBehavior(Baritone baritone) {
super(baritone);
}
@Override
public void onTick(TickEvent event) {
@@ -64,53 +67,80 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
if (mining == null) {
return;
}
if (quantity > 0) {
if (desiredQuantity > 0) {
Item item = mining.get(0).getItemDropped(mining.get(0).getDefaultState(), new Random(), 0);
int curr = player().inventory.mainInventory.stream().filter(stack -> item.equals(stack.getItem())).mapToInt(ItemStack::getCount).sum();
System.out.println("Currently have " + curr + " " + item);
if (curr >= quantity) {
if (curr >= desiredQuantity) {
logDirect("Have " + curr + " " + item.getItemStackDisplayName(new ItemStack(item, 1)));
cancel();
return;
}
}
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
if (mineGoalUpdateInterval != 0) {
if (event.getCount() % mineGoalUpdateInterval == 0) {
Baritone.INSTANCE.getExecutor().execute(this::rescan);
}
if (mineGoalUpdateInterval != 0 && event.getCount() % mineGoalUpdateInterval == 0) {
Baritone.INSTANCE.getExecutor().execute(this::rescan);
}
if (Baritone.settings().legitMine.get()) {
addNearby();
}
updateGoal();
PathingBehavior.INSTANCE.revalidateGoal();
baritone.getPathingBehavior().revalidateGoal();
}
private void updateGoal() {
if (mining == null) {
if (mining == null || world() == null || player() == null) {
return;
}
List<BlockPos> locs = locationsCache;
List<BlockPos> locs = knownOreLocations;
if (!locs.isEmpty()) {
locs = prune(new ArrayList<>(locs), mining, 64);
PathingBehavior.INSTANCE.setGoal(coalesce(locs));
PathingBehavior.INSTANCE.path();
locationsCache = locs;
List<BlockPos> locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, world());
// 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
baritone.getPathingBehavior().setGoalAndPath(new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new)));
knownOreLocations = locs2;
return;
}
// we don't know any ore locations at the moment
if (!Baritone.settings().legitMine.get()) {
return;
}
// only in non-Xray mode (aka legit mode) do we do this
if (branchPoint == null) {
int y = Baritone.settings().legitMineYLevel.get();
if (!baritone.getPathingBehavior().isPathing() && playerFeet().y == y) {
// cool, path is over and we are at desired y
branchPoint = playerFeet();
} else {
baritone.getPathingBehavior().setGoalAndPath(new GoalYLevel(y));
return;
}
}
if (playerFeet().equals(branchPoint)) {
// TODO mine 1x1 shafts to either side
branchPoint = branchPoint.north(10);
}
baritone.getPathingBehavior().setGoalAndPath(new GoalBlock(branchPoint));
}
private void rescan() {
if (mining == null) {
if (mining == null || world() == null || player() == null) {
return;
}
List<BlockPos> locs = scanFor(mining, 64);
if (Baritone.settings().legitMine.get()) {
return;
}
List<BlockPos> locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world());
locs.addAll(droppedItemsScan(mining, world()));
if (locs.isEmpty()) {
logDebug("No locations for " + mining + " known, cancelling");
mine(0, (String[]) null);
return;
}
locationsCache = locs;
knownOreLocations = locs;
}
public Goal coalesce(BlockPos loc, List<BlockPos> locs) {
private static Goal coalesce(BlockPos loc, List<BlockPos> locs) {
if (!Baritone.settings().forceInternalMining.get()) {
return new GoalTwoBlocks(loc);
}
@@ -132,11 +162,30 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
}
}
public GoalComposite coalesce(List<BlockPos> locs) {
return new GoalComposite(locs.stream().map(loc -> coalesce(loc, locs)).toArray(Goal[]::new));
public static List<BlockPos> droppedItemsScan(List<Block> mining, World world) {
if (!Baritone.settings().mineScanDroppedItems.get()) {
return new ArrayList<>();
}
Set<Item> searchingFor = new HashSet<>();
for (Block block : mining) {
Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0);
Item ore = Item.getItemFromBlock(block);
searchingFor.add(drop);
searchingFor.add(ore);
}
List<BlockPos> ret = new ArrayList<>();
for (Entity entity : world.loadedEntityList) {
if (entity instanceof EntityItem) {
EntityItem ei = (EntityItem) entity;
if (searchingFor.contains(ei.getItem().getItem())) {
ret.add(entity.getPosition());
}
}
}
return ret;
}
public List<BlockPos> scanFor(List<Block> mining, int max) {
public static List<BlockPos> searchWorld(List<Block> mining, int max, World world) {
List<BlockPos> locs = new ArrayList<>();
List<Block> uninteresting = new ArrayList<>();
//long b = System.currentTimeMillis();
@@ -156,29 +205,59 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26));
//System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms");
}
return prune(locs, mining, max);
return prune(locs, mining, max, world);
}
public List<BlockPos> prune(List<BlockPos> locs, List<Block> mining, int max) {
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
public void addNearby() {
BlockPos playerFeet = playerFeet();
int searchDist = 4;//why four? idk
for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) {
for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) {
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
BlockPos pos = new BlockPos(x, y, z);
if (mining.contains(BlockStateInterface.getBlock(pos)) && RotationUtils.reachable(player(), pos).isPresent()) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught
knownOreLocations.add(pos);
}
}
}
}
knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT, world());
}
public static List<BlockPos> prune(List<BlockPos> locs2, List<Block> mining, int max, World world) {
List<BlockPos> dropped = droppedItemsScan(mining, world);
List<BlockPos> locs = locs2
.stream()
// remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> world.getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()) || dropped.contains(pos))
// remove any that are implausible to mine (encased in bedrock, or touching lava)
.filter(MineBehavior::plausibleToBreak)
.sorted(Comparator.comparingDouble(Helper.HELPER.playerFeet()::distanceSq))
.collect(Collectors.toList());
// remove any that are within loaded chunks that aren't actually what we want
locs.removeAll(locs.stream()
.filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk))
.filter(pos -> !mining.contains(BlockStateInterface.get(pos).getBlock()))
.collect(Collectors.toList()));
if (locs.size() > max) {
return locs.subList(0, max);
}
return locs;
}
public static boolean plausibleToBreak(BlockPos pos) {
if (MovementHelper.avoidBreaking(pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(pos))) {
return false;
}
// bedrock above and below makes it implausible, otherwise we're good
return !(BlockStateInterface.getBlock(pos.up()) == Blocks.BEDROCK && BlockStateInterface.getBlock(pos.down()) == Blocks.BEDROCK);
}
@Override
public void mine(int quantity, String... blocks) {
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList());
this.quantity = quantity;
this.locationsCache = new ArrayList<>();
this.desiredQuantity = quantity;
this.knownOreLocations = new ArrayList<>();
this.branchPoint = null;
rescan();
updateGoal();
}
@@ -186,8 +265,9 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
@Override
public void mine(int quantity, Block... blocks) {
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks);
this.quantity = quantity;
this.locationsCache = new ArrayList<>();
this.desiredQuantity = quantity;
this.knownOreLocations = new ArrayList<>();
this.branchPoint = null;
rescan();
updateGoal();
}
@@ -195,6 +275,6 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
@Override
public void cancel() {
mine(0, (String[]) null);
PathingBehavior.INSTANCE.cancel();
baritone.getPathingBehavior().cancel();
}
}
@@ -32,21 +32,23 @@ import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.calc.CutoffPath;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.PathExecutor;
import baritone.utils.BlockBreakHelper;
import baritone.utils.Helper;
import baritone.utils.PathRenderer;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.*;
import java.util.stream.Collectors;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Optional;
import java.util.concurrent.LinkedBlockingQueue;
public final class PathingBehavior extends Behavior implements IPathingBehavior, Helper {
public static final PathingBehavior INSTANCE = new PathingBehavior();
private PathExecutor current;
private PathExecutor next;
@@ -59,29 +61,46 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
private boolean lastAutoJump;
private PathingBehavior() {}
private final LinkedBlockingQueue<PathEvent> toDispatch = new LinkedBlockingQueue<>();
private void dispatchPathEvent(PathEvent event) {
Baritone.INSTANCE.getExecutor().execute(() -> Baritone.INSTANCE.getGameEventHandler().onPathEvent(event));
public PathingBehavior(Baritone baritone) {
super(baritone);
}
private void queuePathEvent(PathEvent event) {
toDispatch.add(event);
}
private void dispatchEvents() {
ArrayList<PathEvent> curr = new ArrayList<>();
toDispatch.drainTo(curr);
for (PathEvent event : curr) {
Baritone.INSTANCE.getGameEventHandler().onPathEvent(event);
}
}
@Override
public void onTick(TickEvent event) {
dispatchEvents();
if (event.getType() == TickEvent.Type.OUT) {
this.cancel();
cancel();
return;
}
mc.playerController.setPlayerCapabilities(mc.player);
tickPath();
dispatchEvents();
}
private void tickPath() {
if (current == null) {
return;
}
boolean safe = current.onTick(event);
boolean safe = current.onTick();
synchronized (pathPlanLock) {
if (current.failed() || current.finished()) {
current = null;
if (goal == null || goal.isInGoal(playerFeet())) {
logDebug("All done. At " + goal);
dispatchPathEvent(PathEvent.AT_GOAL);
queuePathEvent(PathEvent.AT_GOAL);
next = null;
return;
}
@@ -93,43 +112,38 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
// but if we fail in the middle of current
// we're nowhere close to our planned ahead path
// so need to discard it sadly.
dispatchPathEvent(PathEvent.DISCARD_NEXT);
queuePathEvent(PathEvent.DISCARD_NEXT);
next = null;
}
if (next != null) {
logDebug("Continuing on to planned next path");
dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
queuePathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
current = next;
next = null;
current.onTick(event);
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 (isPathCalcInProgress) {
dispatchPathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
queuePathEvent(PathEvent.PATH_FINISHED_NEXT_STILL_CALCULATING);
// if we aren't calculating right now
return;
}
dispatchPathEvent(PathEvent.CALC_STARTED);
queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true, Optional.empty());
}
return;
}
// at this point, we know current is in progress
if (safe) {
// a movement just ended
if (next != null) {
if (next.snipsnapifpossible()) {
// jump directly onto the next path
logDebug("Splicing into planned next path early...");
dispatchPathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
current = next;
next = null;
current.onTick(event);
return;
}
}
if (safe && next != null && player().onGround && next.snipsnapifpossible()) {
// a movement just ended; jump directly onto the next path
logDebug("Splicing into planned next path early...");
queuePathEvent(PathEvent.SPLICING_ONTO_NEXT_EARLY);
current = next;
next = null;
current.onTick();
return;
}
synchronized (pathCalcLock) {
if (isPathCalcInProgress) {
@@ -147,7 +161,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (ticksRemainingInSegment().get() < Baritone.settings().planningTickLookAhead.get()) {
// and this path has 5 seconds or less left
logDebug("Path almost over. Planning ahead...");
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_STARTED);
findPathInNewThread(current.getPath().getDest(), false, Optional.of(current.getPath()));
}
}
@@ -184,6 +198,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
this.goal = goal;
}
public boolean setGoalAndPath(Goal goal) {
setGoal(goal);
return path();
}
@Override
public Goal getGoal() {
return goal;
@@ -211,7 +230,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
@Override
public void cancel() {
dispatchPathEvent(PathEvent.CANCELED);
queuePathEvent(PathEvent.CANCELED);
current = null;
next = null;
Baritone.INSTANCE.getInputOverrideHandler().clearAllKeys();
@@ -244,7 +263,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (isPathCalcInProgress) {
return false;
}
dispatchPathEvent(PathEvent.CALC_STARTED);
queuePathEvent(PathEvent.CALC_STARTED);
findPathInNewThread(pathStart(), true, Optional.empty());
return true;
}
@@ -309,12 +328,13 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
isPathCalcInProgress = true;
}
CalculationContext context = new CalculationContext(); // not safe to create on the other thread, it looks up a lot of stuff in minecraft
Baritone.INSTANCE.getExecutor().execute(() -> {
if (talkAboutIt) {
logDebug("Starting to search for path from " + start + " to " + goal);
}
Optional<IPath> path = findPath(start, previous);
Optional<IPath> path = findPath(start, previous, context);
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks();
@@ -343,18 +363,18 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
synchronized (pathPlanLock) {
if (current == null) {
if (executor.isPresent()) {
dispatchPathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
queuePathEvent(PathEvent.CALC_FINISHED_NOW_EXECUTING);
current = executor.get();
} else {
dispatchPathEvent(PathEvent.CALC_FAILED);
queuePathEvent(PathEvent.CALC_FAILED);
}
} else {
if (next == null) {
if (executor.isPresent()) {
dispatchPathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
queuePathEvent(PathEvent.NEXT_SEGMENT_CALC_FINISHED);
next = executor.get();
} else {
dispatchPathEvent(PathEvent.NEXT_CALC_FAILED);
queuePathEvent(PathEvent.NEXT_CALC_FAILED);
}
} else {
throw new IllegalStateException("I have no idea what to do with this path");
@@ -382,19 +402,15 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
* @param start
* @return
*/
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous) {
private Optional<IPath> findPath(BlockPos start, Optional<IPath> previous, CalculationContext context) {
Goal goal = this.goal;
if (goal == null) {
logDebug("no goal");
return Optional.empty();
}
if (Baritone.settings().simplifyUnloadedYCoord.get()) {
BlockPos pos = null;
if (goal instanceof IGoalRenderPos) {
pos = ((IGoalRenderPos) goal).getGoalPos();
}
if (pos != null && world().getChunk(pos) instanceof EmptyChunk) {
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
if (world().getChunk(pos) instanceof EmptyChunk) {
logDebug("Simplifying " + goal.getClass() + " to GoalXZ due to distance");
goal = new GoalXZ(pos.getX(), pos.getZ());
}
@@ -405,14 +421,14 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
} else {
timeout = Baritone.settings().planAheadTimeoutMS.<Long>get();
}
Optional<HashSet<Long>> favoredPositions;
if (Baritone.settings().backtrackCostFavoringCoefficient.get() == 1D) {
favoredPositions = Optional.empty();
} else {
favoredPositions = previous.map(IPath::positions).map(Collection::stream).map(x -> x.map(BetterBlockPos::longHash)).map(x -> x.collect(Collectors.toList())).map(HashSet::new); // <-- okay this is EPIC
Optional<LongOpenHashSet> favoredPositions = Optional.empty();
if (Baritone.settings().backtrackCostFavoringCoefficient.get() != 1D && previous.isPresent()) {
LongOpenHashSet tmp = new LongOpenHashSet();
previous.get().positions().forEach(pos -> tmp.add(BetterBlockPos.longHash(pos)));
favoredPositions = Optional.of(tmp);
}
try {
IPathFinder pf = new AStarPathFinder(start.getX(), start.getY(), start.getZ(), goal, favoredPositions);
IPathFinder pf = new AStarPathFinder(start.getX(), start.getY(), start.getZ(), goal, favoredPositions, context);
return pf.calculate(timeout);
} catch (Exception e) {
logDebug("Pathing exception: " + e);
+55 -33
View File
@@ -33,40 +33,62 @@ import java.util.*;
*/
public final class CachedChunk implements IBlockTypeAccess, Helper {
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(new HashSet<Block>() {{
add(Blocks.DIAMOND_ORE);
add(Blocks.DIAMOND_BLOCK);
//add(Blocks.COAL_ORE);
add(Blocks.COAL_BLOCK);
//add(Blocks.IRON_ORE);
add(Blocks.IRON_BLOCK);
//add(Blocks.GOLD_ORE);
add(Blocks.GOLD_BLOCK);
add(Blocks.EMERALD_ORE);
add(Blocks.EMERALD_BLOCK);
public static final Set<Block> BLOCKS_TO_KEEP_TRACK_OF;
add(Blocks.ENDER_CHEST);
add(Blocks.FURNACE);
add(Blocks.CHEST);
add(Blocks.END_PORTAL);
add(Blocks.END_PORTAL_FRAME);
add(Blocks.MOB_SPAWNER);
// TODO add all shulker colors
add(Blocks.PORTAL);
add(Blocks.HOPPER);
add(Blocks.BEACON);
add(Blocks.BREWING_STAND);
add(Blocks.SKULL);
add(Blocks.ENCHANTING_TABLE);
add(Blocks.ANVIL);
add(Blocks.LIT_FURNACE);
add(Blocks.BED);
add(Blocks.DRAGON_EGG);
add(Blocks.JUKEBOX);
add(Blocks.END_GATEWAY);
add(Blocks.WEB);
add(Blocks.NETHER_WART);
}});
static {
HashSet<Block> temp = new HashSet<>();
temp.add(Blocks.DIAMOND_ORE);
temp.add(Blocks.DIAMOND_BLOCK);
//temp.add(Blocks.COAL_ORE);
temp.add(Blocks.COAL_BLOCK);
//temp.add(Blocks.IRON_ORE);
temp.add(Blocks.IRON_BLOCK);
//temp.add(Blocks.GOLD_ORE);
temp.add(Blocks.GOLD_BLOCK);
temp.add(Blocks.EMERALD_ORE);
temp.add(Blocks.EMERALD_BLOCK);
temp.add(Blocks.ENDER_CHEST);
temp.add(Blocks.FURNACE);
temp.add(Blocks.CHEST);
temp.add(Blocks.TRAPPED_CHEST);
temp.add(Blocks.END_PORTAL);
temp.add(Blocks.END_PORTAL_FRAME);
temp.add(Blocks.MOB_SPAWNER);
temp.add(Blocks.BARRIER);
temp.add(Blocks.OBSERVER);
temp.add(Blocks.WHITE_SHULKER_BOX);
temp.add(Blocks.ORANGE_SHULKER_BOX);
temp.add(Blocks.MAGENTA_SHULKER_BOX);
temp.add(Blocks.LIGHT_BLUE_SHULKER_BOX);
temp.add(Blocks.YELLOW_SHULKER_BOX);
temp.add(Blocks.LIME_SHULKER_BOX);
temp.add(Blocks.PINK_SHULKER_BOX);
temp.add(Blocks.GRAY_SHULKER_BOX);
temp.add(Blocks.SILVER_SHULKER_BOX);
temp.add(Blocks.CYAN_SHULKER_BOX);
temp.add(Blocks.PURPLE_SHULKER_BOX);
temp.add(Blocks.BLUE_SHULKER_BOX);
temp.add(Blocks.BROWN_SHULKER_BOX);
temp.add(Blocks.GREEN_SHULKER_BOX);
temp.add(Blocks.RED_SHULKER_BOX);
temp.add(Blocks.BLACK_SHULKER_BOX);
temp.add(Blocks.PORTAL);
temp.add(Blocks.HOPPER);
temp.add(Blocks.BEACON);
temp.add(Blocks.BREWING_STAND);
temp.add(Blocks.SKULL);
temp.add(Blocks.ENCHANTING_TABLE);
temp.add(Blocks.ANVIL);
temp.add(Blocks.LIT_FURNACE);
temp.add(Blocks.BED);
temp.add(Blocks.DRAGON_EGG);
temp.add(Blocks.JUKEBOX);
temp.add(Blocks.END_GATEWAY);
temp.add(Blocks.WEB);
temp.add(Blocks.NETHER_WART);
BLOCKS_TO_KEEP_TRACK_OF = Collections.unmodifiableSet(temp);
}
/**
* The size of the chunk data in bits. Equal to 16 KiB.
+6
View File
@@ -167,6 +167,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
private synchronized void prune() {
BlockPos pruneCenter = guessPosition();
for (CachedRegion region : allRegions()) {
if (region == null) {
continue;
}
int distX = (region.getX() * 512 + 256) - pruneCenter.getX();
int distZ = (region.getZ() * 512 + 256) - pruneCenter.getZ();
double dist = Math.sqrt(distX * distX + distZ * distZ);
@@ -187,6 +190,9 @@ public final class CachedWorld implements ICachedWorld, Helper {
}
CachedChunk mostRecentlyModified = null;
for (CachedRegion region : allRegions()) {
if (region == null) {
continue;
}
CachedChunk ch = region.mostRecentlyModified();
if (ch == null) {
continue;
+6 -3
View File
@@ -40,6 +40,8 @@ import java.util.*;
*/
public final class ChunkPacker implements Helper {
private static final Map<String, Block> resourceCache = new HashMap<>();
private ChunkPacker() {}
public static CachedChunk pack(Chunk chunk) {
@@ -93,7 +95,8 @@ public final class ChunkPacker implements Helper {
for (int z = 0; z < 16; z++) {
// @formatter:off
https://www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
https:
//www.ibm.com/developerworks/library/j-perry-writing-good-java-code/index.html
// @formatter:on
for (int x = 0; x < 16; x++) {
for (int y = 255; y >= 0; y--) {
@@ -120,12 +123,12 @@ public final class ChunkPacker implements Helper {
}
public static Block stringToBlock(String name) {
return Block.getBlockFromName(name.contains(":") ? name : "minecraft:" + name);
return resourceCache.computeIfAbsent(name, n -> Block.getBlockFromName(n.contains(":") ? n : "minecraft:" + n));
}
private static PathingBlockType getPathingBlockType(IBlockState state) {
Block block = state.getBlock();
if (block.equals(Blocks.WATER)) {
if (block == Blocks.WATER && !MovementHelper.isFlowing(state)) {
// only water source blocks are plausibly usable, flowing water should be avoid
return PathingBlockType.WATER;
}
@@ -29,8 +29,8 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.MutableMoveResult;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import java.util.HashSet;
import java.util.Optional;
/**
@@ -40,11 +40,13 @@ import java.util.Optional;
*/
public final class AStarPathFinder extends AbstractNodeCostSearch implements Helper {
private final Optional<HashSet<Long>> favoredPositions;
private final Optional<LongOpenHashSet> favoredPositions;
private final CalculationContext calcContext;
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<HashSet<Long>> favoredPositions) {
public AStarPathFinder(int startX, int startY, int startZ, Goal goal, Optional<LongOpenHashSet> favoredPositions, CalculationContext context) {
super(startX, startY, startZ, goal);
this.favoredPositions = favoredPositions;
this.calcContext = context;
}
@Override
@@ -61,11 +63,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
bestHeuristicSoFar[i] = startNode.estimatedCostToGoal;
bestSoFar[i] = startNode;
}
CalculationContext calcContext = new CalculationContext();
MutableMoveResult res = new MutableMoveResult();
HashSet<Long> favored = favoredPositions.orElse(null);
BetterWorldBorder worldBorder = new BetterWorldBorder(world().getWorldBorder());
BlockStateInterface.clearCachedChunk();
LongOpenHashSet favored = favoredPositions.orElse(null);
long startTime = System.nanoTime() / 1000000L;
boolean slowPath = Baritone.settings().slowPath.get();
if (slowPath) {
@@ -99,14 +100,12 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
for (Moves moves : Moves.values()) {
int newX = currentNode.x + moves.xOffset;
int newZ = currentNode.z + moves.zOffset;
if (newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) {
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !BlockStateInterface.isLoaded(newX, newZ)) {
// only need to check if the destination is a loaded chunk if it's in a different chunk than the start of the movement
if (!BlockStateInterface.isLoaded(newX, newZ)) {
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
numEmptyChunk++;
}
continue;
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
numEmptyChunk++;
}
continue;
}
if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) {
continue;
@@ -132,7 +131,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
}
if (!moves.dynamicY && res.y != currentNode.y + moves.yOffset) {
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
throw new IllegalStateException(moves + " " + res.y + " " + (currentNode.y + moves.yOffset));
}
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (favoring && favored.contains(hashCode)) {
@@ -48,11 +48,7 @@ public class CalculationContext implements Helper {
private final BetterWorldBorder worldBorder;
public CalculationContext() {
this(new ToolSet());
}
public CalculationContext(ToolSet toolSet) {
this.toolSet = toolSet;
this.toolSet = new ToolSet();
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(false);
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) && !world().provider.isNether();
this.canSprint = Baritone.settings().allowSprint.get() && player().getFoodStats().getFoodLevel() > 6;
@@ -87,10 +83,7 @@ public class CalculationContext implements Helper {
if (!allowBreak()) {
return false;
}
if (isPossiblyProtected(x, y, z)) {
return false;
}
return true;
return !isPossiblyProtected(x, y, z);
}
public boolean isPossiblyProtected(int x, int y, int z) {
@@ -20,16 +20,13 @@ package baritone.pathing.movement;
import baritone.Baritone;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.VecUtils;
import baritone.behavior.LookBehavior;
import baritone.api.utils.*;
import baritone.utils.BlockBreakHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.InputOverrideHandler;
import net.minecraft.block.BlockLiquid;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
@@ -37,6 +34,7 @@ import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import static baritone.utils.InputOverrideHandler.Input;
@@ -115,9 +113,9 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
*/
@Override
public MovementStatus update() {
player().capabilities.allowFlying = false;
player().capabilities.isFlying = false;
MovementState latestState = updateState(currentState);
if (BlockStateInterface.isLiquid(playerFeet())) {
if (MovementHelper.isLiquid(playerFeet())) {
latestState.setInput(Input.JUMP, true);
}
if (player().isEntityInsideOpaqueBlock()) {
@@ -126,7 +124,7 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
// If the movement target has to force the new rotations, or we aren't using silent move, then force the rotations
latestState.getTarget().getRotation().ifPresent(rotation ->
LookBehavior.INSTANCE.updateTarget(
Baritone.INSTANCE.getLookBehavior().updateTarget(
rotation,
latestState.getTarget().hasToForceRotations()));
@@ -178,7 +176,10 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
Optional<Rotation> reachable = RotationUtils.reachable(player(), blockPos);
if (reachable.isPresent()) {
MovementHelper.switchToBestToolFor(BlockStateInterface.get(blockPos));
state.setTarget(new MovementState.MovementTarget(reachable.get(), true)).setInput(Input.CLICK_LEFT, true);
state.setTarget(new MovementState.MovementTarget(reachable.get(), true));
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), blockPos) || BlockStateInterface.getBlock(blockPos) == Blocks.FIRE) {
state.setInput(Input.CLICK_LEFT, true);
}
return false;
}
//get rekt minecraft
@@ -187,7 +188,9 @@ public abstract class Movement implements IMovement, Helper, MovementHelper {
//you dont own me!!!!
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(player().getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(blockPos)), true)
).setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
);
// don't check selectedblock on this one, this is a fallback when we can't see any face directly, it's intended to be breaking the "incorrect" block
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
return false;
}
}
@@ -76,7 +76,7 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.AIR) { // early return for most common case
return true;
}
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL) {
if (block == Blocks.FIRE || block == Blocks.TRIPWIRE || block == Blocks.WEB || block == Blocks.END_PORTAL || block == Blocks.COCOA) {
return false;
}
if (block instanceof BlockDoor || block instanceof BlockFenceGate) {
@@ -98,14 +98,18 @@ public interface MovementHelper extends ActionCosts, Helper {
if (snow) {
// the check in BlockSnow.isPassable is layers < 5
// while actually, we want < 3 because 3 or greater makes it impassable in a 2 high ceiling
return state.getValue(BlockSnow.LAYERS) < 3;
if (state.getValue(BlockSnow.LAYERS) >= 3) {
return false;
}
// ok, it's low enough we could walk through it, but is it supported?
return canWalkOn(x, y - 1, z);
}
if (trapdoor) {
return !state.getValue(BlockTrapDoor.OPEN); // see BlockTrapDoor.isPassable
}
throw new IllegalStateException();
}
if (BlockStateInterface.isFlowing(state)) {
if (isFlowing(state)) {
return false; // Don't walk through flowing liquids
}
if (block instanceof BlockLiquid) {
@@ -145,6 +149,7 @@ public interface MovementHelper extends ActionCosts, Helper {
|| block == Blocks.WEB
|| block == Blocks.VINE
|| block == Blocks.LADDER
|| block == Blocks.COCOA
|| block instanceof BlockDoor
|| block instanceof BlockFenceGate
|| block instanceof BlockSnow
@@ -226,7 +231,7 @@ public interface MovementHelper extends ActionCosts, Helper {
return true;
}
return facing == playerFacing == open;
return (facing == playerFacing) == open;
}
static boolean avoidWalkingInto(Block block) {
@@ -254,9 +259,6 @@ public interface MovementHelper extends ActionCosts, Helper {
return false;
}
if (state.isBlockNormalCube()) {
if (BlockStateInterface.isLava(block) || BlockStateInterface.isWater(block)) {
throw new IllegalStateException();
}
return true;
}
if (block == Blocks.LADDER || (block == Blocks.VINE && Baritone.settings().allowVines.get())) { // TODO reconsider this
@@ -268,22 +270,22 @@ public interface MovementHelper extends ActionCosts, Helper {
if (block == Blocks.ENDER_CHEST || block == Blocks.CHEST) {
return true;
}
if (BlockStateInterface.isWater(block)) {
if (isWater(block)) {
// since this is called literally millions of times per second, the benefit of not allocating millions of useless "pos.up()"
// BlockPos s that we'd just garbage collect immediately is actually noticeable. I don't even think its a decrease in readability
Block up = BlockStateInterface.get(x, y + 1, z).getBlock();
if (up == Blocks.WATERLILY) {
return true;
}
if (BlockStateInterface.isFlowing(state) || block == Blocks.FLOWING_WATER) {
if (isFlowing(state) || block == Blocks.FLOWING_WATER) {
// the only scenario in which we can walk on flowing water is if it's under still water with jesus off
return BlockStateInterface.isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
return isWater(up) && !Baritone.settings().assumeWalkOnWater.get();
}
// if assumeWalkOnWater is on, we can only walk on water if there isn't water above it
// if assumeWalkOnWater is off, we can only walk on water if there is water above it
return BlockStateInterface.isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
return isWater(up) ^ Baritone.settings().assumeWalkOnWater.get();
}
if (block instanceof BlockGlass || block instanceof BlockStainedGlass) {
if (block == Blocks.GLASS || block == Blocks.STAINED_GLASS) {
return true;
}
if (block instanceof BlockSlab) {
@@ -295,10 +297,7 @@ public interface MovementHelper extends ActionCosts, Helper {
}
return true;
}
if (block instanceof BlockStairs) {
return true;
}
return false;
return block instanceof BlockStairs;
}
static boolean canWalkOn(BetterBlockPos pos, IBlockState state) {
@@ -400,7 +399,7 @@ public interface MovementHelper extends ActionCosts, Helper {
* @param ts previously calculated ToolSet
*/
static void switchToBestToolFor(IBlockState b, ToolSet ts) {
mc.player.inventory.currentItem = ts.getBestSlot(b);
mc.player.inventory.currentItem = ts.getBestSlot(b.getBlock());
}
static boolean throwaway(boolean select) {
@@ -447,4 +446,46 @@ public interface MovementHelper extends ActionCosts, Helper {
false
)).setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
}
/**
* Returns whether or not the specified block is
* water, regardless of whether or not it is flowing.
*
* @param b The block
* @return Whether or not the block is water
*/
static boolean isWater(Block b) {
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
}
/**
* Returns whether or not the block at the specified pos is
* water, regardless of whether or not it is flowing.
*
* @param bp The block pos
* @return Whether or not the block is water
*/
static boolean isWater(BlockPos bp) {
return isWater(BlockStateInterface.getBlock(bp));
}
static boolean isLava(Block b) {
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
}
/**
* Returns whether or not the specified pos has a liquid
*
* @param p The pos
* @return Whether or not the block is a liquid
*/
static boolean isLiquid(BlockPos p) {
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
}
static boolean isFlowing(IBlockState state) {
// Will be IFluidState in 1.13
return state.getBlock() instanceof BlockLiquid
&& state.getValue(BlockLiquid.LEVEL) != 0;
}
}
@@ -75,7 +75,7 @@ public class MovementAscend extends Movement {
if (!context.canPlaceThrowawayAt(destX, y, destZ)) {
return COST_INF;
}
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y, destZ, toPlace)) {
return COST_INF;
}
// TODO: add ability to place against .down() as well as the cardinal directions
@@ -97,21 +97,19 @@ public class MovementAscend extends Movement {
}
}
IBlockState srcUp2 = null;
if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling) {//it would fall on us and possibly suffocate us
if (BlockStateInterface.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(x, y + 1, z) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).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
if (MovementHelper.canWalkThrough(x, y + 1, z) || !((srcUp2 = BlockStateInterface.get(x, y + 2, z)).getBlock() instanceof BlockFalling)) {
// if the lower one is can't walk through and the upper one is falling, that means that by standing on src
// (the presupposition of this Movement)
// we have necessarily already cleared the entire BlockFalling stack
// on top of our head
// if the lower one is can't walk through and the upper one is falling, that means that by standing on src
// (the presupposition of this Movement)
// we have necessarily already cleared the entire BlockFalling stack
// on top of our head
// as in, if we have a block, then two BlockFallings on top of it
// and that block is x, y+1, z, and we'd have to clear it to even start this movement
// we don't need to worry about those BlockFallings because we've already cleared them
return COST_INF;
}
// as in, if we have a block, then two BlockFallings on top of it
// and that block is x, y+1, z, and we'd have to clear it to even start this movement
// we don't need to worry about those BlockFallings because we've already cleared them
return COST_INF;
// you may think we only need to check srcUp2, not srcUp
// however, in the scenario where glitchy world gen where unsupported sand / gravel generates
// it's possible srcUp is AIR from the start, and srcUp2 is falling
@@ -206,10 +204,8 @@ public class MovementAscend extends Movement {
return state.setStatus(MovementStatus.UNREACHABLE);
}
MovementHelper.moveTowards(state, dest);
if (MovementHelper.isBottomSlab(jumpingOnto)) {
if (!MovementHelper.isBottomSlab(src.down())) {
return state; // don't jump while walking from a non double slab into a bottom slab
}
if (MovementHelper.isBottomSlab(jumpingOnto) && !MovementHelper.isBottomSlab(src.down())) {
return state; // don't jump while walking from a non double slab into a bottom slab
}
if (Baritone.settings().assumeStep.get()) {
@@ -130,7 +130,7 @@ public class MovementDescend extends Movement {
}
IBlockState ontoBlock = BlockStateInterface.get(destX, newY, destZ);
double tentativeCost = WALK_OFF_BLOCK_COST + FALL_N_BLOCKS_COST[fallHeight] + frontBreak;
if (ontoBlock.getBlock() == Blocks.WATER && !BlockStateInterface.isFlowing(ontoBlock) && BlockStateInterface.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
if (ontoBlock.getBlock() == Blocks.WATER && !MovementHelper.isFlowing(ontoBlock) && BlockStateInterface.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { // TODO flowing check required here?
// 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 (Baritone.settings().assumeWalkOnWater.get()) {
@@ -183,11 +183,10 @@ public class MovementDescend extends Movement {
}
BlockPos playerFeet = playerFeet();
if (playerFeet.equals(dest)) {
if (BlockStateInterface.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094) { // lilypads
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
return state.setStatus(MovementStatus.SUCCESS);
}/* else {
if (playerFeet.equals(dest) && (MovementHelper.isLiquid(dest) || player().posY - playerFeet.getY() < 0.094)) { // lilypads
// Wait until we're actually on the ground before saying we're done because sometimes we continue to fall if the next action starts immediately
return state.setStatus(MovementStatus.SUCCESS);
/* else {
// System.out.println(player().posY + " " + playerFeet.getY() + " " + (player().posY - playerFeet.getY()));
}*/
}
@@ -78,11 +78,11 @@ public class MovementDiagonal extends Movement {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
}
Block cuttingOver1 = BlockStateInterface.get(x, y - 1, destZ).getBlock();
if (cuttingOver1 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver1)) {
if (cuttingOver1 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver1)) {
return COST_INF;
}
Block cuttingOver2 = BlockStateInterface.get(destX, y - 1, z).getBlock();
if (cuttingOver2 == Blocks.MAGMA || BlockStateInterface.isLava(cuttingOver2)) {
if (cuttingOver2 == Blocks.MAGMA || MovementHelper.isLava(cuttingOver2)) {
return COST_INF;
}
IBlockState pb0 = BlockStateInterface.get(x, y, destZ);
@@ -101,25 +101,22 @@ public class MovementDiagonal extends Movement {
return COST_INF;
}
IBlockState pb3 = BlockStateInterface.get(destX, y + 1, z);
if (optionA == 0) {
if (optionA == 0 && ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER))) {
// at this point we're done calculating optionA, so we can check if it's actually possible to edge around in that direction
if ((MovementHelper.avoidWalkingInto(pb2.getBlock()) && pb2.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb3.getBlock()) && pb3.getBlock() != Blocks.WATER)) {
return COST_INF;
}
return COST_INF;
}
optionB += MovementHelper.getMiningDurationTicks(context, destX, y + 1, z, pb3, true);
if (optionA != 0 && optionB != 0) {
// and finally, if the cost is nonzero for both ways to approach this diagonal, it's not possible
return COST_INF;
}
if (optionB == 0) {
if (optionB == 0 && ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER))) {
// and now that option B is fully calculated, see if we can edge around that way
if ((MovementHelper.avoidWalkingInto(pb0.getBlock()) && pb0.getBlock() != Blocks.WATER) || (MovementHelper.avoidWalkingInto(pb1.getBlock()) && pb1.getBlock() != Blocks.WATER)) {
return COST_INF;
}
return COST_INF;
}
boolean water = false;
if (BlockStateInterface.isWater(BlockStateInterface.getBlock(x, y, z)) || BlockStateInterface.isWater(destInto.getBlock())) {
Block startIn = BlockStateInterface.getBlock(x, y, z);
if (MovementHelper.isWater(startIn) || MovementHelper.isWater(destInto.getBlock())) {
// 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
@@ -128,6 +125,10 @@ public class MovementDiagonal extends Movement {
}
if (optionA != 0 || optionB != 0) {
multiplier *= SQRT_2 - 0.001; // TODO tune
if (startIn == Blocks.LADDER || startIn == Blocks.VINE) {
// edging around doesn't work if doing so would climb a ladder or vine instead of moving sideways
return COST_INF;
}
}
if (context.canSprint() && !water) {
// If we aren't edging around anything, and we aren't in water
@@ -149,7 +150,7 @@ public class MovementDiagonal extends Movement {
state.setStatus(MovementStatus.SUCCESS);
return state;
}
if (!BlockStateInterface.isLiquid(playerFeet())) {
if (!MovementHelper.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
MovementHelper.moveTowards(state, dest);
@@ -25,7 +25,6 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.entity.player.InventoryPlayer;
@@ -63,7 +62,7 @@ public class MovementFall extends Movement {
BlockPos playerFeet = playerFeet();
Rotation targetRotation = null;
if (!BlockStateInterface.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
if (!MovementHelper.isWater(dest) && src.getY() - dest.getY() > Baritone.settings().maxFallHeightNoWater.get() && !playerFeet.equals(dest)) {
if (!InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_WATER)) || world().provider.isNether()) {
return state.setStatus(MovementStatus.UNREACHABLE);
}
@@ -84,8 +83,8 @@ public class MovementFall extends Movement {
} else {
state.setTarget(new MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
}
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || BlockStateInterface.isWater(dest))) { // 0.094 because lilypads
if (BlockStateInterface.isWater(dest)) {
if (playerFeet.equals(dest) && (player().posY - playerFeet.getY() < 0.094 || MovementHelper.isWater(dest))) { // 0.094 because lilypads
if (MovementHelper.isWater(dest)) {
if (InventoryPlayer.isHotbar(player().inventory.getSlotFor(STACK_BUCKET_EMPTY))) {
player().inventory.currentItem = player().inventory.getSlotFor(STACK_BUCKET_EMPTY);
if (player().motionY >= 0) {
@@ -32,6 +32,7 @@ import baritone.utils.Helper;
import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block;
import net.minecraft.block.BlockStairs;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
@@ -68,7 +69,7 @@ public class MovementParkour extends Movement {
return;
}
IBlockState standingOn = BlockStateInterface.get(x, y - 1, z);
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || MovementHelper.isBottomSlab(standingOn)) {
if (standingOn.getBlock() == Blocks.VINE || standingOn.getBlock() == Blocks.LADDER || standingOn.getBlock() instanceof BlockStairs || MovementHelper.isBottomSlab(standingOn)) {
return;
}
int xDiff = dir.getXOffset();
@@ -124,7 +125,7 @@ public class MovementParkour extends Movement {
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
return;
}
if (toPlace.getBlock() != Blocks.AIR && !BlockStateInterface.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
if (toPlace.getBlock() != Blocks.AIR && !MovementHelper.isWater(toPlace.getBlock()) && !MovementHelper.isReplacable(destX, y - 1, destZ, toPlace)) {
return;
}
for (int i = 0; i < 5; i++) {
@@ -202,7 +203,7 @@ public class MovementParkour extends Movement {
} else if (!playerFeet().equals(src)) {
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
if (!MovementHelper.canWalkOn(dest.down())) {
if (!MovementHelper.canWalkOn(dest.down()) && !player().onGround) {
BlockPos positionToPlace = dest.down();
for (int i = 0; i < 5; i++) {
BlockPos against1 = positionToPlace.offset(HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i]);
@@ -54,16 +54,12 @@ public class MovementPillar extends Movement {
if (fromDownDown.getBlock() instanceof BlockLadder || fromDownDown.getBlock() instanceof BlockVine) {
return COST_INF;
}
if (fromDownDown.getBlock() instanceof BlockSlab) {
if (!((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
}
if (fromDownDown.getBlock() instanceof BlockSlab && !((BlockSlab) fromDownDown.getBlock()).isDouble() && fromDownDown.getValue(BlockSlab.HALF) == BlockSlab.EnumBlockHalf.BOTTOM) {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder
}
}
if (fromDown instanceof BlockVine) {
if (!hasAgainst(x, y, z)) {
return COST_INF;
}
if (fromDown instanceof BlockVine && !hasAgainst(x, y, z)) {
return COST_INF;
}
IBlockState toBreak = BlockStateInterface.get(x, y + 2, z);
Block toBreakBlock = toBreak.getBlock();
@@ -71,9 +67,9 @@ public class MovementPillar extends Movement {
return COST_INF;
}
Block srcUp = null;
if (BlockStateInterface.isWater(toBreakBlock) && BlockStateInterface.isWater(fromDown)) {
if (MovementHelper.isWater(toBreakBlock) && MovementHelper.isWater(fromDown)) {
srcUp = BlockStateInterface.get(x, y + 1, z).getBlock();
if (BlockStateInterface.isWater(srcUp)) {
if (MovementHelper.isWater(srcUp)) {
return LADDER_UP_ONE_COST;
}
}
@@ -148,7 +144,7 @@ public class MovementPillar extends Movement {
}
IBlockState fromDown = BlockStateInterface.get(src);
if (BlockStateInterface.isWater(fromDown.getBlock()) && BlockStateInterface.isWater(dest)) {
if (MovementHelper.isWater(fromDown.getBlock()) && MovementHelper.isWater(dest)) {
// stay centered while swimming up a water column
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.getBlockPosCenter(dest)), false));
Vec3d destCenter = VecUtils.getBlockPosCenter(dest);
@@ -162,10 +158,11 @@ public class MovementPillar extends Movement {
}
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine;
boolean vine = fromDown.getBlock() instanceof BlockVine;
Rotation rotation = RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch));
if (!ladder) {
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(mc.player.getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(mc.player.rotationYaw, mc.player.rotationPitch)), true));
state.setTarget(new MovementState.MovementTarget(new Rotation(mc.player.rotationYaw, rotation.getPitch()), true));
}
boolean blockIsThere = MovementHelper.canWalkOn(src) || ladder;
@@ -198,7 +195,8 @@ public class MovementPillar extends Movement {
// If our Y coordinate is above our goal, stop jumping
state.setInput(InputOverrideHandler.Input.JUMP, player().posY < dest.getY());
state.setInput(InputOverrideHandler.Input.SNEAK, true);
state.setInput(InputOverrideHandler.Input.SNEAK, player().posY > dest.getY()); // delay placement by 1 tick for ncp compatibility
// since (lower down) we only right click once player.isSneaking, and that happens the tick after we request to sneak
double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5);
@@ -209,6 +207,9 @@ public class MovementPillar extends Movement {
// If it's been more than forty ticks of trying to jump and we aren't done yet, go forward, maybe we are stuck
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
// revise our target to both yaw and pitch if we're going to be moving forward
state.setTarget(new MovementState.MovementTarget(rotation, true));
}
@@ -217,7 +218,7 @@ public class MovementPillar extends Movement {
if (!(fr instanceof BlockAir || fr.isReplaceable(Minecraft.getMinecraft().world, src))) {
state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
blockIsThere = false;
} else if (Minecraft.getMinecraft().player.isSneaking()) {
} else if (Minecraft.getMinecraft().player.isSneaking()) { // 1 tick after we're able to place
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
}
@@ -239,7 +240,7 @@ public class MovementPillar extends Movement {
state.setInput(InputOverrideHandler.Input.SNEAK, true);
}
}
if (BlockStateInterface.isWater(dest.up())) {
if (MovementHelper.isWater(dest.up())) {
return true;
}
return super.prepared(state);
@@ -66,7 +66,7 @@ public class MovementTraverse extends Movement {
if (MovementHelper.canWalkOn(destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
double WC = WALK_ONE_BLOCK_COST;
boolean water = false;
if (BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock())) {
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
WC = context.waterWalkSpeed();
water = true;
} else {
@@ -101,18 +101,18 @@ public class MovementTraverse extends Movement {
return COST_INF;
}
if (destOn.getBlock().equals(Blocks.AIR) || MovementHelper.isReplacable(destX, y - 1, destZ, destOn)) {
boolean throughWater = BlockStateInterface.isWater(pb0.getBlock()) || BlockStateInterface.isWater(pb1.getBlock());
if (BlockStateInterface.isWater(destOn.getBlock()) && throughWater) {
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
return COST_INF;
}
if (!context.canPlaceThrowawayAt(destX, y - 1, destZ)) {
return COST_INF;
}
double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb0, false);
double hardness1 = MovementHelper.getMiningDurationTicks(context, destX, y, destZ, pb1, false);
if (hardness1 >= COST_INF) {
return COST_INF;
}
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb1, true);
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true);
double WC = throughWater ? context.waterWalkSpeed() : WALK_ONE_BLOCK_COST;
for (int i = 0; i < 4; i++) {
@@ -189,11 +189,9 @@ public class MovementTraverse extends Movement {
} else if (pb1.getBlock() instanceof BlockDoor && !MovementHelper.isDoorPassable(dest, src)) {
isDoorActuallyBlockingUs = true;
}
if (isDoorActuallyBlockingUs) {
if (!(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.calculateBlockCenter(positionsToBreak[0])), true))
.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
if (isDoorActuallyBlockingUs && !(Blocks.IRON_DOOR.equals(pb0.getBlock()) || Blocks.IRON_DOOR.equals(pb1.getBlock()))) {
return state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), VecUtils.calculateBlockCenter(positionsToBreak[0])), true))
.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
}
@@ -225,7 +223,7 @@ public class MovementTraverse extends Movement {
if (playerFeet().equals(dest)) {
return state.setStatus(MovementStatus.SUCCESS);
}
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
if (wasTheBridgeBlockAlwaysThere && !MovementHelper.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
}
Block destDown = BlockStateInterface.get(dest.down()).getBlock();
@@ -267,11 +265,8 @@ public class MovementTraverse extends Movement {
state.setTarget(new MovementState.MovementTarget(RotationUtils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), against1) && (Minecraft.getMinecraft().player.isSneaking() || Baritone.settings().assumeSafeWalk.get())) {
if (RayTraceUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
// wrong side?
if (Objects.equals(RayTraceUtils.getSelectedBlock().orElse(null), against1) && (Minecraft.getMinecraft().player.isSneaking() || Baritone.settings().assumeSafeWalk.get()) && RayTraceUtils.getSelectedBlock().get().offset(side).equals(positionToPlace)) {
return state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
//System.out.println("Trying to look at " + against1 + ", actually looking at" + RayTraceUtils.getSelectedBlock());
return state.setInput(InputOverrideHandler.Input.CLICK_LEFT, true);
@@ -18,7 +18,6 @@
package baritone.pathing.path;
import baritone.Baritone;
import baritone.api.event.events.TickEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.movement.IMovement;
@@ -81,14 +80,10 @@ public class PathExecutor implements IPathExecutor, Helper {
/**
* Tick this executor
*
* @param event
* @return True if a movement just finished (and the player is therefore in a "stable" state, like,
* not sneaking out over lava), false otherwise
*/
public boolean onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
throw new IllegalStateException();
}
public boolean onTick() {
if (pathPosition == path.length() - 1) {
pathPosition++;
}
@@ -261,7 +256,7 @@ public class PathExecutor implements IPathExecutor, Helper {
//System.out.println("Movement done, next path");
pathPosition++;
onChangeInPathPosition();
onTick(event);
onTick();
return true;
} else {
sprintIfRequested();
@@ -276,7 +271,7 @@ public class PathExecutor implements IPathExecutor, Helper {
return true;
}
}
return false; // movement is in progress
return canCancel; // movement is in progress, but if it reports cancellable, PathingBehavior is good to cut onto the next path
}
private Tuple<Double, BlockPos> closestPathPos(IPath path) {
@@ -331,10 +326,7 @@ public class PathExecutor implements IPathExecutor, Helper {
// when we're midair in the middle of a fall, we're very far from both the beginning and the end, but we aren't actually off path
if (path.movements().get(pathPosition) instanceof MovementFall) {
BlockPos fallDest = path.positions().get(pathPosition + 1); // .get(pathPosition) is the block we fell off of
if (VecUtils.entityFlatDistanceToCenter(player(), fallDest) < leniency) { // ignore Y by using flat distance
return false;
}
return true;
return VecUtils.entityFlatDistanceToCenter(player(), fallDest) >= leniency; // ignore Y by using flat distance
} else {
return true;
}
@@ -432,20 +424,13 @@ public class PathExecutor implements IPathExecutor, Helper {
}
private static boolean canSprintInto(IMovement current, IMovement next) {
if (next instanceof MovementDescend) {
if (next.getDirection().equals(current.getDirection())) {
return true;
}
}
if (next instanceof MovementTraverse) {
if (next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
return true;
}
}
if (next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get()) {
if (next instanceof MovementDescend && next.getDirection().equals(current.getDirection())) {
return true;
}
return false;
if (next instanceof MovementTraverse && next.getDirection().down().equals(current.getDirection()) && MovementHelper.canWalkOn(next.getDest().down())) {
return true;
}
return next instanceof MovementDiagonal && Baritone.settings().allowOvershootDiagonalDescend.get();
}
private void onChangeInPathPosition() {
@@ -17,11 +17,11 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.event.events.TickEvent;
import baritone.api.event.listener.AbstractGameEventListener;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.behavior.PathingBehavior;
import net.minecraft.client.Minecraft;
import net.minecraft.client.gui.GuiMainMenu;
import net.minecraft.client.settings.GameSettings;
@@ -105,8 +105,8 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
}
// Setup Baritone's pathing goal and (if needed) begin pathing
PathingBehavior.INSTANCE.setGoal(GOAL);
PathingBehavior.INSTANCE.path();
Baritone.INSTANCE.getPathingBehavior().setGoal(GOAL);
Baritone.INSTANCE.getPathingBehavior().path();
// If we have reached our goal, print a message and safely close the game
if (GOAL.isInGoal(playerFeet())) {
@@ -22,7 +22,6 @@ import baritone.cache.CachedRegion;
import baritone.cache.WorldData;
import baritone.cache.WorldProvider;
import net.minecraft.block.Block;
import net.minecraft.block.BlockLiquid;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
@@ -128,47 +127,4 @@ public class BlockStateInterface implements Helper {
public static Block getBlock(int x, int y, int z) {
return get(x, y, z).getBlock();
}
/**
* Returns whether or not the specified block is
* water, regardless of whether or not it is flowing.
*
* @param b The block
* @return Whether or not the block is water
*/
public static boolean isWater(Block b) {
return b == Blocks.FLOWING_WATER || b == Blocks.WATER;
}
/**
* Returns whether or not the block at the specified pos is
* water, regardless of whether or not it is flowing.
*
* @param bp The block pos
* @return Whether or not the block is water
*/
public static boolean isWater(BlockPos bp) {
return isWater(BlockStateInterface.getBlock(bp));
}
public static boolean isLava(Block b) {
return b == Blocks.FLOWING_LAVA || b == Blocks.LAVA;
}
/**
* Returns whether or not the specified pos has a liquid
*
* @param p The pos
* @return Whether or not the block is a liquid
*/
public static boolean isLiquid(BlockPos p) {
return BlockStateInterface.getBlock(p) instanceof BlockLiquid;
}
public static boolean isFlowing(IBlockState state) {
// Will be IFluidState in 1.13
return state.getBlock() instanceof BlockLiquid
&& state.getPropertyKeys().contains(BlockLiquid.LEVEL)
&& state.getValue(BlockLiquid.LEVEL) != 0;
}
}
@@ -26,8 +26,6 @@ import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior;
import baritone.behavior.FollowBehavior;
import baritone.behavior.MineBehavior;
import baritone.behavior.PathingBehavior;
import baritone.cache.ChunkPacker;
import baritone.cache.Waypoint;
@@ -48,47 +46,83 @@ import java.util.stream.Stream;
public class ExampleBaritoneControl extends Behavior implements Helper {
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
public static ExampleBaritoneControl INSTANCE; // compatibility with impact 4.4
private ExampleBaritoneControl() {
private static final String HELP_MSG =
"baritone - Output settings into chat\n" +
"settings - Same as baritone\n" +
"goal - Create a goal (one number is '<Y>', two is '<X> <Z>', three is '<X> <Y> <Z>, 'clear' to clear)\n" +
"path - Go towards goal\n" +
"repack - (debug) Repacks chunk cache\n" +
"rescan - (debug) Same as repack\n" +
"axis - Paths towards the closest axis or diagonal axis, at y=120\n" +
"cancel - Cancels current path\n" +
"forcecancel - sudo cancel (only use if very glitched, try toggling 'pause' first)\n" +
"gc - Calls System.gc();\n" +
"invert - Runs away from the goal instead of towards it\n" +
"follow - Follows a player 'follow username'\n" +
"reloadall - (debug) Reloads chunk cache\n" +
"saveall - (debug) Saves chunk cache\n" +
"find - (debug) outputs how many blocks of a certain type are within the cache\n" +
"mine - Paths to and mines specified blocks 'mine x_ore y_ore ...'\n" +
"thisway - Creates a goal X blocks where you're facing\n" +
"list - Lists waypoints under a category\n" +
"get - Same as list\n" +
"show - Same as list\n" +
"save - Saves a waypoint (works but don't try to make sense of it)\n" +
"goto - Paths towards specified block or waypoint\n" +
"spawn - Paths towards world spawn or your most recent bed right-click\n" +
"sethome - Sets \"home\"\n" +
"home - Paths towards \"home\" \n" +
"costs - (debug) all movement costs from current location\n" +
"pause - Toggle pause\n" +
"damn - Daniel ";
}
public void initAndRegister() {
Baritone.INSTANCE.registerBehavior(this);
public ExampleBaritoneControl(Baritone baritone) {
super(baritone);
INSTANCE = this;
}
@Override
public void onSendChatMessage(ChatEvent event) {
if (!Baritone.settings().chatControl.get()) {
if (!Baritone.settings().removePrefix.get()) {
return;
}
if (!Baritone.settings().chatControl.get() && !Baritone.settings().removePrefix.get()) {
return;
}
String msg = event.getMessage().toLowerCase(Locale.US);
String msg = event.getMessage();
if (Baritone.settings().prefix.get()) {
if (!msg.startsWith("#")) {
return;
}
msg = msg.substring(1);
}
if (runCommand(msg)) {
event.cancel();
}
}
public boolean runCommand(String msg0) {
String msg = msg0.toLowerCase(Locale.US).trim(); // don't reassign the argument LOL
PathingBehavior pathingBehavior = baritone.getPathingBehavior();
List<Settings.Setting<Boolean>> toggleable = Baritone.settings().getAllValuesByType(Boolean.class);
for (Settings.Setting<Boolean> setting : toggleable) {
if (msg.equalsIgnoreCase(setting.getName())) {
setting.value ^= true;
event.cancel();
logDirect("Toggled " + setting.getName() + " to " + setting.value);
SettingsUtil.save(Baritone.settings());
return;
return true;
}
}
if (msg.equals("baritone") || msg.equals("settings")) {
for (Settings.Setting<?> setting : Baritone.settings().allSettings) {
logDirect(setting.toString());
}
event.cancel();
return;
return true;
}
if (msg.equals("") || msg.equals("help") || msg.equals("?")) {
for (String line : HELP_MSG.split("\n")) {
logDirect(line);
}
return false;
}
if (msg.contains(" ")) {
String[] data = msg.split(" ");
@@ -110,25 +144,21 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
}
} catch (NumberFormatException e) {
logDirect("Unable to parse " + data[1]);
event.cancel();
return;
return true;
}
SettingsUtil.save(Baritone.settings());
logDirect(setting.toString());
event.cancel();
return;
return true;
}
}
}
if (Baritone.settings().byLowerName.containsKey(msg)) {
Settings.Setting<?> setting = Baritone.settings().byLowerName.get(msg);
logDirect(setting.toString());
event.cancel();
return;
return true;
}
if (msg.startsWith("goal")) {
event.cancel();
String[] params = msg.substring(4).trim().split(" ");
if (params[0].equals("")) {
params = new String[]{};
@@ -154,30 +184,29 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
break;
default:
logDirect("unable to understand lol");
return;
return true;
}
} catch (NumberFormatException ex) {
logDirect("unable to parse integer " + ex);
return;
return true;
}
PathingBehavior.INSTANCE.setGoal(goal);
pathingBehavior.setGoal(goal);
logDirect("Goal: " + goal);
return;
return true;
}
if (msg.equals("path")) {
if (!PathingBehavior.INSTANCE.path()) {
if (PathingBehavior.INSTANCE.getGoal() == null) {
if (!pathingBehavior.path()) {
if (pathingBehavior.getGoal() == null) {
logDirect("No goal.");
} else {
if (PathingBehavior.INSTANCE.getGoal().isInGoal(playerFeet())) {
if (pathingBehavior.getGoal().isInGoal(playerFeet())) {
logDirect("Already in goal");
} else {
logDirect("Currently executing a path. Please cancel it first.");
}
}
}
event.cancel();
return;
return true;
}
if (msg.equals("repack") || msg.equals("rescan")) {
ChunkProviderClient cli = world().getChunkProvider();
@@ -194,41 +223,36 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
}
}
logDirect("Queued " + count + " chunks for repacking");
event.cancel();
return;
return true;
}
if (msg.equals("axis")) {
PathingBehavior.INSTANCE.setGoal(new GoalAxis());
PathingBehavior.INSTANCE.path();
event.cancel();
return;
pathingBehavior.setGoal(new GoalAxis());
pathingBehavior.path();
return true;
}
if (msg.equals("cancel") || msg.equals("stop")) {
MineBehavior.INSTANCE.cancel();
FollowBehavior.INSTANCE.cancel();
PathingBehavior.INSTANCE.cancel();
event.cancel();
baritone.getMineBehavior().cancel();
baritone.getFollowBehavior().cancel();
pathingBehavior.cancel();
logDirect("ok canceled");
return;
return true;
}
if (msg.equals("forcecancel")) {
MineBehavior.INSTANCE.cancel();
FollowBehavior.INSTANCE.cancel();
PathingBehavior.INSTANCE.cancel();
baritone.getMineBehavior().cancel();
baritone.getFollowBehavior().cancel();
pathingBehavior.cancel();
AbstractNodeCostSearch.forceCancel();
PathingBehavior.INSTANCE.forceCancel();
event.cancel();
pathingBehavior.forceCancel();
logDirect("ok force canceled");
return;
return true;
}
if (msg.equals("gc")) {
System.gc();
event.cancel();
logDirect("Called System.gc();");
return;
return true;
}
if (msg.equals("invert")) {
Goal goal = PathingBehavior.INSTANCE.getGoal();
Goal goal = pathingBehavior.getGoal();
BlockPos runAwayFrom;
if (goal instanceof GoalXZ) {
runAwayFrom = new BlockPos(((GoalXZ) goal).getX(), 0, ((GoalXZ) goal).getZ());
@@ -239,17 +263,16 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("Inverting goal of player feet");
runAwayFrom = playerFeet();
}
PathingBehavior.INSTANCE.setGoal(new GoalRunAway(1, runAwayFrom) {
pathingBehavior.setGoal(new GoalRunAway(1, runAwayFrom) {
@Override
public boolean isInGoal(BlockPos pos) {
public boolean isInGoal(int x, int y, int z) {
return false;
}
});
if (!PathingBehavior.INSTANCE.path()) {
if (!pathingBehavior.path()) {
logDirect("Currently executing a path. Please cancel it first.");
}
event.cancel();
return;
return true;
}
if (msg.startsWith("follow")) {
String name = msg.substring(6).trim();
@@ -259,34 +282,28 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
} else {
for (EntityPlayer pl : world().playerEntities) {
String theirName = pl.getName().trim().toLowerCase();
if (!theirName.equals(player().getName().trim().toLowerCase())) { // don't follow ourselves lol
if (theirName.contains(name) || name.contains(theirName)) {
toFollow = Optional.of(pl);
}
if (!theirName.equals(player().getName().trim().toLowerCase()) && (theirName.contains(name) || name.contains(theirName))) { // don't follow ourselves lol
toFollow = Optional.of(pl);
}
}
}
if (!toFollow.isPresent()) {
logDirect("Not found");
event.cancel();
return;
return true;
}
FollowBehavior.INSTANCE.follow(toFollow.get());
baritone.getFollowBehavior().follow(toFollow.get());
logDirect("Following " + toFollow.get());
event.cancel();
return;
return true;
}
if (msg.equals("reloadall")) {
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().reloadAllFromDisk();
logDirect("ok");
event.cancel();
return;
return true;
}
if (msg.equals("saveall")) {
WorldProvider.INSTANCE.getCurrentWorld().getCachedWorld().save();
logDirect("ok");
event.cancel();
return;
return true;
}
if (msg.startsWith("find")) {
String blockType = msg.substring(4).trim();
@@ -298,8 +315,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
System.out.println("Was looking for " + blockType + " but actually found " + actually + " " + ChunkPacker.blockToString(actually));
}
}
event.cancel();
return;
return true;
}
if (msg.startsWith("mine")) {
String[] blockTypes = msg.substring(4).trim().split(" ");
@@ -307,34 +323,30 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
int quantity = Integer.parseInt(blockTypes[1]);
Block block = ChunkPacker.stringToBlock(blockTypes[0]);
Objects.requireNonNull(block);
MineBehavior.INSTANCE.mine(quantity, block);
baritone.getMineBehavior().mine(quantity, block);
logDirect("Will mine " + quantity + " " + blockTypes[0]);
event.cancel();
return;
return true;
} catch (NumberFormatException | ArrayIndexOutOfBoundsException | NullPointerException ex) {}
for (String s : blockTypes) {
if (ChunkPacker.stringToBlock(s) == null) {
logDirect(s + " isn't a valid block name");
event.cancel();
return;
return true;
}
}
MineBehavior.INSTANCE.mine(0, blockTypes);
baritone.getMineBehavior().mine(0, blockTypes);
logDirect("Started mining blocks of type " + Arrays.toString(blockTypes));
event.cancel();
return;
return true;
}
if (msg.startsWith("thisway")) {
try {
Goal goal = GoalXZ.fromDirection(playerFeetAsVec(), player().rotationYaw, Double.parseDouble(msg.substring(7).trim()));
PathingBehavior.INSTANCE.setGoal(goal);
pathingBehavior.setGoal(goal);
logDirect("Goal: " + goal);
} catch (NumberFormatException ex) {
logDirect("Error unable to parse '" + msg.substring(7).trim() + "' to a double.");
}
event.cancel();
return;
return true;
}
if (msg.startsWith("list") || msg.startsWith("get ") || msg.startsWith("show")) {
String waypointType = msg.substring(4).trim();
@@ -345,8 +357,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
Waypoint.Tag tag = Waypoint.Tag.fromString(waypointType);
if (tag == null) {
logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
event.cancel();
return;
return true;
}
Set<IWaypoint> waypoints = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getByTag(tag);
// might as well show them from oldest to newest
@@ -356,11 +367,9 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
for (IWaypoint waypoint : sorted) {
logDirect(waypoint.toString());
}
event.cancel();
return;
return true;
}
if (msg.startsWith("save")) {
event.cancel();
String name = msg.substring(4).trim();
BlockPos pos = playerFeet();
if (name.contains(" ")) {
@@ -368,19 +377,19 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
String[] parts = name.split(" ");
if (parts.length != 4) {
logDirect("Unable to parse, expected four things");
return;
return true;
}
try {
pos = new BlockPos(Integer.parseInt(parts[1]), Integer.parseInt(parts[2]), Integer.parseInt(parts[3]));
} catch (NumberFormatException ex) {
logDirect("Unable to parse coordinate integers");
return;
return true;
}
name = parts[0];
}
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint(name, Waypoint.Tag.USER, pos));
logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto user' to set goal, say 'list user' to list.");
return;
logDirect("Saved user defined position " + pos + " under name '" + name + "'. Say 'goto " + name + "' to set goal, say 'list user' to list custom waypoints.");
return true;
}
if (msg.startsWith("goto")) {
String waypointType = msg.substring(4).trim();
@@ -394,40 +403,35 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
String mining = waypointType;
Block block = ChunkPacker.stringToBlock(mining);
//logDirect("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
event.cancel();
if (block == null) {
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getAllWaypoints().stream().filter(w -> w.getName().equalsIgnoreCase(mining)).max(Comparator.comparingLong(IWaypoint::getCreationTimestamp)).orElse(null);
if (waypoint == null) {
logDirect("No locations for " + mining + " known, cancelling");
return;
return true;
}
} else {
List<BlockPos> locs = MineBehavior.INSTANCE.scanFor(Collections.singletonList(block), 64);
List<BlockPos> locs = baritone.getMineBehavior().searchWorld(Collections.singletonList(block), 64, world());
if (locs.isEmpty()) {
logDirect("No locations for " + mining + " known, cancelling");
return;
return true;
}
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
PathingBehavior.INSTANCE.path();
return;
pathingBehavior.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
pathingBehavior.path();
return true;
}
} else {
waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(tag);
if (waypoint == null) {
logDirect("None saved for tag " + tag);
event.cancel();
return;
return true;
}
}
Goal goal = new GoalBlock(waypoint.getLocation());
PathingBehavior.INSTANCE.setGoal(goal);
if (!PathingBehavior.INSTANCE.path()) {
if (!goal.isInGoal(playerFeet())) {
logDirect("Currently executing a path. Please cancel it first.");
}
pathingBehavior.setGoal(goal);
if (!pathingBehavior.path() && !goal.isInGoal(playerFeet())) {
logDirect("Currently executing a path. Please cancel it first.");
}
event.cancel();
return;
return true;
}
if (msg.equals("spawn") || msg.equals("bed")) {
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.BED);
@@ -436,20 +440,18 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
// for some reason the default spawnpoint is underground sometimes
Goal goal = new GoalXZ(spawnPoint.getX(), spawnPoint.getZ());
logDirect("spawn not saved, defaulting to world spawn. set goal to " + goal);
PathingBehavior.INSTANCE.setGoal(goal);
pathingBehavior.setGoal(goal);
} else {
Goal goal = new GoalBlock(waypoint.getLocation());
PathingBehavior.INSTANCE.setGoal(goal);
pathingBehavior.setGoal(goal);
logDirect("Set goal to most recent bed " + goal);
}
event.cancel();
return;
return true;
}
if (msg.equals("sethome")) {
WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().addWaypoint(new Waypoint("", Waypoint.Tag.HOME, playerFeet()));
logDirect("Saved. Say home to set goal.");
event.cancel();
return;
return true;
}
if (msg.equals("home")) {
IWaypoint waypoint = WorldProvider.INSTANCE.getCurrentWorld().getWaypoints().getMostRecentByTag(Waypoint.Tag.HOME);
@@ -457,12 +459,11 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
logDirect("home not saved");
} else {
Goal goal = new GoalBlock(waypoint.getLocation());
PathingBehavior.INSTANCE.setGoal(goal);
PathingBehavior.INSTANCE.path();
pathingBehavior.setGoal(goal);
pathingBehavior.path();
logDirect("Going to saved home " + goal);
}
event.cancel();
return;
return true;
}
if (msg.equals("costs")) {
List<Movement> moves = Stream.of(Moves.values()).map(x -> x.apply0(playerFeet())).collect(Collectors.toCollection(ArrayList::new));
@@ -479,18 +480,16 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
}
logDirect(parts[parts.length - 1] + " " + move.getDest().getX() + "," + move.getDest().getY() + "," + move.getDest().getZ() + " " + strCost);
}
event.cancel();
return;
return true;
}
if (msg.equals("pause")) {
boolean enabled = PathingBehavior.INSTANCE.toggle();
boolean enabled = pathingBehavior.toggle();
logDirect("Pathing Behavior has " + (enabled ? "resumed" : "paused") + ".");
event.cancel();
return;
return true;
}
if (msg.equals("damn")) {
logDirect("daniel");
return;
}
return false;
}
}
+114 -58
View File
@@ -23,41 +23,41 @@ import net.minecraft.block.state.IBlockState;
import net.minecraft.enchantment.EnchantmentHelper;
import net.minecraft.init.Enchantments;
import net.minecraft.init.MobEffects;
import net.minecraft.item.Item.ToolMaterial;
import net.minecraft.item.ItemStack;
import net.minecraft.item.ItemTool;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Function;
/**
* A cached list of the best tools on the hotbar for any block
*
* @author avecowa, Brady, leijurv
* @author Avery, Brady, leijurv
*/
public class ToolSet implements Helper {
/**
* A cache mapping a {@link Block} to how long it will take to break
* with this toolset, given the optimum tool is used.
*/
private Map<Block, Double> breakStrengthCache = new HashMap<>();
private final Map<Block, Double> breakStrengthCache;
/**
* Calculate which tool on the hotbar is best for mining
*
* @param b the blockstate to be mined
* @return a byte indicating the index in the tools array that worked best
* My buddy leijurv owned me so we have this to not create a new lambda instance.
*/
public byte getBestSlot(IBlockState b) {
byte best = 0;
double value = -1;
for (byte i = 0; i < 9; i++) {
double v = calculateStrVsBlock(i, b);
if (v > value || value == -1) {
value = v;
best = i;
}
private final Function<Block, Double> backendCalculation;
public ToolSet() {
breakStrengthCache = new HashMap<>();
if (Baritone.settings().considerPotionEffects.get()) {
double amplifier = potionAmplifier();
Function<Double, Double> amplify = x -> amplifier * x;
backendCalculation = amplify.compose(this::getBestDestructionTime);
} else {
backendCalculation = this::getBestDestructionTime;
}
return best;
}
/**
@@ -67,14 +67,64 @@ public class ToolSet implements Helper {
* @return how long it would take in ticks
*/
public double getStrVsBlock(IBlockState state) {
Double strength = this.breakStrengthCache.get(state.getBlock());
if (strength != null) {
// the function will take this path >99% of the time
return strength;
return breakStrengthCache.computeIfAbsent(state.getBlock(), backendCalculation);
}
/**
* Evaluate the material cost of a possible tool. The priority matches the
* listed order in the Item.ToolMaterial enum.
*
* @param itemStack a possibly empty ItemStack
* @return values range from -1 to 4
*/
private int getMaterialCost(ItemStack itemStack) {
if (itemStack.getItem() instanceof ItemTool) {
ItemTool tool = (ItemTool) itemStack.getItem();
return ToolMaterial.valueOf(tool.getToolMaterialName()).ordinal();
} else {
return -1;
}
double str = calculateStrVsBlock(getBestSlot(state), state);
this.breakStrengthCache.put(state.getBlock(), str);
return str;
}
/**
* Calculate which tool on the hotbar is best for mining
*
* @param b the blockstate to be mined
* @return A byte containing the index in the tools array that worked best
*/
public byte getBestSlot(Block b) {
byte best = 0;
double value = Double.NEGATIVE_INFINITY;
int materialCost = Integer.MIN_VALUE;
IBlockState blockState = b.getDefaultState();
for (byte i = 0; i < 9; i++) {
ItemStack itemStack = player().inventory.getStackInSlot(i);
double v = calculateStrVsBlock(itemStack, blockState);
if (v > value) {
value = v;
best = i;
materialCost = getMaterialCost(itemStack);
} else if (v == value) {
int c = getMaterialCost(itemStack);
if (c < materialCost) {
value = v;
best = i;
materialCost = c;
}
}
}
return best;
}
/**
* Calculate how effectively a block can be destroyed
*
* @param b the blockstate to be mined
* @return A double containing the destruction ticks with the best tool
*/
private double getBestDestructionTime(Block b) {
ItemStack stack = player().inventory.getStackInSlot(getBestSlot(b));
return calculateStrVsBlock(stack, b.getDefaultState());
}
/**
@@ -84,49 +134,55 @@ public class ToolSet implements Helper {
* @param state the blockstate to be mined
* @return how long it would take in ticks
*/
private double calculateStrVsBlock(byte slot, IBlockState state) {
// Calculate the slot with the best item
ItemStack contents = player().inventory.getStackInSlot(slot);
float blockHard = state.getBlockHardness(null, null);
if (blockHard < 0) {
private double calculateStrVsBlock(ItemStack item, IBlockState state) {
float hardness = state.getBlockHardness(null, null);
if (hardness < 0) {
return -1;
}
float speed = contents.getDestroySpeed(state);
float speed = item.getDestroySpeed(state);
if (speed > 1) {
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, contents);
if (effLevel > 0 && !contents.isEmpty()) {
int effLevel = EnchantmentHelper.getEnchantmentLevel(Enchantments.EFFICIENCY, item);
if (effLevel > 0 && !item.isEmpty()) {
speed += effLevel * effLevel + 1;
}
}
if (Baritone.settings().considerPotionEffects.get()) {
if (player().isPotionActive(MobEffects.HASTE)) {
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
}
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
case 0:
speed *= 0.3;
break;
case 1:
speed *= 0.09;
break;
case 2:
speed *= 0.0027;
break;
default:
speed *= 0.00081;
break;
}
}
}
speed /= blockHard;
if (state.getMaterial().isToolNotRequired() || (!contents.isEmpty() && contents.canHarvestBlock(state))) {
return speed / 30;
speed /= hardness;
if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) {
speed /= 30;
} else {
return speed / 100;
speed /= 100;
}
return speed;
}
/**
* Calculates any modifier to breaking time based on status effects.
*
* @return a double to scale block breaking speed.
*/
private double potionAmplifier() {
double speed = 1;
if (player().isPotionActive(MobEffects.HASTE)) {
speed *= 1 + (player().getActivePotionEffect(MobEffects.HASTE).getAmplifier() + 1) * 0.2;
}
if (player().isPotionActive(MobEffects.MINING_FATIGUE)) {
switch (player().getActivePotionEffect(MobEffects.MINING_FATIGUE).getAmplifier()) {
case 0:
speed *= 0.3;
break;
case 1:
speed *= 0.09;
break;
case 2:
speed *= 0.0027;
break;
default:
speed *= 0.00081;
break;
}
}
return speed;
}
}