bammerbom.ultimatecore.bukkit.resources.utils.BossbarUtil.java Source code

Java tutorial

Introduction

Here is the source code for bammerbom.ultimatecore.bukkit.resources.utils.BossbarUtil.java

Source

/*
 * This file is part of UltimateCore, licensed under the MIT License (MIT).
 *
 * Copyright (c) Bammerbom
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */
package bammerbom.ultimatecore.bukkit.resources.utils;

import bammerbom.ultimatecore.bukkit.r;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Iterator;
import java.util.UUID;
import org.apache.commons.lang.Validate;
import org.bukkit.Bukkit;
import org.bukkit.Location;
import org.bukkit.World;
import org.bukkit.block.BlockFace;
import org.bukkit.entity.Entity;
import org.bukkit.entity.Player;
import org.bukkit.event.EventHandler;
import org.bukkit.event.EventPriority;
import org.bukkit.event.Listener;
import org.bukkit.event.player.PlayerKickEvent;
import org.bukkit.event.player.PlayerQuitEvent;
import org.bukkit.event.player.PlayerRespawnEvent;
import org.bukkit.event.player.PlayerTeleportEvent;

public class BossbarUtil implements Listener {

    static boolean enabled = false;
    private static HashMap<UUID, FakeDragon> players = new HashMap<>();
    private static HashMap<UUID, Integer> timers = new HashMap<>();

    public static void enable() {
        if (enabled == true) {
            return;
        }
        enabled = true;
        Bukkit.getServer().getPluginManager().registerEvents(new BossbarUtil(), r.getUC());
        Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(r.getUC(), new Runnable() {
            public void run() {
                for (UUID uuid : players.keySet()) {
                    Player p = Bukkit.getPlayer(uuid);
                    Util.sendPacket(p, players.get(uuid).getTeleportPacket(getDragonLocation(p.getLocation())));
                }
            }
        }, 0L, 5L);
    }

    public static void disable() {
        for (Player player : r.getOnlinePlayers()) {
            removeBar(player);
        }
        players.clear();
        for (Iterator<Integer> i = timers.values().iterator(); i.hasNext();) {
            int timerID = i.next().intValue();
            Bukkit.getScheduler().cancelTask(timerID);
        }
        timers.clear();
    }

    private static String cleanMessage(String message) {
        if (message.length() > 64) {
            message = message.substring(0, 63);
        }
        return message;
    }

    private static void cancelTimer(Player player) {
        Integer timerID = timers.remove(player.getUniqueId());
        if (timerID != null) {
            Bukkit.getScheduler().cancelTask(timerID.intValue());
        }
    }

    private static void sendDragon(FakeDragon dragon, Player player) {
        Util.sendPacket(player, dragon.getMetaPacket(dragon.getWatcher()));
        Util.sendPacket(player, dragon.getTeleportPacket(getDragonLocation(player.getLocation())));
    }

    private static FakeDragon getDragon(Player player, String message) {
        if (hasBar(player)) {
            return players.get(player.getUniqueId());
        }
        return addDragon(player, cleanMessage(message));
    }

    private static FakeDragon addDragon(Player player, String message) {
        FakeDragon dragon = Util.newDragon(message, getDragonLocation(player.getLocation()));
        Util.sendPacket(player, dragon.getSpawnPacket());
        players.put(player.getUniqueId(), dragon);
        return dragon;
    }

    private static FakeDragon addDragon(Player player, Location loc, String message) {
        FakeDragon dragon = Util.newDragon(message, getDragonLocation(loc));
        Util.sendPacket(player, dragon.getSpawnPacket());
        players.put(player.getUniqueId(), dragon);
        return dragon;
    }

    private static Location getDragonLocation(Location loc) {
        loc.subtract(0.0D, 300.0D, 0.0D);
        return loc;
    }

