PlayerPing - Get client ping times on the Server

PingTimes

by boatbomber

I needed ping times to try and negate the impact of network delay in a game I was working on, so I wrote a module that gets it!


Usage:

My goal was to make it as simple and fool-proof as possible to use. Simply require the module from both Client and Server.
(Note: The client’s require will return nil, but it’s needed to initialize the client ping responder.)

To get the ping time of a player, you simply index the module with that Player. This can only be done on the Server.

PingTimes[Player] returns a number that represents network round trip time measured in seconds.

local PingTimes = require(ReplicatedStorage.PingTimes)

local PlayerPing = PingTimes[Player]

The module is behind a proxy table with a metatable that prevents you from breaking the module’s internals, so attempting to manually set PingTimes[Player] will warn and discard your change. Attempting to index with something other than a Player Instance will return nil.


Security:

It is important that exploiter can’t fire the remotes of this to change their ping values, so I used the GUID Validation method that was recommended by @berezaa in this thread. The ping must be returned with the correct GUID or it is ignored. Each ping attempt generates a new GUID, so there is no way for the exploiter to know the validation value ahead of time.

To prevent timeout, I make use of the wonderful Postie module by @BenSBk. Major shoutout to that, it made this way easier for me.


Notes:

When a player first joins the game, their ping time might not be accurate yet. Give it a moment so they can establish a stable connection first.

If, for some reason, it cannot get their ping, it defaults to 100 milliseconds since that’s a general average afaik.

It refreshes ping times every 3 seconds, so the data will be reasonably up-to-date without applying undue strain to your network and bandwidth. This is changeable via the UPDATE_FREQUENCY variable in the module, if you desire.


Test Place:


Module:

Library:

GitHub:




Enjoying my work? I love to create and share with the community, for free.

If you’d like to help fund my work, consider sponsoring me on GitHub or donating on BuyMeACoffee!

129 Likes

Wow, just thanks. I really need this for my game. I will search and watch how this exactly works. Its just… to beautifull to be true. Thanks boatbomber, it‘s a to-watch module!

1 Like

Il check it out later it looks pretty cool.

If you press Shift+F3, is your ping listed there as 25 or 250?

Hm. It is listed as around 250 in performance stats. That’s strange. Sorry for the false report.

1 Like

I guess the issue is with your ISP, not my module :laughing:

Thanks for reporting though, I appreciate the thought. Better safe than sorry!

1 Like

Ok, sorry if I might be sound dumb, but how it works? I can‘t understand what berezaa said and if you are using the same method or not.

(P.S.: Yes, this sound really dumb, sorry for this question)

Sure, I’m happy that you asked. Here to help.

Essentially, the server invokes the client and measures how long it takes to respond. To make sure that the client response isn’t being faked/manipulated/corrupted, the server sends along a random piece of data with the request and the client must send that data back. If they don’t send back that exact data, we know that some funny business is going on and disregard the request.

(PS: It’s never dumb to ask a question! It would be silly to need to know something but never ask or learn!)

11 Likes

Wow, thanks for helping!

This sound really good. I am asking if it is possible to applicate this security system to other thing (Code verification, idk system like this)

Can this essentially detect that an exploit is happening to which our code can carry out the kick script?

If you think you’re question is dumb, ask it anyways! It’ll allow you teach yourself new information!

Nope! That would be a bad plan. A player with a poor connection might be kicked unfairly because of corrupted data, packet loss, or any number of weird things. Networks aren’t magical, so we can’t rely on them being perfect!

1 Like

This system is designed to validate responses. If you can think of another use case, great! But it’s not made to confirm that something has “worked”.

1 Like

But with this line you’ve stated, can I still detect whether it’s being exploited?

Sorry if I missed something, but what does it say the ping is when it times out? Does it do the 100 ms for that (even though it’s probably higher than that)?

2 Likes

Perhaps I should have chosen my words more carefully. Funny business could mean that their network is screwing up!

3 Likes

Ahhhh thank you for the clarification! I thought when you said “funny business” you meant exploiting, sorry about that! Thank you for creating this, I’ll take a look at it and hopefully implement it into my future game!

1 Like

If it times out, it discards that request attempt. If the ping request was successful before, it’ll remain at that value. If it was never successful, it stays at the default value.

2 Likes

Oh, so this is how the developers of New User Machine get everyone’s ping time and show it over their nametag.

How does making the client return a GUID prevent exploiters from spoofing it? Is there some reason why exploiters can’t just return the GUID passed by the remote function?

It prevents pre-emptive spoofing, since they can’t know the GUID ahead of time. Therefore, they cannot lower their ping. However, they can artificially raise their ping, unfortunately. There really isn’t a good way to prevent this. How can you distinguish an intentionally bad ping from a real bad ping? To the server, they’re identical.

3 Likes