From 1736f2ffc7c92eff5cd117ee7a9c0cb78207dce1 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 23 Dec 2022 16:34:49 -0700 Subject: [PATCH 01/17] replace the world scanner with a 500x faster one --- .../baritone/launch/mixins/MixinBitArray.java | 10 + .../mixins/MixinBlockStateContainer.java | 10 + src/main/java/baritone/BaritoneProvider.java | 3 +- .../baritone/cache/FasterWorldScanner.java | 270 ++++++++++++++++++ .../command/defaults/MineCommand.java | 3 +- .../command/defaults/PathCommand.java | 3 +- .../command/defaults/RepackCommand.java | 3 +- .../java/baritone/process/FarmProcess.java | 3 +- .../java/baritone/process/MineProcess.java | 3 +- .../baritone/utils/accessor/IBitArray.java | 4 + .../utils/accessor/IBlockStateContainer.java | 6 + 11 files changed, 312 insertions(+), 6 deletions(-) create mode 100644 src/main/java/baritone/cache/FasterWorldScanner.java diff --git a/src/launch/java/baritone/launch/mixins/MixinBitArray.java b/src/launch/java/baritone/launch/mixins/MixinBitArray.java index bece3e3bf..bf7d9e535 100644 --- a/src/launch/java/baritone/launch/mixins/MixinBitArray.java +++ b/src/launch/java/baritone/launch/mixins/MixinBitArray.java @@ -64,4 +64,14 @@ public abstract class MixinBitArray implements IBitArray { return out; } + + @Override + public long getMaxEntryValue() { + return maxEntryValue; + } + + @Override + public int getBitsPerEntry() { + return bitsPerEntry; + } } diff --git a/src/launch/java/baritone/launch/mixins/MixinBlockStateContainer.java b/src/launch/java/baritone/launch/mixins/MixinBlockStateContainer.java index f1cc28b9f..566c3cf8b 100644 --- a/src/launch/java/baritone/launch/mixins/MixinBlockStateContainer.java +++ b/src/launch/java/baritone/launch/mixins/MixinBlockStateContainer.java @@ -35,6 +35,16 @@ public abstract class MixinBlockStateContainer implements IBlockStateContainer { @Shadow protected IBlockStatePalette palette; + @Override + public IBlockStatePalette getPalette() { + return palette; + } + + @Override + public BitArray getStorage() { + return storage; + } + @Override public IBlockState getAtPalette(int index) { return palette.getBlockState(index); diff --git a/src/main/java/baritone/BaritoneProvider.java b/src/main/java/baritone/BaritoneProvider.java index d5457cf85..c49c02e10 100644 --- a/src/main/java/baritone/BaritoneProvider.java +++ b/src/main/java/baritone/BaritoneProvider.java @@ -22,6 +22,7 @@ import baritone.api.IBaritoneProvider; import baritone.api.cache.IWorldScanner; import baritone.api.command.ICommandSystem; import baritone.api.schematic.ISchematicSystem; +import baritone.cache.FasterWorldScanner; import baritone.cache.WorldScanner; import baritone.command.CommandSystem; import baritone.command.ExampleBaritoneControl; @@ -59,7 +60,7 @@ public final class BaritoneProvider implements IBaritoneProvider { @Override public IWorldScanner getWorldScanner() { - return WorldScanner.INSTANCE; + return FasterWorldScanner.INSTANCE; } @Override diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java new file mode 100644 index 000000000..f1829f9f0 --- /dev/null +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -0,0 +1,270 @@ +/* + * 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 . + */ + +package baritone.cache; + +import baritone.api.cache.ICachedWorld; +import baritone.api.cache.IWorldScanner; +import baritone.api.utils.BetterBlockPos; +import baritone.api.utils.BlockOptionalMetaLookup; +import baritone.api.utils.IPlayerContext; +import baritone.utils.accessor.IBitArray; +import baritone.utils.accessor.IBlockStateContainer; +import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; +import net.minecraft.block.Block; +import net.minecraft.block.state.IBlockState; +import net.minecraft.network.PacketBuffer; +import net.minecraft.util.BitArray; +import net.minecraft.util.math.BlockPos; +import net.minecraft.util.math.ChunkPos; +import net.minecraft.world.chunk.*; +import net.minecraft.world.chunk.storage.ExtendedBlockStorage; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.concurrent.ConcurrentHashMap; +import java.util.function.BiConsumer; +import java.util.function.IntConsumer; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +public enum FasterWorldScanner implements IWorldScanner { + INSTANCE; + @Override + public List scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) { + return new WorldScannerContext(filter, ctx).scanAroundPlayerRange(maxSearchRadius); + } + + @Override + public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) { + return new WorldScannerContext(filter, ctx).scanAroundPlayerUntilCount(max); + } + + @Override + public int repack(IPlayerContext ctx) { + return this.repack(ctx, 40); + } + + @Override + public int repack(IPlayerContext ctx, int range) { + IChunkProvider chunkProvider = ctx.world().getChunkProvider(); + ICachedWorld cachedWorld = ctx.worldData().getCachedWorld(); + + BetterBlockPos playerPos = ctx.playerFeet(); + + int playerChunkX = playerPos.getX() >> 4; + int playerChunkZ = playerPos.getZ() >> 4; + + int minX = playerChunkX - range; + int minZ = playerChunkZ - range; + int maxX = playerChunkX + range; + int maxZ = playerChunkZ + range; + + int queued = 0; + for (int x = minX; x <= maxX; x++) { + for (int z = minZ; z <= maxZ; z++) { + Chunk chunk = chunkProvider.getLoadedChunk(x, z); + + if (chunk != null && !chunk.isEmpty()) { + queued++; + cachedWorld.queueForPacking(chunk); + } + } + } + + return queued; + } + + // for porting, see {@link https://github.com/JsMacros/JsMacros/blob/backport-1.12.2/common/src/main/java/xyz/wagyourtail/jsmacros/client/api/classes/worldscanner/WorldScanner.java} + public static class WorldScannerContext { + private final BlockOptionalMetaLookup filter; + private final IPlayerContext ctx; + private final Map cachedFilter = new ConcurrentHashMap<>(); + + public WorldScannerContext(BlockOptionalMetaLookup filter, IPlayerContext ctx) { + this.filter = filter; + this.ctx = ctx; + } + + public List getChunkRange(int centerX, int centerZ, int chunkrange) { + List chunks = new ArrayList<>(); + for (int x = centerX - chunkrange; x <= centerX + chunkrange; x++) { + for (int z = centerZ - chunkrange; z <= centerZ + chunkrange; z++) { + chunks.add(new ChunkPos(x, z)); + } + } + return chunks; + } + + public List scanAroundPlayerRange(int range) { + return scanAroundPlayer(range, -1); + } + + public List scanAroundPlayerUntilCount(int count) { + return scanAroundPlayer(32, count); + } + + public List scanAroundPlayer(int range, int maxCount) { + assert ctx.player() != null; + return scanChunkRange(ctx.playerFeet().x >> 4, ctx.playerFeet().z >> 4, range, maxCount); + } + + public List scanChunkRange(int centerX, int centerZ, int chunkRange, int maxBlocks) { + assert ctx.world() != null; + if (chunkRange < 0) { + throw new IllegalArgumentException("chunkRange must be >= 0"); + } + return scanChunksInternal(getChunkRange(centerX, centerZ, chunkRange), maxBlocks); + } + + private List scanChunksInternal(List chunkPositions, int maxBlocks) { + assert ctx.world() != null; + return chunkPositions.parallelStream().flatMap(this::scanChunkInternal).limit(maxBlocks <= 0 ? Long.MAX_VALUE : maxBlocks).collect(Collectors.toList()); + } + private Stream scanChunkInternal(ChunkPos pos) { + IChunkProvider chunkProvider = ctx.world().getChunkProvider(); + // if chunk is not loaded, return empty stream + if (!chunkProvider.isChunkGeneratedAt(pos.x, pos.z)) { + return Stream.empty(); + } + + long chunkX = (long) pos.x << 4; + long chunkZ = (long) pos.z << 4; + + List blocks = new ArrayList<>(); + + streamChunkSections(chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { + int yOffset = section.getYLocation(); + BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); + forEach(array, isInFilter, place -> blocks.add(new BlockPos( + chunkX + ((place & 255) & 15), + yOffset + (place >> 8), + chunkZ + ((place & 255) >> 4) + ))); + }); + return blocks.stream(); + } + + private void streamChunkSections(Chunk chunk, BiConsumer consumer) { + for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { + if (section == null || section.isEmpty()) { + continue; + } + + BlockStateContainer sectionContainer = section.getData(); + //this won't work if the PaletteStorage is of the type EmptyPaletteStorage + if (((IBlockStateContainer) sectionContainer).getStorage() == null) { + continue; + } + + boolean[] isInFilter = getIncludedFilterIndices(((IBlockStateContainer) sectionContainer).getPalette()); + if (isInFilter.length == 0) { + continue; + } + consumer.accept(section, isInFilter); + } + } + + private boolean getFilterResult(IBlockState state) { + Boolean v; + return (v = cachedFilter.get(state)) == null ? addCachedState(state) : v; + } + + private boolean addCachedState(IBlockState state) { + boolean isInFilter = false; + + if (filter != null) { + isInFilter = filter.has(state); + } + + cachedFilter.put(state, isInFilter); + return isInFilter; + } + + private boolean[] getIncludedFilterIndices(IBlockStatePalette palette) { + boolean commonBlockFound = false; + Int2ObjectOpenHashMap paletteMap = getPalette(palette); + int size = paletteMap.size(); + + boolean[] isInFilter = new boolean[size]; + + for (int i = 0; i < size; i++) { + IBlockState state = paletteMap.get(i); + if (getFilterResult(state)) { + isInFilter[i] = true; + commonBlockFound = true; + } else { + isInFilter[i] = false; + } + } + + if (!commonBlockFound) { + return new boolean[0]; + } + return isInFilter; + } + + private static void forEach(BitArray array, boolean[] isInFilter, IntConsumer action) { + int counter = 0; + long[] storage = array.getBackingLongArray(); + int arraySize = array.size(); + int elementBits = ((IBitArray) array).getBitsPerEntry(); + long maxValue = ((IBitArray) array).getMaxEntryValue(); + int storageLength = storage.length; + + if (storageLength != 0) { + int lastStorageIdx = 0; + long row = storage[0]; + long nextRow = storageLength > 1 ? storage[1] : 0L; + + for (int idx = 0; idx < arraySize; idx++) { + int n = idx * elementBits; + int storageIdx = n >> 6; + int p = (idx + 1) * elementBits - 1 >> 6; + int q = n ^ storageIdx << 6; + if (storageIdx != lastStorageIdx) { + row = nextRow; + nextRow = storageIdx + 1 < storageLength ? storage[storageIdx + 1] : 0L; + lastStorageIdx = storageIdx; + } + if (storageIdx == p) { + if (isInFilter[(int) (row >>> q & maxValue)]) { + action.accept(counter); + } else { + if (isInFilter[(int) ((row >>> q | nextRow << (64 - q)) & maxValue)]) { + action.accept(counter); + } + } + } + } + } + } + + private static Int2ObjectOpenHashMap getPalette(IBlockStatePalette palette) { + PacketBuffer buf = new PacketBuffer(Unpooled.buffer()); + palette.write(buf); + int size = buf.readVarInt(); + Int2ObjectOpenHashMap paletteMap = new Int2ObjectOpenHashMap<>(size); + for (int i = 0; i < size; i++) { + paletteMap.put(i, Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt())); + } + return paletteMap; + } + } +} diff --git a/src/main/java/baritone/command/defaults/MineCommand.java b/src/main/java/baritone/command/defaults/MineCommand.java index 63712fe3e..1ab5c3321 100644 --- a/src/main/java/baritone/command/defaults/MineCommand.java +++ b/src/main/java/baritone/command/defaults/MineCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; @@ -45,7 +46,7 @@ public class MineCommand extends Command { while (args.hasAny()) { boms.add(args.getDatatypeFor(ForBlockOptionalMeta.INSTANCE)); } - WorldScanner.INSTANCE.repack(ctx); + BaritoneAPI.getProvider().getWorldScanner().repack(ctx); logDirect(String.format("Mining %s", boms.toString())); baritone.getMineProcess().mine(quantity, boms.toArray(new BlockOptionalMeta[0])); } diff --git a/src/main/java/baritone/command/defaults/PathCommand.java b/src/main/java/baritone/command/defaults/PathCommand.java index 182a1e5bc..24f47d625 100644 --- a/src/main/java/baritone/command/defaults/PathCommand.java +++ b/src/main/java/baritone/command/defaults/PathCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; @@ -38,7 +39,7 @@ public class PathCommand extends Command { public void execute(String label, IArgConsumer args) throws CommandException { ICustomGoalProcess customGoalProcess = baritone.getCustomGoalProcess(); args.requireMax(0); - WorldScanner.INSTANCE.repack(ctx); + BaritoneAPI.getProvider().getWorldScanner().repack(ctx); customGoalProcess.path(); logDirect("Now pathing"); } diff --git a/src/main/java/baritone/command/defaults/RepackCommand.java b/src/main/java/baritone/command/defaults/RepackCommand.java index cafbea524..cd054b10b 100644 --- a/src/main/java/baritone/command/defaults/RepackCommand.java +++ b/src/main/java/baritone/command/defaults/RepackCommand.java @@ -17,6 +17,7 @@ package baritone.command.defaults; +import baritone.api.BaritoneAPI; import baritone.api.IBaritone; import baritone.api.command.Command; import baritone.api.command.argument.IArgConsumer; @@ -36,7 +37,7 @@ public class RepackCommand extends Command { @Override public void execute(String label, IArgConsumer args) throws CommandException { args.requireMax(0); - logDirect(String.format("Queued %d chunks for repacking", WorldScanner.INSTANCE.repack(ctx))); + logDirect(String.format("Queued %d chunks for repacking", BaritoneAPI.getProvider().getWorldScanner().repack(ctx))); } @Override diff --git a/src/main/java/baritone/process/FarmProcess.java b/src/main/java/baritone/process/FarmProcess.java index 0ef85f07d..73c575d22 100644 --- a/src/main/java/baritone/process/FarmProcess.java +++ b/src/main/java/baritone/process/FarmProcess.java @@ -18,6 +18,7 @@ package baritone.process; import baritone.Baritone; +import baritone.api.BaritoneAPI; import baritone.api.pathing.goals.Goal; import baritone.api.pathing.goals.GoalBlock; import baritone.api.pathing.goals.GoalComposite; @@ -189,7 +190,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, scan, 256, 10, 10)); + Baritone.getExecutor().execute(() -> locations = BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius(ctx, scan, 256, 10, 10)); } if (locations == null) { return new PathingCommand(null, PathingCommandType.REQUEST_PAUSE); diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 1ec47cd92..a10a569aa 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -18,6 +18,7 @@ package baritone.process; import baritone.Baritone; +import baritone.api.BaritoneAPI; import baritone.api.pathing.goals.*; import baritone.api.process.IMineProcess; import baritone.api.process.PathingCommand; @@ -355,7 +356,7 @@ public final class MineProcess extends BaritoneProcessHelper implements IMinePro locs = prune(ctx, locs, filter, max, blacklist, dropped); if (!untracked.isEmpty() || (Baritone.settings().extendCacheOnThreshold.value && locs.size() < max)) { - locs.addAll(WorldScanner.INSTANCE.scanChunkRadius( + locs.addAll(BaritoneAPI.getProvider().getWorldScanner().scanChunkRadius( ctx.getBaritone().getPlayerContext(), filter, max, diff --git a/src/main/java/baritone/utils/accessor/IBitArray.java b/src/main/java/baritone/utils/accessor/IBitArray.java index baea5c1da..08f54584c 100644 --- a/src/main/java/baritone/utils/accessor/IBitArray.java +++ b/src/main/java/baritone/utils/accessor/IBitArray.java @@ -3,4 +3,8 @@ package baritone.utils.accessor; public interface IBitArray { int[] toArray(); + + long getMaxEntryValue(); + + int getBitsPerEntry(); } diff --git a/src/main/java/baritone/utils/accessor/IBlockStateContainer.java b/src/main/java/baritone/utils/accessor/IBlockStateContainer.java index 39572fc5d..bd280aeb1 100644 --- a/src/main/java/baritone/utils/accessor/IBlockStateContainer.java +++ b/src/main/java/baritone/utils/accessor/IBlockStateContainer.java @@ -1,9 +1,15 @@ 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 getAtPalette(int index); int[] storageArray(); From 0b6088cd2df5ee5a099ec7a63fa00ad0378d0c6a Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 23 Dec 2022 16:58:10 -0700 Subject: [PATCH 02/17] fix getting the block from the pallete, and change the chunk scan order to spiral out --- .../baritone/cache/FasterWorldScanner.java | 62 ++++++++++--------- 1 file changed, 33 insertions(+), 29 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index f1829f9f0..189374dd6 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -102,12 +102,27 @@ public enum FasterWorldScanner implements IWorldScanner { this.ctx = ctx; } - public List getChunkRange(int centerX, int centerZ, int chunkrange) { + public List getChunkRange(int centerX, int centerZ, int chunkRadius) { List chunks = new ArrayList<>(); - for (int x = centerX - chunkrange; x <= centerX + chunkrange; x++) { - for (int z = centerZ - chunkrange; z <= centerZ + chunkrange; z++) { + // spiral out + int x = centerX; + int z = centerZ; + int dx = 0; + int dz = -1; + int t = Math.max(chunkRadius, 1); + int maxI = t * t; + for (int i = 0; i < maxI; i++) { + if ((-chunkRadius / 2 <= x) && (x <= chunkRadius / 2) && (-chunkRadius / 2 <= z) && (z <= chunkRadius / 2)) { chunks.add(new ChunkPos(x, z)); } + // idk how this works, copilot did it + if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) { + t = dx; + dx = -dz; + dz = t; + } + x += dx; + z += dz; } return chunks; } @@ -221,36 +236,25 @@ public enum FasterWorldScanner implements IWorldScanner { } private static void forEach(BitArray array, boolean[] isInFilter, IntConsumer action) { - int counter = 0; - long[] storage = array.getBackingLongArray(); + long[] longArray = array.getBackingLongArray(); int arraySize = array.size(); - int elementBits = ((IBitArray) array).getBitsPerEntry(); - long maxValue = ((IBitArray) array).getMaxEntryValue(); - int storageLength = storage.length; + int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); + long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); - if (storageLength != 0) { - int lastStorageIdx = 0; - long row = storage[0]; - long nextRow = storageLength > 1 ? storage[1] : 0L; + for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { + final int i = idx * bitsPerEntry; + final int j = i >> 6; + final int l = i & 63; + final int k = kl >> 6; + final long jl = longArray[j] >>> l; - for (int idx = 0; idx < arraySize; idx++) { - int n = idx * elementBits; - int storageIdx = n >> 6; - int p = (idx + 1) * elementBits - 1 >> 6; - int q = n ^ storageIdx << 6; - if (storageIdx != lastStorageIdx) { - row = nextRow; - nextRow = storageIdx + 1 < storageLength ? storage[storageIdx + 1] : 0L; - lastStorageIdx = storageIdx; + if (j == k) { + if (isInFilter[(int) (jl & maxEntryValue)]) { + action.accept(idx); } - if (storageIdx == p) { - if (isInFilter[(int) (row >>> q & maxValue)]) { - action.accept(counter); - } else { - if (isInFilter[(int) ((row >>> q | nextRow << (64 - q)) & maxValue)]) { - action.accept(counter); - } - } + } else { + if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) { + action.accept(idx); } } } From 12b596e53696212515087f458167775d45d12a85 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 23 Dec 2022 17:10:37 -0700 Subject: [PATCH 03/17] fix spiral --- .../baritone/cache/FasterWorldScanner.java | 24 +++++++------------ 1 file changed, 8 insertions(+), 16 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 189374dd6..ce4a8cd48 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -105,24 +105,16 @@ public enum FasterWorldScanner implements IWorldScanner { public List getChunkRange(int centerX, int centerZ, int chunkRadius) { List chunks = new ArrayList<>(); // spiral out - int x = centerX; - int z = centerZ; - int dx = 0; - int dz = -1; - int t = Math.max(chunkRadius, 1); - int maxI = t * t; - for (int i = 0; i < maxI; i++) { - if ((-chunkRadius / 2 <= x) && (x <= chunkRadius / 2) && (-chunkRadius / 2 <= z) && (z <= chunkRadius / 2)) { - chunks.add(new ChunkPos(x, z)); + chunks.add(new ChunkPos(centerX, centerZ)); + for (int i = 1; i < chunkRadius; i++) { + for (int x = centerX - i; x <= centerX + i; x++) { + chunks.add(new ChunkPos(x, centerZ - i)); + chunks.add(new ChunkPos(x, centerZ + i)); } - // idk how this works, copilot did it - if ((x == z) || ((x < 0) && (x == -z)) || ((x > 0) && (x == 1 - z))) { - t = dx; - dx = -dz; - dz = t; + for (int z = centerZ - i + 1; z <= centerZ + i - 1; z++) { + chunks.add(new ChunkPos(centerX - i, z)); + chunks.add(new ChunkPos(centerX + i, z)); } - x += dx; - z += dz; } return chunks; } From 0ae59755e3ade3f576d4e83ae9b4b5abef542b75 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 23 Dec 2022 17:25:23 -0700 Subject: [PATCH 04/17] make limit not happen if it shouldn't --- .../baritone/cache/FasterWorldScanner.java | 44 ++++++++++++++----- 1 file changed, 33 insertions(+), 11 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index ce4a8cd48..535e925e1 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -30,6 +30,7 @@ import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.network.PacketBuffer; import net.minecraft.util.BitArray; +import net.minecraft.util.ObjectIntIdentityMap; import net.minecraft.util.math.BlockPos; import net.minecraft.util.math.ChunkPos; import net.minecraft.world.chunk.*; @@ -142,8 +143,20 @@ public enum FasterWorldScanner implements IWorldScanner { private List scanChunksInternal(List chunkPositions, int maxBlocks) { assert ctx.world() != null; - return chunkPositions.parallelStream().flatMap(this::scanChunkInternal).limit(maxBlocks <= 0 ? Long.MAX_VALUE : maxBlocks).collect(Collectors.toList()); + try { + Stream posStream = chunkPositions.parallelStream().flatMap(this::scanChunkInternal); + if (maxBlocks >= 0) { + // WARNING: this can be expensive if maxBlocks is large... + // see limit's javadoc + posStream = posStream.limit(maxBlocks); + } + return posStream.collect(Collectors.toList()); + } catch (Exception e) { + e.printStackTrace(); + throw e; + } } + private Stream scanChunkInternal(ChunkPos pos) { IChunkProvider chunkProvider = ctx.world().getChunkProvider(); // if chunk is not loaded, return empty stream @@ -206,13 +219,13 @@ public enum FasterWorldScanner implements IWorldScanner { private boolean[] getIncludedFilterIndices(IBlockStatePalette palette) { boolean commonBlockFound = false; - Int2ObjectOpenHashMap paletteMap = getPalette(palette); + ObjectIntIdentityMap paletteMap = getPalette(palette); int size = paletteMap.size(); boolean[] isInFilter = new boolean[size]; for (int i = 0; i < size; i++) { - IBlockState state = paletteMap.get(i); + IBlockState state = paletteMap.getByValue(i); if (getFilterResult(state)) { isInFilter[i] = true; commonBlockFound = true; @@ -252,15 +265,24 @@ public enum FasterWorldScanner implements IWorldScanner { } } - private static Int2ObjectOpenHashMap getPalette(IBlockStatePalette palette) { - PacketBuffer buf = new PacketBuffer(Unpooled.buffer()); - palette.write(buf); - int size = buf.readVarInt(); - Int2ObjectOpenHashMap paletteMap = new Int2ObjectOpenHashMap<>(size); - for (int i = 0; i < size; i++) { - paletteMap.put(i, Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt())); + /** + * cheats to get the actual map of id -> blockstate from the various palette implementations + */ + private static ObjectIntIdentityMap getPalette(IBlockStatePalette palette) { + if (palette instanceof BlockStatePaletteRegistry) { + return Block.BLOCK_STATE_IDS; + } else { + PacketBuffer buf = new PacketBuffer(Unpooled.buffer()); + palette.write(buf); + int size = buf.readVarInt(); + ObjectIntIdentityMap states = new ObjectIntIdentityMap<>(); + for (int i = 0; i < size; i++) { + IBlockState state = Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt()); + assert state != null; + states.put(state, i); + } + return states; } - return paletteMap; } } } From 96f432d2d550ca92a8e96c66981696a62bb628b1 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 23 Dec 2022 17:26:46 -0700 Subject: [PATCH 05/17] add comment --- src/main/java/baritone/cache/FasterWorldScanner.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 535e925e1..6c110decb 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -93,6 +93,7 @@ public enum FasterWorldScanner implements IWorldScanner { } // for porting, see {@link https://github.com/JsMacros/JsMacros/blob/backport-1.12.2/common/src/main/java/xyz/wagyourtail/jsmacros/client/api/classes/worldscanner/WorldScanner.java} + // tho I did change some things... public static class WorldScannerContext { private final BlockOptionalMetaLookup filter; private final IPlayerContext ctx; From ecdec87e7a7a8107eefe20a7797decf4ad1e7972 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 24 Dec 2022 11:43:54 -0700 Subject: [PATCH 06/17] fix using wrong functions in scan --- src/main/java/baritone/cache/FasterWorldScanner.java | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 6c110decb..ace429de9 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -25,7 +25,6 @@ import baritone.api.utils.IPlayerContext; import baritone.utils.accessor.IBitArray; import baritone.utils.accessor.IBlockStateContainer; import io.netty.buffer.Unpooled; -import it.unimi.dsi.fastutil.ints.Int2ObjectOpenHashMap; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.network.PacketBuffer; @@ -49,12 +48,12 @@ public enum FasterWorldScanner implements IWorldScanner { INSTANCE; @Override public List scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) { - return new WorldScannerContext(filter, ctx).scanAroundPlayerRange(maxSearchRadius); + return new WorldScannerContext(filter, ctx).scanAroundPlayer(maxSearchRadius, max); } @Override public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) { - return new WorldScannerContext(filter, ctx).scanAroundPlayerUntilCount(max); + return new WorldScannerContext(filter, ctx).scanChunkInternal(pos).collect(Collectors.toList()); } @Override From ce1fb49252e897f0b223e1bbdc18bb096ac56678 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 24 Dec 2022 11:52:48 -0700 Subject: [PATCH 07/17] spiral always pick closest chunk first now --- .../baritone/cache/FasterWorldScanner.java | 42 ++++++++++--------- 1 file changed, 23 insertions(+), 19 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index ace429de9..efb80245a 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -91,34 +91,38 @@ public enum FasterWorldScanner implements IWorldScanner { return queued; } - // for porting, see {@link https://github.com/JsMacros/JsMacros/blob/backport-1.12.2/common/src/main/java/xyz/wagyourtail/jsmacros/client/api/classes/worldscanner/WorldScanner.java} - // tho I did change some things... + // ordered in a way that the closest blocks are generally first + public List getChunkRange(int centerX, int centerZ, int chunkRadius) { + List chunks = new ArrayList<>(); + // spiral out + chunks.add(new ChunkPos(centerX, centerZ)); + for (int i = 1; i < chunkRadius; i++) { + for (int j = 0; j <= i; j++) { + chunks.add(new ChunkPos(centerX - j, centerZ - i)); + chunks.add(new ChunkPos(centerX + j, centerZ - i)); + chunks.add(new ChunkPos(centerX - j, centerZ + i)); + chunks.add(new ChunkPos(centerX + j, centerZ + i)); + if (j != 0 && j != i) { + chunks.add(new ChunkPos(centerX - i, centerZ - j)); + chunks.add(new ChunkPos(centerX + i, centerZ - j)); + chunks.add(new ChunkPos(centerX - i, centerZ + j)); + chunks.add(new ChunkPos(centerX + i, centerZ + j)); + } + } + } + return chunks; + } + public static class WorldScannerContext { private final BlockOptionalMetaLookup filter; private final IPlayerContext ctx; - private final Map cachedFilter = new ConcurrentHashMap<>(); public WorldScannerContext(BlockOptionalMetaLookup filter, IPlayerContext ctx) { this.filter = filter; this.ctx = ctx; } - public List getChunkRange(int centerX, int centerZ, int chunkRadius) { - List chunks = new ArrayList<>(); - // spiral out - chunks.add(new ChunkPos(centerX, centerZ)); - for (int i = 1; i < chunkRadius; i++) { - for (int x = centerX - i; x <= centerX + i; x++) { - chunks.add(new ChunkPos(x, centerZ - i)); - chunks.add(new ChunkPos(x, centerZ + i)); - } - for (int z = centerZ - i + 1; z <= centerZ + i - 1; z++) { - chunks.add(new ChunkPos(centerX - i, z)); - chunks.add(new ChunkPos(centerX + i, z)); - } - } - return chunks; - } + public List scanAroundPlayerRange(int range) { return scanAroundPlayer(range, -1); From 6260c6d3d7edd984a8b2b900770d4d11c60d4dbd Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 24 Dec 2022 12:11:26 -0700 Subject: [PATCH 08/17] apply suggestions --- .../baritone/api/utils/BlockOptionalMeta.java | 4 + .../api/utils/BlockOptionalMetaLookup.java | 25 +- .../baritone/cache/FasterWorldScanner.java | 279 ++++++++---------- 3 files changed, 132 insertions(+), 176 deletions(-) diff --git a/src/api/java/baritone/api/utils/BlockOptionalMeta.java b/src/api/java/baritone/api/utils/BlockOptionalMeta.java index a9a34a4aa..e86341816 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMeta.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMeta.java @@ -315,4 +315,8 @@ public final class BlockOptionalMeta { return null; } + + public Set getAllBlockStates() { + return blockstates; + } } diff --git a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java index 041c6162c..8fb52fb52 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java @@ -22,15 +22,22 @@ import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; import java.util.Arrays; +import java.util.HashSet; import java.util.List; +import java.util.Set; import java.util.stream.Stream; public class BlockOptionalMetaLookup { - + private final Set blockSet = new HashSet<>(); + private final Set blockStateSet = new HashSet<>(); private final BlockOptionalMeta[] boms; public BlockOptionalMetaLookup(BlockOptionalMeta... boms) { this.boms = boms; + for (BlockOptionalMeta bom : boms) { + blockSet.add(bom.getBlock()); + blockStateSet.addAll(bom.getAllBlockStates()); + } } public BlockOptionalMetaLookup(Block... blocks) { @@ -52,23 +59,11 @@ public class BlockOptionalMetaLookup { } public boolean has(Block block) { - for (BlockOptionalMeta bom : boms) { - if (bom.getBlock() == block) { - return true; - } - } - - return false; + return blockSet.contains(block); } public boolean has(IBlockState state) { - for (BlockOptionalMeta bom : boms) { - if (bom.matches(state)) { - return true; - } - } - - return false; + return blockStateSet.contains(state); } public boolean has(ItemStack stack) { diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index efb80245a..7a46f04ff 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -37,8 +37,6 @@ import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.ArrayList; import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; import java.util.function.BiConsumer; import java.util.function.IntConsumer; import java.util.stream.Collectors; @@ -48,12 +46,16 @@ public enum FasterWorldScanner implements IWorldScanner { INSTANCE; @Override public List scanChunkRadius(IPlayerContext ctx, BlockOptionalMetaLookup filter, int max, int yLevelThreshold, int maxSearchRadius) { - return new WorldScannerContext(filter, ctx).scanAroundPlayer(maxSearchRadius, max); + assert ctx.world() != null; + if (maxSearchRadius < 0) { + throw new IllegalArgumentException("chunkRange must be >= 0"); + } + return scanChunksInternal(ctx, filter, getChunkRange(ctx.playerFeet().x >> 4, ctx.playerFeet().z >> 4, maxSearchRadius), max); } @Override public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) { - return new WorldScannerContext(filter, ctx).scanChunkInternal(pos).collect(Collectors.toList()); + return scanChunkInternal(ctx, filter, pos).limit(max).collect(Collectors.toList()); } @Override @@ -92,15 +94,17 @@ public enum FasterWorldScanner implements IWorldScanner { } // ordered in a way that the closest blocks are generally first - public List getChunkRange(int centerX, int centerZ, int chunkRadius) { + public static List getChunkRange(int centerX, int centerZ, int chunkRadius) { List chunks = new ArrayList<>(); // spiral out chunks.add(new ChunkPos(centerX, centerZ)); for (int i = 1; i < chunkRadius; i++) { for (int j = 0; j <= i; j++) { chunks.add(new ChunkPos(centerX - j, centerZ - i)); - chunks.add(new ChunkPos(centerX + j, centerZ - i)); - chunks.add(new ChunkPos(centerX - j, centerZ + i)); + if (j != 0) { + chunks.add(new ChunkPos(centerX + j, centerZ - i)); + chunks.add(new ChunkPos(centerX - j, centerZ + i)); + } chunks.add(new ChunkPos(centerX + j, centerZ + i)); if (j != 0 && j != i) { chunks.add(new ChunkPos(centerX - i, centerZ - j)); @@ -113,180 +117,133 @@ public enum FasterWorldScanner implements IWorldScanner { return chunks; } - public static class WorldScannerContext { - private final BlockOptionalMetaLookup filter; - private final IPlayerContext ctx; - - public WorldScannerContext(BlockOptionalMetaLookup filter, IPlayerContext ctx) { - this.filter = filter; - this.ctx = ctx; - } - - - - public List scanAroundPlayerRange(int range) { - return scanAroundPlayer(range, -1); - } - - public List scanAroundPlayerUntilCount(int count) { - return scanAroundPlayer(32, count); - } - - public List scanAroundPlayer(int range, int maxCount) { - assert ctx.player() != null; - return scanChunkRange(ctx.playerFeet().x >> 4, ctx.playerFeet().z >> 4, range, maxCount); - } - - public List scanChunkRange(int centerX, int centerZ, int chunkRange, int maxBlocks) { - assert ctx.world() != null; - if (chunkRange < 0) { - throw new IllegalArgumentException("chunkRange must be >= 0"); - } - return scanChunksInternal(getChunkRange(centerX, centerZ, chunkRange), maxBlocks); - } - - private List scanChunksInternal(List chunkPositions, int maxBlocks) { - assert ctx.world() != null; - try { - Stream posStream = chunkPositions.parallelStream().flatMap(this::scanChunkInternal); + private List scanChunksInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, List chunkPositions, int maxBlocks) { + assert ctx.world() != null; + try { + Stream posStream = chunkPositions.parallelStream().flatMap(p -> scanChunkInternal(ctx, lookup, p)); if (maxBlocks >= 0) { // WARNING: this can be expensive if maxBlocks is large... // see limit's javadoc posStream = posStream.limit(maxBlocks); } return posStream.collect(Collectors.toList()); - } catch (Exception e) { - e.printStackTrace(); - throw e; - } + } catch (Exception e) { + e.printStackTrace(); + throw e; + } + } + + private Stream scanChunkInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, ChunkPos pos) { + IChunkProvider chunkProvider = ctx.world().getChunkProvider(); + // if chunk is not loaded, return empty stream + if (!chunkProvider.isChunkGeneratedAt(pos.x, pos.z)) { + return Stream.empty(); } - private Stream scanChunkInternal(ChunkPos pos) { - IChunkProvider chunkProvider = ctx.world().getChunkProvider(); - // if chunk is not loaded, return empty stream - if (!chunkProvider.isChunkGeneratedAt(pos.x, pos.z)) { - return Stream.empty(); + long chunkX = (long) pos.x << 4; + long chunkZ = (long) pos.z << 4; + + List blocks = new ArrayList<>(); + + collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { + int yOffset = section.getYLocation(); + BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); + collectBlockLocations(array, isInFilter, place -> blocks.add(new BlockPos( + chunkX + ((place & 255) & 15), + yOffset + (place >> 8), + chunkZ + ((place & 255) >> 4) + ))); + }); + return blocks.stream(); + } + + + + private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, BiConsumer consumer) { + for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { + if (section == null || section.isEmpty()) { + continue; } - long chunkX = (long) pos.x << 4; - long chunkZ = (long) pos.z << 4; - - List blocks = new ArrayList<>(); - - streamChunkSections(chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { - int yOffset = section.getYLocation(); - BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); - forEach(array, isInFilter, place -> blocks.add(new BlockPos( - chunkX + ((place & 255) & 15), - yOffset + (place >> 8), - chunkZ + ((place & 255) >> 4) - ))); - }); - return blocks.stream(); - } - - private void streamChunkSections(Chunk chunk, BiConsumer consumer) { - for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { - if (section == null || section.isEmpty()) { - continue; - } - - BlockStateContainer sectionContainer = section.getData(); - //this won't work if the PaletteStorage is of the type EmptyPaletteStorage - if (((IBlockStateContainer) sectionContainer).getStorage() == null) { - continue; - } - - boolean[] isInFilter = getIncludedFilterIndices(((IBlockStateContainer) sectionContainer).getPalette()); - if (isInFilter.length == 0) { - continue; - } - consumer.accept(section, isInFilter); - } - } - - private boolean getFilterResult(IBlockState state) { - Boolean v; - return (v = cachedFilter.get(state)) == null ? addCachedState(state) : v; - } - - private boolean addCachedState(IBlockState state) { - boolean isInFilter = false; - - if (filter != null) { - isInFilter = filter.has(state); + BlockStateContainer sectionContainer = section.getData(); + //this won't work if the PaletteStorage is of the type EmptyPaletteStorage + if (((IBlockStateContainer) sectionContainer).getStorage() == null) { + continue; } - cachedFilter.put(state, isInFilter); - return isInFilter; - } - - private boolean[] getIncludedFilterIndices(IBlockStatePalette palette) { - boolean commonBlockFound = false; - ObjectIntIdentityMap paletteMap = getPalette(palette); - int size = paletteMap.size(); - - boolean[] isInFilter = new boolean[size]; - - for (int i = 0; i < size; i++) { - IBlockState state = paletteMap.getByValue(i); - if (getFilterResult(state)) { - isInFilter[i] = true; - commonBlockFound = true; - } else { - isInFilter[i] = false; - } + boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette()); + if (isInFilter.length == 0) { + continue; } - - if (!commonBlockFound) { - return new boolean[0]; - } - return isInFilter; + consumer.accept(section, isInFilter); } + } - private static void forEach(BitArray array, boolean[] isInFilter, IntConsumer action) { - long[] longArray = array.getBackingLongArray(); - int arraySize = array.size(); - int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); - long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); + private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { + boolean commonBlockFound = false; + ObjectIntIdentityMap paletteMap = getPalette(palette); + int size = paletteMap.size(); - for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { - final int i = idx * bitsPerEntry; - final int j = i >> 6; - final int l = i & 63; - final int k = kl >> 6; - final long jl = longArray[j] >>> l; + boolean[] isInFilter = new boolean[size]; - if (j == k) { - if (isInFilter[(int) (jl & maxEntryValue)]) { - action.accept(idx); - } - } else { - if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) { - action.accept(idx); - } - } - } - } - - /** - * cheats to get the actual map of id -> blockstate from the various palette implementations - */ - private static ObjectIntIdentityMap getPalette(IBlockStatePalette palette) { - if (palette instanceof BlockStatePaletteRegistry) { - return Block.BLOCK_STATE_IDS; + for (int i = 0; i < size; i++) { + IBlockState state = paletteMap.getByValue(i); + if (lookup.has(state)) { + isInFilter[i] = true; + commonBlockFound = true; } else { - PacketBuffer buf = new PacketBuffer(Unpooled.buffer()); - palette.write(buf); - int size = buf.readVarInt(); - ObjectIntIdentityMap states = new ObjectIntIdentityMap<>(); - for (int i = 0; i < size; i++) { - IBlockState state = Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt()); - assert state != null; - states.put(state, i); + isInFilter[i] = false; + } + } + + if (!commonBlockFound) { + return new boolean[0]; + } + return isInFilter; + } + + private static void collectBlockLocations(BitArray array, boolean[] isInFilter, IntConsumer action) { + long[] longArray = array.getBackingLongArray(); + int arraySize = array.size(); + int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); + long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); + + for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { + final int i = idx * bitsPerEntry; + final int j = i >> 6; + final int l = i & 63; + final int k = kl >> 6; + final long jl = longArray[j] >>> l; + + if (j == k) { + if (isInFilter[(int) (jl & maxEntryValue)]) { + action.accept(idx); + } + } else { + if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) { + action.accept(idx); } - return states; } } } + + /** + * cheats to get the actual map of id -> blockstate from the various palette implementations + */ + private static ObjectIntIdentityMap getPalette(IBlockStatePalette palette) { + if (palette instanceof BlockStatePaletteRegistry) { + return Block.BLOCK_STATE_IDS; + } else { + PacketBuffer buf = new PacketBuffer(Unpooled.buffer()); + palette.write(buf); + int size = buf.readVarInt(); + ObjectIntIdentityMap states = new ObjectIntIdentityMap<>(); + for (int i = 0; i < size; i++) { + IBlockState state = Block.BLOCK_STATE_IDS.getByValue(buf.readVarInt()); + assert state != null; + states.put(state, i); + } + return states; + } + } } From c04eb066cb84e8a4362f913c301fc03da346718c Mon Sep 17 00:00:00 2001 From: William Gray Date: Wed, 28 Dec 2022 01:06:10 +0000 Subject: [PATCH 09/17] Update src/main/java/baritone/cache/FasterWorldScanner.java Co-authored-by: ZacSharp <68165024+ZacSharp@users.noreply.github.com> --- src/main/java/baritone/cache/FasterWorldScanner.java | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 7a46f04ff..4dd480f25 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -106,11 +106,13 @@ public enum FasterWorldScanner implements IWorldScanner { chunks.add(new ChunkPos(centerX - j, centerZ + i)); } chunks.add(new ChunkPos(centerX + j, centerZ + i)); - if (j != 0 && j != i) { + if (j != i) { chunks.add(new ChunkPos(centerX - i, centerZ - j)); chunks.add(new ChunkPos(centerX + i, centerZ - j)); - chunks.add(new ChunkPos(centerX - i, centerZ + j)); - chunks.add(new ChunkPos(centerX + i, centerZ + j)); + if (j != 0) { + chunks.add(new ChunkPos(centerX - i, centerZ + j)); + chunks.add(new ChunkPos(centerX + i, centerZ + j)); + } } } } From 98a748afb3340ad979a09a62623ddefcdb2d7887 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Tue, 27 Dec 2022 22:42:38 -0700 Subject: [PATCH 10/17] fix stream limit. immutable's in BOML --- .../baritone/api/utils/BlockOptionalMeta.java | 8 ++++-- .../api/utils/BlockOptionalMetaLookup.java | 28 ++++++++++++------- .../baritone/cache/FasterWorldScanner.java | 6 +++- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/src/api/java/baritone/api/utils/BlockOptionalMeta.java b/src/api/java/baritone/api/utils/BlockOptionalMeta.java index e86341816..e0f491fba 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMeta.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMeta.java @@ -41,8 +41,8 @@ public final class BlockOptionalMeta { private final int meta; private final boolean noMeta; private final Set blockstates; - private final ImmutableSet stateHashes; - private final ImmutableSet stackHashes; + private final Set stateHashes; + private final Set stackHashes; private static final Pattern pattern = Pattern.compile("^(.+?)(?::(\\d+))?$"); private static final Map normalizations; @@ -319,4 +319,8 @@ public final class BlockOptionalMeta { public Set getAllBlockStates() { return blockstates; } + + public Set stackHashes() { + return stackHashes; + } } diff --git a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java index 8fb52fb52..6d236e90e 100644 --- a/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java +++ b/src/api/java/baritone/api/utils/BlockOptionalMetaLookup.java @@ -17,6 +17,7 @@ package baritone.api.utils; +import com.google.common.collect.ImmutableSet; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.item.ItemStack; @@ -28,34 +29,41 @@ import java.util.Set; import java.util.stream.Stream; public class BlockOptionalMetaLookup { - private final Set blockSet = new HashSet<>(); - private final Set blockStateSet = new HashSet<>(); + private final Set blockSet; + private final Set blockStateSet; private final BlockOptionalMeta[] boms; public BlockOptionalMetaLookup(BlockOptionalMeta... boms) { this.boms = boms; + Set blocks = new HashSet<>(); + Set blockStates = new HashSet<>(); + Set stacks = new HashSet<>(); for (BlockOptionalMeta bom : boms) { - blockSet.add(bom.getBlock()); - blockStateSet.addAll(bom.getAllBlockStates()); + blocks.add(bom.getBlock()); + blockStates.addAll(bom.getAllBlockStates()); + stacks.addAll(bom.stackHashes()); } + this.blockSet = ImmutableSet.copyOf(blocks); + this.blockStateSet = ImmutableSet.copyOf(blockStates); } public BlockOptionalMetaLookup(Block... blocks) { - this.boms = Stream.of(blocks) + this(Stream.of(blocks) .map(BlockOptionalMeta::new) - .toArray(BlockOptionalMeta[]::new); + .toArray(BlockOptionalMeta[]::new)); + } public BlockOptionalMetaLookup(List blocks) { - this.boms = blocks.stream() + this(blocks.stream() .map(BlockOptionalMeta::new) - .toArray(BlockOptionalMeta[]::new); + .toArray(BlockOptionalMeta[]::new)); } public BlockOptionalMetaLookup(String... blocks) { - this.boms = Stream.of(blocks) + this(Stream.of(blocks) .map(BlockOptionalMeta::new) - .toArray(BlockOptionalMeta[]::new); + .toArray(BlockOptionalMeta[]::new)); } public boolean has(Block block) { diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 4dd480f25..e133f0e49 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -55,7 +55,11 @@ public enum FasterWorldScanner implements IWorldScanner { @Override public List scanChunk(IPlayerContext ctx, BlockOptionalMetaLookup filter, ChunkPos pos, int max, int yLevelThreshold) { - return scanChunkInternal(ctx, filter, pos).limit(max).collect(Collectors.toList()); + Stream stream = scanChunkInternal(ctx, filter, pos); + if (max >= 0) { + stream = stream.limit(max); + } + return stream.collect(Collectors.toList()); } @Override From e55db05f204a8e913ee90b9f3400b40a1abec509 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Tue, 27 Dec 2022 23:30:35 -0700 Subject: [PATCH 11/17] sacrifice a bit of speed for better block ordering --- .../baritone/cache/FasterWorldScanner.java | 57 ++++++++++++++----- 1 file changed, 43 insertions(+), 14 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index e133f0e49..d4c20766e 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -36,10 +36,13 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.ArrayList; +import java.util.Comparator; import java.util.List; +import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.IntConsumer; import java.util.stream.Collectors; +import java.util.stream.IntStream; import java.util.stream.Stream; public enum FasterWorldScanner implements IWorldScanner { @@ -146,43 +149,59 @@ public enum FasterWorldScanner implements IWorldScanner { return Stream.empty(); } - long chunkX = (long) pos.x << 4; - long chunkZ = (long) pos.z << 4; + long inChunkX = (long) pos.x << 4; + long inChunkZ = (long) pos.z << 4; - List blocks = new ArrayList<>(); + int playerY = ctx.playerFeet().y; + int playerSection = ctx.playerFeet().y >> 4; - collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { + + return streamChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), playerSection).flatMap((data) -> { + ExtendedBlockStorage section = data.section; + boolean[] isInFilter = data.isInFilter; + List blocks = new ArrayList<>(); int yOffset = section.getYLocation(); BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); collectBlockLocations(array, isInFilter, place -> blocks.add(new BlockPos( - chunkX + ((place & 255) & 15), + (int) inChunkX + ((place & 255) & 15), yOffset + (place >> 8), - chunkZ + ((place & 255) >> 4) + (int) inChunkZ + ((place & 255) >> 4) ))); + return blocks.stream().sorted((a, b) -> { + int distA = Math.abs(a.getY() - playerY); + int distB = Math.abs(b.getY() - playerY); + return Integer.compare(distA, distB); + }); }); - return blocks.stream(); } - private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, BiConsumer consumer) { - for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { + private Stream streamChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, int playerSection) { + ExtendedBlockStorage[] sections = chunk.getBlockStorageArray(); + // order sections by distance to player + + return IntStream.range(0, sections.length) + .boxed() + .sorted(Comparator.comparingInt(a -> Math.abs(a - playerSection))) + .map(i -> { + ExtendedBlockStorage section = sections[i]; if (section == null || section.isEmpty()) { - continue; + return null; } BlockStateContainer sectionContainer = section.getData(); //this won't work if the PaletteStorage is of the type EmptyPaletteStorage if (((IBlockStateContainer) sectionContainer).getStorage() == null) { - continue; + return null; } boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette()); if (isInFilter.length == 0) { - continue; + return null; } - consumer.accept(section, isInFilter); - } + return new SectionData(section, isInFilter); + }).filter(Objects::nonNull); } private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { @@ -252,4 +271,14 @@ public enum FasterWorldScanner implements IWorldScanner { return states; } } + + private static class SectionData { + ExtendedBlockStorage section; + boolean[] isInFilter; + + SectionData(ExtendedBlockStorage section, boolean[] isInFilter) { + this.section = section; + this.isInFilter = isInFilter; + } + } } From a367031fe248e01910c00122ab75c91c586ed005 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Tue, 27 Dec 2022 23:30:35 -0700 Subject: [PATCH 12/17] Revert "sacrifice a bit of speed for better block ordering" This reverts commit e55db05f204a8e913ee90b9f3400b40a1abec509. --- .../baritone/cache/FasterWorldScanner.java | 57 +++++-------------- 1 file changed, 14 insertions(+), 43 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index d4c20766e..e133f0e49 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -36,13 +36,10 @@ import net.minecraft.world.chunk.*; import net.minecraft.world.chunk.storage.ExtendedBlockStorage; import java.util.ArrayList; -import java.util.Comparator; import java.util.List; -import java.util.Objects; import java.util.function.BiConsumer; import java.util.function.IntConsumer; import java.util.stream.Collectors; -import java.util.stream.IntStream; import java.util.stream.Stream; public enum FasterWorldScanner implements IWorldScanner { @@ -149,59 +146,43 @@ public enum FasterWorldScanner implements IWorldScanner { return Stream.empty(); } - long inChunkX = (long) pos.x << 4; - long inChunkZ = (long) pos.z << 4; + long chunkX = (long) pos.x << 4; + long chunkZ = (long) pos.z << 4; - int playerY = ctx.playerFeet().y; - int playerSection = ctx.playerFeet().y >> 4; + List blocks = new ArrayList<>(); - - return streamChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), playerSection).flatMap((data) -> { - ExtendedBlockStorage section = data.section; - boolean[] isInFilter = data.isInFilter; - List blocks = new ArrayList<>(); + collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { int yOffset = section.getYLocation(); BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); collectBlockLocations(array, isInFilter, place -> blocks.add(new BlockPos( - (int) inChunkX + ((place & 255) & 15), + chunkX + ((place & 255) & 15), yOffset + (place >> 8), - (int) inChunkZ + ((place & 255) >> 4) + chunkZ + ((place & 255) >> 4) ))); - return blocks.stream().sorted((a, b) -> { - int distA = Math.abs(a.getY() - playerY); - int distB = Math.abs(b.getY() - playerY); - return Integer.compare(distA, distB); - }); }); + return blocks.stream(); } - private Stream streamChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, int playerSection) { - ExtendedBlockStorage[] sections = chunk.getBlockStorageArray(); - // order sections by distance to player - - return IntStream.range(0, sections.length) - .boxed() - .sorted(Comparator.comparingInt(a -> Math.abs(a - playerSection))) - .map(i -> { - ExtendedBlockStorage section = sections[i]; + private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, BiConsumer consumer) { + for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { if (section == null || section.isEmpty()) { - return null; + continue; } BlockStateContainer sectionContainer = section.getData(); //this won't work if the PaletteStorage is of the type EmptyPaletteStorage if (((IBlockStateContainer) sectionContainer).getStorage() == null) { - return null; + continue; } boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette()); if (isInFilter.length == 0) { - return null; + continue; } - return new SectionData(section, isInFilter); - }).filter(Objects::nonNull); + consumer.accept(section, isInFilter); + } } private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { @@ -271,14 +252,4 @@ public enum FasterWorldScanner implements IWorldScanner { return states; } } - - private static class SectionData { - ExtendedBlockStorage section; - boolean[] isInFilter; - - SectionData(ExtendedBlockStorage section, boolean[] isInFilter) { - this.section = section; - this.isInFilter = isInFilter; - } - } } From 746faf6df6ea9d615dd2bcd421cef446d1b9f922 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Wed, 28 Dec 2022 01:05:17 -0700 Subject: [PATCH 13/17] faster section reorder --- .../baritone/cache/FasterWorldScanner.java | 48 ++++++++++++------- .../java/baritone/process/MineProcess.java | 2 +- 2 files changed, 33 insertions(+), 17 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index e133f0e49..9adbf76b0 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -149,9 +149,11 @@ public enum FasterWorldScanner implements IWorldScanner { long chunkX = (long) pos.x << 4; long chunkZ = (long) pos.z << 4; + int playerSectionY = ctx.playerFeet().y >> 4; + List blocks = new ArrayList<>(); - collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), (section, isInFilter) -> { + collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), playerSectionY, (section, isInFilter) -> { int yOffset = section.getYLocation(); BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); collectBlockLocations(array, isInFilter, place -> blocks.add(new BlockPos( @@ -165,26 +167,40 @@ public enum FasterWorldScanner implements IWorldScanner { - private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, BiConsumer consumer) { - for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) { - if (section == null || section.isEmpty()) { - continue; + private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, int playerSection, BiConsumer consumer) { + // iterate over sections relative to player + ExtendedBlockStorage[] sections = chunk.getBlockStorageArray(); + int l = sections.length; + int i = playerSection - 1; + int j = playerSection; + for (; i >= 0 || j < l; ++j, --i) { + if (j < l) { + visitSection(lookup, sections[j], consumer); } - - BlockStateContainer sectionContainer = section.getData(); - //this won't work if the PaletteStorage is of the type EmptyPaletteStorage - if (((IBlockStateContainer) sectionContainer).getStorage() == null) { - continue; + if (i >= 0) { + visitSection(lookup, sections[i], consumer); } - - boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette()); - if (isInFilter.length == 0) { - continue; - } - consumer.accept(section, isInFilter); } } + private void visitSection(BlockOptionalMetaLookup lookup, ExtendedBlockStorage section, BiConsumer consumer) { + if (section == null || section.isEmpty()) { + return; + } + + BlockStateContainer sectionContainer = section.getData(); + //this won't work if the PaletteStorage is of the type EmptyPaletteStorage + if (((IBlockStateContainer) sectionContainer).getStorage() == null) { + return; + } + + boolean[] isInFilter = getIncludedFilterIndices(lookup, ((IBlockStateContainer) sectionContainer).getPalette()); + if (isInFilter.length == 0) { + return; + } + consumer.accept(section, isInFilter); + } + private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { boolean commonBlockFound = false; ObjectIntIdentityMap paletteMap = getPalette(palette); diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 807dbc303..137313de9 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -54,7 +54,7 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF; */ public final class MineProcess extends BaritoneProcessHelper implements IMineProcess { - private static final int ORE_LOCATIONS_COUNT = 64; + private static final int ORE_LOCATIONS_COUNT = 32; private BlockOptionalMetaLookup filter; private List knownOreLocations; From b71c9e776ac62cef47e2ec05f484195e850d5e52 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Wed, 28 Dec 2022 01:09:46 -0700 Subject: [PATCH 14/17] oops didn't mean to commit that --- src/main/java/baritone/process/MineProcess.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/main/java/baritone/process/MineProcess.java b/src/main/java/baritone/process/MineProcess.java index 137313de9..807dbc303 100644 --- a/src/main/java/baritone/process/MineProcess.java +++ b/src/main/java/baritone/process/MineProcess.java @@ -54,7 +54,7 @@ import static baritone.api.pathing.movement.ActionCosts.COST_INF; */ public final class MineProcess extends BaritoneProcessHelper implements IMineProcess { - private static final int ORE_LOCATIONS_COUNT = 32; + private static final int ORE_LOCATIONS_COUNT = 64; private BlockOptionalMetaLookup filter; private List knownOreLocations; From 7404414e7a180925502aa6ad1063a321f121cd3a Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Fri, 20 Jan 2023 23:43:00 -0700 Subject: [PATCH 15/17] less impure --- .../baritone/cache/FasterWorldScanner.java | 47 +++++++++++-------- 1 file changed, 27 insertions(+), 20 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 9adbf76b0..a813e9119 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -25,6 +25,8 @@ import baritone.api.utils.IPlayerContext; import baritone.utils.accessor.IBitArray; import baritone.utils.accessor.IBlockStateContainer; import io.netty.buffer.Unpooled; +import it.unimi.dsi.fastutil.ints.IntArrayList; +import it.unimi.dsi.fastutil.ints.IntList; import net.minecraft.block.Block; import net.minecraft.block.state.IBlockState; import net.minecraft.network.PacketBuffer; @@ -126,6 +128,7 @@ public enum FasterWorldScanner implements IWorldScanner { private List scanChunksInternal(IPlayerContext ctx, BlockOptionalMetaLookup lookup, List chunkPositions, int maxBlocks) { assert ctx.world() != null; try { + // p -> scanChunkInternal(ctx, lookup, p) Stream posStream = chunkPositions.parallelStream().flatMap(p -> scanChunkInternal(ctx, lookup, p)); if (maxBlocks >= 0) { // WARNING: this can be expensive if maxBlocks is large... @@ -151,39 +154,30 @@ public enum FasterWorldScanner implements IWorldScanner { int playerSectionY = ctx.playerFeet().y >> 4; - List blocks = new ArrayList<>(); - - collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), playerSectionY, (section, isInFilter) -> { - int yOffset = section.getYLocation(); - BitArray array = (BitArray) ((IBlockStateContainer) section.getData()).getStorage(); - collectBlockLocations(array, isInFilter, place -> blocks.add(new BlockPos( - chunkX + ((place & 255) & 15), - yOffset + (place >> 8), - chunkZ + ((place & 255) >> 4) - ))); - }); - return blocks.stream(); + return collectChunkSections(lookup, chunkProvider.getLoadedChunk(pos.x, pos.z), chunkX, chunkZ, playerSectionY).stream(); } - private void collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, int playerSection, BiConsumer consumer) { + private List collectChunkSections(BlockOptionalMetaLookup lookup, Chunk chunk, long chunkX, long chunkZ, int playerSection) { // iterate over sections relative to player + List blocks = new ArrayList<>(); ExtendedBlockStorage[] sections = chunk.getBlockStorageArray(); int l = sections.length; int i = playerSection - 1; int j = playerSection; for (; i >= 0 || j < l; ++j, --i) { if (j < l) { - visitSection(lookup, sections[j], consumer); + visitSection(lookup, sections[j], blocks, chunkX, chunkZ); } if (i >= 0) { - visitSection(lookup, sections[i], consumer); + visitSection(lookup, sections[i], blocks, chunkX, chunkZ); } } + return blocks; } - private void visitSection(BlockOptionalMetaLookup lookup, ExtendedBlockStorage section, BiConsumer consumer) { + private void visitSection(BlockOptionalMetaLookup lookup, ExtendedBlockStorage section, List blocks, long chunkX, long chunkZ) { if (section == null || section.isEmpty()) { return; } @@ -198,7 +192,17 @@ public enum FasterWorldScanner implements IWorldScanner { if (isInFilter.length == 0) { return; } - consumer.accept(section, isInFilter); + + + int yOffset = section.getYLocation(); + BitArray array = ((IBlockStateContainer) section.getData()).getStorage(); + for (int place : collectBlockLocations(array, isInFilter)) { + blocks.add(new BlockPos( + chunkX + ((place & 255) & 15), + yOffset + (place >> 8), + chunkZ + ((place & 255) >> 4) + )); + } } private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { @@ -224,12 +228,14 @@ public enum FasterWorldScanner implements IWorldScanner { return isInFilter; } - private static void collectBlockLocations(BitArray array, boolean[] isInFilter, IntConsumer action) { + private static IntList collectBlockLocations(BitArray array, boolean[] isInFilter) { long[] longArray = array.getBackingLongArray(); int arraySize = array.size(); int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); + IntList positions = new IntArrayList(); + for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { final int i = idx * bitsPerEntry; final int j = i >> 6; @@ -239,14 +245,15 @@ public enum FasterWorldScanner implements IWorldScanner { if (j == k) { if (isInFilter[(int) (jl & maxEntryValue)]) { - action.accept(idx); + positions.add(idx); } } else { if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) { - action.accept(idx); + positions.add(idx); } } } + return positions; } /** From 334d9c119b6269e1896963905a214667eae24dcb Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 28 Jan 2023 00:44:54 -0700 Subject: [PATCH 16/17] remove the allocation of an intlist per section --- .../baritone/cache/FasterWorldScanner.java | 27 ++++++++++--------- 1 file changed, 14 insertions(+), 13 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index a813e9119..4a41eaf10 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -196,13 +196,7 @@ public enum FasterWorldScanner implements IWorldScanner { int yOffset = section.getYLocation(); BitArray array = ((IBlockStateContainer) section.getData()).getStorage(); - for (int place : collectBlockLocations(array, isInFilter)) { - blocks.add(new BlockPos( - chunkX + ((place & 255) & 15), - yOffset + (place >> 8), - chunkZ + ((place & 255) >> 4) - )); - } + collectBlockLocations(array, isInFilter, blocks, chunkX, chunkZ, yOffset); } private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { @@ -228,14 +222,12 @@ public enum FasterWorldScanner implements IWorldScanner { return isInFilter; } - private static IntList collectBlockLocations(BitArray array, boolean[] isInFilter) { + private static void collectBlockLocations(BitArray array, boolean[] isInFilter, List blocks, long chunkX, long chunkZ, int yOffset) { long[] longArray = array.getBackingLongArray(); int arraySize = array.size(); int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); - IntList positions = new IntArrayList(); - for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { final int i = idx * bitsPerEntry; final int j = i >> 6; @@ -245,15 +237,24 @@ public enum FasterWorldScanner implements IWorldScanner { if (j == k) { if (isInFilter[(int) (jl & maxEntryValue)]) { - positions.add(idx); + //noinspection DuplicateExpressions + blocks.add(new BlockPos( + chunkX + ((idx & 255) & 15), + yOffset + (idx >> 8), + chunkZ + ((idx & 255) >> 4) + )); } } else { if (isInFilter[(int) ((jl | longArray[k] << (64 - l)) & maxEntryValue)]) { - positions.add(idx); + //noinspection DuplicateExpressions + blocks.add(new BlockPos( + chunkX + ((idx & 255) & 15), + yOffset + (idx >> 8), + chunkZ + ((idx & 255) >> 4) + )); } } } - return positions; } /** From 6de266a106534b06f73550846d51aacd436b6ec7 Mon Sep 17 00:00:00 2001 From: Wagyourtail Date: Sat, 28 Jan 2023 01:39:58 -0700 Subject: [PATCH 17/17] remove extra method call --- .../baritone/cache/FasterWorldScanner.java | 55 +++++++++---------- 1 file changed, 26 insertions(+), 29 deletions(-) diff --git a/src/main/java/baritone/cache/FasterWorldScanner.java b/src/main/java/baritone/cache/FasterWorldScanner.java index 4a41eaf10..fbdc238ce 100644 --- a/src/main/java/baritone/cache/FasterWorldScanner.java +++ b/src/main/java/baritone/cache/FasterWorldScanner.java @@ -193,41 +193,15 @@ public enum FasterWorldScanner implements IWorldScanner { return; } - - int yOffset = section.getYLocation(); BitArray array = ((IBlockStateContainer) section.getData()).getStorage(); - collectBlockLocations(array, isInFilter, blocks, chunkX, chunkZ, yOffset); - } - - private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { - boolean commonBlockFound = false; - ObjectIntIdentityMap paletteMap = getPalette(palette); - int size = paletteMap.size(); - - boolean[] isInFilter = new boolean[size]; - - for (int i = 0; i < size; i++) { - IBlockState state = paletteMap.getByValue(i); - if (lookup.has(state)) { - isInFilter[i] = true; - commonBlockFound = true; - } else { - isInFilter[i] = false; - } - } - - if (!commonBlockFound) { - return new boolean[0]; - } - return isInFilter; - } - - private static void collectBlockLocations(BitArray array, boolean[] isInFilter, List blocks, long chunkX, long chunkZ, int yOffset) { long[] longArray = array.getBackingLongArray(); int arraySize = array.size(); int bitsPerEntry = ((IBitArray) array).getBitsPerEntry(); long maxEntryValue = ((IBitArray) array).getMaxEntryValue(); + + int yOffset = section.getYLocation(); + for (int idx = 0, kl = bitsPerEntry - 1; idx < arraySize; idx++, kl += bitsPerEntry) { final int i = idx * bitsPerEntry; final int j = i >> 6; @@ -257,6 +231,29 @@ public enum FasterWorldScanner implements IWorldScanner { } } + private boolean[] getIncludedFilterIndices(BlockOptionalMetaLookup lookup, IBlockStatePalette palette) { + boolean commonBlockFound = false; + ObjectIntIdentityMap paletteMap = getPalette(palette); + int size = paletteMap.size(); + + boolean[] isInFilter = new boolean[size]; + + for (int i = 0; i < size; i++) { + IBlockState state = paletteMap.getByValue(i); + if (lookup.has(state)) { + isInFilter[i] = true; + commonBlockFound = true; + } else { + isInFilter[i] = false; + } + } + + if (!commonBlockFound) { + return new boolean[0]; + } + return isInFilter; + } + /** * cheats to get the actual map of id -> blockstate from the various palette implementations */