scan for uninteresting blocks in loaded chunks, fixes #99
This commit is contained in:
parent
0bd3f9f680
commit
7cc23bc89b
@ -19,8 +19,10 @@ package baritone.behavior.impl;
|
|||||||
|
|
||||||
import baritone.api.event.events.TickEvent;
|
import baritone.api.event.events.TickEvent;
|
||||||
import baritone.behavior.Behavior;
|
import baritone.behavior.Behavior;
|
||||||
|
import baritone.chunk.CachedChunk;
|
||||||
import baritone.chunk.ChunkPacker;
|
import baritone.chunk.ChunkPacker;
|
||||||
import baritone.chunk.WorldProvider;
|
import baritone.chunk.WorldProvider;
|
||||||
|
import baritone.chunk.WorldScanner;
|
||||||
import baritone.pathing.goals.Goal;
|
import baritone.pathing.goals.Goal;
|
||||||
import baritone.pathing.goals.GoalComposite;
|
import baritone.pathing.goals.GoalComposite;
|
||||||
import baritone.pathing.goals.GoalTwoBlocks;
|
import baritone.pathing.goals.GoalTwoBlocks;
|
||||||
@ -55,21 +57,7 @@ public class MineBehavior extends Behavior {
|
|||||||
if (mining == null) {
|
if (mining == null) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
List<BlockPos> locs = new ArrayList<>();
|
List<BlockPos> locs = scanFor(mining, 64);
|
||||||
for (String m : mining) {
|
|
||||||
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(m, 1, 1));
|
|
||||||
}
|
|
||||||
BlockPos playerFeet = playerFeet();
|
|
||||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
|
||||||
|
|
||||||
// remove any that are within loaded chunks that aren't actually what we want
|
|
||||||
locs.removeAll(locs.stream()
|
|
||||||
.filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk))
|
|
||||||
.filter(pos -> !mining.contains(ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).toLowerCase()))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
if (locs.size() > 30) {
|
|
||||||
locs = locs.subList(0, 30);
|
|
||||||
}
|
|
||||||
if (locs.isEmpty()) {
|
if (locs.isEmpty()) {
|
||||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||||
cancel();
|
cancel();
|
||||||
@ -79,6 +67,31 @@ public class MineBehavior extends Behavior {
|
|||||||
PathingBehavior.INSTANCE.path();
|
PathingBehavior.INSTANCE.path();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public static List<BlockPos> scanFor(List<String> mining, int max) {
|
||||||
|
List<BlockPos> locs = new ArrayList<>();
|
||||||
|
List<String> uninteresting = new ArrayList<>();
|
||||||
|
for (String m : mining) {
|
||||||
|
if (CachedChunk.BLOCKS_TO_KEEP_TRACK_OF.contains(ChunkPacker.stringToBlock(m))) {
|
||||||
|
locs.addAll(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(m, 1, 1));
|
||||||
|
} else {
|
||||||
|
uninteresting.add(m);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
locs.addAll(WorldScanner.INSTANCE.scanLoadedChunks(uninteresting, max));
|
||||||
|
BlockPos playerFeet = MineBehavior.INSTANCE.playerFeet();
|
||||||
|
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
||||||
|
|
||||||
|
// 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(ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).toLowerCase()))
|
||||||
|
.collect(Collectors.toList()));
|
||||||
|
if (locs.size() > max) {
|
||||||
|
locs = locs.subList(0, max);
|
||||||
|
}
|
||||||
|
return locs;
|
||||||
|
}
|
||||||
|
|
||||||
public void mine(String... mining) {
|
public void mine(String... mining) {
|
||||||
this.mining = mining == null || mining.length == 0 ? null : new ArrayList<>(Arrays.asList(mining));
|
this.mining = mining == null || mining.length == 0 ? null : new ArrayList<>(Arrays.asList(mining));
|
||||||
}
|
}
|
||||||
|
92
src/main/java/baritone/chunk/WorldScanner.java
Normal file
92
src/main/java/baritone/chunk/WorldScanner.java
Normal file
@ -0,0 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of Baritone.
|
||||||
|
*
|
||||||
|
* Baritone is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU 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 General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU General Public License
|
||||||
|
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package baritone.chunk;
|
||||||
|
|
||||||
|
import baritone.utils.Helper;
|
||||||
|
import net.minecraft.block.Block;
|
||||||
|
import net.minecraft.block.state.IBlockState;
|
||||||
|
import net.minecraft.client.multiplayer.ChunkProviderClient;
|
||||||
|
import net.minecraft.util.math.BlockPos;
|
||||||
|
import net.minecraft.world.chunk.BlockStateContainer;
|
||||||
|
import net.minecraft.world.chunk.Chunk;
|
||||||
|
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
|
||||||
|
|
||||||
|
import java.util.LinkedList;
|
||||||
|
import java.util.List;
|
||||||
|
import java.util.stream.Collectors;
|
||||||
|
|
||||||
|
public enum WorldScanner implements Helper {
|
||||||
|
INSTANCE;
|
||||||
|
|
||||||
|
public List<BlockPos> scanLoadedChunks(List<String> blockTypes, int max) {
|
||||||
|
List<Block> asBlocks = blockTypes.stream().map(ChunkPacker::stringToBlock).collect(Collectors.toList());
|
||||||
|
if (asBlocks.contains(null)) {
|
||||||
|
throw new IllegalStateException("Invalid block name should have been caught earlier: " + blockTypes.toString());
|
||||||
|
}
|
||||||
|
LinkedList<BlockPos> res = new LinkedList<>();
|
||||||
|
ChunkProviderClient chunkProvider = world().getChunkProvider();
|
||||||
|
|
||||||
|
int playerChunkX = playerFeet().getX() >> 4;
|
||||||
|
int playerChunkZ = playerFeet().getZ() >> 4;
|
||||||
|
|
||||||
|
int searchRadius = 0;
|
||||||
|
while (true) {
|
||||||
|
boolean allUnloaded = true;
|
||||||
|
for (int xoff = -searchRadius; xoff <= searchRadius; xoff++) {
|
||||||
|
for (int zoff = -searchRadius; zoff <= searchRadius; zoff++) {
|
||||||
|
int distance = xoff * xoff + zoff * zoff;
|
||||||
|
if (distance != searchRadius) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int chunkX = xoff + playerChunkX;
|
||||||
|
int chunkZ = zoff + playerChunkZ;
|
||||||
|
Chunk chunk = chunkProvider.getLoadedChunk(chunkX, chunkZ);
|
||||||
|
if (chunk == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
allUnloaded = false;
|
||||||
|
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
|
||||||
|
for (int y0 = 0; y0 < 16; y0++) {
|
||||||
|
ExtendedBlockStorage extendedblockstorage = chunkInternalStorageArray[y0];
|
||||||
|
if (extendedblockstorage == null) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
BlockStateContainer bsc = extendedblockstorage.getData();
|
||||||
|
for (int x = 0; x < 16; x++) {
|
||||||
|
for (int y = 0; y < 16; y++) {
|
||||||
|
for (int z = 0; z < 16; z++) {
|
||||||
|
IBlockState state = bsc.get(x, y, z);
|
||||||
|
if (asBlocks.contains(state.getBlock())) {
|
||||||
|
res.add(new BlockPos(chunkX * 16 + x, y0 * 16 + y, chunkZ * 16 + z));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (allUnloaded) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
if (res.size() >= max) {
|
||||||
|
return res;
|
||||||
|
}
|
||||||
|
searchRadius++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -38,10 +38,8 @@ import baritone.utils.pathing.BetterBlockPos;
|
|||||||
import net.minecraft.block.Block;
|
import net.minecraft.block.Block;
|
||||||
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.world.chunk.EmptyChunk;
|
|
||||||
|
|
||||||
import java.util.*;
|
import java.util.*;
|
||||||
import java.util.stream.Collectors;
|
|
||||||
|
|
||||||
public class ExampleBaritoneControl extends Behavior {
|
public class ExampleBaritoneControl extends Behavior {
|
||||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||||
@ -188,9 +186,16 @@ public class ExampleBaritoneControl extends Behavior {
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (msg.toLowerCase().startsWith("mine")) {
|
if (msg.toLowerCase().startsWith("mine")) {
|
||||||
String blockType = msg.toLowerCase().substring(4).trim();
|
String[] blockTypes = msg.toLowerCase().substring(4).trim().split(" ");
|
||||||
MineBehavior.INSTANCE.mine(blockType.split(" "));
|
for (String s : blockTypes) {
|
||||||
displayChatMessageRaw("Started mining blocks of type " + Arrays.toString(blockType.split(" ")));
|
if (ChunkPacker.stringToBlock(s) == null) {
|
||||||
|
displayChatMessageRaw(s + " isn't a valid block name");
|
||||||
|
event.cancel();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
MineBehavior.INSTANCE.mine(blockTypes);
|
||||||
|
displayChatMessageRaw("Started mining blocks of type " + Arrays.toString(blockTypes));
|
||||||
event.cancel();
|
event.cancel();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -235,21 +240,14 @@ public class ExampleBaritoneControl extends Behavior {
|
|||||||
String mining = waypointType;
|
String mining = waypointType;
|
||||||
//displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
//displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||||
event.cancel();
|
event.cancel();
|
||||||
List<BlockPos> locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(mining, 1, 1));
|
if (ChunkPacker.stringToBlock(mining) == null) {
|
||||||
if (locs.isEmpty()) {
|
|
||||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
BlockPos playerFeet = playerFeet();
|
List<BlockPos> locs = MineBehavior.scanFor(Arrays.asList(mining), 64);
|
||||||
locs.sort(Comparator.comparingDouble(playerFeet::distanceSq));
|
if (locs.isEmpty()) {
|
||||||
|
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||||
// remove any that are within loaded chunks that aren't actually what we want
|
return;
|
||||||
locs.removeAll(locs.stream()
|
|
||||||
.filter(pos -> !(world().getChunk(pos) instanceof EmptyChunk))
|
|
||||||
.filter(pos -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(mining))
|
|
||||||
.collect(Collectors.toList()));
|
|
||||||
if (locs.size() > 30) {
|
|
||||||
locs = locs.subList(0, 30);
|
|
||||||
}
|
}
|
||||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||||
PathingBehavior.INSTANCE.path();
|
PathingBehavior.INSTANCE.path();
|
||||||
|
Loading…
Reference in New Issue
Block a user