Untitled

 avatar
unknown
plain_text
16 days ago
20 kB
2
Indexable
package me.hiro3.seismicsenseav;

import com.comphenix.protocol.PacketType;
import com.comphenix.protocol.ProtocolLibrary;
import com.comphenix.protocol.events.PacketContainer;
import com.comphenix.protocol.wrappers.*;
import com.google.common.collect.Lists;
import com.projectkorra.projectkorra.GeneralMethods;
import com.projectkorra.projectkorra.ProjectKorra;
import com.projectkorra.projectkorra.ability.EarthAbility;
import it.unimi.dsi.fastutil.ints.IntArrayList;
import org.bukkit.*;
import org.bukkit.block.BlockFace;
import org.bukkit.block.data.BlockData;
import org.bukkit.entity.EntityType;
import org.bukkit.entity.LivingEntity;
import org.bukkit.entity.Player;
import org.bukkit.scheduler.BukkitRunnable;
import org.bukkit.util.Vector;
import org.joml.Quaternionf;
import org.joml.Vector3f;

import java.util.ArrayList;
import java.util.List;
import java.util.Random;
import java.util.UUID;

public class UtilityMethods {

    public static void sendTextDisplay(Player p, Location loc, String text, double yaw, double pitch, long lifetime) {
        PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
        int entityId = Integer.MAX_VALUE / 2 + new Random().nextInt(Integer.MAX_VALUE / 2);

        spawnPacket.getIntegers().write(0, entityId);
        spawnPacket.getUUIDs().write(0, UUID.randomUUID());
        spawnPacket.getEntityTypeModifier().write(0, EntityType.TEXT_DISPLAY);

        float scaleVal = 1f;
        Quaternionf qt = new Quaternionf().rotateLocalX((float) Math.toRadians(pitch)).rotateLocalY((float) Math.toRadians(yaw));

        spawnPacket.getDoubles()
                .write(0, loc.getX())
                .write(1, loc.getY() + (1-scaleVal) / 2f)
                .write(2, loc.getZ());

        PacketContainer glowPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
        glowPacket.getModifier().writeDefaults();

        WrappedChatComponent wcc = WrappedChatComponent.fromText(text);

        glowPacket.getIntegers().write(0, entityId);
        List<WrappedDataValue> glowValue = Lists.newArrayList(
                new WrappedDataValue(11, WrappedDataWatcher.Registry.get(Vector3f.class), new Vector3f(1f, 1f, 1f).mul(scaleVal)),
                new WrappedDataValue(12, WrappedDataWatcher.Registry.get(Quaternionf.class), qt),
                new WrappedDataValue(22, WrappedDataWatcher.Registry.getChatComponentSerializer(), wcc.getHandle())
        );

        glowPacket.getDataValueCollectionModifier().write(0, glowValue);

        ProtocolLibrary.getProtocolManager().sendServerPacket(p, spawnPacket);
        ProtocolLibrary.getProtocolManager().sendServerPacket(p, glowPacket);


        Bukkit.getScheduler().scheduleSyncDelayedTask(ProjectKorra.plugin, () -> {
            PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);

            destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));

