How to make a DataStore work better

Hello everyone, I am trying to make my DataStore even better, because sometimes one tool does not save at all, and so I am trying to learn how to maybe keep trying with a pcall function to see if it would keep trying if it did not save.

local DataStore = game:GetService("DataStoreService"):GetDataStore("MyDataStore")

game.Players.PlayerAdded:Connect(function(plr)

	local data

	local success, errorMessage = pcall(function()
		data = DataStore:GetAsync(plr.UserId)
	end)
	if data ~= nil then
		for _, toolName in pairs(data) do

			local tool = game.ReplicatedStorage.ToolsSaved:FindFirstChild(toolName)

			if tool then
				local newTool = tool:Clone()
				newTool.Parent = plr.Backpack

				local newTool = tool:Clone()
				newTool.Parent = plr.StarterGear

			end
		end
	end	
end)
game.Players.PlayerRemoving:Connect(function(plr)

	local toolsTable = {}

	for _, tool in pairs(plr.Backpack:GetChildren()) do
		if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
			table.insert(toolsTable,tool.Name)
		end
	end


	local success, errorMessage = pcall(function()
		DataStore:SetAsync(plr.UserId,toolsTable)
	end)

end)

game:BindToClose(function()
	for _, plr in pairs(game.Players:GetPlayers()) do
		local toolsTable = {}

		for _, tool in pairs(plr.StarterGear:GetChildren()) do
			if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
				table.insert(toolsTable,tool.Name)
			end
		end


		local success, errorMessage = pcall(function()
			DataStore:SetAsync(plr.UserId,toolsTable)
		end)	
	end
end)

while wait(10) do --Every 30 seconds loop through all of the players (you can also change this time to anything you want)
	for i, plr in pairs (game.Players:GetChildren()) do  --loop through all of the players
		local toolsTable = {}

		for _, tool in pairs(plr.StarterGear:GetChildren()) do
			if game.ReplicatedStorage.ToolsSaved:FindFirstChild(tool.Name) then
				table.insert(toolsTable,tool.Name)
			end
		end

		local success, errorMessage = pcall(function()
			DataStore:SetAsync(plr.UserId,toolsTable)
		end)	
	end
end

You have a pcall but no means of repeating it.
Pcall catches errors but does not automatically retry the failed lines.

so while true do
-- the pcall
    if success then
        break
    end
end

or for limited number of attempts (5 in this case)

for i = 1, 5 do
-- The pcall
   if success then
      break
   end
end

I know what you mean, but I am still a little confused in a way about it. What is the pcall area? I know kind of how to replace it but not completely sure after studying it a lot.

You’ve posted this at least maybe 4 times and from what I saw you were already given advise to help. From what I picked up reading your posts is that you’re confused about how DataStores work.

Theoretically the only time you’ll run in to a problem with data not saving/loading is from user (developer) error. Roblox data outages are very rare and sometimes can restore data to a certain extent. You should touch up on how datastores work from the developer API.

These are some of your pcalls. What happens is if the code works then success will exist. If it doesn’t then you will get errormessage and success would be nil.

all you have to do is repeat it until success has a value (meaning it worked)

The problem is it is not rare for me and usually only one tool does not save, which causes the problem because it is a new tool.

Is the tool that doesn’t save the tool that the player has equipped at the time?

How do I define success, errorMessage then? do I do local success, errorMessage = Datastore:GetAsync(plr.UserId)

This could be it maybe but I can double check right now.

1 Like

Which again, is a user error. You’re not storing your data properly. I’m not trying to sound mean or anything but asking “how to make a datastore stronger” isn’t going to help you; your problem is with how you’re saving data.

This is a possibility and should be considered.

You are right I think, but I am not completely sure because I left pretty quick but every other tool except the one I was holding saved. Maybe that is the problem,.

Can all tools in your game be acquired by a shop? If so you can also save the tool to the DataStore on purchase, not when you’re leaving the game because it may be unreliable.

No not all some are accquired by a click detector for events such as that, but most are in the Shop.

I know your problem, you loop through every tool in their backpack and save it. If they have a tool equipped that tool won’t be in their character, instead it would be a child to their character.

1 Like

success is automatically assigned to based on the outcome of the pcall.
pcall attempts to run the code within it and will even return success or the errormessage it would have created.

pcall runs once.
It will return success = true when the code works
on failure success = nil and errormessage will have value.

Yes you might be true I am not completely sure but the tool I equipped just got lost for some reason which could be a coincedence. I can test again to be sure.

When tools are equipped they get parented to the character, they get moved back to the players backpack when it’s unequipped. None of his code iterates through the character to try to find an equipped tool to save.

If you need an example on using datastores, this is how I will use :GetAsync(), and the same can be applied to other datastore functions:

local function load(datastore, player, defaultValue)
	local key = tostring(player.UserId)
	local s, data
	for i=1,5 do
		s, data = pcall(datastore.GetAsync, datastore, key)
		if s then
			if data == nil then
				return defaultValue
			end
			return data
		end
	end
	if player then
		player:Kick("Error occured while loading data.")
	end
	warn("Error occured while loading data. Key: \"" .. key .. "\"")
end

That is wrong because I tried it again, and another tool I equipped was lost.

But then I would be kicking players randomly which is bad if they really like the game.