Scripting Helpers is winding down operations and is now read-only. More info→
Ad
Log in to vote
0

how to prevent remotes from being spammed using the server-side script?

Asked by
Elixcore 1337 Moderation Voter
6 years ago
Edited 6 years ago

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?

2 answers

Log in to vote
3
Answered by 6 years ago
Edited 6 years ago

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.

Ad
Log in to vote
2
Answered by
amanda 1059 Moderation Voter
6 years ago
Edited 6 years ago

For this, you need a server-side debounce.

There are two approaches to this:

  1. 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)
    
  2. 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)
    

Answer this question