Making exploiter-proof guns

I’m trying to solve the issue of client based hit detection on weapons (so that you get instant feedback) and doing server sided checks so that exploiters can’t abuse it. I tried to implement lag compensation, where you save the positions of all players and their ping and rewind time when they get a hit, then do a server sided raycast to check if the hit was valid. This works in studio with simulated latency within a margin of error of about 1 stud between where the player was, and where the hit registered. The problem is that when it’s on a server with real players, and fluctuating ping, the positions never seem to be completely accurate and can often be way off (10+ studs) from where the shot hit and the player was at the time of the shot based on the shooter’s ping. A solution would be to make it so shots are valid if they’re within 20 or so studs of the victim’s rewinded position, but that makes the script less reliable and less effective at stopping exploiters.

So, if anyone else has experience with this I would really appreciate some help. How do you handle hit detection in your games? What works best at both giving the shooter instant feedback when he fires his weapon, while also being exploiter proof so that clients can’t spam hit markers on players they never could have hit?

7 Likes

What I would do in this situation is check on the client if the bullet hit, then show the client that they did. Then, I would fire a remote event for the server to check if the bullet hit, and if it did, deal the actual damage.

2 Likes

That’s what I am doing, although the method doesn’t seem to be very accurate, due to (I think) fluctuating ping of the shooter making the ‘rewind’ less accurate in getting the actual time they fired the shot.

1 Like

It is the unfortunate truth that there will never be a way to truly fix latency issues. The most we can do is make it unexploitable / fair and try to hide it with some magic tricks.

Exploitability / Fairness

One of the most common tricks in the hackers book is to play with their network latency. To cut a long message short, I’ll say this: each player should be disadvantaged by only their own latency. Any damage or loss to players should not be dependent upon another player’s latency, or else a hacker can use this against other players. In your problem, this means that whatever logic decides if a hit took place or not cannot compensate by the latency of the person who shot. If so, then it is exploitable. I’d also add that this check cannot be done on the client shooting (for obvious reasons) or on the client being hit (an exploiter would never admit to being hit). That leaves that this check must be done on the server.

The server is also the most fair place to determine hits because its game world or normally between the game world of the attacker when they shot the bullet and the game world of the victim when they are hit. Each player is also only disadvantaged by their own latency. A hacker having high latency means that they must lead their shots more; a victim with high latency cannot pull a Neo, break all the known laws of physics, and dodge flying bullets.

A server can handle a couple bullets. If not, then you can apply some optimizations. Trying to pre-optimize in this case will lead to a bad design decision. The server can handle the cost of running this critical game logic, and it doesn’t need to be handed off to a client.

The Black Magic

It is unfortunate that players with more latency will see "rubber banding". If each client is in charge of their own position, this rubber banding is almost always twice as large. If the server is in charge then rubber banding is cut in half and it is more fair, but the person moving has to interpolate. I've written a lot about client interpolation, you can find all of it by searching "client interpolation" on my profile.

Each client can with its own latency extrapolate where players are going to actually be at a given moment. This provides a more accurate representation of the game world and reduces the problem of missing shots when it looks like they should have hit to moments when the victim had just moved and the server found out but the shooter hasn’t. There is no way to fix this without introducing exploits. The shooter must be disadvantaged by their latency or else you are giving them leeway they can use to their advantage. Likewise, a player will be hit when it looks like they shouldn’t have been when they had just moved but the server hasn’t found out yet. If you trust the client to tell you where they are, then they can pull a Neo at any time. In addition, the victim is being disadvantaged by their own latency to the server. Compensation will also give them leeway to exploit.

To sum it up, the best you can to is extrapolate the positions of other players and interpolate the client’s position. Running the checks on the server is the only fair place. Any other way is prone to exploitation.

12 Likes

If you handle the shot only on the server then there’s a delay when firing making the guns feel unresponsive and bad to use. This has been solved by Lag Compensation in other games to get both immediate client side feedback, and server checks for validity. It’s not natively supported by roblox though so you kinda have to hack it in like I did. My code works most of the time to a decent degree but has issues sometimes with the rewind time being off which leads to some inconsistencies.

