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.behavior.Behavior;
|
||||
import baritone.chunk.CachedChunk;
|
||||
import baritone.chunk.ChunkPacker;
|
||||
import baritone.chunk.WorldProvider;
|
||||
import baritone.chunk.WorldScanner;
|
||||
import baritone.pathing.goals.Goal;
|
||||
import baritone.pathing.goals.GoalComposite;
|
||||
import baritone.pathing.goals.GoalTwoBlocks;
|
||||
@ -55,21 +57,7 @@ public class MineBehavior extends Behavior {
|
||||
if (mining == null) {
|
||||
return;
|
||||
}
|
||||
List<BlockPos> locs = new ArrayList<>();
|
||||
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);
|
||||
}
|
||||
List<BlockPos> locs = scanFor(mining, 64);
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
cancel();
|
||||
@ -79,6 +67,31 @@ public class MineBehavior extends Behavior {
|
||||
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) {
|
||||
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.entity.Entity;
|
||||
import net.minecraft.util.math.BlockPos;
|
||||
import net.minecraft.world.chunk.EmptyChunk;
|
||||
|
||||
import java.util.*;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
public class ExampleBaritoneControl extends Behavior {
|
||||
public static ExampleBaritoneControl INSTANCE = new ExampleBaritoneControl();
|
||||
@ -188,9 +186,16 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
return;
|
||||
}
|
||||
if (msg.toLowerCase().startsWith("mine")) {
|
||||
String blockType = msg.toLowerCase().substring(4).trim();
|
||||
MineBehavior.INSTANCE.mine(blockType.split(" "));
|
||||
displayChatMessageRaw("Started mining blocks of type " + Arrays.toString(blockType.split(" ")));
|
||||
String[] blockTypes = msg.toLowerCase().substring(4).trim().split(" ");
|
||||
for (String s : blockTypes) {
|
||||
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();
|
||||
return;
|
||||
}
|
||||
@ -235,21 +240,14 @@ public class ExampleBaritoneControl extends Behavior {
|
||||
String mining = waypointType;
|
||||
//displayChatMessageRaw("Not a valid tag. Tags are: " + Arrays.asList(Waypoint.Tag.values()).toString().toLowerCase());
|
||||
event.cancel();
|
||||
List<BlockPos> locs = new ArrayList<>(WorldProvider.INSTANCE.getCurrentWorld().cache.getLocationsOf(mining, 1, 1));
|
||||
if (locs.isEmpty()) {
|
||||
if (ChunkPacker.stringToBlock(mining) == null) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
}
|
||||
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 -> !ChunkPacker.blockToString(BlockStateInterface.get(pos).getBlock()).equalsIgnoreCase(mining))
|
||||
.collect(Collectors.toList()));
|
||||
if (locs.size() > 30) {
|
||||
locs = locs.subList(0, 30);
|
||||
List<BlockPos> locs = MineBehavior.scanFor(Arrays.asList(mining), 64);
|
||||
if (locs.isEmpty()) {
|
||||
displayChatMessageRaw("No locations for " + mining + " known, cancelling");
|
||||
return;
|
||||
}
|
||||
PathingBehavior.INSTANCE.setGoal(new GoalComposite(locs.stream().map(GoalGetToBlock::new).toArray(Goal[]::new)));
|
||||
PathingBehavior.INSTANCE.path();
|
||||
|
Loading…
Reference in New Issue
Block a user