/* * 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 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 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 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 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 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; } } }