Last active
March 10, 2016 02:11
-
-
Save Techcable/91b613160f0280163c18 to your computer and use it in GitHub Desktop.
Utilities to iterate over adjacent block positions
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
| package net.techcable.tacospigot.utils; | |
| import java.util.AbstractSet; | |
| import java.util.Iterator; | |
| import java.util.Spliterator; | |
| import java.util.Spliterators; | |
| import java.util.function.Consumer; | |
| import java.util.function.Predicate; | |
| import java.util.stream.Stream; | |
| import java.util.stream.StreamSupport; | |
| import com.google.common.base.Preconditions; | |
| import com.google.common.collect.AbstractIterator; | |
| import net.minecraft.server.Block; | |
| import net.minecraft.server.BlockPosition; | |
| public class BlockHelper { | |
| private BlockHelper() { | |
| } | |
| public static Stream<BlockPosition> streamAdjacentBlocks(final BlockPosition pos, int radius) { | |
| Preconditions.checkArgument(radius >= 0, "Negative radius %s", radius); | |
| return StreamSupport.stream(new AdjacentBlockSet(pos, radius).spliterator(), false); | |
| } | |
| public static void forEachAdjacentBlock(BlockPosition position, int radius, Consumer<BlockPosition> action) { | |
| new AdjacentBlockSet(position, radius).forEach(action); | |
| } | |
| public static boolean isAllAdjacentBlocksFillPredicate(BlockPosition position, int radius, Predicate<BlockPosition> predicate) { | |
| for (BlockPosition adjacent : new AdjacentBlockSet(position, radius)) { | |
| if (!predicate.test(adjacent)) return false; | |
| } | |
| return true; | |
| } | |
| private static final Block[] blockById = new Block[256]; | |
| static { | |
| for (int i = 0; i < blockById.length; i++) { | |
| blockById[i] = Block.getById(i); | |
| } | |
| } | |
| public static Block getBlock(int id) { | |
| return id < 256 ? blockById[id] : Block.getById(id); | |
| } | |
| public static class AdjacentBlockSet extends AbstractSet<BlockPosition> { | |
| private final int startX, endX; | |
| private final int startY, endY; | |
| private final int startZ, endZ; | |
| public AdjacentBlockSet(BlockPosition pos, int radius) { | |
| this( | |
| pos.getX() - radius, // startX | |
| pos.getX() + radius, // endX | |
| Math.max(0, pos.getY() - radius), // startY | |
| Math.min(255, pos.getY() + radius), // endY | |
| pos.getZ() - radius, // startZ | |
| pos.getZ() + radius // endZ | |
| ); | |
| } | |
| public AdjacentBlockSet(int startX, int endX, int startY, int endY, int startZ, int endZ) { | |
| this.startX = startX; | |
| this.endX = endX; | |
| this.startY = startY; | |
| this.endY = endY; | |
| this.startZ = startZ; | |
| this.endZ = endZ; | |
| } | |
| @Override | |
| public int size() { | |
| return (endX - startX) * (endY - startY) * (endZ - startZ); | |
| } | |
| @Override | |
| public Spliterator<BlockPosition> spliterator() { | |
| return Spliterators.spliterator(iterator(), size(), Spliterator.IMMUTABLE | Spliterator.ORDERED | Spliterator.DISTINCT | Spliterator.NONNULL); | |
| } | |
| @Override | |
| public Iterator<BlockPosition> iterator() { | |
| return new AdjacentBlockIterator(); | |
| } | |
| @Override | |
| public void forEach(Consumer<? super BlockPosition> action) { | |
| iterator().forEachRemaining(action); | |
| } | |
| private class AdjacentBlockIterator extends AbstractIterator<BlockPosition> { | |
| private int x = startX; | |
| private int y = startY; | |
| private int z = startZ; | |
| @Override | |
| protected BlockPosition computeNext() { | |
| final int x = this.x; | |
| final int y = this.y; | |
| final int z = this.z; | |
| if (z <= endZ) { | |
| ++this.z; | |
| } else { | |
| if (y < endY) { | |
| ++this.y; | |
| } else { | |
| if (x < endX) { | |
| ++this.x; | |
| } else return endOfData(); | |
| this.y = startY; | |
| } | |
| this.z = startZ; | |
| return computeNext(); | |
| } | |
| return new BlockPosition(x, y, z); | |
| } | |
| @Override | |
| public void forEachRemaining(Consumer<? super BlockPosition> action) { | |
| for (int x = this.x; x <= endX; x++) { | |
| for (int y = this.y; y <= endY; y++) { | |
| for (int z = this.z; z <= endZ; z++) { | |
| BlockPosition adjacent = new BlockPosition(x, y, z); | |
| action.accept(adjacent); | |
| } | |
| } | |
| } | |
| endOfData(); | |
| } | |
| } | |
| } | |
| } |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment