Skip to content

Instantly share code, notes, and snippets.

@Techcable
Last active March 10, 2016 02:11
Show Gist options
  • Select an option

  • Save Techcable/91b613160f0280163c18 to your computer and use it in GitHub Desktop.

Select an option

Save Techcable/91b613160f0280163c18 to your computer and use it in GitHub Desktop.
Utilities to iterate over adjacent block positions
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