I am looking to get some feedback for how I could make the following.
I am looking to make a datastore which saves a list of every individual player who has played the game. I am looking to list them all on a SurfaceGui, but am looking for a solution for the datastore part of it.
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("DataStore")
local players = game:GetService("Players")
players.PlayerAdded:Connect(function(player)
local leaderstats = Instance.new("Folder")
leaderstats.Name = "leaderstats"
leaderstats.Parent = player
local veteran = Instance.new("StringValue")
veteran.Name = "Veteran"
veteran.Value = "False"
veteran.Parent = leaderstats
local success, result = pcall(function()
return ds:GetAsync(player.UserId)
end)
if success then
if result then
veteran.Value = "True"
end
else
warn(result)
end
end)
players.PlayerRemoving:Connect(function(player)
local success, result = pcall(function()
ds:SetAsync(player.UserId, true)
end)
if success then
if result then
print(result)
end
else
warn(result)
end
end)
game:BindToClose(function()
for _, player in ipairs(players:GetPlayers()) do
local success, result = pcall(function()
ds:SetAsync(player.UserId, true)
end)
if success then
if result then
print(result)
end
else
warn(result)
end
end
end)
Here you go, I’ve incorporated a leaderstats too, it’ll display “False” for players that have never visited before and “True” for players that have visited before.
I advise against using datastore:SetAsync(key,data) for saving data. It may be faster in saving data, but by using it, you’re increasing the chances of losing data. Instead, use datastore:UpdateAsync(key, function() return data end) and wrap it in a pcall()
This is just for saving players that have visited the game before, we’re not transforming any existing data so “UpdateAsync()” would be unnecessary.
Thank you fro the replies. These are all helpful, I was just wondering how I could potentiallky get a list of all of the players recorded in the datastore. Is there a way to see what data is in it?
Hey there! In order to achieve this, with the necessary revisions, you may want to consider using this script I drafted for you.
local service = game:GetService("DataStoreService")
local store = service:GetDataStore("PlayersWhoJoined")
local key = "MainList1" -- change to reset data
local players = game.Players
local surfaceGui -- set this yourself
players.PlayerAdded:Connect(function(player)
store:UpdateAsync(key, function(old)
old=old or {}
old[player.UserId]=true
return old
end)
local data = store:GetAsync(key)
for i,v in pairs(data) do
local playerName = game.Players:GetNameFromUserIdAsync(i)
print(playerName) -- this is where you would put your surfaceGui stuff
end
end)
Let me know if I need to go into more depth on this.
Sure! I also hope the script I provided works for you.
UpdateAsync is good because it provides you with the original data, so that you can add onto it rather than completely replacing it.
The two arguments are the key and the data. As you can see, I use a function with the parameter old (it can be anything). The parameter old is set to the data that is currently set for the key provided.
Another example, more similar to this situation, would be with table data.
Suppose the data under the key “Kobe” is a table:
{"ball","shoes"}
Let’s say we want to add a third item to that table and save it using DataStorage. We do not know what he currently has saved. That’s when we would use UpdateAsync
DataStorage:UpdateAsync("Kobe", function(data)
return table.insert(data, 1, "water")
end
The first one makes sure that a table already exists. It sets the parameter, old to either itself or an empty table. If old is equal to nil, then it will, by default, be set to the second option in the “or” statement (which is {} in our case).
The second line creates a dictionary location. It goes into old, which is now either an empty dictionary or one that was already created, and creates a new “slot” labelled the user ID. It set’s their slot to true (which doesn’t really matter, as long as it is not nil).
This is what it looks like visually:
--BEFORE NEW PLAYER JOINS
data = nil
--old = old or {}
data = {}
--next line
data = {
[1098734] = true
}
UpdateAsync() merely allows you to transform existing data associated with some key of the datastore, it’s essentially the same as performing GetAsync() and SetAsync() in a single step.
You can’t use UpdateAsync() to iterate over all of the entries of a datastore.
Consider using “game.GameId” as a static datastore key (it’s more intuitive). You also need to wrap “UpdateAsync()” and “GetNameFromUserIdAsync()” in pcalls as they are API requests and as such are prone to errors and if either request fails the entire script will abruptly terminate.
We understand that, which is why I gave him an in-depth explanation of how it works. The topic has been solved because what he was looking for was given, then he wanted additional information.
That’s iterating over the data (a table value) of some particular key of a datastore not iterating over the data of all keys within a datastore (the question you proposed).
For the latter you’d need to make use of an ordered datastore.