Solved Get player ping with reflection.

Discussion in 'Spigot Plugin Development' started by JoseGamer_PT, May 15, 2016.

  1. Hello spigot community, so i have this code:

    Code (Text):

        public static String pegarPing(Player p) {
            CraftPlayer p1 = (CraftPlayer) p;
            EntityPlayer p2 = p1.getHandle();
            return String.valueOf(p2.ping + " ms");
        }
     
    But the code needs:
    import org.bukkit.craftbukkit.v1_9_R1.entity.CraftPlayer;
    (Protocol)

    I need a version of ping with reflection!

    PS: I'm portuguese, sorry for my bad english :/

    Thanks for your time!
    - Jose
     
  2. Code (Java):
    public static String getServerVersion ()
    {
       return Bukkit.getServer().getClass().getPackage().getName().substring(23);
    }


    Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit." + getServerVersion() + ".entity.CraftPlayer");
    Method getHandle = craftPlayer.getMethod("getHandle");
    Object entityPlayer = getHandle.invoke(originalplayer);
    double /*replace with whatever the ping variable actually is*/ ping = (double) entityPlayer.getField("ping");
     
  3. Nope. Didn't work.
    http://prntscr.com/b4ann5
     
  4. Don't you need the Class instead of the Object? You can cast getField on a Class instance. You need to provide the field you want as well as the object you want to cast it on (As far as I recall)
     
  5. Well, if you read abit up on it before saying so you'd know.
    Add .getClass() right before .getField

    mhm
     
  6. Code (Text):
    public int getPing(Player p) {
            CraftPlayer cp = (CraftPlayer) p;
            EntityPlayer ep = cp.getHandle();
            return ep.ping;
        }
     
    • Optimistic Optimistic x 1
  7. That's not reflection. If the server version changes, the code would need to be updated to fit his needs, because Bukkit/Spigot change their package names every update to the protocol version.
     
  8. Sorry didn't notice the reflection part ._.
     
  9. That's the title of the thread! :p
     
  10. This may work.
    Code (Text):
    public int getPlayerPing(Player player) {
            try {
                int ping = 0;
                Class<?> craftPlayer = Class.forName("org.bukkit.craftbukkit." + getServerVersion() + ".entity.CraftPlayer");
                Object converted = craftPlayer.cast(player);
                Method handle = converted.getClass().getMethod("getHandle", new Class[0]);
                Object entityPlayer = handle.invoke(converted, new Object[0]);
                Field pingField = entityPlayer.getClass().getField("ping");
                ping = pingField.getInt(entityPlayer);
                return ping;
            } catch (Exception e) {
                e.printStackTrace();
                return 0;
            }
        }
     
        private String getServerVersion() {
            Pattern brand = Pattern.compile("(v|)[0-9][_.][0-9][_.][R0-9]*");
         
            String pkg = Bukkit.getServer().getClass().getPackage().getName();
            String version = pkg.substring(pkg.lastIndexOf('.') + 1);
            if (!brand.matcher(version).matches()) {
                version = "";
            }
         
            return version;
        }
     
    • Like Like x 1
    • Useful Useful x 1
  11. konsolas

    Supporter

    I have a lazily loaded system that works well without checking the server version:
    Code (Text):
    public class Ping {
        private static Method getHandleMethod;
        private static Field pingField;

        public static int getPing(Player player) {
            try {
                if (getHandleMethod == null) {
                    getHandleMethod = player.getClass().getDeclaredMethod("getHandle");
                    getHandleMethod.setAccessible(true);
                }
                Object entityPlayer = getHandleMethod.invoke(player);
                if (pingField == null) {
                    pingField = entityPlayer.getClass().getDeclaredField("ping");
                    pingField.setAccessible(true);
                }
                int ping = pingField.getInt(entityPlayer);

                return ping > 0 ? ping : 0;
            } catch (Exception e) {
                return 1;
            }
        }
    }
     
     
    • Useful Useful x 3
  12. SOLVED THANKS FOR ALL HELP!
     
  13. konsolas

    Supporter

    I mean, at least cache the reflection so it isn't extremely slow :)
     
  14. Thanks you 2 konsolas <3