For Loops won't run while saving things to a data store?

So I have a folder in ReplicatedStorage named Whackers and I wanted to save some values from that into a data store and I have a print() function in the loop, but it never prints anything so I was wondering if for loops just don’t run when saving to a data store?

Here is my code:

game.Players.PlayerRemoving:Connect(function(player)
	
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(player.UserId.."-cash", player.leaderstats.Coins.Value)
		
		
	end)
	
	
	if success then
		for i,v in pairs(game.ReplicatedStorage.Whackers:GetChildren()) do
			myDataStore:SetAsync(player.UserId.."-"..v.Name, player.DataFolder:FindFirstChild(v.Name.."_Id").Value)
			print(player.UserId.."-"..v.Name, player.DataFolder:FindFirstChild(v.Name.."_Id").Value)
		end
		print("Player data successfully saved!")
	else
		print("There was an error when saving data")
		warn(errormessage)
	end
end)

Please do not ask people to write entire scripts or design entire systems for you. If you can’t answer the three questions above, you should probably pick a different category.

If you are testing it in studio the studio session may shut down faster than the player removing function can fire. Add a game:BindToClose in your script and just have a wait 3 seconds in the bind to close function.

for loops will always run when saving data. There is nothing preventing them from doing that. Like DarkDanny04 said, the playtest server is likely closing before the for loop is run. Try running a local server with 2 players so it stays open once you have one of the players leave.
I will say this system is quite inefficient, as setting more than 1 datastore key isn’t really needed since you have 4mb of available space to work with. Because you’re setting more than one datastore key for each plater, your datastore queue will fill up quickly.

What do you mean by my system is inefficient and setting more than 1 datastore key isn’t really needed? I’m am quite new to saving stuff to a datastore and I have one key which is the player’s id then “-cash” for their cash then a system where it creates more keys (I am guessing that is what they are called) which saves the value if the player has them or not.

I am not quite sure this is the issue. I made a function and put all the saving stuff in there but then I get the error “BindToClose failed because the model is already closing.” Also if I don’t change the value I am saving in the game then it does the loop, but if I change it nothing runs.

Why can’t you just use a dictionary to store all the values, saving multiple items to different keys is pretty inefficient as @Styre_x pointed out.

You could do something like this.

local ReplicatedStorage = game:GetService("ReplicatedStorage") — always use GetService to grab services
local whackerValues = {}

for _, v in in ipairs(ReplicatedStorage.Whackers:GetChildren()) do
   whackerValues[v.Name] = v.Value
end

— save the values to the data store
PlayerData:UpdateAsync(player.UserId.."-whackers", function() — UpdateAsync is the canonical way to save data, go read up on it.
   return whackerValues — save the values to the data store.
end)

1 Like

This is something similar to what I tried before but I didn’t understand what I was doing but this looks like I can understand. My other question is how would I go about loading the items to the player whenever they join?

Edit: Also I just tried putting this in the code and data store cannot be store Dictionaries.

DataStores can store dictionaries, I do a system like this in all of my newer DataStores.

1 Like

You could try something like

game:GetService("Players").PlayerAdded:Connect(function(player)
     local success, output = pcall(function()
         return PlayerData:GetAsync(player.UserId .. "-cash")
     end)
     
     if success then
        if output ~= nil then
            -- code here
        end
     else
        warn("Unable to retrieve data")
     end
end)

but it gave me an error saying “Cannot store dictionary in data store. Data stores can only accept valid UTF-8 characters”

What kinds of names and values are being stored?

for k, v in pairs(whackerValues) do
    print(k, v) — what does the output look like after the loop?
end

I put print(myDataStore:GetAsync(player.UserId…“whackers”)) and the output is for some reason “table: 0x66c4756d68f40327”

That’s the hexadecimal for the table

So how would I return the values of the table rather than whatever the hek that is?

For example

local myTable = {
    x = 10
}

print(myTable.x) -- 10

Basically to get the values from the table, you have to search the table for the requested index (I can’t of an easier way to explain it)

or

local myTable = {
    x = 10,
    y = 20
}

for i, v in pairs(myTable) do
   print(i, v)
end

Like @xKaihatsu did

So I tried this:

local whackerValues = {}
	
	for _, v in ipairs(game.ReplicatedStorage.Whackers:GetChildren()) do
		whackerValues[v.Name] = v.Name
		
	end
	
	local success, errormessage = pcall(function()
		myDataStore:SetAsync(player.UserId.."-cash", player.leaderstats.Coins.Value)
		
		myDataStore:UpdateAsync(player.UserId.."-whackers", function()
			for i,v in pairs(whackerValues) do
				return whackerValues.v
			end
			
		end)
		print(myDataStore:GetAsync(player.UserId.."-whackers"))
	end) 

And the output of the print is still “table: 0xdcf7d7ea18ef0e97”

Try this instead

local whackerValues = {}
	
for _, v in ipairs(game.ReplicatedStorage.Whackers:GetChildren()) do
	whackerValues[v.Name] = v.Name
end
	
local success, errormessage = pcall(function()
	myDataStore:SetAsync(player.UserId.."-cash", player.leaderstats.Coins.Value)
		
	myDataStore:UpdateAsync(player.UserId.."-whackers", function(oldValue)
        local newWhackerValue = oldValue or {}

		for i,v in pairs(whackerValues) do
			newWhackerValue[i] = v
		end
		
        return newWhackerValue
	end)

	for k, v in pairs(myDataStore:GetAsync(player.UserId.."-whackers")) do
       print(k, v)
    end
end) 

I tried this and it gave an error for the “For k, v in pairs” section and it says "missing argument #1 to ‘pairs’(table expected) so I guess you can’t look through the pairs in the data store?

It might be because DataStore:GetAsync() yields.Try replacing the old “for k, v” with this

local Data = myDataStore:GetAsync(player.UserId.."-whackers")

for k, v in pairs(Data) do
   print(k, v)
end

Or try

local Data = myDataStore:GetAsync(player.UserId.."-whackers")
print(tostring(Data))

If it returns nil then it’s because there’s no data

Oh wow it actually prints the name of the tools, but it prints it twice so thanks for the absolutely massive help!

but I have one more question:
How would I load the tools from this data store when the player joins?

1 Like