Compare commits

...

62 Commits

Author SHA1 Message Date
Leijurv
0db18a7caf v0.0.8 2018-10-11 11:48:07 -07:00
Leijurv
a1c0f4dbb4 keep baritone provider properly 2018-10-11 11:10:59 -07:00
Brady
db7d3184c9 fINAL 2018-10-11 12:34:40 -05:00
Brady
7dfe6ac3ca Add EntityPlayerSP field to relevant events 2018-10-11 12:32:42 -05:00
Leijurv
8fd921c60e disable cancelOnGoalInvalidation 2018-10-10 21:28:55 -07:00
Leijurv
fec29d03fd automatically break block while suffocating, fixes #33 2018-10-10 21:25:21 -07:00
Leijurv
9bd205f190 center pillar regardless of timing 2018-10-10 21:07:59 -07:00
Leijurv
089037663e tweak backtrack cost favoring coefficient 2018-10-10 21:06:31 -07:00
leijurv
8c0bc3e2ef splice tighter, fixes #44 2018-10-10 20:49:25 -07:00
leijurv
db21045cfb renderPathIgnoreDepth 2018-10-10 20:40:15 -07:00
Leijurv
fbf0f2271c revamp pathStart, fixes #209 2018-10-10 17:05:51 -07:00
Leijurv
7e78ed2139 rework minebehavior threading model, fixes #217 2018-10-10 16:40:33 -07:00
Leijurv
5676acbba6 add off hand, fixes #206 2018-10-10 16:29:48 -07:00
Leijurv
43b155d7b8 better check than air 2018-10-10 16:27:48 -07:00
Brady
93158226b6 The sources jar should use SRG names not MCP 2018-10-10 14:10:02 -05:00
Leijurv
d3bf4ef198 renderSelectionBoxesIgnoreDepth 2018-10-09 19:34:53 -07:00
Leijurv
fc9d13a03c there was literally no reason to have it like that 2018-10-09 17:36:35 -07:00
Leijurv
22d2036657 splice better, fixes #215 2018-10-09 16:40:04 -07:00
Leijurv
9e15960581 fix pause stuttering, fixes #216 2018-10-09 16:13:46 -07:00
leijurv
738ce25ff0 tighten fall column 2018-10-09 11:15:42 -07:00
Brady
5da9347e2c Merge pull request #214 from cabaletta/path-api
Pathing API
2018-10-09 00:14:25 -05:00
Brady
771e892b31 Get Cutoff implementation out of API we DON'T need you 2018-10-09 00:10:50 -05:00
Leijurv
9df5f942de add shebang 2018-10-08 22:01:57 -07:00
Brady
0fb5f3233f MovementStatus javadocs 2018-10-08 23:52:36 -05:00
Leijurv
f17ce87e45 publicize 2018-10-08 21:51:19 -07:00
Leijurv
a497a944a6 bottom of the class 2018-10-08 21:49:36 -07:00
Brady
2e69bbe371 Minimal CutoffResult Javadocs 2018-10-08 23:34:12 -05:00
Brady
875f01c358 More comprehensive IPath javadocs 2018-10-08 23:29:16 -05:00
Leijurv
8e1d827819 v0.0.7 2018-10-08 20:57:06 -07:00
Brady
6a4a8ab2d9 I'm an IDIOT 2018-10-08 21:09:54 -05:00
Brady
8278576227 Rename getCurrentPathSearch to getPathFinder 2018-10-08 21:02:55 -05:00
Brady
7d0aa4d7a5 Add override annotation to getPath in PathExecutor 2018-10-08 20:39:33 -05:00
Brady
2b4512ee3f Move to API 2018-10-08 20:37:52 -05:00
Leijurv
413e505683 epic 2018-10-08 18:08:01 -07:00
Leijurv
0f1edba5f1 save settings 2018-10-08 18:05:08 -07:00
Brady
e23a9c976a Bad code 2018-10-08 20:01:44 -05:00
Brady
1449edb8af Didn't need to do that 2018-10-08 19:59:25 -05:00
Brady
d177db5a35 IMovement
Hey would you look at that
2018-10-08 19:57:22 -05:00
Brady
1245e222a7 Begin path api prep 2018-10-08 19:23:43 -05:00
Leijurv
336154fd9b clean up build and remove unnecessary files 2018-10-08 15:25:09 -07:00
Brady
0ee14b4b90 Good javadocs
They're not good they're shit I lied to you
2018-10-08 17:12:51 -05:00
Leijurv
5a9e5cdac4 move rendering, fixes #212 2018-10-08 15:11:07 -07:00
Brady
10bb177664 Add renderGoalIgnoreDepth setting 2018-10-08 17:06:41 -05:00
leijurv
69762bf4b4 fix parkour maybe? fixes #211 2018-10-07 22:08:37 -07:00
leijurv
e17cc79cb3 synchronize MemoryBehavior, fixes #198 2018-10-07 21:55:40 -07:00
leijurv
60c29fd159 actually stop sprinting, fixes #199 2018-10-07 21:40:18 -07:00
Leijurv
7481c98dbc more documentation 2018-10-07 17:57:07 -07:00
Leijurv
796b45601e add info about reproducibility 2018-10-07 17:39:13 -07:00
Leijurv
b5347cebc3 cleanup build gradle 2018-10-07 17:02:21 -07:00
Leijurv
65ce5ca752 fix nullpointerexception in cachedworld 2018-10-07 16:57:04 -07:00
Leijurv
d1e62ef8f2 ok but really this time they're deterministic 2018-10-07 16:56:46 -07:00
Leijurv
db8daf4c59 maybe in jar 2018-10-07 16:07:35 -07:00
Leijurv
80240cb9f2 maybe needs to be higher 2018-10-07 14:23:29 -07:00
Leijurv
4da0731664 deterministic 2018-10-07 12:00:18 -07:00
leijurv
af357d4d8e fix a weird bug 2018-10-06 20:28:47 -07:00
Leijurv
8c76573395 don't pause on one block overlap 2018-10-06 18:43:20 -07:00
Leijurv
939e9c32d5 pause when current best is a backtrack, fixes #201 2018-10-06 18:39:48 -07:00
Brady
e4ef659756 Fix WorldScanner exposure 2018-10-06 20:35:32 -05:00
Brady
4b61452c62 Expose WorldScanner in API 2018-10-06 20:30:09 -05:00
Brady
d5130aa6ba Expose event listener registry in API 2018-10-06 20:16:38 -05:00
Leijurv
6c9f317f31 don't look to the side on a parkour place until the place is in range 2018-10-05 18:27:02 -07:00
Leijurv
1ab5609d4e spam travis less 2018-10-05 15:51:23 -07:00
61 changed files with 1219 additions and 404 deletions

View File

@@ -10,13 +10,16 @@
- **Falling blocks** Baritone understands the costs of breaking blocks with falling blocks on top, and includes all of their break costs. Additionally, since it avoids breaking any blocks touching a liquid, it won't break the bottom of a gravel stack below a lava lake (anymore).
- **Avoiding dangerous blocks** Obviously, it knows not to walk through fire or on magma, not to corner over lava (that deals some damage), not to break any blocks touching a liquid (it might drown), etc.
- **Parkour** Sprint jumping over 1, 2, or 3 block gaps
- **Parkour place** Sprint jumping over a 3 block gap and placing the block to land on while executing the jump. It's really cool.
# Pathing method
Baritone uses a modified version of A*.
Baritone uses A*, with some modifications:
- **Incremental cost backoff** Since most of the time Baritone only knows the terrain up to the render distance, it can't calculate a full path to the goal. Therefore it needs to select a segment to execute first (assuming it will calculate the next segment at the end of this one). It uses incremental cost backoff to select the best node by varying metrics, then paths to that node. This is unchanged from MineBot and I made a <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">write-up</a> that still applies. In essence, it keeps track of the best node by various increasing coefficients, then picks the node with the least coefficient that goes at least 5 blocks from the starting position.
- **Segmented calculation** Traditional A* calculates until the most promising node is in the goal, however in the environment of Minecraft with a limited render distance, we don't know the environment all the way to our goal. Baritone has three possible ways for path calculation to end: finding a path all the way to the goal, running out of time, or getting to the render distance. In the latter two scenarios, the selection of which segment to actually execute falls to the next item (incremental cost backoff). Whenever the path calculation thread finds that the best / most promising node is at the edge of loaded chunks, it increments a counter. If this happens more than 50 times (configurable), path calculation exits early. This happens with very low render distances. Otherwise, calculation continues until the timeout is hit (also configurable) or we find a path all the way to the goal.
- **Incremental cost backoff** When path calculation exits early without getting all the way to the goal, Baritone it needs to select a segment to execute first (assuming it will calculate the next segment at the end of this one). It uses incremental cost backoff to select the best node by varying metrics, then paths to that node. This is unchanged from MineBot and I made a <a href="https://docs.google.com/document/d/1WVHHXKXFdCR1Oz__KtK8sFqyvSwJN_H4lftkHFgmzlc/edit">write-up</a> that still applies. In essence, it keeps track of the best node by various increasing coefficients, then picks the node with the least coefficient that goes at least 5 blocks from the starting position.
- **Minimum improvement repropagation** The pathfinder ignores alternate routes that provide minimal improvements (less than 0.01 ticks of improvement), because the calculation cost of repropagating this to all connected nodes is much higher than the half-millisecond path time improvement it would get.
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment slightly, as a tiebreaker. This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a>
- **Backtrack cost favoring** While calculating the next segment, Baritone favors backtracking its current segment. The cost is decreased heavily, but is still positive (this won't cause it to backtrack if it doesn't need to). This allows it to splice and jump onto the next segment as early as possible, if the next segment begins with a backtrack of the current one. <a href="https://www.youtube.com/watch?v=CGiMcb8-99Y">Example</a>
- **Backtrack detection and pausing** While path calculation happens on a separate thread, the main game thread has access to the latest node considered, and the best path so far (those are rendered light blue and dark blue respectively). When the current best path (rendered dark blue) passes through the player's current position on the current path segment, path execution is paused (if it's safe to do so), because there's no point continuing forward if we're about to turn around and go back that same way. Note that the current best path as reported by the path calculation thread takes into account the incremental cost backoff system, so it's accurate to what the path calculation thread will actually pick once it finishes.
# Configuring Baritone
All the settings and documentation are <a href="https://github.com/cabaletta/baritone/blob/master/src/api/java/baritone/api/Settings.java">here</a>.
@@ -30,6 +33,7 @@ The pathing goal can be set to any of these options:
- **GoalTwoBlocks** a block position that the player should stand in, either at foot or eye level
- **GoalGetToBlock** a block position that the player should stand adjacent to, below, or on top of
- **GoalNear** a block position that the player should get within a certain radius of, used for following entities
- **GoalAxis** a block position on an axis or diagonal axis (so x=0, z=0, or x=z), and y=120 (configurable)
And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one of which satisfies the goal. For example, `mine diamond_ore` creates a `GoalComposite` of `GoalTwoBlocks`s for every diamond ore location it knows of.
@@ -38,7 +42,6 @@ And finally `GoalComposite`. `GoalComposite` is a list of other goals, any one o
Things it doesn't have yet
- Trapdoors
- Sprint jumping in a 1x2 corridor
- Parkour (jumping over gaps of any length) [IN PROGRESS]
See <a href="https://github.com/cabaletta/baritone/issues">issues</a> for more.

View File

