Secure Advanced Leveling system

Hello fellow developers,

I’ve been working on a project, and i try to create a exp system. But i have multiple stats that you can individually increase. I have though about it and i have no idea how i could make this secure.

The stats are: (every stat has its own exp)

Speed;
Inteligence;
Power;
stability;
determination;

So i need to find a way, to give people individually exp, without hackers being able to change it.

How can i make this secure? Like do i need to make individual events to give them exp, and should i create this client sided (clinet sends info to server), or create the exp and datasavingscript in a single script.

For example, if i want people to get more speed if they walk/run. Can i do things like this serversided?

If you still don’t understand what i mean, i just want to create a secure exp system where you can get exp on different stats, and get exp on different ways like walking, running, traing, etc…

I need to go somewhere so i might not react today.

2 Likes

Yes, Clients to Server events are very secure and should be use for anything like or similar to saving data.

Change: NO THEY ARE NOT!

1 Like

Maybe make it complicated but only to others, and a much quicker client-server, server-client? don’t just use simple changes, make sure they are full or else it would probably be very easy to change.

1 Like

just have clients request doing their move to give them exp, have the server verify the amount and have a serverside debounce so they can’t spam the remote every 1.534 milliseconds

2 Likes

As long as you change, and verify the values on the server, hackers can’t affect anything with the server recognizing it, therefore it being as they never changed it.

1 Like

just handle most of it on the server

2 Likes

I believe you can use RemoteEvent but this time with signals, I think signal can help securing your things.

I have made some steps but i don’t know if it will be effective.

The first step is to randomize something, or you could use HttpService GenerateGUID ONCE from the server side.

The second step is to create a string value in replicated storage and attach your randomized thing or generate guid to the string value from the server side so that the code thing can be received by the client side.

The third step is to get the String Value in the Replicated Storage from Client Sided once, and Server Sided also needs to get the String Value for the Remote Event Signal, and Server Sided SHOULD delete the String Value in Replicated Storage for probably a second, so it wouldn’t be nil.

For the next step, you can simply do the remote event now!

If my explanation confuses you, there’s a code below this message but I don’t know if it will work since I’m using a phone right now. I hope you’ll take this code as an example.

--ServerScript
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("ExampleEvent")
local ReceivedCode

local HttpService = game:GetService("HttpService")

if not ReplicatedStorage:FindFirstChild("TemporaryCode") then
local StringValue = Instance.new("StringValue")
StringValue.Parent = ReplicatedStorage
StringValue.Value = HttpService:GenerateGUID(true)
StringValue.Name = "TemporaryCode"
end
if not ReplicatedStorage:FindFirstChild("ExampleEvent") then
local RemoteEventInstance = Instance.new("RemoteEvent")
RemoteEventInstance.Name = "ExampleEvent"
RemoteEventInstance.Parent = ReplicatedStorage
end

task.wait(1)
if ReplicatedStorage:FindFirstChild("TemporaryCode") then
ReceivedCode = ReplicatedStorage.TemporaryCode.Value -- Receives the string value
print("Received the code!")
task.wait(1) 
print("Deleted")
ReplicatedStorage.TemporaryCode:Destroy() -- Delete the string value so those exploiters wouldn't receive the code.
end

RemoteEvent.OnServerEvent:Connect(function(Player, SignalSecure)
if SignalSecure == ReceivedCode then
print("It did work")
end
end)

-- Local Script

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local RemoteEvent = ReplicatedStorage:WaitForChild("ExampleEvent")
local ReceiveCode
local Player = game:GetService("Players")
local LocalPlayer = Player.LocalPlayer

task.wait(1)
if ReplicatedStorage:FindFirstChild("TemporaryCode") then
ReceiveCode = ReplicatedStorage.TemporaryCode.Value
end

RemoteEvent:FireServer(LocalPlayer, ReceiveCode) -- bring localplayer and ReceivedCode from replicatedstorage

-- This script i made was in rush and coded in phone i'm not very sure if it will work but it's better to take it as an example or test it.
1 Like

But is this secure? Can’t hackers see this value? They could probably create a script that litterly does the same. Does this 100% work?

Do you know how i can achieve this?

Could you give me a better example?

Hackers can see the value, but if they change it it would not get replicated to the server, so if you add to the stats via a server script, hackers can’t cheat.

Oh, i have all the values in serverscriptservice in a table. I did this so that hackers can’t see values.

1 Like

Use remote events for this. When something happens on the client (for example they jump or move) fire a remote event, validate that they actually did the action, then add to the stat (in the server)

This could be possible. I will try this. (I am on phone rn). So create events that see what the userimputs, and give them exp coresponding to what a player did?

Yes, the most important is that you have checks to make sure the client didn’t hack to fire the remote event, so validate the input on the server aswell and if it’s ok, then add the exp (on the server)

I am confident that it will be secure, because the value will be deleted so that the hackers wouldn’t receive the string value code.

But they could create a script that gets the value right?

I think they can’t get the string value because it will be deleted. If they attempt to get the string value in replicated storage, it will return nil for them because it’s been deleted.

It seems that my script i made on phone didn’t work, I have made another one for this but i don’t think it’s effective.

I will just remind you, this is only an example and it works perfectly.

local RemoteEvent
local ReceiveCode
local Player : Players = game:GetService("Players")
local LocalPlayer = Player.LocalPlayer
local Creator = game.CreatorId

local ReceiveTheCode = function(NameOfCode)
	local GetCode = ReplicatedStorage:FindFirstChild(NameOfCode)
	if GetCode then
		return (GetCode.Value)
	end
end

if Player:GetUserIdFromNameAsync(LocalPlayer.UserId) == Creator then
	ReceiveCode = ReceiveTheCode("TemporaryCode")
end

if ReceiveCode ~= nil then
	ReplicatedStorage:WaitForChild("ExampleEvent"):FireServer(ReceiveCode)
end


-- LOCAL SCRIPT

local ReplicatedStorage = game:GetService("ReplicatedStorage")
local ReceivedCode
local RemoteEvent = ReplicatedStorage:FindFirstChild("ExampleEvent")

local HttpService = game:GetService("HttpService")

game:GetService("Players").PlayerAdded:Connect(function(plr)
if not ReplicatedStorage:FindFirstChild("TemporaryCode") and (game:GetService("Players"):GetNameFromUserIdAsync(plr.UserId) == game.CreatorId) then
	local StringValue = Instance.new("StringValue")
	StringValue.Parent = ReplicatedStorage
	StringValue.Value = HttpService:GenerateGUID(true)
	StringValue.Name = "TemporaryCode" -- CODE
	ReceivedCode = StringValue.Value
	end
	if ReplicatedStorage:FindFirstChild("TemporaryCode") then
		task.wait(3)
		print("Deleted.")
		ReplicatedStorage.TemporaryCode:Destroy()
	end
end)

if not ReplicatedStorage:FindFirstChild("ExampleEvent") then
	local RemoteEventInstance = Instance.new("RemoteEvent")
	RemoteEventInstance.Parent = ReplicatedStorage
	RemoteEventInstance.Name = "ExampleEvent"
	if RemoteEvent == nil then
		RemoteEvent = RemoteEventInstance
	end
end

RemoteEvent.OnServerEvent:Connect(function(Player : Player, Code : string)
	print(ReceivedCode, Code)
	if ReceivedCode == Code then
		print("The event was fired and the code matches!")
	else
		print("Nope kick them it doesn't match")
		Player:Kick("No you can't do that.")
	end
end)

- SERVER SCRIPT

Thanks, but if you create anew value, they can get it right? So if you wait 3 seconds, they have 3 seconds to get the value before its deleted right?