I don’t understand what do you mean for the Key.
Yeah that works, but it still won’t stop the exploiter from figuring out the key. They can just rejoin constantly and keep trying till they get it.
The easiest preventative you can do is simply authenticating events, beyond that you cannot do much. To authenticate your just checking if the player satisfies the conditions to trigger the relevant event - this can span from checking if the player is in range to checking if their data allows it.
Simply adding wait() at the start will prevent your server from being crashed by an event as it then handles it when its ready to. You can also then check how many times they’ve requested it afterwards and then kick them based on this information.
The reason the chat events were so fatal was because at Roblox’s core they forgot to add in any preventatives (and so unless you manually added it you could do nothing).
Never rely on security through obscurity, you should be making sure that the server is able to check for legitimate serverevents/invokes
Actually yeah I don’t think a key will make your script secure, because you have to fire it from the client. An exploiter using remote spy, or some tool can figure out the parameters instantly.
Or use a ban script.
Also, I made a code that generates random things.
local Key
for i = 1,100 do
Key = string.char(math.random(104))
end
You don’t need to worry, what I do is check really good on the server side. Done, if they spam it really fast they will get a timeout from firing the remote event or function really fast. So just do strong checks on the server side. With that in mind you don’t need to worry. Never Kick Someone Instead you should punish them in another way. What I do, is I remove health from them. Or do you want to lose players?
A key? Since when did I mention a key…
Also, you shouldn’t do things like your example on the client as your basically trusting them to award themselves money every 15 seconds (which you shouldn’t do when the server could do it for you).
You can add tick() to tell if a player spams it too much.
local Remote = game.ReplicatedStorage.Event
local lastTick = {}
local TimeBetweenCash = 3
Remote.OnServerEvent:Connect(function(Player)
if lastTick[Player] then
if lastTick[Player] < tick() + TimeBetweenCash then
Player:Kick()
end
else
end
lastTick[Player] = tick()
end)
I have tested this method, in regards to crash defenses your server can actually crash before it has time to Kick the player - therefore its not a particularly good defense. Its also hard to apply context to these scenarios, as its very simple from your code to deduce that I can now award myself cash every 3.00000…1 seconds later which exploiters can easily catch onto.
Yeah, but what if you add your method like a wait() between the tick()
You could do that, but that wouldn’t solve his issue. Hence why I mentioned authentication as the best method if he has a reason it needs to be called from the client, although your method is a way of authenticating it isn’t really perfect whereas running checks can be more valuable.
You can’t really run checks for giving a player stats. The problem with that is that you fire it to add the cash. If he wants gaining cash to be undetectable he should make the whole script serversided, because then you can’t spam fire a remote to abuse gaining cash when it’s non existant.
But yeah for other Remotes it is useful to add checks, and if he already has but still wants more then I suggest my method it’s simple, and it helps prevent exploiters more than it already does by adding checks in your remotes.
Eh, you can use time stamps to authenticate if 15 seconds has passed - but then you’ll always have the issue of connection times. Sometimes as well you might find an occurrence when you need the client to run the authentication (such as they might need a specific client side properties in order to collect the money) although this is extremely rare.
You are right in saying putting it on the server is the best method.
Checking within the heartbeat if 15 seconds has elapsed as while
loops with wait() are not as accurate.
Yeah, you can also use heartbeat on the server it’s pretty simple. Also there’s other ways to give players cash if it has something to do with clicking you don’t have to make it completely client sided. You could use a tool, or even a script and a textbutton.
local Debounce = false
local TimeWait = 15
game:GetService("RunService").Heartbeat:Connect(function()
if Debounce then return end
Debounce = true
-- loop through players giving them cash
wait(TimeWait)
Debounce = false
end)
No!!! You don’t want to use wait() at all as its really unreliable when the server is lagging - it can also unnecessarily wait - basically 15 seconds wouldn’t be 15 seconds.
This method is the closest way of getting 15 seconds (it would be out by about .00014 or something ridiculously small).
local start = tick()
local delta = 15
game:GetService("RunService").Heartbeat:Connect(function()
if tick() - start >= delta then
start = tick()
-- award money
end
end)
That function also takes advantage of every heartbeat.
Well yeah, but does it really matter if it’s .00014 seconds below the specific time? By unreliable you mean when you get a lag spike, the cash will delay before firing to the client telling you your cash? Because that doesn’t really sound like a BIG deal, and lagging is unreliable with server side either way you can’t really change that.
I meant 0.00014 above.
The heartbeat is a pretty reliable source, and your delay can be for various reasons such as the server is dedicating its time to a more heavy process which is why wait() isn’t always the best to use especially when you want a specific wait time such as 15 seconds.
Also, lagging on the server can be reduced by creating better optimised and less heavy code by using more efficient methods and taking advantage of anything you use to its max.
The method you used for the heartbeat really just negates the need for it, whereas the method I provided takes advantage of it fully. Your method only does something meaningful with the heartbeat probably 1/150th of the time due to debounce whereas mine is making use of it by just checking if the time has elapsed by that by the frame (which is the closest measurement to that second we can get without massive complexities).
just use task.wait which relies on the same method