Util Holograms

Discussion in 'Resources' started by Ultimate_n00b, Feb 25, 2014.

Thread Status:
Not open for further replies.
  1. [​IMG]

    I finally finished coding no dependency holograms, which I'm sure you've heard of by now.

    These do not require and dependency such as ProtocolLib, and work fine on their own.

    Code:java
    1. public class Hologram {
    2. private static final double distance = 0.23;
    3. private List<String> lines = new ArrayList<String>();
    4. private List<Integer> ids = new ArrayList<Integer>();
    5. private boolean showing = false;
    6. private Location location;
    7.  
    8. public Hologram(String... lines) {
    9. this.lines.addAll(Arrays.asList(lines));
    10. }
    11.  
    12. public void change(String... lines) {
    13. destroy();
    14. this.lines = Arrays.asList(lines);
    15. show(this.location);
    16. }
    17.  
    18. public void show(Location loc) {
    19. if (showing == true) {
    20. try {
    21. throw new Exception("Is already showing!");
    22. } catch (Exception e) {
    23. e.printStackTrace();
    24. }
    25. }
    26. Location first = loc.clone().add(0, (this.lines.size() / 2) * distance, 0);
    27. for (int i = 0; i < this.lines.size(); i++) {
    28. ids.addAll(showLine(first.clone(), this.lines.get(i)));
    29. first.subtract(0, distance, 0);
    30. }
    31. showing = true;
    32. this.location = loc;
    33. }
    34.  
    35. public void show(Location loc, long ticks) {
    36. show(loc);
    37. new BukkitRunnable() {
    38. @Override
    39. public void run() {
    40. destroy();
    41. }
    42. }.runTaskLater(MMGames.getPlugin(), ticks);
    43. }
    44.  
    45. public void destroy() {
    46. if (showing == false) {
    47. try {
    48. throw new Exception("Isn't showing!");
    49. } catch (Exception e) {
    50. e.printStackTrace();
    51. }
    52. }
    53. int[] ints = new int[this.ids.size()];
    54. for (int j = 0; j < ints.length; j++) {
    55. ints[j] = ids.get(j);
    56. }
    57. PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ints);
    58. for (Player player : Bukkit.getOnlinePlayers()) {
    59. ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
    60. }
    61. showing = false;
    62. this.location = null;
    63. }
    64.  
    65. private static List<Integer> showLine(Location loc, String text) {
    66. WorldServer world = ((CraftWorld) loc.getWorld()).getHandle();
    67. EntityWitherSkull skull = new EntityWitherSkull(world);
    68. skull.setLocation(loc.getX(), loc.getY() + 1 + 55, loc.getZ(), 0, 0);
    69. PacketPlayOutSpawnEntity skull_packet = new PacketPlayOutSpawnEntity(skull);
    70.  
    71. EntityHorse horse = new EntityHorse(world);
    72. horse.setLocation(loc.getX(), loc.getY() + 55, loc.getZ(), 0, 0);
    73. horse.setAge(-1700000);
    74. horse.setCustomName(text);
    75. horse.setCustomNameVisible(true);
    76. PacketPlayOutSpawnEntityLiving packedt = new PacketPlayOutSpawnEntityLiving(horse);
    77. for (Player player : loc.getWorld().getPlayers()) {
    78. EntityPlayer nmsPlayer = ((CraftPlayer) player).getHandle();
    79. nmsPlayer.playerConnection.sendPacket(packedt);
    80. nmsPlayer.playerConnection.sendPacket(skull_packet);
    81.  
    82. PacketPlayOutAttachEntity pa = new PacketPlayOutAttachEntity(0, horse, skull);
    83. nmsPlayer.playerConnection.sendPacket(pa);
    84. }
    85. return Arrays.asList(skull.getId(), horse.getId());
    86. }
    87.  
    88. }


    Basic Usage:

    Code:java
    1. new Hologram(ChatColor.GOLD + "" + ChatColor.BOLD + "Welcome to the server!", "Do /help if you need any help!").show(location)


    COMING SOON: Plugin with more features than a single class could hold.

    Big thanks to Goblom , zombiekiller753 , and to Asdjke for the original idea.
     
    macmc, jjssman, WesJD and 10 others like this.
  2. Offline

    zombiekiller753

    How bout this?

    Code:
    package com.zombiekiller753.holograms;
     
    import java.util.HashMap;
     
    import net.minecraft.server.v1_7_R1.EntityHorse;
    import net.minecraft.server.v1_7_R1.EntityWitherSkull;
    import net.minecraft.server.v1_7_R1.Packet;
    import net.minecraft.server.v1_7_R1.PacketPlayOutAttachEntity;
    import net.minecraft.server.v1_7_R1.PacketPlayOutEntityDestroy;
    import net.minecraft.server.v1_7_R1.PacketPlayOutSpawnEntityLiving;
    import net.minecraft.server.v1_7_R1.World;
     
    import org.bukkit.Bukkit;
    import org.bukkit.Location;
    import org.bukkit.craftbukkit.v1_7_R1.CraftWorld;
    import org.bukkit.craftbukkit.v1_7_R1.entity.CraftPlayer;
    import org.bukkit.entity.Player;
     
    public class Hologram {
        private final Location loc;
        private final double dy;
        private final String message;
        private final World world;
        private final EntityWitherSkull skull;
        private HashMap<String, Integer> tags = new HashMap<String, Integer>();
        private boolean lock = false;
        
        public Hologram(Location loc, double dy, String message) {
            this.loc = loc;
            this.dy = dy;
            this.message = message;
            this.world = ((CraftWorld) loc.getWorld()).getHandle();
            skull = new EntityWitherSkull(world);
            skull.setLocation(loc.getX(), loc.getY() + dy + 55, loc.getZ(), 0, 0);
            ((CraftWorld) loc.getWorld()).getHandle().addEntity(skull);
        }
        public Hologram(String world, double x, double y, double z, double dy, String message) {
            this(new Location(Bukkit.getWorld(world), x, y, z), dy, message);
        }
        
        public void send(Player player) throws Exception {
            if (!lock) {
                EntityHorse horse = new EntityHorse(world);
                horse.setLocation(loc.getX(), loc.getY() + dy + 55.25, loc.getZ(), 0, 0);
                horse.setAge(-1700000);
                horse.setCustomName(message);
                horse.setCustomNameVisible(true);
                PacketPlayOutSpawnEntityLiving spawn = new PacketPlayOutSpawnEntityLiving(horse);
                sendPacket(player, spawn);
                
                PacketPlayOutAttachEntity pa = new PacketPlayOutAttachEntity(0, horse, skull);
                sendPacket(player, pa);
                tags.put(player.getName(), horse.getId());
            } else {
                throw new Exception("There is a lock on this hologram!");
            }
        }
        public void remove(Player player) throws Exception {
            if (!lock) {
                PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(tags.get(player.getName()));
                sendPacket(player, packet);
                tags.remove(player.getName());
            } else {
                throw new Exception("There is a lock on this hologram!");
            }
        }
        public void remove() throws Exception {
            if (!lock) {
                lock = true;
                for (String s : tags.keySet()) {
                    PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(tags.get(s));
                    sendPacket(Bukkit.getPlayer(s), packet);
                }
                tags.clear();
            } else {
                throw new Exception("There is a lock on this hologram!");
            }
        }
        private void sendPacket(Player p, Packet packet) {
            ((CraftPlayer) p).getHandle().playerConnection.sendPacket(packet);
        }
    }
    
    https://gist.github.com/zombiekiller753/9222882
     
  3. There's a few things I see this doesn't include, mainly the fact that you need to make an hologram for each line. In my post, you can easily make it multilined. As well, it has support for ImageMessage's array of text.
     
  4. Nice work, I'm totally going to use this ;D

    Could you add some comments in your code, to show which line does what or something like that?
     
    Niknea likes this.
  5. Offline

    CrazyGuy3000

    ^ this please, would be easier to read IMO x3
     
  6. Offline

    zombiekiller753

    bluegru CrazyGuy3000
    Gonna add that, but I'm also planning to release an API, so I'm not sure
     
  7. Ultimate_n00b Hmm, NPE on line 87,
    Code:java
    1. WorldServer world = ((CraftWorld) loc.getWorld()).getHandle();

    My world is
    Code:java
    1. public static Location hub = new Location(Bukkit.getWorld("hub"), 13.12185, -294.23402, 2);
    2.  

    which doesn't return null in any other places that I use it. Also, you still have your plugin mentioned a few places in your class (specifically the runnables, with plugin). It would be a good idea to change those to save some headaches ;)

    Cheers,
    ccrama
     
  8. You are correct about it being simpler, however there's quite a few issues with yours. For one, the entities have a number of requirements before they can spawn. As well, there are a number of plugins that can modify your entities. There are a few other flaws, but I'm sure you already know them.
     
  9. Offline

    Dread9Nought

  10. Offline

    zombiekiller753

    ccrama Not WorldServer. World.

    import net.minecraft.server.v1_7_R1.World;
    Dread9Nought
    [​IMG]

    filoghost This method is better because rather than spawning in entities, which makes /killall ruin it, this just sends packets.
     
  11. This is sick, thanks.
    I used it for messages on the screen. You know how games have that popup with "gained 5 XP" or something..?
     
    Phasesaber likes this.
  12. Desle

    This is exactly what I want to do ;D
    Do you mind to show me the code?
     
  13. bluegru
    It's really easy.
    I've just modified the class above a bit, so you can tell it what players to send the hologram to.
    When they kill a player, just show a hologram to the killer, on the location of the killed entity.

    Code:java
    1. public void expMessage(Player p, Location loc, double gained, double needed, double current) {
    2. if(gained == 0) {
    3. return;
    4. }
    5. final Hologram holo = new Hologram(ChatColor.RED + "+ " + gained + " XP", ChatColor.GRAY + "[" + current + "/" + needed + "]");
    6. holo.show(p, loc);
    7. Bukkit.getScheduler().scheduleSyncDelayedTask(this, new BukkitRunnable() {
    8.  
    9. @Override
    10. public void run() {
    11. holo.destroy();
    12. }
    13. }, getConfig().getInt("configuration" + ".xpmessages-time"));
    14. }


    And here is the Hologram class;
    Code:java
    1. public class Hologram {
    2. private static final double distance = 0.23;
    3. private List<String> lines = new ArrayList<String>();
    4. private List<Integer> ids = new ArrayList<Integer>();
    5. private boolean showing = false;
    6. private Location location;
    7.  
    8. public Hologram(String... lines) {
    9. this.lines.addAll(Arrays.asList(lines));
    10. }
    11.  
    12. public void show(Player p, Location loc) {
    13. if (showing == true) {
    14. try {
    15. throw new Exception("Is already showing!");
    16. } catch (Exception e) {
    17. e.printStackTrace();
    18. }
    19. }
    20. Location first = loc.clone().add(0, (this.lines.size() / 2) * distance, 0);
    21. for (int i = 0; i < this.lines.size(); i++) {
    22. ids.addAll(showLine(p, first.clone(), this.lines.get(i)));
    23. first.subtract(0, distance, 0);
    24. }
    25. showing = true;
    26. this.location = loc;
    27. }
    28.  
    29. public void destroy() {
    30. if (showing == false) {
    31. try {
    32. throw new Exception("Isn't showing!");
    33. } catch (Exception e) {
    34. e.printStackTrace();
    35. }
    36. }
    37. int[] ints = new int[this.ids.size()];
    38. for (int j = 0; j < ints.length; j++) {
    39. ints[j] = ids.get(j);
    40. }
    41. PacketPlayOutEntityDestroy packet = new PacketPlayOutEntityDestroy(ints);
    42. for (Player player : Bukkit.getOnlinePlayers()) {
    43. ((CraftPlayer) player).getHandle().playerConnection.sendPacket(packet);
    44. }
    45. showing = false;
    46. this.location = null;
    47. }
    48.  
    49. private static List<Integer> showLine(Player p, Location loc, String text) {
    50. WorldServer world = ((CraftWorld) loc.getWorld()).getHandle();
    51. EntityWitherSkull skull = new EntityWitherSkull(world);
    52. skull.setLocation(loc.getX(), loc.getY() + 1 + 55, loc.getZ(), 0, 0);
    53. ((CraftWorld) loc.getWorld()).getHandle().addEntity(skull);
    54.  
    55. EntityHorse horse = new EntityHorse(world);
    56. horse.setLocation(loc.getX(), loc.getY() + 55, loc.getZ(), 0, 0);
    57. horse.setAge(-1700000);
    58. horse.setCustomName(text);
    59. horse.setCustomNameVisible(true);
    60. PacketPlayOutSpawnEntityLiving packedt = new PacketPlayOutSpawnEntityLiving(horse);
    61. EntityPlayer nmsPlayer = ((CraftPlayer) p).getHandle();
    62. nmsPlayer.playerConnection.sendPacket(packedt);
    63.  
    64. PacketPlayOutAttachEntity pa = new PacketPlayOutAttachEntity(0, horse, skull);
    65. nmsPlayer.playerConnection.sendPacket(pa);
    66. return Arrays.asList(skull.getId(), horse.getId());
    67. }
    68. }
     
  14. zombiekiller753 Ultimate_n00b after changing it from WorldServer to World, it still throws an NPE at me. Could anything else be the issue?

    //EDIT:
    My LOCATION was the NPE (don't know why), but even if I set the spawn location to the user's location, it still doesn't appear. I thought it was the location angle was making it invisible, but I added 3 to the Y value to no avail. Any ideas?
     
  15. Offline

    zombiekiller753

    ccrama
    I'll take a look at it, and see what could be wrong. What's your dy value though?


    Also, I don't know about Paul, but I would like credit if possible :p
     
  16. Ultimate_n00b There's some downsides for each method. With your method you have to handle teleports, players that join and leave, etc. With mine, I should take care of other plugins killing my entities. But I will add a fake CraftEntity that extends their relative CraftEntities removing the method .remove(); (making it empty). Other plugins then should be able to kill my entities only with NMS.
     
  17. SoThatsIt I'm not quite sure.

    all Remodeling it, will release new version later today.

    Not really, but WorldServer is the correct thing.

    EDIT by Moderator: merged posts, please use the edit button instead of double posting.
     
    Last edited by a moderator: Jun 6, 2016
  18. Offline

    sipsi133

  19. sipsi133
    You have to store all holograms in a list, so you can just loop through that list and destroy() them.
     
  20. sipsi133 Desle Almost done with a new version which will make this easier.
     
  21. Is there a way to make it with no animals? If I'm using mc-core with animals option disabled, it wouldn't show...
     
  22. Really? hm.. Are you sure it's not something you're doing wrong? I tested with blocking all types of mob spawning, nothing came up.
     
  23. Ultimate_n00b ok, sorry I was doing it wrong xD
    But after I reload/relog on the server, the nametag disappears :/
     
  24. You'll have to recreate it, I don't save them for you.
     
  25. Would it work if I sent them to a List, and whenever the player joins, it re-makes the holograms?
    (And then, when server stops, send the list to a config file, and when load the server again, re-make all the holograms?)
     
  26. Nice, I saw this in vanilla from Asdjke and ever since I have been really looking forward to working with it. It gives everything just a bit more pizzazz, so good job! :)

    As for LCastr0 's issue if, with Ultimate_n00b 's consent, I would love to edit the code a bit so it's a bit more relog friendly and post it in here. For the reload just put the Hologram in the onEnable method.
     
Thread Status:
Not open for further replies.

Share This Page