ShapeUtil

ShapeUtil

Версия(и) Minecraft
1.20.1
Код запилен был на версию 1.20.1, но учитывая что сама суть AABB не менялась, я думаю никаких совершенно проблем актуализировать это на любую другую версию нет. Особых комментариев не даю, думаю тут все читаемо. Моя старая утилита могла поворачивать только обычные кубы. Этот поворачивает уже баундбокс любого вида (по сути та же логика, просто составной шейп разделяется на примитивы, каждый поворачивается по очереди и затем все собирается обратно). Думаю если дальше мне будет надо, я доделаю это до новых поворотов также не только по Y, но и по X или Z осям, а также отражения. Но пока мне эт не нужно.
Енум сделан для красоты, в принципе можно напрямую пользоваться методами поворота, если надо)
Кодэ:
import net.minecraft.world.level.block.Block;
import net.minecraft.world.phys.AABB;
import net.minecraft.world.phys.shapes.Shapes;
import net.minecraft.world.phys.shapes.VoxelShape;
/**
 * A util class for turning boundboxes
 * @author Tesmio
 */
public class ShapesUtil {

    public static final VoxelShape FULL_CUBE = Block.box(0.0, 0.0, 0.0, 16.0, 16.0, 16.0);
    public static final VoxelShapeUtil INSTANCE = new VoxelShapeUtil();

    public enum RotationDegree {
        D90,
        D180,
        D270
    }

    public static VoxelShape rotate(VoxelShape vs, RotationDegree degree) {
        switch (degree) {
            case D90:
                return rotate90(vs);
            case D180:
                return rotate180(vs);
            case D270:
                return rotate270(vs);
            default:
                throw new IllegalArgumentException("Unsupported rotation degree: " + degree);
        }
    }

    private static VoxelShape rotate90(VoxelShape vs) {
        VoxelShape result = Shapes.empty();
        for (AABB box : vs.toAabbs()) {
            double newMinX = 0.5 + (box.minZ - 0.5);
            double newMaxX = 0.5 + (box.maxZ - 0.5);
            double newMinZ = 0.5 - (box.maxX - 0.5);
            double newMaxZ = 0.5 - (box.minX - 0.5);

            double minX = Math.min(newMinX, newMaxX);
            double maxX = Math.max(newMinX, newMaxX);
            double minZ = Math.min(newMinZ, newMaxZ);
            double maxZ = Math.max(newMinZ, newMaxZ);

            result = Shapes.or(result, Shapes.create(minX, box.minY, minZ, maxX, box.maxY, maxZ));
        }
        return result;
    }

    private static VoxelShape rotate180(VoxelShape vs) {
        VoxelShape result = Shapes.empty();
        for (AABB box : vs.toAabbs()) {
            double newMinX = 1.0 - box.maxX;
            double newMaxX = 1.0 - box.minX;
            double newMinZ = 1.0 - box.maxZ;
            double newMaxZ = 1.0 - box.minZ;

            double minX = Math.min(newMinX, newMaxX);
            double maxX = Math.max(newMinX, newMaxX);
            double minZ = Math.min(newMinZ, newMaxZ);
            double maxZ = Math.max(newMinZ, newMaxZ);

            result = Shapes.or(result, Shapes.create(minX, box.minY, minZ, maxX, box.maxY, maxZ));
        }
        return result;
    }

    private static VoxelShape rotate270(VoxelShape vs) {
        VoxelShape result = Shapes.empty();
        for (AABB box : vs.toAabbs()) {
            double newMinX = 0.5 - (box.maxZ - 0.5);
            double newMaxX = 0.5 - (box.minZ - 0.5);
            double newMinZ = 0.5 + (box.minX - 0.5);
            double newMaxZ = 0.5 + (box.maxX - 0.5);

            double minX = Math.min(newMinX, newMaxX);
            double maxX = Math.max(newMinX, newMaxX);
            double minZ = Math.min(newMinZ, newMaxZ);
            double maxZ = Math.max(newMinZ, newMaxZ);

            result = Shapes.or(result, Shapes.create(minX, box.minY, minZ, maxX, box.maxY, maxZ));
        }
        return result;
    }
}


Пользоваться соответственно так:
ShapesUtil.rotate(shape, ShapesUtil.RotationDegree.D180 //поворот на 180 например
Автор
Maxik
Просмотры
691
Первый выпуск
Обновление
Оценка
0.00 звёзд 0 оценок

Другие ресурсы пользователя Maxik

Назад
Сверху