> blocksToAvoidBreaking = new Setting<>(new ArrayList<>(Arrays.asList( // TODO can this be a HashSet or ImmutableSet?
+ Blocks.CRAFTING_TABLE,
+ Blocks.FURNACE,
+ Blocks.LIT_FURNACE,
+ Blocks.CHEST,
+ Blocks.TRAPPED_CHEST
+ )));
+
+ /**
+ * If this setting is true, Baritone will never break a block that is adjacent to an unsupported falling block.
+ *
+ * I.E. it will never trigger cascading sand / gravel falls
+ */
+ public final Setting avoidUpdatingFallingBlocks = new Setting<>(true);
/**
* Enables some more advanced vine features. They're honestly just gimmicks and won't ever be needed in real
@@ -204,6 +215,13 @@ public final class Settings {
*/
public final Setting sprintAscends = new Setting<>(true);
+ /**
+ * If we overshoot a traverse and end up one block beyond the destination, mark it as successful anyway.
+ *
+ * This helps with speed at >=20m/s
+ */
+ public final Setting overshootTraverse = new Setting<>(true);
+
/**
* When breaking blocks for a movement, wait until all falling blocks have settled before continuing
*/
@@ -527,6 +545,8 @@ public final class Settings {
/**
* Exclusively use cached chunks for pathing
+ *
+ * Never turn this on
*/
public final Setting pathThroughCachedOnly = new Setting<>(false);
@@ -557,7 +577,7 @@ public final class Settings {
public final Setting renderCachedChunks = new Setting<>(false);
/**
- * 0.0f = not visible, fully transparent
+ * 0.0f = not visible, fully transparent (instead of setting this to 0, turn off renderCachedChunks)
* 1.0f = fully opaque
*/
public final Setting cachedChunksOpacity = new Setting<>(0.5f);
@@ -572,6 +592,16 @@ public final class Settings {
*/
public final Setting walkWhileBreaking = new Setting<>(true);
+ /**
+ * When a new segment is calculated that doesn't overlap with the current one, but simply begins where the current segment ends,
+ * splice it on and make a longer combined path. If this setting is off, any planned segment will not be spliced and will instead
+ * be the "next path" in PathingBehavior, and will only start after this one ends. Turning this off hurts planning ahead,
+ * because the next segment will exist even if it's very short.
+ *
+ * @see #planningTickLookahead
+ */
+ public final Setting splicePath = new Setting<>(true);
+
/**
* If we are more than 300 movements into the current path, discard the oldest segments, as they are no longer useful
*/
@@ -618,7 +648,7 @@ public final class Settings {
public final Setting exploreMaintainY = new Setting<>(64);
/**
- * Replant nether wart
+ * Replant nether wart while farming
*/
public final Setting replantNetherWart = new Setting<>(false);
@@ -635,14 +665,30 @@ public final class Settings {
public final Setting buildInLayers = new Setting<>(false);
/**
- * How far to move before repeating the build. -1 for the size of the build in that axis. 0 to disable
+ * false = build from bottom to top
+ *
+ * true = build from top to bottom
*/
- public final Setting buildRepeatDistance = new Setting<>(0);
+ public final Setting layerOrder = new Setting<>(false);
/**
- * What direction to repeat the build in
+ * How far to move before repeating the build. 0 to disable repeating on a certain axis, 0,0,0 to disable entirely
*/
- public final Setting buildRepeatDirection = new Setting<>(EnumFacing.NORTH);
+ public final Setting buildRepeat = new Setting<>(new Vec3i(0, 0, 0));
+
+ /**
+ * Allow standing above a block while mining it, in BuilderProcess
+ *
+ * Experimental
+ */
+ public final Setting breakFromAbove = new Setting<>(false);
+
+ /**
+ * As well as breaking from above, set a goal to up and to the side of all blocks to break.
+ *
+ * Never turn this on without also turning on breakFromAbove.
+ */
+ public final Setting goalBreakFromAbove = new Setting<>(false);
/**
* While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)?
@@ -764,6 +810,11 @@ public final class Settings {
*/
public final Setting> logger = new Setting<>(Minecraft.getMinecraft().ingameGUI.getChatGUI()::printChatMessage);
+ /**
+ * The size of the box that is rendered when the current goal is a GoalYLevel
+ */
+ public final Setting yLevelBoxSize = new Setting<>(15D);
+
/**
* The color of the current path
*/
diff --git a/src/api/java/baritone/api/pathing/goals/GoalYLevel.java b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
index ce54eebb..9add7176 100644
--- a/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
+++ b/src/api/java/baritone/api/pathing/goals/GoalYLevel.java
@@ -29,7 +29,7 @@ public class GoalYLevel implements Goal, ActionCosts {
/**
* The target Y level
*/
- private final int level;
+ public final int level;
public GoalYLevel(int level) {
this.level = level;
diff --git a/src/api/java/baritone/api/utils/BetterBlockPos.java b/src/api/java/baritone/api/utils/BetterBlockPos.java
index a1a3cb32..3b94a833 100644
--- a/src/api/java/baritone/api/utils/BetterBlockPos.java
+++ b/src/api/java/baritone/api/utils/BetterBlockPos.java
@@ -61,6 +61,8 @@ public final class BetterBlockPos extends BlockPos {
}
public static long longHash(int x, int y, int z) {
+ // TODO use the same thing as BlockPos.fromLong();
+ // invertibility would be incredibly useful
/*
* This is the hashcode implementation of Vec3i (the superclass of the class which I shall not name)
*
diff --git a/src/api/java/baritone/api/utils/ExampleBaritoneControl.java b/src/api/java/baritone/api/utils/ExampleBaritoneControl.java
index 715d8edb..29547281 100644
--- a/src/api/java/baritone/api/utils/ExampleBaritoneControl.java
+++ b/src/api/java/baritone/api/utils/ExampleBaritoneControl.java
@@ -332,7 +332,7 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
if (suffix.isEmpty()) {
// clear the area from the current goal to here
Goal goal = baritone.getPathingBehavior().getGoal();
- if (goal == null || !(goal instanceof GoalBlock)) {
+ if (!(goal instanceof GoalBlock)) {
logDirect("Need to specify goal of opposite corner");
return true;
}
@@ -385,17 +385,6 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
logDirect("farming");
return true;
}
- // this literally doesn't work, memory is disabled lol
- /*if (msg.equals("echest")) {
- Optional> contents = baritone.getMemoryBehavior().echest();
- if (contents.isPresent()) {
- logDirect("echest contents:");
- log(contents.get());
- } else {
- logDirect("echest contents unknown");
- }
- return true;
- }*/
if (msg.equals("chests")) {
for (Map.Entry entry : baritone.getWorldProvider().getCurrentWorld().getContainerMemory().getRememberedInventories().entrySet()) {
logDirect(entry.getKey() + "");
@@ -649,24 +638,6 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
}
return true;
}
- // this is completely impossible from api
- /*if (msg.equals("costs")) {
- List moves = Stream.of(Moves.values()).map(x -> x.apply0(new CalculationContext(baritone), ctx.playerFeet())).collect(Collectors.toCollection(ArrayList::new));
- while (moves.contains(null)) {
- moves.remove(null);
- }
- moves.sort(Comparator.comparingDouble(move -> move.getCost(new CalculationContext(baritone))));
- for (Movement move : moves) {
- String[] parts = move.getClass().toString().split("\\.");
- double cost = move.getCost();
- String strCost = cost + "";
- if (cost >= ActionCosts.COST_INF) {
- strCost = "IMPOSSIBLE";
- }
- logDirect(parts[parts.length - 1] + " " + move.getDest().getX() + "," + move.getDest().getY() + "," + move.getDest().getZ() + " " + strCost);
- }
- return true;
- }*/
if (msg.equals("damn")) {
logDirect("daniel");
}
@@ -688,18 +659,20 @@ public class ExampleBaritoneControl implements Helper, AbstractGameEventListener
private Goal parseGoal(String[] params) {
Goal goal;
try {
+ BetterBlockPos playerFeet = ctx.playerFeet();
switch (params.length) {
case 0:
- goal = new GoalBlock(ctx.playerFeet());
+ goal = new GoalBlock(playerFeet);
break;
case 1:
- goal = new GoalYLevel(Integer.parseInt(params[0]));
+
+ goal = new GoalYLevel(parseOrDefault(params[0], playerFeet.y));
break;
case 2:
- goal = new GoalXZ(Integer.parseInt(params[0]), Integer.parseInt(params[1]));
+ goal = new GoalXZ(parseOrDefault(params[0], playerFeet.x), parseOrDefault(params[1], playerFeet.z));
break;
case 3:
- goal = new GoalBlock(new BlockPos(Integer.parseInt(params[0]), Integer.parseInt(params[1]), Integer.parseInt(params[2])));
+ goal = new GoalBlock(new BlockPos(parseOrDefault(params[0], playerFeet.x), parseOrDefault(params[1], playerFeet.y), parseOrDefault(params[2], playerFeet.z)));
break;
default:
logDirect("unable to understand lol");
diff --git a/src/api/java/baritone/api/utils/MyChunkPos.java b/src/api/java/baritone/api/utils/MyChunkPos.java
index 5748a13d..1df7481d 100644
--- a/src/api/java/baritone/api/utils/MyChunkPos.java
+++ b/src/api/java/baritone/api/utils/MyChunkPos.java
@@ -17,11 +17,17 @@
package baritone.api.utils;
+import com.google.gson.annotations.SerializedName;
+
/**
* Need a non obfed chunkpos that we can load using GSON
*/
public class MyChunkPos {
+
+ @SerializedName("x")
public int x;
+
+ @SerializedName("y")
public int z;
@Override
diff --git a/src/api/java/baritone/api/utils/SettingsUtil.java b/src/api/java/baritone/api/utils/SettingsUtil.java
index 8667f554..5dee6e88 100644
--- a/src/api/java/baritone/api/utils/SettingsUtil.java
+++ b/src/api/java/baritone/api/utils/SettingsUtil.java
@@ -21,6 +21,7 @@ import baritone.api.Settings;
import net.minecraft.block.Block;
import net.minecraft.item.Item;
import net.minecraft.util.EnumFacing;
+import net.minecraft.util.math.Vec3i;
import java.awt.*;
import java.io.BufferedReader;
@@ -29,10 +30,12 @@ import java.io.IOException;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
+import java.util.Objects;
import java.util.function.Consumer;
import java.util.function.Function;
import java.util.regex.Matcher;
@@ -80,6 +83,8 @@ public class SettingsUtil {
ex.printStackTrace();
}
});
+ } catch (NoSuchFileException ignored) {
+ System.out.println("Baritone settings file not found, resetting.");
} catch (Exception ex) {
System.out.println("Exception while reading Baritone settings, some settings may be reset to default values!");
ex.printStackTrace();
@@ -175,6 +180,11 @@ public class SettingsUtil {
str -> new Color(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
color -> color.getRed() + "," + color.getGreen() + "," + color.getBlue()
),
+ VEC3I(
+ Vec3i.class,
+ str -> new Vec3i(Integer.parseInt(str.split(",")[0]), Integer.parseInt(str.split(",")[1]), Integer.parseInt(str.split(",")[2])),
+ vec -> vec.getX() + "," + vec.getY() + "," + vec.getZ()
+ ),
BLOCK(
Block.class,
str -> BlockUtils.stringToBlockRequired(str.trim()),
@@ -234,7 +244,9 @@ public class SettingsUtil {
@Override
public Object parse(ParserContext context, String raw) {
- return this.parser.apply(raw);
+ Object parsed = this.parser.apply(raw);
+ Objects.requireNonNull(parsed);
+ return parsed;
}
@Override
diff --git a/src/main/java/baritone/behavior/InventoryBehavior.java b/src/main/java/baritone/behavior/InventoryBehavior.java
index 03878ee5..684613af 100644
--- a/src/main/java/baritone/behavior/InventoryBehavior.java
+++ b/src/main/java/baritone/behavior/InventoryBehavior.java
@@ -33,7 +33,7 @@ import java.util.OptionalInt;
import java.util.Random;
import java.util.function.Predicate;
-public class InventoryBehavior extends Behavior {
+public final class InventoryBehavior extends Behavior {
public InventoryBehavior(Baritone baritone) {
super(baritone);
}
diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java
index e0031c8c..fbe48ad8 100644
--- a/src/main/java/baritone/behavior/PathingBehavior.java
+++ b/src/main/java/baritone/behavior/PathingBehavior.java
@@ -195,7 +195,9 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior,
current.onTick();
return;
}
- current = current.trySplice(next);
+ if (Baritone.settings().splicePath.value) {
+ current = current.trySplice(next);
+ }
if (next != null && current.getPath().getDest().equals(next.getPath().getDest())) {
next = null;
}
diff --git a/src/main/java/baritone/cache/ContainerMemory.java b/src/main/java/baritone/cache/ContainerMemory.java
index c1cb7b34..e79435e3 100644
--- a/src/main/java/baritone/cache/ContainerMemory.java
+++ b/src/main/java/baritone/cache/ContainerMemory.java
@@ -29,6 +29,7 @@ import net.minecraft.util.math.BlockPos;
import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.NoSuchFileException;
import java.nio.file.Path;
import java.util.*;
@@ -45,6 +46,8 @@ public class ContainerMemory implements IContainerMemory {
this.saveTo = saveTo;
try {
read(Files.readAllBytes(saveTo));
+ } catch (NoSuchFileException ignored) {
+ inventories.clear();
} catch (Exception ex) {
ex.printStackTrace();
inventories.clear();
diff --git a/src/main/java/baritone/pathing/movement/Movement.java b/src/main/java/baritone/pathing/movement/Movement.java
index c9849cab..be29b988 100644
--- a/src/main/java/baritone/pathing/movement/Movement.java
+++ b/src/main/java/baritone/pathing/movement/Movement.java
@@ -32,7 +32,6 @@ import net.minecraft.util.math.BlockPos;
import java.util.ArrayList;
import java.util.List;
-import java.util.Objects;
import java.util.Optional;
public abstract class Movement implements IMovement, MovementHelper {
diff --git a/src/main/java/baritone/pathing/movement/MovementHelper.java b/src/main/java/baritone/pathing/movement/MovementHelper.java
index c0683d47..d8f6a2f7 100644
--- a/src/main/java/baritone/pathing/movement/MovementHelper.java
+++ b/src/main/java/baritone/pathing/movement/MovementHelper.java
@@ -51,12 +51,27 @@ public interface MovementHelper extends ActionCosts, Helper {
return b == Blocks.ICE // ice becomes water, and water can mess up the path
|| b instanceof BlockSilverfish // obvious reasons
// call context.get directly with x,y,z. no need to make 5 new BlockPos for no reason
- || bsi.get0(x, y + 1, z).getBlock() instanceof BlockLiquid//don't break anything touching liquid on any side
- || bsi.get0(x + 1, y, z).getBlock() instanceof BlockLiquid
- || bsi.get0(x - 1, y, z).getBlock() instanceof BlockLiquid
- || bsi.get0(x, y, z + 1).getBlock() instanceof BlockLiquid
- || bsi.get0(x, y, z - 1).getBlock() instanceof BlockLiquid
- || Baritone.settings().blocksToAvoidBreaking.value.contains(b);
+ || avoidAdjacentBreaking(bsi, x, y + 1, z, true)
+ || avoidAdjacentBreaking(bsi, x + 1, y, z, false)
+ || avoidAdjacentBreaking(bsi, x - 1, y, z, false)
+ || avoidAdjacentBreaking(bsi, x, y, z + 1, false)
+ || avoidAdjacentBreaking(bsi, x, y, z - 1, false);
+ }
+
+ static boolean avoidAdjacentBreaking(BlockStateInterface bsi, int x, int y, int z, boolean directlyAbove) {
+ // returns true if you should avoid breaking a block that's adjacent to this one (e.g. lava that will start flowing if you give it a path)
+ // this is only called for north, south, east, west, and up. this is NOT called for down.
+ // we assume that it's ALWAYS okay to break the block thats ABOVE liquid
+ IBlockState state = bsi.get0(x, y, z);
+ Block block = state.getBlock();
+ if (!directlyAbove // it is fine to mine a block that has a falling block directly above, this (the cost of breaking the stacked fallings) is included in cost calculations
+ // therefore if directlyAbove is true, we will actually ignore if this is falling
+ && block instanceof BlockFalling // obviously, this check is only valid for falling blocks
+ && Baritone.settings().avoidUpdatingFallingBlocks.value // and if the setting is enabled
+ && BlockFalling.canFallThrough(bsi.get0(x, y - 1, z))) { // and if it would fall (i.e. it's unsupported)
+ return true; // dont break a block that is adjacent to unsupported gravel because it can cause really weird stuff
+ }
+ return block instanceof BlockLiquid;
}
static boolean canWalkThrough(IPlayerContext ctx, BetterBlockPos pos) {
@@ -353,6 +368,9 @@ public interface MovementHelper extends ActionCosts, Helper {
static double getMiningDurationTicks(CalculationContext context, int x, int y, int z, IBlockState state, boolean includeFalling) {
Block block = state.getBlock();
if (!canWalkThrough(context.bsi, x, y, z, state)) {
+ if (block instanceof BlockLiquid) {
+ return COST_INF;
+ }
double mult = context.breakCostMultiplierAt(x, y, z);
if (mult >= COST_INF) {
return COST_INF;
@@ -360,16 +378,11 @@ public interface MovementHelper extends ActionCosts, Helper {
if (avoidBreaking(context.bsi, x, y, z, state)) {
return COST_INF;
}
- if (block instanceof BlockLiquid) {
- return COST_INF;
- }
- double m = Blocks.CRAFTING_TABLE.equals(block) ? 10 : 1; // TODO see if this is still necessary. it's from MineBot when we wanted to penalize breaking its crafting table
double strVsBlock = context.toolSet.getStrVsBlock(state);
if (strVsBlock <= 0) {
return COST_INF;
}
-
- double result = m / strVsBlock;
+ double result = 1 / strVsBlock;
result += context.breakBlockAdditionalCost;
result *= mult;
if (includeFalling) {
diff --git a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
index 4f7ae713..a9266f14 100644
--- a/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
+++ b/src/main/java/baritone/pathing/movement/movements/MovementTraverse.java
@@ -36,8 +36,6 @@ import net.minecraft.init.Blocks;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.Vec3d;
-import java.util.Objects;
-
public class MovementTraverse extends Movement {
/**
@@ -230,7 +228,11 @@ public class MovementTraverse extends Movement {
}
if (isTheBridgeBlockThere) {
- if (ctx.playerFeet().equals(dest)) {
+ BetterBlockPos feet = ctx.playerFeet();
+ if (feet.equals(dest)) {
+ return state.setStatus(MovementStatus.SUCCESS);
+ }
+ if (Baritone.settings().overshootTraverse.value && (feet.equals(dest.add(getDirection())) || feet.equals(dest.add(getDirection()).add(getDirection())))) {
return state.setStatus(MovementStatus.SUCCESS);
}
Block low = BlockStateInterface.get(ctx, src).getBlock();
diff --git a/src/main/java/baritone/pathing/path/PathExecutor.java b/src/main/java/baritone/pathing/path/PathExecutor.java
index c848f42b..852ac44e 100644
--- a/src/main/java/baritone/pathing/path/PathExecutor.java
+++ b/src/main/java/baritone/pathing/path/PathExecutor.java
@@ -610,7 +610,7 @@ public class PathExecutor implements IPathExecutor, Helper {
ret.costEstimateIndex = costEstimateIndex;
ret.ticksOnCurrent = ticksOnCurrent;
return ret;
- }).orElse(cutIfTooLong());
+ }).orElseGet(this::cutIfTooLong); // dont actually call cutIfTooLong every tick if we won't actually use it, use a method reference
}
private PathExecutor cutIfTooLong() {
diff --git a/src/main/java/baritone/process/BackfillProcess.java b/src/main/java/baritone/process/BackfillProcess.java
index 8567a049..65e5692e 100644
--- a/src/main/java/baritone/process/BackfillProcess.java
+++ b/src/main/java/baritone/process/BackfillProcess.java
@@ -35,7 +35,7 @@ import net.minecraft.world.chunk.EmptyChunk;
import java.util.*;
import java.util.stream.Collectors;
-public class BackfillProcess extends BaritoneProcessHelper {
+public final class BackfillProcess extends BaritoneProcessHelper {
public HashMap blocksToReplace = new HashMap<>();
diff --git a/src/main/java/baritone/process/BuilderProcess.java b/src/main/java/baritone/process/BuilderProcess.java
index 6185b300..27c1f885 100644
--- a/src/main/java/baritone/process/BuilderProcess.java
+++ b/src/main/java/baritone/process/BuilderProcess.java
@@ -35,6 +35,9 @@ import baritone.utils.BlockStateInterface;
import baritone.utils.PathingCommandContext;
import baritone.utils.schematic.AirSchematic;
import baritone.utils.schematic.Schematic;
+import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
+import net.minecraft.block.BlockAir;
+import net.minecraft.block.BlockLiquid;
import net.minecraft.block.state.IBlockState;
import net.minecraft.init.Blocks;
import net.minecraft.item.ItemBlock;
@@ -49,13 +52,13 @@ import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.*;
-import java.util.stream.Collectors;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
-public class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
+public final class BuilderProcess extends BaritoneProcessHelper implements IBuilderProcess {
private HashSet incorrectPositions;
+ private LongOpenHashSet observedCompleted; // positions that are completed even if they're out of render distance and we can't make sure right now
private String name;
private ISchematic realSchematic;
private ISchematic schematic;
@@ -76,6 +79,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
this.origin = origin;
this.paused = false;
this.layer = 0;
+ this.observedCompleted = new LongOpenHashSet();
}
public void resume() {
@@ -133,15 +137,18 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return state;
}
-
- public Optional> toBreakNearPlayer(BuilderCalculationContext bcc) {
+ private Optional> toBreakNearPlayer(BuilderCalculationContext bcc) {
BetterBlockPos center = ctx.playerFeet();
+ BetterBlockPos pathStart = baritone.getPathingBehavior().pathStart();
for (int dx = -5; dx <= 5; dx++) {
- for (int dy = 0; dy <= 5; dy++) {
+ for (int dy = Baritone.settings().breakFromAbove.value ? -1 : 0; dy <= 5; dy++) {
for (int dz = -5; dz <= 5; dz++) {
int x = center.x + dx;
int y = center.y + dy;
int z = center.z + dz;
+ if (dy == -1 && x == pathStart.x && z == pathStart.z) {
+ continue; // dont mine what we're supported by, but not directly standing on
+ }
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired == null) {
continue; // irrelevant
@@ -174,7 +181,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
}
}
- public Optional searchForPlacables(BuilderCalculationContext bcc, List desirableOnHotbar) {
+ private Optional searchForPlacables(BuilderCalculationContext bcc, List desirableOnHotbar) {
BetterBlockPos center = ctx.playerFeet();
for (int dx = -5; dx <= 5; dx++) {
for (int dy = -5; dy <= 1; dy++) {
@@ -203,7 +210,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return Optional.empty();
}
- public Optional possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
+ private Optional possibleToPlace(IBlockState toPlace, int x, int y, int z, BlockStateInterface bsi) {
for (EnumFacing against : EnumFacing.values()) {
BetterBlockPos placeAgainstPos = new BetterBlockPos(x, y, z).offset(against);
IBlockState placeAgainstState = bsi.get0(placeAgainstPos);
@@ -231,8 +238,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return Optional.empty();
}
-
- public OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
+ private OptionalInt hasAnyItemThatWouldPlace(IBlockState desired, RayTraceResult result, Rotation rot) {
for (int i = 0; i < 9; i++) {
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
if (stack.isEmpty() || !(stack.getItem() instanceof ItemBlock)) {
@@ -295,12 +301,29 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
if (realSchematic == null) {
realSchematic = schematic;
}
+ ISchematic realSchematic = this.realSchematic; // wrap this properly, dont just have the inner class refer to the builderprocess.this
+ int minYInclusive;
+ int maxYInclusive;
+ // layer = 0 should be nothing
+ // layer = realSchematic.heightY() should be everything
+ if (Baritone.settings().layerOrder.value) { // top to bottom
+ maxYInclusive = realSchematic.heightY() - 1;
+ minYInclusive = realSchematic.heightY() - layer;
+ } else {
+ maxYInclusive = layer - 1;
+ minYInclusive = 0;
+ }
schematic = new ISchematic() {
@Override
public IBlockState desiredState(int x, int y, int z) {
return realSchematic.desiredState(x, y, z);
}
+ @Override
+ public boolean inSchematic(int x, int y, int z) {
+ return ISchematic.super.inSchematic(x, y, z) && y >= minYInclusive && y <= maxYInclusive;
+ }
+
@Override
public int widthX() {
return realSchematic.widthX();
@@ -308,7 +331,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
@Override
public int heightY() {
- return layer;
+ return realSchematic.heightY();
}
@Override
@@ -324,20 +347,16 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
layer++;
return onTick(calcFailed, isSafeToCancel);
}
- int distance = Baritone.settings().buildRepeatDistance.value;
- EnumFacing direction = Baritone.settings().buildRepeatDirection.value;
- if (distance == 0) {
+ Vec3i repeat = Baritone.settings().buildRepeat.value;
+ if (repeat.equals(new Vec3i(0, 0, 0))) {
logDirect("Done building");
onLostControl();
return null;
}
// build repeat time
- if (distance == -1) {
- distance = schematic.size(direction.getAxis());
- }
layer = 0;
- origin = new BlockPos(origin).offset(direction, distance);
- logDirect("Repeating build " + distance + " blocks to the " + direction + ", new origin is " + origin);
+ origin = new BlockPos(origin).add(repeat);
+ logDirect("Repeating build in vector " + repeat + ", new origin is " + origin);
return onTick(calcFailed, isSafeToCancel);
}
trim(bcc);
@@ -413,7 +432,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return new PathingCommandContext(goal, PathingCommandType.FORCE_REVALIDATE_GOAL_AND_PATH, bcc);
}
- public boolean recalc(BuilderCalculationContext bcc) {
+ private boolean recalc(BuilderCalculationContext bcc) {
if (incorrectPositions == null) {
incorrectPositions = new HashSet<>();
fullRecalc(bcc);
@@ -428,7 +447,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return !incorrectPositions.isEmpty();
}
- public void trim(BuilderCalculationContext bcc) {
+ private void trim(BuilderCalculationContext bcc) {
HashSet copy = new HashSet<>(incorrectPositions);
copy.removeIf(pos -> pos.distanceSq(ctx.player().posX, ctx.player().posY, ctx.player().posZ) > 200);
if (!copy.isEmpty()) {
@@ -436,7 +455,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
}
}
- public void recalcNearby(BuilderCalculationContext bcc) {
+ private void recalcNearby(BuilderCalculationContext bcc) {
BetterBlockPos center = ctx.playerFeet();
for (int dx = -5; dx <= 5; dx++) {
for (int dy = -5; dy <= 5; dy++) {
@@ -447,10 +466,13 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
IBlockState desired = bcc.getSchematic(x, y, z);
if (desired != null) {
// we care about this position
+ BetterBlockPos pos = new BetterBlockPos(x, y, z);
if (valid(bcc.bsi.get0(x, y, z), desired)) {
- incorrectPositions.remove(new BetterBlockPos(x, y, z));
+ incorrectPositions.remove(pos);
+ observedCompleted.add(BetterBlockPos.longHash(pos));
} else {
- incorrectPositions.add(new BetterBlockPos(x, y, z));
+ incorrectPositions.add(pos);
+ observedCompleted.remove(BetterBlockPos.longHash(pos));
}
}
}
@@ -458,13 +480,32 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
}
}
- public void fullRecalc(BuilderCalculationContext bcc) {
+ private void fullRecalc(BuilderCalculationContext bcc) {
incorrectPositions = new HashSet<>();
for (int y = 0; y < schematic.heightY(); y++) {
for (int z = 0; z < schematic.lengthZ(); z++) {
for (int x = 0; x < schematic.widthX(); x++) {
- if (schematic.inSchematic(x, y, z) && !valid(bcc.bsi.get0(x + origin.getX(), y + origin.getY(), z + origin.getZ()), schematic.desiredState(x, y, z))) {
- incorrectPositions.add(new BetterBlockPos(x + origin.getX(), y + origin.getY(), z + origin.getZ()));
+ if (!schematic.inSchematic(x, y, z)) {
+ continue;
+ }
+ int blockX = x + origin.getX();
+ int blockY = y + origin.getY();
+ int blockZ = z + origin.getZ();
+ if (bcc.bsi.worldContainsLoadedChunk(blockX, blockZ)) { // check if its in render distance, not if its in cache
+ // we can directly observe this block, it is in render distance
+ if (valid(bcc.bsi.get0(blockX, blockY, blockZ), schematic.desiredState(x, y, z))) {
+ observedCompleted.add(BetterBlockPos.longHash(blockX, blockY, blockZ));
+ } else {
+ incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
+ observedCompleted.remove(BetterBlockPos.longHash(blockX, blockY, blockZ));
+ }
+ continue;
+ }
+ // this is not in render distance
+ if (!observedCompleted.contains(BetterBlockPos.longHash(blockX, blockY, blockZ))) {
+ // and we've never seen this position be correct
+ // therefore mark as incorrect
+ incorrectPositions.add(new BetterBlockPos(blockX, blockY, blockZ));
}
}
}
@@ -472,17 +513,45 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
}
private Goal assemble(BuilderCalculationContext bcc, List approxPlacable) {
- List placable = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() == Blocks.AIR && approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))).collect(Collectors.toList());
- Goal[] toBreak = incorrectPositions.stream().filter(pos -> bcc.bsi.get0(pos).getBlock() != Blocks.AIR).map(GoalBreak::new).toArray(Goal[]::new);
- Goal[] toPlace = placable.stream().filter(pos -> !placable.contains(pos.down()) && !placable.contains(pos.down(2))).map(pos -> placementgoal(pos, bcc)).toArray(Goal[]::new);
+ List placable = new ArrayList<>();
+ List breakable = new ArrayList<>();
+ List sourceLiquids = new ArrayList<>();
+ incorrectPositions.forEach(pos -> {
+ IBlockState state = bcc.bsi.get0(pos);
+ if (state.getBlock() instanceof BlockAir) {
+ if (approxPlacable.contains(bcc.getSchematic(pos.x, pos.y, pos.z))) {
+ placable.add(pos);
+ }
+ } else {
+ if (state.getBlock() instanceof BlockLiquid) {
+ // if the block itself is JUST a liquid (i.e. not just a waterlogged block), we CANNOT break it
+ // TODO for 1.13 make sure that this only matches pure water, not waterlogged blocks
+ if (!MovementHelper.possiblyFlowing(state)) {
+ // if it's a source block then we want to replace it with a throwaway
+ sourceLiquids.add(pos);
+ }
+ } else {
+ breakable.add(pos);
+ }
+ }
+ });
+ List toBreak = new ArrayList<>();
+ breakable.forEach(pos -> toBreak.add(breakGoal(pos, bcc)));
+ List toPlace = new ArrayList<>();
+ placable.forEach(pos -> {
+ if (!placable.contains(pos.down()) && !placable.contains(pos.down(2))) {
+ toPlace.add(placementGoal(pos, bcc));
+ }
+ });
+ sourceLiquids.forEach(pos -> toPlace.add(new GoalBlock(pos.up())));
- if (toPlace.length != 0) {
- return new JankyGoalComposite(new GoalComposite(toPlace), new GoalComposite(toBreak));
+ if (!toPlace.isEmpty()) {
+ return new JankyGoalComposite(new GoalComposite(toPlace.toArray(new Goal[0])), new GoalComposite(toBreak.toArray(new Goal[0])));
}
- if (toBreak.length == 0) {
+ if (toBreak.isEmpty()) {
return null;
}
- return new GoalComposite(toBreak);
+ return new GoalComposite(toBreak.toArray(new Goal[0]));
}
public static class JankyGoalComposite implements Goal {
@@ -528,8 +597,8 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
}
}
- public Goal placementgoal(BlockPos pos, BuilderCalculationContext bcc) {
- if (ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) {
+ private Goal placementGoal(BlockPos pos, BuilderCalculationContext bcc) {
+ if (ctx.world().getBlockState(pos).getBlock() != Blocks.AIR) { // TODO can this even happen?
return new GoalPlace(pos);
}
boolean allowSameLevel = ctx.world().getBlockState(pos.up()).getBlock() != Blocks.AIR;
@@ -541,6 +610,21 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return new GoalPlace(pos);
}
+ private Goal breakGoal(BlockPos pos, BuilderCalculationContext bcc) {
+ if (Baritone.settings().goalBreakFromAbove.value && bcc.bsi.get0(pos.up()).getBlock() instanceof BlockAir && bcc.bsi.get0(pos.up(2)).getBlock() instanceof BlockAir) { // TODO maybe possible without the up(2) check?
+ return new JankyGoalComposite(new GoalBreak(pos), new GoalGetToBlock(pos.up()) {
+ @Override
+ public boolean isInGoal(int x, int y, int z) {
+ if (y > this.y || (x == this.x && y == this.y && z == this.z)) {
+ return false;
+ }
+ return super.isInGoal(x, y, z);
+ }
+ });
+ }
+ return new GoalBreak(pos);
+ }
+
public static class GoalAdjacent extends GoalGetToBlock {
private boolean allowSameLevel;
@@ -587,6 +671,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
realSchematic = null;
layer = 0;
paused = false;
+ observedCompleted = null;
}
@Override
@@ -594,7 +679,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return paused ? "Builder Paused" : "Building " + name;
}
- public List placable(int size) {
+ private List placable(int size) {
List result = new ArrayList<>();
for (int i = 0; i < size; i++) {
ItemStack stack = ctx.player().inventory.mainInventory.get(i);
@@ -609,7 +694,7 @@ public class BuilderProcess extends BaritoneProcessHelper implements IBuilderPro
return result;
}
- public boolean valid(IBlockState current, IBlockState desired) {
+ private boolean valid(IBlockState current, IBlockState desired) {
// TODO more complicated comparison logic I guess
return desired == null || current.equals(desired);
}
diff --git a/src/main/java/baritone/process/CustomGoalProcess.java b/src/main/java/baritone/process/CustomGoalProcess.java
index 4003b7a7..b45c7d6f 100644
--- a/src/main/java/baritone/process/CustomGoalProcess.java
+++ b/src/main/java/baritone/process/CustomGoalProcess.java
@@ -29,7 +29,7 @@ import baritone.utils.BaritoneProcessHelper;
*
* @author leijurv
*/
-public class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess {
+public final class CustomGoalProcess extends BaritoneProcessHelper implements ICustomGoalProcess {
/**
* The current goal
diff --git a/src/main/java/baritone/process/ExploreProcess.java b/src/main/java/baritone/process/ExploreProcess.java
index 35ddcb84..aa7e2c2a 100644
--- a/src/main/java/baritone/process/ExploreProcess.java
+++ b/src/main/java/baritone/process/ExploreProcess.java
@@ -41,7 +41,7 @@ import java.nio.file.Path;
import java.util.ArrayList;
import java.util.List;
-public class ExploreProcess extends BaritoneProcessHelper implements IExploreProcess {
+public final class ExploreProcess extends BaritoneProcessHelper implements IExploreProcess {
private BlockPos explorationOrigin;
diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java
index ac6d488f..9593a192 100644
--- a/src/main/java/baritone/process/FarmProcess.java
+++ b/src/main/java/baritone/process/FarmProcess.java
@@ -50,7 +50,7 @@ import java.util.List;
import java.util.Optional;
import java.util.function.Predicate;
-public class FarmProcess extends BaritoneProcessHelper implements IFarmProcess {
+public final class FarmProcess extends BaritoneProcessHelper implements IFarmProcess {
private boolean active;
diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java
index 0116df83..4fb4d540 100644
--- a/src/main/java/baritone/process/GetToBlockProcess.java
+++ b/src/main/java/baritone/process/GetToBlockProcess.java
@@ -34,7 +34,7 @@ import net.minecraft.util.math.BlockPos;
import java.util.*;
-public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
+public final class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBlockProcess {
private Block gettingTo;
private List knownLocations;
@@ -42,6 +42,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
private BlockPos start;
private int tickCount = 0;
+ private int arrivalTickCount = 0;
public GetToBlockProcess(Baritone baritone) {
super(baritone);
@@ -53,6 +54,7 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
gettingTo = block;
start = ctx.playerFeet();
blacklist = new ArrayList<>();
+ arrivalTickCount = 0;
rescan(new ArrayList<>(), new CalculationContext(baritone));
}
@@ -196,6 +198,10 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl
return true;
}
}
+ if (arrivalTickCount++ > 20) {
+ logDirect("Right click timed out");
+ return true;
+ }
return false; // trying to right click, will do it next tick or so
}
}
diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java
index 6051fe4a..ca1b3490 100644
--- a/src/main/java/baritone/process/MineProcess.java
+++ b/src/main/java/baritone/process/MineProcess.java
@@ -88,17 +88,16 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return null;
}
}
- boolean shouldCancel = calcFailed;
- if (calcFailed && !knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
- logDirect("Unable to find any path to " + mining + ", blacklisting presumably unreachable closest instance...");
- knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(blacklist::add);
- knownOreLocations.removeIf(blacklist::contains);
- shouldCancel = false; // 😎
- }
- if (shouldCancel) {
- logDirect("Unable to find any path to " + mining + ", canceling Mine");
- cancel();
- return null;
+ if (calcFailed) {
+ if (!knownOreLocations.isEmpty() && Baritone.settings().blacklistClosestOnFailure.value) {
+ logDirect("Unable to find any path to " + mining + ", blacklisting presumably unreachable closest instance...");
+ knownOreLocations.stream().min(Comparator.comparingDouble(ctx.player()::getDistanceSq)).ifPresent(blacklist::add);
+ knownOreLocations.removeIf(blacklist::contains);
+ } else {
+ logDirect("Unable to find any path to " + mining + ", canceling Mine");
+ cancel();
+ return null;
+ }
}
int mineGoalUpdateInterval = Baritone.settings().mineGoalUpdateInterval.value;
List curr = new ArrayList<>(knownOreLocations);
@@ -111,7 +110,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
}
Optional shaft = curr.stream()
.filter(pos -> pos.getX() == ctx.playerFeet().getX() && pos.getZ() == ctx.playerFeet().getZ())
- .filter(pos -> pos.getY() > ctx.playerFeet().getY())
+ .filter(pos -> pos.getY() >= ctx.playerFeet().getY())
.filter(pos -> !(BlockStateInterface.get(ctx, pos).getBlock() instanceof BlockAir)) // after breaking a block, it takes mineGoalUpdateInterval ticks for it to actually update this list =(
.min(Comparator.comparingDouble(ctx.player()::getDistanceSq));
baritone.getInputOverrideHandler().clearAllKeys();
@@ -206,9 +205,16 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
knownOreLocations = locs;
}
- private static boolean internalMiningGoal(BlockPos pos, IPlayerContext ctx, List locs) {
+ private boolean internalMiningGoal(BlockPos pos, IPlayerContext ctx, List locs) {
// Here, BlockStateInterface is used because the position may be in a cached chunk (the targeted block is one that is kept track of)
- return locs.contains(pos) || (Baritone.settings().internalMiningAirException.value && BlockStateInterface.getBlock(ctx, pos) instanceof BlockAir);
+ if (locs.contains(pos)) {
+ return true;
+ }
+ Block block = BlockStateInterface.getBlock(ctx, pos);
+ if (Baritone.settings().internalMiningAirException.value && block instanceof BlockAir) {
+ return true;
+ }
+ return mining.contains(block);
}
private Goal coalesce(BlockPos loc, List locs) {
@@ -363,7 +369,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
.filter(pos -> !blacklist.contains(pos))
- .sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().playerFeet()::distanceSq))
+ .sorted(Comparator.comparingDouble(ctx.getBaritone().getPlayerContext().player()::getDistanceSq))
.collect(Collectors.toList());
if (locs.size() > max) {
diff --git a/src/main/java/baritone/utils/PathRenderer.java b/src/main/java/baritone/utils/PathRenderer.java
index d1afe34d..88a18147 100644
--- a/src/main/java/baritone/utils/PathRenderer.java
+++ b/src/main/java/baritone/utils/PathRenderer.java
@@ -276,13 +276,13 @@ public final class PathRenderer implements Helper {
double maxY;
double y1;
double y2;
+ double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
if (goal instanceof IGoalRenderPos) {
BlockPos goalPos = ((IGoalRenderPos) goal).getGoalPos();
minX = goalPos.getX() + 0.002 - renderPosX;
maxX = goalPos.getX() + 1 - 0.002 - renderPosX;
minZ = goalPos.getZ() + 0.002 - renderPosZ;
maxZ = goalPos.getZ() + 1 - 0.002 - renderPosZ;
- double y = MathHelper.cos((float) (((float) ((System.nanoTime() / 100000L) % 20000L)) / 20000F * Math.PI * 2));
if (goal instanceof GoalGetToBlock || goal instanceof GoalTwoBlocks) {
y /= 2;
}
@@ -341,6 +341,16 @@ public final class PathRenderer implements Helper {
drawDankLitGoalBox(player, g, partialTicks, color);
}
return;
+ } else if (goal instanceof GoalYLevel) {
+ GoalYLevel goalpos = (GoalYLevel) goal;
+ minX = player.posX - Baritone.settings().yLevelBoxSize.value - renderPosX;
+ minZ = player.posZ - Baritone.settings().yLevelBoxSize.value - renderPosZ;
+ maxX = player.posX + Baritone.settings().yLevelBoxSize.value - renderPosX;
+ maxZ = player.posZ + Baritone.settings().yLevelBoxSize.value - renderPosZ;
+ minY = ((GoalYLevel) goal).level - renderPosY;
+ maxY = minY + 2;
+ y1 = 1 + y + goalpos.level - renderPosY;
+ y2 = 1 - y + goalpos.level - renderPosY;
} else {
return;
}
diff --git a/src/main/java/baritone/utils/ToolSet.java b/src/main/java/baritone/utils/ToolSet.java
index 31f23f20..69a5ae9a 100644
--- a/src/main/java/baritone/utils/ToolSet.java
+++ b/src/main/java/baritone/utils/ToolSet.java
@@ -65,10 +65,10 @@ public class ToolSet {
}
/**
- * Using the best tool on the hotbar, how long would it take to mine this block
+ * Using the best tool on the hotbar, how fast we can mine this block
*
* @param state the blockstate to be mined
- * @return how long it would take in ticks
+ * @return the speed of how fast we'll mine it. 1/(time in ticks)
*/
public double getStrVsBlock(IBlockState state) {
return breakStrengthCache.computeIfAbsent(state.getBlock(), backendCalculation);
@@ -128,7 +128,11 @@ public class ToolSet {
*/
private double getBestDestructionTime(Block b) {
ItemStack stack = player.inventory.getStackInSlot(getBestSlot(b));
- return calculateSpeedVsBlock(stack, b.getDefaultState());
+ return calculateSpeedVsBlock(stack, b.getDefaultState()) * avoidanceMultiplier(b);
+ }
+
+ private double avoidanceMultiplier(Block b) {
+ return Baritone.settings().blocksToAvoidBreaking.value.contains(b) ? 0.1 : 1;
}
/**