DataStore Improvement

This is the first topic I’ve ever created; please forgive me if anything is wrong or not up-to-par.

The purpose of this topic is to:
- See if this is an inefficient way of using datastores
- See if is any better ways of accomplishing what I already have
- Be warned about any errors or exploits that I may not have accounted for

Also, if my coding seems “unprofessional”, my apologies in advance :grimacing:
(any suggestions on improving the way I do anything is gladly accepted)

local datastore = game:GetService("DataStoreService")
local DATA_lvl = datastore:GetDataStore("...")
local DATA_coins = datastore:GetDataStore("...")
local DATA_gems = datastore:GetDataStore("...")
local DATA_wins = datastore:GetDataStore("...")
local DATA_xp = datastore:GetDataStore("...")
local DATA_xpn = datastore:GetDataStore("...")
local DATA_rebirths = datastore:GetDataStore("...")
local DATA_colors = datastore:GetDataStore("...")
local DATA_trail = datastore:GetDataStore("...")


function savedata(dataname, playerid, value)
 datastore:GetDataStore(dataname):SetAsync(playerid, value)
end

game.Players.PlayerAdded:connect(function(player)
local playerconfig = player:WaitForChild("PlayerConfiguration")
local leaderstats = player:WaitForChild("leaderstats")
local level = leaderstats:WaitForChild("Level")
local coins = leaderstats:WaitForChild("Coins")
local gems = playerconfig:WaitForChild("Gems")
local wins = leaderstats:WaitForChild("Wins")
local xp = playerconfig:WaitForChild("xp")
local xpneeded = playerconfig:WaitForChild("xpneeded")
local rebirths = leaderstats:WaitForChild("Rebirths")
local colornumbers = game:GetService("ReplicatedStorage"):WaitForChild("PeoplesColors"):WaitForChild(player.Name)
local trail = game:GetService("ReplicatedStorage"):WaitForChild("PeoplesTrails"):WaitForChild(player.Name)

repeat wait() until trail
	if DATA_coins:GetAsync(tostring(player.userId)) ~= nil then
	coins.Value = DATA_coins:GetAsync(tostring(player.userId))
	end
	if DATA_gems:GetAsync(tostring(player.userId)) ~= nil then
	gems.Value = DATA_gems:GetAsync(tostring(player.userId))
	end
	if DATA_wins:GetAsync(tostring(player.userId)) ~= nil then
	wins.Value = DATA_wins:GetAsync(tostring(player.userId))
	end
	if DATA_xpn:GetAsync(tostring(player.userId)) ~= nil then
	xpneeded.Value = DATA_xpn:GetAsync(tostring(player.userId))
	end
	if DATA_xp:GetAsync(tostring(player.userId)) ~= nil then
	xp.Value = DATA_xp:GetAsync(tostring(player.userId))
	end
	if DATA_rebirths:GetAsync(tostring(player.userId)) ~= nil then
	rebirths.Value = DATA_rebirths:GetAsync(tostring(player.userId))
	end
	if DATA_colors:GetAsync(tostring(player.userId)) ~= nil then
	colornumbers.Value = Color3.new(DATA_colors:GetAsync(tostring(player.userId)).r,DATA_colors:GetAsync(tostring(player.userId)).g,DATA_colors:GetAsync(tostring(player.userId)).b)
	end
	if DATA_lvl:GetAsync(tostring(player.userId)) ~= nil then
	level.Value = DATA_lvl:GetAsync(tostring(player.userId))
	end
	if DATA_trail:GetAsync(tostring(player.userId)) ~= nil then
	trail.Value = DATA_trail:GetAsync(tostring(player.userId))
	end
end)

