270 lines
		
	
	
	
		
			8.1 KiB
		
	
	
	
		
			Java
		
	
	
	
	
	
			
		
		
	
	
			270 lines
		
	
	
	
		
			8.1 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 xSize, int ySize, int zSize) {
 | |
| 		if (xSize >= 0 && ySize >= 0 && zSize >= 0) {
 | |
| 			this.xSize = xSize;
 | |
| 			this.ySize = ySize;
 | |
| 			this.zSize = zSize;
 | |
| 		} else {
 | |
| 			throw new IllegalArgumentException("Need all positive sizes: x: " + xSize + ", y: " + ySize + ", z: " + zSize);
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public DiscreteVoxelShape rotate(OctahedralGroup octahedralGroup) {
 | |
| 		if (octahedralGroup == OctahedralGroup.IDENTITY) {
 | |
| 			return this;
 | |
| 		} else {
 | |
| 			Direction.Axis axis = octahedralGroup.permute(Direction.Axis.X);
 | |
| 			Direction.Axis axis2 = octahedralGroup.permute(Direction.Axis.Y);
 | |
| 			Direction.Axis axis3 = octahedralGroup.permute(Direction.Axis.Z);
 | |
| 			int i = axis.choose(this.xSize, this.ySize, this.zSize);
 | |
| 			int j = axis2.choose(this.xSize, this.ySize, this.zSize);
 | |
| 			int k = axis3.choose(this.xSize, this.ySize, this.zSize);
 | |
| 			boolean bl = octahedralGroup.inverts(axis);
 | |
| 			boolean bl2 = octahedralGroup.inverts(axis2);
 | |
| 			boolean bl3 = octahedralGroup.inverts(axis3);
 | |
| 			boolean bl4 = axis.choose(bl, bl2, bl3);
 | |
| 			boolean bl5 = axis2.choose(bl, bl2, bl3);
 | |
| 			boolean bl6 = axis3.choose(bl, bl2, bl3);
 | |
| 			DiscreteVoxelShape discreteVoxelShape = new BitSetDiscreteVoxelShape(i, j, k);
 | |
| 
 | |
| 			for (int l = 0; l < this.xSize; l++) {
 | |
| 				for (int m = 0; m < this.ySize; m++) {
 | |
| 					for (int n = 0; n < this.zSize; n++) {
 | |
| 						if (this.isFull(l, m, n)) {
 | |
| 							int o = axis.choose(l, m, n);
 | |
| 							int p = axis2.choose(l, m, n);
 | |
| 							int q = axis3.choose(l, m, n);
 | |
| 							discreteVoxelShape.fill(bl4 ? i - 1 - o : o, bl5 ? j - 1 - p : p, bl6 ? k - 1 - q : q);
 | |
| 						}
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 
 | |
| 			return discreteVoxelShape;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public boolean isFullWide(AxisCycle axis, int x, int y, int z) {
 | |
| 		return this.isFullWide(axis.cycle(x, y, z, Direction.Axis.X), axis.cycle(x, y, z, Direction.Axis.Y), axis.cycle(x, y, z, Direction.Axis.Z));
 | |
| 	}
 | |
| 
 | |
| 	public boolean isFullWide(int x, int y, int z) {
 | |
| 		if (x < 0 || y < 0 || z < 0) {
 | |
| 			return false;
 | |
| 		} else {
 | |
| 			return x < this.xSize && y < this.ySize && z < this.zSize ? this.isFull(x, y, z) : false;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public boolean isFull(AxisCycle rotation, int x, int y, int z) {
 | |
| 		return this.isFull(rotation.cycle(x, y, z, Direction.Axis.X), rotation.cycle(x, y, z, Direction.Axis.Y), rotation.cycle(x, y, z, Direction.Axis.Z));
 | |
| 	}
 | |
| 
 | |
| 	public abstract boolean isFull(int x, int y, int z);
 | |
| 
 | |
| 	public abstract void fill(int x, int y, int z);
 | |
| 
 | |
| 	public boolean isEmpty() {
 | |
| 		for (Direction.Axis axis : AXIS_VALUES) {
 | |
| 			if (this.firstFull(axis) >= this.lastFull(axis)) {
 | |
| 				return true;
 | |
| 			}
 | |
| 		}
 | |
| 
 | |
| 		return false;
 | |
| 	}
 | |
| 
 | |
| 	public abstract int firstFull(Direction.Axis axis);
 | |
| 
 | |
| 	public abstract int lastFull(Direction.Axis axis);
 | |
| 
 | |
| 	public int firstFull(Direction.Axis axis, int y, int z) {
 | |
| 		int i = this.getSize(axis);
 | |
| 		if (y >= 0 && z >= 0) {
 | |
| 			Direction.Axis axis2 = AxisCycle.FORWARD.cycle(axis);
 | |
| 			Direction.Axis axis3 = AxisCycle.BACKWARD.cycle(axis);
 | |
| 			if (y < this.getSize(axis2) && z < this.getSize(axis3)) {
 | |
| 				AxisCycle axisCycle = AxisCycle.between(Direction.Axis.X, axis);
 | |
| 
 | |
| 				for (int j = 0; j < i; j++) {
 | |
| 					if (this.isFull(axisCycle, j, y, z)) {
 | |
| 						return j;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return i;
 | |
| 			} else {
 | |
| 				return i;
 | |
| 			}
 | |
| 		} else {
 | |
| 			return i;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	/**
 | |
| 	 * Gives the index of the last filled part in the column.
 | |
| 	 */
 | |
| 	public int lastFull(Direction.Axis axis, int y, int z) {
 | |
| 		if (y >= 0 && z >= 0) {
 | |
| 			Direction.Axis axis2 = AxisCycle.FORWARD.cycle(axis);
 | |
| 			Direction.Axis axis3 = AxisCycle.BACKWARD.cycle(axis);
 | |
| 			if (y < this.getSize(axis2) && z < this.getSize(axis3)) {
 | |
| 				int i = this.getSize(axis);
 | |
| 				AxisCycle axisCycle = AxisCycle.between(Direction.Axis.X, axis);
 | |
| 
 | |
| 				for (int j = i - 1; j >= 0; j--) {
 | |
| 					if (this.isFull(axisCycle, j, y, z)) {
 | |
| 						return j + 1;
 | |
| 					}
 | |
| 				}
 | |
| 
 | |
| 				return 0;
 | |
| 			} else {
 | |
| 				return 0;
 | |
| 			}
 | |
| 		} else {
 | |
| 			return 0;
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public int getSize(Direction.Axis axis) {
 | |
| 		return axis.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 consumer, boolean combine) {
 | |
| 		this.forAllAxisEdges(consumer, AxisCycle.NONE, combine);
 | |
| 		this.forAllAxisEdges(consumer, AxisCycle.FORWARD, combine);
 | |
| 		this.forAllAxisEdges(consumer, AxisCycle.BACKWARD, combine);
 | |
| 	}
 | |
| 
 | |
| 	private void forAllAxisEdges(DiscreteVoxelShape.IntLineConsumer lineConsumer, AxisCycle axis, boolean combine) {
 | |
| 		AxisCycle axisCycle = axis.inverse();
 | |
| 		int i = this.getSize(axisCycle.cycle(Direction.Axis.X));
 | |
| 		int j = this.getSize(axisCycle.cycle(Direction.Axis.Y));
 | |
| 		int k = this.getSize(axisCycle.cycle(Direction.Axis.Z));
 | |
| 
 | |
| 		for (int l = 0; l <= i; l++) {
 | |
| 			for (int m = 0; m <= j; m++) {
 | |
| 				int n = -1;
 | |
| 
 | |
| 				for (int o = 0; o <= k; o++) {
 | |
| 					int p = 0;
 | |
| 					int q = 0;
 | |
| 
 | |
| 					for (int r = 0; r <= 1; r++) {
 | |
| 						for (int s = 0; s <= 1; s++) {
 | |
| 							if (this.isFullWide(axisCycle, l + r - 1, m + s - 1, o)) {
 | |
| 								p++;
 | |
| 								q ^= r ^ s;
 | |
| 							}
 | |
| 						}
 | |
| 					}
 | |
| 
 | |
| 					if (p == 1 || p == 3 || p == 2 && (q & 1) == 0) {
 | |
| 						if (combine) {
 | |
| 							if (n == -1) {
 | |
| 								n = o;
 | |
| 							}
 | |
| 						} else {
 | |
| 							lineConsumer.consume(
 | |
| 								axisCycle.cycle(l, m, o, Direction.Axis.X),
 | |
| 								axisCycle.cycle(l, m, o, Direction.Axis.Y),
 | |
| 								axisCycle.cycle(l, m, o, Direction.Axis.Z),
 | |
| 								axisCycle.cycle(l, m, o + 1, Direction.Axis.X),
 | |
| 								axisCycle.cycle(l, m, o + 1, Direction.Axis.Y),
 | |
| 								axisCycle.cycle(l, m, o + 1, Direction.Axis.Z)
 | |
| 							);
 | |
| 						}
 | |
| 					} else if (n != -1) {
 | |
| 						lineConsumer.consume(
 | |
| 							axisCycle.cycle(l, m, n, Direction.Axis.X),
 | |
| 							axisCycle.cycle(l, m, n, Direction.Axis.Y),
 | |
| 							axisCycle.cycle(l, m, n, Direction.Axis.Z),
 | |
| 							axisCycle.cycle(l, m, o, Direction.Axis.X),
 | |
| 							axisCycle.cycle(l, m, o, Direction.Axis.Y),
 | |
| 							axisCycle.cycle(l, m, o, Direction.Axis.Z)
 | |
| 						);
 | |
| 						n = -1;
 | |
| 					}
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public void forAllBoxes(DiscreteVoxelShape.IntLineConsumer consumer, boolean combine) {
 | |
| 		BitSetDiscreteVoxelShape.forAllBoxes(this, consumer, combine);
 | |
| 	}
 | |
| 
 | |
| 	public void forAllFaces(DiscreteVoxelShape.IntFaceConsumer faceConsumer) {
 | |
| 		this.forAllAxisFaces(faceConsumer, AxisCycle.NONE);
 | |
| 		this.forAllAxisFaces(faceConsumer, AxisCycle.FORWARD);
 | |
| 		this.forAllAxisFaces(faceConsumer, AxisCycle.BACKWARD);
 | |
| 	}
 | |
| 
 | |
| 	private void forAllAxisFaces(DiscreteVoxelShape.IntFaceConsumer faceConsumer, AxisCycle axisRotation) {
 | |
| 		AxisCycle axisCycle = axisRotation.inverse();
 | |
| 		Direction.Axis 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(axis);
 | |
| 		Direction direction = Direction.fromAxisAndDirection(axis, Direction.AxisDirection.NEGATIVE);
 | |
| 		Direction direction2 = Direction.fromAxisAndDirection(axis, Direction.AxisDirection.POSITIVE);
 | |
| 
 | |
| 		for (int l = 0; l < i; l++) {
 | |
| 			for (int m = 0; m < j; m++) {
 | |
| 				boolean bl = false;
 | |
| 
 | |
| 				for (int n = 0; n <= k; n++) {
 | |
| 					boolean bl2 = n != k && this.isFull(axisCycle, l, m, n);
 | |
| 					if (!bl && bl2) {
 | |
| 						faceConsumer.consume(
 | |
| 							direction, axisCycle.cycle(l, m, n, Direction.Axis.X), axisCycle.cycle(l, m, n, Direction.Axis.Y), axisCycle.cycle(l, m, n, Direction.Axis.Z)
 | |
| 						);
 | |
| 					}
 | |
| 
 | |
| 					if (bl && !bl2) {
 | |
| 						faceConsumer.consume(
 | |
| 							direction2,
 | |
| 							axisCycle.cycle(l, m, n - 1, Direction.Axis.X),
 | |
| 							axisCycle.cycle(l, m, n - 1, Direction.Axis.Y),
 | |
| 							axisCycle.cycle(l, m, n - 1, Direction.Axis.Z)
 | |
| 						);
 | |
| 					}
 | |
| 
 | |
| 					bl = bl2;
 | |
| 				}
 | |
| 			}
 | |
| 		}
 | |
| 	}
 | |
| 
 | |
| 	public interface IntFaceConsumer {
 | |
| 		void consume(Direction direction, int i, int j, int k);
 | |
| 	}
 | |
| 
 | |
| 	public interface IntLineConsumer {
 | |
| 		void consume(int i, int j, int k, int l, int m, int n);
 | |
| 	}
 | |
| }
 |