Compare commits

...

99 Commits

Author SHA1 Message Date
Leijurv 9ce574266f Merge branch 'master' into benchmark 2019-01-17 12:24:23 -08:00
Leijurv a5b9885767 not even used 2019-01-17 12:22:36 -08:00
Leijurv 2daedecf92 maybe fix 2019-01-16 17:42:43 -08:00
Brady db24822d2f Fix cursed exception 2019-01-16 13:50:15 -06:00
Brady 59320d9b85 Auto test class javadoc 2019-01-16 13:37:39 -06:00
Leijurv 9dfcef6356 crucial performance optimization 2019-01-15 17:21:50 -08:00
Leijurv ae3fc14b52 refactor name 2019-01-14 19:52:31 -08:00
Leijurv f8681d179d TODO use nanotime when calc starts on dec 31 2019-01-13 00:00:52 -08:00
Leijurv f23630064e reorder 2019-01-12 22:33:46 -08:00
Leijurv bec7f9be96 this lets proguard optimize out one more double division 2019-01-11 13:18:31 -08:00
Leijurv 09e94eaa8e not anymore 2019-01-11 13:02:03 -08:00
Leijurv 5f29bb3e7f gotta go fast 2019-01-10 18:55:55 -08:00
Leijurv 1ad6a0d5b5 remove all that crap lol 2019-01-10 18:21:02 -08:00
Brady f727e71eaf Expose IPathingControlManager in IBaritone 2019-01-10 19:57:09 -06:00
Leijurv 14f006c3a5 Merge branch 'epic-movement-input' 2019-01-10 17:25:57 -08:00
Leijurv 200211c186 dont continue walking if there is no process in charge 2019-01-10 13:52:52 -08:00
Leijurv 5ca214534d mouse stuff 2019-01-09 19:11:53 -08:00
Leijurv 85ea21e83b epic movement input 2019-01-09 18:22:34 -08:00
Leijurv 7d572d748b shouldnt be needed actually 2019-01-09 15:13:48 -08:00
Leijurv fbcae10f96 cherry picked fix from builder 2019-01-09 15:13:09 -08:00
Leijurv a4495ce80a tweaks 2019-01-08 22:00:33 -08:00
Leijurv f5478f6169 Merge pull request #306 from babbaj/master
fix garbage code
2019-01-08 21:56:27 -08:00
babbaj ae1e229619 fix garbage code 2019-01-09 05:39:37 -05:00
Leijurv bc5982b994 fine lol 2019-01-08 20:45:35 -08:00
Leijurv e971d5d43f prevent favoring from affecting movement cost thresholds 2019-01-08 14:56:21 -08:00
Leijurv ee9519d891 tweaks 2019-01-07 08:53:39 -08:00
Leijurv 58bb209158 Merge pull request #305 from babbaj/master
real gamers do it like this
2019-01-07 08:45:26 -08:00
babbaj 23dc97ad5e oops that should have been static 2019-01-07 01:25:39 -05:00
Leijurv 84b580b001 cursed 2019-01-06 22:21:52 -08:00
babbaj 227b303669 value doesnt have to be lowercase 2019-01-07 01:16:52 -05:00
babbaj 712a0a3905 refactor SettingsUtil to be more epic 2019-01-07 01:08:46 -05:00
EvilSourcerer 76427b8ecb real gamers use bufferedreader 2019-01-06 19:10:47 -06:00
Leijurv 8b6d621d20 crucial performance optimization 2019-01-05 23:38:24 -08:00
Leijurv 7898b24bac mc is weird 2019-01-04 23:37:00 -08:00
Leijurv 39648c5dc6 comment 2019-01-03 23:40:43 -08:00
Leijurv 83e6b2fdfe cursed 2019-01-02 21:08:31 -08:00
Leijurv 816727d65b not happening 2019-01-01 22:32:43 -08:00
Leijurv 0e012adb6c unneeded 2018-12-31 08:00:43 -10:00
Leijurv 539b0e64c8 bitshift 2: electric boogaloo 2018-12-30 07:36:10 -10:00
Leijurv 258700ee7b bitshift 2018-12-29 14:50:21 -10:00
Leijurv 1da72ba473 unneeded 2018-12-28 17:17:43 -10:00
Leijurv c2c69f243e nothing is trashy in baritone 2018-12-27 16:16:12 -10:00
Brady dffbb8e4c8 Overload reachable with IPlayerContext parameter 2018-12-27 17:15:32 -06:00
Leijurv bebdede33b unneeded 2018-12-26 18:07:14 -10:00
Leijurv 50d37bb311 lol 2018-12-25 20:07:26 -08:00
Leijurv bbb73008ac stupid 2018-12-24 18:42:01 -08:00
Brady c324f11a96 Fix bad block breaking that NCP doesn't agree with 2018-12-24 12:15:23 -06:00
Leijurv c4eb6be0fe dumb 2018-12-23 23:09:02 -08:00
Leijurv 64200030d2 brady was too optimistic 2018-12-22 20:38:44 -08:00
Leijurv 4d7e74365b reformat 2018-12-21 17:54:16 -08:00
Leijurv b9b25e7e6b no more stupid wrapper getters 2018-12-20 21:22:18 -08:00
Leijurv 8a4f48f08d diagonal descend option 2018-12-20 21:06:56 -08:00
Leijurv ae9ab03e51 walk on water hunger penalty 2018-12-19 22:01:47 -08:00
Leijurv 02478ee887 wtF 2018-12-19 21:30:58 -08:00
Leijurv 57f238de7d that was a big screwup 2018-12-19 17:02:09 -08:00
Leijurv 77938a77e8 add jump penalty 2018-12-19 14:37:11 -08:00
Leijurv d41aa5f9ae epicly fast 2018-12-19 12:59:07 -08:00
Leijurv 0ef3386ebf appease codacy 2018-12-19 12:48:41 -08:00
Brady 9703de86d3 Fix NullPointerException 2018-12-18 19:36:43 -06:00
Brady 764e8d7daa Add windowClick to IPlayerController 2018-12-18 19:27:45 -06:00
Brady 18f5c129a4 Remove dependency for PlayerControllerMP implementation 2018-12-18 19:25:23 -06:00
Leijurv 807d6a0cf4 crucial performance optimization 2018-12-18 16:22:54 -08:00
Leijurv a0ab2a8ba7 timing meme 2018-12-18 16:16:32 -08:00
Leijurv 90d0fb7efb simplify check 2018-12-17 18:27:31 -08:00
Leijurv fe4290b218 little fix 2018-12-16 20:14:21 -08:00
Leijurv cc04342358 epic performance 2018-12-16 16:26:48 -08:00
Leijurv 66da826eab fix toxic cloud 2018-12-15 22:25:50 -08:00
Leijurv dcb93dab50 Merge branch 'master' into benchmark 2018-11-23 13:42:20 -08:00
Leijurv f8c0b4c1c1 Merge branch 'master' into benchmark 2018-11-13 13:30:51 -08:00
Leijurv c41f65d4f6 clean up benchmark branch 2018-09-27 11:38:32 -07:00
Leijurv 54811fb643 merge 2018-09-27 10:22:37 -07:00
Leijurv 92442dcdb9 total accounted time 2018-09-26 13:58:11 -07:00
Leijurv 68af1f3bb3 Merge branch 'master' into benchmark 2018-09-26 13:46:29 -07:00
Leijurv a796e9c047 merge 2018-09-26 13:45:00 -07:00
Leijurv 2c32cadf18 count BetterBlockPos 2018-09-22 08:55:46 -07:00
Leijurv 32cd519bcf merge 2018-09-22 08:51:03 -07:00
Leijurv 88908d8776 more better block pos 2018-09-22 08:47:02 -07:00
Leijurv 79bd26968a count betterblockpos instantiation 2018-09-21 22:10:25 -07:00
Leijurv 2d288c7a47 Merge branch 'master' into benchmark 2018-09-21 21:58:26 -07:00
Leijurv 2c46458bc1 merge 2018-09-11 13:57:01 -07:00
Brady 9c37414e50 Merge branch 'master' into benchmark 2018-09-07 19:31:01 -05:00
Leijurv fb667c3b4d merge 2018-09-04 15:41:35 -07:00
Leijurv da07b63e0a measure 2018-08-31 12:57:38 -07:00
Leijurv 1fe262929e forgot print 2018-08-31 12:04:55 -07:00
Leijurv 0ee93aea23 cache chunk in BlockStateInterface 2018-08-31 11:51:43 -07:00
Leijurv 836b41a3aa num lookups check 2018-08-31 11:51:08 -07:00
Leijurv c370461a24 merge 2018-08-31 11:45:45 -07:00
Leijurv a753fe5df9 bench the whole loop 2018-08-29 14:46:58 -07:00
Leijurv 27aeba3f8b Merge branch 'master' into benchmark 2018-08-29 14:16:32 -07:00
Leijurv 141a9f92cb node map performance, fixes #107 2018-08-29 13:21:54 -07:00
Leijurv 5e4f0b47c5 merge 2018-08-29 12:24:45 -07:00
leijurv d0a88987a8 format 2018-08-29 07:38:35 -07:00
leijurv 9cb199d40a also bench getnode 2018-08-28 21:31:16 -07:00
leijurv a1d218b37a merge 2018-08-28 21:17:12 -07:00
leijurv 7ae1a9f6e4 3x faster cache check 2018-08-28 21:14:50 -07:00
leijurv fd74fcabc0 way more bench checks 2018-08-28 21:10:56 -07:00
leijurv 4da155c0ed 20% improvement to cached chunk check performance 2018-08-28 21:10:41 -07:00
leijurv 7a3f7f9a9e Merge branch 'master' into benchmark 2018-08-28 20:51:42 -07:00
Leijurv 1212d34f91 rudimentary benchmark 2018-08-28 15:48:36 -07:00
66 changed files with 617 additions and 480 deletions
-2
View File
@@ -25,8 +25,6 @@ Here are some links to help to get started:
- [Installation](INSTALL.md) - [Installation](INSTALL.md)
There's also some useful information down below
# Setup # Setup
## Command Line ## Command Line
@@ -208,7 +208,7 @@ public class ProguardTask extends BaritoneGradleTask {
Objects.requireNonNull(extension); Objects.requireNonNull(extension);
// for some reason cant use Class.forName // for some reason cant use Class.forName
Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); Class<?> class_baseExtension = extension.getClass().getSuperclass().getSuperclass().getSuperclass(); // <-- cursed
Field f_replacer = class_baseExtension.getDeclaredField("replacer"); Field f_replacer = class_baseExtension.getDeclaredField("replacer");
f_replacer.setAccessible(true); f_replacer.setAccessible(true);
Object replacer = f_replacer.get(extension); Object replacer = f_replacer.get(extension);
@@ -26,4 +26,4 @@ public enum MappingType {
SEARGE, SEARGE,
NOTCH, NOTCH,
CUSTOM // forgegradle CUSTOM // forgegradle
} }
@@ -60,4 +60,4 @@ public class ReobfWrapper {
throw new IllegalStateException(ex); throw new IllegalStateException(ex);
} }
} }
} }
+3
View File
@@ -21,6 +21,7 @@ import baritone.api.behavior.ILookBehavior;
import baritone.api.behavior.IPathingBehavior; import baritone.api.behavior.IPathingBehavior;
import baritone.api.cache.IWorldProvider; import baritone.api.cache.IWorldProvider;
import baritone.api.event.listener.IEventBus; import baritone.api.event.listener.IEventBus;
import baritone.api.pathing.calc.IPathingControlManager;
import baritone.api.process.ICustomGoalProcess; import baritone.api.process.ICustomGoalProcess;
import baritone.api.process.IFollowProcess; import baritone.api.process.IFollowProcess;
import baritone.api.process.IGetToBlockProcess; import baritone.api.process.IGetToBlockProcess;
@@ -64,6 +65,8 @@ public interface IBaritone {
*/ */
IWorldProvider getWorldProvider(); IWorldProvider getWorldProvider();
IPathingControlManager getPathingControlManager();
IInputOverrideHandler getInputOverrideHandler(); IInputOverrideHandler getInputOverrideHandler();
ICustomGoalProcess getCustomGoalProcess(); ICustomGoalProcess getCustomGoalProcess();
+20 -7
View File
@@ -68,6 +68,16 @@ public class Settings {
*/ */
public Setting<Double> blockBreakAdditionalPenalty = new Setting<>(2D); public Setting<Double> blockBreakAdditionalPenalty = new Setting<>(2D);
/**
* Additional penalty for hitting the space bar (ascend, pillar, or parkour) beacuse it uses hunger
*/
public Setting<Double> jumpPenalty = new Setting<>(2D);
/**
* Walking on water uses up hunger really quick, so penalize it
*/
public Setting<Double> walkOnWaterOnePenalty = new Setting<>(5D);
/** /**
* Allow Baritone to fall arbitrary distances and place a water bucket beneath it. * Allow Baritone to fall arbitrary distances and place a water bucket beneath it.
* Reliability: questionable. * Reliability: questionable.
@@ -101,6 +111,15 @@ public class Settings {
*/ */
public Setting<Boolean> allowJumpAt256 = new Setting<>(false); public Setting<Boolean> allowJumpAt256 = new Setting<>(false);
/**
* Allow descending diagonally
* <p>
* Safer than allowParkour yet still slightly unsafe, can make contact with unchecked adjacent blocks, so it's unsafe in the nether.
* <p>
* For a generic "take some risks" mode I'd turn on this one, parkour, and parkour place.
*/
public Setting<Boolean> allowDiagonalDescend = new Setting<>(false);
/** /**
* Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.) * Blocks that Baritone is allowed to place (as throwaway, for sneak bridging, pillaring, etc.)
*/ */
@@ -153,10 +172,8 @@ public class Settings {
* metric gets better and better with each block, instead of slightly worse. * metric gets better and better with each block, instead of slightly worse.
* <p> * <p>
* Finding the optimal path is worth it, so it's the default. * Finding the optimal path is worth it, so it's the default.
* <p>
* This value is an expression instead of a literal so that it's exactly equal to SPRINT_ONE_BLOCK_COST defined in ActionCosts.java
*/ */
public Setting<Double> costHeuristic = new Setting<>(20 / 5.612); public Setting<Double> costHeuristic = new Setting<>(3.563);
// a bunch of obscure internal A* settings that you probably don't want to change // a bunch of obscure internal A* settings that you probably don't want to change
/** /**
@@ -435,10 +452,6 @@ public class Settings {
/** /**
* {@code true}: can mine blocks when in inventory, chat, or tabbed away in ESC menu * {@code true}: can mine blocks when in inventory, chat, or tabbed away in ESC menu
* <p>
* {@code false}: works on cosmic prisons
* <p>
* LOL
*/ */
public Setting<Boolean> leftClickWorkaround = new Setting<>(true); public Setting<Boolean> leftClickWorkaround = new Setting<>(true);
@@ -36,9 +36,6 @@ public interface AbstractGameEventListener extends IGameEventListener {
@Override @Override
default void onPlayerUpdate(PlayerUpdateEvent event) {} default void onPlayerUpdate(PlayerUpdateEvent event) {}
@Override
default void onProcessKeyBinds() {}
@Override @Override
default void onSendChatMessage(ChatEvent event) {} default void onSendChatMessage(ChatEvent event) {}
@@ -49,11 +49,6 @@ public interface IGameEventListener {
*/ */
void onPlayerUpdate(PlayerUpdateEvent event); void onPlayerUpdate(PlayerUpdateEvent event);
/**
* Run once per game tick from before keybinds are processed.
*/
void onProcessKeyBinds();
/** /**
* Runs whenever the client player sends a message to the server. * Runs whenever the client player sends a message to the server.
* *
@@ -36,7 +36,6 @@ public interface IPathFinder {
* *
* @param primaryTimeout If a path is found, the path finder will stop after this amount of time * @param primaryTimeout If a path is found, the path finder will stop after this amount of time
* @param failureTimeout If a path isn't found, the path finder will continue for this amount of time * @param failureTimeout If a path isn't found, the path finder will continue for this amount of time
*
* @return The final path * @return The final path
*/ */
PathCalculationResult calculate(long primaryTimeout, long failureTimeout); PathCalculationResult calculate(long primaryTimeout, long failureTimeout);
@@ -33,7 +33,6 @@ public interface Goal {
* @param x The goal X position * @param x The goal X position
* @param y The goal Y position * @param y The goal Y position
* @param z The goal Z position * @param z The goal Z position
*
* @return Whether or not it satisfies this goal * @return Whether or not it satisfies this goal
*/ */
boolean isInGoal(int x, int y, int z); boolean isInGoal(int x, int y, int z);
@@ -44,7 +43,6 @@ public interface Goal {
* @param x The goal X position * @param x The goal X position
* @param y The goal Y position * @param y The goal Y position
* @param z The goal Z position * @param z The goal Z position
*
* @return The estimate number of ticks to satisfy the goal * @return The estimate number of ticks to satisfy the goal
*/ */
double heuristic(int x, int y, int z); double heuristic(int x, int y, int z);
@@ -35,6 +35,15 @@ public final class BetterBlockPos extends BlockPos {
public final int x; public final int x;
public final int y; public final int y;
public final int z; public final int z;
public static long numCreated;
static {
numCreated = 0;
}
{
numCreated++;
}
public BetterBlockPos(int x, int y, int z) { public BetterBlockPos(int x, int y, int z) {
super(x, y, z); super(x, y, z);
@@ -27,9 +27,7 @@ import net.minecraft.client.settings.KeyBinding;
*/ */
public interface IInputOverrideHandler extends IBehavior { public interface IInputOverrideHandler extends IBehavior {
default boolean isInputForcedDown(KeyBinding key) { Boolean isInputForcedDown(KeyBinding key);
return isInputForcedDown(Input.getInputForBind(key));
}
boolean isInputForcedDown(Input input); boolean isInputForcedDown(Input input);
@@ -20,7 +20,6 @@ package baritone.api.utils;
import baritone.api.cache.IWorldData; import baritone.api.cache.IWorldData;
import net.minecraft.block.BlockSlab; import net.minecraft.block.BlockSlab;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.entity.Entity; import net.minecraft.entity.Entity;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
@@ -37,7 +36,7 @@ public interface IPlayerContext {
EntityPlayerSP player(); EntityPlayerSP player();
PlayerControllerMP playerController(); IPlayerController playerController();
World world(); World world();
@@ -17,11 +17,30 @@
package baritone.api.utils; package baritone.api.utils;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType;
/** /**
* @author Brady * @author Brady
* @since 9/23/2018 * @since 12/14/2018
*/ */
public class Logger { public interface IPlayerController {
boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side);
void resetBlockRemoving();
ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player);
void setGameType(GameType type);
GameType getGameType();
default double getBlockReachDistance() {
return this.getGameType().isCreative() ? 5.0F : 4.5F;
}
} }
@@ -19,6 +19,7 @@ package baritone.api.utils;
import baritone.api.pathing.calc.IPath; import baritone.api.pathing.calc.IPath;
import java.util.Objects;
import java.util.Optional; import java.util.Optional;
public class PathCalculationResult { public class PathCalculationResult {
@@ -31,11 +32,9 @@ public class PathCalculationResult {
} }
public PathCalculationResult(Type type, IPath path) { public PathCalculationResult(Type type, IPath path) {
Objects.requireNonNull(type);
this.path = path; this.path = path;
this.type = type; this.type = type;
if (type == null) {
throw new IllegalArgumentException("come on");
}
} }
public final Optional<IPath> getPath() { public final Optional<IPath> getPath() {
@@ -127,6 +127,16 @@ public final class RotationUtils {
return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2)); return new Vec3d((double) (f1 * f2), (double) f3, (double) (f * f2));
} }
/**
* @param ctx Context for the viewing entity
* @param pos The target block position
* @return The optional rotation
* @see #reachable(EntityPlayerSP, BlockPos, double)
*/
public static Optional<Rotation> reachable(IPlayerContext ctx, BlockPos pos) {
return reachable(ctx.player(), pos, ctx.playerController().getBlockReachDistance());
}
/** /**
* Determines if the specified entity is able to reach the center of any of the sides * Determines if the specified entity is able to reach the center of any of the sides
* of the specified block. It first checks if the block center is reachable, and if so, * of the specified block. It first checks if the block center is reachable, and if so,
@@ -18,56 +18,77 @@
package baritone.api.utils; package baritone.api.utils;
import baritone.api.Settings; import baritone.api.Settings;
import net.minecraft.client.Minecraft;
import net.minecraft.item.Item; import net.minecraft.item.Item;
import net.minecraft.util.ResourceLocation; import net.minecraft.util.ResourceLocation;
import java.awt.*; import java.awt.*;
import java.io.File; import java.io.BufferedReader;
import java.io.FileOutputStream; import java.io.BufferedWriter;
import java.util.*; import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
import java.util.function.Consumer;
import java.util.function.Function; import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors; import java.util.stream.Collectors;
import java.util.stream.Stream; import java.util.stream.Stream;
import static net.minecraft.client.Minecraft.getMinecraft;
public class SettingsUtil { public class SettingsUtil {
private static final File settingsFile = new File(new File(Minecraft.getMinecraft().gameDir, "baritone"), "settings.txt"); private static final Path SETTINGS_PATH = getMinecraft().gameDir.toPath().resolve("baritone").resolve("settings.txt");
private static final Pattern SETTING_PATTERN = Pattern.compile("^(?<setting>[^ ]+) +(?<value>[^ ]+)"); // 2 words separated by spaces
private static final Map<Class<?>, SettingsIO> map; private static final Map<Class<?>, SettingsIO> map;
private static boolean isComment(String line) {
return line.startsWith("#") || line.startsWith("//");
}
private static void forEachLine(Path file, Consumer<String> consumer) throws IOException {
try (BufferedReader scan = Files.newBufferedReader(file)) {
String line;
while ((line = scan.readLine()) != null) {
if (line.isEmpty() || isComment(line)) {
continue;
}
consumer.accept(line);
}
}
}
public static void readAndApply(Settings settings) { public static void readAndApply(Settings settings) {
try (Scanner scan = new Scanner(settingsFile)) { try {
while (scan.hasNextLine()) { forEachLine(SETTINGS_PATH, line -> {
String line = scan.nextLine(); Matcher matcher = SETTING_PATTERN.matcher(line);
if (line.isEmpty()) { if (!matcher.matches()) {
continue; System.out.println("Invalid syntax in setting file: " + line);
return;
} }
if (line.startsWith("#") || line.startsWith("//")) {
continue; String settingName = matcher.group("setting").toLowerCase();
} String settingValue = matcher.group("value");
int space = line.indexOf(" ");
if (space == -1) {
System.out.println("Skipping invalid line with no space: " + line);
continue;
}
String settingName = line.substring(0, space).trim().toLowerCase();
String settingValue = line.substring(space).trim();
try { try {
parseAndApply(settings, settingName, settingValue); parseAndApply(settings, settingName, settingValue);
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
System.out.println("Unable to parse line " + line); System.out.println("Unable to parse line " + line);
ex.printStackTrace();
} }
} });
} catch (Exception ex) { } catch (Exception ex) {
ex.printStackTrace();
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!"); System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
ex.printStackTrace();
} }
} }
public static synchronized void save(Settings settings) { public static synchronized void save(Settings settings) {
try (FileOutputStream out = new FileOutputStream(settingsFile)) { try (BufferedWriter out = Files.newBufferedWriter(SETTINGS_PATH)) {
for (Settings.Setting setting : settings.allSettings) { for (Settings.Setting setting : settings.allSettings) {
if (setting.get() == null) { if (setting.get() == null) {
System.out.println("NULL SETTING?" + setting.getName()); System.out.println("NULL SETTING?" + setting.getName());
@@ -83,11 +104,11 @@ public class SettingsUtil {
if (io == null) { if (io == null) {
throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting + " " + setting.getName()); throw new IllegalStateException("Missing " + setting.getValueClass() + " " + setting + " " + setting.getName());
} }
out.write((setting.getName() + " " + io.toString.apply(setting.get()) + "\n").getBytes()); out.write(setting.getName() + " " + io.toString.apply(setting.get()) + "\n");
} }
} catch (Exception ex) { } catch (Exception ex) {
System.out.println("Exception thrown while saving Baritone settings!");
ex.printStackTrace(); ex.printStackTrace();
System.out.println("Exception while saving Baritone settings!");
} }
} }
@@ -18,8 +18,10 @@
package baritone.launch.mixins; package baritone.launch.mixins;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.utils.Helper;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import org.spongepowered.asm.mixin.Mixin; import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Shadow;
import org.spongepowered.asm.mixin.injection.At; import org.spongepowered.asm.mixin.injection.At;
import org.spongepowered.asm.mixin.injection.Inject; import org.spongepowered.asm.mixin.injection.Inject;
import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable; import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@@ -31,6 +33,9 @@ import org.spongepowered.asm.mixin.injection.callback.CallbackInfoReturnable;
@Mixin(KeyBinding.class) @Mixin(KeyBinding.class)
public class MixinKeyBinding { public class MixinKeyBinding {
@Shadow
public int pressTime;
@Inject( @Inject(
method = "isKeyDown", method = "isKeyDown",
at = @At("HEAD"), at = @At("HEAD"),
@@ -38,8 +43,26 @@ public class MixinKeyBinding {
) )
private void isKeyDown(CallbackInfoReturnable<Boolean> cir) { private void isKeyDown(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys // only the primary baritone forces keys
if (BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this)) { Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
cir.setReturnValue(true); if (force != null) {
cir.setReturnValue(force); // :sunglasses:
}
}
@Inject(
method = "isPressed",
at = @At("HEAD"),
cancellable = true
)
private void isPressed(CallbackInfoReturnable<Boolean> cir) {
// only the primary baritone forces keys
Boolean force = BaritoneAPI.getProvider().getPrimaryBaritone().getInputOverrideHandler().isInputForcedDown((KeyBinding) (Object) this);
if (force != null && force == false) { // <-- cursed
if (pressTime > 0) {
Helper.HELPER.logDirect("You're trying to press this mouse button but I won't let you");
pressTime--;
}
cir.setReturnValue(force); // :sunglasses:
} }
} }
} }
@@ -96,15 +96,6 @@ public class MixinMinecraft {
} }
@Inject(
method = "processKeyBinds",
at = @At("HEAD")
)
private void runTickKeyboard(CallbackInfo ci) {
// keyboard input is only the primary baritone
BaritoneAPI.getProvider().getPrimaryBaritone().getGameEventHandler().onProcessKeyBinds();
}
@Inject( @Inject(
method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V", method = "loadWorld(Lnet/minecraft/client/multiplayer/WorldClient;Ljava/lang/String;)V",
at = @At("HEAD") at = @At("HEAD")
+1
View File
@@ -129,6 +129,7 @@ public class Baritone implements IBaritone {
this.initialized = true; this.initialized = true;
} }
@Override
public PathingControlManager getPathingControlManager() { public PathingControlManager getPathingControlManager() {
return this.pathingControlManager; return this.pathingControlManager;
} }
@@ -55,10 +55,7 @@ public class InventoryBehavior extends Behavior {
} }
private void swapWithHotBar(int inInventory, int inHotbar) { private void swapWithHotBar(int inInventory, int inHotbar) {
if (inInventory < 9) { ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory < 9 ? inInventory + 36 : inInventory, inHotbar, ClickType.SWAP, ctx.player());
inInventory += 36;
}
ctx.playerController().windowClick(ctx.player().inventoryContainer.windowId, inInventory, inHotbar, ClickType.SWAP, ctx.player());
} }
private int firstValidThrowaway() { // TODO offhand idk private int firstValidThrowaway() { // TODO offhand idk
@@ -81,7 +78,7 @@ public class InventoryBehavior extends Behavior {
continue; continue;
} }
if (klass.isInstance(stack.getItem())) { if (klass.isInstance(stack.getItem())) {
double speed = ToolSet.calculateStrVsBlock(stack, against.getDefaultState()); // takes into account enchants double speed = ToolSet.calculateSpeedVsBlock(stack, against.getDefaultState()); // takes into account enchants
if (speed > bestSpeed) { if (speed > bestSpeed) {
bestSpeed = speed; bestSpeed = speed;
bestInd = i; bestInd = i;
@@ -21,6 +21,7 @@ import baritone.Baritone;
import baritone.api.event.events.BlockInteractEvent; import baritone.api.event.events.BlockInteractEvent;
import baritone.api.event.events.PacketEvent; import baritone.api.event.events.PacketEvent;
import baritone.api.event.events.PlayerUpdateEvent; import baritone.api.event.events.PlayerUpdateEvent;
import baritone.api.event.events.TickEvent;
import baritone.api.event.events.type.EventState; import baritone.api.event.events.type.EventState;
import baritone.cache.ContainerMemory; import baritone.cache.ContainerMemory;
import baritone.cache.Waypoint; import baritone.cache.Waypoint;
@@ -60,6 +61,14 @@ public final class MemoryBehavior extends Behavior {
super(baritone); super(baritone);
} }
@Override
public synchronized void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) {
enderChestWindowId = null;
futureInventories.clear();
}
}
@Override @Override
public synchronized void onPlayerUpdate(PlayerUpdateEvent event) { public synchronized void onPlayerUpdate(PlayerUpdateEvent event) {
if (event.getState() == EventState.PRE) { if (event.getState() == EventState.PRE) {
@@ -116,12 +125,10 @@ public final class MemoryBehavior extends Behavior {
System.out.println("Received packet " + packet.getGuiId() + " " + packet.getEntityId() + " " + packet.getSlotCount() + " " + packet.getWindowId()); System.out.println("Received packet " + packet.getGuiId() + " " + packet.getEntityId() + " " + packet.getSlotCount() + " " + packet.getWindowId());
System.out.println(packet.getWindowTitle()); System.out.println(packet.getWindowTitle());
if (packet.getWindowTitle() instanceof TextComponentTranslation) { if (packet.getWindowTitle() instanceof TextComponentTranslation && ((TextComponentTranslation) packet.getWindowTitle()).getKey().equals("container.enderchest")) {
// title is not customized (i.e. this isn't just a renamed shulker) // title is not customized (i.e. this isn't just a renamed shulker)
if (((TextComponentTranslation) packet.getWindowTitle()).getKey().equals("container.enderchest")) { enderChestWindowId = packet.getWindowId();
enderChestWindowId = packet.getWindowId(); return;
return;
}
} }
futureInventories.stream() futureInventories.stream()
.filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount()) .filter(i -> i.type.equals(packet.getGuiId()) && i.slots == packet.getSlotCount())
@@ -177,7 +184,7 @@ public final class MemoryBehavior extends Behavior {
} }
private BlockPos neighboringConnectedBlock(BlockPos in) { private BlockPos neighboringConnectedBlock(BlockPos in) {
BlockStateInterface bsi = new CalculationContext(baritone).bsi(); BlockStateInterface bsi = new CalculationContext(baritone).bsi;
Block block = bsi.get0(in).getBlock(); Block block = bsi.get0(in).getBlock();
if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) { if (block != Blocks.TRAPPED_CHEST && block != Blocks.CHEST) {
return null; // other things that have contents, but can be placed adjacent without combining return null; // other things that have contents, but can be placed adjacent without combining
@@ -433,7 +433,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Optional<IPath> path = calcResult.getPath(); Optional<IPath> path = calcResult.getPath();
if (Baritone.settings().cutoffAtLoadBoundary.get()) { if (Baritone.settings().cutoffAtLoadBoundary.get()) {
path = path.map(p -> { path = path.map(p -> {
IPath result = p.cutoffAtLoadedChunks(context.bsi()); IPath result = p.cutoffAtLoadedChunks(context.bsi);
if (result instanceof CutoffPath) { if (result instanceof CutoffPath) {
logDebug("Cutting off path at edge of loaded chunks"); logDebug("Cutting off path at edge of loaded chunks");
@@ -499,7 +499,7 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
Goal transformed = goal; Goal transformed = goal;
if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) { if (Baritone.settings().simplifyUnloadedYCoord.get() && goal instanceof IGoalRenderPos) {
BlockPos pos = ((IGoalRenderPos) goal).getGoalPos(); BlockPos pos = ((IGoalRenderPos) goal).getGoalPos();
if (context.world().getChunk(pos) instanceof EmptyChunk) { if (!context.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ())) {
transformed = new GoalXZ(pos.getX(), pos.getZ()); transformed = new GoalXZ(pos.getX(), pos.getZ());
} }
} }
+3 -3
View File
@@ -179,8 +179,8 @@ public final class CachedWorld implements ICachedWorld, Helper {
if (region == null) { if (region == null) {
continue; continue;
} }
int distX = (region.getX() * 512 + 256) - pruneCenter.getX(); int distX = (region.getX() << 9 + 256) - pruneCenter.getX();
int distZ = (region.getZ() * 512 + 256) - pruneCenter.getZ(); int distZ = (region.getZ() << 9 + 256) - pruneCenter.getZ();
double dist = Math.sqrt(distX * distX + distZ * distZ); double dist = Math.sqrt(distX * distX + distZ * distZ);
if (dist > 1024) { if (dist > 1024) {
logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram"); logDebug("Deleting cached region " + region.getX() + "," + region.getZ() + " from ram");
@@ -215,7 +215,7 @@ public final class CachedWorld implements ICachedWorld, Helper {
if (mostRecentlyModified == null) { if (mostRecentlyModified == null) {
return new BlockPos(0, 0, 0); return new BlockPos(0, 0, 0);
} }
return new BlockPos(mostRecentlyModified.x * 16 + 8, 0, mostRecentlyModified.z * 16 + 8); return new BlockPos(mostRecentlyModified.x << 4 + 8, 0, mostRecentlyModified.z << 4 + 8);
} }
private synchronized List<CachedRegion> allRegions() { private synchronized List<CachedRegion> allRegions() {
+2 -1
View File
@@ -123,7 +123,8 @@ public class ContainerMemory implements IContainerMemory {
return out.array(); return out.array();
} }
public static PacketBuffer writeItemStacks(List<ItemStack> write, PacketBuffer out) { public static PacketBuffer writeItemStacks(List<ItemStack> write, PacketBuffer out2) {
PacketBuffer out = out2; // avoid reassigning an argument LOL
out = new PacketBuffer(out.writeInt(write.size())); out = new PacketBuffer(out.writeInt(write.size()));
for (ItemStack stack : write) { for (ItemStack stack : write) {
out = out.writeItemStack(stack); out = out.writeItemStack(stack);
+16 -35
View File
@@ -28,8 +28,9 @@ import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk; import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections; import java.util.Collections;
import java.util.LinkedList;
import java.util.List; import java.util.List;
public enum WorldScanner implements IWorldScanner { public enum WorldScanner implements IWorldScanner {
@@ -41,7 +42,7 @@ public enum WorldScanner implements IWorldScanner {
if (blocks.contains(null)) { if (blocks.contains(null)) {
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString()); throw new IllegalStateException("Invalid block name should have been caught earlier: " + blocks.toString());
} }
LinkedList<BlockPos> res = new LinkedList<>(); ArrayList<BlockPos> res = new ArrayList<>();
if (blocks.isEmpty()) { if (blocks.isEmpty()) {
return res; return res;
} }
@@ -71,33 +72,7 @@ public enum WorldScanner implements IWorldScanner {
continue; continue;
} }
allUnloaded = false; allUnloaded = false;
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); scanChunkInto(chunkX << 4, chunkZ << 4, chunk, blocks, res, max, yLevelThreshold, playerY);
chunkX = chunkX << 4;
chunkZ = chunkZ << 4;
for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
if (extendedblockstorage == null) {
continue;
}
int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (blocks.contains(state.getBlock())) {
int yy = yReal | y;
res.add(new BlockPos(chunkX | x, yy, chunkZ | z));
if (Math.abs(yy - playerY) < yLevelThreshold) {
foundWithinY = true;
}
}
}
}
}
}
} }
} }
if ((allUnloaded && foundChunks) if ((allUnloaded && foundChunks)
@@ -124,7 +99,12 @@ public enum WorldScanner implements IWorldScanner {
return Collections.emptyList(); return Collections.emptyList();
} }
LinkedList<BlockPos> res = new LinkedList<>(); ArrayList<BlockPos> res = new ArrayList<>();
scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY);
return res;
}
public void scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray(); ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
for (int y0 = 0; y0 < 16; y0++) { for (int y0 = 0; y0 < 16; y0++) {
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0]; ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
@@ -133,21 +113,22 @@ public enum WorldScanner implements IWorldScanner {
} }
int yReal = y0 << 4; int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData(); BlockStateContainer bsc = extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) { for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) { for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) { for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z); IBlockState state = bsc.get(x, y, z);
if (blocks.contains(state.getBlock())) { if (search.contains(state.getBlock())) {
int yy = yReal | y; int yy = yReal | y;
res.add(new BlockPos((pos.x << 4) | x, yy, (pos.z << 4) | z)); result.add(new BlockPos(chunkX | x, yy, chunkZ | z));
if (res.size() >= max || Math.abs(yy - playerY) < yLevelThreshold) { if (result.size() >= max && Math.abs(yy - playerY) < yLevelThreshold) {
return res; return;
} }
} }
} }
} }
} }
} }
return res;
} }
} }
@@ -54,11 +54,6 @@ public final class GameEventHandler implements IEventBus, Helper {
listeners.forEach(l -> l.onPlayerUpdate(event)); listeners.forEach(l -> l.onPlayerUpdate(event));
} }
@Override
public final void onProcessKeyBinds() {
listeners.forEach(IGameEventListener::onProcessKeyBinds);
}
@Override @Override
public final void onSendChatMessage(ChatEvent event) { public final void onSendChatMessage(ChatEvent event) {
listeners.forEach(l -> l.onSendChatMessage(event)); listeners.forEach(l -> l.onSendChatMessage(event));
@@ -25,11 +25,15 @@ import baritone.api.utils.BetterBlockPos;
import baritone.pathing.calc.openset.BinaryHeapOpenSet; import baritone.pathing.calc.openset.BinaryHeapOpenSet;
import baritone.pathing.movement.CalculationContext; import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.Moves; import baritone.pathing.movement.Moves;
import baritone.utils.BlockStateInterface;
import baritone.utils.Helper; import baritone.utils.Helper;
import baritone.utils.pathing.BetterWorldBorder; import baritone.utils.pathing.BetterWorldBorder;
import baritone.utils.pathing.Favoring; import baritone.utils.pathing.Favoring;
import baritone.utils.pathing.MutableMoveResult; import baritone.utils.pathing.MutableMoveResult;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Comparator;
import java.util.Optional; import java.util.Optional;
/** /**
@@ -55,7 +59,6 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
startNode.combinedCost = startNode.estimatedCostToGoal; startNode.combinedCost = startNode.estimatedCostToGoal;
BinaryHeapOpenSet openSet = new BinaryHeapOpenSet(); BinaryHeapOpenSet openSet = new BinaryHeapOpenSet();
openSet.insert(startNode); openSet.insert(startNode);
startNode.isOpen = true;
bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i]) bestSoFar = new PathNode[COEFFICIENTS.length];//keep track of the best node by the metric of (estimatedCostToGoal + cost / COEFFICIENTS[i])
double[] bestHeuristicSoFar = new double[COEFFICIENTS.length]; double[] bestHeuristicSoFar = new double[COEFFICIENTS.length];
for (int i = 0; i < bestHeuristicSoFar.length; i++) { for (int i = 0; i < bestHeuristicSoFar.length; i++) {
@@ -64,8 +67,8 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} }
MutableMoveResult res = new MutableMoveResult(); MutableMoveResult res = new MutableMoveResult();
Favoring favored = favoring; Favoring favored = favoring;
BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world().getWorldBorder()); BetterWorldBorder worldBorder = new BetterWorldBorder(calcContext.world.getWorldBorder());
long startTime = System.nanoTime() / 1000000L; long startTime = System.currentTimeMillis();
boolean slowPath = Baritone.settings().slowPath.get(); boolean slowPath = Baritone.settings().slowPath.get();
if (slowPath) { if (slowPath) {
logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms"); logDebug("slowPath is on, path timeout will be " + Baritone.settings().slowPathTimeoutMS.<Long>get() + "ms instead of " + primaryTimeout + "ms");
@@ -77,12 +80,39 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
int numMovementsConsidered = 0; int numMovementsConsidered = 0;
int numEmptyChunk = 0; int numEmptyChunk = 0;
boolean favoring = !favored.isEmpty(); boolean favoring = !favored.isEmpty();
int timeCheckInterval = 1 << 6;
int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior int pathingMaxChunkBorderFetch = Baritone.settings().pathingMaxChunkBorderFetch.get(); // grab all settings beforehand so that changing settings during pathing doesn't cause a crash or unpredictable behavior
boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get(); boolean minimumImprovementRepropagation = Baritone.settings().minimumImprovementRepropagation.get();
long[] timeConsumed = new long[Moves.values().length];
int[] count = new int[Moves.values().length];
int[] stateLookup = new int[Moves.values().length];
long[] posCreation = new long[Moves.values().length];
long heapRemove = 0;
int heapRemoveCount = 0;
long heapAdd = 0;
int heapAddCount = 0;
long heapUpdate = 0;
int heapUpdateCount = 0;
long chunk = 0;
int chunkCount = 0;
long goalCheck = 0;
int goalCheckCount = 0;
long getNode = 0;
int getNodeCount = 0;
int startVal = BlockStateInterface.numTimesChunkSucceeded;
int startVal2 = BlockStateInterface.numBlockStateLookups;
long startVal3 = BetterBlockPos.numCreated;
while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) { while (!openSet.isEmpty() && numEmptyChunk < pathingMaxChunkBorderFetch && !cancelRequested) {
long now = System.nanoTime() / 1000000L; if ((numNodes & (timeCheckInterval - 1)) == 0) { // only call this once every 64 nodes (about half a millisecond)
if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) { long now = System.currentTimeMillis(); // since nanoTime is slow on windows (takes many microseconds)
break; if (now - failureTimeoutTime >= 0 || (!failing && now - primaryTimeoutTime >= 0)) {
break;
}
} }
if (slowPath) { if (slowPath) {
try { try {
@@ -90,15 +120,21 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} catch (InterruptedException ex) { } catch (InterruptedException ex) {
} }
} }
long before = System.nanoTime();
PathNode currentNode = openSet.removeLowest(); PathNode currentNode = openSet.removeLowest();
currentNode.isOpen = false; long t = System.nanoTime();
heapRemove += t - before;
heapRemoveCount++;
mostRecentConsidered = currentNode; mostRecentConsidered = currentNode;
numNodes++; numNodes++;
if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) { if (goal.isInGoal(currentNode.x, currentNode.y, currentNode.z)) {
logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, " + numMovementsConsidered + " movements considered"); logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, " + numMovementsConsidered + " movements considered");
return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext)); return Optional.of(new Path(startNode, currentNode, numNodes, goal, calcContext));
} }
goalCheck += System.nanoTime() - t;
goalCheckCount++;
for (Moves moves : Moves.values()) { for (Moves moves : Moves.values()) {
long s = System.nanoTime();
int newX = currentNode.x + moves.xOffset; int newX = currentNode.x + moves.xOffset;
int newZ = currentNode.z + moves.zOffset; int newZ = currentNode.z + moves.zOffset;
if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) { if ((newX >> 4 != currentNode.x >> 4 || newZ >> 4 != currentNode.z >> 4) && !calcContext.isLoaded(newX, newZ)) {
@@ -106,6 +142,9 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed if (!moves.dynamicXZ) { // only increment the counter if the movement would have gone out of bounds guaranteed
numEmptyChunk++; numEmptyChunk++;
} }
long costStart = System.nanoTime();
chunk += costStart - s;
chunkCount++;
continue; continue;
} }
if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) { if (!moves.dynamicXZ && !worldBorder.entirelyContains(newX, newZ)) {
@@ -114,8 +153,19 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
if (currentNode.y + moves.yOffset > 256 || currentNode.y + moves.yOffset < 0) { if (currentNode.y + moves.yOffset > 256 || currentNode.y + moves.yOffset < 0) {
continue; continue;
} }
long costStart = System.nanoTime();
chunk += costStart - s;
chunkCount++;
// TODO cache cost
int numLookupsBefore = BlockStateInterface.numBlockStateLookups;
long numCreatedBefore = BetterBlockPos.numCreated;
res.reset(); res.reset();
moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res); moves.apply(calcContext, currentNode.x, currentNode.y, currentNode.z, res);
long costEnd = System.nanoTime();
stateLookup[moves.ordinal()] += BlockStateInterface.numBlockStateLookups - numLookupsBefore;
posCreation[moves.ordinal()] += BetterBlockPos.numCreated - numCreatedBefore;
timeConsumed[moves.ordinal()] += costEnd - costStart;
count[moves.ordinal()]++;
numMovementsConsidered++; numMovementsConsidered++;
double actionCost = res.cost; double actionCost = res.cost;
if (actionCost >= ActionCosts.COST_INF) { if (actionCost >= ActionCosts.COST_INF) {
@@ -124,10 +174,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
if (actionCost <= 0 || Double.isNaN(actionCost)) { if (actionCost <= 0 || Double.isNaN(actionCost)) {
throw new IllegalStateException(moves + " calculated implausible cost " + actionCost); throw new IllegalStateException(moves + " calculated implausible cost " + actionCost);
} }
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218 if (moves.dynamicXZ && !worldBorder.entirelyContains(res.x, res.z)) { // see issue #218
continue; continue;
} }
// check destination after verifying it's not COST_INF -- some movements return a static IMPOSSIBLE object with COST_INF and destination being 0,0,0 to avoid allocating a new result for every failed calculation
if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) { if (!moves.dynamicXZ && (res.x != newX || res.z != newZ)) {
throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ); throw new IllegalStateException(moves + " " + res.x + " " + newX + " " + res.z + " " + newZ);
} }
@@ -139,7 +189,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
// see issue #18 // see issue #18
actionCost *= favored.calculate(hashCode); actionCost *= favored.calculate(hashCode);
} }
long st = System.nanoTime();
PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode); PathNode neighbor = getNodeAtPosition(res.x, res.y, res.z, hashCode);
getNode += System.nanoTime() - st;
getNodeCount++;
double tentativeCost = currentNode.cost + actionCost; double tentativeCost = currentNode.cost + actionCost;
if (tentativeCost < neighbor.cost) { if (tentativeCost < neighbor.cost) {
double improvementBy = neighbor.cost - tentativeCost; double improvementBy = neighbor.cost - tentativeCost;
@@ -153,11 +206,16 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
neighbor.previous = currentNode; neighbor.previous = currentNode;
neighbor.cost = tentativeCost; neighbor.cost = tentativeCost;
neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal; neighbor.combinedCost = tentativeCost + neighbor.estimatedCostToGoal;
if (neighbor.isOpen) { if (neighbor.isOpen()) {
long bef = System.nanoTime();
openSet.update(neighbor); openSet.update(neighbor);
heapUpdate += System.nanoTime() - bef;
heapUpdateCount++;
} else { } else {
neighbor.isOpen = true; long bef = System.nanoTime();
openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there openSet.insert(neighbor);//dont double count, dont insert into open set if it's already there
heapAdd += System.nanoTime() - bef;
heapAddCount++;
} }
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < bestSoFar.length; i++) {
double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i]; double heuristic = neighbor.estimatedCostToGoal + neighbor.cost / COEFFICIENTS[i];
@@ -175,13 +233,43 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} }
} }
} }
int numBlockState = BlockStateInterface.numBlockStateLookups - startVal2;
int numSucc = BlockStateInterface.numTimesChunkSucceeded - startVal;
long numSuccc = BetterBlockPos.numCreated - startVal3;
long totalAccountedTimeMS = 0;
totalAccountedTimeMS += heapRemove / 1000000;
totalAccountedTimeMS += heapAdd / 1000000;
totalAccountedTimeMS += heapUpdate / 1000000;
totalAccountedTimeMS += chunk / 1000000;
totalAccountedTimeMS += getNode / 1000000;
totalAccountedTimeMS += goalCheck / 1000000;
System.out.println("Out of " + numBlockState + " block state lookups, " + numSucc + " were in the same chunk as the previous and could be cached");
System.out.println("Instantiated " + numSuccc + " BetterBlockPos objects");
System.out.println("Remove " + (heapRemove / heapRemoveCount) + " " + heapRemove / 1000000 + "ms " + heapRemoveCount);
System.out.println("Add " + (heapAdd / heapAddCount) + " " + heapAdd / 1000000 + "ms " + heapAddCount);
System.out.println("Update " + (heapUpdate / heapUpdateCount) + " " + heapUpdate / 1000000 + "ms " + heapUpdateCount);
System.out.println("Chunk " + (chunk / chunkCount) + " " + chunk / 1000000 + "ms " + chunkCount);
System.out.println("GetNode " + (getNode / getNodeCount) + " " + getNode / 1000000 + "ms " + getNodeCount);
System.out.println("GoalCheck " + (goalCheck / goalCheckCount) + " " + goalCheck / 1000000 + "ms " + goalCheckCount);
ArrayList<Moves> moves = new ArrayList<>(Arrays.asList(Moves.values()));
moves.sort(Comparator.comparingLong(k -> timeConsumed[k.ordinal()] / count[k.ordinal()]));
for (Moves move : moves) {
int num = count[move.ordinal()];
long nanoTime = timeConsumed[move.ordinal()];
totalAccountedTimeMS += nanoTime / 1000000;
System.out.println(nanoTime / num + " " + move + " " + nanoTime / 1000000 + "ms " + num);
System.out.println(stateLookup[move.ordinal()] / num + " " + stateLookup[move.ordinal()]);
System.out.println(posCreation[move.ordinal()] / num + " " + posCreation[move.ordinal()]);
}
System.out.println("Total accounted time: " + totalAccountedTimeMS);
if (cancelRequested) { if (cancelRequested) {
return Optional.empty(); return Optional.empty();
} }
System.out.println(numMovementsConsidered + " movements considered"); System.out.println(numMovementsConsidered + " movements considered");
System.out.println("Open set size: " + openSet.size()); System.out.println("Open set size: " + openSet.size());
System.out.println("PathNode map size: " + mapSize()); System.out.println("PathNode map size: " + mapSize());
System.out.println((int) (numNodes * 1.0 / ((System.nanoTime() / 1000000L - startTime) / 1000F)) + " nodes per second"); System.out.println((int) (numNodes * 1.0 / ((System.currentTimeMillis() - startTime) / 1000F)) + " nodes per second");
double bestDist = 0; double bestDist = 0;
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < bestSoFar.length; i++) {
if (bestSoFar[i] == null) { if (bestSoFar[i] == null) {
@@ -192,7 +280,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
bestDist = dist; bestDist = dist;
} }
if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared if (dist > MIN_DIST_PATH * MIN_DIST_PATH) { // square the comparison since distFromStartSq is squared
logDebug("Took " + (System.nanoTime() / 1000000L - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered"); logDebug("Took " + (System.currentTimeMillis() - startTime) + "ms, A* cost coefficient " + COEFFICIENTS[i] + ", " + numMovementsConsidered + " movements considered");
if (COEFFICIENTS[i] >= 3) { if (COEFFICIENTS[i] >= 3) {
System.out.println("Warning: cost coefficient is greater than three! Probably means that"); System.out.println("Warning: cost coefficient is greater than three! Probably means that");
System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)"); System.out.println("the path I found is pretty terrible (like sneak-bridging for dozens of blocks)");
@@ -136,11 +136,10 @@ public abstract class AbstractNodeCostSearch implements IPathFinder {
* for the node mapped to the specified pos. If no node is found, * for the node mapped to the specified pos. If no node is found,
* a new node is created. * a new node is created.
* *
* @param x The x position of the node * @param x The x position of the node
* @param y The y position of the node * @param y The y position of the node
* @param z The z position of the node * @param z The z position of the node
* @param hashCode The hash code of the node, provided by {@link BetterBlockPos#longHash(int, int, int)} * @param hashCode The hash code of the node, provided by {@link BetterBlockPos#longHash(int, int, int)}
*
* @return The associated node * @return The associated node
* @see <a href="https://github.com/cabaletta/baritone/issues/107">Issue #107</a> * @see <a href="https://github.com/cabaletta/baritone/issues/107">Issue #107</a>
*/ */
@@ -132,7 +132,9 @@ class Path extends PathBase {
Movement move = moves.apply0(context, src); Movement move = moves.apply0(context, src);
if (move.getDest().equals(dest)) { if (move.getDest().equals(dest)) {
// have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution // have to calculate the cost at calculation time so we can accurately judge whether a cost increase happened between cached calculation and real execution
move.override(cost); // however, taking into account possible favoring that could skew the node cost, we really want the stricter limit of the two
// so we take the minimum of the path node cost difference, and the calculated cost
move.override(Math.min(move.calculateCost(context), cost));
return move; return move;
} }
} }
@@ -58,12 +58,6 @@ public final class PathNode {
*/ */
public 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.
*/
public boolean isOpen;
/** /**
* Where is this node in the array flattenization of the binary heap? Needed for decrease-key operations. * Where is this node in the array flattenization of the binary heap? Needed for decrease-key operations.
*/ */
@@ -76,12 +70,16 @@ public final class PathNode {
if (Double.isNaN(estimatedCostToGoal)) { if (Double.isNaN(estimatedCostToGoal)) {
throw new IllegalStateException(goal + " calculated implausible heuristic"); throw new IllegalStateException(goal + " calculated implausible heuristic");
} }
this.isOpen = false; this.heapPosition = -1;
this.x = x; this.x = x;
this.y = y; this.y = y;
this.z = z; this.z = z;
} }
public boolean isOpen() {
return heapPosition != -1;
}
/** /**
* TODO: Possibly reimplement hashCode and equals. They are necessary for this class to function but they could be done better * TODO: Possibly reimplement hashCode and equals. They are necessary for this class to function but they could be done better
* *
@@ -59,7 +59,7 @@ public final class BinaryHeapOpenSet implements IOpenSet {
@Override @Override
public final void insert(PathNode value) { public final void insert(PathNode value) {
if (size >= array.length - 1) { if (size >= array.length - 1) {
array = Arrays.copyOf(array, array.length * 2); array = Arrays.copyOf(array, array.length << 1);
} }
size++; size++;
value.heapPosition = size; value.heapPosition = size;
@@ -42,26 +42,28 @@ public class CalculationContext {
private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET); private static final ItemStack STACK_BUCKET_WATER = new ItemStack(Items.WATER_BUCKET);
private final IBaritone baritone; public final IBaritone baritone;
private final EntityPlayerSP player; public final World world;
private final World world; public final WorldData worldData;
private final WorldData worldData; public final BlockStateInterface bsi;
private final BlockStateInterface bsi; public final ToolSet toolSet;
private final ToolSet toolSet; public final boolean hasWaterBucket;
private final boolean hasWaterBucket; public final boolean hasThrowaway;
private final boolean hasThrowaway; public final boolean canSprint;
private final boolean canSprint; public final double placeBlockCost;
private final double placeBlockCost; public final boolean allowBreak;
private final boolean allowBreak; public final boolean allowParkour;
private final boolean allowParkour; public final boolean allowParkourPlace;
private final boolean allowParkourPlace; public final boolean allowJumpAt256;
private final boolean allowJumpAt256; public final boolean assumeWalkOnWater;
private final boolean assumeWalkOnWater; public final boolean allowDiagonalDescend;
private final int maxFallHeightNoWater; public final int maxFallHeightNoWater;
private final int maxFallHeightBucket; public final int maxFallHeightBucket;
private final double waterWalkSpeed; public final double waterWalkSpeed;
private final double breakBlockAdditionalCost; public final double breakBlockAdditionalCost;
private final BetterWorldBorder worldBorder; public final double jumpPenalty;
public final double walkOnWaterOnePenalty;
public final BetterWorldBorder worldBorder;
public CalculationContext(IBaritone baritone) { public CalculationContext(IBaritone baritone) {
this(baritone, false); this(baritone, false);
@@ -69,11 +71,10 @@ public class CalculationContext {
public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) { public CalculationContext(IBaritone baritone, boolean forUseOnAnotherThread) {
this.baritone = baritone; this.baritone = baritone;
this.player = baritone.getPlayerContext().player(); EntityPlayerSP player = baritone.getPlayerContext().player();
this.world = baritone.getPlayerContext().world(); this.world = baritone.getPlayerContext().world();
this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld(); this.worldData = (WorldData) baritone.getWorldProvider().getCurrentWorld();
this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread); // TODO TODO TODO this.bsi = new BlockStateInterface(world, worldData, forUseOnAnotherThread); // TODO TODO TODO
// new CalculationContext() needs to happen, can't add an argument (i'll beat you), can we get the world provider from currentlyTicking?
this.toolSet = new ToolSet(player); this.toolSet = new ToolSet(player);
this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(baritone.getPlayerContext(), false); this.hasThrowaway = Baritone.settings().allowPlace.get() && MovementHelper.throwaway(baritone.getPlayerContext(), false);
this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether(); this.hasWaterBucket = Baritone.settings().allowWaterBucketFall.get() && InventoryPlayer.isHotbar(player.inventory.getSlotFor(STACK_BUCKET_WATER)) && !world.provider.isNether();
@@ -84,6 +85,7 @@ public class CalculationContext {
this.allowParkourPlace = Baritone.settings().allowParkourPlace.get(); this.allowParkourPlace = Baritone.settings().allowParkourPlace.get();
this.allowJumpAt256 = Baritone.settings().allowJumpAt256.get(); this.allowJumpAt256 = Baritone.settings().allowJumpAt256.get();
this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.get(); this.assumeWalkOnWater = Baritone.settings().assumeWalkOnWater.get();
this.allowDiagonalDescend = Baritone.settings().allowDiagonalDescend.get();
this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get(); this.maxFallHeightNoWater = Baritone.settings().maxFallHeightNoWater.get();
this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get(); this.maxFallHeightBucket = Baritone.settings().maxFallHeightBucket.get();
int depth = EnchantmentHelper.getDepthStriderModifier(player); int depth = EnchantmentHelper.getDepthStriderModifier(player);
@@ -93,6 +95,8 @@ public class CalculationContext {
float mult = depth / 3.0F; float mult = depth / 3.0F;
this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult; this.waterWalkSpeed = ActionCosts.WALK_ONE_IN_WATER_COST * (1 - mult) + ActionCosts.WALK_ONE_BLOCK_COST * mult;
this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.get(); this.breakBlockAdditionalCost = Baritone.settings().blockBreakAdditionalPenalty.get();
this.jumpPenalty = Baritone.settings().jumpPenalty.get();
this.walkOnWaterOnePenalty = Baritone.settings().walkOnWaterOnePenalty.get();
// why cache these things here, why not let the movements just get directly from settings? // why cache these things here, why not let the movements just get directly from settings?
// because if some movements are calculated one way and others are calculated another way, // because if some movements are calculated one way and others are calculated another way,
// then you get a wildly inconsistent path that isn't optimal for either scenario. // then you get a wildly inconsistent path that isn't optimal for either scenario.
@@ -120,7 +124,7 @@ public class CalculationContext {
} }
public boolean canPlaceThrowawayAt(int x, int y, int z) { public boolean canPlaceThrowawayAt(int x, int y, int z) {
if (!hasThrowaway()) { // only true if allowPlace is true, see constructor if (!hasThrowaway) { // only true if allowPlace is true, see constructor
return false; return false;
} }
if (isPossiblyProtected(x, y, z)) { if (isPossiblyProtected(x, y, z)) {
@@ -130,7 +134,7 @@ public class CalculationContext {
} }
public boolean canBreakAt(int x, int y, int z) { public boolean canBreakAt(int x, int y, int z) {
if (!allowBreak()) { if (!allowBreak) {
return false; return false;
} }
return !isPossiblyProtected(x, y, z); return !isPossiblyProtected(x, y, z);
@@ -140,76 +144,4 @@ public class CalculationContext {
// TODO more protection logic here; see #220 // TODO more protection logic here; see #220
return false; return false;
} }
public World world() {
return world;
}
public EntityPlayerSP player() {
return player;
}
public BlockStateInterface bsi() {
return bsi;
}
public WorldData worldData() {
return worldData;
}
public ToolSet getToolSet() {
return toolSet;
}
public boolean hasWaterBucket() {
return hasWaterBucket;
}
public boolean hasThrowaway() {
return hasThrowaway;
}
public boolean canSprint() {
return canSprint;
}
public double placeBlockCost() {
return placeBlockCost;
}
public boolean allowBreak() {
return allowBreak;
}
public boolean allowParkour() {
return allowParkour;
}
public boolean allowParkourPlace() {
return allowParkourPlace;
}
public boolean allowJumpAt256() {
return allowJumpAt256;
}
public boolean assumeWalkOnWater() {
return assumeWalkOnWater;
}
public int maxFallHeightNoWater() {
return maxFallHeightNoWater;
}
public int maxFallHeightBucket() {
return maxFallHeightBucket;
}
public double waterWalkSpeed() {
return waterWalkSpeed;
}
public double breakBlockAdditionalCost() {
return breakBlockAdditionalCost;
}
} }
@@ -26,7 +26,6 @@ import baritone.utils.BlockStateInterface;
import net.minecraft.block.BlockLiquid; import net.minecraft.block.BlockLiquid;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
@@ -35,7 +34,6 @@ import java.util.Optional;
public abstract class Movement implements IMovement, MovementHelper { public abstract class Movement implements IMovement, MovementHelper {
protected static final EnumFacing[] HORIZONTALS = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST};
protected static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN}; protected static final EnumFacing[] HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP = {EnumFacing.NORTH, EnumFacing.SOUTH, EnumFacing.EAST, EnumFacing.WEST, EnumFacing.DOWN};
protected final IBaritone baritone; protected final IBaritone baritone;
@@ -86,7 +84,7 @@ public abstract class Movement implements IMovement, MovementHelper {
return cost; return cost;
} }
protected abstract double calculateCost(CalculationContext context); public abstract double calculateCost(CalculationContext context);
@Override @Override
public double recalculateCost() { public double recalculateCost() {
@@ -126,13 +124,10 @@ public abstract class Movement implements IMovement, MovementHelper {
rotation, rotation,
currentState.getTarget().hasToForceRotations())); currentState.getTarget().hasToForceRotations()));
// TODO: calculate movement inputs from latestState.getGoal().position
// latestState.getTarget().position.ifPresent(null); NULL CONSUMER REALLY SHOULDN'T BE THE FINAL THING YOU SHOULD REALLY REPLACE THIS WITH ALMOST ACTUALLY ANYTHING ELSE JUST PLEASE DON'T LEAVE IT AS IT IS THANK YOU KANYE
currentState.getInputStates().forEach((input, forced) -> { currentState.getInputStates().forEach((input, forced) -> {
baritone.getInputOverrideHandler().setInputForceState(input, forced); baritone.getInputOverrideHandler().setInputForceState(input, forced);
}); });
currentState.getInputStates().replaceAll((input, forced) -> false); currentState.getInputStates().clear();
// If the current status indicates a completed movement // If the current status indicates a completed movement
if (currentState.getStatus().isComplete()) { if (currentState.getStatus().isComplete()) {
@@ -231,7 +226,7 @@ public abstract class Movement implements IMovement, MovementHelper {
} }
public void checkLoadedChunk(CalculationContext context) { public void checkLoadedChunk(CalculationContext context) {
calculatedWhileLoaded = !(context.world().getChunk(getDest()) instanceof EmptyChunk); calculatedWhileLoaded = context.bsi.worldContainsLoadedChunk(dest.x, dest.z);
} }
@Override @Override
@@ -340,24 +340,24 @@ public interface MovementHelper extends ActionCosts, Helper {
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) { static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
Block block = state.getBlock(); Block block = state.getBlock();
if (!canWalkThrough(context.bsi(), x, y, z, state)) { if (!canWalkThrough(context.bsi, x, y, z, state)) {
if (!context.canBreakAt(x, y, z)) { if (!context.canBreakAt(x, y, z)) {
return COST_INF; return COST_INF;
} }
if (avoidBreaking(context.bsi(), x, y, z, state)) { if (avoidBreaking(context.bsi, x, y, z, state)) {
return COST_INF; return COST_INF;
} }
if (block instanceof BlockLiquid) { if (block instanceof BlockLiquid) {
return COST_INF; return COST_INF;
} }
double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
double strVsBlock = context.getToolSet().getStrVsBlock(state); double strVsBlock = context.toolSet.getStrVsBlock(state);
if (strVsBlock <= 0) { if (strVsBlock <= 0) {
return COST_INF; return COST_INF;
} }
double result = m / strVsBlock; double result = m / strVsBlock;
result += context.breakBlockAdditionalCost(); result += context.breakBlockAdditionalCost;
if (includeFalling) { if (includeFalling) {
IBlockState above = context.get(x, y + 1, z); IBlockState above = context.get(x, y + 1, z);
if (above.getBlock() instanceof BlockFalling) { if (above.getBlock() instanceof BlockFalling) {
@@ -20,7 +20,6 @@ package baritone.pathing.movement;
import baritone.api.pathing.movement.MovementStatus; import baritone.api.pathing.movement.MovementStatus;
import baritone.api.utils.Rotation; import baritone.api.utils.Rotation;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import net.minecraft.util.math.Vec3d;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -29,7 +28,6 @@ import java.util.Optional;
public class MovementState { public class MovementState {
private MovementStatus status; private MovementStatus status;
private MovementTarget goal = new MovementTarget();
private MovementTarget target = new MovementTarget(); private MovementTarget target = new MovementTarget();
private final Map<Input, Boolean> inputState = new HashMap<>(); private final Map<Input, Boolean> inputState = new HashMap<>();
@@ -42,15 +40,6 @@ public class MovementState {
return status; return status;
} }
public MovementTarget getGoal() {
return this.goal;
}
public MovementState setGoal(MovementTarget goal) {
this.goal = goal;
return this;
}
public MovementTarget getTarget() { public MovementTarget getTarget() {
return this.target; return this.target;
} }
@@ -65,23 +54,12 @@ public class MovementState {
return this; return this;
} }
public boolean getInput(Input input) {
return this.inputState.getOrDefault(input, false);
}
public Map<Input, Boolean> getInputStates() { public Map<Input, Boolean> getInputStates() {
return this.inputState; return this.inputState;
} }
public static class MovementTarget { public static class MovementTarget {
/**
* Necessary movement to achieve
* <p>
* TODO: Decide desiredMovement type
*/
public Vec3d position;
/** /**
* Yaw and pitch angles that must be matched * Yaw and pitch angles that must be matched
*/ */
@@ -95,27 +73,14 @@ public class MovementState {
private boolean forceRotations; private boolean forceRotations;
public MovementTarget() { public MovementTarget() {
this(null, null, false); this(null, false);
}
public MovementTarget(Vec3d position) {
this(position, null, false);
} }
public MovementTarget(Rotation rotation, boolean forceRotations) { public MovementTarget(Rotation rotation, boolean forceRotations) {
this(null, rotation, forceRotations);
}
public MovementTarget(Vec3d position, Rotation rotation, boolean forceRotations) {
this.position = position;
this.rotation = rotation; this.rotation = rotation;
this.forceRotations = forceRotations; this.forceRotations = forceRotations;
} }
public final Optional<Vec3d> getPosition() {
return Optional.ofNullable(this.position);
}
public final Optional<Rotation> getRotation() { public final Optional<Rotation> getRotation() {
return Optional.ofNullable(this.rotation); return Optional.ofNullable(this.rotation);
} }
@@ -52,18 +52,18 @@ public class MovementAscend extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z, dest.x, dest.z); return cost(context, src.x, src.y, src.z, dest.x, dest.z);
} }
public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) { public static double cost(CalculationContext context, int x, int y, int z, int destX, int destZ) {
IBlockState toPlace = context.get(destX, y, destZ); IBlockState toPlace = context.get(destX, y, destZ);
boolean hasToPlace = false; boolean hasToPlace = false;
if (!MovementHelper.canWalkOn(context.bsi(), destX, y, destZ, toPlace)) { if (!MovementHelper.canWalkOn(context.bsi, destX, y, destZ, toPlace)) {
if (!context.canPlaceThrowawayAt(destX, y, destZ)) { if (!context.canPlaceThrowawayAt(destX, y, destZ)) {
return COST_INF; return COST_INF;
} }
if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi())) { if (!MovementHelper.isReplacable(destX, y, destZ, toPlace, context.bsi)) {
return COST_INF; return COST_INF;
} }
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
@@ -73,7 +73,7 @@ public class MovementAscend extends Movement {
if (againstX == x && againstZ == z) { // we might be able to backplace now, but it doesn't matter because it will have been broken by the time we'd need to use it if (againstX == x && againstZ == z) { // we might be able to backplace now, but it doesn't matter because it will have been broken by the time we'd need to use it
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) { if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
hasToPlace = true; hasToPlace = true;
break; break;
} }
@@ -83,7 +83,7 @@ public class MovementAscend extends Movement {
} }
} }
IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway IBlockState srcUp2 = context.get(x, y + 2, z); // used lower down anyway
if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi(), x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us if (context.get(x, y + 3, z).getBlock() instanceof BlockFalling && (MovementHelper.canWalkThrough(context.bsi, x, y + 1, z) || !(srcUp2.getBlock() instanceof BlockFalling))) {//it would fall on us and possibly suffocate us
// HOWEVER, we assume that we're standing in the start position // HOWEVER, we assume that we're standing in the start position
// that means that src and src.up(1) are both air // that means that src and src.up(1) are both air
// maybe they aren't now, but they will be by the time this starts // maybe they aren't now, but they will be by the time this starts
@@ -115,23 +115,23 @@ public class MovementAscend extends Movement {
if (jumpingToBottomSlab) { if (jumpingToBottomSlab) {
if (jumpingFromBottomSlab) { if (jumpingFromBottomSlab) {
walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); // we hit space immediately on entering this action walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST); // we hit space immediately on entering this action
walk += context.jumpPenalty;
} else { } else {
walk = WALK_ONE_BLOCK_COST; // we don't hit space we just walk into the slab walk = WALK_ONE_BLOCK_COST; // we don't hit space we just walk into the slab
} }
} else { } else {
// jumpingFromBottomSlab must be false
if (toPlace.getBlock() == Blocks.SOUL_SAND) { if (toPlace.getBlock() == Blocks.SOUL_SAND) {
walk = WALK_ONE_OVER_SOUL_SAND_COST; walk = WALK_ONE_OVER_SOUL_SAND_COST;
} else { } else {
walk = WALK_ONE_BLOCK_COST; walk = Math.max(JUMP_ONE_BLOCK_COST, WALK_ONE_BLOCK_COST);
} }
walk += context.jumpPenalty;
} }
// cracks knuckles double totalCost = walk;
double totalCost = 0;
totalCost += walk;
if (hasToPlace) { if (hasToPlace) {
totalCost += context.placeBlockCost(); totalCost += context.placeBlockCost;
} }
// start with srcUp2 since we already have its state // start with srcUp2 since we already have its state
// includeFalling isn't needed because of the falling check above -- if srcUp3 is falling we will have already exited with COST_INF if we'd actually have to break it // includeFalling isn't needed because of the falling check above -- if srcUp3 is falling we will have already exited with COST_INF if we'd actually have to break it
@@ -52,7 +52,7 @@ public class MovementDescend extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult(); MutableMoveResult result = new MutableMoveResult();
cost(context, src.x, src.y, src.z, dest.x, dest.z, result); cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) { if (result.y != dest.y) {
@@ -93,7 +93,7 @@ public class MovementDescend extends Movement {
//C, D, etc determine the length of the fall //C, D, etc determine the length of the fall
IBlockState below = context.get(destX, y - 2, destZ); IBlockState below = context.get(destX, y - 2, destZ);
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 2, destZ, below)) { if (!MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ, below)) {
dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res); dynamicFallCost(context, x, y, z, destX, destZ, totalCost, below, res);
return; return;
} }
@@ -122,7 +122,7 @@ public class MovementDescend extends Movement {
// and potentially replace the water we're going to fall into // and potentially replace the water we're going to fall into
return false; return false;
} }
if (!MovementHelper.canWalkThrough(context.bsi(), destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) { if (!MovementHelper.canWalkThrough(context.bsi, destX, y - 2, destZ, below) && below.getBlock() != Blocks.WATER) {
return false; return false;
} }
double costSoFar = 0; double costSoFar = 0;
@@ -140,13 +140,13 @@ public class MovementDescend extends Movement {
if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) { if (ontoBlock.getBlock() == Blocks.WATER && context.getBlock(destX, newY + 1, destZ) != Blocks.WATERLILY) {
// lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad // lilypads are canWalkThrough, but we can't end a fall that should be broken by water if it's covered by a lilypad
// however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works) // however, don't return impossible in the lilypad scenario, because we could still jump right on it (water that's below a lilypad is canWalkOn so it works)
if (context.assumeWalkOnWater()) { if (context.assumeWalkOnWater) {
return false; // TODO fix return false; // TODO fix
} }
if (MovementHelper.isFlowing(ontoBlock)) { if (MovementHelper.isFlowing(ontoBlock)) {
return false; // TODO flowing check required here? return false; // TODO flowing check required here?
} }
if (!MovementHelper.canWalkOn(context.bsi(), destX, newY - 1, destZ)) { if (!MovementHelper.canWalkOn(context.bsi, destX, newY - 1, destZ)) {
// we could punch right through the water into something else // we could punch right through the water into something else
return false; return false;
} }
@@ -168,23 +168,23 @@ public class MovementDescend extends Movement {
effectiveStartHeight = newY; effectiveStartHeight = newY;
continue; continue;
} }
if (MovementHelper.canWalkThrough(context.bsi(), destX, newY, destZ, ontoBlock)) { if (MovementHelper.canWalkThrough(context.bsi, destX, newY, destZ, ontoBlock)) {
continue; continue;
} }
if (!MovementHelper.canWalkOn(context.bsi(), destX, newY, destZ, ontoBlock)) { if (!MovementHelper.canWalkOn(context.bsi, destX, newY, destZ, ontoBlock)) {
return false; return false;
} }
if (MovementHelper.isBottomSlab(ontoBlock)) { if (MovementHelper.isBottomSlab(ontoBlock)) {
return false; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect return false; // falling onto a half slab is really glitchy, and can cause more fall damage than we'd expect
} }
if (context.hasWaterBucket() && unprotectedFallHeight <= context.maxFallHeightBucket() + 1) { if (context.hasWaterBucket && unprotectedFallHeight <= context.maxFallHeightBucket + 1) {
res.x = destX; res.x = destX;
res.y = newY + 1;// this is the block we're falling onto, so dest is +1 res.y = newY + 1;// this is the block we're falling onto, so dest is +1
res.z = destZ; res.z = destZ;
res.cost = tentativeCost + context.placeBlockCost(); res.cost = tentativeCost + context.placeBlockCost;
return true; return true;
} }
if (unprotectedFallHeight <= context.maxFallHeightNoWater() + 1) { if (unprotectedFallHeight <= context.maxFallHeightNoWater + 1) {
// fallHeight = 4 means onto.up() is 3 blocks down, which is the max // fallHeight = 4 means onto.up() is 3 blocks down, which is the max
res.x = destX; res.x = destX;
res.y = newY + 1; res.y = newY + 1;
@@ -54,7 +54,7 @@ public class MovementDiagonal extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult(); MutableMoveResult result = new MutableMoveResult();
cost(context, src.x, src.y, src.z, dest.x, dest.z, result); cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) { if (result.y != dest.y) {
@@ -65,14 +65,14 @@ public class MovementDiagonal extends Movement {
public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) { public static void cost(CalculationContext context, int x, int y, int z, int destX, int destZ, MutableMoveResult res) {
IBlockState destInto = context.get(destX, y, destZ); IBlockState destInto = context.get(destX, y, destZ);
if (!MovementHelper.canWalkThrough(context.bsi(), destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi(), destX, y + 1, destZ)) { if (!MovementHelper.canWalkThrough(context.bsi, destX, y, destZ, destInto) || !MovementHelper.canWalkThrough(context.bsi, destX, y + 1, destZ)) {
return; return;
} }
IBlockState destWalkOn = context.get(destX, y - 1, destZ); IBlockState destWalkOn = context.get(destX, y - 1, destZ);
boolean descend = false; boolean descend = false;
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 1, destZ, destWalkOn)) { if (!MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destWalkOn)) {
descend = true; descend = true;
if (!MovementHelper.canWalkOn(context.bsi(), destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi(), destX, y - 1, destZ, destWalkOn)) { if (!context.allowDiagonalDescend || !MovementHelper.canWalkOn(context.bsi, destX, y - 2, destZ) || !MovementHelper.canWalkThrough(context.bsi, destX, y - 1, destZ, destWalkOn)) {
return; return;
} }
} }
@@ -80,6 +80,8 @@ public class MovementDiagonal extends Movement {
// For either possible soul sand, that affects half of our walking // For either possible soul sand, that affects half of our walking
if (destWalkOn.getBlock() == Blocks.SOUL_SAND) { if (destWalkOn.getBlock() == Blocks.SOUL_SAND) {
multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; multiplier += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
} else if (destWalkOn.getBlock() == Blocks.WATER) {
multiplier += context.walkOnWaterOnePenalty * SQRT_2;
} }
Block fromDown = context.get(x, y - 1, z).getBlock(); Block fromDown = context.get(x, y - 1, z).getBlock();
if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) { if (fromDown == Blocks.LADDER || fromDown == Blocks.VINE) {
@@ -131,7 +133,7 @@ public class MovementDiagonal extends Movement {
// Ignore previous multiplier // Ignore previous multiplier
// Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water // Whatever we were walking on (possibly soul sand) doesn't matter as we're actually floating on water
// Not even touching the blocks below // Not even touching the blocks below
multiplier = context.waterWalkSpeed(); multiplier = context.waterWalkSpeed;
water = true; water = true;
} }
if (optionA != 0 || optionB != 0) { if (optionA != 0 || optionB != 0) {
@@ -142,7 +144,7 @@ public class MovementDiagonal extends Movement {
} }
} else { } else {
// only can sprint if not edging around // only can sprint if not edging around
if (context.canSprint() && !water) { if (context.canSprint && !water) {
// If we aren't edging around anything, and we aren't in water // If we aren't edging around anything, and we aren't in water
// We can sprint =D // We can sprint =D
// Don't check for soul sand, since we can sprint on that too // Don't check for soul sand, since we can sprint on that too
@@ -43,12 +43,12 @@ public class MovementDownward extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z); return cost(context, src.x, src.y, src.z);
} }
public static double cost(CalculationContext context, int x, int y, int z) { public static double cost(CalculationContext context, int x, int y, int z) {
if (!MovementHelper.canWalkOn(context.bsi(), x, y - 2, z)) { if (!MovementHelper.canWalkOn(context.bsi, x, y - 2, z)) {
return COST_INF; return COST_INF;
} }
IBlockState down = context.get(x, y - 1, z); IBlockState down = context.get(x, y - 1, z);
@@ -54,7 +54,7 @@ public class MovementFall extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
MutableMoveResult result = new MutableMoveResult(); MutableMoveResult result = new MutableMoveResult();
MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z, result); MovementDescend.cost(context, src.x, src.y, src.z, dest.x, dest.z, result);
if (result.y != dest.y) { if (result.y != dest.y) {
@@ -60,10 +60,10 @@ public class MovementParkour extends Movement {
} }
public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) { public static void cost(CalculationContext context, int x, int y, int z, EnumFacing dir, MutableMoveResult res) {
if (!context.allowParkour()) { if (!context.allowParkour) {
return; return;
} }
if (y == 256 && !context.allowJumpAt256()) { if (y == 256 && !context.allowJumpAt256) {
return; return;
} }
@@ -74,7 +74,7 @@ public class MovementParkour extends Movement {
return; return;
} }
IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff); IBlockState adj = context.get(x + xDiff, y - 1, z + zDiff);
if (MovementHelper.canWalkOn(context.bsi(), x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now) if (MovementHelper.canWalkOn(context.bsi, x + xDiff, y - 1, z + zDiff, adj)) { // don't parkour if we could just traverse (for now)
// second most common case -- we could just traverse not parkour // second most common case -- we could just traverse not parkour
return; return;
} }
@@ -98,7 +98,7 @@ public class MovementParkour extends Movement {
if (standingOn.getBlock() == Blocks.SOUL_SAND) { if (standingOn.getBlock() == Blocks.SOUL_SAND) {
maxJump = 2; // 1 block gap maxJump = 2; // 1 block gap
} else { } else {
if (context.canSprint()) { if (context.canSprint) {
maxJump = 4; maxJump = 4;
} else { } else {
maxJump = 3; maxJump = 3;
@@ -111,18 +111,18 @@ public class MovementParkour extends Movement {
return; return;
} }
} }
if (MovementHelper.canWalkOn(context.bsi(), x + xDiff * i, y - 1, z + zDiff * i)) { if (MovementHelper.canWalkOn(context.bsi, x + xDiff * i, y - 1, z + zDiff * i)) {
res.x = x + xDiff * i; res.x = x + xDiff * i;
res.y = y; res.y = y;
res.z = z + zDiff * i; res.z = z + zDiff * i;
res.cost = costFromJumpDistance(i); res.cost = costFromJumpDistance(i) + context.jumpPenalty;
return; return;
} }
} }
if (maxJump != 4) { if (maxJump != 4) {
return; return;
} }
if (!context.allowParkourPlace()) { if (!context.allowParkourPlace) {
return; return;
} }
int destX = x + 4 * xDiff; int destX = x + 4 * xDiff;
@@ -131,7 +131,7 @@ public class MovementParkour extends Movement {
return; return;
} }
IBlockState toReplace = context.get(destX, y - 1, destZ); IBlockState toReplace = context.get(destX, y - 1, destZ);
if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi())) { if (!MovementHelper.isReplacable(destX, y - 1, destZ, toReplace, context.bsi)) {
return; return;
} }
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
@@ -141,11 +141,11 @@ public class MovementParkour extends Movement {
if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast if (againstX == x + xDiff * 3 && againstZ == z + zDiff * 3) { // we can't turn around that fast
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) { if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) {
res.x = destX; res.x = destX;
res.y = y; res.y = y;
res.z = destZ; res.z = destZ;
res.cost = costFromJumpDistance(4) + context.placeBlockCost(); res.cost = costFromJumpDistance(4) + context.placeBlockCost + context.jumpPenalty;
return; return;
} }
} }
@@ -166,7 +166,7 @@ public class MovementParkour extends Movement {
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
MutableMoveResult res = new MutableMoveResult(); MutableMoveResult res = new MutableMoveResult();
cost(context, src.x, src.y, src.z, direction, res); cost(context, src.x, src.y, src.z, direction, res);
if (res.x != dest.x || res.z != dest.z) { if (res.x != dest.x || res.z != dest.z) {
@@ -42,7 +42,7 @@ public class MovementPillar extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z); return cost(context, src.x, src.y, src.z);
} }
@@ -58,7 +58,7 @@ public class MovementPillar extends Movement {
return COST_INF; // can't pillar up from a bottom slab onto a non ladder return COST_INF; // can't pillar up from a bottom slab onto a non ladder
} }
} }
if (from instanceof BlockVine && !hasAgainst(context, x, y, z)) { // TODO this vine can't be climbed, but we could place a pillar still since vines are replacable, no? perhaps the pillar jump would be impossible because of the slowdown actually. if (from == Blocks.VINE && !hasAgainst(context, x, y, z)) { // TODO this vine can't be climbed, but we could place a pillar still since vines are replacable, no? perhaps the pillar jump would be impossible because of the slowdown actually.
return COST_INF; return COST_INF;
} }
IBlockState toBreak = context.get(x, y + 2, z); IBlockState toBreak = context.get(x, y + 2, z);
@@ -76,7 +76,7 @@ public class MovementPillar extends Movement {
if (!ladder && !context.canPlaceThrowawayAt(x, y, z)) { // we need to place a block where we started to jump on it if (!ladder && !context.canPlaceThrowawayAt(x, y, z)) { // we need to place a block where we started to jump on it
return COST_INF; return COST_INF;
} }
if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && context.assumeWalkOnWater())) { if (from instanceof BlockLiquid || (fromDown.getBlock() instanceof BlockLiquid && context.assumeWalkOnWater)) {
// otherwise, if we're standing in water, we cannot pillar // otherwise, if we're standing in water, we cannot pillar
// if we're standing on water and assumeWalkOnWater is true, we cannot pillar // if we're standing on water and assumeWalkOnWater is true, we cannot pillar
// if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again // if we're standing on water and assumeWalkOnWater is false, we must have ascended to here, or sneak backplaced, so it is possible to pillar again
@@ -112,7 +112,7 @@ public class MovementPillar extends Movement {
if (ladder) { if (ladder) {
return LADDER_UP_ONE_COST + hardness * 5; return LADDER_UP_ONE_COST + hardness * 5;
} else { } else {
return JUMP_ONE_BLOCK_COST + context.placeBlockCost() + hardness; return JUMP_ONE_BLOCK_COST + context.placeBlockCost + context.jumpPenalty + hardness;
} }
} }
@@ -159,8 +159,8 @@ public class MovementPillar extends Movement {
} }
return state; return state;
} }
boolean ladder = fromDown.getBlock() instanceof BlockLadder || fromDown.getBlock() instanceof BlockVine; boolean ladder = fromDown.getBlock() == Blocks.LADDER || fromDown.getBlock() == Blocks.VINE;
boolean vine = fromDown.getBlock() instanceof BlockVine; boolean vine = fromDown.getBlock() == Blocks.VINE;
Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F), Rotation rotation = RotationUtils.calcRotationFromVec3d(ctx.player().getPositionEyes(1.0F),
VecUtils.getBlockPosCenter(positionToPlace), VecUtils.getBlockPosCenter(positionToPlace),
new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch)); new Rotation(ctx.player().rotationYaw, ctx.player().rotationPitch));
@@ -30,7 +30,10 @@ import baritone.pathing.movement.Movement;
import baritone.pathing.movement.MovementHelper; import baritone.pathing.movement.MovementHelper;
import baritone.pathing.movement.MovementState; import baritone.pathing.movement.MovementState;
import baritone.utils.BlockStateInterface; import baritone.utils.BlockStateInterface;
import net.minecraft.block.*; import net.minecraft.block.Block;
import net.minecraft.block.BlockDoor;
import net.minecraft.block.BlockFenceGate;
import net.minecraft.block.BlockSlab;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks; import net.minecraft.init.Blocks;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
@@ -57,7 +60,7 @@ public class MovementTraverse extends Movement {
} }
@Override @Override
protected double calculateCost(CalculationContext context) { public double calculateCost(CalculationContext context) {
return cost(context, src.x, src.y, src.z, dest.x, dest.z); return cost(context, src.x, src.y, src.z, dest.x, dest.z);
} }
@@ -66,15 +69,17 @@ public class MovementTraverse extends Movement {
IBlockState pb1 = context.get(destX, y, destZ); IBlockState pb1 = context.get(destX, y, destZ);
IBlockState destOn = context.get(destX, y - 1, destZ); IBlockState destOn = context.get(destX, y - 1, destZ);
Block srcDown = context.getBlock(x, y - 1, z); Block srcDown = context.getBlock(x, y - 1, z);
if (MovementHelper.canWalkOn(context.bsi(), destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge if (MovementHelper.canWalkOn(context.bsi, destX, y - 1, destZ, destOn)) {//this is a walk, not a bridge
double WC = WALK_ONE_BLOCK_COST; double WC = WALK_ONE_BLOCK_COST;
boolean water = false; boolean water = false;
if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) { if (MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock())) {
WC = context.waterWalkSpeed(); WC = context.waterWalkSpeed;
water = true; water = true;
} else { } else {
if (destOn.getBlock() == Blocks.SOUL_SAND) { if (destOn.getBlock() == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
} else if (destOn.getBlock() == Blocks.WATER) {
WC += context.walkOnWaterOnePenalty;
} }
if (srcDown == Blocks.SOUL_SAND) { if (srcDown == Blocks.SOUL_SAND) {
WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2; WC += (WALK_ONE_OVER_SOUL_SAND_COST - WALK_ONE_BLOCK_COST) / 2;
@@ -86,7 +91,7 @@ public class MovementTraverse extends Movement {
} }
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break
if (hardness1 == 0 && hardness2 == 0) { if (hardness1 == 0 && hardness2 == 0) {
if (!water && context.canSprint()) { if (!water && context.canSprint) {
// If there's nothing in the way, and this isn't water, and we aren't sneak placing // If there's nothing in the way, and this isn't water, and we aren't sneak placing
// We can sprint =D // We can sprint =D
// Don't check for soul sand, since we can sprint on that too // Don't check for soul sand, since we can sprint on that too
@@ -103,7 +108,7 @@ public class MovementTraverse extends Movement {
if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) { if (srcDown == Blocks.LADDER || srcDown == Blocks.VINE) {
return COST_INF; return COST_INF;
} }
if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi())) { if (MovementHelper.isReplacable(destX, y - 1, destZ, destOn, context.bsi)) {
boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock()); boolean throughWater = MovementHelper.isWater(pb0.getBlock()) || MovementHelper.isWater(pb1.getBlock());
if (MovementHelper.isWater(destOn.getBlock()) && throughWater) { if (MovementHelper.isWater(destOn.getBlock()) && throughWater) {
// this happens when assume walk on water is true and this is a traverse in water, which isn't allowed // this happens when assume walk on water is true and this is a traverse in water, which isn't allowed
@@ -117,7 +122,7 @@ public class MovementTraverse extends Movement {
return COST_INF; return COST_INF;
} }
double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break double hardness2 = MovementHelper.getMiningDurationTicks(context, destX, y + 1, destZ, pb0, true); // only include falling on the upper block to break
double WC = throughWater ? context.waterWalkSpeed() : WALK_ONE_BLOCK_COST; double WC = throughWater ? context.waterWalkSpeed : WALK_ONE_BLOCK_COST;
for (int i = 0; i < 5; i++) { for (int i = 0; i < 5; i++) {
int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset(); int againstX = destX + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getXOffset();
int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset(); int againstY = y - 1 + HORIZONTALS_BUT_ALSO_DOWN____SO_EVERY_DIRECTION_EXCEPT_UP[i].getYOffset();
@@ -125,8 +130,8 @@ public class MovementTraverse extends Movement {
if (againstX == x && againstZ == z) { // this would be a backplace if (againstX == x && againstZ == z) { // this would be a backplace
continue; continue;
} }
if (MovementHelper.canPlaceAgainst(context.bsi(), againstX, againstY, againstZ)) { // found a side place option if (MovementHelper.canPlaceAgainst(context.bsi, againstX, againstY, againstZ)) { // found a side place option
return WC + context.placeBlockCost() + hardness1 + hardness2; return WC + context.placeBlockCost + hardness1 + hardness2;
} }
} }
// now that we've checked all possible directions to side place, we actually need to backplace // now that we've checked all possible directions to side place, we actually need to backplace
@@ -136,8 +141,8 @@ public class MovementTraverse extends Movement {
if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) { if (srcDown == Blocks.FLOWING_WATER || srcDown == Blocks.WATER) {
return COST_INF; // this is obviously impossible return COST_INF; // this is obviously impossible
} }
WC = WC * SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST;//since we are sneak backplacing, we are sneaking lol WC = WC * (SNEAK_ONE_BLOCK_COST / WALK_ONE_BLOCK_COST);//since we are sneak backplacing, we are sneaking lol
return WC + context.placeBlockCost() + hardness1 + hardness2; return WC + context.placeBlockCost + hardness1 + hardness2;
} }
return COST_INF; return COST_INF;
} }
@@ -181,7 +186,7 @@ public class MovementTraverse extends Movement {
state.setInput(Input.SNEAK, false); state.setInput(Input.SNEAK, false);
Block fd = BlockStateInterface.get(ctx, src.down()).getBlock(); Block fd = BlockStateInterface.get(ctx, src.down()).getBlock();
boolean ladder = fd instanceof BlockLadder || fd instanceof BlockVine; boolean ladder = fd == Blocks.LADDER || fd == Blocks.VINE;
IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]); IBlockState pb0 = BlockStateInterface.get(ctx, positionsToBreak[0]);
IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]); IBlockState pb1 = BlockStateInterface.get(ctx, positionsToBreak[1]);
@@ -234,7 +239,7 @@ public class MovementTraverse extends Movement {
state.setInput(Input.SPRINT, true); state.setInput(Input.SPRINT, true);
} }
Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock(); Block destDown = BlockStateInterface.get(ctx, dest.down()).getBlock();
if (whereAmI.getY() != dest.getY() && ladder && (destDown instanceof BlockVine || destDown instanceof BlockLadder)) { if (whereAmI.getY() != dest.getY() && ladder && (destDown == Blocks.VINE || destDown == Blocks.LADDER)) {
new MovementPillar(baritone, dest.down(), dest).updateState(state); // i'm sorry new MovementPillar(baritone, dest.down(), dest).updateState(state); // i'm sorry
return state; return state;
} }
@@ -110,7 +110,6 @@ public class PathExecutor implements IPathExecutor, Helper {
return false; return false;
} }
//System.out.println("Should be at " + whereShouldIBe + " actually am at " + whereAmI);
if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip if (!Blocks.AIR.equals(BlockStateInterface.getBlock(ctx, whereAmI.down()))) {//do not skip if standing on air, because our position isn't stable to skip
for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks for (int i = 0; i < pathPosition - 1 && i < path.length(); i++) {//this happens for example when you lag out and get teleported back a couple blocks
if (whereAmI.equals(path.positions().get(i))) { if (whereAmI.equals(path.positions().get(i))) {
@@ -374,14 +373,15 @@ public class PathExecutor implements IPathExecutor, Helper {
private void sprintIfRequested() { private void sprintIfRequested() {
// first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint // first and foremost, if allowSprint is off, or if we don't have enough hunger, don't try and sprint
if (!new CalculationContext(behavior.baritone).canSprint()) { if (!new CalculationContext(behavior.baritone).canSprint) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false); behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
ctx.player().setSprinting(false); ctx.player().setSprinting(false);
return; return;
} }
// if the movement requested sprinting, then we're done // if the movement requested sprinting, then we're done
if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(mc.gameSettings.keyBindSprint)) { if (behavior.baritone.getInputOverrideHandler().isInputForcedDown(Input.SPRINT)) {
behavior.baritone.getInputOverrideHandler().setInputForceState(Input.SPRINT, false);
if (!ctx.player().isSprinting()) { if (!ctx.player().isSprinting()) {
ctx.player().setSprinting(true); ctx.player().setSprinting(true);
} }
@@ -57,7 +57,6 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
} }
private Goal towards(Entity following) { private Goal towards(Entity following) {
// lol this is trashy but it works
BlockPos pos; BlockPos pos;
if (Baritone.settings().followOffsetDistance.get() == 0) { if (Baritone.settings().followOffsetDistance.get() == 0) {
pos = new BlockPos(following); pos = new BlockPos(following);
@@ -79,7 +78,7 @@ public final class FollowProcess extends BaritoneProcessHelper implements IFollo
if (entity.equals(ctx.player())) { if (entity.equals(ctx.player())) {
return false; return false;
} }
return ctx.world().loadedEntityList.contains(entity) || ctx.world().playerEntities.contains(entity); return ctx.world().loadedEntityList.contains(entity);
} }
private void scanWorld() { private void scanWorld() {
@@ -154,4 +154,4 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
} }
return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST; return block == Blocks.CRAFTING_TABLE || block == Blocks.FURNACE || block == Blocks.ENDER_CHEST || block == Blocks.CHEST || block == Blocks.TRAPPED_CHEST;
} }
} }
@@ -39,7 +39,6 @@ import net.minecraft.item.Item;
import net.minecraft.item.ItemStack; import net.minecraft.item.ItemStack;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.world.World; import net.minecraft.world.World;
import net.minecraft.world.chunk.EmptyChunk;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Collectors;
@@ -210,7 +209,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
//long b = System.currentTimeMillis(); //long b = System.currentTimeMillis();
for (Block m : mining) { for (Block m : mining) {
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) { if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(m)) {
locs.addAll(ctx.worldData().getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2)); locs.addAll(ctx.worldData.getCachedWorld().getLocationsOf(ChunkPacker.blockToString(m), 1, ctx.getBaritone().getPlayerContext().playerFeet().getX(), ctx.getBaritone().getPlayerContext().playerFeet().getZ(), 2));
} else { } else {
uninteresting.add(m); uninteresting.add(m);
} }
@@ -249,16 +248,17 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
} }
public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) { public static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, List<Block> mining, int max) {
List<BlockPos> dropped = droppedItemsScan(mining, ctx.world()); List<BlockPos> dropped = droppedItemsScan(mining, ctx.world);
List<BlockPos> locs = locs2 List<BlockPos> locs = locs2
.stream() .stream()
.distinct() .distinct()
// remove any that are within loaded chunks that aren't actually what we want // remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> ctx.world().getChunk(pos) instanceof EmptyChunk || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
// remove any that are implausible to mine (encased in bedrock, or touching lava) // remove any that are implausible to mine (encased in bedrock, or touching lava)
.filter(pos -> MineProcess.plausibleToBreak(ctx.bsi(), pos)) .filter(pos -> MineProcess.plausibleToBreak(ctx.bsi, pos))
.sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq)) .sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
.collect(Collectors.toList()); .collect(Collectors.toList());
@@ -32,6 +32,15 @@ import net.minecraft.world.GameType;
import net.minecraft.world.WorldSettings; import net.minecraft.world.WorldSettings;
import net.minecraft.world.WorldType; import net.minecraft.world.WorldType;
/**
* Responsible for automatically testing Baritone's pathing algorithm by automatically creating a world with a specific
* seed, setting a specified goal, and only allowing a certain amount of ticks to pass before the pathing test is
* considered a failure. In order to test locally, docker may be used, or through an IDE: Create a run config which runs
* in a separate directory from the primary one (./run), and set the enrivonmental variable {@code BARITONE_AUTO_TEST}
* to {@code true}.
*
* @author leijurv, Brady
*/
public class BaritoneAutoTest implements AbstractGameEventListener, Helper { public class BaritoneAutoTest implements AbstractGameEventListener, Helper {
public static final BaritoneAutoTest INSTANCE = new BaritoneAutoTest(); public static final BaritoneAutoTest INSTANCE = new BaritoneAutoTest();
@@ -23,16 +23,10 @@ import baritone.api.utils.IPlayerContext;
public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper { public abstract class BaritoneProcessHelper implements IBaritoneProcess, Helper {
public static final double DEFAULT_PRIORITY = 0;
protected final Baritone baritone; protected final Baritone baritone;
protected final IPlayerContext ctx; protected final IPlayerContext ctx;
private final double priority; private final double priority;
public BaritoneProcessHelper(Baritone baritone) {
this(baritone, DEFAULT_PRIORITY);
}
public BaritoneProcessHelper(Baritone baritone, double priority) { public BaritoneProcessHelper(Baritone baritone, double priority) {
this.baritone = baritone; this.baritone = baritone;
this.ctx = baritone.getPlayerContext(); this.ctx = baritone.getPlayerContext();
@@ -17,8 +17,6 @@
package baritone.utils; package baritone.utils;
import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import net.minecraft.util.EnumFacing; import net.minecraft.util.EnumFacing;
import net.minecraft.util.EnumHand; import net.minecraft.util.EnumHand;
@@ -31,11 +29,6 @@ import net.minecraft.util.math.RayTraceResult;
*/ */
public final class BlockBreakHelper implements Helper { public final class BlockBreakHelper implements Helper {
/**
* The last block that we tried to break, if this value changes
* between attempts, then we re-initialize the breaking process.
*/
private BlockPos lastBlock;
private boolean didBreakLastTick; private boolean didBreakLastTick;
private IPlayerContext playerContext; private IPlayerContext playerContext;
@@ -45,42 +38,20 @@ public final class BlockBreakHelper implements Helper {
} }
public void tryBreakBlock(BlockPos pos, EnumFacing side) { public void tryBreakBlock(BlockPos pos, EnumFacing side) {
if (!pos.equals(lastBlock)) {
playerContext.playerController().clickBlock(pos, side);
}
if (playerContext.playerController().onPlayerDamageBlock(pos, side)) { if (playerContext.playerController().onPlayerDamageBlock(pos, side)) {
playerContext.player().swingArm(EnumHand.MAIN_HAND); playerContext.player().swingArm(EnumHand.MAIN_HAND);
} }
lastBlock = pos;
} }
public void stopBreakingBlock() { public void stopBreakingBlock() {
if (playerContext.playerController() != null) { // The player controller will never be null, but the player can be
if (playerContext.player() != null) {
playerContext.playerController().resetBlockRemoving(); playerContext.playerController().resetBlockRemoving();
} }
lastBlock = null;
} }
private boolean fakeBreak() {
if (playerContext != BaritoneAPI.getProvider().getPrimaryBaritone().getPlayerContext()) {
// for a non primary player, we need to fake break always, CLICK_LEFT has no effect
return true;
}
if (!Baritone.settings().leftClickWorkaround.get()) {
// if this setting is false, we CLICK_LEFT regardless of gui status
return false;
}
return mc.currentScreen != null;
}
public boolean tick(boolean isLeftClick) {
if (!fakeBreak()) {
if (didBreakLastTick) {
stopBreakingBlock();
}
return isLeftClick;
}
public void tick(boolean isLeftClick) {
RayTraceResult trace = playerContext.objectMouseOver(); RayTraceResult trace = playerContext.objectMouseOver();
boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK; boolean isBlockTrace = trace != null && trace.typeOfHit == RayTraceResult.Type.BLOCK;
@@ -91,6 +62,5 @@ public final class BlockBreakHelper implements Helper {
stopBreakingBlock(); stopBreakingBlock();
didBreakLastTick = false; didBreakLastTick = false;
} }
return false; // fakeBreak is true so no matter what we aren't forcing CLICK_LEFT
} }
} }
@@ -40,12 +40,15 @@ import net.minecraft.world.chunk.Chunk;
*/ */
public class BlockStateInterface { public class BlockStateInterface {
public static int numBlockStateLookups = 0;
public static int numTimesChunkSucceeded = 0;
private final Long2ObjectMap<Chunk> loadedChunks; private final Long2ObjectMap<Chunk> loadedChunks;
private final WorldData worldData; private final WorldData worldData;
private Chunk prev = null; private Chunk prev = null;
private CachedRegion prevCached = null; private CachedRegion prevCached = null;
private final boolean useTheRealWorld;
private static final IBlockState AIR = Blocks.AIR.getDefaultState(); private static final IBlockState AIR = Blocks.AIR.getDefaultState();
public BlockStateInterface(IPlayerContext ctx) { public BlockStateInterface(IPlayerContext ctx) {
@@ -64,6 +67,7 @@ public class BlockStateInterface {
} else { } else {
this.loadedChunks = worldLoaded; // this will only be used on the main thread this.loadedChunks = worldLoaded; // this will only be used on the main thread
} }
this.useTheRealWorld = !Baritone.settings().pathThroughCachedOnly.get();
if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) { if (!Minecraft.getMinecraft().isCallingFromMinecraftThread()) {
throw new IllegalStateException(); throw new IllegalStateException();
} }
@@ -88,13 +92,13 @@ public class BlockStateInterface {
} }
public IBlockState get0(int x, int y, int z) { // Mickey resigned public IBlockState get0(int x, int y, int z) { // Mickey resigned
numBlockStateLookups++;
// Invalid vertical position // Invalid vertical position
if (y < 0 || y >= 256) { if (y < 0 || y >= 256) {
return AIR; return AIR;
} }
if (!Baritone.settings().pathThroughCachedOnly.get()) { if (useTheRealWorld) {
Chunk cached = prev; Chunk cached = prev;
// there's great cache locality in block state lookups // there's great cache locality in block state lookups
// generally it's within each movement // generally it's within each movement
@@ -103,6 +107,7 @@ public class BlockStateInterface {
// which is a Long2ObjectOpenHashMap.get // which is a Long2ObjectOpenHashMap.get
// see issue #113 // see issue #113
if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) { if (cached != null && cached.x == x >> 4 && cached.z == z >> 4) {
numTimesChunkSucceeded++;
return cached.getBlockState(x, y, z); return cached.getBlockState(x, y, z);
} }
Chunk chunk = loadedChunks.get(ChunkPos.asLong(x >> 4, z >> 4)); Chunk chunk = loadedChunks.get(ChunkPos.asLong(x >> 4, z >> 4));
@@ -18,12 +18,15 @@
package baritone.utils; package baritone.utils;
import baritone.Baritone; import baritone.Baritone;
import baritone.api.BaritoneAPI;
import baritone.api.event.events.TickEvent; import baritone.api.event.events.TickEvent;
import baritone.api.utils.IInputOverrideHandler; import baritone.api.utils.IInputOverrideHandler;
import baritone.api.utils.input.Input; import baritone.api.utils.input.Input;
import baritone.behavior.Behavior; import baritone.behavior.Behavior;
import net.minecraft.client.Minecraft;
import net.minecraft.client.settings.KeyBinding; import net.minecraft.client.settings.KeyBinding;
import org.lwjgl.input.Keyboard; import net.minecraft.util.MovementInput;
import net.minecraft.util.MovementInputFromOptions;
import java.util.HashMap; import java.util.HashMap;
import java.util.Map; import java.util.Map;
@@ -57,8 +60,18 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
* @return Whether or not it is being forced down * @return Whether or not it is being forced down
*/ */
@Override @Override
public final boolean isInputForcedDown(KeyBinding key) { public final Boolean isInputForcedDown(KeyBinding key) {
return isInputForcedDown(Input.getInputForBind(key)); Input input = Input.getInputForBind(key);
if (input == null || !inControl()) {
return null;
}
if (input == Input.CLICK_LEFT) {
return false;
}
if (input == Input.CLICK_RIGHT) {
return isInputForcedDown(Input.CLICK_RIGHT);
}
return null;
} }
/** /**
@@ -91,29 +104,25 @@ public final class InputOverrideHandler extends Behavior implements IInputOverri
this.inputForceStateMap.clear(); this.inputForceStateMap.clear();
} }
@Override
public final void onProcessKeyBinds() {
// Simulate the key being held down this tick
for (Input input : Input.values()) {
KeyBinding keyBinding = input.getKeyBinding();
if (isInputForcedDown(keyBinding) && !keyBinding.isKeyDown()) {
int keyCode = keyBinding.getKeyCode();
if (keyCode < Keyboard.KEYBOARD_SIZE) {
KeyBinding.onTick(keyCode < 0 ? keyCode + 100 : keyCode);
}
}
}
}
@Override @Override
public final void onTick(TickEvent event) { public final void onTick(TickEvent event) {
if (event.getType() == TickEvent.Type.OUT) { if (event.getType() == TickEvent.Type.OUT) {
return; return;
} }
boolean stillClick = blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT)); blockBreakHelper.tick(isInputForcedDown(Input.CLICK_LEFT));
setInputForceState(Input.CLICK_LEFT, stillClick);
MovementInput desired = inControl()
? new PlayerMovementInput(this)
: new MovementInputFromOptions(Minecraft.getMinecraft().gameSettings);
if (ctx.player().movementInput.getClass() != desired.getClass()) {
ctx.player().movementInput = desired; // only set it if it was previously incorrect
// gotta do it this way, or else it constantly thinks you're beginning a double tap W sprint lol
}
}
private boolean inControl() {
return baritone.getPathingBehavior().isPathing() || baritone != BaritoneAPI.getProvider().getPrimaryBaritone();
} }
public BlockBreakHelper getBlockBreakHelper() { public BlockBreakHelper getBlockBreakHelper() {
@@ -29,7 +29,7 @@ import baritone.pathing.path.PathExecutor;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import java.util.*; import java.util.*;
import java.util.stream.Collectors; import java.util.stream.Stream;
public class PathingControlManager implements IPathingControlManager { public class PathingControlManager implements IPathingControlManager {
private final Baritone baritone; private final Baritone baritone;
@@ -64,8 +64,7 @@ public class PathingControlManager implements IPathingControlManager {
command = null; command = null;
for (IBaritoneProcess proc : processes) { for (IBaritoneProcess proc : processes) {
proc.onLostControl(); proc.onLostControl();
if (proc.isActive() && !proc.isTemporary()) { // it's okay for a temporary thing (like combat pause) to maintain control even if you say to cancel if (proc.isActive() && !proc.isTemporary()) { // it's okay only for a temporary thing (like combat pause) to maintain control even if you say to cancel
// but not for a non temporary thing
throw new IllegalStateException(proc.displayName()); throw new IllegalStateException(proc.displayName());
} }
} }
@@ -83,11 +82,12 @@ public class PathingControlManager implements IPathingControlManager {
public void preTick() { public void preTick() {
inControlLastTick = inControlThisTick; inControlLastTick = inControlThisTick;
command = doTheStuff(); PathingBehavior p = baritone.getPathingBehavior();
command = executeProcesses();
if (command == null) { if (command == null) {
p.cancelSegmentIfSafe();
return; return;
} }
PathingBehavior p = baritone.getPathingBehavior();
switch (command.commandType) { switch (command.commandType) {
case REQUEST_PAUSE: case REQUEST_PAUSE:
p.requestPause(); p.requestPause();
@@ -170,32 +170,30 @@ public class PathingControlManager implements IPathingControlManager {
} }
public PathingCommand doTheStuff() { public PathingCommand executeProcesses() {
List<IBaritoneProcess> inContention = processes.stream().filter(IBaritoneProcess::isActive).sorted(Comparator.comparingDouble(IBaritoneProcess::priority)).collect(Collectors.toList()); Stream<IBaritoneProcess> inContention = processes.stream()
boolean found = false; .filter(IBaritoneProcess::isActive)
boolean cancelOthers = false; .sorted(Comparator.comparingDouble(IBaritoneProcess::priority).reversed());
PathingCommand exec = null;
for (int i = inContention.size() - 1; i >= 0; i--) { // truly a gamer moment
IBaritoneProcess proc = inContention.get(i); Iterator<IBaritoneProcess> iterator = inContention.iterator();
if (found) { while (iterator.hasNext()) {
if (cancelOthers) { IBaritoneProcess proc = iterator.next();
proc.onLostControl();
PathingCommand exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel());
if (exec == null) {
if (proc.isActive()) {
throw new IllegalStateException(proc.displayName() + " returned null PathingCommand");
} }
proc.onLostControl();
} else { } else {
exec = proc.onTick(Objects.equals(proc, inControlLastTick) && baritone.getPathingBehavior().calcFailedLastTick(), baritone.getPathingBehavior().isSafeToCancel());
if (exec == null) {
if (proc.isActive()) {
throw new IllegalStateException(proc.displayName());
}
proc.onLostControl();
continue;
}
//System.out.println("Executing command " + exec.commandType + " " + exec.goal + " from " + proc.displayName());
inControlThisTick = proc; inControlThisTick = proc;
found = true; if (!proc.isTemporary()) {
cancelOthers = !proc.isTemporary(); iterator.forEachRemaining(IBaritoneProcess::onLostControl);
}
return exec;
} }
} }
return exec; return null;
} }
} }
@@ -0,0 +1,57 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* Baritone is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.utils;
import baritone.api.utils.input.Input;
import net.minecraft.util.MovementInput;
public class PlayerMovementInput extends MovementInput {
private final InputOverrideHandler handler;
public PlayerMovementInput(InputOverrideHandler handler) {
this.handler = handler;
}
public void updatePlayerMoveState() {
this.moveStrafe = 0.0F;
this.moveForward = 0.0F;
jump = handler.isInputForcedDown(Input.JUMP); // oppa
if (this.forwardKeyDown = handler.isInputForcedDown(Input.MOVE_FORWARD)) {
this.moveForward++;
}
if (this.backKeyDown = handler.isInputForcedDown(Input.MOVE_BACK)) {
this.moveForward--;
}
if (this.leftKeyDown = handler.isInputForcedDown(Input.MOVE_LEFT)) {
this.moveStrafe++;
}
if (this.rightKeyDown = handler.isInputForcedDown(Input.MOVE_RIGHT)) {
this.moveStrafe--;
}
if (this.sneak = handler.isInputForcedDown(Input.SNEAK)) {
this.moveStrafe *= 0.3D;
this.moveForward *= 0.3D;
}
}
}
+6 -7
View File
@@ -103,7 +103,7 @@ public class ToolSet {
IBlockState blockState = b.getDefaultState(); IBlockState blockState = b.getDefaultState();
for (byte i = 0; i < 9; i++) { for (byte i = 0; i < 9; i++) {
ItemStack itemStack = player.inventory.getStackInSlot(i); ItemStack itemStack = player.inventory.getStackInSlot(i);
double v = calculateStrVsBlock(itemStack, blockState); double v = calculateSpeedVsBlock(itemStack, blockState);
if (v > value) { if (v > value) {
value = v; value = v;
best = i; best = i;
@@ -128,7 +128,7 @@ public class ToolSet {
*/ */
private double getBestDestructionTime(Block b) { private double getBestDestructionTime(Block b) {
ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b)); ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b));
return calculateStrVsBlock(stack, b.getDefaultState()); return calculateSpeedVsBlock(stack, b.getDefaultState());
} }
/** /**
@@ -138,7 +138,7 @@ public class ToolSet {
* @param state the blockstate to be mined * @param state the blockstate to be mined
* @return how long it would take in ticks * @return how long it would take in ticks
*/ */
public static double calculateStrVsBlock(ItemStack item, IBlockState state) { public static double calculateSpeedVsBlock(ItemStack item, IBlockState state) {
float hardness = state.getBlockHardness(null, null); float hardness = state.getBlockHardness(null, null);
if (hardness < 0) { if (hardness < 0) {
return -1; return -1;
@@ -154,11 +154,10 @@ public class ToolSet {
speed /= hardness; speed /= hardness;
if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) { if (state.getMaterial().isToolNotRequired() || (!item.isEmpty() && item.canHarvestBlock(state))) {
speed /= 30; return speed / 30;
} else { } else {
speed /= 100; return speed / 100;
} }
return speed;
} }
/** /**
@@ -180,7 +179,7 @@ public class ToolSet {
speed *= 0.09; speed *= 0.09;
break; break;
case 2: case 2:
speed *= 0.0027; speed *= 0.0027; // you might think that 0.09*0.3 = 0.027 so that should be next, that would make too much sense. it's 0.0027.
break; break;
default: default:
speed *= 0.00081; speed *= 0.00081;
@@ -23,16 +23,12 @@ import baritone.api.utils.BetterBlockPos;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap; import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import java.util.List;
public final class Favoring { public final class Favoring {
private List<Avoidance> avoidances;
private final Long2DoubleOpenHashMap favorings; private final Long2DoubleOpenHashMap favorings;
public Favoring(IPlayerContext ctx, IPath previous) { public Favoring(IPlayerContext ctx, IPath previous) {
this(previous); this(previous);
avoidances = Avoidance.create(ctx); for (Avoidance avoid : Avoidance.create(ctx)) {
for (Avoidance avoid : avoidances) {
avoid.applySpherical(favorings); avoid.applySpherical(favorings);
} }
System.out.println("Favoring size: " + favorings.size()); System.out.println("Favoring size: " + favorings.size());
@@ -26,7 +26,7 @@ import net.minecraft.util.math.BlockPos;
public abstract class PathBase implements IPath { public abstract class PathBase implements IPath {
@Override @Override
public PathBase cutoffAtLoadedChunks(Object bsi0) { public PathBase cutoffAtLoadedChunks(Object bsi0) { // <-- cursed cursed cursed
BlockStateInterface bsi = (BlockStateInterface) bsi0; BlockStateInterface bsi = (BlockStateInterface) bsi0;
for (int i = 0; i < positions().size(); i++) { for (int i = 0; i < positions().size(); i++) {
BlockPos pos = positions().get(i); BlockPos pos = positions().get(i);
@@ -20,9 +20,9 @@ package baritone.utils.player;
import baritone.api.BaritoneAPI; import baritone.api.BaritoneAPI;
import baritone.api.cache.IWorldData; import baritone.api.cache.IWorldData;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import baritone.api.utils.IPlayerController;
import baritone.utils.Helper; import baritone.utils.Helper;
import net.minecraft.client.entity.EntityPlayerSP; import net.minecraft.client.entity.EntityPlayerSP;
import net.minecraft.client.multiplayer.PlayerControllerMP;
import net.minecraft.util.math.RayTraceResult; import net.minecraft.util.math.RayTraceResult;
import net.minecraft.world.World; import net.minecraft.world.World;
@@ -42,8 +42,8 @@ public enum PrimaryPlayerContext implements IPlayerContext, Helper {
} }
@Override @Override
public PlayerControllerMP playerController() { public IPlayerController playerController() {
return mc.playerController; return PrimaryPlayerController.INSTANCE;
} }
@Override @Override
@@ -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.utils.player;
import baritone.api.utils.IPlayerController;
import baritone.utils.Helper;
import net.minecraft.entity.player.EntityPlayer;
import net.minecraft.inventory.ClickType;
import net.minecraft.item.ItemStack;
import net.minecraft.util.EnumFacing;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.GameType;
/**
* @author Brady
* @since 12/14/2018
*/
public enum PrimaryPlayerController implements IPlayerController, Helper {
INSTANCE;
@Override
public boolean onPlayerDamageBlock(BlockPos pos, EnumFacing side) {
return mc.playerController.onPlayerDamageBlock(pos, side);
}
@Override
public void resetBlockRemoving() {
mc.playerController.resetBlockRemoving();
}
@Override
public ItemStack windowClick(int windowId, int slotId, int mouseButton, ClickType type, EntityPlayer player) {
return mc.playerController.windowClick(windowId, slotId, mouseButton, type, player);
}
@Override
public void setGameType(GameType type) {
mc.playerController.setGameType(type);
}
@Override
public GameType getGameType() {
return mc.playerController.getCurrentGameType();
}
}
+1 -1
View File
@@ -44,4 +44,4 @@ public class CachedRegionTest {
} }
} }
} }
} }
@@ -167,4 +167,4 @@ public class OpenSetsTest {
assertTrue(set.isEmpty()); assertTrue(set.isEmpty());
} }
} }
} }
@@ -47,4 +47,4 @@ public class GoalGetToBlockTest {
} }
assertTrue(acceptableOffsets.toString(), acceptableOffsets.isEmpty()); assertTrue(acceptableOffsets.toString(), acceptableOffsets.isEmpty());
} }
} }
@@ -48,4 +48,4 @@ public class ActionCostsTest {
return fallDistance; return fallDistance;
} }
} }
@@ -136,4 +136,4 @@ public class BetterBlockPosTest {
long after2 = System.nanoTime() / 1000000L; long after2 = System.nanoTime() / 1000000L;
System.out.println((after1 - before1) + " " + (after2 - before2)); System.out.println((after1 - before1) + " " + (after2 - before2));
} }
} }
@@ -29,4 +29,4 @@ public class PathingBlockTypeTest {
assertTrue(type == PathingBlockType.fromBits(bits[0], bits[1])); assertTrue(type == PathingBlockType.fromBits(bits[0], bits[1]));
} }
} }
} }