Hi, I’m trying to save a folder full of values with a Datastore. An example of what I’m trying to do is like an inventory. There’s about 10 items and I want to save the amount of that item the player has for all 10 of those items.
The issue is, I don’t know how to do that.
I’ve tried using a module script to make a function to update the amount the player has but I’m not sure how I’d get the amount for every one of those items and be able to save the amount to those designated items amount values.
local ds = game:GetService("DataStoreService")
local store = ds:GetDataStore("DataStoreNameHere")
local function save(player)
local folder = --folder path here
local items = {}
--this is assuming all the items within the folder are BoolValues, and the value would be true if it is owned.
for _, item in pairs(folder) do
if item.Value == true then
table.insert(items, item.Name)
end
end
local playerData = {
["Inventory"] = items
}
local success, err = pcall(function()
store:SetAsync(dataKey, playerData) --where 'dataKey' is the key you use to access the DataStoreService
end)
end
game.Players.PlayerRemoving:Connect(save)
The first value is a StringValue, containing the item name as the value. There are 2 IntValues inside of the StringValue that are named “Rarity” and “Amount”. I’m trying to save and load the Amount.Value for all of those StringValues, but I’m not sure how.
Just want to make sure I got it right before I write any code, so you don’t want to save anything else other than the Amount for each string value? Do you want to save the StringValue’s item name as well?
I don’t have to because I’ve made a folder in ReplicatedStorage of the folder with all of the StringValues and their children. When the player joins the game, a script will clone that folder and parent it to the player. So I am only assigning the “Amount” value as of now.
Ok, but you might want to save the name of the item as well, so that you know what value is for what item when you load the data.
local ds = game:GetService("DataStoreService")
local store = ds:GetDataStore("DataStoreNameHere")
local folder = nil --path to folder within the player
local items = {}
for _, item in pairs(folder) do
local assignItem = {
[item.Name] = {
["AmountOwned"] = item.Amount.Value
}
}
table.insert(items, assignItem)
end
local key = "DataSavingKeyHere"
local success, err = pcall(function()
store:SetAsync(key, items)
end)
Quick question, if I were to have an autosave feature, would I need to do table.clear(items) before re-inserting new values? (Since there would already be items in the table)
Well, presuming that script I sent above would be used on the PlayerRemoving event, and you are using SetAsync() and not UpdateAsync(), you wouldn’t need to. Just use that same code again.
--autosaves every 5 minutes
while task.wait(300) do
local folder = nil --path to folder within the player
local items = {}
for _, item in pairs(folder) do
local assignItem = {
[item.Name] = {
["AmountOwned"] = item.Amount.Value
}
}
table.insert(items, assignItem)
end
local key = "DataSavingKeyHere"
local success, err = pcall(function()
store:SetAsync(key, items)
end)
end
The only trouble would be with UpdateAsync(), because that reads before it writes. If you use SetAsync(), you should be fine.
I have one more question… I’m trying to load the data I saved, but I’m having trouble.
This is my code to load the amount:
if data.items then
for i, v in pairs(data.items) do
local currentItem = items:FindFirstChild(v)
--
currentItem.Amount.Value = v.amount
end
end
In the above code, data is a table containing all player data, items is the folder that gets parented to the player, and data.items is the table I have the Name saved to. The Name contains the Amount .
Every time I run this code, I get the same error, it says: attempt to index nil with "Amount"
EDIT: When I print (v) I get a table that contains: {[“Common”] = { amount = 0 }}
I’m guessing local currentItem = items:FindFirstChild(v) is nil. But I’m not sure how I would get the name inside of a table that is inside of another table.
The infinite yield might not be preventing the code from running - the game might just be taking a while to load. As for accessing the “amount” key within that table:
-- Sync Items --
if data.items then
for i, v in pairs(data.items) do
print(v) --successfully prints the item in the table
local currentItem = items:WaitForChild(v) --Infinite Yield
--
currentItem.Amount.Value = v["amount"]
end
end