This is my current invenotry saving/loading script
local inv = game:GetService("DataStoreService"):GetDataStore("inv_01") game.Players.PlayerAdded:Connect(function(plr) local items = inv:GetAsync(plr.UserId) or {} local inventory = Instance.new("Folder",plr) inventory.Name = "Inventory" --Load items for i,v in pairs(items) do if game.ReplicatedStorage.Items:FindFirstChild(v) ~= nil then game.ReplicatedStorage.Items[v]:Clone().Parent = inventory end end --Save inventory when item added inventory.ChildAdded:Connect(function(c) items[#items+1] = c.Name inv:SetAsync(plr.UserId, items) end) --save inventory when item removed inventory.ChildRemoved:Connect(function(c) items = {} for i,v in pairs(inventory:GetChildren()) do items[i] = v.Name end inv:SetAsync(plr.UserId, items) end) end)
Not asking for an entire script just a way.
I worked on an inventory system not too long ago, I can think of 2 solutions for your problem
EDIT: I made a test place that has a basic item give shop and date store setup(Uncopylocked) Inventory Data Store Test Place
Use the name of the item as the name to save Make it an IntValue and use the value as the number of the item
The way I did it a while ago since I had multiple things to save for the item was placing values inside of the item and saving/loading those
Example for #2
This will save all the values into a table and then load them 1 by 1 into your inventory folder
It automatically saves every 300 seconds with a 30 second delay between players
I am not very good at coding so I'm sure there are more efficient ways but this is my way of doing it
local DSS = game:GetService("DataStoreService") local set = "example1" local invds = DSS:GetDataStore("inventory"..set) game.Players.PlayerAdded:connect(function(player) local key = tostring(player.UserId..set) local inventory = Instance.new("Folder", player) inventory.Name = "inventory" if invds:GetAsync(key) ~= nil then local tablea1 = invds:GetAsync(key) for k,v in pairs(tablea1) do local itemname = Instance.new("StringValue",player.inventory) itemname.Name = v[1] local itemlevel = Instance.new("IntValue",itemname) itemlevel.Value = v[2] itemlevel.Name = "Level" local itemamount = Instance.new("IntValue",itemname) itemamount.Value = v[3] itemamount.Name = "Amount" end else local iddata = {} invds:SetAsync(key, iddata) end end) function SaveData(player) local key = tostring(player.UserId..set) invds:UpdateAsync(key, function(OldValue) if type(OldValue) == "table" then local tablea1 = {} for k,v in pairs(player.inventory:GetChildren()) do local tabledata = {v.Name, v["Level"].Value, v["Amount"].Value} table.insert(tablea1, tabledata) end OldValue = tablea1 end return OldValue end) end game.Players.PlayerRemoving:Connect(SaveData) while wait(300) do for k,v in pairs(game.Players:GetChildren()) do wait(30) SaveData(v) end end
The short answer, with least modification to your existing system is to simply save a slightly more complex data struct. For example, instead of just saving the array of names, save a small table. So this:
items[i] = v.Name
Might become something like this:
items[i] = { name = itemName, quantity = quantityOfItem, }
How you track the quantity of the item in memory on the server is another matter. I would recommend just using a dictionary keyed with the item name. Don't make multiple copies of the actual items, that is a huge waste of memory. In fact, cloning the items into the player's inventory folder is probably already wasteful. The items probably don't need to exist until you are ready to parent them to something in Workspace or ReplicatedStorage. It's probably best to do all of this inventory stuff just in a table, and only worry about instantiating the actual items when they need to be spawned in world or at least made available to clients.
A side note, you will find a lot of examples and many inventory systems that unpack datastore data into folders of value objects. This is mostly a legacy from the times before RemoteEvents, when this was a way to get values replicated to clients. This a horribly memory-inefficient way to store simple data, equally terrible for read/write performance--recursive search of hierarchical structure where a simple O(1) dictionary could be used--and no longer a good practice for sending data server-to-client. Use tables in server Scripts, and RemoteEvents to communicate values between server and clients.