2 Likes

Lag compensation is hackable for the reasons stated above. You cannot create a exploiter-proof gun with it because you are trusting the client to not manipulate its latency / timestamps. See this video demonstrating the power of exploiting lag compensation: https://www.youtube.com/watch?v=WVNxIUItQTk The only information about time the server can trust is when it received a message. Anything more is exploitable, including the time between when it sent a message and when it received it.

I only mentioned it in the post above because I’ve written a lot on the topic already, but what you need to make the guns feel responsive with an authoritative server is client interpolation instead of server interpolation. Decreasing the time between a shot and the animation / audio feels bad, but perhaps adjusting the bullet speed is better. Extrapolating the positions of other players brings the locations shot at and the actual locations hit even closer.

I think it was quite an accomplishment that you were able to setup lag compensation on a Roblox server, but was not designed for security. What I’m suggesting is like lag compensation on the client side before a bullet is shot. It’s kind of the inverse of what you’ve done. You should search on my profile page for the multiple articles I’ve written on this subject. I’ve posted lots of links to resources on them as well.

2 Likes

This is an issue with no easy solution.

You have to combine several tricks in order to make gameplay feel seamless and instant - but even then, there will be cases where it is too laggy to deal with. Also, exploiters are near impossible to deal with. You’ll have to enforce a maximum possible latency you will allow, and stick with it to reduce abuse (generally, however, there are more devastating client sided hacks that you should worry about first - aimbotting, increasing walkspeed, etc…)

Some techniques I have used in the past:

  • Slow down the bullet on the client that fired it, and speed it up on other clients. This will let you sync with server time, and the bullet should land at roughly the right time on server/client if you do some math to time it correctly.
  • Interpolate between known positions (basically your rewinding technique)
  • Keep generous hitboxes to help account for lag
  • Slight client-sided movement prediction (predict future position of other players based on current movedirection of the character)
  • Split visual effects and actual damage calculation. You can always render hit impacts on the client instantaneously, and let the server figure out whether it counts as a hit or not by itself. This lets you make it seem “instant”, but it can be sort of frustrating because it adds an element of uncertainty to each hit.

I wish roblox gave us more tools to handle this - Better server matchmaking controls would allow us to prioritize for ping over anything else, and reduce the average latency across all players. Also, being able to actually have access to the inbuilt latency measurement would be useful, instead of being forced to write our own.
I also like to establish a “range of accepted latency” when designing such systems - it lets you have a good benchmark for what you should consider to be “seamless”, and reduces vulnerabilities in lag compensation systems. I always try to design my systems to feel seamless up until ~200ms; Past that point I am willing to let a player’s experience degrade, as it is just too much latency to deal with.

5 Likes

Making exploiter proof guns can be quite daunting, but when it comes down to it, you should always try to manage most of this stuff on the server. It will not make much alot of difference to the performance of your game if the code is optimised well.

In my opinion, you should pass a ray calculated based on where the player shot, and from the mouse position (or the part the mouse clicked on) to the server, and the server should use that ray to tell whether a hit has been made, as well as checking where it came from and what it hit. If it’s hit, then damage of course. From there, we just send a signal to the client to “construct” a bullet that will act as the prop itself.

Things to keep in mind when checking stuff on the server

  • Whether the person has a gun equipped or not
  • Whether the direction of the player is pointing in a similar area
  • Range of the gun
  • Whether the part that the player clicked on is actually there, (and if there is, check if its a player or humanoid).
  • Shooting rate of the gun

Things to keep in mind on the client

  • Try and keep bullet rendering to a minimal. If the player is 300 studs away from the shooter, chances are you won’t need to render the bullet, so add a check to go along with that
  • You should try and keep the input the client has to a minimal, as that is the thing that exploiters can effect

Obviously, if you want to stick with a client based only system, thats fine, but know that you are opening up everyone to your code and the workings of it, making it a potential vulnerability for your game.

5 Likes

That’s more or less what I am doing, without movement prediction though

Thanks for the responses all, a lot to take in, and I appreciate the help