Library Holographic Displays v2: an easy way to manage holograms (+ power ups)

Discussion in 'Resources' started by filoghost, May 19, 2014.

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

    filoghost

    Holographic Displays includes a simple API for developers. Here's a tutorial on how to use it.


    Why should you use it
    • Stable, efficient and easy to use.
    • You don't have to use any NMS code.
    • Automatic chunk loading / unloading management (doesn't keep chunks loaded).
    • Always updated to support multiple Bukkit/Spigot/MCPC+/Cauldron versions.
    Tutorial
    Let's start with the tutorial! This is what we're going to create:
    [​IMG]

    Creating an hologram is really simple and just requires a basic Bukkit knowledge. Code example:
    Code:java
    1. // Suppose that "player" is a Player object obtained before.
    2. Hologram hologram = HologramsAPI.createHologram(this, player.getEyeLocation());
    3. hologram.appendTextLine("This is a hologram.", ChatColor.AQUA + "Hello world!");
    4.  


    The hologram is not automatically saved to disk. If you don't remove it, it will stay until server stop.


    How to use it in your plugin
    First of all, add 'softdepend' to your plugin.yml:
    Code:
    softdepend: [HolographicDisplays]
    Then check if Holographic Displays is correctly installed and loaded in your onEnable():
    Code:java
    1. if (!Bukkit.getPluginManager().isPluginEnabled("HolographicDisplays")) {
    2. getLogger().severe("*** HolographicDisplays is not installed or not enabled. ***");
    3. getLogger().severe("*** This plugin will be disabled. ***");
    4. this.setEnabled(false);
    5. return;
    6. }


    If Holographic Displays is not strictly needed, you can use a boolean in your plugin's instance to check if you should use holograms, and continue with the execution instead of disabling your plugin.

    Now you can just use static methods from the class HologramsAPI, as shown in the example above.


    Other tutorials (on GitHub)

    How to create icons
    [​IMG]

    How to create power ups
    [​IMG]


    Read more
    Full API tutorial: [link]
    Hologram class (javadocs): [link]
    HologramsAPI class (javadocs): [link]



    Feedback is appreciated, whether positive or negative. If I forgot something or you just need help, please let me know. Thanks for reading!
     
    Last edited: Dec 21, 2014
  2. Offline

    Onlineids

    How is this better or more useful than HoloApi?
     
    DSH105 likes this.
  3. Offline

    filoghost

    More efficient (custom entities are faster than packets), easier to use API (in my opinion), more stable (all the mayor bugs were fixed 1-2 months ago), MCPC+ full support (1.6 and 1.7), used by more servers.

    Downsides: individual holograms require ProtocolLib, doesn't still support GIFs, and something else that I may not remember.
     
    Bammerbom and Phasesaber like this.
  4. Offline

    Onlineids

    Does it have clickable holograms? Per player holograms?
     
  5. Offline

    filoghost

    Onlineids Touch holograms are not ready yet, but they are ~90% complete. You can have a hologram shown to one player only, but custom individual variables are not included. You must use ProtocolLib, as I did with {player} and {displayname}.
     
  6. Offline

    DSH105

    There is one simple answer to that; personal choice ;)

    HoloAPI (as the name suggests) is specifically designed to be an API. In that respect, it is more extensive and opens up plenty more opportunities for developers than you may have realised :).
     
  7. Can you provide evidence for your claims? Custom entities use packets + use server memory. That means they're both heavy on the client and the server. Packets however are only heavy on the client which results (or should result) in less server lag. Claiming that your entities are better than packets is the same as claiming that being hit by a (driving) car is better than being hit by a pedestrian.
     
  8. Offline

    ccrama


    By their very nature, holograms are resource-intensive. They were not intended to be used in such a way by Mojang, and many would consider it a "hack" whether you use entities or packets. Once everyone has them on their servers, I think this fad will be replaced by the newest coolest thing, but until then we are stuck with the lag.
     
  9. ccrama That is exactly my point. They are very resource-intensive and that is exactly why HoloAPI uses packets, which means the server has no idea the holograms are there (which results in barely/no server lag). Yes the creation of our holograms may take a bit (0.5 ticks?) longer but because the server has no idea the holograms are there, it won't care about them. With custom entities this is entirely different, the server knows there is "something" there, and runs checks and onTick() methods on it.
     
  10. Offline

    filoghost


    I've made some test, with 20 holograms in a single chunk (1 line each one). HoloAPI spent 5 millis on PlayerTeleportEvent, while HolographicDisplays lets the server handle everything. Why should the server lag, if the entities do not even tick? I think it's much more resource intensive doing calculation with players, acting like if holograms are really there. Why not let the server handle them? It runs the "onTick" method, but it's empty. An example could be:

    You have a villager, that doesn't move and when you interact it opens a custom GUI.
    You would just spawn an entity and customize it, instead of sending packets.

    CaptainBern If you want, I can make a benchmark, and see if I'm correct.

    DSH105 Yes, your API is more advanced, but usually people do not need to make complex things with holograms. For example, a minigame that handles the scores through holograms doesn't need a lot of methods, just a setLine().
     
  11. filoghost The methods we use to calculate where to place our holograms are also calculated by you, well by the server to be specific so that isn't a valid argument either.
    Again, please provide sources for your claims.
     
  12. Offline

    filoghost


    Setup:
    20 holograms for each plugin, with one line, in the same location.

    Image:
    Show Spoiler

    [​IMG]


    Execution:
    - Start the server with the holograms already loaded.
    - /timings reset.
    - Made the chunk load 3 times.
    - Teleported to myself 3 times.
    - 1st timings test.
    - After ~10 minutes standing still and writing this post, 2nd timings test.

    Results:
    1) http://aikar.co/timings.php?url=16a41b4e38b83ba37b6f0ba35dcec595
    2) http://aikar.co/timings.php?url=cd33f4357bba92a5e8d7d623e077792b

    First test:
    Average tick for EntityHologramWitherSkull: 0.0008 ms
    Average tick for EntityHologramHorse: 0.0003 ms

    Second test:
    Average tick for EntityHologramWitherSkull: 0.0004 ms
    Average tick for EntityHologramHorse: 0.0002 ms

    As said the tick method is (nearly) empty, and doesn't have any impact on the server.

    8.6823 ms for PlayerTeleportEvent with HoloAPI, while HolographicDisplays doesn't even have registered the event. Holographic Displays is also faster in ChunkLoadEvent and in ChunkUnloadEvent. Sending packets with Bukkit object can't be faster or more than built-in nms methods. It also refreshes the hologram on teleport even if the player is near, that is useless.


    That's why I didn't switched to packets.
     
  13. filoghost Mind sending me the benchmark code? Also why "Sending packets with Bukkit object can't be faster or more than built-in nms methods" ? The only thing that could slow down the packet sending is when we get the send method, which is used by the nms-code.
     
  14. Offline

    filoghost

    There's no code to benchmark, just the latest versions of the two plugins, moving in the world making the chunks load / unload, and /tp filoghost filoghost.

    Correction, Bukkit objects slightly reduce performance (I can only think about casting to CraftPlayer, and the code to find near players). Reflection affects performance. I cannot prove it, I just think that using direct nms methods is faster, or at least equal.
     
  15. I never claimed reflection is faster :p . Your comment was a bit unclear, like you meant "using bukkit to send packets is slower" - which is always false because there is no packet-api in bukkit. Ofcourse reflection is slower, the way it works etc, no need to proof that :p
     
  16. Offline

    filoghost

    CaptainBern Yes, thanks for the correction. Do you trust me now? :)
     
    CaptainBern likes this.
  17. filoghost It's not about trust, it's just that I do not need to appriciate you making claims about my plugin without proper evidence :) (I just discovered a bug because of the "packet sending" you said ;) )
     
  18. Offline

    filoghost

    Ok, no problem :D
     
  19. Offline

    BungeeTheCookie

  20. Offline

    Phasesaber

    With the new naming of any mob that is going to be in 1.8, you can name wither skulls with 0 motion, making them invisible! So, people will continue to make them.
     
  21. Offline

    unforgiven5232

    filoghost hey this is rly cool but I have one question , if I have multiple of these would it lag the server? So for example 20 of them near in one area
     
  22. Offline

    Ultimate_n00b

    If they're in a loaded chunk, a ton of them will start to lag because filog uses actual entities (not packets).
     
    unforgiven5232 and DSH105 like this.
  23. Offline

    filoghost

    Ultimate_n00b what you're saying is false, read the benchmarks. The entities do not tick, and server automatically sends the needed packets. It's actually less efficient with packets than with entities.

    Phasesaber yes I will change to the new system :)

    unforgiven5232 20 holograms are not a problem for the server. The problem is that too many of them can cause fps drops.

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

    Ultimate_n00b

    Hm? I did a lot of tests involving the time for the minecraft ticking method to run. Adding a lot of these (example: 200-1000 spread across the world) will cause a delay in the ticking thread.
     
    DSH105 likes this.
  25. Offline

    filoghost

    Ultimate_n00b there's nothing to measure... the methods are nearly empty.
     
  26. Offline

    BungeeTheCookie

    PHP:
        [11:07:39] [Server thread/ERROR]: Could not pass event ChunkLoadEvent to HolographicDisplays v1.8.2
    org
    .bukkit.event.EventException
        at org
    .bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:294)
        
    at org.bukkit.plugin.RegisteredListener.callEvent(RegisteredListener.java:62)
        
    at org.bukkit.plugin.TimedRegisteredListener.callEvent(TimedRegisteredListener.java:30)
        
    at org.bukkit.plugin.SimplePluginManager.fireEvent(SimplePluginManager.java:502)
        
    at org.bukkit.plugin.SimplePluginManager.callEvent(SimplePluginManager.java:487)
        
    at org.bukkit.craftbukkit.v1_7_R3.chunkio.ChunkIOProvider.callStage2(ChunkIOProvider.java:48)
        
    at org.bukkit.craftbukkit.v1_7_R3.chunkio.ChunkIOProvider.callStage2(ChunkIOProvider.java:13)
        
    at org.bukkit.craftbukkit.v1_7_R3.util.AsynchronousExecutor$Task.finish(AsynchronousExecutor.java:188)
        
    at org.bukkit.craftbukkit.v1_7_R3.util.AsynchronousExecutor$Task.get(AsynchronousExecutor.java:164)
        
    at org.bukkit.craftbukkit.v1_7_R3.util.AsynchronousExecutor.skipQueue(AsynchronousExecutor.java:334)
        
    at org.bukkit.craftbukkit.v1_7_R3.util.AsynchronousExecutor.getSkipQueue(AsynchronousExecutor.java:295)
        
    at org.bukkit.craftbukkit.v1_7_R3.chunkio.ChunkIOExecutor.syncChunkLoad(ChunkIOExecutor.java:16)
        
    at net.minecraft.server.v1_7_R3.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:116)
        
    at net.minecraft.server.v1_7_R3.ChunkProviderServer.getChunkAt(ChunkProviderServer.java:98)
        
    at net.minecraft.server.v1_7_R3.PlayerList.a(PlayerList.java:211)
        
    at net.minecraft.server.v1_7_R3.PlayerList.c(PlayerList.java:268)
        
    at net.minecraft.server.v1_7_R3.PlayerList.a(PlayerList.java:138)
        
    at net.minecraft.server.v1_7_R3.LoginListener.c(LoginListener.java:105)
        
    at net.minecraft.server.v1_7_R3.LoginListener.a(LoginListener.java:43)
        
    at net.minecraft.server.v1_7_R3.NetworkManager.a(NetworkManager.java:183)
        
    at net.minecraft.server.v1_7_R3.ServerConnection.c(ServerConnection.java:81)
        
    at net.minecraft.server.v1_7_R3.MinecraftServer.v(MinecraftServer.java:713)
        
    at net.minecraft.server.v1_7_R3.DedicatedServer.v(DedicatedServer.java:283)
        
    at net.minecraft.server.v1_7_R3.MinecraftServer.u(MinecraftServer.java:576)
        
    at net.minecraft.server.v1_7_R3.MinecraftServer.run(MinecraftServer.java:482)
        
    at net.minecraft.server.v1_7_R3.ThreadServerApplication.run(SourceFile:628)
    Caused byjava.lang.NullPointerException
        at com
    .gmail.filoghost.holograms.object.HologramLine.spawn(HologramLine.java:33) ~[?:?]
        
    at com.gmail.filoghost.holograms.object.CraftHologram.forceUpdate(CraftHologram.java:129) ~[?:?]
        
    at com.gmail.filoghost.holograms.object.APIHologramManager.onChunkLoad(APIHologramManager.java:25) ~[?:?]
        
    at com.gmail.filoghost.holograms.listener.MainListener.onChunkLoad(MainListener.java:48) ~[?:?]
        
    at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) ~[?:1.8.0]
        
    at sun.reflect.NativeMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0]
        
    at sun.reflect.DelegatingMethodAccessorImpl.invoke(Unknown Source) ~[?:1.8.0]
        
    at java.lang.reflect.Method.invoke(Unknown Source) ~[?:1.8.0]
        
    at org.bukkit.plugin.java.JavaPluginLoader$1.execute(JavaPluginLoader.java:292) ~]
        ... 
    25 more
    @flioghost
    Why was this error thrown when I joined?
    Code:
    public class DisplayChicken {
     
    private ClassDisplay display;
    private JavaPlugin plugin;
     
        public DisplayChicken(ClassDisplay display, JavaPlugin plugin){
            this.display = display;
            this.plugin = plugin;
        }
     
        public ClassDisplay getDisplay(){
            return display;
        }
     
        public void spawn(){
            Location l = getDisplay().getLocation();
            Chicken chicken = l.getWorld().spawn(l, Chicken.class);
            EntitySpeedModifier.setSpeed(chicken, Double.MAX_VALUE);
            HolographicDisplaysAPI.createHologram(plugin, l.add(0, 2, 0), MessageManager.translateColors("&e&l" + display.getClassBase().getDisplayName()));
        }
    }
    
     
  27. Offline

    filoghost

  28. Offline

    Ultimate_n00b

    The amount of time it takes to tick entities? That's measurable. Or even better, time taken to tick hologram parts. Also measurable.
     
  29. Offline

    filoghost

    Ultimate_n00b this is the method for horses, and I don't think it's accurately measurable because it's very fast:
    Code:java
    1. if (ticksLived % 20 == 0) {
    2. // The horse dies without a vehicle.
    3. if (this.vehicle == null) {
    4. die();
    5. }
    6. }
    7.  
    8. if (!lockTick) {
    9. super.h();
    10. }


    The timings say 0.0003-0.0002 millis for each of them.
     
  30. Offline

    Ultimate_n00b

    I'm not talking about the single methods, I'm talking about as a whole. Take for example, it calculates if a player is near enough to view it. How long does that method takes? I've been doing all the calculating via packets on an async thread, which is much faster.
     
    DSH105 likes this.
Thread Status:
Not open for further replies.

Share This Page