All Downloads are FREE. Search and download functionalities are using the official Maven repository.

top.hendrixshen.magiclib.util.minecraft.PositionUtil Maven / Gradle / Ivy

There is a newer version: 0.6.59
Show newest version
/*
 * This file is part of the TweakerMore project, licensed under the
 * GNU Lesser General Public License v3.0
 *
 * Copyright (C) 2023  Fallen_Breath and contributors
 *
 * TweakerMore is free software: you can redistribute it and/or modify
 * it under the terms of the GNU Lesser General Public License as published by
 * the Free Software Foundation, either version 3 of the License, or
 * (at your option) any later version.
 *
 * TweakerMore is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public License
 * along with TweakerMore.  If not, see .
 */

package top.hendrixshen.magiclib.util.minecraft;

import com.google.common.collect.Lists;
import it.unimi.dsi.fastutil.longs.Long2DoubleOpenHashMap;
import it.unimi.dsi.fastutil.longs.LongOpenHashSet;
import org.jetbrains.annotations.NotNull;

import java.util.Collection;
import java.util.Collections;
import java.util.List;
import java.util.function.Consumer;
import net.minecraft.class_2338;
import net.minecraft.class_243;

/**
 * Reference to TweakerMore
 */
public class PositionUtil {
    public static @NotNull class_243 centerOf(@NotNull class_2338 blockPos) {
        return new class_243(blockPos.method_10263() + 0.5, blockPos.method_10264() + 0.5, blockPos.method_10260() + 0.5);
    }

    public static @NotNull Collection boxSurface(@NotNull class_2338 pos1, @NotNull class_2338 pos2) {
        int minX = Math.min(pos1.method_10263(), pos2.method_10263());
        int minY = Math.min(pos1.method_10264(), pos2.method_10264());
        int minZ = Math.min(pos1.method_10260(), pos2.method_10260());
        int maxX = Math.max(pos1.method_10263(), pos2.method_10263());
        int maxY = Math.max(pos1.method_10264(), pos2.method_10264());
        int maxZ = Math.max(pos1.method_10260(), pos2.method_10260());
        LongOpenHashSet set = new LongOpenHashSet();
        List result = Lists.newArrayList();
        Consumer storage = pos -> {
            if (set.add(pos.method_10063())) {
                result.add(pos);
            }
        };

        for (int x = minX; x <= maxX; x++) {
            for (int y = minY; y <= maxY; y++) {
                storage.accept(new class_2338(x, y, minZ));
                storage.accept(new class_2338(x, y, maxZ));
            }
        }

        for (int x = minX; x <= maxX; x++) {
            for (int z = minZ; z <= maxZ; z++) {
                storage.accept(new class_2338(x, minY, z));
                storage.accept(new class_2338(x, maxY, z));
            }
        }

        for (int y = minY; y <= maxY; y++) {
            for (int z = minZ; z <= maxZ; z++) {
                storage.accept(new class_2338(minX, y, z));
                storage.accept(new class_2338(maxX, y, z));
            }
        }

        return result;
    }

