[Tutorial] Utilizing the Boss Health Bar

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

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

    etaxi341

    phips99 Same problem here :) But good that he will fix it tomorrow :D
     
  2. Offline

    Omerrg

    I used the fixed version by the one who posted on this topic. But i still have the smokie thing.
     
  3. Offline

    iZanax

    @chasechocolate

    I would highly appreciate to have it working version for 1.6.2,
    Since it didn't work anymore after 1.6. I hope u got some time to
    make it work with the latest changes.

    Thanks in advance.
     
  4. Offline

    phips99

    Omerrg which post do you mean?
     
  5. Offline

    chasechocolate

    Updated to 1.6.2! If you find any errors, please report them in the comments! Updated OP.
     
    hawkfalcon likes this.
  6. chasechocolate Can we use this in plugins we publish to bukkit dev?
     
  7. Offline

    chasechocolate

    BorisTheTerrible feel free to use this in plugins that you post to BukkitDev :)
     
  8. chasechocolate Okay thanks just wanted to make sure I wouldn't been doing anything illegal or want not.
     
  9. Offline

    chasechocolate

    BorisTheTerrible why would I post it here if I didn't want anybody to use it? :p
     
    jimuskin, etaxi341 and hawkfalcon like this.
  10. Offline

    SoThatsIt

    I have recently updated this to use the ender dragon instead of the wither. This gets rid of the smoke effect as well as the white effect that appears when the withers health gets low. Here are the new classes.

    FakeDragon:
    Code:
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
     
    import org.bukkit.Location;
    import org.bukkit.entity.EntityType;
     
    public class 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;
        }
       
    }
    General:

    Code:
    import java.lang.reflect.Constructor;
    import java.lang.reflect.Field;
    import java.lang.reflect.InvocationTargetException;
    import java.lang.reflect.Method;
    import java.util.Arrays;
    import java.util.HashMap;
    import java.util.Map;
     
    import org.bukkit.Bukkit;
    import org.bukkit.command.CommandMap;
    import org.bukkit.command.PluginCommand;
    import org.bukkit.entity.Entity;
    import org.bukkit.entity.Player;
    import org.bukkit.plugin.Plugin;
    import org.bukkit.scheduler.BukkitRunnable;
     
    public class General {
       
        public static Integer ENTITY_ID = 6000;
        public static Map<String, FakeDragon> dragonplayers = new HashMap<String, FakeDragon>();
       
        public static void setStatus(Player player, String text, int healthpercent){
            FakeDragon dragon = null;
            if(dragonplayers.containsKey(player.getName())){
                dragon = dragonplayers.get(player.getName());
            }else{
                dragon = new FakeDragon(text, ENTITY_ID, player.getLocation().add(0, -200, 0));
                Object mobPacket = dragon.getMobPacket();
                sendPacket(player, mobPacket);
               
                dragonplayers.put(player.getName(), dragon);
            }
           
            if(text == ""){
                Object destroyPacket = dragon.getDestroyEntityPacket();
                sendPacket(player, destroyPacket);
               
                dragonplayers.remove(player.getName());
            }else{
                dragon.name=text;
                dragon.health=(healthpercent/100f)*FakeDragon.MAX_HEALTH;
                Object metaPacket = dragon.getMetadataPacket(dragon.getWatcher());
                Object teleportPacket = dragon.getTeleportPacket(player.getLocation().add(0, -200, 0));
                sendPacket(player, metaPacket);
                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);
        }
       
        //Reflection Util
       
        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(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;
        }
     
    }
    
     
    Twister915 and etaxi341 like this.
  11. Offline

    Ultimate_n00b

    Figured it out. LivingEntity.getEntityId();
    When I use it though, it makes the entity disappear and turn into a gray wither power thingy..
    And, tried it again except made all the methods use the entities info. Makes the entity disappear, yet still exists (I did comment the invisibility line).
     
  12. Offline

    chasechocolate

    Ultimate_n00b I know that ._. read what I put in the parenthesizes.
     
  13. Offline

    Ultimate_n00b

    Oh derp ._.

    Well, thanks for the resource. Works like a charm.
     
  14. Offline

    Twister915

    SoThatsIt
    http://puu.sh/3JEkx.jar
    Turned it into a plugin that serves as an API

    Listen for MessageBarSetEvent and depend on MessageBarAPI. :)
     
  15. SoThatsIt Nice but do I have to have protocallib or protocalwrapper stuff for that?
     
  16. Offline

    Nosliw

    No, it works normally :)

    Hmm, something that I did was use an EnderDragon, but +300 on Y coord, this meant that the player couldn't see anything, but because it's an EnderDragon, the health bar is shown no matter what direction you look:)
     
  17. Offline

    Miro

    So is there any easy way to change the original code to the one for the ender dragon? Changing the entity id does change it to an ender dragon, but it's not invisible anymore.

    EDIT: I solved this by just spawning the enderdragon about 200 blocks under the map.
     
  18. Offline

    CoKoC

    chasechocolate
    Created a method which allows to set the bar's percentage : https://gist.github.com/anonymous/6153589

    Also you should make something to set how long we want the message to show, because with that API we can't set it to infinite time. That probably means another method to hide boss bar manually.

    For instance, the code I made doesn't spawn the boss on the player's location. It spawns him 100 blocks away in the direction the player is looking at, excluding the Y axis.
     
    Maulss, BPOtacon and chasechocolate like this.
  19. Offline

    chasechocolate

    CoKoC I'll add those when I get back this weekend. Thanks for the suggestions :D
     
    BPOtacon likes this.
  20. Offline

    Ultimate_n00b

    After testing on a skyblock server, I noticed players talking about a glitched enderdragon in the void..
     
  21. Ultimate_n00b That is because to get around the enderdragon not being able to be set invisibile. The enderdragon is just set to below bedrock.
     
  22. Offline

    Ultimate_n00b

    Yeah, I also just found where the flag is set in the watcher.
     
  23. This would work with any boss in the game. Right?
     
  24. Offline

    Nosliw

    It should work with Withers and Ender Dragons, the only two bosses currently in the game, yes. But if they add more, there is no guarantee it would work, but it should do.
     
  25. Offline

    Ultimate_n00b

    I noticed the the normal ender dragon/wither's boss bars override this one, unless you keep sending this packet to the player.
     
  26. Offline

    Nosliw

    I'm not sure what this has to do with my comment. Although, I think with the Wither boss, the health bar shows which one you are looking at, and I'm not sure, but the Ender Dragon might work based on distance to player or the order the entity appeared. But in most cases, I don't think you would have much of an issue here..
     
  27. Offline

    n1ghtk1n9

    chasechocolate is there a lib I'm missing or something? B/c all of the Packet stuff are null and a lot of the imports are invalid(all of the net.minecraft.server imports, and org.bukkit.craftbukkit.v1_6_R2.entity.CraftPlayer)
     
  28. Offline

    chasechocolate

  29. Offline

    n1ghtk1n9

    chasechocolate What's the difference between the craftbukkit.jar and bukkit.jar? (Sorry if this is a noob question, I've only been using Bukkit/Developing plugins for ~3-4 days)
     
  30. Offline

    ampayne2

    Bukkit is just the api, Craftbukkit is the actual server. Usually you don't need to use it, only if you need to do something there isn't an API for.
     
Thread Status:
Not open for further replies.

Share This Page