/*
*/
package com.infinityraider.agricraft.utility;
import java.util.Iterator;
import java.util.stream.Stream;
import java.util.stream.StreamSupport;
import net.minecraft.util.math.BlockPos;
/**
* Class for representing block ranges.
*/
public class BlockRange implements Iterable<BlockPos> {
private final int minX, minY, minZ;
private final int maxX, maxY, maxZ;
public BlockRange(BlockRange range, BlockPos pos) {
this(range.getMin().add(pos), range.getMax().add(pos));
}
public BlockRange(BlockPos center, int radius) {
this(center.getX(), center.getY(), center.getZ(), radius);
}
public BlockRange(BlockPos min, BlockPos max) {
this(
min.getX(), min.getY(), min.getZ(),
max.getX(), max.getY(), max.getZ()
);
}
public BlockRange(int x, int y, int z, int radius) {
this(
x - radius, y - radius, z - radius,
x + radius, y + radius, z + radius
);
}
public BlockRange(int x1, int y1, int z1, int x2, int y2, int z2) {
if (x1 < x2) {
this.minX = x1;
this.maxX = x2;
} else {
this.minX = x2;
this.maxX = x1;
}
if (y1 < y2) {
this.minY = y1;
this.maxY = y2;
} else {
this.minY = y2;
this.maxY = y1;
}
if (z1 < z2) {
this.minZ = z1;
this.maxZ = z2;
} else {
this.minZ = z2;
this.maxZ = z1;
}
}
public BlockPos getMin() {
return new BlockPos(minX, minY, minZ);
}
public BlockPos getMax() {
return new BlockPos(maxX, maxY, maxZ);
}
public int getMinX() {
return minX;
}
public int getMinY() {
return minY;
}
public int getMinZ() {
return minZ;
}
public int getMaxX() {
return maxX;
}
public int getMaxY() {
return maxY;
}
public int getMaxZ() {
return maxZ;
}
public int getVolume() {
return (maxX - minX + 1)
* (maxY - minY + 1)
* (maxZ - minZ + 1);
}
public boolean contains(BlockPos pos) {
return pos.getX() >= minX
&& pos.getY() >= minY
&& pos.getZ() >= minZ
&& pos.getX() <= maxX
&& pos.getY() <= maxY
&& pos.getZ() <= maxZ;
}
public boolean intersects(BlockRange range) {
return ((this.minX < range.maxX) && (this.maxX > range.minX))
&& ((this.minY < range.maxY) && (this.maxY > range.minY))
&& ((this.minZ < range.maxZ) && (this.maxZ > range.minZ));
}
@Override
public Iterator<BlockPos> iterator() {
return new BlockRangeIterator(this);
}
public Stream<BlockPos> stream() {
return StreamSupport.stream(this.spliterator(), false);
}
public class BlockRangeIterator implements Iterator<BlockPos> {
private int x, y, z;
private final BlockRange range;
public BlockRangeIterator(BlockRange range) {
this.range = range;
this.x = range.minX;
this.y = range.minY;
this.z = range.minZ;
}
@Override
public boolean hasNext() {
return this.x <= this.range.getMaxX()
&& this.y <= this.range.getMaxY()
&& this.z <= this.range.getMaxZ();
}
@Override
public BlockPos next() {
// Ensure haven't fallen out of bounds.
if (!hasNext()) {
throw new IndexOutOfBoundsException();
}
// Create point to return.
final BlockPos pos = new BlockPos(x, y, z);
// Post-Increment
this.x += 1;
if (this.x > this.range.getMaxX()) {
this.x -= 1;
this.y += 1;
if (this.y > this.range.getMaxY()) {
this.y -= 1;
this.z += 1;
}
}
// Return point.
return pos;
}
}
}