diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 04c396fd..0d8529dd 100644 --- a/src/api/java/baritone/api/Settings.java +++ b/src/api/java/baritone/api/Settings.java @@ -24,8 +24,8 @@ import net.minecraft.util.text.ITextComponent; import java.awt.*; import java.lang.reflect.Field; -import java.util.*; import java.util.List; +import java.util.*; import java.util.function.Consumer; /** @@ -396,6 +396,18 @@ public class Settings { */ public Setting axisHeight = new Setting<>(120); + /** + * Allow MineBehavior to use X-Ray to see where the ores are. Turn this option off to force it to mine "legit" + * where it will only mine an ore once it can actually see it, so it won't do or know anything that a normal player + * couldn't. If you don't want it to look like you're X-Raying, turn this off + */ + public Setting legitMine = new Setting<>(false); + + /** + * What Y level to go to for legit strip mining + */ + public Setting legitMineYLevel = new Setting<>(11); + /** * When mining block of a certain type, try to mine two at once instead of one. * If the block above is also a goal block, set GoalBlock instead of GoalTwoBlocks diff --git a/src/main/java/baritone/behavior/MineBehavior.java b/src/main/java/baritone/behavior/MineBehavior.java index 3bb5e8da..81a18ef7 100644 --- a/src/main/java/baritone/behavior/MineBehavior.java +++ b/src/main/java/baritone/behavior/MineBehavior.java @@ -20,14 +20,13 @@ package baritone.behavior; import baritone.Baritone; import baritone.api.behavior.IMineBehavior; import baritone.api.event.events.TickEvent; -import baritone.api.pathing.goals.Goal; -import baritone.api.pathing.goals.GoalBlock; -import baritone.api.pathing.goals.GoalComposite; -import baritone.api.pathing.goals.GoalTwoBlocks; +import baritone.api.pathing.goals.*; +import baritone.api.utils.RotationUtils; import baritone.cache.CachedChunk; import baritone.cache.ChunkPacker; import baritone.cache.WorldProvider; import baritone.cache.WorldScanner; +import baritone.pathing.movement.MovementHelper; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; import net.minecraft.block.Block; @@ -51,6 +50,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe private List mining; private List knownOreLocations; + private BlockPos branchPoint; private int desiredQuantity; private MineBehavior() {} @@ -80,6 +80,9 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe Baritone.INSTANCE.getExecutor().execute(this::rescan); } } + if (Baritone.settings().legitMine.get()) { + addNearby(); + } updateGoal(); PathingBehavior.INSTANCE.revalidateGoal(); } @@ -90,17 +93,42 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe } List locs = knownOreLocations; if (!locs.isEmpty()) { - locs = prune(new ArrayList<>(locs), mining, 64); - PathingBehavior.INSTANCE.setGoal(coalesce(locs)); - PathingBehavior.INSTANCE.path(); + List locs2 = prune(new ArrayList<>(locs), mining, 64); + // can't reassign locs, gotta make a new var locs2, because we use it in a lambda right here, and variables you use in a lambda must be effectively final + PathingBehavior.INSTANCE.setGoalAndPath(new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new))); knownOreLocations = locs; + return; } + // we don't know any ore locations at the moment + if (!Baritone.settings().legitMine.get()) { + return; + } + // only in non-Xray mode (aka legit mode) do we do this + if (branchPoint == null) { + int y = Baritone.settings().legitMineYLevel.get(); + if (!PathingBehavior.INSTANCE.isPathing() && playerFeet().y == y) { + // cool, path is over and we are at desired y + branchPoint = playerFeet(); + } else { + PathingBehavior.INSTANCE.setGoalAndPath(new GoalYLevel(y)); + return; + } + } + + if (playerFeet().equals(branchPoint)) { + // TODO mine 1x1 shafts to either side + branchPoint = branchPoint.north(10); + } + PathingBehavior.INSTANCE.setGoalAndPath(new GoalBlock(branchPoint)); } private void rescan() { if (mining == null) { return; } + if (Baritone.settings().legitMine.get()) { + return; + } List locs = xrayFor(mining, 64); if (locs.isEmpty()) { logDebug("No locations for " + mining + " known, cancelling"); @@ -132,10 +160,6 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe } } - public GoalComposite coalesce(List locs) { - return new GoalComposite(locs.stream().map(loc -> coalesce(loc, locs)).toArray(Goal[]::new)); - } - public List xrayFor(List mining, int max) { List locs = new ArrayList<>(); List uninteresting = new ArrayList<>(); @@ -159,26 +183,57 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe return prune(locs, mining, max); } - public List prune(List locs, List mining, int max) { - BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet(); - locs.sort(Comparator.comparingDouble(playerFeet::distanceSq)); + public void addNearby() { + BlockPos playerFeet = playerFeet(); + int searchDist = 4;//why four? idk + for (int x = playerFeet.getX() - searchDist; x <= playerFeet.getX() + searchDist; x++) { + for (int y = playerFeet.getY() - searchDist; y <= playerFeet.getY() + searchDist; y++) { + for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) { + BlockPos pos = new BlockPos(x, y, z); + if (mining.contains(BlockStateInterface.getBlock(pos))) { + if (RotationUtils.reachable(player(), pos).isPresent()) {//crucial to only add blocks we can see because otherwise this is an x-ray and it'll get caught + knownOreLocations.add(pos); + } + } + } + } + } + knownOreLocations = prune(knownOreLocations, mining, 64); + } + + public static List prune(List locs2, List mining, int max) { + List locs = locs2 + .stream() + + // remove any that are within loaded chunks that aren't actually what we want + .filter(pos -> MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock())) + + // remove any that are implausible to mine (encased in bedrock, or touching lava) + .filter(MineBehavior::plausibleToBreak) + + .sorted(Comparator.comparingDouble(Helper.HELPER.playerFeet()::distanceSq)) + .collect(Collectors.toList()); - // remove any that are within loaded chunks that aren't actually what we want - locs.removeAll(locs.stream() - .filter(pos -> !(MineBehavior.INSTANCE.world().getChunk(pos) instanceof EmptyChunk)) - .filter(pos -> !mining.contains(BlockStateInterface.get(pos).getBlock())) - .collect(Collectors.toList())); if (locs.size() > max) { return locs.subList(0, max); } return locs; } + public static boolean plausibleToBreak(BlockPos pos) { + if (MovementHelper.avoidBreaking(pos.getX(), pos.getY(), pos.getZ(), BlockStateInterface.get(pos))) { + return false; + } + // bedrock above and below makes it implausible, otherwise we're good + return !(BlockStateInterface.getBlock(pos.up()) == Blocks.BEDROCK && BlockStateInterface.getBlock(pos.down()) == Blocks.BEDROCK); + } + @Override public void mine(int quantity, String... blocks) { this.mining = blocks == null || blocks.length == 0 ? null : Arrays.stream(blocks).map(ChunkPacker::stringToBlock).collect(Collectors.toList()); this.desiredQuantity = quantity; this.knownOreLocations = new ArrayList<>(); + this.branchPoint = null; rescan(); updateGoal(); } @@ -188,6 +243,7 @@ public final class MineBehavior extends Behavior implements IMineBehavior, Helpe this.mining = blocks == null || blocks.length == 0 ? null : Arrays.asList(blocks); this.desiredQuantity = quantity; this.knownOreLocations = new ArrayList<>(); + this.branchPoint = null; rescan(); updateGoal(); } diff --git a/src/main/java/baritone/behavior/PathingBehavior.java b/src/main/java/baritone/behavior/PathingBehavior.java index 869aac1f..f1899333 100644 --- a/src/main/java/baritone/behavior/PathingBehavior.java +++ b/src/main/java/baritone/behavior/PathingBehavior.java @@ -201,6 +201,11 @@ public final class PathingBehavior extends Behavior implements IPathingBehavior, this.goal = goal; } + public boolean setGoalAndPath(Goal goal) { + setGoal(goal); + return path(); + } + @Override public Goal getGoal() { return goal;