278 lines
11 KiB
Java
278 lines
11 KiB
Java
package net.minecraft.world.phys.shapes;
|
|
|
|
import com.mojang.math.OctahedralGroup;
|
|
import net.minecraft.core.AxisCycle;
|
|
import net.minecraft.core.Direction;
|
|
|
|
public abstract class DiscreteVoxelShape {
|
|
private static final Direction.Axis[] AXIS_VALUES = Direction.Axis.values();
|
|
protected final int xSize;
|
|
protected final int ySize;
|
|
protected final int zSize;
|
|
|
|
protected DiscreteVoxelShape(int p_82787_, int p_82788_, int p_82789_) {
|
|
if (p_82787_ >= 0 && p_82788_ >= 0 && p_82789_ >= 0) {
|
|
this.xSize = p_82787_;
|
|
this.ySize = p_82788_;
|
|
this.zSize = p_82789_;
|
|
} else {
|
|
throw new IllegalArgumentException("Need all positive sizes: x: " + p_82787_ + ", y: " + p_82788_ + ", z: " + p_82789_);
|
|
}
|
|
}
|
|
|
|
public DiscreteVoxelShape rotate(OctahedralGroup p_393550_) {
|
|
if (p_393550_ == OctahedralGroup.IDENTITY) {
|
|
return this;
|
|
} else {
|
|
Direction.Axis direction$axis = p_393550_.permute(Direction.Axis.X);
|
|
Direction.Axis direction$axis1 = p_393550_.permute(Direction.Axis.Y);
|
|
Direction.Axis direction$axis2 = p_393550_.permute(Direction.Axis.Z);
|
|
int i = direction$axis.choose(this.xSize, this.ySize, this.zSize);
|
|
int j = direction$axis1.choose(this.xSize, this.ySize, this.zSize);
|
|
int k = direction$axis2.choose(this.xSize, this.ySize, this.zSize);
|
|
boolean flag = p_393550_.inverts(direction$axis);
|
|
boolean flag1 = p_393550_.inverts(direction$axis1);
|
|
boolean flag2 = p_393550_.inverts(direction$axis2);
|
|
boolean flag3 = direction$axis.choose(flag, flag1, flag2);
|
|
boolean flag4 = direction$axis1.choose(flag, flag1, flag2);
|
|
boolean flag5 = direction$axis2.choose(flag, flag1, flag2);
|
|
DiscreteVoxelShape discretevoxelshape = new BitSetDiscreteVoxelShape(i, j, k);
|
|
|
|
for (int l = 0; l < this.xSize; l++) {
|
|
for (int i1 = 0; i1 < this.ySize; i1++) {
|
|
for (int j1 = 0; j1 < this.zSize; j1++) {
|
|
if (this.isFull(l, i1, j1)) {
|
|
int k1 = direction$axis.choose(l, i1, j1);
|
|
int l1 = direction$axis1.choose(l, i1, j1);
|
|
int i2 = direction$axis2.choose(l, i1, j1);
|
|
discretevoxelshape.fill(flag3 ? i - 1 - k1 : k1, flag4 ? j - 1 - l1 : l1, flag5 ? k - 1 - i2 : i2);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return discretevoxelshape;
|
|
}
|
|
}
|
|
|
|
public boolean isFullWide(AxisCycle p_82823_, int p_82824_, int p_82825_, int p_82826_) {
|
|
return this.isFullWide(
|
|
p_82823_.cycle(p_82824_, p_82825_, p_82826_, Direction.Axis.X),
|
|
p_82823_.cycle(p_82824_, p_82825_, p_82826_, Direction.Axis.Y),
|
|
p_82823_.cycle(p_82824_, p_82825_, p_82826_, Direction.Axis.Z)
|
|
);
|
|
}
|
|
|
|
public boolean isFullWide(int p_82847_, int p_82848_, int p_82849_) {
|
|
if (p_82847_ < 0 || p_82848_ < 0 || p_82849_ < 0) {
|
|
return false;
|
|
} else {
|
|
return p_82847_ < this.xSize && p_82848_ < this.ySize && p_82849_ < this.zSize ? this.isFull(p_82847_, p_82848_, p_82849_) : false;
|
|
}
|
|
}
|
|
|
|
public boolean isFull(AxisCycle p_82836_, int p_82837_, int p_82838_, int p_82839_) {
|
|
return this.isFull(
|
|
p_82836_.cycle(p_82837_, p_82838_, p_82839_, Direction.Axis.X),
|
|
p_82836_.cycle(p_82837_, p_82838_, p_82839_, Direction.Axis.Y),
|
|
p_82836_.cycle(p_82837_, p_82838_, p_82839_, Direction.Axis.Z)
|
|
);
|
|
}
|
|
|
|
public abstract boolean isFull(int p_82829_, int p_82830_, int p_82831_);
|
|
|
|
public abstract void fill(int p_165998_, int p_165999_, int p_166000_);
|
|
|
|
public boolean isEmpty() {
|
|
for (Direction.Axis direction$axis : AXIS_VALUES) {
|
|
if (this.firstFull(direction$axis) >= this.lastFull(direction$axis)) {
|
|
return true;
|
|
}
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
public abstract int firstFull(Direction.Axis p_82827_);
|
|
|
|
public abstract int lastFull(Direction.Axis p_82840_);
|
|
|
|
public int firstFull(Direction.Axis p_165995_, int p_165996_, int p_165997_) {
|
|
int i = this.getSize(p_165995_);
|
|
if (p_165996_ >= 0 && p_165997_ >= 0) {
|
|
Direction.Axis direction$axis = AxisCycle.FORWARD.cycle(p_165995_);
|
|
Direction.Axis direction$axis1 = AxisCycle.BACKWARD.cycle(p_165995_);
|
|
if (p_165996_ < this.getSize(direction$axis) && p_165997_ < this.getSize(direction$axis1)) {
|
|
AxisCycle axiscycle = AxisCycle.between(Direction.Axis.X, p_165995_);
|
|
|
|
for (int j = 0; j < i; j++) {
|
|
if (this.isFull(axiscycle, j, p_165996_, p_165997_)) {
|
|
return j;
|
|
}
|
|
}
|
|
|
|
return i;
|
|
} else {
|
|
return i;
|
|
}
|
|
} else {
|
|
return i;
|
|
}
|
|
}
|
|
|
|
public int lastFull(Direction.Axis p_82842_, int p_82843_, int p_82844_) {
|
|
if (p_82843_ >= 0 && p_82844_ >= 0) {
|
|
Direction.Axis direction$axis = AxisCycle.FORWARD.cycle(p_82842_);
|
|
Direction.Axis direction$axis1 = AxisCycle.BACKWARD.cycle(p_82842_);
|
|
if (p_82843_ < this.getSize(direction$axis) && p_82844_ < this.getSize(direction$axis1)) {
|
|
int i = this.getSize(p_82842_);
|
|
AxisCycle axiscycle = AxisCycle.between(Direction.Axis.X, p_82842_);
|
|
|
|
for (int j = i - 1; j >= 0; j--) {
|
|
if (this.isFull(axiscycle, j, p_82843_, p_82844_)) {
|
|
return j + 1;
|
|
}
|
|
}
|
|
|
|
return 0;
|
|
} else {
|
|
return 0;
|
|
}
|
|
} else {
|
|
return 0;
|
|
}
|
|
}
|
|
|
|
public int getSize(Direction.Axis p_82851_) {
|
|
return p_82851_.choose(this.xSize, this.ySize, this.zSize);
|
|
}
|
|
|
|
public int getXSize() {
|
|
return this.getSize(Direction.Axis.X);
|
|
}
|
|
|
|
public int getYSize() {
|
|
return this.getSize(Direction.Axis.Y);
|
|
}
|
|
|
|
public int getZSize() {
|
|
return this.getSize(Direction.Axis.Z);
|
|
}
|
|
|
|
public void forAllEdges(DiscreteVoxelShape.IntLineConsumer p_82820_, boolean p_82821_) {
|
|
this.forAllAxisEdges(p_82820_, AxisCycle.NONE, p_82821_);
|
|
this.forAllAxisEdges(p_82820_, AxisCycle.FORWARD, p_82821_);
|
|
this.forAllAxisEdges(p_82820_, AxisCycle.BACKWARD, p_82821_);
|
|
}
|
|
|
|
private void forAllAxisEdges(DiscreteVoxelShape.IntLineConsumer p_82816_, AxisCycle p_82817_, boolean p_82818_) {
|
|
AxisCycle axiscycle = p_82817_.inverse();
|
|
int j = this.getSize(axiscycle.cycle(Direction.Axis.X));
|
|
int k = this.getSize(axiscycle.cycle(Direction.Axis.Y));
|
|
int l = this.getSize(axiscycle.cycle(Direction.Axis.Z));
|
|
|
|
for (int i1 = 0; i1 <= j; i1++) {
|
|
for (int j1 = 0; j1 <= k; j1++) {
|
|
int i = -1;
|
|
|
|
for (int k1 = 0; k1 <= l; k1++) {
|
|
int l1 = 0;
|
|
int i2 = 0;
|
|
|
|
for (int j2 = 0; j2 <= 1; j2++) {
|
|
for (int k2 = 0; k2 <= 1; k2++) {
|
|
if (this.isFullWide(axiscycle, i1 + j2 - 1, j1 + k2 - 1, k1)) {
|
|
l1++;
|
|
i2 ^= j2 ^ k2;
|
|
}
|
|
}
|
|
}
|
|
|
|
if (l1 == 1 || l1 == 3 || l1 == 2 && (i2 & 1) == 0) {
|
|
if (p_82818_) {
|
|
if (i == -1) {
|
|
i = k1;
|
|
}
|
|
} else {
|
|
p_82816_.consume(
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.X),
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.Y),
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.Z),
|
|
axiscycle.cycle(i1, j1, k1 + 1, Direction.Axis.X),
|
|
axiscycle.cycle(i1, j1, k1 + 1, Direction.Axis.Y),
|
|
axiscycle.cycle(i1, j1, k1 + 1, Direction.Axis.Z)
|
|
);
|
|
}
|
|
} else if (i != -1) {
|
|
p_82816_.consume(
|
|
axiscycle.cycle(i1, j1, i, Direction.Axis.X),
|
|
axiscycle.cycle(i1, j1, i, Direction.Axis.Y),
|
|
axiscycle.cycle(i1, j1, i, Direction.Axis.Z),
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.X),
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.Y),
|
|
axiscycle.cycle(i1, j1, k1, Direction.Axis.Z)
|
|
);
|
|
i = -1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public void forAllBoxes(DiscreteVoxelShape.IntLineConsumer p_82833_, boolean p_82834_) {
|
|
BitSetDiscreteVoxelShape.forAllBoxes(this, p_82833_, p_82834_);
|
|
}
|
|
|
|
public void forAllFaces(DiscreteVoxelShape.IntFaceConsumer p_82811_) {
|
|
this.forAllAxisFaces(p_82811_, AxisCycle.NONE);
|
|
this.forAllAxisFaces(p_82811_, AxisCycle.FORWARD);
|
|
this.forAllAxisFaces(p_82811_, AxisCycle.BACKWARD);
|
|
}
|
|
|
|
private void forAllAxisFaces(DiscreteVoxelShape.IntFaceConsumer p_82813_, AxisCycle p_82814_) {
|
|
AxisCycle axiscycle = p_82814_.inverse();
|
|
Direction.Axis direction$axis = axiscycle.cycle(Direction.Axis.Z);
|
|
int i = this.getSize(axiscycle.cycle(Direction.Axis.X));
|
|
int j = this.getSize(axiscycle.cycle(Direction.Axis.Y));
|
|
int k = this.getSize(direction$axis);
|
|
Direction direction = Direction.fromAxisAndDirection(direction$axis, Direction.AxisDirection.NEGATIVE);
|
|
Direction direction1 = Direction.fromAxisAndDirection(direction$axis, Direction.AxisDirection.POSITIVE);
|
|
|
|
for (int l = 0; l < i; l++) {
|
|
for (int i1 = 0; i1 < j; i1++) {
|
|
boolean flag = false;
|
|
|
|
for (int j1 = 0; j1 <= k; j1++) {
|
|
boolean flag1 = j1 != k && this.isFull(axiscycle, l, i1, j1);
|
|
if (!flag && flag1) {
|
|
p_82813_.consume(
|
|
direction,
|
|
axiscycle.cycle(l, i1, j1, Direction.Axis.X),
|
|
axiscycle.cycle(l, i1, j1, Direction.Axis.Y),
|
|
axiscycle.cycle(l, i1, j1, Direction.Axis.Z)
|
|
);
|
|
}
|
|
|
|
if (flag && !flag1) {
|
|
p_82813_.consume(
|
|
direction1,
|
|
axiscycle.cycle(l, i1, j1 - 1, Direction.Axis.X),
|
|
axiscycle.cycle(l, i1, j1 - 1, Direction.Axis.Y),
|
|
axiscycle.cycle(l, i1, j1 - 1, Direction.Axis.Z)
|
|
);
|
|
}
|
|
|
|
flag = flag1;
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
public interface IntFaceConsumer {
|
|
void consume(Direction p_82854_, int p_82855_, int p_82856_, int p_82857_);
|
|
}
|
|
|
|
public interface IntLineConsumer {
|
|
void consume(int p_82859_, int p_82860_, int p_82861_, int p_82862_, int p_82863_, int p_82864_);
|
|
}
|
|
} |