Datastore Feedback (Saving Players Who Have Joined)

Hello,

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.

Any help would be appreciated.
Thanks!

1 Like
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.

This worked when testing.

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.

1 Like

Sorry for the extremely delayed response.

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?

Thanks

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.

EDIT: I had to change one small thing.

Made my last edit, it should be good!

Hey, just for the future if I were to create something similar to this, can you explain how the function in the UpdateAsync() works? What si old?

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.

For example:

DataStore:UpdateAsync("Key1", function(data)
    return data+1
end)

The above script will update the data to whatever the data was originally, plus one.

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

Now the data would read:

{"water", "ball", "shoes"}

I am just a little confused about the following lines:

old=old or {}
old[player.UserId]=true

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
}

Let me know if that helps

That helps a lot actually. Thank you veriy much for your time!

No problem :grin: Glad to have helped.

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.

1 Like

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.

I didn’t do that in the case that the data were wanted to be reset.

RemoveAsync() exists for this very purpose (it too should be wrapped inside a pcall when used).

https://developer.roblox.com/en-us/api-reference/function/GlobalDataStore/RemoveAsync

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.