    @SuppressWarnings("unused")
    private static BlockFace getDirection(Location loc) {
        float dir = Math.round(loc.getYaw() / 90.0F);
        if ((dir == -4.0F) || (dir == 0.0F) || (dir == 4.0F)) {
            return BlockFace.SOUTH;
        }
        if ((dir == -1.0F) || (dir == 3.0F)) {
            return BlockFace.EAST;
        }
        if ((dir == -2.0F) || (dir == 2.0F)) {
            return BlockFace.NORTH;
        }
        if ((dir == -3.0F) || (dir == 1.0F)) {
            return BlockFace.WEST;
        }
        return null;
    }

    //Api
    public static void setMessage(String message) {
        for (Player player : r.getOnlinePlayers()) {
            setMessage(player, message);
        }
    }

    public static void setMessage(Player player, String message) {
        FakeDragon dragon = getDragon(player, message);
        dragon.name = cleanMessage(message);
        dragon.health = dragon.getMaxHealth();
        cancelTimer(player);
        sendDragon(dragon, player);
    }

    public static void setMessage(String message, float percent) {
        for (Player player : r.getOnlinePlayers()) {
            setMessage(player, message, percent);
        }
    }

    public static void setMessage(Player player, String message, float percent) {
        Validate.isTrue((0.0F <= percent) && (percent <= 100.0F), "Percent must be between 0F and 100F, but was: ",
                percent);
        FakeDragon dragon = getDragon(player, message);
        dragon.name = cleanMessage(message);
        dragon.health = (percent / 100.0F * dragon.getMaxHealth());
        cancelTimer(player);
        sendDragon(dragon, player);
    }

    public static void setMessage(String message, int seconds) {
        for (Player player : r.getOnlinePlayers()) {
            setMessage(player, message, seconds);
        }
    }

    public static void setMessage(final Player player, String message, int seconds) {
        Validate.isTrue(seconds > 0, "Seconds must be above 1 but was: ", seconds);
        FakeDragon dragon = getDragon(player, message);
        dragon.name = cleanMessage(message);
        dragon.health = dragon.getMaxHealth();
        final float dragonHealthMinus = dragon.getMaxHealth() / seconds;
        cancelTimer(player);

        timers.put(player.getUniqueId(),
                Integer.valueOf(Bukkit.getScheduler().runTaskTimer(r.getUC(), new Runnable() {
                    public void run() {
                        FakeDragon drag = getDragon(player, "");
                        drag.health -= dragonHealthMinus;

                        if (drag.health <= 1.0F) {
                            removeBar(player);
                            cancelTimer(player);
                        } else {
                            sendDragon(drag, player);
                        }
                    }
                }, 20L, 20L).getTaskId()));

        sendDragon(dragon, player);
    }

    public static boolean hasBar(Player player) {
        return players.get(player.getUniqueId()) != null;
    }

    public static void removeBar(Player player) {
        if (!hasBar(player)) {
            return;
        }
        Util.sendPacket(player, getDragon(player, "").getDestroyPacket());

        players.remove(player.getUniqueId());

        cancelTimer(player);
    }

    public static void setHealth(Player player, float percent) {
        if (!hasBar(player)) {
            return;
        }
        FakeDragon dragon = getDragon(player, "");
        dragon.health = (percent / 100.0F * dragon.getMaxHealth());

        cancelTimer(player);

        if (percent == 0.0F) {
            removeBar(player);
        } else {
            sendDragon(dragon, player);
        }
    }

    public static float getHealth(Player player) {
        if (!hasBar(player)) {
            return -1.0F;
        }
        return getDragon(player, "").health;
    }

    public static String getMessage(Player player) {
        if (!hasBar(player)) {
            return "";
        }
        return getDragon(player, "").name;
    }

    //Events
    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void PlayerLoggout(PlayerQuitEvent event) {
        removeBar(event.getPlayer());
    }

    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onPlayerKick(PlayerKickEvent event) {
        removeBar(event.getPlayer());
    }

    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onPlayerTeleport(PlayerTeleportEvent event) {
        handleTeleport(event.getPlayer(), event.getTo().clone());
    }

    @EventHandler(priority = EventPriority.MONITOR, ignoreCancelled = true)
    public void onPlayerTeleport(PlayerRespawnEvent event) {
        handleTeleport(event.getPlayer(), event.getRespawnLocation().clone());
    }

