Immutable view of GridAlignedBB

This commit is contained in:
Jozufozu 2021-09-04 19:57:32 -07:00
parent c055873bac
commit 1f7af0d8b2
7 changed files with 304 additions and 234 deletions

View file

@ -5,7 +5,6 @@ import com.jozufozu.flywheel.core.AtlasStitcher;
import com.jozufozu.flywheel.core.Contexts;
import com.jozufozu.flywheel.core.Materials;
import com.jozufozu.flywheel.core.PartialModel;
import com.jozufozu.flywheel.light.debug.DebugView;
import com.jozufozu.flywheel.vanilla.VanillaInstances;
import net.minecraftforge.eventbus.api.IEventBus;

View file

@ -10,6 +10,7 @@ import com.jozufozu.flywheel.light.GridAlignedBB;
import com.jozufozu.flywheel.light.ILightUpdateListener;
import com.jozufozu.flywheel.light.LightProvider;
import com.jozufozu.flywheel.light.ListenerStatus;
import com.jozufozu.flywheel.light.ReadOnlyBox;
import net.minecraft.util.math.BlockPos;
import net.minecraft.world.LightType;
@ -73,7 +74,7 @@ public abstract class AbstractInstance implements IInstance, ILightUpdateListene
}
@Override
public void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed) {
public void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed) {
updateLight();
}

View file

