NMS Get Players ping!

Discussion in 'Resources' started by mine-care, Jan 24, 2015.

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

    mine-care

    As the title sugests, here you can find how to get player's ping!
    This is usefull especially for game servers/minigames either to know when a player is lagging or to add the command /ping ingame :- )

    Method #1 (version depended but simple and small) This method is more practical to understand how its done than implement it in code.
    Code:
       public int getPing(Player who){
            //turning player to CraftPlayer, then to EntityPlayer (.getHandle()) and getting field "ping"
            return ((CraftPlayer)who).getHandle().ping;
        }
    Method #2 (Version independed!) now this is the version that is better to use in code even if it is less efficient than Method #1, and the reason is because if your plugin is build on version 1.7.2 and server is on version 1.7.10 it will still work :)
    Code:
        public int pingPlayer(Player who) {
            try {
                // Building the version of the server in such a form we can use it
                // in NMS code.
                String bukkitversion = Bukkit.getServer().getClass().getPackage()
                        .getName().substring(23);
                // Getting craftplayer
                Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit."
                        + bukkitversion + ".entity.CraftPlayer");
                // Invoking method getHandle() for the player
                Object handle = craftPlayer.getMethod("getHandle").invoke(who);
                // Getting field "ping" that holds player's ping obviously
                Integer ping = (Integer) handle.getClass().getDeclaredField("ping")
                        .get(handle);
                // Returning the ping
                return ping.intValue();
            } catch (ClassNotFoundException | IllegalAccessException
                    | IllegalArgumentException | InvocationTargetException
                    | NoSuchMethodException | SecurityException
                    | NoSuchFieldException e) {
                // Handle exceptions however you like, i chose to return value of
                // -1; since player's ping can't be -1.
                return -1;
            }
        }
    
    Thanks @DJSkepter and @RingOfStorms for their help :- )


    Thanks for reading!
    Hope you like it!

    PS. if i have any error please mind leaving a reply pointing it out <3 thanks!
     
    Last edited: Jan 25, 2015
  2. @mine-care Why did you cast to player? My method (using Reflection) didn't require casting...
     
  3. Offline

    mine-care

    @DJSkepter where u mean?
    Thanks for ya comment :- )
     
  4. @mine-care You used
    Code:
    craftPlayer.cast(who);
    whereas when I had done the same outcome in my ReflectionUtils, I didn't need to cast the player to CraftPlayer
     
  5. Offline

    mine-care

    @DJSkepter :O really? how did you obtain ping then? it is not available in player obj :/ it is in EntityPlayer that i need to obtain from craftplayer's handle.... If you want i can add your method of doing this in this thread =)
    Thanks.
     
  6. Offline

    RingOfStorms

    What he means is that you don't need to cast something to something that you already know that it is. You know that "who" is a CraftPlayer, so why do you cast it to one, it is a bunch of wasted lines of code.

    So in other words, remove the casted part and simply invoke on "who".

    Here is an example if you want proof of this being real: http://ideone.com/LokkmI

    Reflection only looks at things as an object anyways, so casting is a pointless operation (unless you plan on returning it and using it outside of reflection), especially when you immediately cast it back to an Object again, doesn't make too much sense.

    Code:
        public int pingPlayer(Player who) {
            try {
                //Building the version of the server in such a form we can use it in NMS code.
                String bukkitversion = Bukkit.getServer().getClass().getPackage()
                        .getName().substring(23);
                //Getting craftplayer to cast later on
                Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit."
                        + bukkitversion + ".entity.CraftPlayer");
                //Invoking method getHandle() for the craftplayer we build above, and now we have a EntityPlayer
                Object handle = craftPlayer.getMethod("getHandle").invoke(who);
                //Getting field "ping" that holds player's ping obviously
                Integer ping = (Integer) handle.getClass().getDeclaredField("ping").get(handle);
                //Returning the ping
                return ping.intValue();
            } catch (ClassNotFoundException | IllegalAccessException
                    | IllegalArgumentException | InvocationTargetException
                    | NoSuchMethodException | SecurityException
                    | NoSuchFieldException e) {
                //Handle exceptions however you like, i chose to return value of -1; since player's ping can't be -1.
                return -1;
            }
        }
     
    DJSkepter likes this.
  7. Offline

    mine-care

    GrandmaJam and DJSkepter like this.
  8. Been developing for years yet I still love your tutorials @mine-care thanks!
     
    GrandmaJam likes this.
  9. Offline

    Eos

    @mine-care I'll definitely be using this in the long run, this will come in handy.
     
  10. Offline

    mine-care

    @Eos thanks mate! I need to update the reflection bit tho to make it efficient
     
  11. Offline

    Konato_K

    @mine-care Nice, but you should keep the version and the field in a fiel (lol) so you don't have to get them every time again, they won't change at runtime.
     
  12. Offline

    mine-care

    @Konato_K
    :- )
     
  13. @mine-care
    No need for using the Class.forName(), the Player#getClass() will always return CraftPlayer, if it doesn't it's player-made and using the CraftPlayer class won't work then too because it's not an instance of it :p.
     
  14. Offline

    mine-care

    @megamichiel
     
Thread Status:
Not open for further replies.

Share This Page