How to save tables to datastore?

I wanted to do an Inventory System that saves the ID and then u can get the inv in the next session.
I looked everywhere and i still didnt understand how to do it.

I would be grateful if you helped me.
And if u want to help me more, could you tell me how to like make that the table save numbers that are portraying the numbers, that multiple items can be saved.

local InventoryD = DataStore:GetDataStore("Inv")


local DataStore = game:GetService("DataStoreService")
local Inv = DataStore:GetDataStore("Inv")


local R_INV = game.ReplicatedStorage.Inventory.Events:WaitForChild("Recieve_INV")
local Send_INV = game.ReplicatedStorage.Inventory.Events:WaitForChild("Send_INV")


local Inventory = { -- Example Player Inventory

}

game.Players.PlayerAdded:Connect(function(plr)
	local folder = Instance.new("Folder",plr)
	folder.Name = "Inven"


	local success,errorMessage = pcall(function()
		local data = Inv:GetAsync(plr.UserId, "InventoryValue", Inventory)
		
		Inventory = data[1]
		print(Inventory)
	end)
	
	if success then
		print("Data successfully loaded!")
	end
	if errorMessage then
		warn(errorMessage)
	end

	game.Players.PlayerRemoving:Connect(function(plr)
		local coins = plr.Ingame.Coins

		Inv:SetAsync(plr.UserId.. "Inv", Inventory)
	end)

	game:BindToClose(function()
		for i,plr in pairs(game.Players:GetPlayers()) do
			local coins = plr.Ingame.Coins


			Inv:SetAsync(plr.UserId.. "Inv", Inventory)
		end
	end)

end)

R_INV.OnServerEvent:Connect(function(ID, plr)
	
	local success,errorMessage = pcall(function()
		local data = Inv:GetAsync(plr.UserId)
		
		print(Inventory)
	end)
	
	table.insert(Inventory, ID)
	Inv:SetAsync(plr.UserId.. "Inv", Inventory)
	print(Inventory)
end)

game.Players.PlayerAdded:Connect(function(player)
	Send_INV:FireClient(player, Inventory)
end)
2 Likes

you should use HttpService to json encode the table, then store the results. When you load the data use HttpService:JSONDecode to read the data

i heard its not nercessary tho

You cannot store tables/arrays in Roblox Datastore. If you want to still use tables and avoid having to seperate arrays, please use

game:GetService("HttpService"):JSONDecode / Encode
2 Likes

I am saving tables like this and it works:

local t = {}
for i, v in pairs(Inventory:GetChildren()) do
	table.insert(t, v.Name)
end
game:GetService("DataStoreService"):GetDataStore("InventorySave"):SetAsync(plr.UserId, t)
1 Like

alr i did that but now i have an error at SetAsync()

ServerScriptService.Data.Inventory:64: attempt to index number with 'UserId'

here is the section of the code


R_INV.OnServerEvent:Connect(function(ID, plr)
	
	local success,errorMessage = pcall(function()
		local data = Inv:GetAsync(plr.UserId)
		Inventory = HttpS:JSONDecode(data)
		print(Inventory)
	end)
	
	table.insert(Inventory, ID)
	local InvE = HttpS:JSONEncode(Inventory)
	Inv:SetAsync(plr.UserId, InvE)
end)

The error is telling you that you plr is not player object. Also what is the ID variable

1 Like

So how my inventory system works is like with ID’s of the skins, other scripts check the IDs in the skins intvalue from the inventory and then the skins with the ID should go to the inventory.

R_INV.OnServerEvent:Connect(function(InventoryIDs, plr) -- This is firing when Player's inventory has to be saved I guess
	local t = {}
    for _, ID in pairs()InventoryIDs do
        table.insert(t, ID)
    end
	Inv:SetAsync(plr.UserId, t)
end)

Something like this is what I would do

1 Like

Sorry for the misunderstanding but its only 1 ID that comes from the event
Does it change anything?

then you can just skip the for _, ID function and set

Inv:SetAsync(plr.UserId, ID)

Also does that mean you don’t need table to save it in?

1 Like

i need a table cuz if i buy more skins per session it needs to be saved in inventory?

So you mean it might be only 1 ID?
if that then you can still use the first one with for i, v function

like every skin has 1 ID.
If u buy it u send the ID to the Server script
The event imports the ID number and should save it in a table and save it to the data store

In that case you have to make it like this:

R_INV.OnServerEvent:Connect(function(InventoryIDs, plr) -- This is firing when Player's inventory has to be saved I guess
	local t = {}
    local SavedIDs = Inv:GetAsync(plr.UserId)
    if SavedIDs ~= nil then
        for _, ID in pairs(SavedIDs) do
            table.insert(t, ID)
        end
    end
    table.insert(t, ID)
	Inv:SetAsync(plr.UserId, t)
end)

This is the only way I can think in which it won’t overwrite saved values

1 Like

You can store tables and arrays in Datastores

now GetAsync causes the same ServerScriptService.Data.Inventory:55: attempt to index number with ‘UserId’ error

Are you accounting for the fact any first parameter to an OnServerEvent callback will always be the player that fired the event?

@iHasLag9 you do not need to encode and decode tables to save to the data store as long as they only contain numbers, strings and Booleans.

Don’t have connections in connections to avoid memory leaks and prevent incorrect data saving.

Try to mass save data as well to stay within the budget, also use UpdateAsync @WtVietterGHG .

2 Likes

Yea I forgot This should work

R_INV.OnServerEvent:Connect(function(plr, InventoryIDs)
	local t = {}
    local SavedIDs = Inv:GetAsync(plr.UserId)
    if SavedIDs ~= nil then
        for _, ID in pairs(SavedIDs) do
            table.insert(t, ID)
        end
    end
    table.insert(t, ID)
	Inv:SetAsync(plr.UserId, t)
end)

i know this isn’t your issue, but you shouldn’t have players.PlayerRemoving() inside of a players.PlayerAdded() event since you’re making a new connection each time a player joins, which makes it execute multiple times when multiple people are playing. also the same with the :BindToClose() event.

Another thing is that you also have 2 seperate PlayerAdded events, which i recommend you merge into one.