[Tutorial] Utilizing the Boss Health Bar

Discussion in 'Resources' started by chasechocolate, Jul 5, 2013.

Thread Status:
Not open for further replies.
  1. Offline

    adde

  2. Offline

    ZedMike

    adde likes this.
  3. Offline

    adde

    Sure, but the time will not be per-time message. :p
     
  4. Offline

    ZedMike

    So theres no way to make a message appear for 10 seconds then disappear?
     
  5. Offline

    adde

    Yes, there is. But not per-message.

    If you read the configuration on the dev.bukkit page, it says "Change message in seconds".
    If you edit this one, to let's say 30, it will change message it 30 second.
     
  6. Offline

    BPOtacon

  7. Offline

    confuserr

    I've created an API which other plugins can use rather easily. It also takes into account multiple plugins attempting to set multiple bars. Based on the reflection class FakeDragon SoThatsIt wrote earlier on in the topic.

    http://dev.bukkit.org/bukkit-plugins/bar-api/
     
    hawkfalcon likes this.
  8. Offline

    SoThatsIt

    ive updated my class to work quite well if someone wants to use it. all you need to do is use the setStatus method in the class. if you want to get rid of the bar then just set the status to a string with nothing in it, example: "". there are also some other methods in there which you could also find helpful.

    FakeDragon.class
    Code:
    public class FakeDragon {
     
        public static Integer ENTITY_ID = 6000;
        public static Map<String, FakeDragon> dragonplayers = new HashMap<String, FakeDragon>();
        public static final int MAX_HEALTH = 200;
        public boolean visible;
        public int EntityID;
        public int x;
        public int y;
        public int z;
        public int pitch = 0;
        public int head_pitch = 0;
        public int yaw = 0;
        public byte xvel = 0;
        public byte yvel = 0;
        public byte zvel = 0;
        public float health;
        public String name;
     
        public FakeDragon(String name, int EntityID, Location loc){
            this(name, EntityID, (int) Math.floor(loc.getBlockX() * 32.0D), (int) Math.floor(loc.getBlockY() * 32.0D), (int) Math.floor(loc.getBlockZ() * 32.0D));
        }
     
        public FakeDragon(String name, int EntityID, Location loc, float health, boolean visible){
            this(name, EntityID, (int) Math.floor(loc.getBlockX() * 32.0D), (int) Math.floor(loc.getBlockY() * 32.0D), (int) Math.floor(loc.getBlockZ() * 32.0D), health, visible);
        }
     
        public FakeDragon(String name, int EntityID, int x, int y, int z){
            this(name, EntityID, x, y, z, MAX_HEALTH, false);
        }
     
        public FakeDragon(String name, int EntityID, int x, int y, int z, float health, boolean visible){
            this.name=name;
            this.EntityID=EntityID;
            this.x=x;
            this.y=y;
            this.z=z;
            this.health=health;
            this.visible=visible;
        }
     
        public Object getMobPacket(){
            Class<?> mob_class = General.getCraftClass("Packet24MobSpawn");
            Object mobPacket = null;
            try {
                mobPacket = mob_class.newInstance();
             
                Field a = General.getField(mob_class, "a");
                a.setAccessible(true);
                a.set(mobPacket, EntityID);//Entity ID
                Field b = General.getField(mob_class, "b");
                b.setAccessible(true);
                b.set(mobPacket, EntityType.ENDER_DRAGON.getTypeId());//Mob type (ID: 64)
                Field c = General.getField(mob_class, "c");
                c.setAccessible(true);
                c.set(mobPacket, x);//X position
                Field d = General.getField(mob_class, "d");
                d.setAccessible(true);
                d.set(mobPacket, y);//Y position
                Field e = General.getField(mob_class, "e");
                e.setAccessible(true);
                e.set(mobPacket, z);//Z position
                Field f = General.getField(mob_class, "f");
                f.setAccessible(true);
                f.set(mobPacket, (byte) ((int) (pitch * 256.0F / 360.0F)));//Pitch
                Field g = General.getField(mob_class, "g");
                g.setAccessible(true);
                g.set(mobPacket, (byte) ((int) (head_pitch * 256.0F / 360.0F)));//Head Pitch
                Field h = General.getField(mob_class, "h");
                h.setAccessible(true);
                h.set(mobPacket, (byte) ((int) (yaw * 256.0F / 360.0F)));//Yaw
                Field i = General.getField(mob_class, "i");
                i.setAccessible(true);
                i.set(mobPacket, xvel);//X velocity
                Field j = General.getField(mob_class, "j");
                j.setAccessible(true);
                j.set(mobPacket, yvel);//Y velocity
                Field k = General.getField(mob_class, "k");
                k.setAccessible(true);
                k.set(mobPacket, zvel);//Z velocity
     
                Object watcher = getWatcher();
                Field t = General.getField(mob_class, "t");
                t.setAccessible(true);
                t.set(mobPacket, watcher);
            } catch (InstantiationException e1) {
                e1.printStackTrace();
            } catch (IllegalAccessException e1) {
                e1.printStackTrace();
            }
     
            return mobPacket;
        }
     
        public Object getDestroyEntityPacket(){
            Class<?> packet_class = General.getCraftClass("Packet29DestroyEntity");
            Object packet = null;
            try {
                packet = packet_class.newInstance();
             
                Field a = General.getField(packet_class, "a");
                a.setAccessible(true);
                a.set(packet, new int[]{EntityID});
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
     
            return packet;
        }
     
        public Object getMetadataPacket(Object watcher){
            Class<?> packet_class = General.getCraftClass("Packet40EntityMetadata");
            Object packet = null;
            try {
                packet = packet_class.newInstance();
             
                Field a = General.getField(packet_class, "a");
                a.setAccessible(true);
                a.set(packet, EntityID);
             
                Method watcher_c = General.getMethod(watcher.getClass(), "c");
                Field b = General.getField(packet_class, "b");
                b.setAccessible(true);
                b.set(packet, watcher_c.invoke(watcher));
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
     
            return packet;
        }
     
        public Object getTeleportPacket(Location loc){
            Class<?> packet_class = General.getCraftClass("Packet34EntityTeleport");
            Object packet = null;
            try {
                packet = packet_class.newInstance();
             
                Field a = General.getField(packet_class, "a");
                a.setAccessible(true);
                a.set(packet, EntityID);
                Field b = General.getField(packet_class, "b");
                b.setAccessible(true);
                b.set(packet, (int) Math.floor(loc.getX() * 32.0D));
                Field c = General.getField(packet_class, "c");
                c.setAccessible(true);
                c.set(packet, (int) Math.floor(loc.getY() * 32.0D));
                Field d = General.getField(packet_class, "d");
                d.setAccessible(true);
                d.set(packet, (int) Math.floor(loc.getZ() * 32.0D));
                Field e = General.getField(packet_class, "e");
                e.setAccessible(true);
                e.set(packet, (byte) ((int) (loc.getYaw() * 256.0F / 360.0F)));
                Field f = General.getField(packet_class, "f");
                f.setAccessible(true);
                f.set(packet, (byte) ((int) (loc.getPitch() * 256.0F / 360.0F)));
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return packet;
        }
     
        public Object getRespawnPacket(){
            Class<?> packet_class = General.getCraftClass("Packet205ClientCommand");
            Object packet = null;
            try {
                packet = packet_class.newInstance();
             
                Field a = General.getField(packet_class, "a");
                a.setAccessible(true);
                a.set(packet, 1);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            }
            return packet;
        }
     
        public Object getWatcher(){
            Class<?> watcher_class = General.getCraftClass("DataWatcher");
            Object watcher = null;
            try {
                watcher = watcher_class.newInstance();
             
                Method a = General.getMethod(watcher_class, "a", new Class<?>[] {int.class, Object.class});
                a.setAccessible(true);
             
                a.invoke(watcher, 0, visible ? (byte)0 : (byte)0x20);
                a.invoke(watcher, 6, (Float) (float) health);
                a.invoke(watcher, 7, (Integer) (int) 0);
                a.invoke(watcher, 8, (Byte) (byte) 0);
                a.invoke(watcher, 10, (String) name);
                a.invoke(watcher, 11, (Byte) (byte) 1);
            } catch (InstantiationException e) {
                e.printStackTrace();
            } catch (IllegalAccessException e) {
                e.printStackTrace();
            } catch (IllegalArgumentException e) {
                e.printStackTrace();
            } catch (InvocationTargetException e) {
                e.printStackTrace();
            }
         
            return watcher;
        }
     
        public static void setStatus(Player player, String text, int healthpercent){
            FakeDragon dragon = null;
            if(dragonplayers.containsKey(player.getName())){
                dragon = dragonplayers.get(player.getName());
            }else if(!text.equals("")){
                dragon = new FakeDragon(text, ENTITY_ID, player.getLocation().add(0, -200, 0));
             
                dragonplayers.put(player.getName(), dragon);
            }
         
            if(text.equals("") && dragonplayers.containsKey(player.getName())){
                Object destroyPacket = dragon.getDestroyEntityPacket();
                General.sendPacket(player, destroyPacket);
             
                dragonplayers.remove(player.getName());
            }else{
                Object mobPacket = dragon.getMobPacket();
                General.sendPacket(player, mobPacket);
             
                dragon.health=(healthpercent/100f)*FakeDragon.MAX_HEALTH;
                Object metaPacket = dragon.getMetadataPacket(dragon.getWatcher());
                Object teleportPacket = dragon.getTeleportPacket(player.getLocation().add(0, -200, 0));
                General.sendPacket(player, metaPacket);
                General.sendPacket(player, teleportPacket);
            }
        }
     
        public static void displayDragonTextBar(Plugin plugin, String text, final Player player, long length){
            setStatus(player, text, 100);
     
            new BukkitRunnable(){
                @Override
                public void run(){
                    setStatus(player, "", 100);
                }
            }.runTaskLater(plugin, length);
        }
     
        public static void displayDragonLoadingBar(final Plugin plugin, final String text, final String completeText, final Player player, final int healthAdd, final long delay, final boolean loadUp){
            setStatus(player, "", (loadUp ? 1 : 100));
     
            new BukkitRunnable(){
                int health = (loadUp ? 1 : 100);
     
                @Override
                public void run(){
                    if((loadUp ? health < 100 : health > 1)){
                        setStatus(player, text, health);
                        if(loadUp){
                            health += healthAdd;
                        } else {
                            health -= healthAdd;
                        }
                    } else {
                        setStatus(player, completeText, (loadUp ? 100 : 1));
                        new BukkitRunnable(){
                            @Override
                            public void run(){
                                setStatus(player, "", (loadUp ? 100 : 1));
                            }
                        }.runTaskLater(plugin, 20);
     
                        this.cancel();
                    }
                }
            }.runTaskTimer(plugin, delay, delay);
        }
     
        public static void displayDragonLoadingBar(final Plugin plugin, final String text, final String completeText, final Player player, final int secondsDelay, final boolean loadUp){
            final int healthChangePerSecond = 100 / secondsDelay / 4;
     
            displayDragonLoadingBar(plugin, text, completeText, player, healthChangePerSecond, 5L, loadUp);
        }
     
    }
    
    it will also require this reflection class

    General.java
    Code:
    public class General {
        public static void sendPacket(Object packet){
            for(Player p : Bukkit.getOnlinePlayers()){
                sendPacket(p, packet);
            }
        }
     
        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, 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 name = Bukkit.getServer().getClass().getPackage().getName();
            String version = name.substring(name.lastIndexOf('.') + 1)+".";
            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(Entity entity){
            Object nms_entity = null;
            Method entity_getHandle = getMethod(entity.getClass(), "getHandle");
            try {
                nms_entity = entity_getHandle.invoke(entity);
            } 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 {
                Field field = cl.getDeclaredField(field_name);
                return field;
            } 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(Integer.valueOf(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;
        }
     
    }
    

    The methods in fakedragon:
    setStatus(Player p, String text, int percent);
    sets the status of a player. percent is out of 100. if text is set as "" it will get rid of the players bar altogether

    displayDragonTextBar(Plugin plugin, String text, Player player, long length);
    displays a simple text bar for a set period of time. length in seconds.

    displayDragonLoadingBar(Plugin plugin, String text, String completeText, Player player, int healthAdd, long delay, boolean loadup);
    displays a loading bar for the player. complete text shown for a second when loading is finished. health add is the health added per tick and delay is the period between each tick. if load up is true the bar will go from empty to full but if not it will go from full to empty.

    displayDragonLoadingBar(Plugin plugin, String text, String completeText, Player player, int secondsDelay, boolean loadup);
    A simplified version of other displayDragonLoadingBar method. seconds delay is the amount of time you want the message to appear for.
     
    hawkfalcon likes this.
  9. Offline

    darkness1999

    FakeDragon.displayDragonTextBar(ServerManager.plugin, "test", p, (long) 10); <-- this is working for me!
    FakeDragon.displayDragonLoadingBar(ServerManager.plugin, "test", "test 1", p, 10, (long) 10, true);

    And if I use the below one I get a null pointer exception. What have I done wrong?

    EDIT: I´m using the LIB from SoThatsIt
    EDIT: I edited nothing in the General and FakeDragon class.

    EDIT: Maybe I imported something wrong...it would be great if you could add the imports to the LIB
     
  10. Offline

    Hoolean

    Comphenix chasechocolate

    Hey guys :)

    Is it possible to show the health bar with a custom percent filled? And to keep it on the screen and not remove it?
     
  11. Offline

    chasechocolate

  12. Offline

    Hoolean

  13. Offline

    Deleted user

    SoThatsIt

    Having the a problem- Ender dragon spawns directly above player's head
     
  14. Offline

    Deleted user

  15. Offline

    chasechocolate

    Eballer48 hmm, does it ever go invisible?
     
  16. Offline

    Deleted user

    Nope
     
  17. Offline

    Minnymin3

    Using stuff from multiple posts here (though a lot of what SoThatsIt did) I created a mana bar :D
    [​IMG]
    Just wanted to say thanks and post another example image of what is possible with this resource.
     
    _DSH105_, chasechocolate and Hoolean like this.
  18. Offline

    chasechocolate

  19. Offline

    iZanax

    What is the range of the boss health bar?so on what range does the bar dissapear when somewalks too far away of the point where the fake boss is spawned.
     
  20. Offline

    Axe2760

    Creating an rpg plugin with lots of mobs and bosses for a server -- this has become extremely handy where applicable! Thanks for this awesome resource! :) I will provide credit in the code as well as somewhere on the server. is that alright?

    Thanks again! :p I'll post some screens when i feel like it :p
     
  21. Offline

    Ultimate_n00b

    Huh? It sends a fake packet to a certain player. So if you wanted a range, just get the nearby players and show them it.
     
  22. Offline

    Nebula111

    I am getting a orangish tinge when the bar comes up, any fixes?[​IMG]


    Code:
    public void task(){
            Bukkit.getServer().getScheduler().scheduleSyncRepeatingTask(this, new Runnable() {
         
                public void run() {
                    messages = getConfig().getStringList("Messages");
                    for (Player p : Bukkit.getOnlinePlayers()){
                    //    if (p.hasPermission("messageboard.ignore") || p.isOp()) return;
                        PacketUtils.displayTextBar("Testing", p);
                        p.sendMessage("Testing");
                    }
                 
                }
            }, 20,20 * 30);
     
        }
    chasechocolate
     
  23. Offline

    deathknife

    chasechocolate I'm quite new to bukkit, and i have encouraged error(s) while trying this out. first of all, displayTextBar gives me an error: http://prntscr.com/1vhzxp
    Second of all, I renamed MinecraftFPS.getInstance() to plugin but it gives me an error, how to i find out the instance of my main class?
     
  24. Offline

    chasechocolate

    deathknife for the first one, thanks for pointing that out, fixed the first post. As for your second question, search up "constructors".
     
  25. Offline

    deathknife

    chasechocolate
    i get internal error when using the examples u gave. When I remove those 2 lines, it works fine.
    It's on command, and i get player using:
    Player player = (Player) theSender;

    Console error on internal error:

    http://prntscr.com/1vloxk
    EDIT ---:
    I have used the method by SoThatsIt and it works fine.
     
  26. Offline

    confuserr

    If you're having trouble, try my BarAPI, you might find it easier.
     
  27. Offline

    bloodless2010

    How do you modify the health of the health bar?
     
  28. Offline

    chasechocolate

    bloodless2010 currently there is no method - it does it automatically - but I am working on an improved version that contains methods like that. I may release it as an API plugin or just make it into 1 class.
     
  29. Offline

    bloodless2010

    chasechocolate Well then this is useless to me I'm sorry, I need to use the hp bar as an xp bar for a plugin I'm working on.
     
  30. Offline

    xigsag

    There is this MinecraftFPS thing in there, giving me an error. What is that?
     
Thread Status:
Not open for further replies.

Share This Page