DataStore loading data to WRONG value!

just skip to the bottom if you cant be bothered reading lol

I’m currently working on a shop in my game where players purchase items such as hats and hairs in-game. I’m trying to organize these and save them into a table. (which I think is probably the best way of doing it instead of sending like tones of data store reqs)

This is what the items look like:
image

each player gets this loaded into them containing bool values for all the items and an attribute called Equipped which also saves. They are created by looping through the folder shown before and creating a new folder for the categories and a new value for the item. The value is checked if they own it and the equipped is checked when they equip it in the menu.

image

SAVING

Here is how I save the data, which runs on PlayerRemoved (and BindToClose). It loops through all the values in the Accesories folder in the player, checks if they are a value and not a category folder and then adds the value and equipped value to a table then that table is added to a bigger table.

function save(player) -- save player data
	local folder = player:FindFirstChild("Accessories")
	local save = {}

	for index, value in pairs(folder:GetDescendants()) do -- loop through values
		if value:IsA("ValueBase") then
			local tbl = {} -- load data into table
			tbl.Value = value.Value
			tbl.Equipped = value:GetAttribute("Equipped") or false
			
			table.insert(save, #save + 1, tbl) -- load table into main save table
		end
	end
	
    print(save)
	local success, err = pcall(function()
		dataStore:SetAsync(player.UserId, save) -- save table to datastore
	end)
end

That save table will end up looking something like this with all the values:

▼  { -- main table (called Save(
    [1] =  ▼  { -- one table for each item
       ["Equipped"] = false, -- if item is equipped
       ["Value"] = false -- owned
                    },
    [2] =  ▶ {...},
    [3] =  ▶ {...} -- so 3 items in total
    -- etc etc...

LOADING

When the player loads into the game, this is what happens, and this is where I think the problem occurs. Ready carefully.

players.PlayerAdded:Connect(function(player)	
	local folder = Instance.new("Folder") -- make folder for the categories
	folder.Name = "Accessories"
	folder.Parent = player
	
	-- create values
	for _, category in pairs(shopItems:GetChildren()) do -- loop through that folder wt the items
		local categoryFolder = Instance.new("Folder") -- create a folder for that category inside the player
		categoryFolder.Name = category.Name
		
		for index, val in pairs(category:GetChildren()) do -- get all items inside category
			local value = Instance.new("BoolValue") -- create value for each item and parent inside of created category folder
			value:SetAttribute("Equipped", false)
			value.Name = val.Name
			value.Parent = categoryFolder
		end
		
		categoryFolder.Parent = folder -- parent each category folder into the main accessories folder
	end
	
	-- load data
	local stats = dataStore:GetAsync(player.UserId) -- get data from datastore
	print(stats)

	for index, value in pairs(folder:GetDescendants()) do -- load through accessories folder
		if not value:IsA("ValueBase") then continue end -- check if it is not a category folder
		
		-- keep in mind, stats[index] is a table shown before containing 2 values, Value and Equipped.
		
		if stats ~= nil and stats[index] ~= nil then -- if the player has data for that index (that is the number of the iteration)
			value.Value = stats[index].Value or false -- set the value to the saved data value
			value:SetAttribute("Equipped", stats[index].Equipped) -- do the same for  equipped value
			
			print("Set value "..value.Name.." to "..tostring(stats[index].Value).." "..tostring(stats[index].Equipped))
		else
			value.Value = false
			value:SetAttribute("Equipped", false) -- if they have no data set to the defaults false and false
			
			print("Set value "..value.Name.." to false false")
		end
	end
end)

THE PROBLEM
I think is with the for loop. It loops through all of the descendants of this folder called Accessories as shown before.

image

But it skips the folder meaning it goes up one more index thing because its checking if it is not a folder.

if not value:IsA("ValueBase") then continue end -- check if it is not a category folder

This makes all of the index number the wrong number aswell because in the saving system, it puts the values into a table and the index for those are 1, 2, 3 etc but for this the index 1 or 2 or 3 could be a folder so it skips it. Meaning that the index could be 4 even though in the table it is actually 3 but the folder caused it to skip 1.

I don’t think its just the folders causing the problem though it could be because of different values being in different folders.

For example, lets set HairTest and HatTest to true, everything else is false!

image

Now lets rejoin and you can see now this table here which is the same as the image above with the folders and boolvalues just in a table, prints all the data correctly.

image

But this prints the index and what it set the values to.

image

It prints the value and then the equipped value but lets just worry about the value atm.

On the first line it prints 2 because 1 would have been one of the folders so the loop skipped it, and in the table it says that the data for 2 is false, so it sets it to false. Even though it should be true according to the table above, but because it skipped that folder, the index is 2.

Same with the 4, it should be true but was set to 3 which is false, because again it skipped 1 because of the category folder.

And no I cant really just do index = index - 1 because in other cases there could be 2 skipped folders in a row or something etc it wouldn’t work.

In other cases I have tried changing other values and it set the wrong values for the wrong thing. Bassically I’m trying to figure out how to get the right item from the table. And I’ve tried using names for it but if I change the name or if two things have the same name the data is lost.

TLDR

Data not saving to correct values because the loop skips the folder, just read it lol.

Thanks. Comment for anymore info.

1 Like

sorry, still looking for solutions on this lol

Before this line in your loading you can do:

local index = 0
for _, value in pairs(folder:GetDescendants()) do
   if not value:IsA("ValueBase") then continue end
   index += 1
   ...

This way your index only increases when a valid child has been found and keeps everything in order.

1 Like

This way you create minimal edit without touching anything else.

Lol I did this before and it wasn’t working and I think it’s because I still had the index variable in the for loop so it must have overridden it. Wasn’t expecting a simple fix like this, I should check better for something like that lol. Thanks, I’ll let you know if something happens again.

image

1 Like

Yes it definitely overwrote your initial definition thereafter but good documentation in your issue request. You put everything needed so no questions had to be asked lol very helpful in helping

1 Like