game.Players.PlayerRemoving:connect(function(player)
local playerconfig = player:WaitForChild("PlayerConfiguration")
local leaderstats = player:WaitForChild("leaderstats")
local level = leaderstats:WaitForChild("Level")
local coins = leaderstats:WaitForChild("Coins")
local gems = playerconfig:WaitForChild("Gems")
local wins = leaderstats:WaitForChild("Wins")
local xp = playerconfig:WaitForChild("xp")
local xpneeded = playerconfig:WaitForChild("xpneeded")
local rebirths = leaderstats:WaitForChild("Rebirths")
local colornumbers = game:GetService("ReplicatedStorage"):WaitForChild("PeoplesColors"):WaitForChild(player.Name)
local trail = game:GetService("ReplicatedStorage"):WaitForChild("PeoplesTrails"):WaitForChild(player.Name)

savedata("...", player.userId, level.Value)
savedata("...", player.userId, coins.Value)
savedata("...", player.userId, gems.Value)
savedata("...", player.userId, wins.Value)
savedata("...", player.userId, xp.Value)
savedata("...", player.userId, xpneeded.Value)
savedata("...", player.userId, rebirths.Value)
savedata("...", player.userId, {r = colornumbers.Value.r, g = colornumbers.Value.g, b = colornumbers.Value.b})
savedata("...", player.userId, trail.Value)
	
end)

(names of datastores were removed)

All constructive criticism, ideas, and suggestions, are accepted!

2 Likes

So instead of creating a new DataStore for each player stat as you did there it would be much more efficient to create one data store and store all your player stats within a table. I believe the wiki shows you a good way to begin using a CURRENT_SESSION table to store everything. I’m sure you’ve looked at the wiki but you can find more here. That is one of the big problems I see, I’m sure others will pick more apart:) welcome to the forums!

Edit: Grammar

2 Likes

I will definitely be adjusting things, thanks for the link and the reply! :slight_smile:

1 Like

So one suggestion, you can use datastore2 to make your life a lot easier using datastores. It is pretty much a failsafe against losing data, and it is easier to set up once you see the “gotchas” at the end.

Other than this, I would recommend using tables/dictionaries to shorten and organize your code.
e.g:

local DATA = {
	lvl = datastore:GetDataStore("..."),
	coins = datastore:GetDataStore("..."),
	--...
}
--...
game.PlayersAdded:Connect(function(player) --capitalize Connect, connect is deprecated!
	local playerconfig = player:wfc() --shortened
	local leaderstats = player:wfc()
	local leaderData = { --name it something comfortable, unlike mine
		lvl = leaderstats:WaitForChild("Level"), -- use the same indexes as DATA !
		coins = leaderstats:WaitForChild("Coins")
		--...
	}
	repeat wait() until trail
	for name,store in pairs(DATA) do
		if store:GetAsync(tostring(player.UserId)) ~= nil then --user id's are uppercase!
			leaderData[name].Value = store:GetAsync(player.UserId))
			-- I would use GetAsync once and store it in a variable, instead of calling it twice
		end
	end
end)

game.Players.PlayerRemoving:Connect(function(player)
	local playerconfig = player:wfc()
	local leaderstats = player:wfc()
	local leaderData = {
		level = leaderstats:WaitForChild("Level"),
		coins = leaderstats:WaitForChild("Coins"),
		--...
	}
	for name,data in pairs(leaderData) do
		savedata(DATA[name], player.UserId, data.Value)
		--something like that
	end
end)

I would probably also save a table of values like SkoobiDoobiDoo said, and I would also try to keep track of this data in the same way as you would for keeping track of it in leaderstats.

3 Likes

Only 1 main data store table is required and better in my opinion
data_name would get very annoying to use.

1 Like

Thank you so much for that detailed reply!

I have a few questions though;

  1. (as stupid as this may sound, but;) what difference/what changes when using :Connect rather than :connect? And .UserId rather than .userId

  2. I’m extremely inexperience at using modules like this, if I have any questions about it in the future, do you think I could contact you for some “stupid” questions?

So,

  1. deprecated means that roblox developers will not be opting for updates to this feature in the future, as another has succeeded it, and this is mainly because of changes to the jargon so that future functions either follow already-common practices in naming things, or are just easier to understand from the name.

  2. You can ask me questions about this, but it is most likely that I may forget to answer your questions due to things outside my control, such as school or just life in general.

Therefore, I would recommend researching dev forums (here), the developer wiki, or the lua documentation for any other “stupid” questions you may have. If even those resources do not answer your questions, you can always make a topic here, as there are many that are willing to help.
If you don’t know how to word your question, scripting helpers has a dictionary of terms to help you figure out what you are trying to ask, and you can also use them as a resource as well.

1 Like

Alrighty, thank you very much!

1 Like