so if I have a remote called print and if you execute it from the localscript it prints out whatever the argument is, how would I make the remote usable only once every second using the server script?
how to prevent remotes from being spammed using the server-side script?
2 answers
Keep track of the last moment the remote was fired on the server. Compare the last time a specific client fired the server event, and if it's past or equal to some cooldown, allow the code to execute.
local PlayerService = game:GetService("Players")
local REMOTE_COOLDOWN = 1
local ClientEventHistory = {}
remote.OnServerEvent:Connect(function(client, ...)
local lastFiredFromClient = ClientEventHistory[client]
local now = tick()
if now - lastFiredFromClient >= eventCooldown then
print(...) -- print args or do code
ClientEventHistory[client] = now
end
end)
Players.PlayerAdded:Connect(function(player)
ClientEventHistory[player] = 0
end)
Players.PlayerRemoving(function(player)
ClientEventHistory[player] = nil
end)
You can handle this procedure on the client as well. In fact, depending on your circumstance, I may recommend doing this on the client instead. Handling this on the server is more of a safety net than anything else. The con of explicitly handling this on the client, is of course, the client can be exploited to bypass the cooldown by just firing the remote event.
Conclusion
Do this on the client if you expect this remote to be fired rapidly so that you're not using bandwidth by sending so many requests (although, if you're firing a remote so rapidly that you need to set a cooldown in place, there is probably a bigger design flaw at hand). Do this on the server if you're worried that an exploiter may be firing a remote within an interval that it's not supposed to be fired.
For this, you need a server-side debounce.
There are two approaches to this:
Global Debounce
- Doing this will make it so the entire RE is debounced.
- It is achieved using a variable that you toggle to true and false within your server script
Server:
local rep = game:GetService("ReplicatedStorage") local printRE = rep:WaitForChild("PrintRE") local debounce printRE.OnServerEvent:Connect(function(player, msg) if not debounce then debounce = true print("SERVER: "..msg) wait(1) debounce = false else print("SERVER DEBOUNCE") end end)Player Debounce
- Doing this will make it so each player has their own server-side debounce, preventing individual spam, but not holding others up who use the RE in moderation.
- It is achieved by using a table to hold bools with keys for each player Server:
local rep = game:GetService("ReplicatedStorage") local printRE = rep:WaitForChild("PrintRE") local debounce = {} printRE.OnServerEvent:Connect(function(player, msg) local name = player.Name if not debounce[name] then debounce[name] = true print(name..": "..msg) wait(1) debounce[name] = false else print(name.." has been debounced, please wait a second and try again.") end end) game:GetService("Players").PlayerRemoving:Connect(function(player) debounce[player.Name] = nil end)
This discussion is preserved as it was. New answers, comments, and votes are closed.
