Hey. I made an inventory system, basically, at the beginning it loads the data the player has, and then I don’t save each time it changed, rather when they leave, I make an empty table loop through the scrolling frame and get all the instances’ name and insert them to the table, but for some reason, it won’t save the data. Here are both of my codes:
Inventory saver:
local inventoryDataStore = dataStoreService:GetDataStore("InventoryDataStoreTwo");
game:BindToClose(function()
for _, v in ipairs(game.Players:GetPlayers()) do
local userId = v.UserId;
local newTable = {};
for _, v in ipairs(v.PlayerGui.Inventory.ImageLabel.Inventory:GetChildren()) do
if not v:IsA("UIGridLayout") and not v:IsA("Script") then
table.insert(newTable, #newTable + 1, v.Name);
end
end
local succed = pcall(function()
local data = inventoryDataStore:GetAsync(userId);
if data then
inventoryDataStore:UpdateAsync(userId, function()
return newTable
end)
else
end
end)
end
end)
Inventory loader:
local dataStoreService = game:GetService("DataStoreService");
local dataStore = dataStoreService:GetDataStore("InventoryDataStoreTwo");
local function load()
local succed = pcall(function()
local player = script.Parent.Parent.Parent.Parent.Parent;
local data = dataStore:GetAsync(player.UserId);
if data then
for _, v in ipairs(data) do
local templateClone = script.Template:Clone();
templateClone.Parent = script.Parent
templateClone.Name = tostring(v)
end
else
local freeItems = {"Taco"};
for _, v in ipairs(freeItems) do
local templateClone = script.Template:Clone();
templateClone.Parent = script.Parent
templateClone.Name = tostring(v)
end
end
end)
end;
load()
local table = {"item1", "item2", "item3"}
local http = game:GetService("HttpService")
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("DataStore")
function save(player, tbl) -- Takes a player object and a table
if not tbl then return end
local ntbl = http:JSONEncode(tbl)
local s,f = pcall(function()
ds:UpdateAsync(player.UserId, ntbl)
end)
if f then
print(f)
end
end
also, I noticed that you only save when the game closes, this means that if there is more than one player in the server, when they leave their data will not be saved. You can fix this using
local dataStoreService = game:GetService("DataStoreService");
local dataStore = dataStoreService:GetDataStore("InventoryDataStore5");
local httpService = game:GetService("HttpService");
game:BindToClose(function()
for _, v in ipairs(game.Players:GetPlayers()) do
local userId = v.UserId;
local newTable = {"Taco", "Chips"};
for _, v in ipairs(v.PlayerGui.Inventory.ImageLabel.Inventory:GetChildren()) do
if not v:IsA("UIGridLayout") and not v:IsA("Script") then
table.insert(newTable, #newTable + 1, v.Name);
end
end
local succed = pcall(function()
local data = inventoryDataStore:GetAsync(userId);
if data then
inventoryDataStore:UpdateAsync(userId, function()
return game:GetService("HttpService"):JSONEncode(newTable)
end)
else
end
end)
end
end)
And:
local dataStoreService = game:GetService("DataStoreService");
local dataStore = dataStoreService:GetDataStore("InventoryDataStore5");
local httpService = game:GetService("HttpService");
local function load()
local succed = pcall(function()
local player = script.Parent.Parent.Parent.Parent.Parent;
local data = dataStore:GetAsync(player.UserId);
if data then
for _, v in ipairs(httpService:JSONDecode(data)) do
local templateClone = script.Template:Clone();
templateClone.Parent = script.Parent
templateClone.Name = tostring(v)
end
else
local freeItems = {"Taco"};
for _, v in ipairs(freeItems) do
local templateClone = script.Template:Clone();
templateClone.Parent = script.Parent
templateClone.Name = tostring(v)
end
end
end)
end;
load()
local dss = game:GetService("DataStoreService")
local ds = dss:GetDataStore("InventoryDataStore5")
local http = game:GetService("HttpService")
function load(player)
local data
local s,f = pcall(function()
data = ds:GetAsync(player.UserId)
if not data then
-- give default
data = http:JSONEncode({"Taco", "Chips"})
end
end)
return http:JSONDecode(data)
end
function save(player,tbl)
local s,f = pcall(function()
local new = http:JSONEncode(tbl)
ds:UpdateAsync(player.UserId, function(old)
if old == new then
return old
else
return new
end
end)
if f then
print(f)
end
end
game:BindToClose(function()
local itable = {}
for i,v in pairs(game.Players:GetPlayers()) do
local itable = {}
for a,b in pairs(v.PlayerGui.Inventory.ImageLabel.Inventory:GetChildren()) do
itable[#itable+1] = b.Name
end
save(v,itable)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
local itable = {}
for a,b in pairs(v.PlayerGui.Inventory.ImageLabel.Inventory:GetChildren()) do
itable[#itable+1] = b.Name
end
save(player, itable)
end)
game.Players.PlayerAdded:Connect(function(player)
local data = load(player)
-- returns table, do load thing
end
Also, to note, tables can be directly saved without converting them to JSON strings. Roblox already does this to save them. When they’re returned using GetAsync they’re auto-decoded back.
local DataStoreService = game:GetService("DataStoreService")
local Players = game:GetService("Players")
local DataStore = DataStoreService:GetDataStore("data store name", "data store scope (if you have one)")
local function load(player) -- load data function
local success, err = pcall(function()
return DataStore:GetAsync(player.UserId) -- get the player's pre-existing data, return nil if there is none
end)
if not success then return warn (err) else return err end -- if it cannot get the player's data then it sends a warning in the output (the reason why it couldn't get the data), if it can, it returns the data (which can be nil)
end
local function save(player) -- the function the load data
local success, err = pcall(function()
DataStore:UpdateAsync(player.UserId, function(oldData)
if not oldData then return {} end -- if there is no data to update, then it will return a table by default
local newData = oldData
-- code here
return newData
end
end)
if not success then warn (err) end -- like the first check, it will send a warning in the output
end
Players.PlayerAdded:Connect(load)
Players.PLayerRemoving:Connect(save)
-- alternate for loading player data
Players.PlayerAdded:Connect(function(player)
local Playerdata = load(player)
if Playerdata then
-- code here
else
warn ("no playerdata to load")
end
end)