@@ -18,6 +18,8 @@ For Impact 4.3, there is no Baritone integration yet, so you will want `baritone
Any official release will be GPG signed by leijurv (44A3EA646EADAC6A) and ZeroMemes (73A788379A197567). Please verify that the hash of the file you download is in `checksums.txt` and that `checksums_signed.asc` is a valid signature by those two public keys of `checksums.txt`.
The build for `baritone-unoptimized-X.Y.Z.jar` is deterministic, and you can verify Travis did it properly by running `scripts/build.sh` yourself and comparing the shasum. The proguarded files (api and standalone) aren't yet reproducible, because proguard annoyingly includes the current timestamp into the final jar.
### Building Baritone yourself
There are a few steps to this
- Clone this repository

View File

@@ -1,3 +1,7 @@
import java.util.jar.JarEntry
import java.util.jar.JarFile
import java.util.jar.JarOutputStream
/*
* This file is part of Baritone.
*
@@ -16,7 +20,7 @@
*/
group 'baritone'
version '0.0.6'
version '0.0.8'
buildscript {
repositories {
@@ -57,7 +61,9 @@ minecraft {
mappings = 'snapshot_20180731'
tweakClass = 'baritone.launch.BaritoneTweaker'
runDir = 'run'
makeObfSourceJar = false
// The sources jar should use SRG names not MCP to ensure compatibility with all mappings
makeObfSourceJar = true
}
repositories {
@@ -88,4 +94,36 @@ mixin {
jar {
from sourceSets.launch.output, sourceSets.api.output
preserveFileTimestamps = false
reproducibleFileOrder = true
}
build {
// while "jar" supports preserveFileTimestamps false
// reobfJar doesn't, it just sets all the last modified times to that instant where it runs the reobfuscator
// so we have to set all those last modified times back to zero
doLast {
File jarFile = new File("build/libs/baritone-" + version + ".jar")
JarFile jf = new JarFile(jarFile)
JarOutputStream jos = new JarOutputStream(new FileOutputStream(new File("temp.jar")))
jf.entries().unique { it.name }.sort { it.name }.each {
if (it.name != "META-INF/fml_cache_annotation.json" && it.name != "META-INF/fml_cache_class_versions.json") {
JarEntry clone = new JarEntry(it)
clone.time = 0
jos.putNextEntry(clone)
copy(jf.getInputStream(it), jos)
}
}
jos.finish()
jf.close()
file("temp.jar").renameTo(jarFile)
}
}
void copy(InputStream is, OutputStream os) {
byte[] buffer = new byte[1024]
int len = 0
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len)
}
}

View File

@@ -1,3 +1,4 @@
#!/bin/sh
set -e # this makes the whole script fail immediately if any one of these commands fails
./gradlew build
export VERSION=$(cat build.gradle | grep "version '" | cut -d "'" -f 2-2)
@@ -9,7 +10,7 @@ echo "-injars 'baritone-$VERSION.jar'" >> api.pro # insert current version
cat ../../scripts/proguard.pro | grep -v "this is the rt jar" | grep -v "\-injars" >> api.pro # remove default rt jar and injar lines
echo "-libraryjars '$(java -verbose 2>/dev/null | sed -ne '1 s/\[Opened \(.*\)\]/\1/p')'" >> api.pro # insert correct rt.jar location
tail api.pro # debug, print out what the previous two commands generated
cat api.pro | grep -v "\-keep class baritone.api" > standalone.pro # standalone doesn't keep baritone api
cat api.pro | grep -v "this is the keep api" > standalone.pro # standalone doesn't keep baritone api
#instead of downloading these jars from my dropbox in a zip, just assume gradle's already got them for us
mkdir -p tempLibraries

View File

@@ -1,4 +1,4 @@
-injars baritone-0.0.6.jar
-injars baritone-0.0.8.jar
-outjars Obfuscated
@@ -16,8 +16,9 @@
-flattenpackagehierarchy
-repackageclasses 'baritone'
-keep class baritone.api.** { *; }
-keep class baritone.api.** { *; } # this is the keep api
-keep class baritone.BaritoneProvider
-keep class baritone.api.IBaritoneProvider
# setting names are reflected from field names, so keep field names
-keepclassmembers class baritone.api.Settings {

View File

@@ -19,6 +19,9 @@ package baritone.api;
import baritone.api.behavior.*;
import baritone.api.cache.IWorldProvider;
import baritone.api.cache.IWorldScanner;
import baritone.api.event.listener.IGameEventListener;
import baritone.api.utils.SettingsUtil;
import java.util.Iterator;
import java.util.ServiceLoader;
@@ -42,6 +45,7 @@ public final class BaritoneAPI {
baritone = instances.next();
settings = new Settings();
SettingsUtil.readAndApply(settings);
}
public static IFollowBehavior getFollowBehavior() {
@@ -71,4 +75,12 @@ public final class BaritoneAPI {
public static IWorldProvider getWorldProvider() {
return baritone.getWorldProvider();
}
public static IWorldScanner getWorldScanner() {
return baritone.getWorldScanner();
}
public static void registerEventListener(IGameEventListener listener) {
baritone.registerEventListener(listener);
}
}

View File

@@ -19,6 +19,8 @@ package baritone.api;
import baritone.api.behavior.*;
import baritone.api.cache.IWorldProvider;
import baritone.api.cache.IWorldScanner;
import baritone.api.event.listener.IGameEventListener;
/**
* @author Brady
@@ -67,4 +69,18 @@ public interface IBaritoneProvider {
* @return The {@link IWorldProvider} instance
*/
IWorldProvider getWorldProvider();
/**
* @see IWorldScanner
*
* @return The {@link IWorldScanner} instance
*/
IWorldScanner getWorldScanner();
/**
* Registers a {@link IGameEventListener} with Baritone's "event bus".
*
* @param listener The listener
*/
void registerEventListener(IGameEventListener listener);
}

View File

@@ -156,7 +156,7 @@ public class Settings {
*
* @see <a href="https://github.com/cabaletta/baritone/issues/18">Issue #18</a>
*/
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.1);
public Setting<Double> backtrackCostFavoringCoefficient = new Setting<>(0.5);
/**
* Don't repropagate cost improvements below 0.01 ticks. They're all just floating point inaccuracies,
@@ -302,6 +302,21 @@ public class Settings {
*/
public Setting<Boolean> renderGoal = new Setting<>(true);
/**
* Ignore depth when rendering the goal
*/
public Setting<Boolean> renderGoalIgnoreDepth = new Setting<>(false);
/**
* Ignore depth when rendering the selection boxes (to break, to place, to walk into)
*/
public Setting<Boolean> renderSelectionBoxesIgnoreDepth = new Setting<>(false);
/**
* Ignore depth when rendering the path
*/
public Setting<Boolean> renderPathIgnoreDepth = new Setting<>(false);
/**
* Line width of the path when rendered, in pixels
*/
@@ -374,7 +389,7 @@ public class Settings {
* <p>
* Also on cosmic prisons this should be set to true since you don't actually mine the ore it just gets replaced with stone.
*/
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(true);
public Setting<Boolean> cancelOnGoalInvalidation = new Setting<>(false);
/**
* The "axis" command (aka GoalAxis) will go to a axis, or diagonal axis, at this Y level.
@@ -480,11 +495,19 @@ public class Settings {
*/
public Setting<Color> colorGoalBox = new Setting<>(Color.GREEN);
/**
* A map of lowercase setting field names to their respective setting
*/
public final Map<String, Setting<?>> byLowerName;
/**
* A list of all settings
*/
public final List<Setting<?>> allSettings;
public class Setting<T> {
public T value;
public final T defaultValue;
private String name;
private final Class<T> klass;
@@ -494,6 +517,7 @@ public class Settings {
throw new IllegalArgumentException("Cannot determine value type class from null");
}
this.value = value;
this.defaultValue = value;
this.klass = (Class<T>) value.getClass();
}
@@ -517,7 +541,7 @@ public class Settings {
// here be dragons
{
Settings() {
Field[] temp = getClass().getFields();
HashMap<String, Setting<?>> tmpByName = new HashMap<>();
List<Setting<?>> tmpAll = new ArrayList<>();
@@ -552,6 +576,4 @@ public class Settings {
}
return result;
}
Settings() { }
}

View File

@@ -17,7 +17,10 @@
package baritone.api.behavior;
import baritone.api.pathing.calc.IPathFinder;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.path.IPathExecutor;
import java.util.Optional;
@@ -65,4 +68,30 @@ public interface IPathingBehavior extends IBehavior {
* Cancels the pathing behavior or the current path calculation.
*/
void cancel();
/**
* Returns the current path, from the current path executor, if there is one.
*
* @return The current path
*/
default Optional<IPath> getPath() {
return Optional.ofNullable(getCurrent()).map(IPathExecutor::getPath);
}
/**
* @return The current path finder being executed
*/
Optional<IPathFinder> getPathFinder();
/**
* @return The current path executor
*/
IPathExecutor getCurrent();
/**
* Returns the next path executor, created when planning ahead.
*
* @return The next path executor
*/
IPathExecutor getNext();
}

View File

@@ -0,0 +1,42 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.cache;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
import java.util.List;
/**
* @author Brady
* @since 10/6/2018
*/
public interface IWorldScanner {
/**
* Scans the world, up to the specified max chunk radius, for the specified blocks.
*
* @param blocks The blocks to scan for
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @param maxSearchRadius The maximum chunk search radius
* @return The matching block positions
*/
List<BlockPos> scanLoadedChunks(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius);
}

View File

@@ -20,6 +20,8 @@ package baritone.api.event.events;
import net.minecraft.util.math.BlockPos;
/**
* Called when the local player interacts with a block, can be either {@link Type#BREAK} or {@link Type#USE}.
*
* @author Brady
* @since 8/22/2018
*/

View File

@@ -17,20 +17,22 @@
package baritone.api.event.events;
import baritone.api.event.events.type.Cancellable;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* @author Brady
* @since 8/1/2018 6:39 PM
*/
public final class ChatEvent extends Cancellable {
public final class ChatEvent extends ManagedPlayerEvent.Cancellable {
/**
* The message being sent
*/
private final String message;
public ChatEvent(String message) {
public ChatEvent(EntityPlayerSP player, String message) {
super(player);
this.message = message;
}

View File

@@ -18,6 +18,7 @@
package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import net.minecraft.network.NetworkManager;
import net.minecraft.network.Packet;
/**
@@ -26,15 +27,22 @@ import net.minecraft.network.Packet;
*/
public final class PacketEvent {
private final NetworkManager networkManager;
private final EventState state;
private final Packet<?> packet;
public PacketEvent(EventState state, Packet<?> packet) {
public PacketEvent(NetworkManager networkManager, EventState state, Packet<?> packet) {
this.networkManager = networkManager;
this.state = state;
this.packet = packet;
}
public final NetworkManager getNetworkManager() {
return this.networkManager;
}
public final EventState getState() {
return this.state;
}

View File

@@ -18,19 +18,22 @@
package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* @author Brady
* @since 8/21/2018
*/
public final class PlayerUpdateEvent {
public final class PlayerUpdateEvent extends ManagedPlayerEvent {
/**
* The state of the event
*/
private final EventState state;
public PlayerUpdateEvent(EventState state) {
public PlayerUpdateEvent(EntityPlayerSP player, EventState state) {
super(player);
this.state = state;
}

View File

@@ -18,6 +18,8 @@
package baritone.api.event.events;
import baritone.api.event.events.type.EventState;
import baritone.api.event.events.type.ManagedPlayerEvent;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.entity.EntityLivingBase;
@@ -25,7 +27,7 @@ import net.minecraft.entity.EntityLivingBase;
* @author Brady
* @since 8/21/2018
*/
public final class RotationMoveEvent {
public final class RotationMoveEvent extends ManagedPlayerEvent {
/**
* The type of event
@@ -37,7 +39,8 @@ public final class RotationMoveEvent {
*/
private final EventState state;
public RotationMoveEvent(EventState state, Type type) {
public RotationMoveEvent(EntityPlayerSP player, EventState state, Type type) {
super(player);
this.state = state;
this.type = type;
}

View File

@@ -21,23 +21,19 @@ package baritone.api.event.events.type;
* @author Brady
* @since 8/1/2018 6:41 PM
*/
public class Cancellable {
public class Cancellable implements ICancellable {
/**
* Whether or not this event has been cancelled
*/
private boolean cancelled;
/**
* Cancels this event
*/
@Override
public final void cancel() {
this.cancelled = true;
}
/**
* @return Whether or not this event has been cancelled
*/
@Override
public final boolean isCancelled() {
return this.cancelled;
}

View File

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

View File

@@ -0,0 +1,61 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.event.events.type;
import net.minecraft.client.entity.EntityPlayerSP;
/**
* An event that has a reference to a locally managed player.
*
* @author Brady
* @since 10/11/2018
*/
public class ManagedPlayerEvent {
protected final EntityPlayerSP player;
public ManagedPlayerEvent(EntityPlayerSP player) {
this.player = player;
}
public final EntityPlayerSP getPlayer() {
return this.player;
}
public static class Cancellable extends ManagedPlayerEvent implements ICancellable {
/**
* Whether or not this event has been cancelled
*/
private boolean cancelled;
public Cancellable(EntityPlayerSP player) {
super(player);
}
@Override
public final void cancel() {
this.cancelled = true;
}
@Override
public final boolean isCancelled() {
return this.cancelled;
}
}
}

View File

@@ -15,37 +15,35 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.pathing.path;
package baritone.api.pathing.calc;
import baritone.Baritone;
import baritone.api.Settings;
import baritone.api.pathing.goals.Goal;
import baritone.pathing.movement.Movement;
import baritone.utils.Helper;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import baritone.api.pathing.movement.IMovement;
import baritone.api.utils.BetterBlockPos;
import java.util.List;
/**
* @author leijurv
* @author leijurv, Brady
*/
public interface IPath extends Helper {
public interface IPath {
/**
* Ordered list of movements to carry out.
* movements.get(i).getSrc() should equal positions.get(i)
* movements.get(i).getDest() should equal positions.get(i+1)
* movements.size() should equal positions.size()-1
*
* @return All of the movements to carry out
*/
List<Movement> movements();
List<IMovement> movements();
/**
* All positions along the way.
* Should begin with the same as getSrc and end with the same as getDest
*
* @return All of the positions along this path
*/
List<BetterBlockPos> positions();
@@ -53,10 +51,10 @@ public interface IPath extends Helper {
* This path is actually going to be executed in the world. Do whatever additional processing is required.
* (as opposed to Path objects that are just constructed every frame for rendering)
*/
default void postprocess() {}
default void postProcess() {}
/**
* Number of positions in this path
* Returns the number of positions in this path. Equivalent to {@code positions().size()}.
*
* @return Number of positions in this path
*/
@@ -65,74 +63,74 @@ public interface IPath extends Helper {
}
/**
* What goal was this path calculated towards?
*
* @return
* @return The goal that this path was calculated towards
*/
Goal getGoal();
default Tuple<Double, BlockPos> closestPathPos() {
double best = -1;
BlockPos bestPos = null;
for (BlockPos pos : positions()) {
double dist = Utils.playerDistanceToCenter(pos);
if (dist < best || best == -1) {
best = dist;
bestPos = pos;
}
}
return new Tuple<>(best, bestPos);
}
/**
* Returns the number of nodes that were considered during calculation before
* this path was found.
*
* @return The number of nodes that were considered before finding this path
*/
int getNumNodesConsidered();
/**
* Where does this path start
* Returns the start position of this path. This is the first element in the
* {@link List} that is returned by {@link IPath#positions()}.
*
* @return The start position of this path
*/
default BetterBlockPos getSrc() {
return positions().get(0);
}
/**
* Where does this path end
* Returns the end position of this path. This is the last element in the
* {@link List} that is returned by {@link IPath#positions()}.
*
* @return The end position of this path.
*/
default BetterBlockPos getDest() {
List<BetterBlockPos> pos = positions();
return pos.get(pos.size() - 1);
}
/**
* Returns the estimated number of ticks to complete the path from the given node index.
*
* @param pathPosition The index of the node we're calculating from
* @return The estimated number of ticks remaining frm the given position
*/
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(null);
sum += movements().get(i).getCost();
}
return sum;
}
int getNumNodesConsidered();
/**
* Cuts off this path at the loaded chunk border, and returns the resulting path. Default
* implementation just returns this path, without the intended functionality.
*
* @return The result of this cut-off operation
*/
default IPath cutoffAtLoadedChunks() {
for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i);
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
logDebug("Cutting off path at edge of loaded chunks");
logDebug("Length decreased by " + (positions().size() - i - 1));
return new CutoffPath(this, i);
}
}
logDebug("Path ends within loaded chunks");
return this;
}
/**
* Cuts off this path using the min length and cutoff factor settings, and returns the resulting path.
* Default implementation just returns this path, without the intended functionality.
*
* @see Settings#pathCutoffMinimumLength
* @see Settings#pathCutoffFactor
*
* @return The result of this cut-off operation
*/
default IPath staticCutoff(Goal destination) {
if (length() < Baritone.settings().pathCutoffMinimumLength.get()) {
return this;
}
if (destination == null || destination.isInGoal(getDest())) {
return this;
}
double factor = Baritone.settings().pathCutoffFactor.get();
int newLength = (int) (length() * factor);
logDebug("Static cutoff " + length() + " to " + newLength);
return new CutoffPath(this, newLength);
return this;
}
}

View File

@@ -15,10 +15,9 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.pathing.calc;
package baritone.api.pathing.calc;
import baritone.api.pathing.goals.Goal;
import baritone.pathing.path.IPath;
import java.util.Optional;

View File

@@ -0,0 +1,67 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.movement;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.math.BlockPos;
import java.util.List;
/**
* @author Brady
* @since 10/8/2018
*/
public interface IMovement {
double getCost();
MovementStatus update();
/**
* Resets the current state status to {@link MovementStatus#PREPPING}
*/
void reset();
/**
* Resets the cache for special break, place, and walk into blocks
*/
void resetBlockCache();
/**
* @return Whether or not it is safe to cancel the current movement state
*/
boolean safeToCancel();
double recalculateCost();
double calculateCostWithoutCaching();
boolean calculatedWhileLoaded();
BetterBlockPos getSrc();
BetterBlockPos getDest();
BlockPos getDirection();
List<BlockPos> toBreak();
List<BlockPos> toPlace();
List<BlockPos> toWalkInto();
}

View File

@@ -0,0 +1,74 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.pathing.movement;
/**
* @author Brady
* @since 10/8/2018
*/
public enum MovementStatus {
/**
* We are preparing the movement to be executed. This is when any blocks obstructing the destination are broken.
*/
PREPPING(false),
/**
* We are waiting for the movement to begin, after {@link MovementStatus#PREPPING}.
*/
WAITING(false),
/**
* The movement is currently in progress, after {@link MovementStatus#WAITING}
*/
RUNNING(false),
/**
* The movement has been completed and we are at our destination
*/
SUCCESS(true),
/**
* There was a change in state between calculation and actual
* movement execution, and the movement has now become impossible.
*/
UNREACHABLE(true),
/**
* Unused
*/
FAILED(true),
/**
* "Unused"
*/
CANCELED(true);
/**
* Whether or not this status indicates a complete movement.
*/
private final boolean complete;
MovementStatus(boolean complete) {
this.complete = complete;
}
public final boolean isComplete() {
return this.complete;
}
}

View File

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

View File

@@ -15,9 +15,8 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils.pathing;
package baritone.api.utils;
import baritone.pathing.calc.AbstractNodeCostSearch;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.MathHelper;
@@ -54,11 +53,30 @@ public final class BetterBlockPos extends BlockPos {
@Override
public int hashCode() {
return (int) AbstractNodeCostSearch.posHash(x, y, z);
return (int) longHash(x, y, z);
}
public static long longHash(BetterBlockPos pos) {
return AbstractNodeCostSearch.posHash(pos.x, pos.y, pos.z);
return longHash(pos.x, pos.y, pos.z);
}
public static long longHash(int x, int y, int z) {
/*
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
*
* public int hashCode() {
* return (this.getY() + this.getZ() * 31) * 31 + this.getX();
* }
*
* That is terrible and has tons of collisions and makes the HashMap terribly inefficient.
*
* That's why we grab out the X, Y, Z and calculate our own hashcode
*/
long hash = 3241;
hash = 3457689L * hash + x;
hash = 8734625L * hash + y;
hash = 2873465L * hash + z;
return hash;
}
@Override

View File

@@ -0,0 +1,140 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils;
import baritone.api.Settings;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation;
import java.awt.*;
import java.io.File;
import java.io.FileOutputStream;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class SettingsUtil {
private static final File settingsFile = new File(new File(Minecraft.getMinecraft().gameDir, "baritone"), "settings.txt");
private static final Map<Class<?>, SettingsIO> map;
public static void readAndApply(Settings settings) {
try (Scanner scan = new Scanner(settingsFile)) {
while (scan.hasNextLine()) {
String line = scan.nextLine();
if (line.isEmpty()) {
continue;
}
if (line.startsWith("#") || line.startsWith("//")) {
continue;
}
int space = line.indexOf(" ");
if (space == -1) {
System.out.println("Skipping invalid line with no space: " + line);
continue;
}
String settingName = line.substring(0, space).trim().toLowerCase();
String settingValue = line.substring(space).trim();
try {
parseAndApply(settings, settingName, settingValue);
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Unable to parse line " + line);
}
}
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
}
}
public static synchronized void save(Settings settings) {
try (FileOutputStream out = new FileOutputStream(settingsFile)) {
for (Settings.Setting setting : settings.allSettings) {
if (setting.get() == null) {
System.out.println("NULL SETTING?" + setting.getName());
continue;
}
if (setting.getName().equals("logger")) {
continue; // NO
}
if (setting.value == setting.defaultValue) {
continue;
}
SettingsIO io = map.get(setting.getValueClass());
if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting + " " + setting.getName());
}
out.write((setting.getName() + " " + io.toString.apply(setting.get()) + "\n").getBytes());
}
} catch (Exception ex) {
ex.printStackTrace();
System.out.println("Exception while saving Baritone settings!");
}
}
private static void parseAndApply(Settings settings, String settingName, String settingValue) throws IllegalStateException, NumberFormatException {
Settings.Setting setting = settings.byLowerName.get(settingName);
if (setting == null) {
throw new IllegalStateException("No setting by that name");
}
Class intendedType = setting.getValueClass();
SettingsIO ioMethod = map.get(intendedType);
Object parsed = ioMethod.parser.apply(settingValue);
if (!intendedType.isInstance(parsed)) {
throw new IllegalStateException(ioMethod + " parser returned incorrect type, expected " + intendedType + " got " + parsed + " which is " + parsed.getClass());
}
setting.value = parsed;
}
private enum SettingsIO {
DOUBLE(Double.class, Double::parseDouble),
BOOLEAN(Boolean.class, Boolean::parseBoolean),
INTEGER(Integer.class, Integer::parseInt),
FLOAT(Float.class, Float::parseFloat),
LONG(Long.class, Long::parseLong),
ITEM_LIST(ArrayList.class, str -> Stream.of(str.split(",")).map(Item::getByNameOrId).collect(Collectors.toCollection(ArrayList::new)), list -> ((ArrayList<Item>) list).stream().map(Item.REGISTRY::getNameForObject).map(ResourceLocation::toString).collect(Collectors.joining(","))),
COLOR(Color.class, str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])), color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue());
Class<?> klass;
Function<String, Object> parser;
Function<Object, String> toString;
<T> SettingsIO(Class<T> klass, Function<String, T> parser) {
this(klass, parser, Object::toString);
}
<T> SettingsIO(Class<T> klass, Function<String, T> parser, Function<T, String> toString) {
this.klass = klass;
this.parser = parser::apply;
this.toString = x -> toString.apply((T) x);
}
}
static {
HashMap<Class<?>, SettingsIO> tempMap = new HashMap<>();
for (SettingsIO type : SettingsIO.values()) {
tempMap.put(type.klass, type);
}
map = Collections.unmodifiableMap(tempMap);
}
}

View File

@@ -20,7 +20,7 @@ package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.event.events.RotationMoveEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -40,8 +40,8 @@ public class MixinEntity {
)
private void preMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Minecraft.getMinecraft().player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE));
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.MOTION_UPDATE));
}
@Inject(
@@ -50,7 +50,7 @@ public class MixinEntity {
)
private void postMoveRelative(float strafe, float up, float forward, float friction, CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Minecraft.getMinecraft().player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE));
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.MOTION_UPDATE));
}
}

View File

@@ -20,8 +20,7 @@ package baritone.launch.mixins;
import baritone.Baritone;
import baritone.api.event.events.RotationMoveEvent;
import baritone.api.event.events.type.EventState;
import net.minecraft.client.Minecraft;
import net.minecraft.entity.Entity;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.EntityLivingBase;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.injection.At;
@@ -40,9 +39,9 @@ public class MixinEntityLivingBase {
at = @At("HEAD")
)
private void preJump(CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Minecraft.getMinecraft().player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.PRE, RotationMoveEvent.Type.JUMP));
EntityLivingBase _this = (EntityLivingBase) (Object) this;
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.PRE, RotationMoveEvent.Type.JUMP));
}
@Inject(
@@ -50,8 +49,8 @@ public class MixinEntityLivingBase {
at = @At("RETURN")
)
private void postJump(CallbackInfo ci) {
Entity _this = (Entity) (Object) this;
if (_this == Minecraft.getMinecraft().player)
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent(EventState.POST, RotationMoveEvent.Type.JUMP));
EntityLivingBase _this = (EntityLivingBase) (Object) this;
if (EntityPlayerSP.class.isInstance(_this))
Baritone.INSTANCE.getGameEventHandler().onPlayerRotationMove(new RotationMoveEvent((EntityPlayerSP) _this, EventState.POST, RotationMoveEvent.Type.JUMP));
}
}

View File

@@ -40,7 +40,7 @@ public class MixinEntityPlayerSP {
cancellable = true
)
private void sendChatMessage(String msg, CallbackInfo ci) {
ChatEvent event = new ChatEvent(msg);
ChatEvent event = new ChatEvent((EntityPlayerSP) (Object) this, msg);
Baritone.INSTANCE.getGameEventHandler().onSendChatMessage(event);
if (event.isCancelled()) {
ci.cancel();
@@ -57,7 +57,7 @@ public class MixinEntityPlayerSP {
)
)
private void onPreUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.PRE));
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.PRE));
}
@Inject(
@@ -70,6 +70,6 @@ public class MixinEntityPlayerSP {
)
)
private void onPostUpdate(CallbackInfo ci) {
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent(EventState.POST));
Baritone.INSTANCE.getGameEventHandler().onPlayerUpdate(new PlayerUpdateEvent((EntityPlayerSP) (Object) this, EventState.POST));
}
}

View File

@@ -40,7 +40,6 @@ import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.Redirect;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfo;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
import org.spongepowered.asm.mixin.injection.callback.LocalCapture;
/**

View File

@@ -54,7 +54,7 @@ public class MixinNetworkManager {
)
private void preDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.PRE, inPacket));
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, inPacket));
}
}
@@ -64,7 +64,7 @@ public class MixinNetworkManager {
)
private void postDispatchPacket(Packet<?> inPacket, final GenericFutureListener<? extends Future<? super Void>>[] futureListeners, CallbackInfo ci) {
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent(EventState.POST, inPacket));
Baritone.INSTANCE.getGameEventHandler().onSendPacket(new PacketEvent((NetworkManager) (Object) this, EventState.POST, inPacket));
}
}
@@ -77,7 +77,7 @@ public class MixinNetworkManager {
)
private void preProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
if (this.direction == EnumPacketDirection.CLIENTBOUND) {
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.PRE, packet));}
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.PRE, packet));}
}
@Inject(
@@ -86,7 +86,7 @@ public class MixinNetworkManager {
)
private void postProcessPacket(ChannelHandlerContext context, Packet<?> packet, CallbackInfo ci) {
if (this.channel.isOpen() && this.direction == EnumPacketDirection.CLIENTBOUND) {
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent(EventState.POST, packet));
Baritone.INSTANCE.getGameEventHandler().onReceivePacket(new PacketEvent((NetworkManager) (Object) this, EventState.POST, packet));
}
}
}

View File

@@ -21,7 +21,6 @@ import baritone.api.BaritoneAPI;
import baritone.api.Settings;
import baritone.api.event.listener.IGameEventListener;
import baritone.behavior.*;
import baritone.cache.WorldProvider;
import baritone.event.GameEventHandler;
import baritone.utils.BaritoneAutoTest;
import baritone.utils.InputOverrideHandler;
@@ -36,7 +35,6 @@ import java.util.concurrent.Executor;
import java.util.concurrent.SynchronousQueue;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
import java.util.function.Consumer;
/**
* @author Brady
@@ -61,19 +59,13 @@ public enum Baritone {
private File dir;
private ThreadPoolExecutor threadPool;
/**
* List of consumers to be called after Baritone has initialized
*/
private List<Consumer<Baritone>> onInitConsumers;
/**
* Whether or not Baritone is active
*/
private boolean active;
Baritone() {
this.onInitConsumers = new ArrayList<>();
this.gameEventHandler = new GameEventHandler();
}
public synchronized void init() {
@@ -81,7 +73,6 @@ public enum Baritone {
return;
}
this.threadPool = new ThreadPoolExecutor(4, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<>());
this.gameEventHandler = new GameEventHandler();
this.inputOverrideHandler = new InputOverrideHandler();
// Acquire the "singleton" instance of the settings directly from the API
@@ -109,8 +100,6 @@ public enum Baritone {
this.active = true;
this.initialized = true;
this.onInitConsumers.forEach(consumer -> consumer.accept(this));
}
public boolean isInitialized() {
@@ -157,8 +146,4 @@ public enum Baritone {
public File getDir() {
return this.dir;
}
public void registerInitListener(Consumer<Baritone> runnable) {
this.onInitConsumers.add(runnable);
}
}

View File

@@ -20,8 +20,11 @@ package baritone;
import baritone.api.IBaritoneProvider;
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;
/**
* @author Brady
@@ -58,4 +61,14 @@ public final class BaritoneProvider implements IBaritoneProvider {
public IWorldProvider getWorldProvider() {
return WorldProvider.INSTANCE;
}
@Override
public IWorldScanner getWorldScanner() {
return WorldScanner.INSTANCE;
}
@Override
public void registerEventListener(IGameEventListener listener) {
Baritone.INSTANCE.registerEventListener(listener);
}
}

View File

@@ -50,14 +50,14 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
private MemoryBehavior() {}
@Override
public void onPlayerUpdate(PlayerUpdateEvent event) {
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE) {
updateInventory();
}
}
@Override
public void onSendPacket(PacketEvent event) {
public synchronized void onSendPacket(PacketEvent event) {
Packet p = event.getPacket();
if (event.getState() == EventState.PRE) {
@@ -83,7 +83,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
}
@Override
public void onReceivePacket(PacketEvent event) {
public synchronized void onReceivePacket(PacketEvent event) {
Packet p = event.getPacket();
if (event.getState() == EventState.PRE) {
@@ -130,13 +130,14 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
}
@Override
public final RememberedInventory getInventoryByPos(BlockPos pos) {
public final synchronized RememberedInventory getInventoryByPos(BlockPos pos) {
return this.getCurrentContainer().rememberedInventories.get(pos);
}
@Override
public final Map<BlockPos, IRememberedInventory> getRememberedInventories() {
return Collections.unmodifiableMap(this.getCurrentContainer().rememberedInventories);
public final synchronized Map<BlockPos, IRememberedInventory> getRememberedInventories() {
// make a copy since this map is modified from the packet thread
return new HashMap<>(this.getCurrentContainer().rememberedInventories);
}
private static final class WorldDataContainer {
@@ -213,7 +214,7 @@ public final class MemoryBehavior extends Behavior implements IMemoryBehavior, H
@Override
public final List<ItemStack> getContents() {
return this.items;
return Collections.unmodifiableList(this.items);
}
@Override

View File

@@ -19,16 +19,15 @@ package baritone.behavior;
import baritone.Baritone;
import baritone.api.behavior.IMineBehavior;
import baritone.api.event.events.PathEvent;
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.cache.CachedChunk;
import baritone.cache.ChunkPacker;
import baritone.cache.WorldProvider;
import baritone.cache.WorldScanner;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import net.minecraft.block.Block;
@@ -78,35 +77,37 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.get();
if (mineGoalUpdateInterval != 0) {
if (event.getCount() % mineGoalUpdateInterval == 0) {
Baritone.INSTANCE.getExecutor().execute(this::updateGoal);
Baritone.INSTANCE.getExecutor().execute(this::rescan);
}
}
PathingBehavior.INSTANCE.revalidateGoal();
}
@Override
public void onPathEvent(PathEvent event) {
updateGoal();
PathingBehavior.INSTANCE.revalidateGoal();
}
private void updateGoal() {
if (mining == null) {
return;
}
if (!locationsCache.isEmpty()) {
locationsCache = prune(new ArrayList<>(locationsCache), mining, 64);
PathingBehavior.INSTANCE.setGoal(coalesce(locationsCache));
List<BlockPos> locs = locationsCache;
if (!locs.isEmpty()) {
locs = prune(new ArrayList<>(locs), mining, 64);
PathingBehavior.INSTANCE.setGoal(coalesce(locs));
PathingBehavior.INSTANCE.path();
locationsCache = locs;
}
}
private void rescan() {
if (mining == null) {
return;
}
List<BlockPos> locs = scanFor(mining, 64);
if (locs.isEmpty()) {
logDebug("No locations for " + mining + " known, cancelling");
cancel();
mine(0, (String[]) null);
return;
}
locationsCache = locs;
PathingBehavior.INSTANCE.setGoal(coalesce(locs));
PathingBehavior.INSTANCE.path();
}
public GoalComposite coalesce(List<BlockPos> locs) {
@@ -176,6 +177,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList());
this.quantity = quantity;
this.locationsCache = new ArrayList<>();
rescan();
updateGoal();
}
@@ -184,6 +186,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe
this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks);
this.quantity = quantity;
this.locationsCache = new ArrayList<>();
rescan();
updateGoal();
}

View File

@@ -23,28 +23,24 @@ import baritone.api.event.events.PathEvent;
import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.RenderEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.calc.IPathFinder;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.pathing.calc.AStarPathFinder;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.calc.IPathFinder;
import baritone.pathing.calc.CutoffPath;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.path.IPath;
import baritone.pathing.path.PathExecutor;
import baritone.utils.BlockBreakHelper;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.PathRenderer;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.Collection;
import java.util.Collections;
import java.util.HashSet;
import java.util.Optional;
import java.util.*;
import java.util.stream.Collectors;
public final class PathingBehavior extends Behavior implements IPathingBehavior, Helper {
@@ -105,6 +101,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
dispatchPathEvent(PathEvent.CONTINUING_ONTO_PLANNED_NEXT);
current = next;
next = null;
current.onTick(event);
return;
}
// at this point, current just ended, but we aren't in the goal and have no plan for the future
@@ -123,12 +120,13 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
if (safe) {
// a movement just ended
if (next != null) {
if (next.getPath().positions().contains(playerFeet())) {
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;
}
}
@@ -191,19 +189,19 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
return goal;
}
@Override
public PathExecutor getCurrent() {
return current;
}
@Override
public PathExecutor getNext() {
return next;
}
// TODO: Expose this method in the API?
// In order to do so, we'd need to move over IPath which has a whole lot of references to other
// things that may not need to be exposed necessarily, so we'll need to figure that out.
public Optional<IPath> getPath() {
return Optional.ofNullable(current).map(PathExecutor::getPath);
@Override
public Optional<IPathFinder> getPathFinder() {
return Optional.ofNullable(AbstractNodeCostSearch.currentlyRunning());
}
@Override
@@ -254,12 +252,46 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
}
/**
* See issue #209
*
* @return The starting {@link BlockPos} for a new path
*/
private BlockPos pathStart() {
public BlockPos pathStart() {
BetterBlockPos feet = playerFeet();
if (BlockStateInterface.get(feet.down()).getBlock().equals(Blocks.AIR) && MovementHelper.canWalkOn(feet.down().down())) {
return feet.down();
if (!MovementHelper.canWalkOn(feet.down())) {
if (player().onGround) {
double playerX = player().posX;
double playerZ = player().posZ;
ArrayList<BetterBlockPos> closest = new ArrayList<>();
for (int dx = -1; dx <= 1; dx++) {
for (int dz = -1; dz <= 1; dz++) {
closest.add(new BetterBlockPos(feet.x + dx, feet.y, feet.z + dz));
}
}
closest.sort(Comparator.comparingDouble(pos -> ((pos.x + 0.5D) - playerX) * ((pos.x + 0.5D) - playerX) + ((pos.z + 0.5D) - playerZ) * ((pos.z + 0.5D) - playerZ)));
for (int i = 0; i < 4; i++) {
BetterBlockPos possibleSupport = closest.get(i);
double xDist = Math.abs((possibleSupport.x + 0.5D) - playerX);
double zDist = Math.abs((possibleSupport.z + 0.5D) - playerZ);
if (xDist > 0.8 && zDist > 0.8) {
// can't possibly be sneaking off of this one, we're too far away
continue;
}
if (MovementHelper.canWalkOn(possibleSupport.down()) && MovementHelper.canWalkThrough(possibleSupport) && MovementHelper.canWalkThrough(possibleSupport.up())) {
// this is plausible
logDebug("Faking path start assuming player is standing off the edge of a block");
return possibleSupport;
}
}
} else {
// !onGround
// we're in the middle of a jump
if (MovementHelper.canWalkOn(feet.down().down())) {
logDebug("Faking path start assuming player is midair and falling");
return feet.down();
}
}
}
return feet;
}
@@ -284,9 +316,30 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Optional<IPath> path = findPath(start, previous);
if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(IPath::cutoffAtLoadedChunks);
path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks();
if (result instanceof CutoffPath) {
logDebug("Cutting off path at edge of loaded chunks");
logDebug("Length decreased by " + (p.length() - result.length()));
} else {
logDebug("Path ends within loaded chunks");
}
return result;
});
}
Optional<PathExecutor> executor = path.map(p -> p.staticCutoff(goal)).map(PathExecutor::new);
Optional<PathExecutor> executor = path.map(p -> {
IPath result = p.staticCutoff(goal);
if (result instanceof CutoffPath) {
logDebug("Static cutoff " + p.length() + " to " + result.length());
}
return result;
}).map(PathExecutor::new);
synchronized (pathPlanLock) {
if (current == null) {
if (executor.isPresent()) {
@@ -388,56 +441,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
@Override
public void onRenderPass(RenderEvent event) {
// System.out.println("Render passing");
// System.out.println(event.getPartialTicks());
float partialTicks = event.getPartialTicks();
if (goal != null && Baritone.settings().renderGoal.value) {
PathRenderer.drawLitDankGoalBox(player(), goal, partialTicks, Baritone.settings().colorGoalBox.get());
}
if (!Baritone.settings().renderPath.get()) {
return;
}
//long start = System.nanoTime();
PathExecutor current = this.current; // this should prevent most race conditions?
PathExecutor next = this.next; // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
// TODO is this enough, or do we need to acquire a lock here?
// TODO benchmark synchronized in render loop
// Render the current path, if there is one
if (current != null && current.getPath() != null) {
int renderBegin = Math.max(current.getPosition() - 3, 0);
PathRenderer.drawPath(current.getPath(), renderBegin, player(), partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20);
}
if (next != null && next.getPath() != null) {
PathRenderer.drawPath(next.getPath(), 0, player(), partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20);
}
//long split = System.nanoTime();
if (current != null) {
PathRenderer.drawManySelectionBoxes(player(), current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get());
PathRenderer.drawManySelectionBoxes(player(), current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get());
PathRenderer.drawManySelectionBoxes(player(), current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get());
}
// If there is a path calculation currently running, render the path calculation process
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> {
currentlyRunning.bestPathSoFar().ifPresent(p -> {
PathRenderer.drawPath(p, 0, player(), partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
});
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
PathRenderer.drawPath(mr, 0, player(), partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
PathRenderer.drawManySelectionBoxes(player(), Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
});
});
//long end = System.nanoTime();
//System.out.println((end - split) + " " + (split - start));
// if (end - start > 0) {
// System.out.println("Frame took " + (split - start) + " " + (end - split));
//}
PathRenderer.render(event, this);
}
@Override

View File

@@ -142,7 +142,11 @@ public final class CachedWorld implements ICachedWorld, Helper {
public final void save() {
if (!Baritone.settings().chunkCaching.get()) {
System.out.println("Not saving to disk; chunk caching is disabled.");
allRegions().forEach(CachedRegion::removeExpired); // even if we aren't saving to disk, still delete expired old chunks from RAM
allRegions().forEach(region -> {
if (region != null) {
region.removeExpired();
}
}); // even if we aren't saving to disk, still delete expired old chunks from RAM
return;
}
long start = System.nanoTime() / 1000000L;

View File

@@ -42,7 +42,7 @@ public class WorldData implements IWorldData {
this.waypoints = new Waypoints(directory.resolve("waypoints"));
}
void onClose() {
public void onClose() {
Baritone.INSTANCE.getExecutor().execute(() -> {
System.out.println("Started saving the world in a new thread");
cache.save();

View File

@@ -17,6 +17,7 @@
package baritone.cache;
import baritone.api.cache.IWorldScanner;
import baritone.utils.Helper;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@@ -29,19 +30,11 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.LinkedList;
import java.util.List;
public enum WorldScanner implements Helper {
public enum WorldScanner implements IWorldScanner, Helper {
INSTANCE;
/**
* Scans the world, up to your render distance, for the specified blocks.
*
* @param blocks The blocks to scan for
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @param maxSearchRadius The maximum chunk search radius
* @return The matching block positions
*/
@Override
public List<BlockPos> scanLoadedChunks(List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius) {
if (blocks.contains(null)) {
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString());

View File

@@ -20,10 +20,11 @@ package baritone.pathing.calc;
import baritone.Baritone;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves;
import baritone.pathing.path.IPath;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.pathing.MutableMoveResult;
@@ -47,7 +48,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
@Override
protected Optional<IPath> calculate0(long timeout) {
startNode = getNodeAtPosition(startX, startY, startZ, posHash(startX, startY, startZ));
startNode = getNodeAtPosition(startX, startY, startZ, BetterBlockPos.longHash(startX, startY, startZ));
startNode.cost = 0;
startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
@@ -122,7 +123,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
if (actionCost <= 0) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
}
long hashCode = posHash(res.x, res.y, res.z);
long hashCode = BetterBlockPos.longHash(res.x, res.y, res.z);
if (favoring && favored.contains(hashCode)) {
// see issue #18
actionCost *= favorCoeff;

View File

@@ -18,8 +18,9 @@
package baritone.pathing.calc;
import baritone.Baritone;
import baritone.api.pathing.calc.IPathFinder;
import baritone.api.pathing.goals.Goal;
import baritone.pathing.path.IPath;
import baritone.api.pathing.calc.IPath;
import it.unimi.dsi.fastutil.longs.Long2ObjectOpenHashMap;
import java.util.Optional;
@@ -88,7 +89,7 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
this.cancelRequested = false;
try {
Optional<IPath> path = calculate0(timeout);
path.ifPresent(IPath::postprocess);
path.ifPresent(IPath::postProcess);
isFinished = true;
return path;
} finally {
@@ -140,25 +141,6 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
return node;
}
public static long posHash(int x, int y, int z) {
/*
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
*
* public int hashCode() {
* return (this.getY() + this.getZ() * 31) * 31 + this.getX();
* }
*
* That is terrible and has tons of collisions and makes the HashMap terribly inefficient.
*
* That's why we grab out the X, Y, Z and calculate our own hashcode
*/
long hash = 3241;
hash = 3457689L * hash + x;
hash = 8734625L * hash + y;
hash = 2873465L * hash + z;
return hash;
}
public static void forceCancel() {
currentlyRunning = null;
}
@@ -225,4 +207,8 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
public static Optional<AbstractNodeCostSearch> getCurrentlyRunning() {
return Optional.ofNullable(currentlyRunning);
}
public static AbstractNodeCostSearch currentlyRunning() {
return currentlyRunning;
}
}

View File

@@ -15,11 +15,12 @@
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.pathing.path;
package baritone.pathing.calc;
import baritone.api.pathing.goals.Goal;
import baritone.pathing.movement.Movement;
import baritone.utils.pathing.BetterBlockPos;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import java.util.Collections;
import java.util.List;
@@ -28,13 +29,13 @@ public class CutoffPath implements IPath {
private final List<BetterBlockPos> path;
private final List<Movement> movements;
private final List<IMovement> movements;
private final int numNodes;
private final Goal goal;
public CutoffPath(IPath prev, int lastPositionToInclude) {
CutoffPath(IPath prev, int lastPositionToInclude) {
path = prev.positions().subList(0, lastPositionToInclude + 1);
movements = prev.movements().subList(0, lastPositionToInclude + 1);
numNodes = prev.getNumNodesConsidered();
@@ -47,7 +48,7 @@ public class CutoffPath implements IPath {
}
@Override
public List<Movement> movements() {
public List<IMovement> movements() {
return Collections.unmodifiableList(movements);
}

View File

@@ -17,12 +17,16 @@
package baritone.pathing.calc;
import baritone.api.BaritoneAPI;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.IMovement;
import baritone.api.pathing.calc.IPath;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.Moves;
import baritone.pathing.path.IPath;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.client.Minecraft;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList;
import java.util.Collections;
@@ -139,16 +143,17 @@ class Path implements IPath {
for (Moves moves : Moves.values()) {
Movement move = moves.apply0(src);
if (move.getDest().equals(dest)) {
// TODO instead of recalculating here, could we take pathNode.cost - pathNode.prevNode.cost to get the cost as-calculated?
move.recalculateCost(); // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
return move;
}
}
// leave this as IllegalStateException; it's caught in AbstractNodeCostSearch
// this is no longer called from bestPathSoFar, now it's in postprocessing
throw new IllegalStateException("Movement became impossible during calculation " + src + " " + dest + " " + dest.subtract(src));
}
@Override
public void postprocess() {
public void postProcess() {
if (verified) {
throw new IllegalStateException();
}
@@ -160,7 +165,7 @@ class Path implements IPath {
}
@Override
public List<Movement> movements() {
public List<IMovement> movements() {
if (!verified) {
throw new IllegalStateException();
}
@@ -186,4 +191,28 @@ class Path implements IPath {
public BetterBlockPos getDest() {
return end;
}
@Override
public IPath cutoffAtLoadedChunks() {
for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i);
if (Minecraft.getMinecraft().world.getChunk(pos) instanceof EmptyChunk) {
return new CutoffPath(this, i);
}
}
return this;
}
@Override
public IPath staticCutoff(Goal destination) {
if (length() < BaritoneAPI.getSettings().pathCutoffMinimumLength.get()) {
return this;
}
if (destination == null || destination.isInGoal(getDest())) {
return this;
}
double factor = BaritoneAPI.getSettings().pathCutoffFactor.get();
int newLength = (int) (length() * factor);
return new CutoffPath(this, newLength);
}
}

View File

@@ -19,6 +19,7 @@ package baritone.pathing.calc;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
/**
* A node in the path, containing the cost and steps to get to it.
@@ -30,20 +31,20 @@ public final class PathNode {
/**
* The position of this node
*/
final int x;
final int y;
final int z;
public final int x;
public final int y;
public final int z;
/**
* Cached, should always be equal to goal.heuristic(pos)
*/
final double estimatedCostToGoal;
public final double estimatedCostToGoal;
/**
* Total cost of getting from start to here
* Mutable and changed by PathFinder
*/
double cost;
public double cost;
/**
* Should always be equal to estimatedCosttoGoal + cost
@@ -55,13 +56,13 @@ public final class PathNode {
* In the graph search, what previous node contributed to the cost
* Mutable and changed by PathFinder
*/
PathNode previous;
public PathNode previous;
/**
* Is this a member of the open set in A*? (only used during pathfinding)
* Instead of doing a costly member check in the open set, cache membership in each node individually too.
*/
boolean isOpen;
public boolean isOpen;
/**
* Where is this node in the array flattenization of the binary heap? Needed for decrease-key operations.
@@ -85,7 +86,7 @@ public final class PathNode {
*/
@Override
public int hashCode() {
return (int) AbstractNodeCostSearch.posHash(x, y, z);
return (int) BetterBlockPos.longHash(x, y, z);
}
@Override

View File

@@ -18,12 +18,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.behavior.LookBehavior;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockLiquid;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
@@ -36,7 +37,7 @@ import java.util.Optional;
import static baritone.utils.InputOverrideHandler.Input;
public abstract class Movement implements Helper, MovementHelper {
public abstract class Movement implements IMovement, Helper, MovementHelper {
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
@@ -77,24 +78,27 @@ public abstract class Movement implements Helper, MovementHelper {
this(src, dest, toBreak, null);
}
public double getCost(CalculationContext context) {
@Override
public double getCost() {
if (cost == null) {
cost = calculateCost(context != null ? context : new CalculationContext());
cost = calculateCost(new CalculationContext());
}
return cost;
}
protected abstract double calculateCost(CalculationContext context);
@Override
public double recalculateCost() {
cost = null;
return getCost(null);
return getCost();
}
protected void override(double cost) {
this.cost = cost;
}
@Override
public double calculateCostWithoutCaching() {
return calculateCost(new CalculationContext());
}
@@ -105,12 +109,16 @@ public abstract class Movement implements Helper, MovementHelper {
*
* @return Status
*/
@Override
public MovementStatus update() {
player().capabilities.allowFlying = false;
MovementState latestState = updateState(currentState);
if (BlockStateInterface.isLiquid(playerFeet())) {
latestState.setInput(Input.JUMP, true);
}
if (player().isEntityInsideOpaqueBlock()) {
latestState.setInput(Input.CLICK_LEFT, true);
}
// 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 ->
@@ -147,7 +155,8 @@ public abstract class Movement implements Helper, MovementHelper {
currentState = latestState;
if (isFinished()) {
// If the current status indicates a completed movement
if (currentState.getStatus().isComplete()) {
onFinish(latestState);
}
@@ -187,6 +196,7 @@ public abstract class Movement implements Helper, MovementHelper {
return true;
}
@Override
public boolean safeToCancel() {
return safeToCancel(currentState);
}
@@ -195,16 +205,12 @@ public abstract class Movement implements Helper, MovementHelper {
return true;
}
public boolean isFinished() {
return (currentState.getStatus() != MovementStatus.RUNNING
&& currentState.getStatus() != MovementStatus.PREPPING
&& currentState.getStatus() != MovementStatus.WAITING);
}
@Override
public BetterBlockPos getSrc() {
return src;
}
@Override
public BetterBlockPos getDest() {
return dest;
}
@@ -223,6 +229,7 @@ public abstract class Movement implements Helper, MovementHelper {
currentState.setStatus(MovementStatus.CANCELED);
}
@Override
public void reset() {
currentState = new MovementState().setStatus(MovementStatus.PREPPING);
}
@@ -247,6 +254,7 @@ public abstract class Movement implements Helper, MovementHelper {
return state;
}
@Override
public BlockPos getDirection() {
return getDest().subtract(getSrc());
}
@@ -255,10 +263,19 @@ public abstract class Movement implements Helper, MovementHelper {
calculatedWhileLoaded = !(world().getChunk(getDest()) instanceof EmptyChunk);
}
@Override
public boolean calculatedWhileLoaded() {
return calculatedWhileLoaded;
}
@Override
public void resetBlockCache() {
toBreakCached = null;
toPlaceCached = null;
toWalkIntoCached = null;
}
@Override
public List<BlockPos> toBreak() {
if (toBreakCached != null) {
return toBreakCached;
@@ -273,6 +290,7 @@ public abstract class Movement implements Helper, MovementHelper {
return result;
}
@Override
public List<BlockPos> toPlace() {
if (toPlaceCached != null) {
return toPlaceCached;
@@ -285,6 +303,7 @@ public abstract class Movement implements Helper, MovementHelper {
return result;
}
@Override
public List<BlockPos> toWalkInto() { // overridden by movementdiagonal
if (toWalkIntoCached == null) {
toWalkIntoCached = new ArrayList<>();

View File

@@ -19,11 +19,11 @@ package baritone.pathing.movement;
import baritone.Baritone;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*;
import net.minecraft.block.properties.PropertyBool;
import net.minecraft.block.state.IBlockState;
@@ -31,6 +31,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.entity.Entity;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemPickaxe;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.NonNullList;
@@ -457,6 +458,22 @@ public interface MovementHelper extends ActionCosts, Helper {
return true;
}
}
if (Baritone.settings().acceptableThrowawayItems.get().contains(p.inventory.offHandInventory.get(0).getItem())) {
// main hand takes precedence over off hand
// that means that if we have block A selected in main hand and block B in off hand, right clicking places block B
// we've already checked above ^ and the main hand can't possible have an acceptablethrowawayitem
// so we need to select in the main hand something that doesn't right click
// so not a shovel, not a hoe, not a block, etc
for (byte i = 0; i < 9; i++) {
ItemStack item = inv.get(i);
if (item.isEmpty() || item.getItem() instanceof ItemPickaxe) {
if (select) {
p.inventory.currentItem = i;
}
return true;
}
}
}
return false;
}

View File

@@ -17,6 +17,7 @@
package baritone.pathing.movement;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.Rotation;
import baritone.utils.InputOverrideHandler.Input;
import net.minecraft.util.math.Vec3d;
@@ -72,10 +73,6 @@ public class MovementState {
return this.inputState;
}
public enum MovementStatus {
PREPPING, WAITING, RUNNING, SUCCESS, UNREACHABLE, FAILED, CANCELED
}
public static class MovementTarget {
/**

View File

@@ -17,8 +17,8 @@
package baritone.pathing.movement;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.movements.*;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.util.EnumFacing;

View File

@@ -18,16 +18,16 @@
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;

View File

@@ -18,14 +18,14 @@
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block;
import net.minecraft.block.BlockFalling;

View File

@@ -17,13 +17,14 @@
package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
@@ -140,12 +141,12 @@ public class MovementDiagonal extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
if (playerFeet().equals(dest)) {
state.setStatus(MovementState.MovementStatus.SUCCESS);
state.setStatus(MovementStatus.SUCCESS);
return state;
}
if (!BlockStateInterface.isLiquid(playerFeet())) {

View File

@@ -17,12 +17,13 @@
package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
@@ -64,12 +65,12 @@ public class MovementDownward extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5);

View File

@@ -18,18 +18,18 @@
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.MovementState.MovementStatus;
import baritone.pathing.movement.MovementState.MovementTarget;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.RayTraceUtils;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.entity.player.InventoryPlayer;
import net.minecraft.init.Items;
@@ -106,7 +106,7 @@ public class MovementFall extends Movement {
}
}
Vec3d destCenter = Utils.getBlockPosCenter(dest); // we are moving to the 0.5 center not the edge (like if we were falling on a ladder)
if (Math.abs(player().posX - destCenter.x) > 0.2 || Math.abs(player().posZ - destCenter.z) > 0.2) {
if (Math.abs(player().posX - destCenter.x) > 0.15 || Math.abs(player().posZ - destCenter.z) > 0.15) {
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
}
return state;
@@ -114,7 +114,9 @@ public class MovementFall extends Movement {
@Override
public boolean safeToCancel(MovementState state) {
return state.getStatus() != MovementStatus.RUNNING;
// if we haven't started walking off the edge yet, or if we're in the process of breaking blocks before doing the fall
// then it's safe to cancel this
return playerFeet().equals(src) || state.getStatus() != MovementStatus.RUNNING;
}
private static BetterBlockPos[] buildPositionsToBreak(BetterBlockPos src, BetterBlockPos dest) {

View File

@@ -18,16 +18,15 @@
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import baritone.utils.*;
import baritone.utils.pathing.MutableMoveResult;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
@@ -35,6 +34,7 @@ import net.minecraft.client.Minecraft;
import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult;
import net.minecraft.util.math.Vec3d;
import java.util.Objects;
@@ -164,10 +164,18 @@ public class MovementParkour extends Movement {
return res.cost;
}
@Override
public boolean safeToCancel(MovementState state) {
// once this movement is instantiated, the state is default to PREPPING
// but once it's ticked for the first time it changes to RUNNING
// since we don't really know anything about momentum, it suffices to say Parkour can only be canceled on the 0th tick
return state.getStatus() != MovementStatus.RUNNING;
}
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
if (dist >= 4) {
@@ -179,10 +187,10 @@ public class MovementParkour extends Movement {
if (d == Blocks.VINE || d == Blocks.LADDER) {
// it physically hurt me to add support for parkour jumping onto a vine
// but i did it anyway
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
if (player().posY - playerFeet().getY() < 0.094) { // lilypads
state.setStatus(MovementState.MovementStatus.SUCCESS);
state.setStatus(MovementStatus.SUCCESS);
}
} else if (!playerFeet().equals(src)) {
if (playerFeet().equals(src.offset(direction)) || player().posY - playerFeet().getY() > 0.0001) {
@@ -196,15 +204,18 @@ public class MovementParkour extends Movement {
}
if (MovementHelper.canPlaceAgainst(against1)) {
if (!MovementHelper.throwaway(true)) {//get ready to place a throwaway block
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
return state.setStatus(MovementStatus.UNREACHABLE);
}
double faceX = (dest.getX() + against1.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + against1.getY()) * 0.5D;
double faceZ = (dest.getZ() + against1.getZ() + 1.0D) * 0.5D;
state.setTarget(new MovementState.MovementTarget(Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations()), true));
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
Rotation place = Utils.calcRotationFromVec3d(playerHead(), new Vec3d(faceX, faceY, faceZ), playerRotations());
RayTraceResult res = RayTraceUtils.rayTraceTowards(place);
if (res != null && res.typeOfHit == RayTraceResult.Type.BLOCK && res.getBlockPos().equals(against1) && res.getBlockPos().offset(res.sideHit).equals(dest.down())) {
state.setTarget(new MovementState.MovementTarget(place, true));
}
LookBehaviorUtils.getSelectedBlock().ifPresent(selectedBlock -> {
EnumFacing side = Minecraft.getMinecraft().objectMouseOver.sideHit;
if (Objects.equals(selectedBlock, against1) && selectedBlock.offset(side).equals(dest.down())) {
state.setInput(InputOverrideHandler.Input.CLICK_RIGHT, true);
}
@@ -214,7 +225,7 @@ public class MovementParkour extends Movement {
}
state.setInput(InputOverrideHandler.Input.JUMP, true);
} else {
} else if(!playerFeet().equals(dest.offset(direction, -1))) {
state.setInput(InputOverrideHandler.Input.SPRINT, false);
if (playerFeet().equals(src.offset(direction, -1))) {
MovementHelper.moveTowards(state, src);

View File

@@ -17,6 +17,8 @@
package baritone.pathing.movement.movements;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
@@ -25,7 +27,6 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
@@ -34,18 +35,11 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
public class MovementPillar extends Movement {
private int numTicks = 0;
public MovementPillar(BetterBlockPos start, BetterBlockPos end) {
super(start, end, new BetterBlockPos[]{start.up(2)}, start);
}
@Override
public void reset() {
super.reset();
numTicks = 0;
}
@Override
protected double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z);
@@ -148,7 +142,7 @@ public class MovementPillar extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
if (state.getStatus() != MovementStatus.RUNNING) {
return state;
}
@@ -161,7 +155,7 @@ public class MovementPillar extends Movement {
state.setInput(InputOverrideHandler.Input.MOVE_FORWARD, true);
}
if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
return state;
}
@@ -178,11 +172,11 @@ public class MovementPillar extends Movement {
BlockPos against = vine ? getAgainst(src) : src.offset(fromDown.getValue(BlockLadder.FACING).getOpposite());
if (against == null) {
logDebug("Unable to climb vines");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (playerFeet().equals(against.up()) || playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
if (MovementHelper.isBottomSlab(src.down())) {
state.setInput(InputOverrideHandler.Input.JUMP, true);
@@ -198,28 +192,25 @@ public class MovementPillar extends Movement {
} else {
// Get ready to place a throwaway block
if (!MovementHelper.throwaway(true)) {
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
return state.setStatus(MovementStatus.UNREACHABLE);
}
numTicks++;
// 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);
// Otherwise jump
if (numTicks > 20) {
double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5);
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
//and 0.17 is reasonably less than 0.2
double diffX = player().posX - (dest.getX() + 0.5);
double diffZ = player().posZ - (dest.getZ() + 0.5);
double dist = Math.sqrt(diffX * diffX + diffZ * diffZ);
if (dist > 0.17) {//why 0.17? because it seemed like a good number, that's why
//[explanation added after baritone port lol] also because it needs to be less than 0.2 because of the 0.3 sneak limit
//and 0.17 is reasonably less than 0.2
// 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);
}
// 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);
}
if (!blockIsThere) {
Block fr = BlockStateInterface.get(src).getBlock();
if (!(fr instanceof BlockAir || fr.isReplaceable(Minecraft.getMinecraft().world, src))) {
@@ -233,7 +224,7 @@ public class MovementPillar extends Movement {
// If we are at our goal and the block below us is placed
if (playerFeet().equals(dest) && blockIsThere) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
return state;

View File

@@ -18,6 +18,8 @@
package baritone.pathing.movement.movements;
import baritone.Baritone;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.behavior.LookBehaviorUtils;
import baritone.pathing.movement.CalculationContext;
@@ -27,7 +29,6 @@ import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface;
import baritone.utils.InputOverrideHandler;
import baritone.utils.Utils;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.*;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
@@ -144,13 +145,13 @@ public class MovementTraverse extends Movement {
@Override
public MovementState updateState(MovementState state) {
super.updateState(state);
if (state.getStatus() != MovementState.MovementStatus.RUNNING) {
if (state.getStatus() != MovementStatus.RUNNING) {
// if the setting is enabled
if (!Baritone.settings().walkWhileBreaking.get()) {
return state;
}
// and if we're prepping (aka mining the block in front)
if (state.getStatus() != MovementState.MovementStatus.PREPPING) {
if (state.getStatus() != MovementStatus.PREPPING) {
return state;
}
// and if it's fine to walk into the blocks in front
@@ -225,7 +226,7 @@ public class MovementTraverse extends Movement {
if (isTheBridgeBlockThere) {
if (playerFeet().equals(dest)) {
return state.setStatus(MovementState.MovementStatus.SUCCESS);
return state.setStatus(MovementStatus.SUCCESS);
}
if (wasTheBridgeBlockAlwaysThere && !BlockStateInterface.isLiquid(playerFeet())) {
state.setInput(InputOverrideHandler.Input.SPRINT, true);
@@ -248,7 +249,7 @@ public class MovementTraverse extends Movement {
if (MovementHelper.canPlaceAgainst(against1)) {
if (!MovementHelper.throwaway(true)) { // get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
return state.setStatus(MovementStatus.UNREACHABLE);
}
if (!Baritone.settings().assumeSafeWalk.get()) {
state.setInput(InputOverrideHandler.Input.SNEAK, true);
@@ -287,7 +288,7 @@ public class MovementTraverse extends Movement {
// Out.log(from + " " + to + " " + faceX + "," + faceY + "," + faceZ + " " + whereAmI);
if (!MovementHelper.throwaway(true)) {// get ready to place a throwaway block
logDebug("bb pls get me some blocks. dirt or cobble");
return state.setStatus(MovementState.MovementStatus.UNREACHABLE);
return state.setStatus(MovementStatus.UNREACHABLE);
}
double faceX = (dest.getX() + src.getX() + 1.0D) * 0.5D;
double faceY = (dest.getY() + src.getY() - 1.0D) * 0.5D;
@@ -319,6 +320,14 @@ public class MovementTraverse extends Movement {
}
}
@Override
public boolean safeToCancel(MovementState state) {
// if we're in the process of breaking blocks before walking forwards
// or if this isn't a sneak place (the block is already there)
// then it's safe to cancel this
return state.getStatus() != MovementStatus.RUNNING || MovementHelper.canWalkOn(dest.down());
}
@Override
protected boolean prepared(MovementState state) {
if (playerFeet().equals(src) || playerFeet().equals(src.down())) {

View File

@@ -19,23 +19,24 @@ 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;
import baritone.api.pathing.movement.MovementStatus;
import baritone.api.pathing.path.IPathExecutor;
import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState;
import baritone.pathing.movement.movements.*;
import baritone.utils.*;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.init.Blocks;
import net.minecraft.util.Tuple;
import net.minecraft.util.math.BlockPos;
import java.util.Collections;
import java.util.HashSet;
import java.util.Set;
import java.util.*;
import static baritone.pathing.movement.MovementState.MovementStatus.*;
import static baritone.api.pathing.movement.MovementStatus.*;
/**
* Behavior to execute a precomputed path. Does not (yet) deal with path segmentation or stitching
@@ -43,7 +44,7 @@ import static baritone.pathing.movement.MovementState.MovementStatus.*;
*
* @author leijurv
*/
public class PathExecutor implements Helper {
public class PathExecutor implements IPathExecutor, Helper {
private static final double MAX_MAX_DIST_FROM_PATH = 3;
private static final double MAX_DIST_FROM_PATH = 2;
@@ -115,7 +116,8 @@ public class PathExecutor implements Helper {
return false;
}
}
for (int i = pathPosition + 2; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
for (int i = pathPosition + 3; i < path.length(); i++) { //dont check pathPosition+1. the movement tells us when it's done (e.g. sneak placing)
// also don't check pathPosition+2 because reasons
if (whereAmI.equals(path.positions().get(i))) {
if (i - pathPosition > 2) {
logDebug("Skipping forward " + (i - pathPosition) + " steps, to " + i);
@@ -128,7 +130,7 @@ public class PathExecutor implements Helper {
}
}
}
Tuple<Double, BlockPos> status = path.closestPathPos();
Tuple<Double, BlockPos> status = closestPathPos(path);
if (possiblyOffPath(status, MAX_DIST_FROM_PATH)) {
ticksAway++;
System.out.println("FAR AWAY FROM PATH FOR " + ticksAway + " TICKS. Current distance: " + status.getFirst() + ". Threshold: " + MAX_DIST_FROM_PATH);
@@ -177,18 +179,16 @@ public class PathExecutor implements Helper {
}
}
}*/
long start = System.nanoTime() / 1000000L;
//long start = System.nanoTime() / 1000000L;
for (int i = pathPosition - 10; i < pathPosition + 10; i++) {
if (i < 0 || i >= path.movements().size()) {
continue;
}
Movement m = path.movements().get(i);
IMovement m = path.movements().get(i);
HashSet<BlockPos> prevBreak = new HashSet<>(m.toBreak());
HashSet<BlockPos> prevPlace = new HashSet<>(m.toPlace());
HashSet<BlockPos> prevWalkInto = new HashSet<>(m.toWalkInto());
m.toBreakCached = null;
m.toPlaceCached = null;
m.toWalkIntoCached = null;
m.resetBlockCache();
if (!prevBreak.equals(new HashSet<>(m.toBreak()))) {
recalcBP = true;
}
@@ -213,16 +213,16 @@ public class PathExecutor implements Helper {
toWalkInto = newWalkInto;
recalcBP = false;
}
long end = System.nanoTime() / 1000000L;
/*long end = System.nanoTime() / 1000000L;
if (end - start > 0) {
System.out.println("Recalculating break and place took " + (end - start) + "ms");
}
Movement movement = path.movements().get(pathPosition);
}*/
IMovement movement = path.movements().get(pathPosition);
boolean canCancel = movement.safeToCancel();
if (costEstimateIndex == null || costEstimateIndex != pathPosition) {
costEstimateIndex = pathPosition;
// do this only once, when the movement starts, and deliberately get the cost as cached when this path was calculated, not the cost as it is right now
currentMovementOriginalCostEstimate = movement.getCost(null);
currentMovementOriginalCostEstimate = movement.getCost();
for (int i = 1; i < Baritone.settings().costVerificationLookahead.get() && pathPosition + i < path.length() - 1; i++) {
if (path.movements().get(pathPosition + i).calculateCostWithoutCaching() >= ActionCosts.COST_INF && canCancel) {
logDebug("Something has changed in the world and a future movement has become impossible. Cancelling.");
@@ -242,7 +242,12 @@ public class PathExecutor implements Helper {
cancel();
return true;
}
MovementState.MovementStatus movementStatus = movement.update();
if (shouldPause()) {
logDebug("Pausing since current best path is a backtrack");
clearKeys();
return true;
}
MovementStatus movementStatus = movement.update();
if (movementStatus == UNREACHABLE || movementStatus == FAILED) {
logDebug("Movement returns status " + movementStatus);
cancel();
@@ -270,6 +275,52 @@ public class PathExecutor implements Helper {
return false; // movement is in progress
}
private Tuple<Double, BlockPos> closestPathPos(IPath path) {
double best = -1;
BlockPos bestPos = null;
for (BlockPos pos : path.positions()) {
double dist = Utils.playerDistanceToCenter(pos);
if (dist < best || best == -1) {
best = dist;
bestPos = pos;
}
}
return new Tuple<>(best, bestPos);
}
private boolean shouldPause() {
Optional<AbstractNodeCostSearch> current = AbstractNodeCostSearch.getCurrentlyRunning();
if (!current.isPresent()) {
return false;
}
if (!player().onGround) {
return false;
}
if (!MovementHelper.canWalkOn(playerFeet().down())) {
// we're in some kind of sketchy situation, maybe parkouring
return false;
}
if (!MovementHelper.canWalkThrough(playerFeet()) || !MovementHelper.canWalkThrough(playerFeet().up())) {
// suffocating?
return false;
}
if (!path.movements().get(pathPosition).safeToCancel()) {
return false;
}
Optional<IPath> currentBest = current.get().bestPathSoFar();
if (!currentBest.isPresent()) {
return false;
}
List<BetterBlockPos> positions = currentBest.get().positions();
if (positions.size() < 3) {
return false; // not long enough yet to justify pausing, its far from certain we'll actually take this route
}
// the first block of the next path will always overlap
// no need to pause our very last movement when it would have otherwise cleanly exited with MovementStatus SUCCESS
positions = positions.subList(1, positions.size());
return positions.contains(playerFeet());
}
private boolean possiblyOffPath(Tuple<Double, BlockPos> status, double leniency) {
double distanceFromPath = status.getFirst();
if (distanceFromPath > leniency) {
@@ -288,10 +339,24 @@ public class PathExecutor implements Helper {
}
}
/**
* Regardless of current path position, snap to the current player feet if possible
*/
public boolean snipsnapifpossible() {
int index = path.positions().indexOf(playerFeet());
if (index == -1) {
return false;
}
pathPosition = index;
clearKeys();
return true;
}
private void sprintIfRequested() {
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext().canSprint()) {
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT, false);
player().setSprinting(false);
return;
}
@@ -304,8 +369,11 @@ public class PathExecutor implements Helper {
return;
}
// we'll take it from here, no need for minecraft to see we're holding down control and sprint for us
Baritone.INSTANCE.getInputOverrideHandler().setInputForceState(InputOverrideHandler.Input.SPRINT, false);
// however, descend doesn't request sprinting, beceause it doesn't know the context of what movement comes after it
Movement current = path.movements().get(pathPosition);
IMovement current = path.movements().get(pathPosition);
if (current instanceof MovementDescend && pathPosition < path.length() - 2) {
// (dest - src) + dest is offset 1 more in the same direction
@@ -320,7 +388,7 @@ public class PathExecutor implements Helper {
}
}
Movement next = path.movements().get(pathPosition + 1);
IMovement next = path.movements().get(pathPosition + 1);
if (next instanceof MovementAscend && current.getDirection().up().equals(next.getDirection().down())) {
// a descend then an ascend in the same direction
if (!player().isSprinting()) {
@@ -344,7 +412,7 @@ public class PathExecutor implements Helper {
//logDebug("Turning off sprinting " + movement + " " + next + " " + movement.getDirection() + " " + next.getDirection().down() + " " + next.getDirection().down().equals(movement.getDirection()));
}
if (current instanceof MovementAscend && pathPosition != 0) {
Movement prev = path.movements().get(pathPosition - 1);
IMovement prev = path.movements().get(pathPosition - 1);
if (prev instanceof MovementDescend && prev.getDirection().up().equals(current.getDirection().down())) {
BlockPos center = current.getSrc().up();
if (player().posY >= center.getY()) { // playerFeet adds 0.1251 to account for soul sand
@@ -359,7 +427,7 @@ public class PathExecutor implements Helper {
player().setSprinting(false);
}
private static boolean canSprintInto(Movement current, Movement next) {
private static boolean canSprintInto(IMovement current, IMovement next) {
if (next instanceof MovementDescend) {
if (next.getDirection().equals(current.getDirection())) {
return true;
@@ -397,6 +465,7 @@ public class PathExecutor implements Helper {
return pathPosition;
}
@Override
public IPath getPath() {
return path;
}

View File

@@ -35,8 +35,6 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
public static final BaritoneAutoTest INSTANCE = new BaritoneAutoTest();
private BaritoneAutoTest() {}
public static final boolean ENABLE_AUTO_TEST = "true".equals(System.getenv("BARITONE_AUTO_TEST"));
private static final long TEST_SEED = -928872506371745L;
private static final BlockPos STARTING_POSITION = new BlockPos(0, 65, 0);
@@ -123,4 +121,6 @@ public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
}
}
}
private BaritoneAutoTest() {}
}

View File

@@ -23,6 +23,7 @@ import baritone.api.cache.IWaypoint;
import baritone.api.event.events.ChatEvent;
import baritone.api.pathing.goals.*;
import baritone.api.pathing.movement.ActionCosts;
import baritone.api.utils.SettingsUtil;
import baritone.behavior.Behavior;
import baritone.behavior.FollowBehavior;
import baritone.behavior.MineBehavior;
@@ -31,7 +32,6 @@ import baritone.cache.ChunkPacker;
import baritone.cache.Waypoint;
import baritone.cache.WorldProvider;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.Moves;
@@ -79,6 +79,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
setting.value ^= true;
event.cancel();
logDirect("Toggled " + setting.getName() + " to " + setting.value);
SettingsUtil.save(Baritone.settings());
return;
}
}
@@ -112,6 +113,7 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
event.cancel();
return;
}
SettingsUtil.save(Baritone.settings());
logDirect(setting.toString());
event.cancel();
return;
@@ -467,10 +469,10 @@ public class ExampleBaritoneControl extends Behavior implements Helper {
while (moves.contains(null)) {
moves.remove(null);
}
moves.sort(Comparator.comparingDouble(movement -> movement.getCost(new CalculationContext())));
moves.sort(Comparator.comparingDouble(Movement::getCost));
for (Movement move : moves) {
String[] parts = move.getClass().toString().split("\\.");
double cost = move.getCost(new CalculationContext());
double cost = move.getCost();
String strCost = cost + "";
if (cost >= ActionCosts.COST_INF) {
strCost = "IMPOSSIBLE";

View File

@@ -18,8 +18,8 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.Rotation;
import baritone.utils.pathing.BetterBlockPos;
import net.minecraft.block.BlockSlab;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;

View File

@@ -18,13 +18,17 @@
package baritone.utils;
import baritone.Baritone;
import baritone.api.event.events.RenderEvent;
import baritone.api.pathing.calc.IPath;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.pathing.goals.GoalXZ;
import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.interfaces.IGoalRenderPos;
import baritone.pathing.path.IPath;
import baritone.utils.pathing.BetterBlockPos;
import baritone.behavior.PathingBehavior;
import baritone.pathing.calc.AbstractNodeCostSearch;
import baritone.pathing.path.PathExecutor;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.Minecraft;
import net.minecraft.client.entity.EntityPlayerSP;
@@ -40,6 +44,7 @@ import net.minecraft.util.math.MathHelper;
import java.awt.*;
import java.util.Collection;
import java.util.Collections;
import java.util.List;
import static org.lwjgl.opengl.GL11.*;
@@ -55,6 +60,62 @@ public final class PathRenderer implements Helper {
private PathRenderer() {}
public static void render(RenderEvent event, PathingBehavior behavior) {
// System.out.println("Render passing");
// System.out.println(event.getPartialTicks());
float partialTicks = event.getPartialTicks();
Goal goal = behavior.getGoal();
EntityPlayerSP player = mc.player;
if (goal != null && Baritone.settings().renderGoal.value) {
drawLitDankGoalBox(player, goal, partialTicks, Baritone.settings().colorGoalBox.get());
}
if (!Baritone.settings().renderPath.get()) {
return;
}
//drawManySelectionBoxes(player, Collections.singletonList(behavior.pathStart()), partialTicks, Color.WHITE);
//long start = System.nanoTime();
PathExecutor current = behavior.getCurrent(); // this should prevent most race conditions?
PathExecutor next = behavior.getNext(); // like, now it's not possible for current!=null to be true, then suddenly false because of another thread
// TODO is this enough, or do we need to acquire a lock here?
// TODO benchmark synchronized in render loop
// Render the current path, if there is one
if (current != null && current.getPath() != null) {
int renderBegin = Math.max(current.getPosition() - 3, 0);
drawPath(current.getPath(), renderBegin, player, partialTicks, Baritone.settings().colorCurrentPath.get(), Baritone.settings().fadePath.get(), 10, 20);
}
if (next != null && next.getPath() != null) {
drawPath(next.getPath(), 0, player, partialTicks, Baritone.settings().colorNextPath.get(), Baritone.settings().fadePath.get(), 10, 20);
}
//long split = System.nanoTime();
if (current != null) {
drawManySelectionBoxes(player, current.toBreak(), partialTicks, Baritone.settings().colorBlocksToBreak.get());
drawManySelectionBoxes(player, current.toPlace(), partialTicks, Baritone.settings().colorBlocksToPlace.get());
drawManySelectionBoxes(player, current.toWalkInto(), partialTicks, Baritone.settings().colorBlocksToWalkInto.get());
}
// If there is a path calculation currently running, render the path calculation process
AbstractNodeCostSearch.getCurrentlyRunning().ifPresent(currentlyRunning -> {
currentlyRunning.bestPathSoFar().ifPresent(p -> {
drawPath(p, 0, player, partialTicks, Baritone.settings().colorBestPathSoFar.get(), Baritone.settings().fadePath.get(), 10, 20);
});
currentlyRunning.pathToMostRecentNodeConsidered().ifPresent(mr -> {
drawPath(mr, 0, player, partialTicks, Baritone.settings().colorMostRecentConsidered.get(), Baritone.settings().fadePath.get(), 10, 20);
drawManySelectionBoxes(player, Collections.singletonList(mr.getDest()), partialTicks, Baritone.settings().colorMostRecentConsidered.get());
});
});
//long end = System.nanoTime();
//System.out.println((end - split) + " " + (split - start));
// if (end - start > 0) {
// System.out.println("Frame took " + (split - start) + " " + (end - split));
//}
}
public static void drawPath(IPath path, int startIndex, EntityPlayerSP player, float partialTicks, Color color, boolean fadeOut, int fadeStart0, int fadeEnd0) {
GlStateManager.enableBlend();
GlStateManager.tryBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ZERO);
@@ -62,6 +123,9 @@ public final class PathRenderer implements Helper {
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
if (Baritone.settings().renderPathIgnoreDepth.get()) {
GlStateManager.disableDepth();
}
List<BetterBlockPos> positions = path.positions();
int next;
Tessellator tessellator = Tessellator.getInstance();
@@ -102,6 +166,9 @@ public final class PathRenderer implements Helper {
drawLine(player, x1, y1, z1, x2, y2, z2, partialTicks);
tessellator.draw();
}
if (Baritone.settings().renderPathIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
//GlStateManager.color(0.0f, 0.0f, 0.0f, 0.4f);
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
@@ -127,6 +194,11 @@ public final class PathRenderer implements Helper {
GlStateManager.glLineWidth(Baritone.settings().pathRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
GlStateManager.disableDepth();
}
float expand = 0.002F;
//BlockPos blockpos = movingObjectPositionIn.getBlockPos();
@@ -168,6 +240,10 @@ public final class PathRenderer implements Helper {
TESSELLATOR.draw();
});
if (Baritone.settings().renderSelectionBoxesIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
@@ -232,26 +308,12 @@ public final class PathRenderer implements Helper {
GlStateManager.glLineWidth(Baritone.settings().goalRenderLineWidthPixels.get());
GlStateManager.disableTexture2D();
GlStateManager.depthMask(false);
if (y1 != 0) {
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, y1, minZ).endVertex();
BUFFER.pos(maxX, y1, minZ).endVertex();
BUFFER.pos(maxX, y1, maxZ).endVertex();
BUFFER.pos(minX, y1, maxZ).endVertex();
BUFFER.pos(minX, y1, minZ).endVertex();
TESSELLATOR.draw();
if (Baritone.settings().renderGoalIgnoreDepth.get()) {
GlStateManager.disableDepth();
}
if (y2 != 0) {
BUFFER.begin(GL_LINE_STRIP, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, y2, minZ).endVertex();
BUFFER.pos(maxX, y2, minZ).endVertex();
BUFFER.pos(maxX, y2, maxZ).endVertex();
BUFFER.pos(minX, y2, maxZ).endVertex();
BUFFER.pos(minX, y2, minZ).endVertex();
TESSELLATOR.draw();
}
renderHorizontalQuad(minX, maxX, minZ, maxZ, y1);
renderHorizontalQuad(minX, maxX, minZ, maxZ, y2);
BUFFER.begin(GL_LINES, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, minY, minZ).endVertex();
@@ -264,9 +326,22 @@ public final class PathRenderer implements Helper {
BUFFER.pos(minX, maxY, maxZ).endVertex();
TESSELLATOR.draw();
if (Baritone.settings().renderGoalIgnoreDepth.get()) {
GlStateManager.enableDepth();
}
GlStateManager.depthMask(true);
GlStateManager.enableTexture2D();
GlStateManager.disableBlend();
}
private static void renderHorizontalQuad(double minX, double maxX, double minZ, double maxZ, double y) {
if (y != 0) {
BUFFER.begin(GL_LINE_LOOP, DefaultVertexFormats.POSITION);
BUFFER.pos(minX, y, minZ).endVertex();
BUFFER.pos(maxX, y, minZ).endVertex();
BUFFER.pos(maxX, y, maxZ).endVertex();
BUFFER.pos(minX, y, maxZ).endVertex();
TESSELLATOR.draw();
}
}
}

View File

@@ -17,6 +17,7 @@
package baritone.utils.pathing;
import baritone.api.utils.BetterBlockPos;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import org.junit.Test;