BlockOptionalMeta
This commit is contained in:
parent
4354d09c20
commit
d687e1203a
@ -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);
|
||||
}
|
||||
|
@ -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)
|
||||
));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -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)
|
||||
)
|
||||
);
|
||||
}
|
||||
}
|
95
src/api/java/baritone/api/utils/BlockOptionalMeta.java
Normal file
95
src/api/java/baritone/api/utils/BlockOptionalMeta.java
Normal 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());
|
||||
}
|
||||
}
|
78
src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java
Normal file
78
src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java
Normal 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();
|
||||
}
|
||||
}
|
@ -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());
|
||||
}
|
||||
}
|
@ -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))
|
||||
);
|
||||
}
|
||||
}
|
@ -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();
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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(
|
||||
|
62
src/launch/java/baritone/launch/mixins/MixinBitArray.java
Normal file
62
src/launch/java/baritone/launch/mixins/MixinBitArray.java
Normal 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);
|
||||
}
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
}
|
@ -9,7 +9,9 @@
|
||||
},
|
||||
"client": [
|
||||
"MixinAnvilChunkLoader",
|
||||
"MixinBitArray",
|
||||
"MixinBlockPos",
|
||||
"MixinBlockStateContainer",
|
||||
"MixinChatTabCompleter",
|
||||
"MixinChunkProviderClient",
|
||||
"MixinChunkProviderServer",
|
||||
|
23
src/main/java/baritone/cache/WorldScanner.java
vendored
23
src/main/java/baritone/cache/WorldScanner.java
vendored
@ -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) {
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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!");
|
||||
|
@ -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);
|
||||
}
|
Loading…
Reference in New Issue
Block a user