Merge branch 'master' into comms

This commit is contained in:
Leijurv
2019-01-17 12:16:45 -08:00
63 changed files with 563 additions and 466 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);
+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);
+15
View File
@@ -20,6 +20,7 @@ package baritone.api.cache;
import baritone.api.utils.IPlayerContext; import baritone.api.utils.IPlayerContext;
import net.minecraft.block.Block; import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import java.util.List; import java.util.List;
@@ -42,4 +43,18 @@ public interface IWorldScanner {
* @return The matching block positions * @return The matching block positions
*/ */
List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius); List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> blocks, int max, int yLevelThreshold, int maxSearchRadius);
/**
* Scans a single chunk for the specified blocks.
*
* @param ctx The {@link IPlayerContext} containing player and world info that the
* scan is based upon
* @param blocks The blocks to scan for
* @param pos The position of the target chunk
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @return The matching block positions
*/
List<BlockPos> scanChunk(IPlayerContext ctx, List<Block> blocks, ChunkPos pos, int max, int yLevelThreshold);
} }
@@ -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);
@@ -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")
@@ -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;
@@ -63,6 +64,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) {
@@ -124,12 +133,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())
@@ -204,7 +211,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);
+53 -29
View File
@@ -23,11 +23,14 @@ import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState; import net.minecraft.block.state.IBlockState;
import net.minecraft.client.multiplayer.ChunkProviderClient; import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.BlockStateContainer; 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.LinkedList; import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.List; import java.util.List;
public enum WorldScanner implements IWorldScanner { public enum WorldScanner implements IWorldScanner {
@@ -39,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;
} }
@@ -69,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)
@@ -107,4 +84,51 @@ public enum WorldScanner implements IWorldScanner {
searchRadiusSq++; searchRadiusSq++;
} }
} }
@Override
public List<BlockPos> scanChunk(IPlayerContext ctx, List<Block> blocks, ChunkPos pos, int max, int yLevelThreshold) {
if (blocks.isEmpty()) {
return Collections.emptyList();
}
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z);
int playerY = ctx.playerFeet().getY();
if (chunk == null || chunk.isEmpty()) {
return Collections.emptyList();
}
ArrayList<BlockPos> res = new ArrayList<>();
scanChunkInto(pos.x << 4, pos.z << 4, chunk, blocks, res, max, yLevelThreshold, playerY);
return res;
}
public void scanChunkInto(int chunkX, int chunkZ, Chunk chunk, List<Block> search, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
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 (search.contains(state.getBlock())) {
int yy = yReal | y;
result.add(new BlockPos(chunkX | x, yy, chunkZ | z));
if (result.size() >= max && Math.abs(yy - playerY) < yLevelThreshold) {
return;
}
}
}
}
}
}
}
} }
@@ -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));
@@ -55,7 +55,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 +63,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 +76,15 @@ 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();
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 {
@@ -91,11 +93,10 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
} }
} }
PathNode currentNode = openSet.removeLowest(); PathNode currentNode = openSet.removeLowest();
currentNode.isOpen = false;
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));
} }
for (Moves moves : Moves.values()) { for (Moves moves : Moves.values()) {
@@ -124,10 +125,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);
} }
@@ -153,10 +154,9 @@ 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()) {
openSet.update(neighbor); openSet.update(neighbor);
} else { } else {
neighbor.isOpen = true;
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
} }
for (int i = 0; i < bestSoFar.length; i++) { for (int i = 0; i < bestSoFar.length; i++) {
@@ -181,7 +181,7 @@ public final class AStarPathFinder extends AbstractNodeCostSearch implements Hel
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 +192,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() {
@@ -209,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);
} }
@@ -248,17 +248,16 @@ 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.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || mining.contains(ctx.getBlock(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
.filter(pos -> !ctx.bsi().isLoaded(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();
@@ -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
} }
} }
@@ -46,6 +46,8 @@ public class BlockStateInterface {
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 +66,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();
} }
@@ -94,7 +97,7 @@ public class BlockStateInterface {
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
@@ -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();
}
}