Save tool when held

it saves the tools in backpack but when I hold it or equip it and leave it doesn’t save only if I don’t equip it I dpon’t know how to fix it litarilly

local ToolFolder = game:GetService("ServerStorage"):FindFirstChild("Saved")
local DataStoreService = game:GetService("DataStoreService")
local SaveData = DataStoreService:GetDataStore("SaveData")

-- Tracks currently equipped tool per player
local EquippedTools = {}

game.Players.PlayerAdded:Connect(function(Player)
	print("[JOIN] Player added:", Player.Name)

	local ToolData
	local success, err = pcall(function()
		ToolData = SaveData:GetAsync(Player.UserId)
	end)

	if success then
		print("[LOAD] Tool data found for", Player.Name, ":", ToolData)
	else
		warn("[LOAD ERROR] Failed to get data for", Player.Name, ":", err)
	end

	local Backpack = Player:WaitForChild("Backpack")
	local StarterGear = Player:WaitForChild("StarterGear")

	if ToolData then
		for _, toolName in ipairs(ToolData) do
			local Tool = ToolFolder:FindFirstChild(toolName)
			if Tool and not Backpack:FindFirstChild(toolName) and not StarterGear:FindFirstChild(toolName) then
				print("[LOAD] Giving tool to", Player.Name, ":", toolName)
				local ToolClone1 = Tool:Clone()
				local ToolClone2 = Tool:Clone()
				ToolClone1.Parent = Backpack
				ToolClone2.Parent = StarterGear
			else
				warn("[LOAD] Tool missing or already exists:", toolName)
			end
		end
	end

	Player.CharacterAdded:Connect(function(Character)
		print("[CHARACTER] Spawned for", Player.Name)
		local Humanoid = Character:WaitForChild("Humanoid")

		Humanoid.Equipped:Connect(function(Tool)
			if Tool:IsA("Tool") then
				EquippedTools[Player.UserId] = Tool.Name
				print("[EQUIPPED]", Player.Name, "equipped", Tool.Name)
			end
		end)

		Humanoid.Unequipped:Connect(function(Tool)
			if Tool:IsA("Tool") then
				if EquippedTools[Player.UserId] == Tool.Name then
					print("[UNEQUIPPED]", Player.Name, "unequipped", Tool.Name)
					EquippedTools[Player.UserId] = nil
				end
			end
		end)
	end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
	print("[LEAVE] Player is leaving:", Player.Name)

	local ToolTable = {}

	for _, Tool in ipairs(Player.Backpack:GetChildren()) do
		table.insert(ToolTable, Tool.Name)
		print("[SAVE] Tool in Backpack:", Tool.Name)
	end

	local equippedTool = EquippedTools[Player.UserId]
	if equippedTool then
		print("[SAVE] Equipped tool also being saved:", equippedTool)
		table.insert(ToolTable, equippedTool)
	end

	local success, err = pcall(function()
		SaveData:SetAsync(Player.UserId, ToolTable)
	end)

	if success then
		print("[SAVE SUCCESS] Tools saved for", Player.Name)
	else
		warn("[SAVE ERROR] Could not save tools for", Player.Name, ":", err)
	end

	EquippedTools[Player.UserId] = nil
end)

Check if the player character has a tool parented to it and also save it if so, also, I don’t know if this works but you can try casting the humanoid to unequip the tool and then iterating thro the backpack

1 Like

I tried it 2 times but it didn’t work

Plr.Character:FindFirstChildOfClass(“Tool”)

I didn’t read source code but it’s simple issue. when player hold tool, tool doesn’t exist inside backpack. so write code like Yarik said.
you need to find “tool” class object inside player character and save it

Heres the script. I recreated your script.

local ToolFolder = game:GetService("ServerStorage"):FindFirstChild("Saved")
local DataStoreService = game:GetService("DataStoreService")
local SaveData = DataStoreService:GetDataStore("SaveData")

-- Tracks currently equipped tool per player
local EquippedTools = {}

game.Players.PlayerAdded:Connect(function(Player)
	print("[JOIN] Player added:", Player.Name)

	local ToolData
	local success, err = pcall(function()
		ToolData = SaveData:GetAsync(Player.UserId)
	end)

	if success then
		print("[LOAD] Tool data found for", Player.Name, ":", ToolData)
	else
		warn("[LOAD ERROR] Failed to get data for", Player.Name, ":", err)
	end

	local Backpack = Player:WaitForChild("Backpack")
	local StarterPack = Player:WaitForChild("StarterPack")

	if ToolData then
		for _, toolName in ipairs(ToolData) do
			local Tool = ToolFolder:FindFirstChild(toolName)
			if Tool and not Backpack:FindFirstChild(toolName) and not StarterPack:FindFirstChild(toolName) then
				print("[LOAD] Giving tool to", Player.Name, ":", toolName)
				local ToolClone1 = Tool:Clone()
				local ToolClone2 = Tool:Clone()
				ToolClone1.Parent = Backpack
				ToolClone2.Parent = StarterGear
			else
				warn("[LOAD] Tool missing or already exists for " .. Player.Name .. ":", toolName)
			end
		end
	end

	Player.CharacterAdded:Connect(function(Character)
		print("[CHARACTER] Spawned for", Player.Name)
		local Humanoid = Character:WaitForChild("Humanoid")

		Humanoid.Equipped:Connect(function(Tool)
			if Tool:IsA("Tool") then
				EquippedTools[Player.UserId] = Tool.Name
				print("[EQUIPPED]", Player.Name, "equipped", Tool.Name)
			end
		end)

		Humanoid.Unequipped:Connect(function(Tool)
			if Tool:IsA("Tool") then
				-- Only set to nil if the unequipped tool was the one we tracked as equipped
				if EquippedTools[Player.UserId] == Tool.Name then
					print("[UNEQUIPPED]", Player.Name, "unequipped", Tool.Name)
					EquippedTools[Player.UserId] = nil
				end
			end
		end)
	end)
end)

game.Players.PlayerRemoving:Connect(function(Player)
	print("[LEAVE] Player is leaving:", Player.Name)

	local ToolTable = {}
	local seenTools = {} -- To prevent saving duplicates

	-- 1. Save tools in the Backpack
	for _, Tool in ipairs(Player.Backpack:GetChildren()) do
		if Tool:IsA("Tool") then
			if not seenTools[Tool.Name] then
				table.insert(ToolTable, Tool.Name)
				seenTools[Tool.Name] = true
				print("[SAVE] Tool in Backpack:", Tool.Name)
			end
		end
	end

	-- 2. Save the currently equipped tool (from our tracking table)
	local equippedToolName = EquippedTools[Player.UserId]
	if equippedToolName then
		-- Check if it's already in the table (e.g., if it was unequipped just before leaving, it might be in the backpack)
		if not seenTools[equippedToolName] then
			table.insert(ToolTable, equippedToolName)
			seenTools[equippedToolName] = true
			print("[SAVE] Equipped tool also being saved:", equippedToolName)
		end
	end
	
	-- 3. (Optional, but good for robustness): Check character directly as a fallback
	-- This might be unreliable on PlayerRemoving, but adding it just in case
	local Character = Player.Character
	if Character then
		local equippedToolInChar = Character:FindFirstChildOfClass("Tool")
		if equippedToolInChar and not seenTools[equippedToolInChar.Name] then
			table.insert(ToolTable, equippedToolInChar.Name)
			seenTools[equippedToolInChar.Name] = true
			print("[SAVE] Found tool in Character (fallback check):", equippedToolInChar.Name)
		end
	end

	local success, err = pcall(function()
		SaveData:SetAsync(Player.UserId, ToolTable)
	end)

	if success then
		print("[SAVE SUCCESS] Tools saved for", Player.Name, ":", ToolTable)
	else
		warn("[SAVE ERROR] Could not save tools for", Player.Name, ":", err)
	end

	-- Clean up the EquippedTools table entry for the leaving player
	EquippedTools[Player.UserId] = nil
end)

-- Essential for data saving reliability!
game:BindToClose(function()
	print("[BINDTOCLOSE] Server is shutting down. Attempting to save all player data.")
	local players = game.Players:GetPlayers()
	for _, player in pairs(players) do
		-- Call the PlayerRemoving logic for each player still in game
		-- To ensure data is saved when the server shuts down unexpectedly or through Studio stop
		local ToolTable = {}
		local seenTools = {}

		for _, Tool in ipairs(player.Backpack:GetChildren()) do
			if Tool:IsA("Tool") then
				if not seenTools[Tool.Name] then
					table.insert(ToolTable, Tool.Name)
					seenTools[Tool.Name] = true
				end
			end
		end

		local equippedToolName = EquippedTools[player.UserId]
		if equippedToolName then
			if not seenTools[equippedToolName] then
				table.insert(ToolTable, equippedToolName)
				seenTools[equippedToolName] = true
			end
		end
		
		local Character = player.Character
		if Character then
			local equippedToolInChar = Character:FindFirstChildOfClass("Tool")
			if equippedToolInChar and not seenTools[equippedToolInChar.Name] then
				table.insert(ToolTable, equippedToolInChar.Name)
				seenTools[equippedToolInChar.Name] = true
			end
		end

		local success, err = pcall(function()
			SaveData:SetAsync(player.UserId, ToolTable)
		end)

		if not success then
			warn("[BINDTOCLOSE ERROR] Failed to save data for", player.Name, ":", err)
		end
	end
	-- Give the datastore a moment to save before the server fully closes
	task.wait(2) 
	print("[BINDTOCLOSE] All player data saving attempts complete.")
end)