Prevent Exploiters With Remote Events

The Problem
Hi there! I have a problem, a lot of exploiters can exploit my game easilly because of remote events.
I’m using a localscript to collect coins and that localscript use a remote event to let a server script gives the player money. I heard that using remote events is not reccomended for sending important things such as money, but I don’t know another way, because my script to collect have to be a local script, because the coins the player does collect need to disappear for the player that collects it only and not for the other players. This are the scripts I’m using:

LocalScript (StarterCharacterScripts)

    script.Parent:WaitForChild("Humanoid").Touched:connect(function(collectedCoin, playerCollected)
    	if collectedCoin:FindFirstChild("Lettuce") then
    	     local player = game.Players:GetPlayerFromCharacter(playerCollected.Parent)
    	     if collectedCoin.Transparency == 0 then
    			collectedCoin.Transparency = 1
    			game.ReplicatedStorage.LettuceTouched:FireServer(10)
    		    player.PlayerGui.CollectSound:Play()
    			wait(3)
    			collectedCoin.Transparency = 0
    	    end
    	end
    end)
5 Likes

Sorry, I typed enter on accident, I wasn’t done typing yet.

You can just use the Local code inside of a script, and remove the :FireServer() line, so there will be no way to exploit the system. You could also for easier implementation, hook the coins up to a for loop, then bind each coin to a touched event like the Client code.

An example of the loop would be:

local CoinFolder = workspace:FindFirstChild("Coins")

for i, v in ipairs(CoinFolder:GetChildren()) do
    if v:IsA("BasePart") then -- Checks to see if the child is a valid base part
       v.Touched:Connect(function(Hit)
           -- Do leaderstats and coin visibility and other things
       end)
    end
end
1 Like

You can put a script inside the part and then fire a remote to the client which makes it invisible and such

1 Like

I can’t really get into many details as I don’t really know much about this.

But I know that you can try adding scripts into folders where you store your coin, etc. if you have any because it’ll help since exploiters won’t be able to fire remote events that give money.

You can also try implementing checks into the remote events as well. Your script just has :FireServer(10), using stuff such as obfuscation methods or any sort of check would help in stopping beginner exploiters with these.

Generally using FireServer to give money though, is not really the best method as you stated.

Hope this helps you!

Edit: something that you can think about whenever developing a game is that you shouldn’t let the client handle any sorts of important functions that you might need. You’re better off using server-sided scripts

1 Like

Yes, but I want that the coins only dissapear for the client who touched the part only, not for other people. And I don’t want a localscript give coins.

As I think someone suggested, you can use a remote event and fire to their client from the server, this will allow you to effect them only and to have the remote safe, as it will only be fired to the correct player and it won’t effect game-play since it doesn’t touch the leaderstats.

Please keep in mind that you should always change / set data on the serevr.

1 Like

I don’t totally get how I would do that, because then the local script do need to give coins?

You basically will handle the touch events on the server and the addition of their currency, then fire the remote with the client that has touched the coin. Use a LocalScript to handle the OnClientEvent that will be received when the remote is fired. The local script will just change the transparency of the coin that was sent inside of the parameters of the event.

ServerScript Example:

local Event = -- Define Event
local CoinFolder = workspace:FindFirstChild("Coins")

for i, v in ipairs(CoinFolder:GetChildren()) do
    if v:IsA("BasePart") then -- Checks to see if the child is a valid base part
       v.Touched:Connect(function(Hit)
           local Player = game:GetService("Players"):GetPlayerFromCharacter(Hit.Parent)
           -- Do leaderstats and coin visibility and other things
           Event:FireClient(Player,v) -- Send the player to be fired, and v which is the coin object
       end)
    end
end

LocalScript Example:

local Event = -- Define Event

Event.OnClientEvent:Connect(function( CoinObject ) -- CoinObject is the coin part that was supplied
  CoinObject.Transparency = 1
end)
2 Likes

@desinied basically meant for you to use a server-script to change your money value when the coin has been touched. However, in the same function, you can use FireClient to change the transparency of the coin.

I’m gonna use @desinied’s idea to express what I mean in the script ( credits go to him )

local coinFolder = workspace:FindFirstChild("Coins")

for _,v in pairs(coinFolder:GetChildren()) do
    if v:IsA("BasePart") then
        v.Touched:connect(function(hit)
            -- Do the coin value change
            -- get player using function
            test:FireClient(player v)
        end)
    end
end

Edit: ah @desinied got to it before me. gg hahahhaha

1 Like

Yes, I know that, but I mean: How does it check if the player already collected the coin? Because if it’s local the serverscript doesn’t detect that, right?

If what you mean is that the coin can still be collected after transparency is changed then you can just do :Destroy() on the coin, that way it’ll destroy it for the client and other players will still see it?

I’m not so sure if that’s what you mean though. Elaborate if you can.

I actually mean to check if it’s already collected. So if the coin already has been collected, you need to wait until it’s visible again and then you can collect it.

If they are created on the server, you could use .Touched and FireClient to remove the coin on the client’s screen and then add them to a table to prevent them from collecting it again

Ah okay so try using a variable in the localscript which checks if the coin is touched or not. You can simply do coinTouched = false or coinTouched = true and then add a wait() for it to set back into it’s normal transparency so it can be touched again.

edit: make sure you set the variables and everything into the localscript so that other players have the same effect as well. If you add a variable and the debounce to the serverscript then it’ll affect every player instead of just the client.

Yes, but then 1. it would be for all coins. 2. How would I do that? Because then it needs to check in the localscript and how would the serverscript know when that variable is true or false?

Have a table where the keys are players and the value is the list of coins that player has collected and each time a player collects a coin check if the coin is already collected if not add thet coin to the collected table

or have a table where the keys are the coins and the values are the list of players

  1. Do the coinTouched variable in a local script.
  2. Use something like this:
local Coin = --define coin
Coin.Touched:Connect(function()
      CoinTouched = true
end)

if Coin.Tocuhed == true then
Coin.CanCollide = false
Coin.Transparency = 1
end

At this point just try adding the coins into a table using table.insert(coinTable, coins) and then using a for loop to get each coin that was touched and then set it from there.

edit: the method I probably told u at first was better though cause you make it check for the coin touched in the first place so it’ll only be for the coin touched. And the server doesn’t need to know because the part won’t be touchable if the parts CanCollide is false. Another thing you can do is just get a StringValue but that’ll be very easy to exploit and get past.

The .Touched event still fires even if the CanCollide property is set to false