That code was a little rushed example to Steve_Speedy. The code that i have mentioned about a shop you made it, and it’s similar to my game, and i would like to know how do i fix it…
They can hack values that will be used by client. If they change server value. Server will denied this changes.
It is one hundred percent impossible for an exploiter to modify server sided code because the client can’t access it. This means any value or script on the server is safe from exploiters and in your case 'hackers`.
However anything placed on the client is vulnerable to exploits because it is on the clients machine. This means any value or script placed on the client can be modified and changed by exploiters.
What is the server used for
The server is the authority in your game because it can’t be exploited meaning anything the sever does and says is correct. This is why you should always do your checks, called sanity checks, on the server because you know they are always going to be correct. These checks should be performed whenever the client sends information to the sever because it could have been tampered with. These checks could be as simple as checking if the player have enough currency to by an item.
The server should also be responsible for anything important in your game like data saving because the server is always correct in what it does. Lets say you are making a shop then all the data changes and validation should be done on the server. You shouldn’t be doing any of the shop interface changes on the server because it is a waste of resources.
What is the client used for
Remember anything on the client can be exploited and modified so you shouldn’t be placing anything important there. You have probably heard people throw around the term, “never trust the client.” Well this means anything the client does can’t be trusted and should always assume any data sent from the client has been tampered with. This is why whenever data is sent from the client to the server it is always checked by the server.
The client should be responsible for any input, interface and any local changes you want to make. If any of these things are being ran from the server it would be a waste of server resources that would be better spend on other things. You shouldn’t have to worry about any of these things being exploited because if an exploiter does exploit them they wont gain anything. This is because when it is time for the client to send data to the server you will have the correct server sided checks in place. You also wont have any of the important parts of the system on the client.
Any changes the client makes wont be replicated to the sever because of filtering enabled. Lets say an exploiter removes everything in workspace then that change wont be replicated to the server and any other client. The only way to do client and server communication is through RemoteEvents and RemoteFunctions.
You should mark a post as a solution because it looks like your original issue has been solved by some previous posts. If you want help with another issue you should create a new topic.
Well, thanks for this info!
The part that i didn’t understand is the “Sanity Checks”, can you show me a code example of that?
Sanity checks are server sided checks that you put in place to check something. Lets say a player wants to buy and item and they click the purchase button on a GUI. You would then use a RemoteEvent to tell the server a player wants to purchase the product. Before the server initiates the purchase you should perform some checks called sanity checks. These checks could be checking if the player has enough money or if the player is even allowed to purchase that product.
Here is my best attempt at an example:
local PlayerData = { -- An example of the players data
["waterrunner"] = {
Money = 100;
Items = {}
}
}
local Items = { -- Table of all the shop items
["Sword"] = {
Price = 20
}
}
local function Purchase(Player, Product)
if Items[Product] and PlayerData[Player.Name].Money >= Items[Product].Price then -- This is the sanity checks
PlayerData[Player.Name].Money = PlayerData[Player.Name].Money - Items[Product].Price -- Removes the money from the player
table.insert(PlayerData[Player.Name].Items, Product) -- Gives the player the product
end
end
game:GetService("ReplicatedStorage").Events.Purchase.OnServerEvent:Connect(Purchase)
So this script is in the part you click which is a part of the GAME (server) not part of the player and not in startup folders, and not in the replicated folders (Client accessible) not sure about lighting:
local Part = script.Parent
local Players = game:GetService("Players") -- to gather player information IF needed. Best to have it.
local ServerSideInfo = game.ServerStorage.PlayerVariables --sets up the location of all the player info inside the SERVER Storage.
local openEvent = Instance.new("RemoteEvent")
openEvent.Parent = game.ReplicatedStorage
openEvent.Name = "openEvent" -- all this sets up at the like phone line to the player.
local noAffordEvent = Instance.new("RemoteEvent")
noAffordEvent.Parent = game.ReplicatedStorage
noAffordEvent.Name = "noAffordEvent" -- all this sets up at the like phone line to the player.
local PartID = "Sword"
local ClickDetector = Instance.new("ClickDetector")
ClickDetector.Parent = Part
ClickDetector.MaxActivationDistance = 20 -- sets up the click detector in the part.
ClickDetector.MouseClick:Connect(function(Player)
print("Player want open the gui")
if Player = ServerSideInfo.Player1Name.Value and ServerSideInfo.Player1.Coins.Value >= 100 then
openEvent:FireClient(Player, Coin, PartID) --send the messages to PLAYER, and the Message which is Coins.value.
ServerSideInfo.Player1.Coins.Value = ServerSideInfo.Player1.Coins.Value - 100
else
noAffordEvent:FireClient(Player, ServerSideInfo.Player1.Coins.Value) --send the messages to PLAYER, and the
end) --don't forget to close the function.
-------------------
In the StarterGui.OpenAffordGui.Frame that's copied into the player have this code. Make sure it's a LOCAL script.
----------------
local Frame = script.Parent
local Players = game:GetService("Players")
local ReplicatedStorage = game:GetService("ReplicatedStorage")
local CantAffordEvent = ReplicatedStorage:WaitForChild("CantAffordEvent")--setup client listen
Frame.Position = UDim2.new(0.5, 0, 0, -300) --Start Offscreen
local function onAffordFired(Coin, PartID) --brings up the gui, and gets the Coin message.
Frame:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), nil, nil, 0.25, false)
MyCoin = Coin
Players.LocalPlayer.leaderstats.Coin.Value = Coin -- Player gets told how much money he has.
if PartID = "Sword"
Frame.SwordBought:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), nil, nil, 0.25, false) --shows that the item was bought
end
if PartID = "Bow"
Frame.BowBought:TweenPosition(UDim2.new(0.5, 0, 0.5, 0), nil, nil, 0.25, false) --shows that the item was bought
end
wait(3)
Frame.Position = UDim2.new(0.5, 0, 0, -300) -- Hide the gui.
end
Now if you have a clickable button in the Gui, like “Upgrade” the Upgradebutton can then FireServer with an Upgrade remote event. The Server Script (Probably in ServerScriptService) then does all the work.
local function onUpgradeEvent(Player, UpgradeType)
--work out which player sent the event.
--Change their ServerInfo.Player1.Upgrade.Value
end
Point being. Send messages. Don’t change values.
Part Says “Hey you player, you just bought this!”
Player says, “Oh thank you. I will smile with my Sword! Now Upgrade it.”
Server says “Oh ok. Since everything looks in order, I will change that value for you.”