            ProtocolLibrary.getProtocolManager().sendServerPacket(p, destroyPacket);
        },  lifetime);
    }

    //add color for 1.20.4
    public static void sendGlowingBlock(Player p, Location loc, float scale, long lifetime) {
        sendGlowingBlock(p, loc, null, null, scale, lifetime);
    }

    public static void sendGlowingBlock(Player p, Location loc, Color color, float scale, long lifetime) {
        sendGlowingBlock(p, loc, null, color, scale, lifetime);
    }

    /*
     * Give floor center of the block. The method will handle the Y height according to the given scale.
     */
    public static void sendGlowingBlock(Player p, Location loc, Material type, Color color, float scale, long lifetime) {
        //SPAWN PACKET
        PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
        int entityId = Integer.MAX_VALUE / 2 + new Random().nextInt(Integer.MAX_VALUE / 2);

        spawnPacket.getIntegers().write(0, entityId);
        spawnPacket.getUUIDs().write(0, UUID.randomUUID());
        spawnPacket.getEntityTypeModifier().write(0, EntityType.BLOCK_DISPLAY);

        float scaleVal = Math.max(0, Math.min(scale, 0.999f));

        spawnPacket.getDoubles()
                .write(0, loc.getX())
                .write(1, loc.getY() + (1-scaleVal) / 2f)
                .write(2, loc.getZ());

        //GLOW PACKET
        PacketContainer glowPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
        glowPacket.getModifier().writeDefaults();

        BlockData data = type == null ? loc.getBlock().getBlockData() : type.createBlockData();
        WrappedBlockData wbd = WrappedBlockData.createData(data);
        int finalColor = color == null ? data.getMapColor().asRGB() : color.asRGB();

        glowPacket.getIntegers().write(0, entityId);
        List<WrappedDataValue> glowValue = Lists.newArrayList(
                new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) (0x60)),
                new WrappedDataValue(11, WrappedDataWatcher.Registry.get(Vector3f.class), new Vector3f(-1f, 0f, -1f).mul(scaleVal / 2f)),
                new WrappedDataValue(12, WrappedDataWatcher.Registry.get(Vector3f.class), new Vector3f(1f, 1f, 1f).mul(scaleVal)),
                new WrappedDataValue(22, WrappedDataWatcher.Registry.get(Integer.class), finalColor),
                new WrappedDataValue(23, WrappedDataWatcher.Registry.getBlockDataSerializer(false), wbd.getHandle())
        );
        glowPacket.getDataValueCollectionModifier().write(0, glowValue);

        ProtocolLibrary.getProtocolManager().sendServerPacket(p, spawnPacket);
        ProtocolLibrary.getProtocolManager().sendServerPacket(p, glowPacket);


        Bukkit.getScheduler().scheduleSyncDelayedTask(ProjectKorra.plugin, () -> {
            PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);

            destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));

            ProtocolLibrary.getProtocolManager().sendServerPacket(p, destroyPacket);
        },  lifetime);
    }

    public static void sendGlowingRotatingBlock(Player p, Location loc, Material type, Color color, Vector scale, double yaw, double pitch, long lifetime) {
        //SPAWN PACKET
        PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);
        int entityId = Integer.MAX_VALUE / 2 + new Random().nextInt(Integer.MAX_VALUE / 2);

        spawnPacket.getIntegers().write(0, entityId);
        spawnPacket.getUUIDs().write(0, UUID.randomUUID());
        spawnPacket.getEntityTypeModifier().write(0, EntityType.BLOCK_DISPLAY);

        spawnPacket.getDoubles()
                .write(0, loc.getX())
                .write(1, loc.getY())
                .write(2, loc.getZ());

        //METADATA PACKET
        PacketContainer glowPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
        glowPacket.getModifier().writeDefaults();

        BlockData data = type == null ? loc.getBlock().getBlockData() : type.createBlockData();
        WrappedBlockData wbd = WrappedBlockData.createData(data);
        int finalColor = color == null ? data.getMapColor().asRGB() : color.asRGB();

        Quaternionf qt = new Quaternionf().rotateLocalX((float) pitch).rotateLocalY((float) yaw);

        glowPacket.getIntegers().write(0, entityId);
        List<WrappedDataValue> glowValue = Lists.newArrayList(
                new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) (0x60)),
                new WrappedDataValue(11, WrappedDataWatcher.Registry.get(Vector3f.class), centerDisplayOffset(pitch, yaw, scale, 1)),//new Vector3f(-1f, 0f, -1f).mul(scaleVal / 2f)),
                new WrappedDataValue(12, WrappedDataWatcher.Registry.get(Vector3f.class), scale.toVector3f()),//new Vector3f(1f, 1f, 1f).mul(scaleVal)),
                new WrappedDataValue(13, WrappedDataWatcher.Registry.get(Quaternionf.class), qt),
                new WrappedDataValue(22, WrappedDataWatcher.Registry.get(Integer.class), finalColor),//Color.WHITE.getRGB()),//color),
                new WrappedDataValue(23, WrappedDataWatcher.Registry.getBlockDataSerializer(false), wbd.getHandle())
        );
        glowPacket.getDataValueCollectionModifier().write(0, glowValue);

        ProtocolLibrary.getProtocolManager().sendServerPacket(p, spawnPacket);
        ProtocolLibrary.getProtocolManager().sendServerPacket(p, glowPacket);


        Bukkit.getScheduler().scheduleSyncDelayedTask(ProjectKorra.plugin, () -> {
            PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);

            destroyPacket.getModifier().write(0, new IntArrayList(new int[]{entityId}));

            ProtocolLibrary.getProtocolManager().sendServerPacket(p, destroyPacket);
        },  lifetime);
    }

    public static void sendDisplayBlock(Player p, DisplayData displayData) {
        sendSpawnPacket(p, displayData);
        sendMetadataPacket(p, displayData);
    }

    public static void sendSpawnPacket(Player p, DisplayData displayData) {
        PacketContainer spawnPacket = new PacketContainer(PacketType.Play.Server.SPAWN_ENTITY);

        spawnPacket.getIntegers().write(0, displayData.entityId);
        spawnPacket.getUUIDs().write(0, UUID.randomUUID());
        spawnPacket.getEntityTypeModifier().write(0, EntityType.BLOCK_DISPLAY);

        Location loc = displayData.location;
        spawnPacket.getDoubles()
                .write(0, loc.getX())
                .write(1, loc.getY())
                .write(2, loc.getZ());

        ProtocolLibrary.getProtocolManager().sendServerPacket(p, spawnPacket);

        Bukkit.getScheduler().scheduleSyncDelayedTask(ProjectKorra.plugin, () -> {
            PacketContainer destroyPacket = new PacketContainer(PacketType.Play.Server.ENTITY_DESTROY);

            destroyPacket.getModifier().write(0, new IntArrayList(new int[]{displayData.entityId}));

            ProtocolLibrary.getProtocolManager().sendServerPacket(p, destroyPacket);
        },  displayData.lifetime);
    }

    public static void sendMetadataPacket(Player p, DisplayData displayData) {
        PacketContainer metadataPacket = new PacketContainer(PacketType.Play.Server.ENTITY_METADATA);
        metadataPacket.getModifier().writeDefaults();

        metadataPacket.getIntegers().write(0, displayData.entityId);
        List<WrappedDataValue> metadataValue = new ArrayList<>();
        metadataValue.add(new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), (byte) (0x60)));
        metadataValue.add(new WrappedDataValue(11, WrappedDataWatcher.Registry.get(Vector3f.class), displayData.centerDisplayOffset));
        metadataValue.add(new WrappedDataValue(12, WrappedDataWatcher.Registry.get(Vector3f.class), displayData.scale));
        if (displayData.qt != null)
            metadataValue.add(new WrappedDataValue(13, WrappedDataWatcher.Registry.get(Quaternionf.class), displayData.qt));
        metadataValue.add(new WrappedDataValue(22, WrappedDataWatcher.Registry.get(Integer.class), displayData.color));
        metadataValue.add(new WrappedDataValue(23, WrappedDataWatcher.Registry.getBlockDataSerializer(false), displayData.wbd.getHandle()));
        metadataPacket.getDataValueCollectionModifier().write(0, metadataValue);

        ProtocolLibrary.getProtocolManager().sendServerPacket(p, metadataPacket);
    }

    public static Vector3f centerDisplayOffset(double pitch, double yaw, Vector scale, int mode) {
        //mode 0: stick rotation
        //mode 1: central rotation
        mode = Math.min(1, Math.max(0, mode));
        Vector vector = new Vector(0.5 * scale.getX(), 0.5 * scale.getY(), 0.5 * scale.getZ() * mode);

        double oldX = vector.getX();
        double oldY = vector.getY();
        double oldZ = vector.getZ();
        vector.setY(oldY * Math.cos(pitch) - oldZ * Math.sin(pitch));
        vector.setZ(oldY * Math.sin(pitch) + oldZ * Math.cos(pitch));
        oldY = vector.getY();
        oldZ = vector.getZ();
        vector.setX(oldX * Math.cos(yaw) + oldZ * Math.sin(yaw));
        vector.setZ(-oldX * Math.sin(yaw) + oldZ * Math.cos(yaw));

        return vector.multiply(-1).toVector3f();
    }

    public static void setGlowing(Player sendPacketPlayer, LivingEntity glowingEntity, boolean glow) {
        PacketContainer packet = ProtocolLibrary.getProtocolManager().createPacket(PacketType.Play.Server.ENTITY_METADATA);

        packet.getIntegers().write(0, glowingEntity.getEntityId());

        Byte md = WrappedDataWatcher.getEntityWatcher(glowingEntity).getByte(0);
        Byte mask = (byte) (glow ? 0x40 : 0);
        md = (byte) (md | mask);

        List<WrappedDataValue> values = Lists.newArrayList(
                new WrappedDataValue(0, WrappedDataWatcher.Registry.get(Byte.class), md));

        packet.getDataValueCollectionModifier().write(0, values);

        ProtocolLibrary.getProtocolManager().sendServerPacket(sendPacketPlayer, packet);
    }

    public static void sendPulse(Player player, Location center, double maxRadius, int step, int angleIncrease) {

        new BukkitRunnable() {
            double angle;
            double radius = 0;
            double speed = maxRadius/step;

            @Override
            public void run() {
                if (radius >= maxRadius) {
                    Bukkit.getScheduler().cancelTask(getTaskId());
                    return;
                }

                radius += speed;
                for(int i = 0; i <= 360; i+=angleIncrease) {
                    angle = Math.toRadians(i);
                    double x = radius * Math.cos(angle);
                    double z = radius * Math.sin(angle);
                    center.add(x, 0, z);
                    if (GeneralMethods.isSolid(center.getBlock()))
                        UtilityMethods.sendGlowingBlock(player, center, 0.1f, 1);
                    center.subtract(x, 0, z);
                }
            }

        }.runTaskTimer(ProjectKorra.plugin, 0, 1);

    }

    public static void sendRotatingPulse(Player player, Location center, double radius, int step, int angleIncrease) {
        double radiusIncrease = radius / step;
        double angleIncreaseRad = Math.toRadians(angleIncrease);

        new BukkitRunnable() {

            double r = 0;

            @Override
            public void run() {
                if (r >= radius) {
                    Bukkit.getScheduler().cancelTask(getTaskId());
                    return;
                }

                for (int i = 0; i < 360; i+= angleIncrease) {
                    double angle = Math.toRadians(i);
                    double x = r * Math.cos(angle);
                    double z = r * Math.sin(angle);

                    double c = Math.cos(angleIncreaseRad);
                    double d = r * Math.sqrt( (1 - c) / (1 + c) );

                    double stickLength = 2 * d;
                    Vector scale = new Vector(0.2, 0.2, stickLength);
                    double yaw = -angle;
                    double pitch = 0;

                    center.add(x, 0, z);
                    DisplayData dd = new DisplayData(
                            center,
                            null,
                            null,
                            scale,
                            yaw,
                            pitch,
                            true,
                            2
                    );
                    sendDisplayBlock(player, dd);
                    center.subtract(x, 0, z);
                }
                r += radiusIncrease;
            }
        }.runTaskTimer(ProjectKorra.plugin, 0, 1);
    }

    public static void sendPulseImproved(Player player, Location center, double maxRadius, int step, int angleIncrease) {
        Vector startingVector = new Vector(maxRadius/step, 0, 0);
        Location startingLocation = center;

        ArrayList<Location> l = new ArrayList<Location>();
        ArrayList<Vector> d = new ArrayList<Vector>();
        for (int i = 0; i < 360; i += angleIncrease) {
            l.add(startingLocation.clone());
            d.add(UtilityMethods.rotateVectorAroundY(startingVector, i));
        }

        new BukkitRunnable() {

            int tick = 0;

            @Override
            public void run() {
                if (tick >= step) {
                    Bukkit.getScheduler().cancelTask(getTaskId());
                    return;
                }

                for (int i = 0; i < l.size(); i++) {
                    if (GeneralMethods.isSolid(l.get(i).getBlock())) {
                        UtilityMethods.sendGlowingBlock(player, l.get(i), 0.1f, 1);
                    }
                    if (GeneralMethods.isSolid(l.get(i).getBlock().getRelative(BlockFace.UP))) {
                        l.get(i).add(0, 1, 0);
                    } else {
                        l.get(i).add(d.get(i));
                        if (GeneralMethods.isSolid(l.get(i).getBlock().getRelative(BlockFace.UP))) {
                            l.get(i).add(0, 1, 0);
                        } else {
                            l.set(i, UtilityMethods.getFloor(player, l.get(i)));
                        }
                    }
                }

                tick++;
            }

        }.runTaskTimer(ProjectKorra.plugin, 0, 1);
    }

    public static Vector rotateVectorAroundY(Vector vector, double degrees) {
        double rad = Math.toRadians(degrees);

        double currentX = vector.getX();
        double currentZ = vector.getZ();

        double cosine = Math.cos(rad);
        double sine = Math.sin(rad);

        return new Vector((cosine * currentX - sine * currentZ), vector.getY(), (sine * currentX + cosine * currentZ));
    }

    public static Location getFloor(Player player, Location loc) {
        Location f = loc.clone();
        double sqrMaxHeight = 30 * 30;
        while (!GeneralMethods.isSolid(loc.getBlock()) && loc.distanceSquared(f) < sqrMaxHeight) {
            loc.add(0, -1, 0);
        }
        return loc;
    }

    public static class DisplayData {
        public int entityId;
        public int lifetime;
        public Location location;
        public Vector3f centerDisplayOffset;
        public Vector3f scale;
        public Quaternionf qt;
        public int color;
        public WrappedBlockData wbd;
        public DisplayData(Location loc, Material type, Color color, Vector scale, double yaw, double pitch, boolean rotateFromCenter, int lifetime) {
            this.entityId = Integer.MAX_VALUE / 2 + new Random().nextInt(Integer.MAX_VALUE / 2);
            this.lifetime = lifetime;
            this.location = loc;
            int mode = rotateFromCenter ? 1 : 0;

            this.scale = scale.toVector3f();
            if (yaw != 0 || pitch != 0) {
                this.centerDisplayOffset = centerDisplayOffset(pitch, yaw, scale, mode);
                this.qt = new Quaternionf().rotateLocalX((float) pitch).rotateLocalY((float) yaw);
            } else {
                this.centerDisplayOffset = new Vector3f(
                        (float) (-scale.getX() / 2.),
                        (float) (-scale.getY() / 2.),
                        (float) (-scale.getZ() / 2.) * mode
                );
                this.qt = null;
            }
            BlockData data = type == null ? loc.getBlock().getBlockData() : type.createBlockData();
            this.color = color == null ? data.getMapColor().asRGB() : color.asRGB();
            this.wbd = WrappedBlockData.createData(data);
        }
    }

}
Leave a Comment