    public static Collection beam(class_243 startPos, @NotNull class_243 endPos, double coneAngle, BeamMode mode) {
        class_243 dir1 = endPos.method_1020(startPos).method_1029();

        if (dir1 == class_243.field_1353) {
            return Collections.emptyList();
        }

        double maxLen = startPos.method_1022(endPos);
        double step = 1 / (1 + Math.sin(coneAngle));
        Long2DoubleOpenHashMap positions = new Long2DoubleOpenHashMap();
        class_2338 lastMin = null;
        class_2338 lastMax = null;

        for (double len = 0, angle = coneAngle; len < maxLen + step; len += step) {
            double r = len * Math.sin(angle);
            class_243 vec3 = startPos.method_1019(dir1.method_1021(len));
            class_243 a = vec3.method_1031(-r, -r, -r);
            class_243 b = vec3.method_1031(+r, +r, +r);
            class_2338 pos1 = new class_2338((int) Math.floor(a.field_1352), (int) Math.floor(a.field_1351), (int) Math.floor(a.field_1350));
            class_2338 pos2 = new class_2338((int) Math.ceil(b.field_1352), (int) Math.ceil(b.field_1351), (int) Math.ceil(b.field_1350));

            if (lastMin != null) {
                // Optimize increasing PositionUtil.boxSurface
                int minX = pos1.method_10263();
                int minY = pos1.method_10264();
                int minZ = pos1.method_10260();
                int maxX = pos2.method_10263();
                int maxY = pos2.method_10264();
                int maxZ = pos2.method_10260();

                // minX changed
                if (minX != lastMin.method_10263()) {
                    for (int y = minY; y <= maxY; y++) {
                        for (int z = minZ; z <= maxZ; z++) {
                            positions.putIfAbsent(new class_2338(minX, y, z).method_10063(), angle);
                        }
                    }
                }

                // maxX changed
                if (maxX != lastMax.method_10263()) {
                    for (int y = minY; y <= maxY; y++) {
                        for (int z = minZ; z <= maxZ; z++) {
                            positions.putIfAbsent(new class_2338(maxX, y, z).method_10063(), angle);
                        }
                    }
                }

                // minY changed
                if (minY != lastMin.method_10264()) {
                    for (int x = minX; x <= maxX; x++) {
                        for (int z = minZ; z <= maxZ; z++) {
                            positions.putIfAbsent(new class_2338(x, minY, z).method_10063(), angle);
                        }
                    }
                }

                // minY changed
                if (maxY != lastMax.method_10264()) {
                    for (int x = minX; x <= maxX; x++) {
                        for (int z = minZ; z <= maxZ; z++) {
                            positions.putIfAbsent(new class_2338(x, maxY, z).method_10063(), angle);
                        }
                    }
                }

                // minZ changed
                if (minZ != lastMin.method_10260()) {
                    for (int x = minX; x <= maxX; x++) {
                        for (int y = minY; y <= maxY; y++) {
                            positions.putIfAbsent(new class_2338(x, y, minZ).method_10063(), angle);
                        }
                    }
                }

                // maxZ changed
                if (maxZ != lastMin.method_10260()) {
                    for (int x = minX; x <= maxX; x++) {
                        for (int y = minY; y <= maxY; y++) {
                            positions.putIfAbsent(new class_2338(x, y, maxZ).method_10063(), angle);
                        }
                    }
                }
            } else {
                for (class_2338 pos : PositionUtil.boxSurface(pos1, pos2)) {
                    positions.putIfAbsent(pos.method_10063(), angle);
                }
            }

            lastMin = pos1;
            lastMax = pos2;

            switch (mode) {
                case BEAM:
                    angle = coneAngle * Math.max(1 - len / maxLen, 0);
                    break;
                case CONE:
                    angle = coneAngle;
                    break;
            }
        }

        List result = Lists.newArrayList();
        positions.forEach((l, a) -> {
            class_2338 pos = class_2338.method_10092(l);
            class_243 vec3 = PositionUtil.centerOf(pos).method_1020(startPos);

            if (vec3.method_1033() <= maxLen) {
                class_243 dir2 = vec3.method_1029();
                double cos = dir2.method_1026(dir1);

                if (cos >= Math.cos(a)) {
                    result.add(pos);
                }
            }
        });

        return result;
    }

    public enum BeamMode {
        /*
         *       / ---\
         *   / ---------\
         * x -----------|
         *   \ ---------/
         *       \ ---/
         */
        BEAM,

        /*
         *       /-|
         *     /---|
         *   /-----|
         * x ------|
         *   \-----|
         *     \---|
         *       \-|
         */
        CONE
    }
}




© 2015 - 2024 Weber Informatics LLC | Privacy Policy