Created
November 16, 2023 03:26
-
-
Save TelepathicGrunt/d79487f35fa5ff04f5c1394f7a626c3e to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
public static List<BlockPos> matchingBlocksOfKindInRange(Level level, BlockPos centerPos, int radius, Predicate<BlockState> predicate) { | |
List<BlockPos> validPos = new ObjectArrayList<>(); | |
// Figure out how many chunk radius we need to search outward to encompass the radius properly | |
ChunkPos maxChunkPos = new ChunkPos( | |
SectionPos.blockToSectionCoord(centerPos.getX() + radius), | |
SectionPos.blockToSectionCoord(centerPos.getZ() + radius) | |
); | |
ChunkPos minChunkPos = new ChunkPos( | |
SectionPos.blockToSectionCoord(centerPos.getX() - radius), | |
SectionPos.blockToSectionCoord(centerPos.getZ() - radius) | |
); | |
// Get all the chunks in range | |
for (int xOffset = minChunkPos.x; xOffset <= maxChunkPos.x; xOffset++) { | |
for (int zOffset = minChunkPos.z; zOffset <= maxChunkPos.z; zOffset++) { | |
ChunkAccess chunk = level.getChunk(xOffset, zOffset); | |
// Find and store all matches | |
scanChunkForMatchInRange(predicate, validPos, chunk, centerPos, radius); | |
} | |
} | |
return validPos; | |
} | |
private static void scanChunkForMatchInRange(Predicate<BlockState> predicate, List<BlockPos> validPos, ChunkAccess chunk, BlockPos originalPos, int radius) { | |
BlockPos.MutableBlockPos mutableSectionWorldOrigin = new BlockPos.MutableBlockPos(); | |
BlockPos.MutableBlockPos mutableSectionWorldBlockPos = new BlockPos.MutableBlockPos(); | |
int radiusSq = radius * radius; | |
// Iterate over all sections in chunk. Note, sections can be negative if world extends to negative. | |
for (int i = chunk.getMinSection(); i < chunk.getMaxSection(); ++i) { | |
int sectionWorldY = SectionPos.sectionToBlockCoord(i); | |
// Make sure this section is in range of the radius we want to check. | |
if (sectionWorldY + 15 < originalPos.getY() - radius || sectionWorldY > originalPos.getY() + radius) { | |
continue; | |
} | |
LevelChunkSection levelChunkSection = chunk.getSection(chunk.getSectionIndexFromSectionY(i)); | |
// Check if chunk section has match | |
if (levelChunkSection.maybeHas(predicate)) { | |
// Set to origin corner of chunk section | |
mutableSectionWorldOrigin.set( | |
SectionPos.sectionToBlockCoord(chunk.getPos().x), | |
sectionWorldY, | |
SectionPos.sectionToBlockCoord(chunk.getPos().z)); | |
for(int yOffset = 0; yOffset < 16; yOffset++) { | |
for(int zOffset = 0; zOffset < 16; zOffset++) { | |
for(int xOffset = 0; xOffset < 16; xOffset++) { | |
// Go to spot in section in terms of world position. | |
mutableSectionWorldBlockPos.set(mutableSectionWorldOrigin).move(xOffset, yOffset, zOffset); | |
// Make sure spot is in radius | |
int xDiff = originalPos.getX() - mutableSectionWorldBlockPos.getX(); | |
int yDiff = originalPos.getY() - mutableSectionWorldBlockPos.getY(); | |
int zDiff = originalPos.getZ() - mutableSectionWorldBlockPos.getZ(); | |
if ((xDiff * xDiff + yDiff * yDiff + zDiff * zDiff) <= radiusSq) { | |
// Test block and add position found. | |
BlockState blockState = levelChunkSection.getBlockState(xOffset, yOffset, zOffset); | |
if (predicate.test(blockState)) { | |
validPos.add(mutableSectionWorldBlockPos.immutable()); | |
} | |
} | |
} | |
} | |
} | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment