diff --git a/src/api/java/baritone/api/Settings.java b/src/api/java/baritone/api/Settings.java index 0d8529dd9..6fbd14c63 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.List; import java.util.*; +import java.util.List; import java.util.function.Consumer; /** @@ -376,6 +376,11 @@ public class Settings { */ public Setting mineGoalUpdateInterval = new Setting<>(5); + /** + * While mining, should it also consider dropped items of the correct type as a pathing destination (as well as ore blocks)? + */ + public Setting mineScanDroppedItems = new Setting<>(true); + /** * Cancel the current path if the goal has changed, and the path originally ended in the goal but doesn't anymore. *

diff --git a/src/main/java/baritone/process/GetToBlockProcess.java b/src/main/java/baritone/process/GetToBlockProcess.java index 7f5340ed1..d35b4fb4b 100644 --- a/src/main/java/baritone/process/GetToBlockProcess.java +++ b/src/main/java/baritone/process/GetToBlockProcess.java @@ -94,6 +94,6 @@ public class GetToBlockProcess extends BaritoneProcessHelper implements IGetToBl } private void rescan() { - knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64); + knownLocations = MineProcess.searchWorld(Collections.singletonList(gettingTo), 64, world()); } } \ No newline at end of file diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 2efeca032..e4f3db217 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -32,10 +32,13 @@ import baritone.utils.BaritoneProcessHelper; import baritone.utils.BlockStateInterface; import baritone.utils.Helper; import net.minecraft.block.Block; +import net.minecraft.entity.Entity; +import net.minecraft.entity.item.EntityItem; import net.minecraft.init.Blocks; import net.minecraft.item.Item; import net.minecraft.item.ItemStack; import net.minecraft.util.math.BlockPos; +import net.minecraft.world.World; import net.minecraft.world.chunk.EmptyChunk; import java.util.*; @@ -112,7 +115,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro private Goal updateGoal() { List locs = knownOreLocations; if (!locs.isEmpty()) { - List locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT); + List locs2 = prune(new ArrayList<>(locs), mining, ORE_LOCATIONS_COUNT, world()); // 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 Goal goal = new GoalComposite(locs2.stream().map(loc -> coalesce(loc, locs2)).toArray(Goal[]::new)); knownOreLocations = locs2; @@ -147,7 +150,8 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro if (Baritone.settings().legitMine.get()) { return; } - List locs = searchWorld(mining, ORE_LOCATIONS_COUNT); + List locs = searchWorld(mining, ORE_LOCATIONS_COUNT, world()); + locs.addAll(droppedItemsScan(mining, world())); if (locs.isEmpty()) { logDebug("No locations for " + mining + " known, cancelling"); cancel(); @@ -178,7 +182,30 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro } } - public static List searchWorld(List mining, int max) { + public static List droppedItemsScan(List mining, World world) { + if (!Baritone.settings().mineScanDroppedItems.get()) { + return new ArrayList<>(); + } + Set searchingFor = new HashSet<>(); + for (Block block : mining) { + Item drop = block.getItemDropped(block.getDefaultState(), new Random(), 0); + Item ore = Item.getItemFromBlock(block); + searchingFor.add(drop); + searchingFor.add(ore); + } + List ret = new ArrayList<>(); + for (Entity entity : world.loadedEntityList) { + if (entity instanceof EntityItem) { + EntityItem ei = (EntityItem) entity; + if (searchingFor.contains(ei.getItem().getItem())) { + ret.add(entity.getPosition()); + } + } + } + return ret; + } + + public static List searchWorld(List mining, int max, World world) { List locs = new ArrayList<>(); List uninteresting = new ArrayList<>(); //long b = System.currentTimeMillis(); @@ -198,7 +225,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(uninteresting, max, 10, 26)); //System.out.println("Scan of loaded chunks took " + (System.currentTimeMillis() - before) + "ms"); } - return prune(locs, mining, max); + return prune(locs, mining, max, world); } public void addNearby() { @@ -214,15 +241,16 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro } } } - knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT); + knownOreLocations = prune(knownOreLocations, mining, ORE_LOCATIONS_COUNT, world()); } - public static List prune(List locs2, List mining, int max) { + public static List prune(List locs2, List mining, int max, World world) { + List dropped = droppedItemsScan(mining, world); List locs = locs2 .stream() // remove any that are within loaded chunks that aren't actually what we want - .filter(pos -> Helper.HELPER.world().getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock())) + .filter(pos -> world.getChunk(pos) instanceof EmptyChunk || mining.contains(BlockStateInterface.get(pos).getBlock()) || dropped.contains(pos)) // remove any that are implausible to mine (encased in bedrock, or touching lava) .filter(MineProcess::plausibleToBreak)