Saving a table using DataStore2

Hello everyone,

I recently started learning about DataStore2 to prevent dataloss because the default datastores from roblox are just not good enough to prevent dataloss.

I am trying to save a table using Datastore2 in which I want to save in-game items. I made a script which works and saves a table.

My question is: Is the way I use DataStore2 for saving a table good? or are there any points in this script which could use some improvement?

This is my script:

Note: after the table is loaded in, I put all items from that table in a folder which is located in serverstorage.PlayerData:WaitForChild(plr.Name):WaitForChild(“Inventory”).
I have not included the script which creates this directory because this post is about whether I use DataStore2 correctly or not.



local DataStore2 = require(1936396537)

local Defaults = {} 

game.Players.PlayerAdded:Connect(function(plr)
	
	local TableDataStore = DataStore2("Table", plr)  --getting the datastore 

	local function TableUpdate(updatedValue)		
		local tablev = TableDataStore:GetTable(updatedValue)  --getting the table from the datastore
		for i, v in pairs(tablev) do --iterating through all values inside this table
			if game.ServerStorage.PlayerData:WaitForChild(plr.Name):WaitForChild("Inventory"):FindFirstChild(v) then else --in case an item already exists inside the inventory, we dont put it there again
			local newValue = Instance.new("StringValue") --creating a stringvalue which gets the name of the item. So we can check in-game if the player has this item or not.
			newValue.Parent = game.ServerStorage.PlayerData:WaitForChild(plr.Name):WaitForChild("Inventory") --this item will be put inside the inventory folder.
			newValue.Name = v 
			end
		end
	end													

	TableUpdate(Defaults)  --if there is no table found using the :GetTable, the defaults table will be used.
	TableDataStore:OnUpdate(TableUpdate) 
end)



game.Workspace:WaitForChild("TablePart").ClickDetector.MouseClick:Connect(function(player) --This piece of code will be put inside a part and script.Parent.ClickDetector.... will be used instead.
	local newitem = tostring(math.random(1,1000000)) --just to make it easy for the sake of this post, I use random values as items
	local TableDataStore = DataStore2("Table", player)
	local tablev = TableDataStore:GetTable(Defaults) --again if there is no table to be found, the default table will be used.
	table.insert(tablev, newitem) --the new item gets inserted in the table.
	TableDataStore:Set(tablev)  --the datastore will be updated which launches the :OnUpdate function
end)
2 Likes

Did you follow tutorial to create this? Or did you make it on your own? (Talking about your script) If you haven’t read the thread for DS2 yet, I recommend reading it.

Yes, I have read this thread but I couldn’t figure out which way of saving tables was the best, so I decided to make my own script combining some examples.

Why are you saving Data though ClickDetection?

I’m just using a clickdetector as an example. I could have used a GUI for that matter.

Instead of using :Set to update the Datastore with a new table you should use :Update(). I think if you use :Set and an error occurs or something goes wrong you risk losing your data but with the :Update you first pass through the original cached value and change it. That may be wrong though, I would still recommend using :Update()

Also, it doesn’t look like you’re checking if the Player has data when they join, you just get the Datastore and call the TableUpdate function. You can use a pcall to check if they have data. You can then just set the default table if they don’t.

What I would do for an inventory system is create a global table that holds everyone’s inventories. I would then create different functions that modify their tables(I.E add item, remove item). Then have a save function that inputs the Player whose data you want to save and gets their inventory through that global table and passes it through an :Update().

2 Likes

Okay thanks! I will try :Update() I haven’t used this before because I thought that :Update() could only be used for int/floats. Since it “updates” the old value, and “updating” a table didnt seem logical for me because I don’t use the old table value and update that old value to a new one, I use an entire new table. I didn’t test this out so I could have been wrong.

Concerning checking whether the player has data when joining:
when a player joins, I run the function TableUpdate(parameter Defaults). And if the TableDataStore:GetTable results into nil, the defaults table will be used.

Hello @speeddecoolste

First of all,

DS2 uses default datastores, just in another way. You can read this to know exactly how.
And your DS2 code seems good, I would use a table instead of serverstorage to save the data though. More organized and easier to access data. However I notice a memory leak in your code. You are not removing the data of the player after they leave, if a player keeps rejoining or just a lot of players join and leave, there will be a stack of useless data in your server storage which will keep increasing over time. Everything else seems good to me (except stuff other people have already pointed out) :slight_smile:.

3 Likes

You’re right. I didn’t think about deleting the inventory folder of a player when they leave.

Thanks!

2 Likes

Ahh well, I am fairly new to DataStore2 aswell I have been using it for about a month so maybe you are right about :Set()? I currently handling a bunch of Player’s stats within a table so what I do with the :Update is something like this

local function SAVE_DATA(player)
	if CURRENT_SESSION[player] then
		local playerData = DataStore2("DATAKEY", player)
		playerData:Update(function(old)
			return CURRENT_SESSION[player]
		end)
	end
end

it works great so maybe you could give that try.
Oh also I did not realize you were using :GetTable, that seems much more efficient maybe I will give that a shot for my data! Currently, I’m using :Get() to get the user’s stats table and if they do not have a table I use :Set(defaultstats). But it seems using :GetTable() will make it so I can add more keys to Player’s data whenever I would like without having to completely reset everyone’s data(Which I have been trying to figure out for about 2 days now god I love these forums).

P.S
I would also like to thank @Pseudorandomness for pointing out that memory leak as I did the same thing in my data but using a table.

2 Likes

You’re thinking of SetAsync and UpdateAsync. This is not the case for DataStore2–Set and Update will never error if your code is correct.

3 Likes