Datastore Issue

Hello, so pretty, the datastores need to save a bunch of values.

In replicated storage, there are a few values that need to be saved for the next session, but these values are only set on the client side as these values only affect a players experience (render distance functionality, etc).
So, whenever the player clicks the “Save” button, it sends a table containing all of the values to the RemoteEvent to a server script and then it successfully saves everything.

But the problem is when you actually load into the game, so when you load into the game, a server script detects that you have joined the game and collects all of the data. And then it sends all of that data through the RemoteEvent again to a local script and sets everything in Replicated Storage. The thing is, it keeps saying that it is nil and I’m not exactly so sure why.

When you join the game, it loads

	local passed, failed = pcall(function()
		local data
		data = SavingSettings:GetAsync(Player.UserId.."-Settings")
		
		if data ~= nil then
			game.ReplicatedStorage.SavingData:FireClient(Player, data)
		end
	end)
	
end)

If a player has pressed the save button

game.ReplicatedStorage.SavingData.OnServerEvent:Connect(function(Player, data)
	local passed, failed = pcall(function()
		SavingSettings:SetAsync(Player.UserId.."-Settings", data)
		print(data)
	end)
	if passed then
		print("saved")
	end
end)

If a player has joined the game and it loads to lead their data (this is where the problem occurs)

	game.ReplicatedStorage.SavingData.OnClientEvent:Connect(function(Player, Data)
	for order, values in pairs(game.ReplicatedStorage:GetDescendants()) do
		for dataorder, datavalue in pairs(Data) do
			if dataorder == order then
				values.Value = datavalue.Value
			end
		end
	end
end)

Help would be greatly appreciated, thanks :slight_smile:

Hello! There doesn’t seem to be issues in these scripts so could you send the local script containing the code that collects the data and sends it to the server when he clicks the save button.
Also… if you rely on the client to send the data to be saved this can easily be used by an exploiter to give the self lots of money (or whatever you are saving).

No worries

GUI.Options.Save.MouseButton1Click:Connect(function()

		
		local SendData = {}
		
		for order, Data in pairs(ReplicatedFirst.SettingsData:GetDescendants()) do
			if Data:IsA('ValueBase') then
				table.insert(SendData,Data.Value)
			end

		end
		
		print(SendData)
		game.ReplicatedStorage.SavingData:FireServer(SendData)
end)

By the way, what I’m saving is just settings that make a game better fit for the user. Like the music choice, render distance, enable/disable shadows and more stuff that would not be worth your time to exploit.

What exactly is the full error message?

Do you already have a different datastore Async in this game? For anything separate from this that is.

Nope, I only have one at the moment only.

Alright, well the error seems to be an issue with going through a table. Can you send the script called “GUIScript” under MenuGUI if you haven’t already.

Do you need the entire gui script?

Also I think I’ve already sent it, it’s the Save button above.

If its too long just send the relative area in question and direct me to line 46.

Line 46 is in my original message, it contains the for i v pairs and it’s the one that is triggered by a remote event fired to a client.

Which line is 46,

for order, values in pairs(game.ReplicatedStorage:GetDescendants()) do
or
for dataorder, datavalue in pairs(Data) do

Also I’m not sure how you are storing this but are you using :GetDescendants() on the entirety of ReplicatedStorage by mistake or is that temporary?

It’s no mistake, there are folders in ReplicatedStorage, and there are more folders in replicatedstorage to not only sort out settings, but just stuff in the game.

And also, I think I just realised a mistake, since there are also folders in replicatedstorage, I’m also trying to set the values of the folders as well, I’ll fix that right away.

And I just realised that the remoteEvents are in replicatedstorage, the actual settings are in replicatedfirst.

Keep in mind as well that :GetDescendants() is pretty costly on performance if you have a lot in that spot and the more you expand your game you should expect ReplicatedStorage to fill up a lot. I’d suggest storing all the settings values in a single folder and using :GetDescendants() on that specific folder only.

Thanks for the advice, I’ll do that right now.

Also could you answer this question for which specific in pairs is line 46?

(Wrong Reply My Bad)

Also could you answer this question for which specific in pairs is line 46?

It’s the “for dataorder, datavalue in pairs(Data) do”

Sorry I didn’t answer it before.

It sounds like “Data” isn’t being specified correctly when it is sent. Can you send the full script on top? All You posted was this:

	local passed, failed = pcall(function()
		local data
		data = SavingSettings:GetAsync(Player.UserId.."-Settings")
		
		if data ~= nil then
			game.ReplicatedStorage.SavingData:FireClient(Player, data)
		end
	end)
	
end)

That’s the only part of the code in the script that actually does the data, the rest is just when the player joins the game it teams them and other stuff that doesn’t relate to the data. And also, the variable, “data” is not supposed to be sent if it is nil like you can see.