I made a datastore script for my game but obviously its very important to me to avoid all dataloss if possible. I’m aware that :SetAsync() is a good way to overwrite data, but I’m not sure how else to go about it.
Here’s my script for everyone to review (sorry I don’t use comments, I’m aware its not good.)
local dataService = game:GetService("DataStoreService")
local players = game:GetService("Players")
local Data = dataService:GetDataStore("Stats")
local TimerLeaderboard = dataService:GetOrderedDataStore("TimerLeaderboard")
local MergesLeaderboard = dataService:GetOrderedDataStore("MergesLeaderboard")
local CoinsLeaderboard = dataService:GetOrderedDataStore("CoinsLeaderboard")
local sessionData = {}
local plrsIngame = {}
local function updateLeaderboard()
for i,plr in plrsIngame do
local success, errorMsg = pcall(function()
if sessionData[plr.UserId] then
TimerLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Timer)
CoinsLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Coins)
MergesLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Merges)
end
end)
if not success then
warn("Failed to update leaderboard:", errorMsg)
else
print("Done updating global leaderboard for server")
end
end
end
local function joined(plr)
table.insert(plrsIngame, plr)
local Folder = Instance.new("Folder")
Folder.Name = "Stats"
Folder.Parent = plr
local Merges = Instance.new("NumberValue")
Merges.Name = "Merges"
Merges.Parent = Folder
local Timer = Instance.new("NumberValue")
Timer.Name = "Timer"
Timer.Parent = Folder
local Coins = Instance.new("NumberValue")
Coins.Name = "Coins"
Coins.Parent = Folder
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = plr
local Points = Instance.new("NumberValue")
Points.Name = "Points"
Points.Parent = leaderstats
local Wins = Instance.new("NumberValue")
Wins.Name = "Wins"
Wins.Parent = leaderstats
local success,playerData = pcall(function()
return Data:GetAsync(plr.UserId)
end)
if success then
if not playerData then
playerData = {
["Merges"] = 0,
["Timer"] = 0,
["Coins"] = 0,
["Wins"] = 0
}
end
sessionData[plr.UserId] = playerData
else
plr:Kick("Could not load Data, please rejoin.")
end
Merges.Value = sessionData[plr.UserId].Merges
Timer.Value = sessionData[plr.UserId].Timer
Coins.Value = sessionData[plr.UserId].Coins
Wins.Value = sessionData[plr.UserId].Wins
Merges:GetPropertyChangedSignal("Value"):Connect(function()
sessionData[plr.UserId].Merges = Merges.Value
end)
Timer:GetPropertyChangedSignal("Value"):Connect(function()
sessionData[plr.UserId].Timer = Timer.Value
end)
Coins:GetPropertyChangedSignal("Value"):Connect(function()
sessionData[plr.UserId].Coins = Coins.Value
end)
Wins:GetPropertyChangedSignal("Value"):Connect(function()
sessionData[plr.UserId].Wins = Wins.Value
end)
end
local function leaving(plr)
table.remove(plrsIngame, table.find(plrsIngame, plr))
if sessionData[plr.UserId] then
local success, errorMsg = pcall(function()
Data:SetAsync(plr.UserId, sessionData[plr.UserId])
TimerLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Timer)
CoinsLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Coins)
MergesLeaderboard:SetAsync(plr.UserId, sessionData[plr.UserId].Merges)
sessionData[plr.UserId] = nil
end)
if not success then
warn(errorMsg)
end
end
end
players.PlayerAdded:Connect(joined)
players.PlayerRemoving:Connect(leaving)
task.spawn(function()
while task.wait(60) do
updateLeaderboard()
end
end)