Trouble with saving newly created string values

  1. What do you want to achieve? Keep it simple and clear!
  • A DataStore system capable to save newly created values and load them.
  1. What is the issue? Include screenshots / videos if possible!
  • The output is returning a nil table
    image
  1. 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.

StringValues

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.

1 Like
local success, PD = pcall(function()
		PetsStore:SetAsync(player.UserId, CurrentPlayerData)
		PetsStore:SetAsync(player.UserId, CurrentPetData)
		PetsStore:SetAsync(player.UserId, CurrentPetInventory)
	end)

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

1 Like

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.

So, how would i do something that can store each stuff inside a table?
Like this:

savetable = {
     ["Pets"] = {
           "GGs";
           "OOps"; 
    };

   ["Equipped Pet"] = {"GGS"};
}
1 Like

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.

When you do:

PetStore:SetAsync("a","petdata")
PetStore:SetAsync("b","inventorydata")

You’re effectively doing:

PetStore["a"] = "petdata"
PetStore["a"] = "inventorydata"

print(PetData.a) -- "inventorydata"

Try this instead:

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.

Hope this helps you to understand.

1 Like

This topic was automatically closed 14 days after the last reply. New replies are no longer allowed.