Memory leaks kill performance. When your GUI closes, destroy everything:
function CloseGUI()
for _, item in pairs(screenGui:GetChildren()) do
item:Destroy()
end
screenGui:Destroy()
end
Place this script anywhere inside ServerScriptService. This is where the magic of security happens.
-- Script in ServerScriptService local remote = game.ReplicatedStorage:WaitForChild("PurchaseItem") local itemPrices = HealthPotion = 50remote.OnServerEvent:Connect(function(player, requestedItem) -- VALIDATION LAYER (The "Better" part)
-- 1. Validate the item exists local price = itemPrices[requestedItem] if not price then warn(player.Name .. " tried to buy an invalid item!") return end -- 2. Validate the player exists and has a leaderstats folder local leaderstats = player:FindFirstChild("leaderstats") local coins = leaderstats and leaderstats:FindFirstChild("Coins") if not coins or not coins.Value then player:Kick("Corrupted data. Rejoin.") return end -- 3. Check if they have enough money (Server check!) if coins.Value >= price then -- Deduct money coins.Value -= price -- Give item (Server handles inventory) local backpack = player:FindFirstChild("Backpack") local potion = game.ServerStorage.Items.HealthPotion:Clone() -- Preloaded item potion.Parent = backpack -- Optional: Confirmation back to client local confirmRemote = game.ReplicatedStorage:WaitForChild("NotifyPlayer") confirmRemote:FireClient(player, "Purchased successfully!") else -- Not enough gold. Tell client to revert UI. local failRemote = game.ReplicatedStorage:WaitForChild("NotifyFail") failRemote:FireClient(player, "Not enough gold!") end
end)
Beginner scripters put everything in a single LocalScript. A superior FE strategy separates concerns: