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)
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.
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().
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.
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) .
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.