sacrifice a bit of speed for better block ordering

This commit is contained in:
Wagyourtail 2022-12-27 23:30:35 -07:00
parent 98a748afb3
commit e55db05f20
No known key found for this signature in database
GPG Key ID: B72EB1D5CD437025
1 changed files with 43 additions and 14 deletions

View File

@ -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<BlockPos> 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<BlockPos> 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<ExtendedBlockStorage, boolean[]> consumer) {
for (ExtendedBlockStorage section : chunk.getBlockStorageArray()) {
private Stream<SectionData> 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;
}
}
}