Hello, I have been struggling to save an array/table to the DataStoreService. I am attempting to store various strings into the array, these strings come from a folder I created named “inventory.”
An example of this can be seen here:
Strangely the “inventory” folder appears to be emptied before saving for some reason. I verified this by printing the number of elements on “inventory” which oddly output zero (meaning “inventory” was empty). I also printed out the folder “leaderstats” where I am storing other information that is also meant to be saved and is successfully doing so. I left both print statements on and you can see the results in m output below:
I verified my game does not have any other scripts deleting the contents of the “inventory” folder. So at this point, I am fairly confused as to what may be causing this.
You may see the code below:
local DataStoreService = game:GetService("DataStoreService")
local inventoryDatastore = DataStoreService:GetDataStore("inventorySave")
local function equipAccessory(player, accessory)
local character = player.Character
if accessory ~= nil and character ~= nil then
--local accessory = game.ReplicatedStorage.Hats.Crown
accessory:Clone().Parent = player.Character
print("Equipping cloned "..accessory.Name)
end
end
game.Players.PlayerAdded:Connect(function(player)
local inventory = Instance.new("Folder")
inventory.Name = "inventory"
inventory.Parent = player
pcall(function()
local accessoryData = inventoryDatastore:GetAsync("UserInventory-"..player.UserId) --Array type
print(player.Name.."'s accessory data: "..typeof(accessoryData))--..accessoryData)
if accessoryData then
for i,v in pairs(accessoryData) do
local accessoryFound = game.ReplicatedStorage.Accessories:FindFirstChild(v)
if accessoryFound then
print("Load item - i: "..i.." v: "..v)
local temp = Instance.new("StringValue")
temp.Name = v
temp.Parent = inventory
game.ReplicatedStorage.RemoteEvents.AddAccessoryToInventory2:FireClient(temp) --Adding every item to the frame...
end
end
game.ReplicatedStorage.RemoteEvents.SendData:FireClient(player, accessoryData)
print("Fired sendData!")
else
print("No data found, must be a new player or something happened to the data")
end
end)
end)
--Saving Data for Leaving Players/Closing Server
local function saveData(player)
print(player.Name.." leaving and saving their data...")
if player:FindFirstChild("inventory") then
local accessorySave = {} --To be used as an array
local test1 = player.inventory:GetChildren()
local test2 = player.leaderstats:GetChildren()
print("Num of elements in inventory: "..#test1)
print("Num of elements in leaderstats: "..#test2)
for _,v in pairs(player.inventory:GetChildren()) do
print("Insert item - i: ")--..i.." acc: "..v.Name)
table.insert(accessorySave,v.Name)
end
local success, errorMessage = pcall(function()
inventoryDatastore:SetAsync("UserInventory-"..player.UserId, accessorySave) --Save
end)
if success then
print(accessorySave)
print(player.Name.."'s Accessory Inventory Saved!")
else
print("Error: "..errorMessage)
end
end
end
game:BindToClose(function()
for i, player in pairs(game.Players:GetPlayers()) do
saveData(player)
end
end)
game.Players.PlayerRemoving:Connect(function(player)
saveData(player)
end)
--Remote Events
game.ReplicatedStorage.RemoteEvents.EquipAccessory.OnServerEvent:Connect(function(player,accessoryName)
local accessory = game.ReplicatedStorage.Accessories:FindFirstChild(accessoryName)
-- Only let players Equip accessories they own
if not player.inventory:FindFirstChild(accessoryName) then
equipAccessory(player, accessory)
end
end)
game.ReplicatedStorage.RemoteEvents.UnequipAccessory.OnServerEvent:Connect(function(player,accessoryName)
if player.Character:FindFirstChild(accessoryName) then
player.Character:FindFirstChild(accessoryName):Destroy()
end
end)
Any ideas as to why this might happen or how to fix this?
saveData is called when the player leaves the server. The problem could be, that when the player leaves the server, their folders are removed along with their player from “players”, before the function is called. So, the function won’t be able to find the folder because it got removed along with the player.
Try to print player.inventory in saveData
Edit: I read about the PlayerRemoving event a little, and it seems that it’s called right before the actual player is removed, so it may be that I am wrong, but it would still help if you print the player.inventory, so that we know whether player.inventory exists at the time when the function is called.
A possible solution that I would try would be moving saveData function into the game.Players.PlayerRemoving:Connect(function(player)
end)
So that would look something like this
game.Players.PlayerRemoving:Connect(function(player)
print(player.Name.." leaving and saving their data...")
if player:FindFirstChild("inventory") then
local accessorySave = {} --To be used as an array
local test1 = player.inventory:GetChildren()
local test2 = player.leaderstats:GetChildren()
print("Num of elements in inventory: "..#test1)
print("Num of elements in leaderstats: "..#test2)
for _,v in pairs(player.inventory:GetChildren()) do
print("Insert item - i: ")--..i.." acc: "..v.Name)
table.insert(accessorySave,v.Name)
end
local success, errorMessage = pcall(function()
inventoryDatastore:SetAsync("UserInventory-"..player.UserId, accessorySave) --Save
end)
if success then
print(accessorySave)
print(player.Name.."'s Accessory Inventory Saved!")
else
print("Error: "..errorMessage)
end
end
end)
It is possible that the function is called before the player is removed, but it probably runs after the player is removed.
I know OOP, that particular error does not concern me. I expect that since the data I am trying to store is disappearing/sending multiple empty requests to store nothing. I appreciate the help none the less.
Your suggestion is exactly what my code is doing already. The function call is the equivalent of moving all the data to “game.Players.PlayerRemoving” as your suggestion shows so it won’t do anything. Anyway, I did that for good measure and it did not make any changes. I appreciate the help though.