Client side and Server side cooldowns

Hi there,

Let’s say I have a system where the client clicks to shoot something.

I have a client side cooldown as follows:

local CanShoot = true

if CanShoot then
   CanShoot = false 

   --Fire Server here 

   wait(3)
   CanShoot = true
end

Then, on the server event, I have a server sided cooldown/check as follows:

Event.OnServerEvent:Connect(function()
    if PlayerTbl[plr.UserId].CanShoot then
         PlayerTbl[plr.UserId].CanShoot = false

         --Fire client and render the shot

         wait(2)
         PlayerTbl[plr.UserId].CanShoot = true
    end
end)
  • Now the problem with this is that since I am rendering the shot after the server check there might be delays due to latency. Is there a more efficient approach to this while keeping it unexploitable so they can’t spam click or remove the client sided cooldown?
  • Let’s say there is an exploiter who’s spamming :FireServer(). Will the server side check shown in the second code block prevent them from breaking something?

Thanks in advance to those who answer my questions :smiley:

Hm, it looks like you are getting CanShoot boolean from this table. Is PlayerTbl a replicated object between the client and server? [Assuming since CanShoot is also mentioned in the client script.] If it is, then this could be a weakness in the cooldown.

I am not sure what could make this more efficient, I do not have as much experience with shooter games and efficient remotes for action genres.

No it’s just a table on a server script so it’s not replicated anywhere.

Where is the CanShoot boolean changed in the server? How does it do this change and how does it know the player is in a cooldown?

If the server already stores the player’s debounce, then you don’t necessarily need a client-sided one unless you want one. Also, make sure to remove the cooldown table after the player leaves so it doesn’t take up space.

Also, if you want to sync it with the client, you can set a boolean value’s value since it automatically replicates.

Hope this helps! :smiley:

First question

Second Question, the process starts from firing a remote after clicking sooo. If the exploiter just wants to fire the event for fun it won’t do him any good so I wouldn’t care about that.

Mhm after the player leaves I set the PlayerTbl[Plr.UserId] to nil so there aren’t any memory leaks. I just have a client sided one so I only use the serversided one as a kind of “backup” and to stress the server less if you get what I mean.

My concern is mostly regarding the delays caused by the latency.

Ah okay. In that case, best bet is to use a BoolValue (so it auto-replicates), or to setup a replication system yourself. Either should do nicely.

Hope this helps! :smiley:

I don’t think it would fix the problem since you’re still involving a server check

Player Clicks > Fires Remote to Server > Check if everything is valid > Fire remote to client > render the shot

If there’s latency then there will be unpleasant delays between the player’s click and the shot.

Any sort of cooldown should be handled by the server, a localscript cooldown can easily be bypassed. Add a table and a debuff to each player, so by using your code it would look like this.

local DebuffTable = {}
Event.OnServerEvent:Connect(function(player)
    if not Debuftable[player] then -- if player isn't debuffed then continue
         table.insert(DebuffTable , player) -- add player to debuff

         -- do whatever you want the remote

         wait(2) -- THIS is where you handle the cooldown, so in this case 2 seconds
         DebuffTable[player] = nil -- removes player from debuff table
    end
end)

The only reason there should be a cool down on a client is to handle client cosmetic stuff like the gun shooting particles or whatever happens when you shoot this event, but it should never have any actual effect on the game.

Yes I already did what you’re saying as shown in my second code block but this doesn’t really answer my question.

Not necessarily. Since the BoolValue is only replicated when the server changes the value, you can use it to check on the client as well. Checking the BoolValue’s value would allow the server and client to be in sync, and you can add a check on the client so it only runs if the BoolValue’s value is false, so the cooldown would be universal. Setting the value on the server just ensures that the client and server are both “on the same page”.

Hope this helps! :smiley:

Don’t think you’re quite understanding what I am saying.

You’re right about saying that changes made on the boolean value by the server will replicate to the client. However any client side checks can still be bypassed by simply changing the boolvalue’s value on the client.

What I am trying to say is that if there’s high latency between a client and a server, then the client might take “long” to receive the response from the server and vice versa because of network & what you’re saying (If I am understanding correctly) doesn’t seem to affect or solve this.

I mean generally there would always be some form of latency. Also, exploiters can still manually fire the RemoteEvent, so really there is no solution to the client sided debounce part, since it’s easy for exploiters to bypass. Best bet is just to use a BoolValue so ROBLOX handles the replication, and just checking it on the client. Regardless though, exploiters would still be able to manually fire the event.

Hope this helps! :smiley:

Sorry didn’t get the question, what thunderbeast208 said is your best solution, there’s no way to avoid the latency between client and server. What are you trying to achieve on the client once they shoot the remote and the server receives it?