145 lines
6.4 KiB
Java
145 lines
6.4 KiB
Java
/*
|
|
* Decompiled with CFR 0.152.
|
|
*
|
|
* Could not load the following classes:
|
|
* com.google.common.annotations.VisibleForTesting
|
|
* com.mojang.datafixers.util.Pair
|
|
* it.unimi.dsi.fastutil.ints.IntArrayList
|
|
*/
|
|
package net.minecraft.util;
|
|
|
|
import com.google.common.annotations.VisibleForTesting;
|
|
import com.mojang.datafixers.util.Pair;
|
|
import it.unimi.dsi.fastutil.ints.IntArrayList;
|
|
import java.util.Optional;
|
|
import java.util.function.Predicate;
|
|
import net.minecraft.core.BlockPos;
|
|
import net.minecraft.core.Direction;
|
|
import net.minecraft.world.level.BlockGetter;
|
|
import net.minecraft.world.level.block.Block;
|
|
import net.minecraft.world.level.block.state.BlockState;
|
|
|
|
public class BlockUtil {
|
|
public static FoundRectangle getLargestRectangleAround(BlockPos center, Direction.Axis axis1, int limit1, Direction.Axis axis2, int limit2, Predicate<BlockPos> test) {
|
|
IntBounds lastBounds;
|
|
int i;
|
|
BlockPos.MutableBlockPos pos = center.mutable();
|
|
Direction negativeDirection1 = Direction.get(Direction.AxisDirection.NEGATIVE, axis1);
|
|
Direction positiveDirection1 = negativeDirection1.getOpposite();
|
|
Direction negativeDirection2 = Direction.get(Direction.AxisDirection.NEGATIVE, axis2);
|
|
Direction positiveDirection2 = negativeDirection2.getOpposite();
|
|
int negativeDelta1 = BlockUtil.getLimit(test, pos.set(center), negativeDirection1, limit1);
|
|
int positiveDelta1 = BlockUtil.getLimit(test, pos.set(center), positiveDirection1, limit1);
|
|
int centerIndex1 = negativeDelta1;
|
|
IntBounds[] boundsByAxis1 = new IntBounds[centerIndex1 + 1 + positiveDelta1];
|
|
boundsByAxis1[centerIndex1] = new IntBounds(BlockUtil.getLimit(test, pos.set(center), negativeDirection2, limit2), BlockUtil.getLimit(test, pos.set(center), positiveDirection2, limit2));
|
|
int centerIndex2 = boundsByAxis1[centerIndex1].min;
|
|
for (i = 1; i <= negativeDelta1; ++i) {
|
|
lastBounds = boundsByAxis1[centerIndex1 - (i - 1)];
|
|
boundsByAxis1[centerIndex1 - i] = new IntBounds(BlockUtil.getLimit(test, pos.set(center).move(negativeDirection1, i), negativeDirection2, lastBounds.min), BlockUtil.getLimit(test, pos.set(center).move(negativeDirection1, i), positiveDirection2, lastBounds.max));
|
|
}
|
|
for (i = 1; i <= positiveDelta1; ++i) {
|
|
lastBounds = boundsByAxis1[centerIndex1 + i - 1];
|
|
boundsByAxis1[centerIndex1 + i] = new IntBounds(BlockUtil.getLimit(test, pos.set(center).move(positiveDirection1, i), negativeDirection2, lastBounds.min), BlockUtil.getLimit(test, pos.set(center).move(positiveDirection1, i), positiveDirection2, lastBounds.max));
|
|
}
|
|
int minAxis1 = 0;
|
|
int minAxis2 = 0;
|
|
int sizeAxis1 = 0;
|
|
int sizeAxis2 = 0;
|
|
int[] columns = new int[boundsByAxis1.length];
|
|
for (int i2 = centerIndex2; i2 >= 0; --i2) {
|
|
for (int i1 = 0; i1 < boundsByAxis1.length; ++i1) {
|
|
IntBounds bounds2 = boundsByAxis1[i1];
|
|
int min2 = centerIndex2 - bounds2.min;
|
|
int max2 = centerIndex2 + bounds2.max;
|
|
columns[i1] = i2 >= min2 && i2 <= max2 ? max2 + 1 - i2 : 0;
|
|
}
|
|
Pair<IntBounds, Integer> rectangle = BlockUtil.getMaxRectangleLocation(columns);
|
|
IntBounds boundsAxis1 = (IntBounds)rectangle.getFirst();
|
|
int newSizeAxis1 = 1 + boundsAxis1.max - boundsAxis1.min;
|
|
int newSizeAxis2 = (Integer)rectangle.getSecond();
|
|
if (newSizeAxis1 * newSizeAxis2 <= sizeAxis1 * sizeAxis2) continue;
|
|
minAxis1 = boundsAxis1.min;
|
|
minAxis2 = i2;
|
|
sizeAxis1 = newSizeAxis1;
|
|
sizeAxis2 = newSizeAxis2;
|
|
}
|
|
return new FoundRectangle(center.relative(axis1, minAxis1 - centerIndex1).relative(axis2, minAxis2 - centerIndex2), sizeAxis1, sizeAxis2);
|
|
}
|
|
|
|
private static int getLimit(Predicate<BlockPos> test, BlockPos.MutableBlockPos pos, Direction direction, int limit) {
|
|
int max;
|
|
for (max = 0; max < limit && test.test(pos.move(direction)); ++max) {
|
|
}
|
|
return max;
|
|
}
|
|
|
|
@VisibleForTesting
|
|
static Pair<IntBounds, Integer> getMaxRectangleLocation(int[] columns) {
|
|
int maxStart = 0;
|
|
int maxEnd = 0;
|
|
int maxHeight = 0;
|
|
IntArrayList stack = new IntArrayList();
|
|
stack.push(0);
|
|
for (int column = 1; column <= columns.length; ++column) {
|
|
int height;
|
|
int n = height = column == columns.length ? 0 : columns[column];
|
|
while (!stack.isEmpty()) {
|
|
int stackHeight = columns[stack.topInt()];
|
|
if (height >= stackHeight) {
|
|
stack.push(column);
|
|
break;
|
|
}
|
|
stack.popInt();
|
|
int start = stack.isEmpty() ? 0 : stack.topInt() + 1;
|
|
if (stackHeight * (column - start) <= maxHeight * (maxEnd - maxStart)) continue;
|
|
maxEnd = column;
|
|
maxStart = start;
|
|
maxHeight = stackHeight;
|
|
}
|
|
if (!stack.isEmpty()) continue;
|
|
stack.push(column);
|
|
}
|
|
return new Pair((Object)new IntBounds(maxStart, maxEnd - 1), (Object)maxHeight);
|
|
}
|
|
|
|
public static Optional<BlockPos> getTopConnectedBlock(BlockGetter level, BlockPos pos, Block bodyBlock, Direction growthDirection, Block headBlock) {
|
|
BlockState forwardState;
|
|
BlockPos.MutableBlockPos forwardPos = pos.mutable();
|
|
do {
|
|
forwardPos.move(growthDirection);
|
|
} while ((forwardState = level.getBlockState(forwardPos)).is(bodyBlock));
|
|
if (forwardState.is(headBlock)) {
|
|
return Optional.of(forwardPos);
|
|
}
|
|
return Optional.empty();
|
|
}
|
|
|
|
public static class IntBounds {
|
|
public final int min;
|
|
public final int max;
|
|
|
|
public IntBounds(int min, int max) {
|
|
this.min = min;
|
|
this.max = max;
|
|
}
|
|
|
|
public String toString() {
|
|
return "IntBounds{min=" + this.min + ", max=" + this.max + "}";
|
|
}
|
|
}
|
|
|
|
public static class FoundRectangle {
|
|
public final BlockPos minCorner;
|
|
public final int axis1Size;
|
|
public final int axis2Size;
|
|
|
|
public FoundRectangle(BlockPos minCorner, int axis1Size, int axis2Size) {
|
|
this.minCorner = minCorner;
|
|
this.axis1Size = axis1Size;
|
|
this.axis2Size = axis2Size;
|
|
}
|
|
}
|
|
}
|
|
|