@ -1,7 +1,5 @@
package com.jozufozu.flywheel.light;
import static com.jozufozu.flywheel.util.RenderUtil.isPowerOf2;
import com.jozufozu.flywheel.util.RenderUtil;
import net.minecraft.util.Direction;
@ -10,13 +8,13 @@ import net.minecraft.util.math.BlockPos;
import net.minecraft.util.math.SectionPos;
import net.minecraft.util.math.vector.Vector3i;
public class GridAlignedBB {
public int minX;
public int minY;
public int minZ;
public int maxX;
public int maxY;
public int maxZ;
public class GridAlignedBB implements ReadOnlyBox {
private int minX;
private int minY;
private int minZ;
private int maxX;
private int maxY;
private int maxZ;
public GridAlignedBB(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
this.minX = minX;
@ -31,10 +29,6 @@ public class GridAlignedBB {
return new GridAlignedBB(-radius, -radius, -radius, radius + 1, radius + 1, radius + 1);
}
public static GridAlignedBB copy(GridAlignedBB bb) {
return new GridAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
}
public static GridAlignedBB from(AxisAlignedBB aabb) {
int minX = (int) Math.floor(aabb.minX);
int minY = (int) Math.floor(aabb.minY);
@ -63,62 +57,20 @@ public class GridAlignedBB {
return new GridAlignedBB(startX, 0, startZ, startX + 16, 256, startZ + 16);
}
public static AxisAlignedBB toAABB(GridAlignedBB bb) {
return new AxisAlignedBB(bb.minX, bb.minY, bb.minZ, bb.maxX, bb.maxY, bb.maxZ);
}
public GridAlignedBB copy() {
return copy(this);
}
public boolean sameAs(GridAlignedBB other) {
return minX == other.minX && minY == other.minY && minZ == other.minZ && maxX == other.maxX && maxY == other.maxY && maxZ == other.maxZ;
}
public boolean sameAs(AxisAlignedBB other) {
return minX == Math.floor(other.minX)
&& minY == Math.floor(other.minY)
&& minZ == Math.floor(other.minZ)
&& maxX == Math.ceil(other.maxX)
&& maxY == Math.ceil(other.maxY)
&& maxZ == Math.ceil(other.maxZ);
}
public void fixMinMax() {
int minX = Math.min(this.minX, this.maxX);
int minY = Math.min(this.minY, this.maxY);
int minZ = Math.min(this.minZ, this.maxZ);
int maxX = Math.max(this.minX, this.maxX);
int maxY = Math.max(this.minY, this.maxY);
int maxZ = Math.max(this.minZ, this.maxZ);
int minX = Math.min(this.getMinX(), this.getMaxX());
int minY = Math.min(this.getMinY(), this.getMaxY());
int minZ = Math.min(this.getMinZ(), this.getMaxZ());
int maxX = Math.max(this.getMinX(), this.getMaxX());
int maxY = Math.max(this.getMinY(), this.getMaxY());
int maxZ = Math.max(this.getMinZ(), this.getMaxZ());
this.minX = minX;
this.minY = minY;
this.minZ = minZ;
this.maxX = maxX;
this.maxY = maxY;
this.maxZ = maxZ;
}
public int sizeX() {
return maxX - minX;
}
public int sizeY() {
return maxY - minY;
}
public int sizeZ() {
return maxZ - minZ;
}
public int volume() {
return sizeX() * sizeY() * sizeZ();
}
public boolean empty() {
// if any dimension has side length 0 this box contains no volume
return minX == maxX || minY == maxY || minZ == maxZ;
this.setMinX(minX);
this.setMinY(minY);
this.setMinZ(minZ);
this.setMaxX(maxX);
this.setMaxY(maxY);
this.setMaxZ(maxZ);
}
public void translate(Vector3i by) {
@ -126,12 +78,12 @@ public class GridAlignedBB {
}
public void translate(int x, int y, int z) {
minX += x;
maxX += x;
minY += y;
maxY += y;
minZ += z;
maxZ += z;
setMinX(getMinX() + x);
setMaxX(getMaxX() + x);
setMinY(getMinY() + y);
setMaxY(getMaxY() + y);
setMinZ(getMinZ() + z);
setMaxZ(getMaxZ() + z);
}
public void mirrorAbout(Direction.Axis axis) {
@ -141,15 +93,15 @@ public class GridAlignedBB {
int flipY = axisVec.getY() - 1;
int flipZ = axisVec.getZ() - 1;
int maxX = this.maxX * flipX;
int maxY = this.maxY * flipY;
int maxZ = this.maxZ * flipZ;
this.maxX = this.minX * flipX;
this.maxY = this.minY * flipY;
this.maxZ = this.minZ * flipZ;
this.minX = maxX;
this.minY = maxY;
this.minZ = maxZ;
int maxX = this.getMaxX() * flipX;
int maxY = this.getMaxY() * flipY;
int maxZ = this.getMaxZ() * flipZ;
this.setMaxX(this.getMinX() * flipX);
this.setMaxY(this.getMinY() * flipY);
this.setMaxZ(this.getMinZ() * flipZ);
this.setMinX(maxX);
this.setMinY(maxY);
this.setMinZ(maxZ);
}
/**
@ -168,12 +120,12 @@ public class GridAlignedBB {
int diffY = newSizeY - sizeY;
int diffZ = newSizeZ - sizeZ;
minX -= diffX / 2; // floor division for the minimums
minY -= diffY / 2;
minZ -= diffZ / 2;
maxX += (diffX + 1) / 2; // ceiling divison for the maximums
maxY += (diffY + 1) / 2;
maxZ += (diffZ + 1) / 2;
setMinX(getMinX() - diffX / 2); // floor division for the minimums
setMinY(getMinY() - diffY / 2);
setMinZ(getMinZ() - diffZ / 2);
setMaxX(getMaxX() + (diffX + 1) / 2); // ceiling divison for the maximums
setMaxY(getMaxY() + (diffY + 1) / 2);
setMaxZ(getMaxZ() + (diffZ + 1) / 2);
}
/**
@ -184,14 +136,9 @@ public class GridAlignedBB {
int sizeY = RenderUtil.nextPowerOf2(sizeY());
int sizeZ = RenderUtil.nextPowerOf2(sizeZ());
this.maxX = this.minX + sizeX;
this.maxY = this.minY + sizeY;
this.maxZ = this.minZ + sizeZ;
}
public boolean hasPowerOf2Sides() {
// this is only true if all individual side lengths are powers of 2
return isPowerOf2(volume());
this.setMaxX(this.getMinX() + sizeX);
this.setMaxY(this.getMinY() + sizeY);
this.setMaxZ(this.getMinZ() + sizeZ);
}
public void grow(int s) {
@ -199,109 +146,57 @@ public class GridAlignedBB {
}
public void grow(int x, int y, int z) {
minX -= x;
minY -= y;
minZ -= z;
maxX += x;
maxY += y;
maxZ += z;
setMinX(getMinX() - x);
setMinY(getMinY() - y);
setMinZ(getMinZ() - z);
setMaxX(getMaxX() + x);
setMaxY(getMaxY() + y);
setMaxZ(getMaxZ() + z);
}
public GridAlignedBB intersect(GridAlignedBB other) {
int minX = Math.max(this.minX, other.minX);
int minY = Math.max(this.minY, other.minY);
int minZ = Math.max(this.minZ, other.minZ);
int maxX = Math.min(this.maxX, other.maxX);
int maxY = Math.min(this.maxY, other.maxY);
int maxZ = Math.min(this.maxZ, other.maxZ);
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
public void intersectAssign(ReadOnlyBox other) {
this.setMinX(Math.max(this.getMinX(), other.getMinX()));
this.setMinY(Math.max(this.getMinY(), other.getMinY()));
this.setMinZ(Math.max(this.getMinZ(), other.getMinZ()));
this.setMaxX(Math.min(this.getMaxX(), other.getMaxX()));
this.setMaxY(Math.min(this.getMaxY(), other.getMaxY()));
this.setMaxZ(Math.min(this.getMaxZ(), other.getMaxZ()));
}
public void intersectAssign(GridAlignedBB other) {
this.minX = Math.max(this.minX, other.minX);
this.minY = Math.max(this.minY, other.minY);
this.minZ = Math.max(this.minZ, other.minZ);
this.maxX = Math.min(this.maxX, other.maxX);
this.maxY = Math.min(this.maxY, other.maxY);
this.maxZ = Math.min(this.maxZ, other.maxZ);
}
public GridAlignedBB union(GridAlignedBB other) {
int minX = Math.min(this.minX, other.minX);
int minY = Math.min(this.minY, other.minY);
int minZ = Math.min(this.minZ, other.minZ);
int maxX = Math.max(this.maxX, other.maxX);
int maxY = Math.max(this.maxY, other.maxY);
int maxZ = Math.max(this.maxZ, other.maxZ);
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
}
public void unionAssign(GridAlignedBB other) {
this.minX = Math.min(this.minX, other.minX);
this.minY = Math.min(this.minY, other.minY);
this.minZ = Math.min(this.minZ, other.minZ);
this.maxX = Math.max(this.maxX, other.maxX);
this.maxY = Math.max(this.maxY, other.maxY);
this.maxZ = Math.max(this.maxZ, other.maxZ);
public void unionAssign(ReadOnlyBox other) {
this.setMinX(Math.min(this.getMinX(), other.getMinX()));
this.setMinY(Math.min(this.getMinY(), other.getMinY()));
this.setMinZ(Math.min(this.getMinZ(), other.getMinZ()));
this.setMaxX(Math.max(this.getMaxX(), other.getMaxX()));
this.setMaxY(Math.max(this.getMaxY(), other.getMaxY()));
this.setMaxZ(Math.max(this.getMaxZ(), other.getMaxZ()));
}
public void unionAssign(AxisAlignedBB other) {
this.minX = Math.min(this.minX, (int) Math.floor(other.minX));
this.minY = Math.min(this.minY, (int) Math.floor(other.minY));
this.minZ = Math.min(this.minZ, (int) Math.floor(other.minZ));
this.maxX = Math.max(this.maxX, (int) Math.ceil(other.maxX));
this.maxY = Math.max(this.maxY, (int) Math.ceil(other.maxY));
this.maxZ = Math.max(this.maxZ, (int) Math.ceil(other.maxZ));
this.setMinX(Math.min(this.getMinX(), (int) Math.floor(other.minX)));
this.setMinY(Math.min(this.getMinY(), (int) Math.floor(other.minY)));
this.setMinZ(Math.min(this.getMinZ(), (int) Math.floor(other.minZ)));
this.setMaxX(Math.max(this.getMaxX(), (int) Math.ceil(other.maxX)));
this.setMaxY(Math.max(this.getMaxY(), (int) Math.ceil(other.maxY)));
this.setMaxZ(Math.max(this.getMaxZ(), (int) Math.ceil(other.maxZ)));
}
public void assign(AxisAlignedBB other) {
this.minX = (int) Math.floor(other.minX);
this.minY = (int) Math.floor(other.minY);
this.minZ = (int) Math.floor(other.minZ);
this.maxX = (int) Math.ceil(other.maxX);
this.maxY = (int) Math.ceil(other.maxY);
this.maxZ = (int) Math.ceil(other.maxZ);
this.setMinX((int) Math.floor(other.minX));
this.setMinY((int) Math.floor(other.minY));
this.setMinZ((int) Math.floor(other.minZ));
this.setMaxX((int) Math.ceil(other.maxX));
this.setMaxY((int) Math.ceil(other.maxY));
this.setMaxZ((int) Math.ceil(other.maxZ));
}
public void assign(GridAlignedBB other) {
this.minX = other.minX;
this.minY = other.minY;
this.minZ = other.minZ;
this.maxX = other.maxX;
this.maxY = other.maxY;
this.maxZ = other.maxZ;
}
public boolean intersects(GridAlignedBB other) {
return this.intersects(other.minX, other.minY, other.minZ, other.maxX, other.maxY, other.maxZ);
}
public boolean contains(GridAlignedBB other) {
return other.minX >= this.minX && other.maxX <= this.maxX && other.minY >= this.minY && other.maxY <= this.maxY && other.minZ >= this.minZ && other.maxZ <= this.maxZ;
}
public boolean isContainedBy(GridAlignedBB other) {
return other.contains(this);
}
public boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
return this.minX < maxX && this.maxX > minX && this.minY < maxY && this.maxY > minY && this.minZ < maxZ && this.maxZ > minZ;
}
public void forEachContained(ICoordinateConsumer func) {
if (empty()) return;
for (int x = minX; x < maxX; x++) {
for (int y = Math.max(minY, 0); y < Math.min(maxY, 255); y++) { // clamp to world height limits
for (int z = minZ; z < maxZ; z++) {
func.consume(x, y, z);
}
}
}
}
public AxisAlignedBB toAABB() {
return toAABB(this);
public void assign(ReadOnlyBox other) {
this.setMinX(other.getMinX());
this.setMinY(other.getMinY());
this.setMinZ(other.getMinZ());
this.setMaxX(other.getMaxX());
this.setMaxY(other.getMaxY());
this.setMaxZ(other.getMaxZ());
}
@Override
@ -309,19 +204,79 @@ public class GridAlignedBB {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
GridAlignedBB that = (GridAlignedBB) o;
ReadOnlyBox that = (ReadOnlyBox) o;
return this.sameAs(that);
}
@Override
public int hashCode() {
int result = minX;
result = 31 * result + minY;
result = 31 * result + minZ;
result = 31 * result + maxX;
result = 31 * result + maxY;
result = 31 * result + maxZ;
int result = getMinX();
result = 31 * result + getMinY();
result = 31 * result + getMinZ();
result = 31 * result + getMaxX();
result = 31 * result + getMaxY();
result = 31 * result + getMaxZ();
return result;
}
@Override
public int getMinX() {
return minX;
}
@Override
public int getMinY() {
return minY;
}
@Override
public int getMinZ() {
return minZ;
}
@Override
public int getMaxX() {
return maxX;
}
@Override
public int getMaxY() {
return maxY;
}
@Override
public int getMaxZ() {
return maxZ;
}
public GridAlignedBB setMinX(int minX) {
this.minX = minX;
return this;
}
public GridAlignedBB setMinY(int minY) {
this.minY = minY;
return this;
}
public GridAlignedBB setMinZ(int minZ) {
this.minZ = minZ;
return this;
}
public GridAlignedBB setMaxX(int maxX) {
this.maxX = maxX;
return this;
}
public GridAlignedBB setMaxY(int maxY) {
this.maxY = maxY;
return this;
}
public GridAlignedBB setMaxZ(int maxZ) {
this.maxZ = maxZ;
return this;
}
}

View file

@ -4,14 +4,14 @@ import net.minecraft.world.LightType;
public interface ILightUpdateListener {
GridAlignedBB getVolume();
ReadOnlyBox getVolume();
ListenerStatus status();
/**
* Called when a light updates in a chunk the implementor cares about.
*/
void onLightUpdate(LightProvider world, LightType type, GridAlignedBB changed);
void onLightUpdate(LightProvider world, LightType type, ReadOnlyBox changed);
/**
* Called when the server sends light data to the client.

View file

@ -50,17 +50,17 @@ public class LightUpdater {
if (listener instanceof IMovingListener)
movingListeners.add(((IMovingListener) listener));
GridAlignedBB box = listener.getVolume();
ReadOnlyBox box = listener.getVolume();
LongSet sections = this.sections.getAndResetContainment(listener);
LongSet chunks = this.chunks.getAndResetContainment(listener);
int minX = SectionPos.blockToSectionCoord(box.minX);
int minY = SectionPos.blockToSectionCoord(box.minY);
int minZ = SectionPos.blockToSectionCoord(box.minZ);
int maxX = SectionPos.blockToSectionCoord(box.maxX);
int maxY = SectionPos.blockToSectionCoord(box.maxY);
int maxZ = SectionPos.blockToSectionCoord(box.maxZ);
int minX = SectionPos.blockToSectionCoord(box.getMinX());
int minY = SectionPos.blockToSectionCoord(box.getMinY());
int minZ = SectionPos.blockToSectionCoord(box.getMinZ());
int maxX = SectionPos.blockToSectionCoord(box.getMaxX());
int maxY = SectionPos.blockToSectionCoord(box.getMaxY());
int maxZ = SectionPos.blockToSectionCoord(box.getMaxZ());
for (int x = minX; x <= maxX; x++) {
for (int z = minZ; z <= maxZ; z++) {
@ -88,10 +88,10 @@ public class LightUpdater {
set.removeIf(l -> l.status().shouldRemove());
GridAlignedBB chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
ReadOnlyBox chunkBox = GridAlignedBB.from(SectionPos.of(sectionPos));
for (ILightUpdateListener listener : set) {
listener.onLightUpdate(provider, type, chunkBox.copy());
listener.onLightUpdate(provider, type, chunkBox);
}
}
@ -122,7 +122,7 @@ public class LightUpdater {
return sectionPos & 0xFFFFFFFFFFF_00000L;
}
public Stream<GridAlignedBB> getAllBoxes() {
public Stream<ReadOnlyBox> getAllBoxes() {
return chunks.stream().map(ILightUpdateListener::getVolume);
}

View file

@ -76,36 +76,36 @@ public class LightVolume {
this.textureVolume.nextPowerOf2Centered();
}
public GridAlignedBB getTextureVolume() {
return GridAlignedBB.copy(textureVolume);
public ReadOnlyBox getTextureVolume() {
return textureVolume;
}
public GridAlignedBB getSampleVolume() {
return GridAlignedBB.copy(sampleVolume);
public ReadOnlyBox getSampleVolume() {
return sampleVolume;
}
public int getMinX() {
return textureVolume.minX;
return textureVolume.getMinX();
}
public int getMinY() {
return textureVolume.minY;
return textureVolume.getMinY();
}
public int getMinZ() {
return textureVolume.minZ;
return textureVolume.getMinZ();
}
public int getMaxX() {
return textureVolume.maxX;
return textureVolume.getMaxX();
}
public int getMaxY() {
return textureVolume.maxY;
return textureVolume.getMaxY();
}
public int getMaxZ() {
return textureVolume.maxZ;
return textureVolume.getMaxZ();
}
public int getSizeX() {
@ -144,7 +144,7 @@ public class LightVolume {
}
}
public void notifyLightUpdate(LightProvider world, LightType type, GridAlignedBB changedVolume) {
public void notifyLightUpdate(LightProvider world, LightType type, ReadOnlyBox changedVolume) {
if (removed) return;
if (!changedVolume.intersects(sampleVolume)) return;
@ -173,9 +173,9 @@ public class LightVolume {
BlockPos.Mutable pos = new BlockPos.Mutable();
int shiftX = textureVolume.minX;
int shiftY = textureVolume.minY;
int shiftZ = textureVolume.minZ;
int shiftX = textureVolume.getMinX();
int shiftY = textureVolume.getMinY();
int shiftZ = textureVolume.getMinZ();
sampleVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);
@ -194,10 +194,10 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copyBlock(LightProvider world, GridAlignedBB worldVolume) {
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
public void copyBlock(LightProvider world, ReadOnlyBox worldVolume) {
int xShift = textureVolume.getMinX();
int yShift = textureVolume.getMinY();
int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> {
int light = world.getLight(LightType.BLOCK, x, y, z);
@ -213,10 +213,10 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copySky(LightProvider world, GridAlignedBB worldVolume) {
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
public void copySky(LightProvider world, ReadOnlyBox worldVolume) {
int xShift = textureVolume.getMinX();
int yShift = textureVolume.getMinY();
int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> {
int light = world.getLight(LightType.SKY, x, y, z);
@ -232,12 +232,12 @@ public class LightVolume {
*
* @param worldVolume the region in the world to copy data from.
*/
public void copyLight(LightProvider world, GridAlignedBB worldVolume) {
public void copyLight(LightProvider world, ReadOnlyBox worldVolume) {
BlockPos.Mutable pos = new BlockPos.Mutable();
int xShift = textureVolume.minX;
int yShift = textureVolume.minY;
int zShift = textureVolume.minZ;
int xShift = textureVolume.getMinX();
int yShift = textureVolume.getMinY();
int zShift = textureVolume.getMinZ();
worldVolume.forEachContained((x, y, z) -> {
pos.set(x, y, z);

View file

@ -0,0 +1,115 @@
package com.jozufozu.flywheel.light;
import static com.jozufozu.flywheel.util.RenderUtil.isPowerOf2;
import net.minecraft.util.math.AxisAlignedBB;
public interface ReadOnlyBox {
int getMinX();
int getMinY();
int getMinZ();
int getMaxX();
int getMaxY();
int getMaxZ();
default int sizeX() {
return getMaxX() - getMinX();
}
default int sizeY() {
return getMaxY() - getMinY();
}
default int sizeZ() {
return getMaxZ() - getMinZ();
}
default int volume() {
return sizeX() * sizeY() * sizeZ();
}
default boolean empty() {
// if any dimension has side length 0 this box contains no volume
return getMinX() == getMaxX() || getMinY() == getMaxY() || getMinZ() == getMaxZ();
}
default boolean sameAs(ReadOnlyBox other) {
return getMinX() == other.getMinX() && getMinY() == other.getMinY() && getMinZ() == other.getMinZ() && getMaxX() == other.getMaxX() && getMaxY() == other.getMaxY() && getMaxZ() == other.getMaxZ();
}
default boolean sameAs(AxisAlignedBB other) {
return getMinX() == Math.floor(other.minX)
&& getMinY() == Math.floor(other.minY)
&& getMinZ() == Math.floor(other.minZ)
&& getMaxX() == Math.ceil(other.maxX)
&& getMaxY() == Math.ceil(other.maxY)
&& getMaxZ() == Math.ceil(other.maxZ);
}
default boolean hasPowerOf2Sides() {
// this is only true if all individual side lengths are powers of 2
return isPowerOf2(volume());
}
default GridAlignedBB intersect(ReadOnlyBox other) {
int minX = Math.max(this.getMinX(), other.getMinX());
int minY = Math.max(this.getMinY(), other.getMinY());
int minZ = Math.max(this.getMinZ(), other.getMinZ());
int maxX = Math.min(this.getMaxX(), other.getMaxX());
int maxY = Math.min(this.getMaxY(), other.getMaxY());
int maxZ = Math.min(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
}
default ReadOnlyBox union(ReadOnlyBox other) {
int minX = Math.min(this.getMinX(), other.getMinX());
int minY = Math.min(this.getMinY(), other.getMinY());
int minZ = Math.min(this.getMinZ(), other.getMinZ());
int maxX = Math.max(this.getMaxX(), other.getMaxX());
int maxY = Math.max(this.getMaxY(), other.getMaxY());
int maxZ = Math.max(this.getMaxZ(), other.getMaxZ());
return new GridAlignedBB(minX, minY, minZ, maxX, maxY, maxZ);
}
default boolean intersects(ReadOnlyBox other) {
return this.intersects(other.getMinX(), other.getMinY(), other.getMinZ(), other.getMaxX(), other.getMaxY(), other.getMaxZ());
}
default boolean contains(ReadOnlyBox other) {
return other.getMinX() >= this.getMinX() && other.getMaxX() <= this.getMaxX() && other.getMinY() >= this.getMinY() && other.getMaxY() <= this.getMaxY() && other.getMinZ() >= this.getMinZ() && other.getMaxZ() <= this.getMaxZ();
}
default boolean isContainedBy(GridAlignedBB other) {
return other.contains(this);
}
default boolean intersects(int minX, int minY, int minZ, int maxX, int maxY, int maxZ) {
return this.getMinX() < maxX && this.getMaxX() > minX && this.getMinY() < maxY && this.getMaxY() > minY && this.getMinZ() < maxZ && this.getMaxZ() > minZ;
}
default void forEachContained(ICoordinateConsumer func) {
if (empty()) return;
for (int x = getMinX(); x < getMaxX(); x++) {
for (int y = Math.max(getMinY(), 0); y < Math.min(getMaxY(), 255); y++) { // clamp to world height limits
for (int z = getMinZ(); z < getMaxZ(); z++) {
func.consume(x, y, z);
}
}
}
}
default AxisAlignedBB toAABB() {
return new AxisAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
default GridAlignedBB copy() {
return new GridAlignedBB(getMinX(), getMinY(), getMinZ(), getMaxX(), getMaxY(), getMaxZ());
}
}