package net.minecraft.world.phys.shapes; import java.util.BitSet; import net.minecraft.core.Direction; public final class BitSetDiscreteVoxelShape extends DiscreteVoxelShape { private final BitSet storage; private int xMin; private int yMin; private int zMin; private int xMax; private int yMax; private int zMax; public BitSetDiscreteVoxelShape(int i, int j, int k) { super(i, j, k); this.storage = new BitSet(i * j * k); this.xMin = i; this.yMin = j; this.zMin = k; } public static BitSetDiscreteVoxelShape withFilledBounds(int x, int y, int z, int xMin, int yMin, int zMin, int xMax, int yMax, int zMax) { BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = new BitSetDiscreteVoxelShape(x, y, z); bitSetDiscreteVoxelShape.xMin = xMin; bitSetDiscreteVoxelShape.yMin = yMin; bitSetDiscreteVoxelShape.zMin = zMin; bitSetDiscreteVoxelShape.xMax = xMax; bitSetDiscreteVoxelShape.yMax = yMax; bitSetDiscreteVoxelShape.zMax = zMax; for (int i = xMin; i < xMax; i++) { for (int j = yMin; j < yMax; j++) { for (int k = zMin; k < zMax; k++) { bitSetDiscreteVoxelShape.fillUpdateBounds(i, j, k, false); } } } return bitSetDiscreteVoxelShape; } public BitSetDiscreteVoxelShape(DiscreteVoxelShape shape) { super(shape.xSize, shape.ySize, shape.zSize); if (shape instanceof BitSetDiscreteVoxelShape) { this.storage = (BitSet)((BitSetDiscreteVoxelShape)shape).storage.clone(); } else { this.storage = new BitSet(this.xSize * this.ySize * this.zSize); for (int i = 0; i < this.xSize; i++) { for (int j = 0; j < this.ySize; j++) { for (int k = 0; k < this.zSize; k++) { if (shape.isFull(i, j, k)) { this.storage.set(this.getIndex(i, j, k)); } } } } } this.xMin = shape.firstFull(Direction.Axis.X); this.yMin = shape.firstFull(Direction.Axis.Y); this.zMin = shape.firstFull(Direction.Axis.Z); this.xMax = shape.lastFull(Direction.Axis.X); this.yMax = shape.lastFull(Direction.Axis.Y); this.zMax = shape.lastFull(Direction.Axis.Z); } protected int getIndex(int x, int y, int z) { return (x * this.ySize + y) * this.zSize + z; } @Override public boolean isFull(int x, int y, int z) { return this.storage.get(this.getIndex(x, y, z)); } private void fillUpdateBounds(int x, int y, int z, boolean update) { this.storage.set(this.getIndex(x, y, z)); if (update) { this.xMin = Math.min(this.xMin, x); this.yMin = Math.min(this.yMin, y); this.zMin = Math.min(this.zMin, z); this.xMax = Math.max(this.xMax, x + 1); this.yMax = Math.max(this.yMax, y + 1); this.zMax = Math.max(this.zMax, z + 1); } } @Override public void fill(int x, int y, int z) { this.fillUpdateBounds(x, y, z, true); } @Override public boolean isEmpty() { return this.storage.isEmpty(); } @Override public int firstFull(Direction.Axis axis) { return axis.choose(this.xMin, this.yMin, this.zMin); } @Override public int lastFull(Direction.Axis axis) { return axis.choose(this.xMax, this.yMax, this.zMax); } static BitSetDiscreteVoxelShape join( DiscreteVoxelShape mainShape, DiscreteVoxelShape secondaryShape, IndexMerger mergerX, IndexMerger mergerY, IndexMerger mergerZ, BooleanOp operator ) { BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = new BitSetDiscreteVoxelShape(mergerX.size() - 1, mergerY.size() - 1, mergerZ.size() - 1); int[] is = new int[]{Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MAX_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE, Integer.MIN_VALUE}; mergerX.forMergedIndexes((i, j, k) -> { boolean[] bls = new boolean[]{false}; mergerY.forMergedIndexes((l, m, n) -> { boolean[] bls2 = new boolean[]{false}; mergerZ.forMergedIndexes((o, p, q) -> { if (operator.apply(mainShape.isFullWide(i, l, o), secondaryShape.isFullWide(j, m, p))) { bitSetDiscreteVoxelShape.storage.set(bitSetDiscreteVoxelShape.getIndex(k, n, q)); is[2] = Math.min(is[2], q); is[5] = Math.max(is[5], q); bls2[0] = true; } return true; }); if (bls2[0]) { is[1] = Math.min(is[1], n); is[4] = Math.max(is[4], n); bls[0] = true; } return true; }); if (bls[0]) { is[0] = Math.min(is[0], k); is[3] = Math.max(is[3], k); } return true; }); bitSetDiscreteVoxelShape.xMin = is[0]; bitSetDiscreteVoxelShape.yMin = is[1]; bitSetDiscreteVoxelShape.zMin = is[2]; bitSetDiscreteVoxelShape.xMax = is[3] + 1; bitSetDiscreteVoxelShape.yMax = is[4] + 1; bitSetDiscreteVoxelShape.zMax = is[5] + 1; return bitSetDiscreteVoxelShape; } protected static void forAllBoxes(DiscreteVoxelShape shape, DiscreteVoxelShape.IntLineConsumer consumer, boolean combine) { BitSetDiscreteVoxelShape bitSetDiscreteVoxelShape = new BitSetDiscreteVoxelShape(shape); for (int i = 0; i < bitSetDiscreteVoxelShape.ySize; i++) { for (int j = 0; j < bitSetDiscreteVoxelShape.xSize; j++) { int k = -1; for (int l = 0; l <= bitSetDiscreteVoxelShape.zSize; l++) { if (bitSetDiscreteVoxelShape.isFullWide(j, i, l)) { if (combine) { if (k == -1) { k = l; } } else { consumer.consume(j, i, l, j + 1, i + 1, l + 1); } } else if (k != -1) { int m = j; int n = i; bitSetDiscreteVoxelShape.clearZStrip(k, l, j, i); while (bitSetDiscreteVoxelShape.isZStripFull(k, l, m + 1, i)) { bitSetDiscreteVoxelShape.clearZStrip(k, l, m + 1, i); m++; } while (bitSetDiscreteVoxelShape.isXZRectangleFull(j, m + 1, k, l, n + 1)) { for (int o = j; o <= m; o++) { bitSetDiscreteVoxelShape.clearZStrip(k, l, o, n + 1); } n++; } consumer.consume(j, i, k, m + 1, n + 1, l); k = -1; } } } } } private boolean isZStripFull(int zMin, int zMax, int x, int y) { return x < this.xSize && y < this.ySize ? this.storage.nextClearBit(this.getIndex(x, y, zMin)) >= this.getIndex(x, y, zMax) : false; } private boolean isXZRectangleFull(int xMin, int xMax, int zMin, int zMax, int y) { for (int i = xMin; i < xMax; i++) { if (!this.isZStripFull(zMin, zMax, i, y)) { return false; } } return true; } private void clearZStrip(int zMin, int zMax, int x, int y) { this.storage.clear(this.getIndex(x, y, zMin), this.getIndex(x, y, zMax)); } public boolean isInterior(int x, int y, int z) { boolean bl = x > 0 && x < this.xSize - 1 && y > 0 && y < this.ySize - 1 && z > 0 && z < this.zSize - 1; return bl && this.isFull(x, y, z) && this.isFull(x - 1, y, z) && this.isFull(x + 1, y, z) && this.isFull(x, y - 1, z) && this.isFull(x, y + 1, z) && this.isFull(x, y, z - 1) && this.isFull(x, y, z + 1); } }