Securing my Remote Events

Hey there, everyone. So, here’s the rundown. When the player presses CTRL, they kneel. I have a custom stamina and health regeneration system in place where if the player is kneeling, their stamina and health regeneration speed is increased. When the player stands back up, their regeneration speeds go back to normal.

This is all triggered when the player presses CTRL. A local script detects the player’s keypress with userInputService and then fires a serverEvent to increase or decrease the stamina by 1.5x. So, my question is: How can I prevent exploiters from firing the serverEvent from the client if the userInputService is only available in a local script?

Local Script

Button.InputBegan:Connect(function(Input)
	if Input.KeyCode == Enum.KeyCode.LeftControl then
		if not debounce then
			debounce = true
			CrouchedEvent:FireServer(true)
			Animate1 = Humanoid:LoadAnimation(Crouch)
			Animate1:Play()
			Humanoid.WalkSpeed = 0
		else
			CrouchedEvent:FireServer(false)
			Animate1:Stop()
			Humanoid.WalkSpeed = 16
			debounce = false
		end
	end
end)

Server Script (Event Handler)

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CrouchedEvent = ReplicatedStorage.Events:WaitForChild("CrouchedEvent")

local function updateStats(player, crouched)
	if crouched then
		player:WaitForChild("stats").regen.Value *= 1.5
		player:WaitForChild("stats").stamRegen.Value *= 1.5
	else
		player:WaitForChild("stats").regen.Value /= 1.5
		player:WaitForChild("stats").stamRegen.Value /= 1.5
	end
end

CrouchedEvent.OnServerEvent:Connect(updateStats)

To start, on the server side you can make a table to keep track of all the players that are crouching.

--ex:
local crouchingPlayers = {
    player1 = true,
    player2 = true,
    ...
}

So instead of the client telling the server true or false, just fire with no arguments. Check on the server if they are in the crouchingPlayers table; if they are remove them from the table and reset their speed/stamina. If they are not, add them to the table and set their speed/stamina.

You can also add a debounce on the server. You can keep track of when the player last fired the RemoteEvent and only allow change their stats every X seconds.

local crouchingPlayers = {
    player1 = {lastCrouch = os.time(), crouching = false},
    player2 = {lastCrouch = os.time(), crouching = true},
    ...
}
2 Likes

Adding a debounce would definitely help secure it. But if the event were fired (by, let’s say an exploiter), they would still be added to the table. And they would only need to fire the event once to be added to the table, increasing their stamina and health regeneration without ever actually kneeling. Removing the true and false arguments is a good idea, but ultimately, will that help secure the event?

I agree with the debounce part. A table that keeps track of players who recently fired the events would be helpful.

What keeps you from changing the walkspeed on the server so anyone who fires the remote can’t just fire it and keep their original walkspeed?

Also, you can use constant stamina values or booleans rather than multiplying it every single time the remote is fired

Here’s a bad example script to show you how you could implement the logic for this

local Stamina = Player:WaitForChild("stats"):WaitForChild("Stamina")

while task.wait() do
    Stamina.Value += stamRegen.Value * (Crouching and 1.5 or 1)
end
1 Like

Since the client can play any animation it wants and change its walkspeed, you need some kind of anti cheat.

If your goal is to have the player not be moving to have increased stat regeneration, then you can check the velocity and position of the HumanoidRootPart to see if they are actually staying still.

As for securing RemoteEvents, I generally like to have the client pass in as little information as possible through a RemoteEvent; not sure if it’s the best way of going about it but :man_shrugging:.

1 Like

I like this idea a lot. A really simple solution. If they were to fire the event, then they’d still technically be kneeling and would be unable to move.

I like this as well. But as @uwuCulturist said, an even simpler solution would be to just force the player to stop moving.

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.