Any way to prevent ammo exploits?

So for my weapons, i’ve been using a local variable to deal with ammo, which works in a way. However im pretty sure an exploiter can easily manipulate that variable to whatever value they want. I thought about making the whole ammo thing server-sided but that would be extremely janky for the gun if the player has high ping. So is there any way to somehow prevent or atleast make it harder for an exploiter to manipulate the ammo value for a weapon?

What I’ve been using:

local ammo = 0

function BreakWeapon()
    --Unequips the weapon
end

function Equipped()
    ammo = Stats.StartingAmmo
end

function FireBullet()
    ammo = ammo - 1
    if ammo <= 0 then BreakWeapon() end
end

What you stated originally is the best course of action, make it server sided. It’s a full proof way of making it so that ammo can’t be manipulated by an exploiter, the only way they could do it is if you had a networking issue.

I’d like to note, assuming you handle hit detection, and a variety of other things already on the server; which you should. Then handling ammo would not be a problem either. Even shooting has to be replicated to the server, so high latency with ammo will affect a variety of other things, so I wouldn’t worry about latency.

For me personally, I would just have the ammo count and reload time on the server, and just have the client “mimic” those values so that the numbers on their screen isn’t lagging. This way, even if the player changes the ammo into being say unlimited on the client, the server will know that they do not have ammo, so they would just be wasting their time trying to manipulate the code. Edits - so many typos, lol.

1 Like

This will still be affected by high latency.

You can track the amount of ammo both in server and client.
Let the client request fire bullet via RemoteEvent and reduce the amount of ammo client-side.
Server should get those requests and do the same thing, accepting requests only if amount of ammo is not below zero.

I think his point is that it’s server authoritative while still having fast feedback on the client so it doesn’t need to wait the round trip of your ping before decrementing the local ammo counter.

2 Likes

The solution is simple, do not give the client access to change the ammo in the first place, make it so the server manages these kind of stuff so that way you prevent things like this from happening in the future, only keep the visual work on the client so you remove some strain off of the server. :slightly_smiling_face:

2 Likes

I was thinking of creating a global variable _G as the ammo on the server and detect changes if the value of the ammo goes too high, or changed. Never trust the client, if the player has high ping, you can kick them for high ping, simple or make them wait until their ping is good. The only possible solution I can think of is do the whole ammo thing on the server, it will be janky but atleast not exploitable.

Also, use local functions.

I’m pretty sure that it’s better to use ModuleScripts than _G, ModuleScripts do the same things but better.

Everything should be server sided so that the client can’t get to it and change things at their will.

1 Like

If you don’t want to change this to be server sided you could check ammo every so often to ensure that it is behaving normally, so you want to check it is decreasing and doesn’t exceed the max ammo limit.
This however wouldn’t be as efficient as making it server sided

The rule of thumb for dealing with data is never trust the client, the client is always an exploiter. Consider anything that the client tells you as possibly tainted and always subject it to some form of testing. Under your current system, you can’t do that. You’re trusting the client with their own ammo count which allows modified data through. The only solution to this would be to give the server control of the ammo count.

And in the future, whenever you are receiving data from the client, pretend you’re an exploiter and ask yourself “how could I take advantage of this system?” If you give any answer to that question other than “I couldn’t” then you’ve written insecure code.