Resource [NMS, 1.8.X] Boss Bar Utility (SO SIMPLE)

Discussion in 'Spigot Plugin Development' started by EnervateD, May 26, 2016.

  1. Hello, guys!
    Recently I have been developing a plugin that contains boss bar functions. I didn't want to use some big library with a lot of reflection classes, so I made my own small class that can help you a lot to use a boss bar for your plugin
    Here is a code:

    Code (Java):
    package ru.enervate.bossbar;

    import net.minecraft.server.v1_8_R3.*;
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_8_R3.CraftWorld;
    import org.bukkit.craftbukkit.v1_8_R3.entity.CraftPlayer;
    import org.bukkit.entity.Player;

    import java.lang.reflect.Field;
    import java.util.HashSet;
    import java.util.Map;
    import java.util.Set;
    import java.util.concurrent.ConcurrentHashMap;

    /**
    * Bukkit/Spigot/Bungee Java Plugin Maker.
    * EnervateD. All rights reserved.
    */

    public class BarUtil {

        private static Map<String, EntityEnderDragon> dragons = new ConcurrentHashMap<>();

        public static void setBar(Player p, String text, float healthPercent) {
            Location loc = p.getLocation();
            WorldServer world = ((CraftWorld) p.getLocation().getWorld()).getHandle();

            EntityEnderDragon dragon = new EntityEnderDragon(world);
            dragon.setLocation(loc.getX(), loc.getY() - 100, loc.getZ(), 0, 0);

            PacketPlayOutSpawnEntityLiving packet = new PacketPlayOutSpawnEntityLiving(dragon);

            DataWatcher watcher = new DataWatcher(null);
            watcher.a(0, (byte) 0x20);
            watcher.a(6, (healthPercent * 200) / 100);
            watcher.a(10, text);
            watcher.a(2, text);
            watcher.a(11, (byte) 1);
            watcher.a(3, (byte) 1);

            try{
                Field t = PacketPlayOutSpawnEntityLiving.class.getDeclaredField("l");
                t.setAccessible(true);
                t.set(packet, watcher);
            } catch(Exception ex){
                ex.printStackTrace();
            }

            dragons.put(p.getName(), dragon);
            ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
        }

        public static void removeBar(Player p) {
            if(dragons.containsKey(p.getName())) {
                PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(dragons.get(p.getName()).getId());
                dragons.remove(p.getName());
                ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            }
        }

        public static void teleportBar(Player p) {
            if(dragons.containsKey(p.getName())) {
                Location loc = p.getLocation();
                PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(dragons.get(p.getName()).getId(),
                        (int) loc.getX() * 32, (int) (loc.getY() - 100) * 32, (int) loc.getZ() * 32,
                        (byte) ((int) loc.getYaw() * 256 / 360), (byte) ((int) loc.getPitch() * 256 / 360), false);
                ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            }
        }

        public static void updateText(Player p, String text) {
            updateBar(p, text, -1);
        }

        public static void updateHealth(Player p, float healthPercent) {
            updateBar(p, null, healthPercent);
        }

        public static void updateBar(Player p, String text, float healthPercent) {
            if(dragons.containsKey(p.getName())) {
                DataWatcher watcher = new DataWatcher(null);
                watcher.a(0, (byte) 0x20);
                if (healthPercent != -1) watcher.a(6, (healthPercent * 200) / 100);
                if (text != null) {
                    watcher.a(10, text);
                    watcher.a(2, text);
                }
                watcher.a(11, (byte) 1);
                watcher.a(3, (byte) 1);

                PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(dragons.get(p.getName()).getId(), watcher, true);
                ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            }
        }

        public static Set<String> getPlayers() {
            Set<String> set = new HashSet<>();

            for(Map.Entry<String, EntityEnderDragon> entry : dragons.entrySet()) {
                set.add(entry.getKey());
            }

            return set;
        }

    }
    You can send a bar for player like this:

    Code (Java):
    BarUtil.sendBar(event.getPlayer(), "§6Hello, §a" + e.getPlayer().getName() + "§6!", 50); // It will send a bar for player with text "Hello, %Player!" and with 50 percents of bar health
    When player quit the game, you can remove bar:

    Code (Java):
    BarUtil.removeBar(event.getPlayer());
    At the main class, in onEnable() you should do something like this:

    Code (Java):
        public void onEnable() {
            new Thread(new Runnable() {

                @Override
                public void run() {
                    while(true) {
                        for(String s : BarUtil.getPlayers()) {
                            Player o = Bukkit.getPlayer(s);
                            if(o != null) BarUtil.teleportBar(o);
                        }

                        try {
                            Thread.sleep(1000); // 1000 = 1 sec
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }

            }).start();
        }
    To update bar text, you should make this:

    Code (Java):
    BarUtil.updateText(event.getPlayer(), "New text goes here");
    To update bar health, type following code:

    Code (Java):
    BarUtil.updateHealth(event.getPlayer(), 35);
    To update text and health, you can do this:

    Code (Java):
    BarUtil.updateBar(event.getPlayer(), "New text", 50);
    I wish you good luck in using my utility.
    Thanks for watching!
     
    • Like Like x 4
    • Winner Winner x 3
    • Useful Useful x 1
  2. Good work! ;) I will use this class.
     
  3. You do realise Spigot 1.9 included a whole BossBar API along with it right?
     
    • Agree Agree x 1
  4. 2 minutes late to say this ;-;
     
    • Funny Funny x 1
  5. Or.. update to 1.9 and just use spigot 1.9's bossbar api.
     
  6. The library is for 1.8, maybe OP doesn't want to use 1.9.
     
  7. Regardless, you could just take the API source on http://stash.spgt.tech and use that.
     
  8. I don't get what's wrong with what OP has shared? The class is only about 100 lines and I'm pretty sure the source would be quite different for 1.9 considering all the changes made to boss bars.
     
  9. Because the 1.9 boss bar is the same as the 1.8
     
  10. Well cmiiw but it would be pretty similar no?
     
  11. Guys, this class is for 1.8. I know, that Spigot 1.9 contains the lib for BossBar.
     
    • Agree Agree x 4
  12. This wont work, boss bar is not displaying
     
  13. @Zarlen But... If it won't work, I wouldn't post it here
     
  14. No.. Just no...

    Why are you freezing the entire thread when the plugin is enabled? Thread#sleep() freezes every process on the server. Instead, use a delayed BukkitRunnable.
     
  15. MiniDigger

    Supporter

    take a closer look at his code, he uses a new thread. but yeah, I agree that the scheduler should be used.
     
  16. Do you have a fix for it? Boss bar is not displaying, no errors etc
     
  17. Ah, I see now. Either way, Thread#sleep() should, as you said be avoided as much as possible, and replaced with:

    BukkitTask runTaskLater(Plugin plugin, long delay)
    Schedules this to run after the specified number of server ticks.

    or

    int scheduleSyncDelayedTask(Plugin plugin, Runnable task, long delay)
    Schedules a once off task to occur after a delay.
     
  18. Can you update the code then to working? I tried everything but doesnt work
     
  19. Don't mess with data watcher, i made a version who don't need to mess with datawatcher
     
  20. Code (Text):
    public class BossBar extends BukkitRunnable {
     
        private String title;
        private HashMap<Player, EntityWither> withers = new HashMap<Player, EntityWither>();

        public BossBar(Instance instance, String title) {
            this.title = title;
            runTaskTimer(instance, 0, 10);
        }
     
        public void addPlayer(Player p) {
            EntityWither wither = new EntityWither(((CraftWorld) p.getWorld()).getHandle());
            Location l = getWitherLocation(p.getLocation());
            wither.setCustomName(title);
            wither.setInvisible(true);
            wither.setLocation(l.getX(), l.getY(), l.getZ(), 0, 0);
            PacketPlayOutSpawnEntityLiving packet = new PacketPlayOutSpawnEntityLiving(wither);
            ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
            withers.put(p, wither);
        }

        public void removePlayer(Player p) {
            EntityWither wither = withers.remove(p);
            PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(new int[] {wither.getId()});
            ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
        }
     
        public void setTitle(String title) {
            this.title = title;
            for (Entry<Player, EntityWither> entry : withers.entrySet()) {
                EntityWither wither = entry.getValue();
                wither.setCustomName(title);
                PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(wither.getId(), wither.getDataWatcher(), true);
                ((CraftPlayer) entry.getKey()).getHandle().playerConnection.sendPacket(packet);
            }
        }
     
        public void setProgress(double progress) {
            for (Entry<Player, EntityWither> entry : withers.entrySet()) {
                EntityWither wither = entry.getValue();
                wither.setHealth((float) (progress * wither.getMaxHealth()));
                PacketPlayOutEntityMetadata packet = new PacketPlayOutEntityMetadata(wither.getId(), wither.getDataWatcher(), true);
                ((CraftPlayer) entry.getKey()).getHandle().playerConnection.sendPacket(packet);
            }
        }
     
        public Location getWitherLocation(Location l) {
            return l.add(l.getDirection().multiply(60));
        }

        @Override
        public void run() {
            for (Entry<Player, EntityWither> en : withers.entrySet()) {
                EntityWither wither = en.getValue();
                Location l = getWitherLocation(en.getKey().getLocation());
                wither.setLocation(l.getX(), l.getY(), l.getZ(), 0, 0);
                PacketPlayOutEntityTeleport packet = new PacketPlayOutEntityTeleport(wither);
                ((CraftPlayer)en.getKey()).getHandle().playerConnection.sendPacket(packet);
            }
        }

    }
    His bossbar is so weird made :p, take a note how i made myself