BlockOptionalMeta

This commit is contained in:
Logan Darklock 2019-08-30 15:38:15 -07:00
parent 4354d09c20
commit d687e1203a
No known key found for this signature in database
GPG Key ID: B8C37CEDE1AC60EA
19 changed files with 399 additions and 259 deletions

View File

@ -17,7 +17,7 @@
package baritone.api.cache;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.BlockOptionalMetaLookup;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.Block;
import net.minecraft.util.math.BlockPos;
@ -36,26 +36,30 @@ public interface IWorldScanner {
*
* @param ctx The {@link IPlayerContext} containing player and world info that the
* scan is based upon
* @param filter The block filter to scan for
* @param filter The blocks to scan for
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @param maxSearchRadius The maximum chunk search radius
* @return The matching block positions
*/
List<BlockPos> scanChunkRadius(IPlayerContext ctx, IBlockFilter filter, int max, int yLevelThreshold, int maxSearchRadius);
List<BlockPos> scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius);
default List<BlockPos> scanChunkRadius(IPlayerContext ctx, List<Block> filter, int max, int yLevelThreshold, int maxSearchRadius) {
return scanChunkRadius(ctx, new BlockOptionalMetaLookup(filter.toArray(new Block[0])), max, yLevelThreshold, maxSearchRadius);
}
/**
* Scans a single chunk for the specified blocks.
*
* @param ctx The {@link IPlayerContext} containing player and world info that the
* scan is based upon
* @param filter The block filter to scan for
* @param filter The blocks to scan for
* @param pos The position of the target chunk
* @param max The maximum number of blocks to scan before cutoff
* @param yLevelThreshold If a block is found within this Y level, the current result will be
* returned, if the value is negative, then this condition doesn't apply.
* @return The matching block positions
*/
List<BlockPos> scanChunk(IPlayerContext ctx, IBlockFilter filter, ChunkPos pos, int max, int yLevelThreshold);
List<BlockPos> scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold);
}

View File

