Tool / Inventory Saving Script Not Working

I recently followed a YT tutorial on Inventory / Tool Saving

My Code
local ds = game:GetService("DataStoreService"):GetDataStore("ToolSave")
game.Players.PlayerAdded:connect(function(plr)
 local key = "id-"..plr.userId
 pcall(function()
  local tools = ds:GetAsync(key)
  if tools then
   for i,v in pairs(tools) do
    local tool = game.ServerStorage.Tools:FindFirstChild(v)
    if tool then
     tool:Clone().Parent = plr:WaitForChild("Backpack")
     tool:Clone().Parent = plr:WaitForChild("StarterGear")
    end
   end
  end
 end)
end)
game.Players.PlayerRemoving:connect(function(plr)
 local key = "id-"..plr.userId
 pcall(function()
  local toolsToSave = {}
  for i,v in pairs(plr.Backpack:GetChildren()) do
   if v then
    table.insert(toolsToSave,v.Name)
   end
  end
  ds:SetAsync(key,toolsToSave)
 end)
end)

-Please note, I am very new to scripting, so I do not know much.
Thank You!

Your toolsToSave table is empty, insert all the players tools from their backpack or starter pack like so;

toolsToSave = {}
For i, v in pairs(plr.Backpack:GetChildren()) do
table.insert(toolsToSave, v.Name)
end

Edit: If you have anything in the backpack that is not a tool, you will want to make sure those items cannot be saved in the table or they will cause an error when the load portion tries to clone your tools.

Then continue on with your current code.

1 Like

Fixed indents, nothing else.

local ds = game:GetService("DataStoreService"):GetDataStore("ToolSave")

game.Players.PlayerAdded:connect(function(plr)
	local key = "id-"..plr.userId
	pcall(function()
		local tools = ds:GetAsync(key)
		if tools then
			for i,v in pairs(tools) do
				local tool = game.ServerStorage.Tools:FindFirstChild(v)
				if tool then
					tool:Clone().Parent = plr:WaitForChild("Backpack")
					tool:Clone().Parent = plr:WaitForChild("StarterGear")
				end
			end
		end
	end)
end)

game.Players.PlayerRemoving:connect(function(plr)
	local key = "id-"..plr.userId
	pcall(function()
		local toolsToSave = {}
		for i,v in pairs(plr.Backpack:GetChildren()) do
			if v then
				table.insert(toolsToSave,v.Name)
			end
		end
		ds:SetAsync(key,toolsToSave)
	end)
end)

Analysis:

  • pcall being incorrectly used and utilized, they always return something, more info here
  • Non-capitalized connect is no longer canon, use Connect, although both works
  • SetAsync() is risky and can lose data upon malfunction
  • Failure of saving or loading does not have any safety nets

Therefore an example of correct usage of pcall with return should be:

-- old example of mine
local success, data = pcall(function()
	return ds:GetAsync(key)
end)

-- new example
local success, data = pcall(ds.GetAsync, ds, key)
  • If a player had their tool equipped, this won’t be saved.
  • UserId is incorrectly capitalized, but userId is the deprecated version
  • A magic character was used in a string and the key may fail
1 Like

His answer is an update to your code’s efficiency and function, but not a solution to the problem you were facing. If you want other users to be able to quickly see the answer that solved the problem, please mark my answer as the solution.

It is not really an issue, but it is how the ‘mark Solved’ option is supposed to be utilized. Operatik is correct though, if you incorporate both of our answers into your code, you should see much more consistent functionality.

1 Like

Applied the new fixes.

local ds = game:GetService("DataStoreService"):GetDataStore("ToolSave")

game.Players.PlayerAdded:Connect(function(plr)
	local key = "id_" .. plr.UserId -- fixed the magic character usage
	local success, tools = pcall(ds.GetAsync, ds, key)
	
	if success then
		if tools then
			for _, toolName in pairs(tools) do
				local tool = game.ServerStorage.Tools:FindFirstChild(toolName)
				if tool then
					tool:Clone().Parent = plr:WaitForChild("Backpack")
					tool:Clone().Parent = plr:WaitForChild("StarterGear")
				end
			end
		end
	else
		-- catch the error
	end)
end)

game.Players.PlayerRemoving:Connect(function(plr)
	local key = "id_" .. plr.userId
	local toolsToSave = {}
	
	for _, tool in pairs(plr.StarterGear:GetChildren()) do
		table.insert(toolsToSave, tool.Name)
	end
	
	local success, errorMessage = pcall(function()
		ds:SetAsync(key, toolsToSave)
	end)
	
	if not success then
		-- catch error here, if saving fails
	end
end)

@Hazania I don’t think you provided the solution. I do believe you meant plr.StarterGear:GetChildren() as it is more consistent. Whatever you provided was exactly as written in the previous script.

1 Like

I didn’t see that you included the same fix as me, I did mention startpack but either works imo unless for some reason you are saving at the precise time when your tools have not been added to your character, but I can see why that could happen more than you would guess it to.

Seems we both gave the same solution, but good job adding other important tips.

1 Like

I done this from YT, i’m tryna convert to GUI saving, if is that possible?

tool do have a script that open GUI right?

1 Like

All UI that a tool previously had obviously saves but not its previous stats. You save the tool’s name and retrieve a copy of the tool the next time you join the game.

1 Like