Tool Saving Problem

Hello again

I want to make a tool saving system, I’ve been trying for hours but it does not work.

  1. “ToolsToSave” variable stores the tools successfully, but “LoadedToolData” is nil

I tried searching, sent a post yesterday which fixed it, but i cant fix this one.

Script:

local DS = game:GetService("DataStoreService")

local ToolDataStore = DS:GetDataStore("Tools")

local ServerToolsFolder = game:GetService("ServerStorage"):WaitForChild("ToolsFolder")

game.Players.PlayerAdded:Connect(function(plr)
	
	local LoadedToolData = ToolDataStore:GetAsync(plr.UserId.."-ToolData")
	
	local Backpack = plr:WaitForChild("Backpack")
	
	local StarterGear = plr:WaitForChild("StarterGear")
	
	print(LoadedToolData) --**This is nil** 
	
	if LoadedToolData ~= nil then
		for i,v in pairs(LoadedToolData) do
			if ServerToolsFolder:FindFirstChild(v) then
				local Clone = ServerToolsFolder:FindFirstChild(v):Clone()
				Clone.Parent = Backpack
				local Clone = ServerToolsFolder:FindFirstChild(v):Clone()
				Clone.Parent = StarterGear
			end
		end
	end
end)

game.Players.PlayerRemoving:Connect(function(plr)
	
	local char = plr.Character
	if not char then return end
	
	local hum = char:FindFirstChild("Humanoid")
	if not hum then return end
	
	hum:UnequipTools()
	
	local Backpack = plr.Backpack
	
	local ToolsToSave = {}
	
	for i,v in pairs(Backpack:GetChildren()) do
		ToolsToSave[#ToolsToSave+1] = v.Name
	end
	
	print(ToolsToSave) --**This is working**
	
	ToolDataStore:SetAsync(plr.UserId.."-ToolData",ToolsToSave)
end)

if game:GetService("RunService"):IsServer() then
	game:BindToClose(function()
		task.wait(3)
	end)
end

game.Players:GetPlayerFromCharacter()

The values you retrieve using GetAsync() sometimes can be out of sync with the backend due to the caching behavior.

To opt out of using the cache to retrieve the most up-to-date value from the servers, add the DataStoreGetOptions parameter to your GetAsync() call and set its UseCache property to false to make your request ignore any keys in the cache.

Disabling caching is useful if you have multiple servers writing to a key with high frequency and need to get the latest value from servers. However, it can cause you to consume more of your data stores limits and quotas, since GetAsync() requests bypassing caching always count towards your throughput and server limits.

1 Like

Thanks but it did not help… :frowning:

Try testing out your system in a real Roblox server. Datastores don’t save in studio and can mess up a lot too.

Make sure you have api access turned on

If I understood correctly you are trying to like “copy” the folder from ServerStorage to the player itself and then save the data it’s containing.

local DS = game:GetService("DataStoreService")

local ToolDataStore = DS:GetDataStore("Tools")

local ServerToolsFolder = game:GetService("ServerStorage"):WaitForChild("ToolsFolder")

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

	local success, value = pcall(ToolDataStore.GetAsync, ToolDataStore, plr.UserId)
	if success == false then plr:Kick("DataStore failed") end
	
	local Backpack = plr:WaitForChild("Backpack")

	local StarterGear = plr:WaitForChild("StarterGear")

    local data = value or {}
	print(data) --**This is nil** 

	if data == nil then
		local folder_clone = Instance.new("Folder")
		folder_clone.Name = "PlayerTools"
		for i, tool in ServerToolsFolder:GetChildren() do
			local clone = tool:Clone()
			clone.Parent = folder_clone
		end
		folder_clone.Parent = plr
	end
	
	for i,v in next, data do
		v.Parent = plr.Backpack
	end
end)

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

	local data = {}
	
	for i, tool in ServerToolsFolder:GetChildren() do
		for i, player_tool in plr.Backpack:GetChildren() do
			assert(tool==player_tool, "Error occured")
			data[tool.Name] = player_tool
		end
	end

	local success, value = pcall(ToolDataStore.SetAsync, ToolDataStore, plr.UserId, data)
	print("Saved -> ", data)
end)

game:BindToClose(function()
	for i, plr in game:GetService("Players"):GetPlayers() do
		local data = {}

		for i, tool in ServerToolsFolder:GetChildren() do
			for i, player_tool in plr.Backpack:GetChildren() do
				assert(tool==player_tool, "Error occured")
				data[tool.Name] = player_tool
			end
		end

		local success, value = pcall(ToolDataStore.SetAsync, ToolDataStore, plr.UserId, data)
		print("Saved -> ", data)
	end
end)

And like @Msgme_4issues said make sure you have the Api turned on (Game settings → Security → Enable Studio Access to Api Services).

AND ALSO I wanna clear out that by using StarterGear in this kind of a script is kind of an unnecessary. StarterGear is ONLY and ONLY for Studio configurations when the tools are going to clone into the players backback without any DataStore.

I did all the things you guys said but it does not work for some reason

Oh, Its supposed to get the all tools names in backpack and save them as a table before leaving.
Then its supposed to loop through the saved table. Then clone the tools to the players backpack, If it finds the tools name in the Folder which stores tools

I followed a tutorial and it said something about StarterGear so i added it lol

Maybe because in the 2 dimension loop found in the .PlayerRemoving I did a little typo. Anyway, fixed from now on.