    //Methods
    private void handleTeleport(final Player player, final Location loc) {
        if (!hasBar(player)) {
            return;
        }
        Bukkit.getScheduler().runTaskLater(r.getUC(), new Runnable() {
            public void run() {
                if (!hasBar(player)) {
                    return;
                }
                FakeDragon oldDragon = getDragon(player, "");
                float health = oldDragon.health;
                String message = oldDragon.name;
                Util.sendPacket(player, getDragon(player, "").getDestroyPacket());
                players.remove(player.getUniqueId());
                FakeDragon dragon = addDragon(player, loc, message);
                dragon.health = health;
                sendDragon(dragon, player);
            }
        }, 2L);
    }
}

class Util {

    public static String version = (Bukkit.getServer() != null
            ? Bukkit.getServer().getClass().getPackage().getName().replace(".", ",").split(",")[3]
            : "UNKNOWN") + ".";

    public static FakeDragon newDragon(String message, Location loc) {
        FakeDragon fakeDragon = null;
        try {
            fakeDragon = FakeDragon.class.getConstructor(new Class[] { String.class, Location.class })
                    .newInstance(new Object[] { message, loc });
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return fakeDragon;
    }

    public static void sendPacket(Player p, Object packet) {
        try {
            Object nmsPlayer = getHandle(p);
            Field con_field = nmsPlayer.getClass().getField("playerConnection");
            Object con = con_field.get(nmsPlayer);
            Method packet_method = getMethod(con.getClass(), "sendPacket");
            packet_method.invoke(con, new Object[] { packet });
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
    }

    public static Class<?> getCraftClass(String ClassName) {
        String className = "net.minecraft.server." + version + ClassName;
        Class<?> c = null;
        try {
            c = Class.forName(className);
        } catch (ClassNotFoundException e) {
            e.printStackTrace();
        }
        return c;
    }

    public static Object getHandle(World world) {
        Object nms_entity = null;
        Method entity_getHandle = getMethod(world.getClass(), "getHandle");
        try {
            nms_entity = entity_getHandle.invoke(world, new Object[0]);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return nms_entity;
    }

    public static Object getHandle(Entity entity) {
        Object nms_entity = null;
        Method entity_getHandle = getMethod(entity.getClass(), "getHandle");
        try {
            nms_entity = entity_getHandle.invoke(entity, new Object[0]);
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        }
        return nms_entity;
    }

    public static Field getField(Class<?> cl, String field_name) {
        try {
            return cl.getDeclaredField(field_name);
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static Method getMethod(Class<?> cl, String method, Class<?>[] args) {
        for (Method m : cl.getMethods()) {
            if ((m.getName().equals(method)) && (ClassListEqual(args, m.getParameterTypes()))) {
                return m;
            }
        }
        return null;
    }

    public static Method getMethod(Class<?> cl, String method, Integer args) {
        for (Method m : cl.getMethods()) {
            if ((m.getName().equals(method)) && (args.equals(new Integer(m.getParameterTypes().length)))) {
                return m;
            }
        }
        return null;
    }

    public static Method getMethod(Class<?> cl, String method) {
        for (Method m : cl.getMethods()) {
            if (m.getName().equals(method)) {
                return m;
            }
        }
        return null;
    }

    public static boolean ClassListEqual(Class<?>[] l1, Class<?>[] l2) {
        boolean equal = true;

        if (l1.length != l2.length) {
            return false;
        }
        for (int i = 0; i < l1.length; i++) {
            if (l1[i] != l2[i]) {
                equal = false;
                break;
            }
        }

        return equal;
    }
}

class FakeDragon {

    public float health = 0.0F;
    public String name;
    private float maxHealth = 200.0F;
    private int x;
    private int y;
    private int z;
    private int pitch = 0;
    private int yaw = 0;
    private byte xvel = 0;
    private byte yvel = 0;
    private byte zvel = 0;
    private boolean visible = false;
    private Object world;
    private Object dragon;
    private int id;

    public FakeDragon(String name, Location loc, int percent) {
        this.name = name;
        this.x = loc.getBlockX();
        this.y = (loc.getBlockY() + 200);
        this.z = loc.getBlockZ();
        this.health = (percent / 100.0F * this.maxHealth);
        this.world = Util.getHandle(loc.getWorld());
    }

    public FakeDragon(String name, Location loc) {
        this.name = name;
        this.x = loc.getBlockX();
        this.y = (loc.getBlockY() + 200);
        this.z = loc.getBlockZ();
        this.world = Util.getHandle(loc.getWorld());
    }

    public float getMaxHealth() {
        return this.maxHealth;
    }

    public void setMaxHealth(float max) {
        this.maxHealth = max;
    }

    public void setHealth(int percent) {
        this.health = (percent / 100.0F * this.maxHealth);
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getX() {
        return this.x;
    }

    public void setX(int x) {
        this.x = x;
    }

    public int getY() {
        return this.y;
    }

    public void setY(int y) {
        this.y = y;
    }

    public int getZ() {
        return this.z;
    }

    public void setZ(int z) {
        this.z = z;
    }

    public int getPitch() {
        return this.pitch;
    }

    public void setPitch(int pitch) {
        this.pitch = pitch;
    }

    public int getYaw() {
        return this.yaw;
    }

    public void setYaw(int yaw) {
        this.yaw = yaw;
    }

    public byte getXvel() {
        return this.xvel;
    }

    public void setXvel(byte xvel) {
        this.xvel = xvel;
    }

    public byte getYvel() {
        return this.yvel;
    }

    public void setYvel(byte yvel) {
        this.yvel = yvel;
    }

    public byte getZvel() {
        return this.zvel;
    }

    public void setZvel(byte zvel) {
        this.zvel = zvel;
    }

    public boolean isVisible() {
        return this.visible;
    }

    public void setVisible(boolean visible) {
        this.visible = visible;
    }

    public Object getWorld() {
        return this.world;
    }

    public void setWorld(Object world) {
        this.world = world;
    }

    public Object getSpawnPacket() {
        Class<?> Entity = Util.getCraftClass("Entity");
        Class<?> EntityLiving = Util.getCraftClass("EntityLiving");
        Class<?> EntityEnderDragon = Util.getCraftClass("EntityEnderDragon");
        Object packet = null;
        try {
            this.dragon = EntityEnderDragon.getConstructor(new Class[] { Util.getCraftClass("World") })
                    .newInstance(new Object[] { getWorld() });

            Method setLocation = Util.getMethod(EntityEnderDragon, "setLocation",
                    new Class[] { Double.TYPE, Double.TYPE, Double.TYPE, Float.TYPE, Float.TYPE });
            setLocation.invoke(this.dragon, new Object[] { Integer.valueOf(getX()), Integer.valueOf(getY()),
                    Integer.valueOf(getZ()), Integer.valueOf(getPitch()), Integer.valueOf(getYaw()) });

            Method setInvisible = Util.getMethod(EntityEnderDragon, "setInvisible", new Class[] { Boolean.TYPE });
            setInvisible.invoke(this.dragon, new Object[] { Boolean.valueOf(isVisible()) });

            Method setCustomName = Util.getMethod(EntityEnderDragon, "setCustomName", new Class[] { String.class });
            setCustomName.invoke(this.dragon, new Object[] { this.name });

            Method setHealth = Util.getMethod(EntityEnderDragon, "setHealth", new Class[] { Float.TYPE });
            setHealth.invoke(this.dragon, new Object[] { Float.valueOf(this.health) });

            Field motX = Util.getField(Entity, "motX");
            motX.set(this.dragon, Byte.valueOf(getXvel()));

            Field motY = Util.getField(Entity, "motY");
            motY.set(this.dragon, Byte.valueOf(getYvel()));

            Field motZ = Util.getField(Entity, "motZ");
            motZ.set(this.dragon, Byte.valueOf(getZvel()));

            Method getId = Util.getMethod(EntityEnderDragon, "getId", new Class[0]);
            this.id = ((Number) getId.invoke(this.dragon, new Object[0])).intValue();

            Class<?> PacketPlayOutSpawnEntityLiving = Util.getCraftClass("PacketPlayOutSpawnEntityLiving");

            packet = PacketPlayOutSpawnEntityLiving.getConstructor(new Class[] { EntityLiving })
                    .newInstance(new Object[] { this.dragon });
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return packet;
    }

    public Object getDestroyPacket() {
        Class<?> PacketPlayOutEntityDestroy = Util.getCraftClass("PacketPlayOutEntityDestroy");

        Object packet = null;
        try {
            packet = PacketPlayOutEntityDestroy.newInstance();
            Field a = PacketPlayOutEntityDestroy.getDeclaredField("a");
            a.setAccessible(true);
            a.set(packet, new int[] { this.id });
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (NoSuchFieldException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        }

        return packet;
    }

    public Object getMetaPacket(Object watcher) {
        Class<?> DataWatcher = Util.getCraftClass("DataWatcher");

        Class<?> PacketPlayOutEntityMetadata = Util.getCraftClass("PacketPlayOutEntityMetadata");

        Object packet = null;
        try {
            packet = PacketPlayOutEntityMetadata
                    .getConstructor(new Class[] { Integer.TYPE, DataWatcher, Boolean.TYPE })
                    .newInstance(new Object[] { Integer.valueOf(this.id), watcher, Boolean.valueOf(true) });
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return packet;
    }

    public Object getTeleportPacket(Location loc) {
        Class<?> PacketPlayOutEntityTeleport = Util.getCraftClass("PacketPlayOutEntityTeleport");

        Object packet = null;
        try {
            packet = PacketPlayOutEntityTeleport
                    .getConstructor(new Class[] { Integer.TYPE, Integer.TYPE, Integer.TYPE, Integer.TYPE, Byte.TYPE,
                            Byte.TYPE, Boolean.TYPE })
                    .newInstance(new Object[] { Integer.valueOf(this.id), Integer.valueOf(loc.getBlockX() * 32),
                            Integer.valueOf(loc.getBlockY() * 32), Integer.valueOf(loc.getBlockZ() * 32),
                            Byte.valueOf((byte) ((int) loc.getYaw() * 256 / 360)),
                            Byte.valueOf((byte) ((int) loc.getPitch() * 256 / 360)), Boolean.valueOf(false) });
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }

        return packet;
    }

    public Object getWatcher() {
        Class<?> Entity = Util.getCraftClass("Entity");
        Class<?> DataWatcher = Util.getCraftClass("DataWatcher");

        Object watcher = null;
        try {
            watcher = DataWatcher.getConstructor(new Class[] { Entity }).newInstance(new Object[] { this.dragon });
            Method a = Util.getMethod(DataWatcher, "a", new Class[] { Integer.TYPE, Object.class });

            a.invoke(watcher,
                    new Object[] { Integer.valueOf(0), Byte.valueOf(isVisible() ? (byte) 0 : (byte) 32) });
            a.invoke(watcher, new Object[] { Integer.valueOf(6), Float.valueOf(this.health) });
            a.invoke(watcher, new Object[] { Integer.valueOf(7), Integer.valueOf(0) });
            a.invoke(watcher, new Object[] { Integer.valueOf(8), Byte.valueOf((byte) 0) });
            a.invoke(watcher, new Object[] { Integer.valueOf(10), this.name });
            a.invoke(watcher, new Object[] { Integer.valueOf(11), Byte.valueOf((byte) 1) });
        } catch (IllegalArgumentException e) {
            e.printStackTrace();
        } catch (SecurityException e) {
            e.printStackTrace();
        } catch (InstantiationException e) {
            e.printStackTrace();
        } catch (IllegalAccessException e) {
            e.printStackTrace();
        } catch (InvocationTargetException e) {
            e.printStackTrace();
        } catch (NoSuchMethodException e) {
            e.printStackTrace();
        }
        return watcher;
    }
}