Any tips on improving my DataStore script?

Code:

local DSS = game:GetService("DataStoreService")
local Config = require(script:WaitForChild("Config"))
local Store = DSS:GetDataStore(Config.KeyName)
local CurrenciesToSave = {}
-- Create default currencies and put them in a table to be cloned
for i, v in pairs(Config.Currencies) do
	local new = Instance.new(v.."Value")
	new.Name = i
	table.insert(CurrenciesToSave, new)
end

-- PlayerAdded function
local function Added(plr)
	local PData = Instance.new("IntValue", plr)
	PData.Name = "Data" -- Object's children are saved
	for _, v in pairs(CurrenciesToSave) do
		v:Clone().Parent = PData -- inserts Values into data
	end
	local Key = "Player_"..plr.UserId -- defines key
	local Store = Store:GetAsync(Key) -- gets data
	if Store then -- if data exists then overwrite values with data
		for i, v2 in pairs(Store) do
			PData[i].Value = v2
		end
		print("Loaded data for "..plr.Name)
	else -- if not, then save the data
		local TBL = {}
		for _, v3 in pairs(PData:GetChildren()) do
			TBL[v3.Name] = v3.Value
		end
		local s, f = pcall(function() -- pcall
			Store:UpdateAsync(Key, function()
				return TBL
			end)
		end)
		if s then
			print("Data saved succesfully.")
		else -- retry if failed
			print("Data saving failed. Retrying.")
			local s2, f2 = pcall(function()
				Store:UpdateAsync(Key, function()
					return TBL
				end)
			end)
			if s2 then
				print("Retry succesfull.")
			else
				print("Retry failed.")
			end
		end
	end
end

local function Removing(plr) -- on player remove
	local PData = plr.Data -- Player's data
	local TBL = {} - table of data to save
	for _, v in pairs(PData:GetChildren()) do
		TBL[v.Name] = v.Value -- makes values with the Value's name and Value
	end
	local Key = "Player_"..plr.UserId -- key again
	local s, f = pcall(function() -- pcall again
		Store:UpdateAsync(Key, function()
			return TBL
		end)
	end)
	if s then
		print("Data Saving Succesfull!")
	else -- retry again
		print("Data saving failed. Retrying.")
		local s2, f2 = pcall(function()
			Store:UpdateAsync(Key, function()
				return TBL
			end)
		end)
		if s2 then
			print("Retry succesful")
		else
			print("Retry failed.")
		end
	end
end

local function bindtoclose()
	for _, plr in pairs(game:GetService("Players"):GetPlayers()) do -- save all player's data
		local PData = plr.Data
		local TBL = {}
		for _, v in pairs(PData:GetChildren()) do
			TBL[v.Name] = v.Value
		end
		local Key = "Player_"..plr.UserId
		local s, f = pcall(function()
			Store:UpdateAsync(Key, function()
				return TBL
			end)
		end)
		if s then
			print("Data Saving Succesfull!")
		else
			print("Data saving failed. Retrying.")
			local s2, f2 = pcall(function()
				Store:UpdateAsync(Key, function()
					return TBL
				end)
			end)
			if s2 then
				print("Retry succesful")
			else
				print("Retry failed.")
			end
		end
	end
end
-- connections
game:GetService("Players").PlayerAdded:Connect(Added)
game:GetService("Players").PlayerRemoving:Connect(Removing)
game:BindToClose(bindtoclose)

I’m trying to achieve datastore with less data loss.
Anything I can do to improve?

I would localize the function instead of making them on the spot when the event occurs. Otherwise, it looks good enough to function well.

What does localizing the functions do? Improve performance?

i’m not really sure, but since you are running the function multiple times (i’m assuming the game will be multiplayer) its better to have function that are saved to memory so the server doesn’t have to create a function every single time the event was called.

Alright, thanks for the tip. I’ll try it.

This is incorrect, the function remains in memory, it isn’t declared every time the event is called.

I just don’t like how your code is messy. To be honest everyone should learn how to use datastores before using any, any datastore module, but Datastore modules like DS2, and ProfileService are just so much more superior. They handle everything without you having to think much about it. I highly recommend you use them.

Anyhow, I think you should compare data using UpdateAsync, one way to go is to save a “DataId”, the DataId in this case should be the same when saving data. If it isn’t, then don’t save any data.

@theepicgdog not really true. You should only declare a function from a connection if you’re gonna connect that in multiple events or a lot of times in the same script.

Just note that DS2 is now considerably inferior - due to how it saves backup redundantly and doesn’t do much to protect you from data loss, you are also guaranteed to load old data if the previous server couldn’t / fail to save your data in time because DS2 doesn’t provide session locking. Not to mention that there are a lot of faults in the code and doesn’t handle any edge cases at all.

1 Like

So should I just use regular DataStore instead of DS2?

Your choice, but I would recommend using QuickNetwork as it handles all the edge cases for you and is far more flexible: QuickNetwork

1 Like