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; + } + } }