I have a leaderstat called “Wins” and I want it to be saved to datastore for all players. I have a working code for it already, but for some reason it fails sometimes without printing any errors or warnings. I want to see a working code with the best method, then I will look over it and remember it for future coding!
Would using modules assist you in any way? You can use them without the need to maintain your own code, as long as you don’t need ordered datastores.
Well thing is, I have no idea how modules work yet. Is there 1 script I can put inside of ServerScriptService that will work for the datastore?
Yes, there are multiple to choose from, 2 examples are ProfileService and DataStore2.
I’ll chose DataStore2, because I want to know how that works and it seems more useful than ProfileService. Also is there a DataStore1?
No, only DataStore2 from what I am aware of. Why, may I ask?
Because I was wondering if there was a DataStore1 will it will be a completely different method and I wanted to know the difference between them.
I don’t know if you want this but here is a script from my game it saves them money or whatever you want you can change a little bit of things about it.
local DataStore = game:GetService(“DataStoreService”)
local ds = DataStore:GetDataStore(“CashSaveSystem”)
game.Players.PlayerAdded:connect(function(player)
local leader = Instance.new(“Folder”,player)
leader.Name = “leaderstats”
local Cash = Instance.new(“IntValue”,leader)
Cash.Name = “Cash”
Cash.Value = ds:GetAsync(player.UserId) or 0
ds:SetAsync(player.UserId, Cash.Value)
Cash.Changed:connect(function()
ds:SetAsync(player.UserId, Cash.Value)
end)
end)
Wouldn’t you need to use pcall functions and save it when they leave?
I don’t know if I understand what you said, but it automatically will save your progress when you leave the game.
Well that code you sent is hard for me to read, and I don’t trust it because it looks like it’s missing some things
There’s no DataStore1, there is the simple datastore, here’s an example:
local dss = game:GetService("DataStoreService")
local saveData = dss:GetDataStore("putanythinghere")
game.Players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new(“Folder”,player)
leaderstats.Name = “leaderstats”
local Cash = Instance.new(“IntValue”,leaderstats)
Cash.Name = “Cash”
Cash.Value = 0
local data = saveData:GetAsync(player.UserId)
if data ~= nil then
Cash.Value = data[1]
else
Cash.Value = 0
end
end)
game.Players.PlayerRemoving(player)
local dataToSave = {
player.leaderstats.Cash.Value
}
saveData:SetAsync(player.UserId, dataToSave)
end)
I don’t need to create a leaderstat because I already did that in another script. Does it affect anything in this script? Datastore is new to me and I’m not good at reading it either.
You need to do the first part of the datastore inside of the leaderstats, format it how I did.
And also put the whole datastore in the same script as the leaderstats.
I don’t know what that means, sorry.
Another thing to add, wouldn’t you need to put pcall functions around the datastore stuff? I saw on devhub that you always need to put pcalls around datastore.
Also here is the code that I currently have in the game, maybe we can improve the already existing one?
local DS = game:GetService("DataStoreService"):GetDataStore("Wins")
game:GetService("Players").PlayerAdded:Connect(function(plr)
wait()
local plrkey = "id_"..plr.userId
local save1 = plr.leaderstats.Wins
local GetSaved = nil
local success, errorMessage = pcall(function()
GetSaved = DS:GetAsync(plrkey)
end)
if not success then
warn(errorMessage)
end
if GetSaved ~= nil then
save1.Value = GetSaved[1]
else
local NumberForSaving = {save1.Value}
local success, errorMessage = pcall(function()
DS:GetAsync{plrkey, NumberForSaving}
end)
if not success then
warn(errorMessage)
end
end
end)
game:GetService("Players").PlayerRemoving:Connect(function(plr)
local success, errorMessage = pcall(function()
DS:SetAsync("id_"..plr.userId, {plr.leaderstats.Wins.Value})
end)
if not success then
warn(errorMessage)
end
end)
Just use DataStore2 like I said, you don’t have to worry about data not saving etc as it handles it all for you. As I said, as long as you aren’t using ordered datastores its perfect for your usecase.
Well I don’t know what DataStore2 is and idk how to use it.
Read the documentation like everyone else.
Hey there! So, in essence, modules are just tables, which are returned to you by “requiring” them. Luau, however, is unique in the fact that it can store functions in tables and dictionaries. Because of this, people commonly use modules to neatly store functions. For example:
local Module = {}
function Module.Example()
print("Cool, it works!")
return
end
return Module
This “module”, would return a dictionary (a table that stores values with names/strings and other values instead of numbers indexing from 1+), and you can execute the function in it with
local Module = require(Path.To.Module)
Module.Example() -- This would print out "Cool, it works!"
return
This special property is why a lot of very popular utilities and libraries for use in ROBLOX are made with modules, because any script can access them and they are neatly organized!
So back to the original topic, the values in leaderstats are essentially just instances that store values. For example, a “NumberValue” stores a number that you can access by doing
NumberValue.Value
Then, you can use this value to save a player’s data! Here’s a quick example of a datastore system using ROBLOX’s built in datastores (but feel free to use a module, they’re great!)
local Datastore = {
Cache = {}, -- The currently saved datastore data!
Default = { -- The default data a player with no saved data gets!
Wins = 0,
Losses = 0,
Statistics = {}
}
}
local datastoreService = game:GetService("DatastoreService")
local datastore = datastoreService:GetDataStore("Game")
local function cloneTable(target)
if typeof(target) ~= "table" then
return target
end
local clone = {}
for index, value in pairs(target) do
clone[cloneTable(index)] = cloneTable(value)
end
return clone
end
function Datastore.Get(player)
local userId = tostring(player.UserId)
local cached = Datastore.Cache[userId]
if (cached ~= nil) then
return cached
end
local attempts = 0
local success = false
local data = nil
while true do
if (success ~= false or attempts >= 3) then
break
end
data = datastore:GetAsync(userId)
attempts += 1
if (data ~= nil) then
success = true break
end
wait(0.125)
end
if (data ~= nil) then
Datastore.Cache[userId] = data
return data
end
data = cloneTable(Datastore.Default)
Datastore.Cache[userId] = data
return data
end
function Datastore.Save(player)
local data = Datastore.Get(player)
local attempts = 0
local success = false
local data = nil
while true do
if (success ~= false or attempts >= 3) then
break
end
success = pcall(function() datastore:SetAsync(userId, data) end)
attempts += 1
wait(0.125)
end
end
return Datastore
You can then use this “module”, require it , and load data in a process similar to this:
-- The datastore module to get and save player data!
local Datastore = require(Path.To.Module)
-- The players service for all the important events we need!
local players = game:GetService("Players")
-- The event for when a player joins, so we can print out their wins/losses!
players.PlayerAdded(function(player)
local data = Datastore.Get(player)
print("The player has " .. data.Wins .. " wins, and " .. data.Losses .. " losses!")
return
end)
-- The event for when a player leaves, so we can save their data!
players.PlayerRemoving:Conncet(function(player)
Datastore.Save(player)
return
end)
But you may be wondering, where do leaderstats tie in with all this stuff? Well here’s the magic of modules, instead of rewriting the datastore saving code each time to set the player’s datastore values, you can use the following code to update the cached value, and then it’ll save automatically! (Assuming you are also using the previous script(s) I mentioned)
local Datastore = require(Path.To.Module)
Datastore.Get(player).Wins = leaderstats.Wins.Value
return
Please note, I wrote all of this in this text box, so I’m not quite sure if its 100% bug-free, but I’d be happy to help through any issues
Hope this helps! Have a wonderful day!