Local coin collection system

Hi there, I was trying to make a coin collection system on the client, so that each player has his own coin to collect without having other players stealing… My question is, how can you prevent exploiters from just collecting all the coins via script?
My initial idea was: Spawning the coin in a LocalScript, detecting the .Touched event in a LocalScript, and from there sending an event to the server for it to change money values and stuff like that, but using this method, can’t exploiters just open their booboo program and execute “collectEvent:FireServer(coin)”?

I hope i made this clear, Thanks!

3 Likes

you’re right, exploiters can and will do that, a solution that some games use and probably the best solution is to fire a event from the server to the client to spawn in a coin and pass a UUID with said coin, if a player touches that coin then the client will fire a even saying they touched the UUID linked with the coin, and the server will check if the UUID sent by the player is valid.

I explained it kinda poorly but hopefully you get the idea

1 Like

How would you make this work though?
Server:

game.Players.PlayerAdded:Connect(function(plr)
	
	while task.wait(.1) do
		spawnEvent:FireClient(plr, UUID) --UUID will be made out of random letters or numbers?
	end
end)

Client:

spawnEvent.OnClientEvent:Connect(function(UUID)
	--Spawn the part
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") then
			collectEvent:FireServer(UUID)
		end
	end)
end)

But then how would you check the UUID on the server?
Thanks for your solution though!

1 Like

Hello, I think I have got the solution:

Create the event for the coin collection and send an argument with some data, for example the player’s name, UserId, Nickname or any other type of data, for example true or "Auth"

This way, randomly firing the event by an exploit won’t work.

Client side:

local Player = game:GetService("Players").LocalPlayer
local Coin = game:GetService("Workspace").Coin

Coin.Touched:Connect(function()
        game:GetService("ReplicatedStorage").CoinCollected:FireServer(Player.UserId)
end)

Server side:

local ReplicatedStorage = game:GetService("ReplicatedStorage")

ReplicatedStorage.CoinCollected.OnServerEvent:Connect(function(Player, Auth)
        if Auth == Player.UserId then
                -- Code that gives you the coins
        else
                Player:Kick("Exploit detected") -- Player called the event without auth
        end
end)
2 Likes

might be kinda advanced for you idk how experienced you are though but here’s a relatively good solution

-- server
local function GenerateUUID()
	return game:GetService("HttpService"):GenerateGUID(false)..game:GetService("HttpService"):GenerateGUID(false)
end


game.Players.PlayerAdded:Connect(function(plr)
	local conns = {}
	local ValidUUIDS = {}
	local spawnEvent = nil -- spawn event
	
	table.insert(conns,spawnEvent.OnServerEvent:Connect(function(plrr,uid) -- we can also use the spawn event for getting the response
		if plrr == plr then
			if table.find(ValidUUIDS,uid) then
				table.remove(ValidUUIDS,table.find(ValidUUIDS,uid))
				-- give them their reward
				plrr.Data.Coins.Value += 1
			end
		end
	end))
	
	
	
	while true do
		task.wait(1)
		if not (plr and plr.Parent) then -- plr left
			for i, v in pairs(conns) do
				if v then v:Disconnect() end
			end
			break
		end
		
		local uuid = GenerateUUID()
		table.insert(ValidUUIDS,uuid)
		spawnEvent:FireClient(plr, uuid)
	end
end)
-- local script

spawnEvent.OnClientEvent:Connect(function(UUID)
	--Spawn the part
	part.Touched:Connect(function(hit)
		if hit.Parent:FindFirstChild("Humanoid") and hit.Parent == game.Players.LocalPlayer.Character then
			spawnEvent:FireServer(UUID)
		end
	end)
end)
3 Likes

Oooh, this makes sense, btw didn’t know you could mix tables and events like that, I’ll try this and let you know, thanks!

1 Like

The reason why this won’t avoid exploits is that the argument passed in the event is a static value that can be grabbed and put into the event’s arguments and fire the event, instead using a random value would be the case since the user doesn’t know the value

1 Like

@i_stabman’s solution sucks. It’s literally just a remotevent obfuscator which can be bypassed by just looking at the server return and using that to spam spawnevent :-1:

Why? When the client fires the event, the server checks if the UUIDs are matching, there’s no way for the user to spam the event, or am i wrong?

An exploiter could listen the FireClient and store the uuid to spam the spawnevent.

How can he store it if it’s on the server

1 Like

the problem is about the client firing the spawn event inf times whenever they want, my solution is to fix that problem, not make a perfect system that nobody can exploit, or prevent exploiters from instantly claiming any coin that spawns, like you said, maybe read the original post first?

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