What do you want to achieve? Keep it simple and clear!
A DataStore system capable to save newly created values and load them.
What is the issue? Include screenshots / videos if possible!
The output is returning a nil table
–
What solutions have you tried so far? Did you look for solutions on the Developer Hub?
Using table.insert.
Creating new tables to save.
I tried looking around devforum but i didn’t find anything that could help me out.
INFO
So, i'm making a simple generic simulator and i'm making the pet systems right now, but i'm having trouble in saving the values created by the server whenever the player gacha a pet.
I’ve tried some solutions but none worked, the output returns a nil table, not saving any values. (Look below my code)
Code block
--//Services//
local DSS = game:GetService("DataStoreService")
--//DataStoreInfo
local PetsStore = DSS:GetDataStore("PetsDS_0.0.1c")
--//DataStoreSystem
local Data = {}
local PetData = {}
local PetInventory = {}
game.Players.PlayerAdded:Connect(function(Player)
local success, PD = pcall(PetsStore.GetAsync, PetsStore, Player.UserId)
print("A Data ta funcionando | "..tostring(success))
Data[Player.Name] = {}
PetData[Player.Name] = {}
PetInventory[Player.Name] = {}
local CurrentPlayerData = Data[Player.Name]
local CurrentPetData = PetData[Player.Name]
local CurrentPetInventory = PetInventory[Player.Name]
if success then
print("Data Pets | ", PD)
local PETData = Instance.new("Folder")
PETData.Name = "PetData"
PETData.Parent = Player
local PETInventory = Instance.new("Folder")
PETInventory.Name = "PetInventory"
PETInventory.Parent = Player:WaitForChild("PetData")
local SelectedPet = Instance.new("StringValue")
SelectedPet.Name = "SelectedPet"
SelectedPet.Parent = Player:WaitForChild("PetData")
SelectedPet.Value = PD and PD.SelectedPet or 0
for _,v in PETData:GetChildren() do
if v:IsA("StringValue") then
CurrentPetData[v.Name] = v.Value
end
end
for _,v in PETInventory:GetChildren() do
CurrentPetInventory[v.Name] = v.Value
print(v.Name)
end
else
warn("Erro ao carregar a DataStore de pets")
end
end)
local function SaveData(player)
local CurrentPlayerData = Data[player.Name]
local CurrentPetData = PetData[player.Name]
local CurrentPetInventory = PetInventory[player.Name]
for _,v in player:WaitForChild("PetData"):GetChildren() do
if v:IsA("StringValue") then
CurrentPetData[v.Name] = v.Value
end
end
for _,v in player:WaitForChild("PetData"):WaitForChild("PetInventory"):GetChildren() do
CurrentPetInventory[v.Name] = v.Value
end
local success, PD = pcall(function()
PetsStore:SetAsync(player.UserId, CurrentPlayerData)
PetsStore:SetAsync(player.UserId, CurrentPetData)
PetsStore:SetAsync(player.UserId, CurrentPetInventory)
end)
end
--//Saving when player leaves
game.Players.PlayerRemoving:Connect(function(Player)
SaveData(Player)
end)
--//Saving when the game is shutdown
game:BindToClose(function()
for _,v in game.Players:GetPlayers() do
SaveData(v)
end
end)
If you need more info, just ask below, i’ll be trying my best to answer you clearly.
In this little section here, you are effectively only saving CurrentPetInventory.
As soon as CurrentPetData and CurrentPlayerData was saved, they were both overwritten, as if they had never been saved in the first place
Yeah, basically it saves the last thing which is CurrentPetInventory because you can’t really save more than 1 table in DataStores I guess. So it overwrites the things you saved above.
I know this won’t solve your specific issue, but word of advice:
You should autosave DataStore data every now and then. Like, every 5 minutes or so. Because you can never know if the server crashes by chance and the player loses their data, so it’s best to stay on the safe side
Edit: The point they’re trying to make is, you’re setting the same value twice, overwriting th contents.
local PD = {
CurrentPlayerData = CurrentPlayerData,
CurrentPetData = CurrentPetData,
CurrentPetInventory = CurrentPetInventory
}
local success, info = pcall(PetStore.SetAync, PetStore, Player.UserId, PD)
if not success then
warn("Failed to save player data for" .. Player.Name)
end
I also notice that at the top, when you load the data, you never use it. Make sure to grab the values from PD with the GetAsync statement and use it.
I apologize for double-posting but just wanted to mention that I updated my previous comment to be more helpful and explain what PoppyandNeivaarecute has said.
First, you were using the data stores wrong as others said.
But to do what you wanted, you would need to loop through the PetInventory folder, put it in a table, and save it with the datastore, and on load, loop on it and create the StringValues with the information you saved.
Like this:
-- On Save
local petInventory = {}
for i, obj in petInventoryFolder:GetChildren() do
petInventory[obj.Name] = obj.Value
end
pcall(datastore.SetAsync, datastore, player.UserId, {PetInventory = petInventory})
-- On Load
local success, result = pcall(datastore.GetAsync, datastore, player.UserId)
if success then
-- create folders
if not result or result.PetInventory then return end -- if no pet inventory, cancel
for name, val in result.PetInventory do
local value = Instance.new("StringValue")
value.Name = name
value.Value = val
value.Parent = petInventoryFolder
end
end
That would allow doing what you want, that is saving and loading the StringValues, i would recommend using Attributes too in the future since they are very versatile and do not need to create values for any object.