Leaderstats + Saving (DataStore)
Coins and Wins on the leaderboard, saved safely with UpdateAsync, retries, autosave and shutdown saving.
⚑ Report this
Coins and Wins on the leaderboard, saved safely with UpdateAsync, retries, autosave and shutdown saving.
Shows Coins and Wins on the leaderboard and saves them safely.
SETUP
1. Put this Script in ServerScriptService.
2. Publish the game, then Game Settings > Security > turn ON "Enable Studio Access to API Services"
(only needed to test saving inside Studio).
3. Change other scripts' stats like this: player.leaderstats.Coins.Value += 10
WHY IT'S SAFE
- UpdateAsync (not SetAsync) so two servers never overwrite each other blindly.
- Retries with back-off when Roblox's DataStore service hiccups.
- Autosaves every 2 minutes and saves everyone when the server shuts down.
- Never saves a player whose data failed to load (so a bad load can't wipe their progress).
The main script is shown below with a Copy button, or grab the download with every file and a README.
--[[
Leaderstats + Saving (DataStore) · by Cube Burst Studios · CC0
Shows Coins and Wins on the leaderboard and saves them safely.
SETUP
1. Put this Script in ServerScriptService.
2. Publish the game, then Game Settings > Security > turn ON "Enable Studio Access to API Services"
(only needed to test saving inside Studio).
3. Change other scripts' stats like this: player.leaderstats.Coins.Value += 10
WHY IT'S SAFE
- UpdateAsync (not SetAsync) so two servers never overwrite each other blindly.
- Retries with back-off when Roblox's DataStore service hiccups.
- Autosaves every 2 minutes and saves everyone when the server shuts down.
- Never saves a player whose data failed to load (so a bad load can't wipe their progress).
]]
local Players = game:GetService("Players")
local DataStoreService = game:GetService("DataStoreService")
local RunService = game:GetService("RunService")
local STORE = DataStoreService:GetDataStore("PlayerData_v1") -- change the name to reset everyone's data
local AUTOSAVE_SECONDS = 120
local MAX_TRIES = 4
-- every stat you want: name = starting value
local DEFAULTS = {
Coins = 0,
Wins = 0,
}
local loaded = {} -- [player] = true once their data loaded OK
local function withRetries(fn)
local lastErr
for attempt = 1, MAX_TRIES do
local ok, result = pcall(fn)
if ok then
return true, result
end
lastErr = result
task.wait(2 ^ attempt) -- 2, 4, 8, 16 seconds
end
return false, lastErr
end
local function keyFor(player)
return "player_" .. player.UserId
end
local function load(player)
local folder = Instance.new("Folder")
folder.Name = "leaderstats"
for name, default in pairs(DEFAULTS) do
local value = Instance.new("IntValue")
value.Name = name
value.Value = default
value.Parent = folder
end
folder.Parent = player
local ok, data = withRetries(function()
return STORE:GetAsync(keyFor(player))
end)
if not ok then
warn("Couldn't load data for " .. player.Name .. ": " .. tostring(data))
return -- not marked loaded, so we will never save over their real data
end
if type(data) == "table" then
for name in pairs(DEFAULTS) do
if type(data[name]) == "number" then
folder[name].Value = data[name]
end
end
end
loaded[player] = true
end
local function save(player)
if not loaded[player] then
return
end
local folder = player:FindFirstChild("leaderstats")
if not folder then
return
end
local snapshot = {}
for name in pairs(DEFAULTS) do
local value = folder:FindFirstChild(name)
snapshot[name] = value and value.Value or DEFAULTS[name]
end
local ok, err = withRetries(function()
STORE:UpdateAsync(keyFor(player), function()
return snapshot
end)
end)
if not ok then
warn("Couldn't save data for " .. player.Name .. ": " .. tostring(err))
end
end
Players.PlayerAdded:Connect(load)
for _, player in ipairs(Players:GetPlayers()) do -- players who joined before this script ran
task.spawn(load, player)
end
Players.PlayerRemoving:Connect(function(player)
save(player)
loaded[player] = nil
end)
task.spawn(function()
while true do
task.wait(AUTOSAVE_SECONDS)
for _, player in ipairs(Players:GetPlayers()) do
task.spawn(save, player)
end
end
end)
game:BindToClose(function()
if RunService:IsStudio() then
task.wait(1)
end
local pending = 0
for _, player in ipairs(Players:GetPlayers()) do
pending += 1
task.spawn(function()
save(player)
pending -= 1
end)
end
local started = os.clock()
while pending > 0 and os.clock() - started < 25 do
task.wait(0.1)
end
end)MORE
CODE
View all ↗Coin Shop (Exploit-Safe)
A server-checked shop: prices live on the server, coins are verified, tools are given safely. Includes the shop window.
Pet That Follows You
Every player gets a floating pet that follows smoothly using AlignPosition, with a gentle bob.
Smooth Doors with Keys
Press E to open doors that swing or slide with a tween, close automatically, and can require a key tool.
Sprint + Stamina Bar
Shift / mobile button / controller sprint with stamina drain, regen delay and a clean stamina bar.