@ -17,10 +17,12 @@
package baritone.api.process;
import baritone.api.utils.BlockListFilter;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.BlockOptionalMeta;
import baritone.api.utils.BlockOptionalMetaLookup;
import net.minecraft.block.Block;
import java.util.Arrays;
/**
* @author Brady
* @since 9/23/2018
@ -42,16 +44,16 @@ public interface IMineProcess extends IBaritoneProcess {
* are mined. This is based on the first target block to mine.
*
* @param quantity The number of items to get from blocks mined
* @param filter The filter to run blocks through
* @param filter The blocks to mine
*/
void mine(int quantity, IBlockFilter filter);
void mine(int quantity, BlockOptionalMetaLookup filter);
/**
* Begin to search for and mine the specified blocks.
*
* @param filter The filter to run blocks through
* @param filter The blocks to mine
*/
default void mine(IBlockFilter filter) {
default void mine(BlockOptionalMetaLookup filter) {
mine(0, filter);
}
@ -64,6 +66,24 @@ public interface IMineProcess extends IBaritoneProcess {
mineByName(0, blocks);
}
/**
* Begin to search for and mine the specified blocks.
*
* @param boms The blocks to mine
*/
default void mine(int quantity, BlockOptionalMeta... boms) {
mine(quantity, new BlockOptionalMetaLookup(boms));
}
/**
* Begin to search for and mine the specified blocks.
*
* @param boms The blocks to mine
*/
default void mine(BlockOptionalMeta... boms) {
mine(0, boms);
}
/**
* Begin to search for and mine the specified blocks.
*
@ -71,7 +91,11 @@ public interface IMineProcess extends IBaritoneProcess {
* @param blocks The blocks to mine
*/
default void mine(int quantity, Block... blocks) {
mine(quantity, new BlockListFilter(blocks));
mine(quantity, new BlockOptionalMetaLookup(
Arrays.stream(blocks)
.map(BlockOptionalMeta::new)
.toArray(BlockOptionalMeta[]::new)
));
}
/**

View File

@ -1,46 +0,0 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
public class BlockListFilter implements IBlockFilter {
private final List<Block> blocks = new ArrayList<>();
public BlockListFilter(List<Block> blocks) {
this.blocks.addAll(blocks);
}
public BlockListFilter(Block... blocks) {
this.blocks.addAll(Arrays.asList(blocks));
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
return blocks.contains(blockstate.getBlock());
}
@Override
public List<Block> blocks() {
return blocks;
}
@Override
public String toString() {
return String.format(
"BlockListFilter{%s}",
String.join(
",",
blocks.stream()
.map(Block.REGISTRY::getNameForObject)
.map(ResourceLocation::toString)
.toArray(String[]::new)
)
);
}
}

View File

@ -0,0 +1,95 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import javax.annotation.Nullable;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.Objects.isNull;
public final class BlockOptionalMeta {
private final Block block;
private final int meta;
private final boolean noMeta;
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
public BlockOptionalMeta(@Nonnull Block block, @Nullable Integer meta) {
this.block = block;
this.noMeta = isNull(meta);
this.meta = noMeta ? 0 : meta;
}
public BlockOptionalMeta(@Nonnull Block block) {
this(block, null);
}
public BlockOptionalMeta(@Nonnull String selector) {
Matcher matcher = pattern.matcher(selector);
if (!matcher.find()) {
throw new IllegalArgumentException("invalid block selector");
}
MatchResult matchResult = matcher.toMatchResult();
noMeta = matchResult.groupCount() < 2;
ResourceLocation id = new ResourceLocation(matchResult.group(1));
if (!Block.REGISTRY.containsKey(id)) {
throw new IllegalArgumentException("Invalid block ID");
}
block = Block.REGISTRY.getObject(id);
meta = noMeta ? 0 : Integer.parseInt(matchResult.group(2));
}
public Block getBlock() {
return block;
}
public Integer getMeta() {
return meta;
}
public boolean matches(@Nonnull Block block, int meta) {
// & instead of && is intentional
return block == this.block & (noMeta || meta == this.meta);
}
public boolean matches(@Nonnull IBlockState blockstate) {
return matches(blockstate.getBlock(), block.damageDropped(blockstate));
}
@Override
public String toString() {
return String.format("BlockOptionalMeta{block=%s,meta=%s}", block, meta);
}
public static IBlockState blockStateFromStack(ItemStack stack) {
//noinspection deprecation
return Block.getBlockFromItem(stack.getItem()).getStateFromMeta(stack.getMetadata());
}
}

View File

@ -0,0 +1,78 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import org.apache.commons.lang3.ArrayUtils;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Set;
public class BlockOptionalMetaLookup {
private final Map<Block, int[]> lookup = new HashMap<>();
public BlockOptionalMetaLookup() {
}
public BlockOptionalMetaLookup(BlockOptionalMeta... boms) {
put(boms);
}
public BlockOptionalMetaLookup(Block... blocks) {
put(blocks);
}
public BlockOptionalMetaLookup(List<Block> blocks) {
put(blocks);
}
public void put(BlockOptionalMeta bom) {
final int[] metaArr = new int[] {bom.getMeta()};
lookup.compute(bom.getBlock(), (__, arr) -> arr == null ? metaArr : ArrayUtils.addAll(arr, metaArr));
}
public void put(BlockOptionalMeta... boms) {
for (BlockOptionalMeta bom : boms) {
put(bom);
}
}
public void put(Block... blocks) {
for (Block block : blocks) {
put(new BlockOptionalMeta(block));
}
}
public void put(List<Block> blocks) {
for (Block block : blocks) {
put(new BlockOptionalMeta(block));
}
}
public boolean has(Block block) {
return lookup.containsKey(block);
}
public boolean has(IBlockState state) {
Block block = state.getBlock();
int[] arr = lookup.get(block);
if (arr == null) {
return false;
}
int meta = block.damageDropped(state);
for (int value : arr) {
if (value == meta) {
return true;
}
}
return false;
}
public Set<Block> blocks() {
return lookup.keySet();
}
}

View File

@ -1,64 +0,0 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import net.minecraft.item.ItemStack;
import net.minecraft.util.ResourceLocation;
import javax.annotation.Nonnull;
import java.util.Collections;
import java.util.List;
import java.util.regex.MatchResult;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import static java.util.Objects.isNull;
public class BlockSelector implements IBlockFilter {
private final Block block;
private final IBlockState blockstate;
private final int damage;
private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$");
public BlockSelector(@Nonnull String selector) {
Matcher matcher = pattern.matcher(selector);
if (!matcher.find()) {
throw new RuntimeException("invalid block selector");
}
MatchResult matchResult = matcher.toMatchResult();
boolean hasData = matchResult.groupCount() > 1;
ResourceLocation id = new ResourceLocation(matchResult.group(1));
if (!Block.REGISTRY.containsKey(id)) {
throw new IllegalArgumentException("Invalid block ID");
}
block = Block.REGISTRY.getObject(id);
//noinspection deprecation
blockstate = hasData ? block.getStateFromMeta(Integer.parseInt(matchResult.group(2))) : null;
damage = block.damageDropped(blockstate);
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
return blockstate.getBlock() == block && (isNull(this.blockstate) || block.damageDropped(blockstate) == damage);
}
@Override
public List<Block> blocks() {
return Collections.singletonList(block);
}
@Override
public String toString() {
return String.format("BlockSelector{block=%s,blockstate=%s}", block, blockstate);
}
public static IBlockState stateFromItem(ItemStack stack) {
//noinspection deprecation
return Block.getBlockFromItem(stack.getItem()).getStateFromMeta(stack.getMetadata());
}
}

View File

@ -1,50 +0,0 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import javax.annotation.Nonnull;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
import java.util.List;
import java.util.stream.Collectors;
public class CompositeBlockFilter implements IBlockFilter {
private IBlockFilter[] filters;
public CompositeBlockFilter(List<? extends IBlockFilter> filters) {
this.filters = filters.toArray(new IBlockFilter[0]);
}
public CompositeBlockFilter(IBlockFilter... filters) {
this.filters = filters;
}
@Override
public boolean selected(@Nonnull IBlockState blockstate) {
for (IBlockFilter filter : filters) {
if (filter.selected(blockstate)) {
return true;
}
}
return false;
}
@Override
public List<Block> blocks() {
return Arrays.stream(filters)
.map(IBlockFilter::blocks)
.flatMap(Collection::stream)
.collect(Collectors.toCollection(ArrayList::new));
}
@Override
public String toString() {
return String.format(
"CompositeBlockFilter{%s}",
String.join(",", Arrays.stream(filters).map(Object::toString).toArray(String[]::new))
);
}
}

View File

@ -1,22 +0,0 @@
package baritone.api.utils;
import net.minecraft.block.Block;
import net.minecraft.block.state.IBlockState;
import javax.annotation.Nonnull;
import java.util.List;
public interface IBlockFilter {
/**
* @param blockstate The blockstate of the block to test.
* @return If that blockstate passes this filter.
*/
boolean selected(@Nonnull IBlockState blockstate);
/**
* @return A possibly incomplete list of blocks this filter selects. Not all states of each block may be selected,
* and this may not contain all selected blocks, but every block on this list is guaranteed to have a selected
* state.
*/
List<Block> blocks();
}

View File

@ -1,23 +1,23 @@
package baritone.api.utils.command.datatypes;
import baritone.api.utils.BlockSelector;
import baritone.api.utils.BlockOptionalMeta;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.stream.Stream;
public class ForBlockSelector implements IDatatypeFor<BlockSelector> {
public final BlockSelector selector;
public class ForBlockOptionalMeta implements IDatatypeFor<BlockOptionalMeta> {
public final BlockOptionalMeta selector;
public ForBlockSelector() {
public ForBlockOptionalMeta() {
selector = null;
}
public ForBlockSelector(ArgConsumer consumer) {
selector = new BlockSelector(consumer.getString());
public ForBlockOptionalMeta(ArgConsumer consumer) {
selector = new BlockOptionalMeta(consumer.getString());
}
@Override
public BlockSelector get() {
public BlockOptionalMeta get() {
return selector;
}

View File

@ -18,12 +18,10 @@
package baritone.api.utils.command.defaults;
import baritone.api.Settings;
import baritone.api.utils.BlockSelector;
import baritone.api.utils.CompositeBlockFilter;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.BlockOptionalMeta;
import baritone.api.utils.command.Command;
import baritone.api.utils.command.datatypes.BlockById;
import baritone.api.utils.command.datatypes.ForBlockSelector;
import baritone.api.utils.command.datatypes.ForBlockOptionalMeta;
import baritone.api.utils.command.helpers.arguments.ArgConsumer;
import java.util.ArrayList;
@ -41,15 +39,14 @@ public class MineCommand extends Command {
protected void executed(String label, ArgConsumer args, Settings settings) {
int quantity = args.getAsOrDefault(Integer.class, 0);
args.requireMin(1);
List<BlockSelector> selectors = new ArrayList<>();
List<BlockOptionalMeta> boms = new ArrayList<>();
while (args.has()) {
selectors.add(args.getDatatypeFor(ForBlockSelector.class));
boms.add(args.getDatatypeFor(ForBlockOptionalMeta.class));
}
IBlockFilter filter = new CompositeBlockFilter(selectors);
baritone.getMineProcess().mine(quantity, filter);
logDirect(String.format("Mining %s", filter.toString()));
baritone.getMineProcess().mine(quantity, boms.toArray(new BlockOptionalMeta[0]));
logDirect(String.format("Mining %s", boms.toString()));
}
@Override

View File

@ -28,6 +28,7 @@ public class PauseResumeCommands {
public static Command pausedCommand;
static {
// array for mutability, non-field so reflection can't touch it
final boolean[] paused = {false};
BaritoneAPI.getProvider().getPrimaryBaritone().getPathingControlManager().registerProcess(

View File

@ -0,0 +1,62 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import net.minecraft.util.BitArray;
import org.spongepowered.asm.mixin.Final;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Overwrite;
import org.spongepowered.asm.mixin.Shadow;
@Mixin(BitArray.class)
public abstract class MixinBitArray {
@Shadow
@Final
private long[] longArray;
@Shadow
@Final
private int bitsPerEntry;
@Shadow
@Final
private long maxEntryValue;
/**
* why did mojang divide by 64 instead of shifting right by 6 (2^6=64)?
* why did mojang modulo by 64 instead of ANDing with 63?
* also removed validation check
*
* @author LoganDark
*/
@Overwrite
public int getAt(int index) {
final int b = bitsPerEntry;
final int i = index * b;
final int j = i >> 6;
final int l = i & 63;
final int k = ((index + 1) * b - 1) >> 6;
if (j == k) {
return (int) (this.longArray[j] >>> l & maxEntryValue);
} else {
int i1 = 64 - l;
return (int) ((this.longArray[j] >>> l | longArray[k] << i1) & maxEntryValue);
}
}
}

View File

@ -0,0 +1,42 @@
/*
* This file is part of Baritone.
*
* Baritone is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License
* along with Baritone. If not, see <https://www.gnu.org/licenses/>.
*/
package baritone.launch.mixins;
import baritone.utils.accessor.IBlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BitArray;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.IBlockStatePalette;
import org.spongepowered.asm.mixin.Mixin;
import org.spongepowered.asm.mixin.Unique;
import org.spongepowered.asm.mixin.gen.Accessor;
@Mixin(BlockStateContainer.class)
public abstract class MixinBlockStateContainer implements IBlockStateContainer {
@Accessor
public abstract IBlockStatePalette getPalette();
@Accessor
public abstract BitArray getStorage();
@Override
@Unique
public IBlockState getFast(int x, int y, int z) {
return getPalette().getBlockState(getStorage().getAt(y << 8 | z << 4 | x));
}
}

View File

@ -9,7 +9,9 @@
},
"client": [
"MixinAnvilChunkLoader",
"MixinBitArray",
"MixinBlockPos",
"MixinBlockStateContainer",
"MixinChatTabCompleter",
"MixinChunkProviderClient",
"MixinChunkProviderServer",

View File

@ -18,18 +18,21 @@
package baritone.cache;
import baritone.api.cache.IWorldScanner;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.BlockOptionalMetaLookup;
import baritone.api.utils.IPlayerContext;
import net.minecraft.block.Block;
import baritone.utils.accessor.IBlockStateContainer;
import net.minecraft.block.state.IBlockState;
import net.minecraft.client.multiplayer.ChunkProviderClient;
import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.ChunkPos;
import net.minecraft.world.chunk.BlockStateContainer;
import net.minecraft.world.chunk.Chunk;
import net.minecraft.world.chunk.storage.ExtendedBlockStorage;
import java.util.*;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.stream.IntStream;
public enum WorldScanner implements IWorldScanner {
@ -39,7 +42,7 @@ public enum WorldScanner implements IWorldScanner {
private static final int[] DEFAULT_COORDINATE_ITERATION_ORDER = IntStream.range(0, 16).toArray();
@Override
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, IBlockFilter filter, int max, int yLevelThreshold, int maxSearchRadius) {
public List<BlockPos> scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) {
ArrayList<BlockPos> res = new ArrayList<>();
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
@ -86,7 +89,7 @@ public enum WorldScanner implements IWorldScanner {
}
@Override
public List<BlockPos> scanChunk(IPlayerContext ctx, IBlockFilter filter, ChunkPos pos, int max, int yLevelThreshold) {
public List<BlockPos> scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) {
ChunkProviderClient chunkProvider = (ChunkProviderClient) ctx.world().getChunkProvider();
Chunk chunk = chunkProvider.getLoadedChunk(pos.x, pos.z);
int playerY = ctx.playerFeet().getY();
@ -100,7 +103,7 @@ public enum WorldScanner implements IWorldScanner {
return res;
}
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, IBlockFilter filter, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
private boolean scanChunkInto(int chunkX, int chunkZ, Chunk chunk, BlockOptionalMetaLookup filter, Collection<BlockPos> result, int max, int yLevelThreshold, int playerY, int[] coordinateIterationOrder) {
ExtendedBlockStorage[] chunkInternalStorageArray = chunk.getBlockStorageArray();
boolean foundWithinY = false;
for (int yIndex = 0; yIndex < 16; yIndex++) {
@ -110,14 +113,14 @@ public enum WorldScanner implements IWorldScanner {
continue;
}
int yReal = y0 << 4;
BlockStateContainer bsc = extendedblockstorage.getData();
IBlockStateContainer bsc = (IBlockStateContainer) extendedblockstorage.getData();
// the mapping of BlockStateContainer.getIndex from xyz to index is y << 8 | z << 4 | x;
// for better cache locality, iterate in that order
for (int y = 0; y < 16; y++) {
for (int z = 0; z < 16; z++) {
for (int x = 0; x < 16; x++) {
IBlockState state = bsc.get(x, y, z);
if (filter.selected(state)) {
IBlockState state = bsc.getFast(x, y, z);
if (filter.has(state)) {
int yy = yReal | y;
if (result.size() >= max) {
if (Math.abs(yy - playerY) < yLevelThreshold) {

View File

@ -24,7 +24,6 @@ import baritone.api.pathing.goals.GoalComposite;
import baritone.api.process.IFarmProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.BlockListFilter;
import baritone.api.utils.RayTraceUtils;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
@ -181,7 +180,7 @@ public final class FarmProcess extends BaritoneProcessHelper implements IFarmPro
}
if (Baritone.settings().mineGoalUpdateInterval.value != 0 && tickCount++ % Baritone.settings().mineGoalUpdateInterval.value == 0) {
Baritone.getExecutor().execute(() -> locations = WorldScanner.INSTANCE.scanChunkRadius(ctx, new BlockListFilter(scan), 256, 10, 10));
Baritone.getExecutor().execute(() -> locations = WorldScanner.INSTANCE.scanChunkRadius(ctx, scan, 256, 10, 10));
}
if (locations == null) {
return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE);

View File

@ -22,7 +22,7 @@ import baritone.api.pathing.goals.*;
import baritone.api.process.IGetToBlockProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.BlockListFilter;
import baritone.api.utils.BlockOptionalMetaLookup;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
@ -172,7 +172,7 @@ public final class GetToBlockProcess extends BaritoneProcessHelper implements IG
}
private synchronized void rescan(List<BlockPos> known, CalculationContext context) {
List<BlockPos> positions = MineProcess.searchWorld(context, new BlockListFilter(gettingTo), 64, known, blacklist);
List<BlockPos> positions = MineProcess.searchWorld(context, new BlockOptionalMetaLookup(gettingTo), 64, known, blacklist);
positions.removeIf(blacklist::contains);
knownLocations = positions;
}

View File

@ -18,37 +18,42 @@
package baritone.process;
import baritone.Baritone;
import baritone.api.pathing.goals.*;
import baritone.api.pathing.goals.Goal;
import baritone.api.pathing.goals.GoalBlock;
import baritone.api.pathing.goals.GoalComposite;
import baritone.api.pathing.goals.GoalRunAway;
import baritone.api.pathing.goals.GoalTwoBlocks;
import baritone.api.process.IMineProcess;
import baritone.api.process.PathingCommand;
import baritone.api.process.PathingCommandType;
import baritone.api.utils.BlockSelector;
import baritone.api.utils.BlockUtils;
import baritone.api.utils.CompositeBlockFilter;
import baritone.api.utils.IBlockFilter;
import baritone.api.utils.BlockOptionalMeta;
import baritone.api.utils.BlockOptionalMetaLookup;
import baritone.api.utils.IPlayerContext;
import baritone.api.utils.Rotation;
import baritone.api.utils.RotationUtils;
import baritone.api.utils.input.Input;
import baritone.cache.CachedChunk;
import baritone.cache.WorldScanner;
import baritone.pathing.movement.CalculationContext;
import baritone.pathing.movement.MovementHelper;
import baritone.utils.BaritoneProcessHelper;
import baritone.utils.BlockStateInterface;
import net.minecraft.block.Block;
import net.minecraft.block.BlockAir;
import net.minecraft.block.BlockFalling;
import net.minecraft.block.state.IBlockState;
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 java.util.*;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections;
import java.util.Comparator;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
import static baritone.api.pathing.movement.ActionCosts.COST_INF;
@ -59,10 +64,9 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF;
* @author leijurv
*/
public final class MineProcess extends BaritoneProcessHelper implements IMineProcess {
private static final int ORE_LOCATIONS_COUNT = 64;
private IBlockFilter filter;
private BlockOptionalMetaLookup filter;
private List<BlockPos> knownOreLocations;
private List<BlockPos> blacklist; // inaccessible
private BlockPos branchPoint;
@ -83,7 +87,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
public PathingCommand onTick(boolean calcFailed, boolean isSafeToCancel) {
if (desiredQuantity > 0) {
int curr = ctx.player().inventory.mainInventory.stream()
.filter(stack -> filter.selected(BlockSelector.stateFromItem(stack)))
.filter(stack -> filter.has(BlockOptionalMeta.blockStateFromStack(stack)))
.mapToInt(ItemStack::getCount).sum();
System.out.println("Currently have " + curr + " valid items");
if (curr >= desiredQuantity) {
@ -150,7 +154,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
@Override
public void onLostControl() {
mine(0, (IBlockFilter) null);
mine(0, (BlockOptionalMetaLookup) null);
}
@Override
@ -223,7 +227,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
if (Baritone.settings().internalMiningAirException.value && state.getBlock() instanceof BlockAir) {
return true;
}
return filter.selected(state);
return filter.has(state);
}
private Goal coalesce(BlockPos loc, List<BlockPos> locs) {
@ -288,7 +292,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
}
}
public static List<BlockPos> droppedItemsScan(IBlockFilter filter, World world) {
public static List<BlockPos> droppedItemsScan(BlockOptionalMetaLookup filter, World world) {
if (!Baritone.settings().mineScanDroppedItems.value) {
return Collections.emptyList();
}
@ -297,9 +301,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
if (entity instanceof EntityItem) {
EntityItem ei = (EntityItem) entity;
ItemStack stack = ei.getItem();
Item item = stack.getItem();
//noinspection deprecation
if (filter.selected(Block.getBlockFromItem(item).getStateFromMeta(stack.getItemDamage()))) {
if (filter.has(BlockOptionalMeta.blockStateFromStack(stack))) {
ret.add(new BlockPos(entity));
}
}
@ -307,7 +309,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
return ret;
}
public static List<BlockPos> searchWorld(CalculationContext ctx, IBlockFilter filter, int max, List<BlockPos> alreadyKnown, List<BlockPos> blacklist) {
public static List<BlockPos> searchWorld(CalculationContext ctx, BlockOptionalMetaLookup filter, int max, List<BlockPos> alreadyKnown, List<BlockPos> blacklist) {
List<BlockPos> locs = new ArrayList<>();
locs = prune(ctx, locs, filter, max, blacklist);
locs.addAll(WorldScanner.INSTANCE.scanChunkRadius(ctx.getBaritone().getPlayerContext(), filter, max, 10, 32)); // maxSearchRadius is NOT sq
@ -326,7 +328,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
for (int z = playerFeet.getZ() - searchDist; z <= playerFeet.getZ() + searchDist; z++) {
// crucial to only add blocks we can see because otherwise this
// is an x-ray and it'll get caught
if (filter.selected(bsi.get0(x, y, z))) {
if (filter.has(bsi.get0(x, y, z))) {
BlockPos pos = new BlockPos(x, y, z);
if ((Baritone.settings().legitMineIncludeDiagonals.value && knownOreLocations.stream().anyMatch(ore -> ore.distanceSq(pos) <= 2 /* sq means this is pytha dist <= sqrt(2) */)) || RotationUtils.reachable(ctx.player(), pos, fakedBlockReachDistance).isPresent()) {
knownOreLocations.add(pos);
@ -338,11 +340,11 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
knownOreLocations = prune(new CalculationContext(baritone), knownOreLocations, filter, ORE_LOCATIONS_COUNT, blacklist);
}
private static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, IBlockFilter filter, int max, List<BlockPos> blacklist) {
private static List<BlockPos> prune(CalculationContext ctx, List<BlockPos> locs2, BlockOptionalMetaLookup filter, int max, List<BlockPos> blacklist) {
List<BlockPos> dropped = droppedItemsScan(filter, ctx.world);
dropped.removeIf(drop -> {
for (BlockPos pos : locs2) {
if (pos.distanceSq(drop) <= 9 && filter.selected(ctx.get(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx, pos)) { // TODO maybe drop also has to be supported? no lava below?
if (pos.distanceSq(drop) <= 9 && filter.has(ctx.get(pos.getX(), pos.getY(), pos.getZ())) && MineProcess.plausibleToBreak(ctx, pos)) { // TODO maybe drop also has to be supported? no lava below?
return true;
}
}
@ -353,7 +355,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
.distinct()
// remove any that are within loaded chunks that aren't actually what we want
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || filter.selected(ctx.get(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
.filter(pos -> !ctx.bsi.worldContainsLoadedChunk(pos.getX(), pos.getZ()) || filter.has(ctx.get(pos.getX(), pos.getY(), pos.getZ())) || dropped.contains(pos))
// remove any that are implausible to mine (encased in bedrock, or touching lava)
.filter(pos -> MineProcess.plausibleToBreak(ctx, pos))
@ -380,15 +382,15 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro
@Override
public void mineByName(int quantity, String... blocks) {
mine(quantity, new CompositeBlockFilter(
mine(quantity, new BlockOptionalMetaLookup(
Arrays.stream(Objects.requireNonNull(blocks))
.map(BlockSelector::new)
.toArray(IBlockFilter[]::new)
.map(BlockOptionalMeta::new)
.toArray(BlockOptionalMeta[]::new)
));
}
@Override
public void mine(int quantity, IBlockFilter filter) {
public void mine(int quantity, BlockOptionalMetaLookup filter) {
this.filter = filter;
if (filter != null && !Baritone.settings().allowBreak.value) {
logDirect("Unable to mine when allowBreak is false!");

View File

@ -0,0 +1,13 @@
package baritone.utils.accessor;
import net.minecraft.block.state.IBlockState;
import net.minecraft.util.BitArray;
import net.minecraft.world.chunk.IBlockStatePalette;
public interface IBlockStateContainer {
IBlockStatePalette getPalette();
BitArray getStorage();
IBlockState getFast(int x, int y, int z);
}