What is the best way to store Data?

I’m learning to code even more and i have got to the stage where i want to learn to script with data and get data saved so that it saves players coins and other kind of data.

I’ve looked at some types and all i seem to be getting is Roblox’s own datastore service and Profile Service. But what i want to know is which is better.

I’m just making small projects to start with so anything from Basic to Advanced will do.

You should use data stores for this. Profile service is a module that builds on this and may be easier but I’ve never used it. Here is an example that I use:

locks = {} is not absolutely necessary but I use it for some safety checks elsewhere.

local dataStores = game:GetService("DataStoreService")
local httpService = game:GetService("HttpService")
local statsStore = dataStores:GetDataStore("PlayerStats")

local stats = {}
local locks = {}

local startingStats = {Crumbs = 10000, Shleen = 10}

players.PlayerAdded:Connect(function(player)
	--Initialize save or load stats
	--Lock player initially
	locks[player] = true
	
	--Load stats here, probably async
	local statsJson = statsStore:GetAsync(tostring(player.UserId))
	
	if statsJson == nil or statsJson == "" then
		print("Initializing new player stats for " ..player.Name)
		stats[player] = table.clone(startingStats)
	else
		local playerStats = httpService:JSONDecode(statsJson)
		stats[player] = playerStats
		
		print("Loaded stats for " ..player.Name)
	end
	
	--Don't unlock the player's stats until they have loaded
	locks[player] = false
end)

players.PlayerRemoving:Connect(function(player : Player)
	--SerializeStats
	local statsJson = httpService:JSONEncode(stats[player])
	
	if statsJson == nil or statsJson == "" then
		warn("Failed to JSONEncode save stats for " ..player.Name)
		return
	end
	
	--Save stats
	statsStore:SetAsync(tostring(player.UserId), statsJson)
	print("Saved stats for " ..player.Name)
end)

I’ve never used locks before.
Just for safety checks? What would it do? Basically secure the loading?

I have a script that handles “stats” that are used as currency. The way its set up its possible for multiple transactions to launch at once and there is no guarantee on their order, so when making a purchase I lock out other transactions until its completed.

local function LockPlayer(player : Player)
	if locks[player] == true then
		warn(player.Name.. " is already in a transaction.")
		return false
	end

	locks[player] = true
	
	return true
end

local function UnlockPlayer(player : Player)
	locks[player] = false
end

--Request a purchase, returns true if the transaction goes through
function remotesLocation.Purchase.OnInvoke(player : Player, currencies)
	--Lock this player's stats during transaction
	if not LockPlayer(player) then
		return false
	end
	
	--Perform transaction
	local canAfford = true
	
	for currencyType, currencyAmount in pairs(currencies) do
		local currentAmt = stats[player][currencyType]
		
		if currentAmt == nil or currentAmt < currencyAmount then
			canAfford = false
			break
		end
	end
	
	if canAfford then
		--Allow purchase
		for currencyType, currencyAmount in pairs(currencies) do
			stats[player][currencyType] -= currencyAmount
		end
		
		--Grant purchase
		UnlockPlayer(player)
		return true
	else
		warn(player.Name.. " is too broke to purchase that!")
		UnlockPlayer(player)
		return false
	end
end

Seems to complicated this way but i love learning new ways as ive said that im open to learning basic to Advanced DataStore

This is also just a temporary thing I did and it doesn’t stop most kinds of dupes. You need to put the lock into a MemoryStore or DataStore for that. Also its important that the Purchase function does not error between when it locks and unlocks. It should probably use pcall().

1 Like

all im looking for at the minute is how to store my coins as a table as data

I would suggest DataStore2. It’s a module, that makes saving/loading data trouble-free. My Leaderstats doesnt save - #4 by TortenSkjold